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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include "fib_entry.h"
17 #include "fib_entry_src.h"
18 #include "fib_path_list.h"
19 #include "fib_table.h"
20 #include "fib_entry_cover.h"
21 #include "fib_attached_export.h"
24 * Source initialisation Function
27 fib_entry_src_adj_init (fib_entry_src_t *src)
29 src->adj.fesa_cover = FIB_NODE_INDEX_INVALID;
30 src->adj.fesa_sibling = FIB_NODE_INDEX_INVALID;
34 fib_entry_src_adj_path_swap (fib_entry_src_t *src,
35 const fib_entry_t *entry,
36 fib_path_list_flags_t pl_flags,
37 const fib_route_path_t *paths)
39 src->fes_pl = fib_path_list_create(pl_flags, paths);
43 fib_entry_src_adj_remove (fib_entry_src_t *src)
45 src->fes_pl = FIB_NODE_INDEX_INVALID;
51 * Called when the source is the new longer best source on the entry
54 fib_entry_src_adj_activate (fib_entry_src_t *src,
55 const fib_entry_t *fib_entry)
60 * find the covering prefix. become a dependent thereof.
61 * there should always be a cover, though it may be the default route.
63 src->adj.fesa_cover = fib_table_get_less_specific(fib_entry->fe_fib_index,
64 &fib_entry->fe_prefix);
66 ASSERT(FIB_NODE_INDEX_INVALID != src->adj.fesa_cover);
67 ASSERT(fib_entry_get_index(fib_entry) != src->adj.fesa_cover);
69 cover = fib_entry_get(src->adj.fesa_cover);
71 ASSERT(cover != fib_entry);
73 src->adj.fesa_sibling =
74 fib_entry_cover_track(cover,
75 fib_entry_get_index(fib_entry));
78 * if the cover is attached on the same interface as this adj source then
79 * install the FIB entry via the adj. otherwise install a drop.
80 * This prevents ARP/ND entries that on interface X that do not belong
81 * on X's subnet from being added to the FIB. To do so would allow
82 * nefarious gratuitous ARP requests from attracting traffic to the sender.
84 * and yes, I really do mean attached and not connected.
86 * ip route add 10.0.0.0/24 Eth0
87 * is attached. and we want adj-fibs to install on Eth0.
89 if (FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags_i(cover))
91 u32 cover_itf = fib_entry_get_resolving_interface(src->adj.fesa_cover);
92 u32 adj_itf = fib_path_list_get_resolving_interface(src->fes_pl);
94 if (cover_itf == adj_itf)
101 * if the interface the adj is on is unnumbered to the
102 * cover's, then allow that too.
104 vnet_sw_interface_t *swif;
106 swif = vnet_get_sw_interface (vnet_get_main(), adj_itf);
108 if (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED &&
109 cover_itf == swif->unnumbered_sw_if_index)
120 * Called when the source is no longer best source on the entry
123 fib_entry_src_adj_deactivate (fib_entry_src_t *src,
124 const fib_entry_t *fib_entry)
129 * remove the depednecy on the covering entry
131 ASSERT(FIB_NODE_INDEX_INVALID != src->adj.fesa_cover);
132 cover = fib_entry_get(src->adj.fesa_cover);
134 fib_entry_cover_untrack(cover, src->adj.fesa_sibling);
137 * tell the cover this entry no longer needs exporting
139 fib_attached_export_covered_removed(cover, fib_entry_get_index(fib_entry));
141 src->adj.fesa_cover = FIB_NODE_INDEX_INVALID;
145 fib_entry_src_adj_format (fib_entry_src_t *src,
148 return (format(s, "cover:%d", src->adj.fesa_cover));
152 fib_entry_src_adj_installed (fib_entry_src_t *src,
153 const fib_entry_t *fib_entry)
156 * The adj source now rules! poke our cover to get exported
160 ASSERT(FIB_NODE_INDEX_INVALID != src->adj.fesa_cover);
161 cover = fib_entry_get(src->adj.fesa_cover);
163 fib_attached_export_covered_added(cover,
164 fib_entry_get_index(fib_entry));
167 static fib_entry_src_cover_res_t
168 fib_entry_src_adj_cover_change (fib_entry_src_t *src,
169 const fib_entry_t *fib_entry)
171 fib_entry_src_cover_res_t res = {
173 .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE,
176 fib_entry_src_adj_deactivate(src, fib_entry);
178 res.install = fib_entry_src_adj_activate(src, fib_entry);
182 * ADJ fib can install
184 res.bw_reason = FIB_NODE_BW_REASON_FLAG_EVALUATE;
191 * fib_entry_src_adj_cover_update
193 static fib_entry_src_cover_res_t
194 fib_entry_src_adj_cover_update (fib_entry_src_t *src,
195 const fib_entry_t *fib_entry)
198 * the cover has updated, i.e. its forwarding or flags
199 * have changed. do'nt decativate/activate here, since this
200 * prefix is updated during the covers walk.
202 fib_entry_src_cover_res_t res = {
204 .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE,
208 ASSERT(FIB_NODE_INDEX_INVALID != src->adj.fesa_cover);
210 cover = fib_entry_get(src->adj.fesa_cover);
212 res.install = (FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags_i(cover));
217 const static fib_entry_src_vft_t adj_src_vft = {
218 .fesv_init = fib_entry_src_adj_init,
219 .fesv_path_swap = fib_entry_src_adj_path_swap,
220 .fesv_remove = fib_entry_src_adj_remove,
221 .fesv_activate = fib_entry_src_adj_activate,
222 .fesv_deactivate = fib_entry_src_adj_deactivate,
223 .fesv_format = fib_entry_src_adj_format,
224 .fesv_installed = fib_entry_src_adj_installed,
225 .fesv_cover_change = fib_entry_src_adj_cover_change,
226 .fesv_cover_update = fib_entry_src_adj_cover_update,
230 fib_entry_src_adj_register (void)
232 fib_entry_src_register(FIB_SOURCE_ADJ, &adj_src_vft);