blob: d8bc09c5f1a72049d8699650242eec8db2545a4e [file] [log] [blame]
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001/*
2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <vlib/vlib.h>
17#include <vnet/ip/format.h>
18#include <vnet/ip/lookup.h>
19#include <vnet/adj/adj.h>
Neale Ranns3dffb1e2016-11-01 20:38:53 +000020#include <vnet/dpo/drop_dpo.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010021
22#include "fib_entry_src.h"
Neale Ranns2303cb12018-02-21 04:57:17 -080023#include "fib_entry_src_rr.h"
Neale Ranns0bfe5d82016-08-25 15:29:12 +010024#include "fib_entry_cover.h"
25#include "fib_entry.h"
26#include "fib_table.h"
Stanislav Zaikin4fc68ee2021-02-13 16:32:15 +030027#include "fib_path_ext.h"
Neale Ranns0bfe5d82016-08-25 15:29:12 +010028
29/*
30 * fib_entry_src_rr_resolve_via_connected
31 *
32 * Resolve via a connected cover.
33 */
Neale Ranns2303cb12018-02-21 04:57:17 -080034void
Neale Ranns0bfe5d82016-08-25 15:29:12 +010035fib_entry_src_rr_resolve_via_connected (fib_entry_src_t *src,
36 const fib_entry_t *fib_entry,
37 const fib_entry_t *cover)
38{
39 const fib_route_path_t path = {
Neale Rannsda78f952017-05-24 09:15:43 -070040 .frp_proto = fib_proto_to_dpo(fib_entry->fe_prefix.fp_proto),
Neale Ranns0bfe5d82016-08-25 15:29:12 +010041 .frp_addr = fib_entry->fe_prefix.fp_addr,
42 .frp_sw_if_index = fib_entry_get_resolving_interface(
43 fib_entry_get_index(cover)),
44 .frp_fib_index = ~0,
45 .frp_weight = 1,
46 };
47 fib_route_path_t *paths = NULL;
48 vec_add1(paths, path);
49
50 /*
51 * since the cover is connected, the address this entry corresponds
52 * to is a peer (ARP-able for) on the interface to which the cover is
53 * connected. The fact we resolve via the cover, just means this RR
54 * source is the first SRC to use said peer. The ARP source will be along
55 * shortly to over-rule this RR source.
56 */
57 src->fes_pl = fib_path_list_create(FIB_PATH_LIST_FLAG_NONE, paths);
Neale Ranns2303cb12018-02-21 04:57:17 -080058 src->fes_entry_flags |= (fib_entry_get_flags(fib_entry_get_index(cover)) &
59 FIB_ENTRY_FLAGS_RR_INHERITED);
Neale Ranns0bfe5d82016-08-25 15:29:12 +010060
61 vec_free(paths);
62}
63
Neale Rannsad422ed2016-11-02 14:20:04 +000064
Neale Ranns0bfe5d82016-08-25 15:29:12 +010065/**
66 * Source initialisation Function
67 */
68static void
69fib_entry_src_rr_init (fib_entry_src_t *src)
70{
Neale Ranns2303cb12018-02-21 04:57:17 -080071 src->u.rr.fesr_cover = FIB_NODE_INDEX_INVALID;
72 src->u.rr.fesr_sibling = FIB_NODE_INDEX_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +010073}
74
Neale Ranns08b16482017-05-13 05:52:58 -070075
76/*
77 * use the path-list of the cover, unless it would form a loop.
78 * that is unless the cover is via this entry.
79 * If a loop were to form it would be a 1 level loop (i.e. X via X),
80 * and there would be 2 locks on the path-list; one since its used
81 * by the cover, and 1 from here. The first lock will go when the
82 * cover is removed, the second, and last, when the covered walk
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -070083 * occurs during the cover's removal - this is not a place where
Neale Ranns08b16482017-05-13 05:52:58 -070084 * we can handle last lock gone.
85 * In short, don't let the loop form. The usual rules of 'we must
86 * let it form so we know when it breaks' don't apply here, since
87 * the loop will break when the cover changes, and this function
88 * will be called again when that happens.
89 */
Neale Ranns2303cb12018-02-21 04:57:17 -080090void
Neale Ranns08b16482017-05-13 05:52:58 -070091fib_entry_src_rr_use_covers_pl (fib_entry_src_t *src,
92 const fib_entry_t *fib_entry,
93 const fib_entry_t *cover)
94{
95 fib_node_index_t *entries = NULL;
Neale Rannsda78f952017-05-24 09:15:43 -070096 dpo_proto_t proto;
Stanislav Zaikin4fc68ee2021-02-13 16:32:15 +030097 fib_entry_src_t *s;
Neale Ranns08b16482017-05-13 05:52:58 -070098
Neale Rannsda78f952017-05-24 09:15:43 -070099 proto = fib_proto_to_dpo(fib_entry->fe_prefix.fp_proto);
Neale Ranns08b16482017-05-13 05:52:58 -0700100 vec_add1(entries, fib_entry_get_index(fib_entry));
101
102 if (fib_path_list_recursive_loop_detect(cover->fe_parent,
103 &entries))
104 {
Neale Rannsda78f952017-05-24 09:15:43 -0700105 src->fes_pl = fib_path_list_create_special(proto,
106 FIB_PATH_LIST_FLAG_DROP,
107 drop_dpo_get(proto));
Neale Ranns08b16482017-05-13 05:52:58 -0700108 }
109 else
110 {
111 src->fes_pl = cover->fe_parent;
Stanislav Zaikin4fc68ee2021-02-13 16:32:15 +0300112 vec_foreach (s,cover->fe_srcs)
113 {
114 if (s->fes_pl != cover->fe_parent)
115 continue;
116
117 src->fes_path_exts.fpel_exts = vec_dup (s->fes_path_exts.fpel_exts);
118 break;
119 }
Neale Ranns08b16482017-05-13 05:52:58 -0700120 }
121 vec_free(entries);
122}
123
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100124/*
125 * Source activation. Called when the source is the new best source on the entry
126 */
127static int
128fib_entry_src_rr_activate (fib_entry_src_t *src,
129 const fib_entry_t *fib_entry)
130{
131 fib_entry_t *cover;
132
133 /*
134 * find the covering prefix. become a dependent thereof.
Neale Rannsad422ed2016-11-02 14:20:04 +0000135 * for IP there should always be a cover, though it may be the default route.
136 * For MPLS there is never a cover.
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100137 */
Neale Rannsad422ed2016-11-02 14:20:04 +0000138 if (FIB_PROTOCOL_MPLS == fib_entry->fe_prefix.fp_proto)
139 {
Neale Rannsda78f952017-05-24 09:15:43 -0700140 src->fes_pl = fib_path_list_create_special(DPO_PROTO_MPLS,
Neale Rannsad422ed2016-11-02 14:20:04 +0000141 FIB_PATH_LIST_FLAG_DROP,
142 NULL);
143 fib_path_list_lock(src->fes_pl);
144 return (!0);
145 }
146
Neale Ranns2303cb12018-02-21 04:57:17 -0800147 src->u.rr.fesr_cover = fib_table_get_less_specific(fib_entry->fe_fib_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100148 &fib_entry->fe_prefix);
149
Neale Ranns2303cb12018-02-21 04:57:17 -0800150 ASSERT(FIB_NODE_INDEX_INVALID != src->u.rr.fesr_cover);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100151
Neale Ranns2303cb12018-02-21 04:57:17 -0800152 cover = fib_entry_get(src->u.rr.fesr_cover);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100153
Neale Ranns2303cb12018-02-21 04:57:17 -0800154 src->u.rr.fesr_sibling =
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100155 fib_entry_cover_track(cover, fib_entry_get_index(fib_entry));
156
157 /*
Neale Rannsf12a83f2017-04-18 09:09:40 -0700158 * if the cover is attached then install an attached-host path
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100159 * (like an adj-fib). Otherwise inherit the forwarding from the cover
160 */
161 if (FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags_i(cover))
162 {
163 fib_entry_src_rr_resolve_via_connected(src, fib_entry, cover);
164 }
165 else
166 {
Neale Ranns08b16482017-05-13 05:52:58 -0700167 fib_entry_src_rr_use_covers_pl(src, fib_entry, cover);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100168 }
169 fib_path_list_lock(src->fes_pl);
170
171 /*
172 * return go for install
173 */
174 return (!0);
175}
176
177/**
178 * Source Deactivate.
179 * Called when the source is no longer best source on the entry
180 */
181static void
182fib_entry_src_rr_deactivate (fib_entry_src_t *src,
183 const fib_entry_t *fib_entry)
184{
185 fib_entry_t *cover;
186
187 /*
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700188 * remove the dependency on the covering entry
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100189 */
Neale Ranns2303cb12018-02-21 04:57:17 -0800190 if (FIB_NODE_INDEX_INVALID != src->u.rr.fesr_cover)
Neale Rannsad422ed2016-11-02 14:20:04 +0000191 {
mu.duojiao11232e52019-02-14 16:57:54 +0800192 fib_node_index_t *entries = NULL;
193
Neale Ranns2303cb12018-02-21 04:57:17 -0800194 cover = fib_entry_get(src->u.rr.fesr_cover);
195 fib_entry_cover_untrack(cover, src->u.rr.fesr_sibling);
196 src->u.rr.fesr_cover = FIB_NODE_INDEX_INVALID;
mu.duojiao11232e52019-02-14 16:57:54 +0800197
198 if (FIB_NODE_INDEX_INVALID != cover->fe_parent)
199 {
200 fib_path_list_recursive_loop_detect(cover->fe_parent, &entries);
201
202 vec_free(entries);
203 }
Neale Rannsad422ed2016-11-02 14:20:04 +0000204 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100205
206 fib_path_list_unlock(src->fes_pl);
207 src->fes_pl = FIB_NODE_INDEX_INVALID;
Stanislav Zaikin4fc68ee2021-02-13 16:32:15 +0300208 vec_free (src->fes_path_exts.fpel_exts);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100209 src->fes_entry_flags = FIB_ENTRY_FLAG_NONE;
210}
211
Neale Ranns2303cb12018-02-21 04:57:17 -0800212fib_entry_src_cover_res_t
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100213fib_entry_src_rr_cover_change (fib_entry_src_t *src,
214 const fib_entry_t *fib_entry)
215{
216 fib_entry_src_cover_res_t res = {
217 .install = !0,
218 .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE,
219 };
220
Neale Ranns2303cb12018-02-21 04:57:17 -0800221 if (FIB_NODE_INDEX_INVALID == src->u.rr.fesr_cover)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100222 {
223 /*
224 * the source may be added, but it is not active
225 * if it is not tracking the cover.
226 */
227 return (res);
228 }
229
230 /*
231 * this function is called when this entry's cover has a more specific
232 * entry inserted benaeth it. That does not necessarily mean that this
233 * entry is covered by the new prefix. check that
234 */
Neale Ranns2303cb12018-02-21 04:57:17 -0800235 if (src->u.rr.fesr_cover != fib_table_get_less_specific(fib_entry->fe_fib_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100236 &fib_entry->fe_prefix))
237 {
238 fib_entry_src_rr_deactivate(src, fib_entry);
239 fib_entry_src_rr_activate(src, fib_entry);
240
241 /*
242 * dependent children need to re-resolve to the new forwarding info
243 */
244 res.bw_reason = FIB_NODE_BW_REASON_FLAG_EVALUATE;
245 }
246 return (res);
247}
248
249/*
250 * fib_entry_src_rr_cover_update
251 *
252 * This entry's cover has updated its forwarding info. This entry
253 * will need to re-inheret.
254 */
Neale Ranns2303cb12018-02-21 04:57:17 -0800255fib_entry_src_cover_res_t
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100256fib_entry_src_rr_cover_update (fib_entry_src_t *src,
257 const fib_entry_t *fib_entry)
258{
259 fib_entry_src_cover_res_t res = {
260 .install = !0,
261 .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE,
262 };
263 fib_node_index_t old_path_list;
264 fib_entry_t *cover;
265
Neale Ranns2303cb12018-02-21 04:57:17 -0800266 if (FIB_NODE_INDEX_INVALID == src->u.rr.fesr_cover)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100267 {
268 /*
269 * the source may be added, but it is not active
270 * if it is not tracking the cover.
271 */
272 return (res);
273 }
274
Neale Ranns2303cb12018-02-21 04:57:17 -0800275 cover = fib_entry_get(src->u.rr.fesr_cover);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100276 old_path_list = src->fes_pl;
277
278 /*
279 * if the ocver is attached then install an attached-host path
280 * (like an adj-fib). Otherwise inherit the forwarding from the cover
281 */
282 if (FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags_i(cover))
283 {
284 fib_entry_src_rr_resolve_via_connected(src, fib_entry, cover);
285 }
286 else
287 {
Neale Ranns08b16482017-05-13 05:52:58 -0700288 fib_entry_src_rr_use_covers_pl(src, fib_entry, cover);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100289 }
290 fib_path_list_lock(src->fes_pl);
291 fib_path_list_unlock(old_path_list);
292
293 /*
294 * dependent children need to re-resolve to the new forwarding info
295 */
296 res.bw_reason = FIB_NODE_BW_REASON_FLAG_EVALUATE;
297
298 return (res);
299}
300
301static u8*
302fib_entry_src_rr_format (fib_entry_src_t *src,
303 u8* s)
304{
Neale Ranns2303cb12018-02-21 04:57:17 -0800305 return (format(s, " cover:%d", src->u.rr.fesr_cover));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100306}
307
308const static fib_entry_src_vft_t rr_src_vft = {
309 .fesv_init = fib_entry_src_rr_init,
310 .fesv_activate = fib_entry_src_rr_activate,
311 .fesv_deactivate = fib_entry_src_rr_deactivate,
312 .fesv_cover_change = fib_entry_src_rr_cover_change,
313 .fesv_cover_update = fib_entry_src_rr_cover_update,
314 .fesv_format = fib_entry_src_rr_format,
315};
316
317void
318fib_entry_src_rr_register (void)
319{
Neale Ranns3bab8f92019-12-04 06:11:00 +0000320 fib_entry_src_behaviour_register(FIB_SOURCE_BH_RR, &rr_src_vft);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100321}