blob: 9990223037a108fc3ab007fb062e7a689c0247f4 [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 "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"
22
23/**
24 * Source initialisation Function
25 */
26static void
27fib_entry_src_adj_init (fib_entry_src_t *src)
28{
29 src->adj.fesa_cover = FIB_NODE_INDEX_INVALID;
30 src->adj.fesa_sibling = FIB_NODE_INDEX_INVALID;
31}
32
33static void
34fib_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)
38{
39 src->fes_pl = fib_path_list_create(pl_flags, paths);
40}
41
42static void
43fib_entry_src_adj_remove (fib_entry_src_t *src)
44{
45 src->fes_pl = FIB_NODE_INDEX_INVALID;
46}
47
48
49/*
50 * Source activate.
Neale Ranns3983ac22017-03-10 11:53:27 -080051 * Called when the source is the new longer best source on the entry
Neale Ranns0bfe5d82016-08-25 15:29:12 +010052 */
53static int
54fib_entry_src_adj_activate (fib_entry_src_t *src,
55 const fib_entry_t *fib_entry)
56{
57 fib_entry_t *cover;
58
59 /*
60 * find the covering prefix. become a dependent thereof.
61 * there should always be a cover, though it may be the default route.
62 */
63 src->adj.fesa_cover = fib_table_get_less_specific(fib_entry->fe_fib_index,
64 &fib_entry->fe_prefix);
65
66 ASSERT(FIB_NODE_INDEX_INVALID != src->adj.fesa_cover);
67 ASSERT(fib_entry_get_index(fib_entry) != src->adj.fesa_cover);
68
69 cover = fib_entry_get(src->adj.fesa_cover);
70
71 ASSERT(cover != fib_entry);
72
73 src->adj.fesa_sibling =
74 fib_entry_cover_track(cover,
75 fib_entry_get_index(fib_entry));
76
77 /*
Neale Ranns3983ac22017-03-10 11:53:27 -080078 * 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.
Neale Ranns0bfe5d82016-08-25 15:29:12 +010080 * 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.
83 *
84 * and yes, I really do mean attached and not connected.
85 * this abomination;
86 * ip route add 10.0.0.0/24 Eth0
87 * is attached. and we want adj-fibs to install on Eth0.
88 */
Neale Ranns3983ac22017-03-10 11:53:27 -080089 if (FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags_i(cover))
90 {
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);
93
94 if (cover_itf == adj_itf)
95 {
96 return (1);
97 }
98 else
99 {
100 /*
101 * if the interface the adj is on is unnumbered to the
102 * cover's, then allow that too.
103 */
104 vnet_sw_interface_t *swif;
105
106 swif = vnet_get_sw_interface (vnet_get_main(), adj_itf);
107
108 if (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED &&
109 cover_itf == swif->unnumbered_sw_if_index)
110 {
111 return (1);
112 }
113 }
114 }
115 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100116}
117
118/*
119 * Source Deactivate.
120 * Called when the source is no longer best source on the entry
121 */
122static void
123fib_entry_src_adj_deactivate (fib_entry_src_t *src,
124 const fib_entry_t *fib_entry)
125{
126 fib_entry_t *cover;
127
128 /*
129 * remove the depednecy on the covering entry
130 */
131 ASSERT(FIB_NODE_INDEX_INVALID != src->adj.fesa_cover);
132 cover = fib_entry_get(src->adj.fesa_cover);
133
134 fib_entry_cover_untrack(cover, src->adj.fesa_sibling);
135
136 /*
137 * tell the cover this entry no longer needs exporting
138 */
139 fib_attached_export_covered_removed(cover, fib_entry_get_index(fib_entry));
140
141 src->adj.fesa_cover = FIB_NODE_INDEX_INVALID;
142}
143
144static u8*
145fib_entry_src_adj_format (fib_entry_src_t *src,
146 u8* s)
147{
148 return (format(s, "cover:%d", src->adj.fesa_cover));
149}
150
151static void
152fib_entry_src_adj_installed (fib_entry_src_t *src,
153 const fib_entry_t *fib_entry)
154{
155 /*
156 * The adj source now rules! poke our cover to get exported
157 */
158 fib_entry_t *cover;
159
160 ASSERT(FIB_NODE_INDEX_INVALID != src->adj.fesa_cover);
161 cover = fib_entry_get(src->adj.fesa_cover);
162
163 fib_attached_export_covered_added(cover,
164 fib_entry_get_index(fib_entry));
165}
166
167static fib_entry_src_cover_res_t
168fib_entry_src_adj_cover_change (fib_entry_src_t *src,
169 const fib_entry_t *fib_entry)
170{
171 fib_entry_src_cover_res_t res = {
172 .install = !0,
173 .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE,
174 };
175
176 fib_entry_src_adj_deactivate(src, fib_entry);
177
178 res.install = fib_entry_src_adj_activate(src, fib_entry);
179
180 if (res.install) {
181 /*
182 * ADJ fib can install
183 */
184 res.bw_reason = FIB_NODE_BW_REASON_FLAG_EVALUATE;
185 }
186
187 return (res);
188}
189
190/*
191 * fib_entry_src_adj_cover_update
192 */
193static fib_entry_src_cover_res_t
194fib_entry_src_adj_cover_update (fib_entry_src_t *src,
195 const fib_entry_t *fib_entry)
196{
197 /*
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.
201 */
202 fib_entry_src_cover_res_t res = {
203 .install = !0,
204 .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE,
205 };
206 fib_entry_t *cover;
207
208 ASSERT(FIB_NODE_INDEX_INVALID != src->adj.fesa_cover);
209
210 cover = fib_entry_get(src->adj.fesa_cover);
211
212 res.install = (FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags_i(cover));
213
214 return (res);
215}
216
217const 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,
227};
228
229void
230fib_entry_src_adj_register (void)
231{
232 fib_entry_src_register(FIB_SOURCE_ADJ, &adj_src_vft);
233}