Line data Source code
1 : /*
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 <vnet/vnet.h>
17 :
18 : #include <vnet/mfib/mfib_itf.h>
19 : #include <vnet/mfib/mfib_signal.h>
20 : #include <vnet/fib/fib_path.h>
21 : #include <vnet/ethernet/mac_address.h>
22 :
23 : mfib_itf_t *mfib_itf_pool;
24 :
25 : index_t
26 17367 : mfib_itf_create (fib_node_index_t path_index,
27 : mfib_itf_flags_t mfi_flags)
28 : {
29 : mfib_itf_t *mfib_itf;
30 :
31 17367 : pool_get_aligned(mfib_itf_pool, mfib_itf,
32 : CLIB_CACHE_LINE_BYTES);
33 :
34 17367 : mfib_itf->mfi_sw_if_index = fib_path_get_resolving_interface(path_index);
35 17367 : mfib_itf->mfi_si = INDEX_INVALID;
36 :
37 : /*
38 : * add the path index to the per-path hash
39 : */
40 17367 : mfib_itf->mfi_hash = hash_set(mfib_itf->mfi_hash, path_index, mfi_flags);
41 :
42 : /*
43 : * the combined flags from all the paths is from just the one contributor
44 : */
45 17367 : mfib_itf->mfi_flags = mfi_flags;
46 :
47 17367 : return (mfib_itf - mfib_itf_pool);
48 : }
49 :
50 : static mfib_itf_flags_t
51 12384 : mfib_itf_mk_flags (const mfib_itf_t *mfib_itf)
52 : {
53 : mfib_itf_flags_t combined_flags, flags;
54 : fib_node_index_t *path_index;
55 :
56 12384 : combined_flags = MFIB_ITF_FLAG_NONE;
57 :
58 804972 : hash_foreach(path_index, flags, mfib_itf->mfi_hash,
59 : {
60 : combined_flags |= flags;
61 : });
62 :
63 12384 : return (combined_flags);
64 : }
65 :
66 : int
67 12384 : mfib_itf_update (mfib_itf_t *mfib_itf,
68 : fib_node_index_t path_index,
69 : mfib_itf_flags_t mfi_flags)
70 : {
71 : /*
72 : * add or remove the path index to the per-path hash
73 : */
74 12384 : if (MFIB_ITF_FLAG_NONE == mfi_flags)
75 : {
76 12376 : hash_unset(mfib_itf->mfi_hash, path_index);
77 : }
78 : else
79 : {
80 8 : mfib_itf->mfi_hash = hash_set(mfib_itf->mfi_hash,
81 : path_index,
82 : mfi_flags);
83 : }
84 :
85 : /*
86 : * re-generate the combined flags from all the paths.
87 : */
88 12384 : mfib_itf->mfi_flags = mfib_itf_mk_flags(mfib_itf);
89 :
90 : /*
91 : * The interface can be removed if there are no more flags
92 : */
93 12384 : return (MFIB_ITF_FLAG_NONE == mfib_itf->mfi_flags);
94 : }
95 :
96 : static void
97 16192 : mfib_itf_hash_flush (mfib_itf_t *mfi)
98 : {
99 16192 : fib_node_index_t path_index, *path_indexp, *all = NULL;
100 : mfib_itf_flags_t flags;
101 :
102 1056300 : hash_foreach(path_index, flags, mfi->mfi_hash,
103 : {
104 : vec_add1(all, path_index);
105 : });
106 :
107 20010 : vec_foreach(path_indexp, all)
108 : {
109 3818 : hash_unset(mfi->mfi_hash, *path_indexp);
110 : };
111 16192 : }
112 :
113 : static void
114 12045 : mfib_itf_prefix4_to_mac (const mfib_prefix_t *pfx,
115 : mac_address_t *mac)
116 : {
117 12045 : mac->bytes[0] = 0x01;
118 12045 : mac->bytes[1] = 0x0;
119 12045 : mac->bytes[2] = 0x5e;
120 12045 : mac->bytes[3] = pfx->fp_grp_addr.ip4.as_u8[1] & 0x7f;
121 12045 : mac->bytes[4] = pfx->fp_grp_addr.ip4.as_u8[2];
122 12045 : mac->bytes[5] = pfx->fp_grp_addr.ip4.as_u8[3];
123 12045 : }
124 :
125 : static void
126 16434 : mfib_itf_prefix6_to_mac (const mfib_prefix_t *pfx,
127 : mac_address_t *mac)
128 : {
129 16434 : mac->bytes[0] = 0x33;
130 16434 : mac->bytes[1] = 0x33;
131 16434 : mac->bytes[2] = pfx->fp_grp_addr.ip6.as_u8[12];
132 16434 : mac->bytes[3] = pfx->fp_grp_addr.ip6.as_u8[13];
133 16434 : mac->bytes[4] = pfx->fp_grp_addr.ip6.as_u8[14];
134 16434 : mac->bytes[5] = pfx->fp_grp_addr.ip6.as_u8[15];
135 16434 : }
136 :
137 : static void
138 28479 : mfib_itf_prefix_to_mac (const mfib_prefix_t *pfx,
139 : mac_address_t *mac)
140 : {
141 28479 : switch (pfx->fp_proto)
142 : {
143 12045 : case FIB_PROTOCOL_IP4:
144 12045 : mfib_itf_prefix4_to_mac(pfx, mac);
145 12045 : break;
146 16434 : case FIB_PROTOCOL_IP6:
147 16434 : mfib_itf_prefix6_to_mac(pfx, mac);
148 16434 : break;
149 0 : case FIB_PROTOCOL_MPLS:
150 0 : break;
151 : }
152 28479 : }
153 :
154 : static void
155 28479 : mfib_itf_mac_add_del (mfib_itf_t *itf,
156 : const mfib_prefix_t *pfx,
157 : int add)
158 : {
159 : vnet_sw_interface_t *si;
160 : vnet_main_t *vnm;
161 : mac_address_t mac;
162 :
163 28479 : vnm = vnet_get_main();
164 28479 : mfib_itf_prefix_to_mac(pfx, &mac);
165 :
166 28479 : si = vnet_get_sw_interface(vnm, itf->mfi_sw_if_index);
167 28479 : vnet_hw_interface_add_del_mac_address (vnet_get_main(),
168 : si->hw_if_index,
169 : mac.bytes, add);
170 28479 : }
171 :
172 : void
173 16152 : mfib_itf_mac_add (mfib_itf_t *itf,
174 : const mfib_prefix_t *pfx)
175 : {
176 16152 : mfib_itf_mac_add_del(itf, pfx, 1);
177 16152 : }
178 :
179 : void
180 12327 : mfib_itf_mac_del (mfib_itf_t *itf,
181 : const mfib_prefix_t *pfx)
182 : {
183 12327 : mfib_itf_mac_add_del(itf, pfx, 0);
184 12327 : }
185 :
186 : void
187 16192 : mfib_itf_delete (mfib_itf_t *mfi)
188 : {
189 16192 : mfib_itf_hash_flush(mfi);
190 16192 : mfib_signal_remove_itf(mfi);
191 16192 : pool_put(mfib_itf_pool, mfi);
192 16192 : }
193 :
194 : u8 *
195 6 : format_mfib_itf (u8 * s, va_list * args)
196 : {
197 : mfib_itf_t *mfib_itf;
198 : vnet_main_t *vnm;
199 : index_t mfi;
200 :
201 6 : mfi = va_arg (*args, index_t);
202 :
203 6 : vnm = vnet_get_main();
204 6 : mfib_itf = mfib_itf_get(mfi);
205 :
206 6 : if (~0 != mfib_itf->mfi_sw_if_index)
207 : {
208 6 : return (format(s, " %U: %U",
209 : format_vnet_sw_interface_name,
210 : vnm,
211 : vnet_get_sw_interface(vnm,
212 : mfib_itf->mfi_sw_if_index),
213 6 : format_mfib_itf_flags, mfib_itf->mfi_flags));
214 : }
215 : else
216 : {
217 0 : return (format(s, " local: %U",
218 0 : format_mfib_itf_flags, mfib_itf->mfi_flags));
219 : }
220 : return (s);
221 : }
222 :
223 : static clib_error_t *
224 0 : show_mfib_itf_command (vlib_main_t * vm,
225 : unformat_input_t * input,
226 : vlib_cli_command_t * cmd)
227 : {
228 : index_t mfii;
229 :
230 0 : if (unformat (input, "%d", &mfii))
231 : {
232 : /*
233 : * show one in detail
234 : */
235 0 : if (!pool_is_free_index(mfib_itf_pool, mfii))
236 : {
237 0 : vlib_cli_output (vm, "%d@%U",
238 : mfii,
239 : format_mfib_itf, mfii);
240 : }
241 : else
242 : {
243 0 : vlib_cli_output (vm, "itf %d invalid", mfii);
244 : }
245 : }
246 : else
247 : {
248 : /*
249 : * show all
250 : */
251 0 : vlib_cli_output (vm, "mFIB interfaces::");
252 0 : pool_foreach_index (mfii, mfib_itf_pool)
253 : {
254 0 : vlib_cli_output (vm, "%d@%U",
255 : mfii,
256 : format_mfib_itf, mfii);
257 : }
258 : }
259 :
260 0 : return (NULL);
261 : }
262 :
263 : /*?
264 : * This command displays an MFIB interface, or all interfaces, indexed by their
265 : * unique numerical identifier.
266 : ?*/
267 285289 : VLIB_CLI_COMMAND (show_mfib_itf, static) = {
268 : .path = "show mfib interface",
269 : .function = show_mfib_itf_command,
270 : .short_help = "show mfib interface",
271 : };
|