blob: cb22547f9409269dd2b6af23a45d49d21bb62bdc [file] [log] [blame]
Matus Fabianf468e232016-12-02 06:00:53 -08001/*
2 *------------------------------------------------------------------
3 * l2_api.c - layer 2 forwarding api
4 *
5 * Copyright (c) 2016 Cisco and/or its affiliates.
Laszlo Kiraly0f8f4352022-09-16 13:20:07 +02006 * Copyright (c) 2022 Nordix Foundation.
Matus Fabianf468e232016-12-02 06:00:53 -08007 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at:
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *------------------------------------------------------------------
19 */
20
21#include <vnet/vnet.h>
22#include <vlibmemory/api.h>
23
24#include <vnet/interface.h>
25#include <vnet/api_errno.h>
26#include <vnet/l2/l2_input.h>
Pavel Kotucek0f971d82017-01-03 10:48:54 +010027#include <vnet/l2/l2_fib.h>
Pavel Kotucekadec5872017-01-25 08:50:53 +010028#include <vnet/l2/l2_vtr.h>
John Lo8d00fff2017-08-03 00:35:36 -040029#include <vnet/l2/l2_learn.h>
Neale Rannsb4743802018-09-05 09:13:57 -070030#include <vnet/l2/l2_bd.h>
Neale Ranns192b13f2019-03-15 02:16:20 -070031#include <vnet/l2/l2_bvi.h>
Neale Rannscbe25aa2019-09-30 10:53:31 +000032#include <vnet/l2/l2_arp_term.h>
Neale Ranns4d5b9172018-10-24 02:57:49 -070033#include <vnet/ip/ip_types_api.h>
34#include <vnet/ethernet/ethernet_types_api.h>
Matus Fabianf468e232016-12-02 06:00:53 -080035
Filip Tehlar5a9d2a12021-06-22 21:20:29 +000036#include <vnet/format_fns.h>
37#include <vnet/l2/l2.api_enum.h>
38#include <vnet/l2/l2.api_types.h>
Matus Fabianf468e232016-12-02 06:00:53 -080039
Filip Tehlar5a9d2a12021-06-22 21:20:29 +000040#define REPLY_MSG_ID_BASE l2input_main.msg_id_base
Matus Fabianf468e232016-12-02 06:00:53 -080041#include <vlibapi/api_helper_macros.h>
42
Matus Fabianf468e232016-12-02 06:00:53 -080043static void
Florin Coras6c4dae22018-01-09 06:39:23 -080044send_l2_xconnect_details (vl_api_registration_t * reg, u32 context,
Matus Fabianf468e232016-12-02 06:00:53 -080045 u32 rx_sw_if_index, u32 tx_sw_if_index)
46{
47 vl_api_l2_xconnect_details_t *mp;
48
49 mp = vl_msg_api_alloc (sizeof (*mp));
Dave Barachb7b92992018-10-17 10:38:51 -040050 clib_memset (mp, 0, sizeof (*mp));
Filip Tehlar5a9d2a12021-06-22 21:20:29 +000051 mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_L2_XCONNECT_DETAILS);
Matus Fabianf468e232016-12-02 06:00:53 -080052 mp->context = context;
53 mp->rx_sw_if_index = htonl (rx_sw_if_index);
54 mp->tx_sw_if_index = htonl (tx_sw_if_index);
55
Florin Coras6c4dae22018-01-09 06:39:23 -080056 vl_api_send_msg (reg, (u8 *) mp);
Matus Fabianf468e232016-12-02 06:00:53 -080057}
58
59static void
60vl_api_l2_xconnect_dump_t_handler (vl_api_l2_xconnect_dump_t * mp)
61{
Florin Coras6c4dae22018-01-09 06:39:23 -080062 vl_api_registration_t *reg;
Matus Fabianf468e232016-12-02 06:00:53 -080063 l2input_main_t *l2im = &l2input_main;
Steven Luong16f08652021-02-08 23:48:30 -080064 u32 sw_if_index;
Matus Fabianf468e232016-12-02 06:00:53 -080065 l2_input_config_t *config;
66
Florin Coras6c4dae22018-01-09 06:39:23 -080067 reg = vl_api_client_index_to_registration (mp->client_index);
68 if (!reg)
Matus Fabianf468e232016-12-02 06:00:53 -080069 return;
70
71 /* *INDENT-OFF* */
Steven Luong16f08652021-02-08 23:48:30 -080072 vec_foreach_index (sw_if_index, l2im->configs)
73 {
74 config = vec_elt_at_index (l2im->configs, sw_if_index);
75 if (l2_input_is_xconnect (config))
76 send_l2_xconnect_details (reg, mp->context, sw_if_index,
77 config->output_sw_if_index);
78 }
Matus Fabianf468e232016-12-02 06:00:53 -080079 /* *INDENT-ON* */
80}
81
Pavel Kotucek0f971d82017-01-03 10:48:54 +010082static void
83vl_api_l2_fib_clear_table_t_handler (vl_api_l2_fib_clear_table_t * mp)
84{
85 int rv = 0;
86 vl_api_l2_fib_clear_table_reply_t *rmp;
87
Eyal Bari7537e712017-04-27 14:07:55 +030088 /* Clear all MACs including static MACs */
89 l2fib_clear_table ();
Pavel Kotucek0f971d82017-01-03 10:48:54 +010090
91 REPLY_MACRO (VL_API_L2_FIB_CLEAR_TABLE_REPLY);
92}
93
94static void
95send_l2fib_table_entry (vpe_api_main_t * am,
Florin Coras6c4dae22018-01-09 06:39:23 -080096 vl_api_registration_t * reg,
Pavel Kotucek0f971d82017-01-03 10:48:54 +010097 l2fib_entry_key_t * l2fe_key,
98 l2fib_entry_result_t * l2fe_res, u32 context)
99{
Ole Troan01384fe2017-05-12 11:55:35 +0200100 vl_api_l2_fib_table_details_t *mp;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100101
102 mp = vl_msg_api_alloc (sizeof (*mp));
Dave Barachb7b92992018-10-17 10:38:51 -0400103 clib_memset (mp, 0, sizeof (*mp));
Filip Tehlar5a9d2a12021-06-22 21:20:29 +0000104 mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_L2_FIB_TABLE_DETAILS);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100105
106 mp->bd_id =
107 ntohl (l2input_main.bd_configs[l2fe_key->fields.bd_index].bd_id);
108
Jakub Grajciar145e3302019-10-24 13:52:42 +0200109 mac_address_encode ((mac_address_t *) l2fe_key->fields.mac, mp->mac);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100110 mp->sw_if_index = ntohl (l2fe_res->fields.sw_if_index);
Neale Ranns7341b6d2018-09-19 04:07:02 -0700111 mp->static_mac = (l2fib_entry_result_is_set_STATIC (l2fe_res) ? 1 : 0);
112 mp->filter_mac = (l2fib_entry_result_is_set_FILTER (l2fe_res) ? 1 : 0);
113 mp->bvi_mac = (l2fib_entry_result_is_set_BVI (l2fe_res) ? 1 : 0);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100114 mp->context = context;
115
Florin Coras6c4dae22018-01-09 06:39:23 -0800116 vl_api_send_msg (reg, (u8 *) mp);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100117}
118
119static void
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100120vl_api_l2_fib_table_dump_t_handler (vl_api_l2_fib_table_dump_t * mp)
121{
122 vpe_api_main_t *am = &vpe_api_main;
123 bd_main_t *bdm = &bd_main;
124 l2fib_entry_key_t *l2fe_key = NULL;
125 l2fib_entry_result_t *l2fe_res = NULL;
126 u32 ni, bd_id = ntohl (mp->bd_id);
127 u32 bd_index;
Florin Coras6c4dae22018-01-09 06:39:23 -0800128 vl_api_registration_t *reg;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100129 uword *p;
130
Florin Coras6c4dae22018-01-09 06:39:23 -0800131 reg = vl_api_client_index_to_registration (mp->client_index);
132 if (!reg)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100133 return;
134
135 /* see l2fib_table_dump: ~0 means "any" */
136 if (bd_id == ~0)
137 bd_index = ~0;
138 else
139 {
140 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
141 if (p == 0)
142 return;
143
144 bd_index = p[0];
145 }
146
147 l2fib_table_dump (bd_index, &l2fe_key, &l2fe_res);
148
149 vec_foreach_index (ni, l2fe_key)
150 {
Florin Coras6c4dae22018-01-09 06:39:23 -0800151 send_l2fib_table_entry (am, reg, vec_elt_at_index (l2fe_key, ni),
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100152 vec_elt_at_index (l2fe_res, ni), mp->context);
153 }
154 vec_free (l2fe_key);
155 vec_free (l2fe_res);
156}
157
158static void
159vl_api_l2fib_add_del_t_handler (vl_api_l2fib_add_del_t * mp)
160{
161 bd_main_t *bdm = &bd_main;
162 l2input_main_t *l2im = &l2input_main;
163 vl_api_l2fib_add_del_reply_t *rmp;
164 int rv = 0;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100165 u32 bd_id = ntohl (mp->bd_id);
Eyal Bari31a71ab2017-06-25 14:42:33 +0300166 uword *p = hash_get (bdm->bd_index_by_bd_id, bd_id);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100167
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100168 if (!p)
169 {
170 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
171 goto bad_sw_if_index;
172 }
Eyal Bari31a71ab2017-06-25 14:42:33 +0300173 u32 bd_index = p[0];
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100174
Jakub Grajciar145e3302019-10-24 13:52:42 +0200175 mac_address_t mac;
Mohsin Kazmi57938f62017-10-27 21:28:07 +0200176
Jakub Grajciar145e3302019-10-24 13:52:42 +0200177 mac_address_decode (mp->mac, &mac);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100178 if (mp->is_add)
179 {
Eyal Bari31a71ab2017-06-25 14:42:33 +0300180 if (mp->filter_mac)
Jakub Grajciar145e3302019-10-24 13:52:42 +0200181 l2fib_add_filter_entry (mac.bytes, bd_index);
Eyal Bari31a71ab2017-06-25 14:42:33 +0300182 else
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100183 {
Neale Rannsb54d0812018-09-06 06:22:56 -0700184 l2fib_entry_result_flags_t flags = L2FIB_ENTRY_RESULT_FLAG_NONE;
Eyal Bari31a71ab2017-06-25 14:42:33 +0300185 u32 sw_if_index = ntohl (mp->sw_if_index);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100186 VALIDATE_SW_IF_INDEX (mp);
187 if (vec_len (l2im->configs) <= sw_if_index)
188 {
189 rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
190 goto bad_sw_if_index;
191 }
192 else
193 {
194 l2_input_config_t *config;
195 config = vec_elt_at_index (l2im->configs, sw_if_index);
Neale Ranns47a3d992020-09-29 15:38:51 +0000196 if (!l2_input_is_bridge (config))
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100197 {
198 rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
199 goto bad_sw_if_index;
200 }
201 }
Neale Rannsb54d0812018-09-06 06:22:56 -0700202 if (mp->static_mac)
203 flags |= L2FIB_ENTRY_RESULT_FLAG_STATIC;
204 if (mp->bvi_mac)
205 flags |= L2FIB_ENTRY_RESULT_FLAG_BVI;
Jakub Grajciar145e3302019-10-24 13:52:42 +0200206 l2fib_add_entry (mac.bytes, bd_index, sw_if_index, flags);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100207 }
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100208 }
209 else
210 {
John Lo7dbd7262018-05-31 10:25:18 -0400211 u32 sw_if_index = ntohl (mp->sw_if_index);
Jakub Grajciar145e3302019-10-24 13:52:42 +0200212 if (l2fib_del_entry (mac.bytes, bd_index, sw_if_index))
John Lo7dbd7262018-05-31 10:25:18 -0400213 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100214 }
215
216 BAD_SW_IF_INDEX_LABEL;
217
218 REPLY_MACRO (VL_API_L2FIB_ADD_DEL_REPLY);
219}
220
221static void
Jerome Tollet0f8d1002021-01-07 12:44:17 +0100222vl_api_want_l2_macs_events2_t_handler (vl_api_want_l2_macs_events2_t *mp)
John Lo8d00fff2017-08-03 00:35:36 -0400223{
224 int rv = 0;
Jerome Tollet0f8d1002021-01-07 12:44:17 +0100225 vl_api_want_l2_macs_events2_reply_t *rmp;
John Lo8d00fff2017-08-03 00:35:36 -0400226 l2learn_main_t *lm = &l2learn_main;
227 l2fib_main_t *fm = &l2fib_main;
228 u32 pid = ntohl (mp->pid);
John Lo8d00fff2017-08-03 00:35:36 -0400229
230 if (mp->enable_disable)
231 {
Jerome Tollet0f8d1002021-01-07 12:44:17 +0100232 if ((lm->client_pid == 0) || (lm->client_pid == pid))
John Lo8d00fff2017-08-03 00:35:36 -0400233 {
John Lo8d00fff2017-08-03 00:35:36 -0400234 if (mp->max_macs_in_event)
235 fm->max_macs_in_event = mp->max_macs_in_event * 10;
236 else
Jakub Grajciar145e3302019-10-24 13:52:42 +0200237 {
238 rv = VNET_API_ERROR_INVALID_VALUE;
239 goto exit;
240 }
John Lo8d00fff2017-08-03 00:35:36 -0400241
Jerome Tollet0f8d1002021-01-07 12:44:17 +0100242 /* if scan_delay was not set before */
243 if (fm->event_scan_delay == 0.0)
244 fm->event_scan_delay = (f64) (10) * 10e-3;
John Lo8d00fff2017-08-03 00:35:36 -0400245
Jerome Tollet0f8d1002021-01-07 12:44:17 +0100246 lm->client_pid = pid;
247 lm->client_index = mp->client_index;
John Lo8d00fff2017-08-03 00:35:36 -0400248 l2fib_flush_all_mac (vlib_get_main ());
249 }
250 else if (lm->client_pid != pid)
251 {
252 rv = VNET_API_ERROR_L2_MACS_EVENT_CLINET_PRESENT;
253 goto exit;
254 }
255 }
256 else if (lm->client_pid)
257 {
258 lm->client_pid = 0;
259 lm->client_index = 0;
Jerome Tollet0f8d1002021-01-07 12:44:17 +0100260 }
261
262exit:
263 REPLY_MACRO (VL_API_WANT_L2_MACS_EVENTS2_REPLY);
264}
265
266static void
267vl_api_want_l2_macs_events_t_handler (vl_api_want_l2_macs_events_t *mp)
268{
269 int rv = 0;
270 vl_api_want_l2_macs_events_reply_t *rmp;
271 l2learn_main_t *lm = &l2learn_main;
272 l2fib_main_t *fm = &l2fib_main;
273 u32 pid = ntohl (mp->pid);
274 u32 learn_limit = ntohl (mp->learn_limit);
275
276 if (mp->enable_disable)
277 {
278 if ((lm->client_pid == 0) || (lm->client_pid == pid))
279 {
280 if ((mp->max_macs_in_event == 0) || (mp->scan_delay == 0) ||
281 (learn_limit == 0) || (learn_limit > L2LEARN_DEFAULT_LIMIT))
282 {
283 rv = VNET_API_ERROR_INVALID_VALUE;
284 goto exit;
285 }
286 lm->client_pid = pid;
287 lm->client_index = mp->client_index;
288
289 fm->max_macs_in_event = mp->max_macs_in_event * 10;
290 fm->event_scan_delay = (f64) (mp->scan_delay) * 10e-3;
291
292 /* change learn limit and flush all learned MACs */
293 lm->global_learn_limit = learn_limit;
294 l2fib_flush_all_mac (vlib_get_main ());
295 }
296 else if (lm->client_pid != pid)
297 {
298 rv = VNET_API_ERROR_L2_MACS_EVENT_CLINET_PRESENT;
299 goto exit;
300 }
301 }
302 else if (lm->client_pid)
303 {
304 lm->client_pid = 0;
305 lm->client_index = 0;
306 if (learn_limit && (learn_limit <= L2LEARN_DEFAULT_LIMIT))
John Loe531f4c2017-08-22 09:16:50 -0400307 lm->global_learn_limit = learn_limit;
308 else
309 lm->global_learn_limit = L2LEARN_DEFAULT_LIMIT;
John Lo8d00fff2017-08-03 00:35:36 -0400310 }
311
312exit:
313 REPLY_MACRO (VL_API_WANT_L2_MACS_EVENTS_REPLY);
314}
315
316static void
Eyal Barif24991c2017-04-05 05:33:21 +0300317vl_api_l2fib_flush_int_t_handler (vl_api_l2fib_flush_int_t * mp)
318{
319 int rv = 0;
320 vlib_main_t *vm = vlib_get_main ();
321 vl_api_l2fib_flush_int_reply_t *rmp;
322
323 VALIDATE_SW_IF_INDEX (mp);
324
325 u32 sw_if_index = ntohl (mp->sw_if_index);
326 l2fib_flush_int_mac (vm, sw_if_index);
327
328 BAD_SW_IF_INDEX_LABEL;
329 REPLY_MACRO (VL_API_L2FIB_FLUSH_INT_REPLY);
330}
331
332static void
Eyal Bari7537e712017-04-27 14:07:55 +0300333vl_api_l2fib_flush_all_t_handler (vl_api_l2fib_flush_all_t * mp)
334{
335 int rv = 0;
336 vl_api_l2fib_flush_all_reply_t *rmp;
337
338 l2fib_flush_all_mac (vlib_get_main ());
339 REPLY_MACRO (VL_API_L2FIB_FLUSH_ALL_REPLY);
340}
341
342static void
Eyal Barif24991c2017-04-05 05:33:21 +0300343vl_api_l2fib_flush_bd_t_handler (vl_api_l2fib_flush_bd_t * mp)
344{
345 int rv = 0;
346 vlib_main_t *vm = vlib_get_main ();
347 bd_main_t *bdm = &bd_main;
348 vl_api_l2fib_flush_bd_reply_t *rmp;
349
350 u32 bd_id = ntohl (mp->bd_id);
351 uword *p = hash_get (bdm->bd_index_by_bd_id, bd_id);
352 if (p == 0)
353 {
354 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
355 goto out;
356 }
357 l2fib_flush_bd_mac (vm, *p);
358out:
359 REPLY_MACRO (VL_API_L2FIB_FLUSH_BD_REPLY);
360}
361
362static void
Jerome Tollet0f8d1002021-01-07 12:44:17 +0100363vl_api_l2fib_set_scan_delay_t_handler (vl_api_l2fib_set_scan_delay_t *mp)
364{
365 int rv = 0;
366 l2fib_main_t *fm = &l2fib_main;
367 vl_api_l2fib_set_scan_delay_reply_t *rmp;
368 u16 scan_delay = ntohs (mp->scan_delay);
369
370 if (mp->scan_delay)
371 {
372 fm->event_scan_delay = (f64) (scan_delay) *10e-3;
373 l2fib_flush_all_mac (vlib_get_main ());
374 }
375 else
376 {
377 rv = VNET_API_ERROR_INVALID_VALUE;
378 goto exit;
379 }
380
381exit:
382 REPLY_MACRO (VL_API_L2FIB_SET_SCAN_DELAY_REPLY);
383}
384
385static void
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100386vl_api_l2_flags_t_handler (vl_api_l2_flags_t * mp)
387{
388 vl_api_l2_flags_reply_t *rmp;
389 int rv = 0;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100390 u32 rbm = 0;
391
392 VALIDATE_SW_IF_INDEX (mp);
393
Eyal Barifead6702017-04-04 04:46:32 +0300394 u32 sw_if_index = ntohl (mp->sw_if_index);
John Lo8d00fff2017-08-03 00:35:36 -0400395 u32 flags = ntohl (mp->feature_bitmap);
396 u32 bitmap = 0;
397
398 if (flags & L2_LEARN)
399 bitmap |= L2INPUT_FEAT_LEARN;
400
401 if (flags & L2_FWD)
402 bitmap |= L2INPUT_FEAT_FWD;
403
404 if (flags & L2_FLOOD)
405 bitmap |= L2INPUT_FEAT_FLOOD;
406
407 if (flags & L2_UU_FLOOD)
408 bitmap |= L2INPUT_FEAT_UU_FLOOD;
409
410 if (flags & L2_ARP_TERM)
411 bitmap |= L2INPUT_FEAT_ARP_TERM;
412
413 rbm = l2input_intf_bitmap_enable (sw_if_index, bitmap, mp->is_set);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100414
415 BAD_SW_IF_INDEX_LABEL;
416
417 /* *INDENT-OFF* */
418 REPLY_MACRO2(VL_API_L2_FLAGS_REPLY,
419 ({
420 rmp->resulting_feature_bitmap = ntohl(rbm);
421 }));
422 /* *INDENT-ON* */
423}
424
425static void
Jerome Tollet5f93e3b2020-12-18 09:44:24 +0100426vl_api_bridge_domain_set_default_learn_limit_t_handler (
427 vl_api_bridge_domain_set_default_learn_limit_t *mp)
428{
429 vl_api_bridge_domain_set_default_learn_limit_reply_t *rmp;
430 int rv = 0;
431
432 l2learn_main.bd_default_learn_limit = ntohl (mp->learn_limit);
433 REPLY_MACRO (VL_API_BRIDGE_DOMAIN_SET_DEFAULT_LEARN_LIMIT_REPLY);
434}
435
436static void
437vl_api_bridge_domain_set_learn_limit_t_handler (
438 vl_api_bridge_domain_set_learn_limit_t *mp)
439{
440 vlib_main_t *vm = vlib_get_main ();
441 bd_main_t *bdm = &bd_main;
442 vl_api_bridge_domain_set_learn_limit_reply_t *rmp;
443 int rv = 0;
444 u32 bd_id = ntohl (mp->bd_id);
445 uword *p;
446
447 if (bd_id == 0)
448 {
449 rv = VNET_API_ERROR_BD_NOT_MODIFIABLE;
450 goto out;
451 }
452
453 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
454 if (p == 0)
455 {
456 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
457 goto out;
458 }
459 bd_set_learn_limit (vm, *p, ntohl (mp->learn_limit));
460out:
461 REPLY_MACRO (VL_API_BRIDGE_DOMAIN_SET_LEARN_LIMIT_REPLY);
462}
463
464static void
Eyal Barifead6702017-04-04 04:46:32 +0300465vl_api_bridge_domain_set_mac_age_t_handler (vl_api_bridge_domain_set_mac_age_t
466 * mp)
467{
468 vlib_main_t *vm = vlib_get_main ();
469 bd_main_t *bdm = &bd_main;
470 vl_api_bridge_domain_set_mac_age_reply_t *rmp;
471 int rv = 0;
472 u32 bd_id = ntohl (mp->bd_id);
Jon Loeliger1c7d4852017-05-02 11:06:23 -0500473 uword *p;
474
475 if (bd_id == 0)
476 {
477 rv = VNET_API_ERROR_BD_NOT_MODIFIABLE;
478 goto out;
479 }
480
481 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
Eyal Barifead6702017-04-04 04:46:32 +0300482 if (p == 0)
483 {
484 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
485 goto out;
486 }
487 bd_set_mac_age (vm, *p, mp->mac_age);
488out:
489 REPLY_MACRO (VL_API_BRIDGE_DOMAIN_SET_MAC_AGE_REPLY);
490}
491
492static void
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100493vl_api_bridge_domain_add_del_t_handler (vl_api_bridge_domain_add_del_t * mp)
494{
Eyal Barib1352ed2017-04-07 23:14:17 +0300495 l2_bridge_domain_add_del_args_t a = {
496 .is_add = mp->is_add,
497 .flood = mp->flood,
498 .uu_flood = mp->uu_flood,
499 .forward = mp->forward,
500 .learn = mp->learn,
501 .arp_term = mp->arp_term,
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +0200502 .arp_ufwd = mp->arp_ufwd,
Eyal Barib1352ed2017-04-07 23:14:17 +0300503 .mac_age = mp->mac_age,
504 .bd_id = ntohl (mp->bd_id),
Jerome Tollet48304142017-09-05 12:13:22 +0100505 .bd_tag = mp->bd_tag
Eyal Barib1352ed2017-04-07 23:14:17 +0300506 };
507
508 int rv = bd_add_del (&a);
509
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100510 vl_api_bridge_domain_add_del_reply_t *rmp;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100511 REPLY_MACRO (VL_API_BRIDGE_DOMAIN_ADD_DEL_REPLY);
512}
513
514static void
Laszlo Kiraly0f8f4352022-09-16 13:20:07 +0200515vl_api_bridge_domain_add_del_v2_t_handler (
516 vl_api_bridge_domain_add_del_v2_t *mp)
517{
518 vl_api_bridge_domain_add_del_v2_reply_t *rmp;
519 u32 bd_id = ntohl (mp->bd_id);
520 int rv = 0;
521
522 if ((~0 == bd_id) && (mp->is_add))
523 bd_id = bd_get_unused_id ();
524
525 if ((~0 == bd_id) && (mp->is_add))
526 rv = VNET_API_ERROR_EAGAIN;
527 else
528 {
529 l2_bridge_domain_add_del_args_t a = { .is_add = mp->is_add,
530 .flood = mp->flood,
531 .uu_flood = mp->uu_flood,
532 .forward = mp->forward,
533 .learn = mp->learn,
534 .arp_term = mp->arp_term,
535 .arp_ufwd = mp->arp_ufwd,
536 .mac_age = mp->mac_age,
537 .bd_id = bd_id,
538 .bd_tag = mp->bd_tag };
539 rv = bd_add_del (&a);
540 }
541 REPLY_MACRO2 (VL_API_BRIDGE_DOMAIN_ADD_DEL_V2_REPLY,
542 ({ rmp->bd_id = htonl (bd_id); }));
543}
544
545static void
Ole Troan01384fe2017-05-12 11:55:35 +0200546send_bridge_domain_details (l2input_main_t * l2im,
Florin Coras6c4dae22018-01-09 06:39:23 -0800547 vl_api_registration_t * reg,
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100548 l2_bridge_domain_t * bd_config,
549 u32 n_sw_ifs, u32 context)
550{
551 vl_api_bridge_domain_details_t *mp;
Ole Troan01384fe2017-05-12 11:55:35 +0200552 l2_flood_member_t *m;
553 vl_api_bridge_domain_sw_if_t *sw_ifs;
554 l2_input_config_t *input_cfg;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100555
Ole Troan01384fe2017-05-12 11:55:35 +0200556 mp = vl_msg_api_alloc (sizeof (*mp) +
557 (n_sw_ifs * sizeof (vl_api_bridge_domain_sw_if_t)));
Dave Barachb7b92992018-10-17 10:38:51 -0400558 clib_memset (mp, 0, sizeof (*mp));
Filip Tehlar5a9d2a12021-06-22 21:20:29 +0000559 mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_BRIDGE_DOMAIN_DETAILS);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100560 mp->bd_id = ntohl (bd_config->bd_id);
561 mp->flood = bd_feature_flood (bd_config);
562 mp->uu_flood = bd_feature_uu_flood (bd_config);
563 mp->forward = bd_feature_forward (bd_config);
564 mp->learn = bd_feature_learn (bd_config);
565 mp->arp_term = bd_feature_arp_term (bd_config);
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +0200566 mp->arp_ufwd = bd_feature_arp_ufwd (bd_config);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100567 mp->bvi_sw_if_index = ntohl (bd_config->bvi_sw_if_index);
Neale Rannsb4743802018-09-05 09:13:57 -0700568 mp->uu_fwd_sw_if_index = ntohl (bd_config->uu_fwd_sw_if_index);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100569 mp->mac_age = bd_config->mac_age;
Jerome Tollet48304142017-09-05 12:13:22 +0100570 if (bd_config->bd_tag)
571 {
572 strncpy ((char *) mp->bd_tag, (char *) bd_config->bd_tag,
573 ARRAY_LEN (mp->bd_tag) - 1);
574 mp->bd_tag[ARRAY_LEN (mp->bd_tag) - 1] = 0;
575 }
576
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100577 mp->context = context;
578
Ole Troan01384fe2017-05-12 11:55:35 +0200579 sw_ifs = (vl_api_bridge_domain_sw_if_t *) mp->sw_if_details;
580 vec_foreach (m, bd_config->members)
581 {
582 sw_ifs->sw_if_index = ntohl (m->sw_if_index);
583 input_cfg = vec_elt_at_index (l2im->configs, m->sw_if_index);
584 sw_ifs->shg = input_cfg->shg;
585 sw_ifs++;
586 mp->n_sw_ifs++;
587 }
588 mp->n_sw_ifs = htonl (mp->n_sw_ifs);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100589
Florin Coras6c4dae22018-01-09 06:39:23 -0800590 vl_api_send_msg (reg, (u8 *) mp);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100591}
592
593static void
594vl_api_bridge_domain_dump_t_handler (vl_api_bridge_domain_dump_t * mp)
595{
596 bd_main_t *bdm = &bd_main;
597 l2input_main_t *l2im = &l2input_main;
Florin Coras6c4dae22018-01-09 06:39:23 -0800598 vl_api_registration_t *reg;
Jakub Grajciar145e3302019-10-24 13:52:42 +0200599 u32 bd_id, bd_index, end, filter_sw_if_index;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100600
Florin Coras6c4dae22018-01-09 06:39:23 -0800601 reg = vl_api_client_index_to_registration (mp->client_index);
602 if (!reg)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100603 return;
604
Jakub Grajciar145e3302019-10-24 13:52:42 +0200605 filter_sw_if_index = ntohl (mp->sw_if_index);
606 if (filter_sw_if_index != ~0)
607 return; /* UNIMPLEMENTED */
608
Florin Coras6c4dae22018-01-09 06:39:23 -0800609 bd_id = ntohl (mp->bd_id);
Jon Loeliger1c7d4852017-05-02 11:06:23 -0500610 if (bd_id == 0)
611 return;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100612
Eyal Bari259fca72017-05-14 10:38:39 +0300613 if (bd_id == ~0)
614 bd_index = 0, end = vec_len (l2im->bd_configs);
615 else
616 {
617 bd_index = bd_find_index (bdm, bd_id);
618 if (bd_index == ~0)
619 return;
620
621 end = bd_index + 1;
622 }
Jon Loeliger1c7d4852017-05-02 11:06:23 -0500623
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100624 for (; bd_index < end; bd_index++)
625 {
Eyal Bari259fca72017-05-14 10:38:39 +0300626 l2_bridge_domain_t *bd_config =
627 l2input_bd_config_from_index (l2im, bd_index);
Dave Barach11fb09e2020-08-06 12:10:09 -0400628 /* skip placeholder bd_id 0 */
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100629 if (bd_config && (bd_config->bd_id > 0))
Florin Coras6c4dae22018-01-09 06:39:23 -0800630 send_bridge_domain_details (l2im, reg, bd_config,
Ole Troan01384fe2017-05-12 11:55:35 +0200631 vec_len (bd_config->members),
632 mp->context);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100633 }
634}
635
Neale Rannsb4743802018-09-05 09:13:57 -0700636static bd_flags_t
637bd_flags_decode (vl_api_bd_flags_t v)
638{
639 bd_flags_t f = L2_NONE;
640
641 v = ntohl (v);
642
643 if (v & BRIDGE_API_FLAG_LEARN)
644 f |= L2_LEARN;
645 if (v & BRIDGE_API_FLAG_FWD)
646 f |= L2_FWD;
647 if (v & BRIDGE_API_FLAG_FLOOD)
648 f |= L2_FLOOD;
649 if (v & BRIDGE_API_FLAG_UU_FLOOD)
650 f |= L2_UU_FLOOD;
651 if (v & BRIDGE_API_FLAG_ARP_TERM)
652 f |= L2_ARP_TERM;
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +0200653 if (v & BRIDGE_API_FLAG_ARP_UFWD)
654 f |= L2_ARP_UFWD;
Neale Rannsb4743802018-09-05 09:13:57 -0700655
656 return (f);
657}
658
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100659static void
660vl_api_bridge_flags_t_handler (vl_api_bridge_flags_t * mp)
661{
662 vlib_main_t *vm = vlib_get_main ();
663 bd_main_t *bdm = &bd_main;
664 vl_api_bridge_flags_reply_t *rmp;
Dave Barach98d6b612019-01-03 09:30:00 -0500665 u32 bitmap = 0;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100666 int rv = 0;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100667
Neale Rannsb4743802018-09-05 09:13:57 -0700668 bd_flags_t flags = bd_flags_decode (mp->flags);
Eyal Bari259fca72017-05-14 10:38:39 +0300669 u32 bd_id = ntohl (mp->bd_id);
Jon Loeliger1c7d4852017-05-02 11:06:23 -0500670 if (bd_id == 0)
671 {
672 rv = VNET_API_ERROR_BD_NOT_MODIFIABLE;
673 goto out;
674 }
675
Eyal Bari259fca72017-05-14 10:38:39 +0300676 u32 bd_index = bd_find_index (bdm, bd_id);
677 if (bd_index == ~0)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100678 {
679 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
680 goto out;
681 }
682
Dave Barach98d6b612019-01-03 09:30:00 -0500683 bitmap = bd_set_flags (vm, bd_index, flags, mp->is_set);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100684
685out:
686 /* *INDENT-OFF* */
687 REPLY_MACRO2(VL_API_BRIDGE_FLAGS_REPLY,
688 ({
John Lo8d00fff2017-08-03 00:35:36 -0400689 rmp->resulting_feature_bitmap = ntohl(bitmap);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100690 }));
691 /* *INDENT-ON* */
692}
Matus Fabianf468e232016-12-02 06:00:53 -0800693
Pavel Kotucekadec5872017-01-25 08:50:53 +0100694static void
695 vl_api_l2_interface_vlan_tag_rewrite_t_handler
696 (vl_api_l2_interface_vlan_tag_rewrite_t * mp)
697{
698 int rv = 0;
699 vl_api_l2_interface_vlan_tag_rewrite_reply_t *rmp;
700 vnet_main_t *vnm = vnet_get_main ();
701 vlib_main_t *vm = vlib_get_main ();
702 u32 vtr_op;
703
704 VALIDATE_SW_IF_INDEX (mp);
705
706 vtr_op = ntohl (mp->vtr_op);
707
708 /* The L2 code is unsuspicious */
709 switch (vtr_op)
710 {
711 case L2_VTR_DISABLED:
712 case L2_VTR_PUSH_1:
713 case L2_VTR_PUSH_2:
714 case L2_VTR_POP_1:
715 case L2_VTR_POP_2:
716 case L2_VTR_TRANSLATE_1_1:
717 case L2_VTR_TRANSLATE_1_2:
718 case L2_VTR_TRANSLATE_2_1:
719 case L2_VTR_TRANSLATE_2_2:
720 break;
721
722 default:
723 rv = VNET_API_ERROR_INVALID_VALUE;
724 goto bad_sw_if_index;
725 }
726
727 rv = l2vtr_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
728 ntohl (mp->push_dot1q), ntohl (mp->tag1),
729 ntohl (mp->tag2));
730
731 BAD_SW_IF_INDEX_LABEL;
732
733 REPLY_MACRO (VL_API_L2_INTERFACE_VLAN_TAG_REWRITE_REPLY);
734}
735
736static void
737 vl_api_l2_interface_pbb_tag_rewrite_t_handler
738 (vl_api_l2_interface_pbb_tag_rewrite_t * mp)
739{
740 vl_api_l2_interface_pbb_tag_rewrite_reply_t *rmp;
741 vnet_main_t *vnm = vnet_get_main ();
742 vlib_main_t *vm = vlib_get_main ();
743 u32 vtr_op;
744 int rv = 0;
Jakub Grajciar145e3302019-10-24 13:52:42 +0200745 mac_address_t b_dmac, b_smac;
Pavel Kotucekadec5872017-01-25 08:50:53 +0100746
747 VALIDATE_SW_IF_INDEX (mp);
748
749 vtr_op = ntohl (mp->vtr_op);
750
751 switch (vtr_op)
752 {
753 case L2_VTR_DISABLED:
754 case L2_VTR_PUSH_2:
755 case L2_VTR_POP_2:
756 case L2_VTR_TRANSLATE_2_1:
757 break;
758
759 default:
760 rv = VNET_API_ERROR_INVALID_VALUE;
761 goto bad_sw_if_index;
762 }
763
Jakub Grajciar145e3302019-10-24 13:52:42 +0200764 mac_address_decode (mp->b_dmac, &b_dmac);
765 mac_address_decode (mp->b_smac, &b_smac);
766
Pavel Kotucekadec5872017-01-25 08:50:53 +0100767 rv = l2pbb_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
Jakub Grajciar145e3302019-10-24 13:52:42 +0200768 b_dmac.bytes, b_smac.bytes, ntohs (mp->b_vlanid),
Pavel Kotucekadec5872017-01-25 08:50:53 +0100769 ntohl (mp->i_sid), ntohs (mp->outer_tag));
770
771 BAD_SW_IF_INDEX_LABEL;
772
773 REPLY_MACRO (VL_API_L2_INTERFACE_PBB_TAG_REWRITE_REPLY);
774}
775
Neale Rannsb8d44812017-11-10 06:53:54 -0800776static void
777 vl_api_sw_interface_set_l2_xconnect_t_handler
778 (vl_api_sw_interface_set_l2_xconnect_t * mp)
779{
780 vl_api_sw_interface_set_l2_xconnect_reply_t *rmp;
781 int rv = 0;
782 u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
783 u32 tx_sw_if_index = ntohl (mp->tx_sw_if_index);
784 vlib_main_t *vm = vlib_get_main ();
785 vnet_main_t *vnm = vnet_get_main ();
786
787 VALIDATE_RX_SW_IF_INDEX (mp);
788
789 if (mp->enable)
790 {
791 VALIDATE_TX_SW_IF_INDEX (mp);
792 rv = set_int_l2_mode (vm, vnm, MODE_L2_XC,
Neale Rannsb4743802018-09-05 09:13:57 -0700793 rx_sw_if_index, 0,
794 L2_BD_PORT_TYPE_NORMAL, 0, tx_sw_if_index);
Neale Rannsb8d44812017-11-10 06:53:54 -0800795 }
796 else
797 {
Neale Rannsb4743802018-09-05 09:13:57 -0700798 rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0,
799 L2_BD_PORT_TYPE_NORMAL, 0, 0);
Neale Rannsb8d44812017-11-10 06:53:54 -0800800 }
801
Alexander Chernavine178b272018-09-24 05:42:01 -0400802 switch (rv)
803 {
804 case MODE_ERROR_ETH:
805 rv = VNET_API_ERROR_NON_ETHERNET;
806 break;
807 case MODE_ERROR_BVI_DEF:
808 rv = VNET_API_ERROR_BD_ALREADY_HAS_BVI;
809 break;
810 }
811
Neale Rannsb8d44812017-11-10 06:53:54 -0800812 BAD_RX_SW_IF_INDEX_LABEL;
813 BAD_TX_SW_IF_INDEX_LABEL;
814
815 REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_XCONNECT_REPLY);
816}
817
Neale Rannsb4743802018-09-05 09:13:57 -0700818static int
819l2_bd_port_type_decode (vl_api_l2_port_type_t v, l2_bd_port_type_t * l)
820{
821 v = clib_net_to_host_u32 (v);
822
823 switch (v)
824 {
825 case L2_API_PORT_TYPE_NORMAL:
826 *l = L2_BD_PORT_TYPE_NORMAL;
827 return 0;
828 case L2_API_PORT_TYPE_BVI:
829 *l = L2_BD_PORT_TYPE_BVI;
830 return 0;
831 case L2_API_PORT_TYPE_UU_FWD:
832 *l = L2_BD_PORT_TYPE_UU_FWD;
833 return 0;
834 }
835
836 return (VNET_API_ERROR_INVALID_VALUE);
837}
838
Neale Rannsb8d44812017-11-10 06:53:54 -0800839static void
840 vl_api_sw_interface_set_l2_bridge_t_handler
841 (vl_api_sw_interface_set_l2_bridge_t * mp)
842{
843 bd_main_t *bdm = &bd_main;
844 vl_api_sw_interface_set_l2_bridge_reply_t *rmp;
845 int rv = 0;
846 vlib_main_t *vm = vlib_get_main ();
847 vnet_main_t *vnm = vnet_get_main ();
Neale Rannsb4743802018-09-05 09:13:57 -0700848 l2_bd_port_type_t pt;
Neale Rannsb8d44812017-11-10 06:53:54 -0800849
850 VALIDATE_RX_SW_IF_INDEX (mp);
851 u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
Neale Rannsb4743802018-09-05 09:13:57 -0700852 rv = l2_bd_port_type_decode (mp->port_type, &pt);
Neale Rannsb8d44812017-11-10 06:53:54 -0800853
Neale Rannsb4743802018-09-05 09:13:57 -0700854 if (0 != rv)
855 goto out;
Neale Rannsb8d44812017-11-10 06:53:54 -0800856 if (mp->enable)
857 {
858 VALIDATE_BD_ID (mp);
859 u32 bd_id = ntohl (mp->bd_id);
860 u32 bd_index = bd_find_or_add_bd_index (bdm, bd_id);
Neale Rannsb4743802018-09-05 09:13:57 -0700861
Neale Rannsb8d44812017-11-10 06:53:54 -0800862 rv = set_int_l2_mode (vm, vnm, MODE_L2_BRIDGE,
Neale Rannsb4743802018-09-05 09:13:57 -0700863 rx_sw_if_index, bd_index, pt, mp->shg, 0);
Neale Rannsb8d44812017-11-10 06:53:54 -0800864 }
865 else
866 {
Neale Rannsb4743802018-09-05 09:13:57 -0700867 rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0, pt, 0, 0);
Neale Rannsb8d44812017-11-10 06:53:54 -0800868 }
869
Alexander Chernavine178b272018-09-24 05:42:01 -0400870 switch (rv)
871 {
872 case MODE_ERROR_ETH:
873 rv = VNET_API_ERROR_NON_ETHERNET;
874 break;
875 case MODE_ERROR_BVI_DEF:
876 rv = VNET_API_ERROR_BD_ALREADY_HAS_BVI;
877 break;
878 }
879
Neale Rannsb8d44812017-11-10 06:53:54 -0800880 BAD_RX_SW_IF_INDEX_LABEL;
881 BAD_BD_ID_LABEL;
Neale Rannsb4743802018-09-05 09:13:57 -0700882out:
Neale Rannsb8d44812017-11-10 06:53:54 -0800883 REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_BRIDGE_REPLY);
884}
885
886static void
Mohsin Kazmi5d82d2f2018-08-13 19:17:54 +0200887send_bd_ip_mac_entry (vpe_api_main_t * am,
888 vl_api_registration_t * reg,
Neale Rannsbc764c82019-06-19 07:07:13 -0700889 u32 bd_id,
890 const ip46_address_t * ip,
891 ip46_type_t itype,
892 const mac_address_t * mac, u32 context)
Mohsin Kazmi5d82d2f2018-08-13 19:17:54 +0200893{
894 vl_api_bd_ip_mac_details_t *mp;
895
896 mp = vl_msg_api_alloc (sizeof (*mp));
Dave Barachb7b92992018-10-17 10:38:51 -0400897 clib_memset (mp, 0, sizeof (*mp));
Filip Tehlar5a9d2a12021-06-22 21:20:29 +0000898 mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_BD_IP_MAC_DETAILS);
Mohsin Kazmi5d82d2f2018-08-13 19:17:54 +0200899
Mohsin Kazmi5d82d2f2018-08-13 19:17:54 +0200900 mp->context = context;
Neale Rannsbc764c82019-06-19 07:07:13 -0700901 mp->entry.bd_id = ntohl (bd_id);
902
903 ip_address_encode (ip, itype, &mp->entry.ip);
904 mac_address_encode (mac, mp->entry.mac);
Mohsin Kazmi5d82d2f2018-08-13 19:17:54 +0200905
906 vl_api_send_msg (reg, (u8 *) mp);
907}
908
909static void
910vl_api_bd_ip_mac_dump_t_handler (vl_api_bd_ip_mac_dump_t * mp)
911{
912 vpe_api_main_t *am = &vpe_api_main;
913 bd_main_t *bdm = &bd_main;
914 l2_bridge_domain_t *bd_config;
915 u32 bd_id = ntohl (mp->bd_id);
Mohsin Kazmib24dfec2018-08-23 12:24:19 +0200916 u32 bd_index, start, end;
Mohsin Kazmi5d82d2f2018-08-13 19:17:54 +0200917 vl_api_registration_t *reg;
918 uword *p;
919
920 reg = vl_api_client_index_to_registration (mp->client_index);
921 if (!reg)
922 return;
923
Mohsin Kazmi5d82d2f2018-08-13 19:17:54 +0200924 /* see bd_id: ~0 means "any" */
925 if (bd_id == ~0)
Mohsin Kazmib24dfec2018-08-23 12:24:19 +0200926 {
927 start = 1;
928 end = vec_len (l2input_main.bd_configs);
929 }
Mohsin Kazmi5d82d2f2018-08-13 19:17:54 +0200930 else
931 {
932 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
933 if (p == 0)
934 return;
935
936 bd_index = p[0];
937 vec_validate (l2input_main.bd_configs, bd_index);
938 start = bd_index;
939 end = start + 1;
940 }
941
942 for (bd_index = start; bd_index < end; bd_index++)
943 {
944 bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
945 if (bd_is_valid (bd_config))
946 {
947 ip4_address_t ip4_addr;
948 ip6_address_t *ip6_addr;
Neale Rannsbc764c82019-06-19 07:07:13 -0700949 mac_address_t mac;
950 u64 mac64;
Mohsin Kazmi5d82d2f2018-08-13 19:17:54 +0200951 bd_id = bd_config->bd_id;
952
953 /* *INDENT-OFF* */
Neale Rannsbc764c82019-06-19 07:07:13 -0700954 hash_foreach (ip4_addr.as_u32, mac64, bd_config->mac_by_ip4,
Mohsin Kazmi5d82d2f2018-08-13 19:17:54 +0200955 ({
Neale Rannsbc764c82019-06-19 07:07:13 -0700956 ip46_address_t ip = {
957 .ip4 = ip4_addr,
958 };
959 mac_address_from_u64(&mac, mac64);
960
961 send_bd_ip_mac_entry (am, reg, bd_id, &ip, IP46_TYPE_IP4,
962 &mac, mp->context);
Mohsin Kazmi5d82d2f2018-08-13 19:17:54 +0200963 }));
964
Neale Rannsbc764c82019-06-19 07:07:13 -0700965 hash_foreach_mem (ip6_addr, mac64, bd_config->mac_by_ip6,
Mohsin Kazmi5d82d2f2018-08-13 19:17:54 +0200966 ({
Neale Rannsbc764c82019-06-19 07:07:13 -0700967 ip46_address_t ip = {
968 .ip6 = *ip6_addr,
969 };
970 mac_address_from_u64(&mac, mac64);
971
972 send_bd_ip_mac_entry (am, reg, bd_id, &ip, IP46_TYPE_IP6,
973 &mac, mp->context);
Mohsin Kazmi5d82d2f2018-08-13 19:17:54 +0200974 }));
975 /* *INDENT-ON* */
976 }
977 }
978}
979
980static void
Neale Rannsb8d44812017-11-10 06:53:54 -0800981vl_api_bd_ip_mac_add_del_t_handler (vl_api_bd_ip_mac_add_del_t * mp)
982{
Neale Ranns4d5b9172018-10-24 02:57:49 -0700983 ip46_address_t ip_addr = ip46_address_initializer;
Neale Rannsb8d44812017-11-10 06:53:54 -0800984 vl_api_bd_ip_mac_add_del_reply_t *rmp;
Neale Ranns4d5b9172018-10-24 02:57:49 -0700985 bd_main_t *bdm = &bd_main;
986 u32 bd_index, bd_id;
987 mac_address_t mac;
988 ip46_type_t type;
Neale Rannsb8d44812017-11-10 06:53:54 -0800989 int rv = 0;
Neale Rannsb8d44812017-11-10 06:53:54 -0800990 uword *p;
991
Neale Rannsbc764c82019-06-19 07:07:13 -0700992 bd_id = ntohl (mp->entry.bd_id);
Neale Ranns4d5b9172018-10-24 02:57:49 -0700993
Neale Rannsb8d44812017-11-10 06:53:54 -0800994 if (bd_id == 0)
995 {
996 rv = VNET_API_ERROR_BD_NOT_MODIFIABLE;
997 goto out;
998 }
999
1000 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1001 if (p == 0)
1002 {
1003 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1004 goto out;
1005 }
Neale Rannsb8d44812017-11-10 06:53:54 -08001006 bd_index = p[0];
Neale Ranns4d5b9172018-10-24 02:57:49 -07001007
Neale Rannsbc764c82019-06-19 07:07:13 -07001008 type = ip_address_decode (&mp->entry.ip, &ip_addr);
1009 mac_address_decode (mp->entry.mac, &mac);
Neale Ranns4d5b9172018-10-24 02:57:49 -07001010
1011 if (bd_add_del_ip_mac (bd_index, type, &ip_addr, &mac, mp->is_add))
Neale Rannsb8d44812017-11-10 06:53:54 -08001012 rv = VNET_API_ERROR_UNSPECIFIED;
1013
1014out:
1015 REPLY_MACRO (VL_API_BD_IP_MAC_ADD_DEL_REPLY);
1016}
1017
John Loe26c81f2019-01-07 15:16:33 -05001018static void
1019vl_api_bd_ip_mac_flush_t_handler (vl_api_bd_ip_mac_flush_t * mp)
1020{
1021 vl_api_bd_ip_mac_flush_reply_t *rmp;
1022 bd_main_t *bdm = &bd_main;
1023 u32 bd_index, bd_id;
1024 int rv = 0;
1025 uword *p;
1026
1027 bd_id = ntohl (mp->bd_id);
1028
1029 if (bd_id == 0)
1030 {
1031 rv = VNET_API_ERROR_BD_NOT_MODIFIABLE;
1032 goto out;
1033 }
1034
1035 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1036 if (p == 0)
1037 {
1038 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1039 goto out;
1040 }
1041 bd_index = p[0];
1042
1043 bd_flush_ip_mac (bd_index);
1044
1045out:
1046 REPLY_MACRO (VL_API_BD_IP_MAC_FLUSH_REPLY);
1047}
1048
Neale Rannsb8d44812017-11-10 06:53:54 -08001049extern void l2_efp_filter_configure (vnet_main_t * vnet_main,
Neale Ranns6b9b41c2018-07-23 05:47:09 -04001050 u32 sw_if_index, u8 enable);
Neale Rannsb8d44812017-11-10 06:53:54 -08001051
1052static void
1053vl_api_l2_interface_efp_filter_t_handler (vl_api_l2_interface_efp_filter_t *
1054 mp)
1055{
1056 int rv;
1057 vl_api_l2_interface_efp_filter_reply_t *rmp;
1058 vnet_main_t *vnm = vnet_get_main ();
1059
Neale Ranns6b9b41c2018-07-23 05:47:09 -04001060 VALIDATE_SW_IF_INDEX (mp);
1061
Neale Rannsb8d44812017-11-10 06:53:54 -08001062 // enable/disable the feature
Neale Ranns6b9b41c2018-07-23 05:47:09 -04001063 l2_efp_filter_configure (vnm, ntohl (mp->sw_if_index), mp->enable_disable);
Neale Rannsb8d44812017-11-10 06:53:54 -08001064 rv = vnm->api_errno;
1065
Neale Ranns6b9b41c2018-07-23 05:47:09 -04001066 BAD_SW_IF_INDEX_LABEL;
Neale Rannsb8d44812017-11-10 06:53:54 -08001067 REPLY_MACRO (VL_API_L2_INTERFACE_EFP_FILTER_REPLY);
1068}
1069
1070static void
1071vl_api_l2_patch_add_del_t_handler (vl_api_l2_patch_add_del_t * mp)
1072{
1073 extern int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
1074 int is_add);
1075 vl_api_l2_patch_add_del_reply_t *rmp;
1076 int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
1077 int is_add);
1078 int rv = 0;
1079
1080 VALIDATE_RX_SW_IF_INDEX (mp);
1081 VALIDATE_TX_SW_IF_INDEX (mp);
1082
1083 rv = vnet_l2_patch_add_del (ntohl (mp->rx_sw_if_index),
1084 ntohl (mp->tx_sw_if_index),
1085 (int) (mp->is_add != 0));
1086
1087 BAD_RX_SW_IF_INDEX_LABEL;
1088 BAD_TX_SW_IF_INDEX_LABEL;
1089
1090 REPLY_MACRO (VL_API_L2_PATCH_ADD_DEL_REPLY);
1091}
1092
1093static void
1094vl_api_sw_interface_set_vpath_t_handler (vl_api_sw_interface_set_vpath_t * mp)
1095{
1096 vl_api_sw_interface_set_vpath_reply_t *rmp;
1097 int rv = 0;
1098 u32 sw_if_index = ntohl (mp->sw_if_index);
1099
1100 VALIDATE_SW_IF_INDEX (mp);
1101
1102 l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_VPATH, mp->enable);
1103 vnet_feature_enable_disable ("ip4-unicast", "vpath-input-ip4",
1104 sw_if_index, mp->enable, 0, 0);
1105 vnet_feature_enable_disable ("ip4-multicast", "vpath-input-ip4",
1106 sw_if_index, mp->enable, 0, 0);
1107 vnet_feature_enable_disable ("ip6-unicast", "vpath-input-ip6",
1108 sw_if_index, mp->enable, 0, 0);
1109 vnet_feature_enable_disable ("ip6-multicast", "vpath-input-ip6",
1110 sw_if_index, mp->enable, 0, 0);
1111
1112 BAD_SW_IF_INDEX_LABEL;
1113
1114 REPLY_MACRO (VL_API_SW_INTERFACE_SET_VPATH_REPLY);
1115}
1116
Neale Ranns192b13f2019-03-15 02:16:20 -07001117static void
1118vl_api_bvi_create_t_handler (vl_api_bvi_create_t * mp)
1119{
1120 vl_api_bvi_create_reply_t *rmp;
1121 mac_address_t mac;
1122 u32 sw_if_index;
1123 int rv;
1124
1125 mac_address_decode (mp->mac, &mac);
1126
1127 rv = l2_bvi_create (ntohl (mp->user_instance), &mac, &sw_if_index);
1128
1129 /* *INDENT-OFF* */
1130 REPLY_MACRO2(VL_API_BVI_CREATE_REPLY,
1131 ({
1132 rmp->sw_if_index = ntohl (sw_if_index);
1133 }));
1134 /* *INDENT-ON* */
1135}
1136
1137static void
1138vl_api_bvi_delete_t_handler (vl_api_bvi_delete_t * mp)
1139{
1140 vl_api_bvi_delete_reply_t *rmp;
1141 int rv;
1142
1143 rv = l2_bvi_delete (ntohl (mp->sw_if_index));
1144
1145 REPLY_MACRO (VL_API_BVI_DELETE_REPLY);
1146}
1147
Neale Rannscbe25aa2019-09-30 10:53:31 +00001148static bool
1149l2_arp_term_publish_event_is_equal (const l2_arp_term_publish_event_t * e1,
1150 const l2_arp_term_publish_event_t * e2)
1151{
1152 if (e1 == NULL || e2 == NULL)
1153 return false;
1154 return (ip46_address_is_equal (&e1->ip, &e2->ip) &&
1155 (e1->sw_if_index == e2->sw_if_index) &&
1156 (mac_address_equal (&e1->mac, &e2->mac)));
1157}
1158
1159static uword
1160l2_arp_term_process (vlib_main_t * vm, vlib_node_runtime_t * rt,
1161 vlib_frame_t * f)
1162{
1163 /* These cross the longjmp boundary (vlib_process_wait_for_event)
1164 * and need to be volatile - to prevent them from being optimized into
1165 * a register - which could change during suspension */
1166 volatile f64 last = vlib_time_now (vm);
1167 volatile l2_arp_term_publish_event_t last_event = { };
1168
1169 l2_arp_term_main_t *l2am = &l2_arp_term_main;
1170
1171 while (1)
1172 {
1173 uword event_type = L2_ARP_TERM_EVENT_PUBLISH;
1174 vpe_client_registration_t *reg;
1175 f64 now;
1176
1177 vlib_process_wait_for_event (vm);
1178
1179 vlib_process_get_event_data (vm, &event_type);
1180 now = vlib_time_now (vm);
1181
1182 if (event_type == L2_ARP_TERM_EVENT_PUBLISH)
1183 {
1184 l2_arp_term_publish_event_t *event;
1185
1186 vec_foreach (event, l2am->publish_events)
1187 {
1188 /* dampen duplicate events - cast away volatile */
1189 if (l2_arp_term_publish_event_is_equal
1190 (event, (l2_arp_term_publish_event_t *) & last_event) &&
1191 (now - last) < 10.0)
1192 {
1193 continue;
1194 }
1195 last_event = *event;
1196 last = now;
1197
Damjan Marionb2c31b62020-12-13 21:47:40 +01001198 pool_foreach (reg, vpe_api_main.l2_arp_term_events_registrations)
Steven Luonge46bd4c2021-02-15 09:25:10 -08001199 {
1200 vl_api_registration_t *vl_reg;
1201 vl_reg =
1202 vl_api_client_index_to_registration (reg->client_index);
1203 ALWAYS_ASSERT (vl_reg != NULL);
Neale Rannscbe25aa2019-09-30 10:53:31 +00001204
Steven Luonge46bd4c2021-02-15 09:25:10 -08001205 if (vl_reg && vl_api_can_send_msg (vl_reg))
1206 {
1207 vl_api_l2_arp_term_event_t *vevent;
1208 vevent = vl_msg_api_alloc (sizeof *vevent);
1209 clib_memset (vevent, 0, sizeof *vevent);
Filip Tehlar5a9d2a12021-06-22 21:20:29 +00001210 vevent->_vl_msg_id =
1211 htons (REPLY_MSG_ID_BASE + VL_API_L2_ARP_TERM_EVENT);
Steven Luonge46bd4c2021-02-15 09:25:10 -08001212 vevent->client_index = reg->client_index;
1213 vevent->pid = reg->client_pid;
1214 ip_address_encode (&event->ip, event->type, &vevent->ip);
1215 vevent->sw_if_index = htonl (event->sw_if_index);
1216 mac_address_encode (&event->mac, vevent->mac);
1217 vl_api_send_msg (vl_reg, (u8 *) vevent);
1218 }
1219 }
Neale Rannscbe25aa2019-09-30 10:53:31 +00001220 }
1221 vec_reset_length (l2am->publish_events);
1222 }
1223 }
1224
1225 return 0;
1226}
1227
1228/* *INDENT-OFF* */
1229VLIB_REGISTER_NODE (l2_arp_term_process_node) = {
1230 .function = l2_arp_term_process,
1231 .type = VLIB_NODE_TYPE_PROCESS,
1232 .name = "l2-arp-term-publisher",
1233};
1234/* *INDENT-ON* */
1235
1236static void
1237vl_api_want_l2_arp_term_events_t_handler (vl_api_want_l2_arp_term_events_t *
1238 mp)
1239{
1240 vl_api_want_l2_arp_term_events_reply_t *rmp;
1241 vpe_api_main_t *am = &vpe_api_main;
1242 vpe_client_registration_t *rp;
1243 int rv = 0;
1244 uword *p;
1245
1246 p = hash_get (am->l2_arp_term_events_registration_hash, mp->client_index);
1247
1248 if (p)
1249 {
1250 if (mp->enable)
1251 {
1252 clib_warning ("pid %d: already enabled...", mp->pid);
1253 rv = VNET_API_ERROR_INVALID_REGISTRATION;
1254 goto reply;
1255 }
1256 else
1257 {
1258 rp = pool_elt_at_index (am->l2_arp_term_events_registrations, p[0]);
1259 pool_put (am->l2_arp_term_events_registrations, rp);
1260 hash_unset (am->l2_arp_term_events_registration_hash,
1261 mp->client_index);
1262 if (pool_elts (am->l2_arp_term_events_registrations) == 0)
1263 l2_arp_term_set_publisher_node (false);
1264 goto reply;
1265 }
1266 }
1267 if (mp->enable == 0)
1268 {
1269 clib_warning ("pid %d: already disabled...", mp->pid);
1270 rv = VNET_API_ERROR_INVALID_REGISTRATION;
1271 goto reply;
1272 }
1273 pool_get (am->l2_arp_term_events_registrations, rp);
1274 rp->client_index = mp->client_index;
1275 rp->client_pid = mp->pid;
1276 hash_set (am->l2_arp_term_events_registration_hash, rp->client_index,
1277 rp - am->l2_arp_term_events_registrations);
1278 l2_arp_term_set_publisher_node (true);
1279
1280reply:
1281 REPLY_MACRO (VL_API_WANT_L2_ARP_TERM_EVENTS_REPLY);
1282}
1283
1284static clib_error_t *
1285want_l2_arp_term_events_reaper (u32 client_index)
1286{
1287 vpe_client_registration_t *rp;
1288 vpe_api_main_t *am;
1289 uword *p;
1290
1291 am = &vpe_api_main;
1292
1293 /* remove from the registration hash */
1294 p = hash_get (am->l2_arp_term_events_registration_hash, client_index);
1295
1296 if (p)
1297 {
1298 rp = pool_elt_at_index (am->l2_arp_term_events_registrations, p[0]);
1299 pool_put (am->l2_arp_term_events_registrations, rp);
1300 hash_unset (am->l2_arp_term_events_registration_hash, client_index);
1301 if (pool_elts (am->l2_arp_term_events_registrations) == 0)
1302 l2_arp_term_set_publisher_node (false);
1303 }
1304 return (NULL);
1305}
1306
1307VL_MSG_API_REAPER_FUNCTION (want_l2_arp_term_events_reaper);
1308
Filip Tehlar5a9d2a12021-06-22 21:20:29 +00001309#include <vnet/l2/l2.api.c>
Matus Fabianf468e232016-12-02 06:00:53 -08001310static clib_error_t *
1311l2_api_hookup (vlib_main_t * vm)
1312{
Dave Barach39d69112019-11-27 11:42:13 -05001313 api_main_t *am = vlibapi_get_main ();
Matus Fabianf468e232016-12-02 06:00:53 -08001314
Steven Luongc5fa2b82019-04-25 11:19:49 -07001315 /* Mark VL_API_BRIDGE_DOMAIN_DUMP as mp safe */
Damjan Marioncada9eb2022-05-18 22:16:11 +02001316 vl_api_set_msg_thread_safe (am, VL_API_BRIDGE_DOMAIN_DUMP, 1);
Steven Luongc5fa2b82019-04-25 11:19:49 -07001317
Matus Fabianf468e232016-12-02 06:00:53 -08001318 /*
1319 * Set up the (msg_name, crc, message-id) table
1320 */
Filip Tehlar5a9d2a12021-06-22 21:20:29 +00001321 REPLY_MSG_ID_BASE = setup_message_id_table ();
Matus Fabianf468e232016-12-02 06:00:53 -08001322
1323 return 0;
1324}
1325
1326VLIB_API_INIT_FUNCTION (l2_api_hookup);
1327
1328/*
1329 * fd.io coding-style-patch-verification: ON
1330 *
1331 * Local Variables:
1332 * eval: (c-set-style "gnu")
1333 * End:
1334 */