diff options
Diffstat (limited to 'src/vnet/l2')
31 files changed, 1657 insertions, 264 deletions
diff --git a/src/vnet/l2/feat_bitmap.c b/src/vnet/l2/feat_bitmap.c index 349ec67462b..507fe365f07 100644 --- a/src/vnet/l2/feat_bitmap.c +++ b/src/vnet/l2/feat_bitmap.c @@ -155,7 +155,6 @@ feat_bitmap_drop_init (vlib_main_t * vm) VLIB_INIT_FUNCTION (feat_bitmap_drop_init); -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (feat_bitmap_drop_node,static) = { .function = feat_bitmap_drop_node_fn, .name = "feature-bitmap-drop", @@ -173,7 +172,6 @@ VLIB_REGISTER_NODE (feat_bitmap_drop_node,static) = { [FEAT_BITMAP_DROP_NEXT_DROP] = "error-drop", }, }; -/* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON diff --git a/src/vnet/l2/l2.api b/src/vnet/l2/l2.api index b0ac23f705a..ccba9aa3df1 100644 --- a/src/vnet/l2/l2.api +++ b/src/vnet/l2/l2.api @@ -1,6 +1,7 @@ /* Hey Emacs use -*- mode: C -*- */ /* * Copyright (c) 2016 Cisco and/or its affiliates. + * Copyright (c) 2022 Nordix Foundation. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -14,7 +15,7 @@ * limitations under the License. */ -option version = "3.1.0"; +option version = "3.2.0"; import "vnet/ip/ip_types.api"; import "vnet/ethernet/ethernet_types.api"; @@ -304,7 +305,7 @@ autoreply define bridge_domain_set_learn_limit u32 learn_limit; }; -/** \brief L2 bridge domain add or delete request +/** \brief L2 bridge domain add or delete request - will be deprecated @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param bd_id - the bridge domain to create @@ -319,6 +320,7 @@ autoreply define bridge_domain_set_learn_limit */ autoreply define bridge_domain_add_del { + option deprecated; u32 client_index; u32 context; u32 bd_id; @@ -333,6 +335,49 @@ autoreply define bridge_domain_add_del bool is_add [default=true]; }; +/** \brief L2 bridge domain add delete request version 2 + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param bd_id - if the id == ~0 creates a bridge domain with an unused id + if the id != ~0 the id of the bridge domain to create/delete + @param flood - enable/disable bcast/mcast flooding in the bd + @param uu_flood - enable/disable unknown unicast flood in the bd + @param forward - enable/disable forwarding on all interfaces in the bd + @param learn - enable/disable learning on all interfaces in the bd + @param arp_term - enable/disable arp termination in the bd + @param arp_ufwd - enable/disable arp unicast forwarding in the bd + @param mac_age - mac aging time in min, 0 for disabled + @param is_add - add or delete flag +*/ +define bridge_domain_add_del_v2 +{ + u32 client_index; + u32 context; + u32 bd_id; + bool flood; + bool uu_flood; + bool forward; + bool learn; + bool arp_term; + bool arp_ufwd; + u8 mac_age; + string bd_tag[64]; + bool is_add [default=true]; +}; + +/** \brief L2 bridge domain add delete version 2 response + @param context - sender context, to match reply w/ request + @param retval - return code for the set bridge flags request + @param resulting_id - the id for the new bridge domain +*/ +define bridge_domain_add_del_v2_reply +{ + u32 context; + i32 retval; + u32 bd_id; +}; + + /** \brief L2 bridge domain request operational state details @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request diff --git a/src/vnet/l2/l2_api.c b/src/vnet/l2/l2_api.c index 5a0432de43d..035542d298d 100644 --- a/src/vnet/l2/l2_api.c +++ b/src/vnet/l2/l2_api.c @@ -3,6 +3,7 @@ * l2_api.c - layer 2 forwarding api * * Copyright (c) 2016 Cisco and/or its affiliates. + * Copyright (c) 2022 Nordix Foundation. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -67,7 +68,6 @@ vl_api_l2_xconnect_dump_t_handler (vl_api_l2_xconnect_dump_t * mp) if (!reg) return; - /* *INDENT-OFF* */ vec_foreach_index (sw_if_index, l2im->configs) { config = vec_elt_at_index (l2im->configs, sw_if_index); @@ -75,7 +75,6 @@ vl_api_l2_xconnect_dump_t_handler (vl_api_l2_xconnect_dump_t * mp) send_l2_xconnect_details (reg, mp->context, sw_if_index, config->output_sw_if_index); } - /* *INDENT-ON* */ } static void @@ -413,12 +412,10 @@ vl_api_l2_flags_t_handler (vl_api_l2_flags_t * mp) BAD_SW_IF_INDEX_LABEL; - /* *INDENT-OFF* */ REPLY_MACRO2(VL_API_L2_FLAGS_REPLY, ({ rmp->resulting_feature_bitmap = ntohl(rbm); })); - /* *INDENT-ON* */ } static void @@ -511,6 +508,37 @@ vl_api_bridge_domain_add_del_t_handler (vl_api_bridge_domain_add_del_t * mp) } static void +vl_api_bridge_domain_add_del_v2_t_handler ( + vl_api_bridge_domain_add_del_v2_t *mp) +{ + vl_api_bridge_domain_add_del_v2_reply_t *rmp; + u32 bd_id = ntohl (mp->bd_id); + int rv = 0; + + if ((~0 == bd_id) && (mp->is_add)) + bd_id = bd_get_unused_id (); + + if ((~0 == bd_id) && (mp->is_add)) + rv = VNET_API_ERROR_EAGAIN; + else + { + l2_bridge_domain_add_del_args_t a = { .is_add = mp->is_add, + .flood = mp->flood, + .uu_flood = mp->uu_flood, + .forward = mp->forward, + .learn = mp->learn, + .arp_term = mp->arp_term, + .arp_ufwd = mp->arp_ufwd, + .mac_age = mp->mac_age, + .bd_id = bd_id, + .bd_tag = mp->bd_tag }; + rv = bd_add_del (&a); + } + REPLY_MACRO2 (VL_API_BRIDGE_DOMAIN_ADD_DEL_V2_REPLY, + ({ rmp->bd_id = htonl (bd_id); })); +} + +static void send_bridge_domain_details (l2input_main_t * l2im, vl_api_registration_t * reg, l2_bridge_domain_t * bd_config, @@ -651,12 +679,10 @@ vl_api_bridge_flags_t_handler (vl_api_bridge_flags_t * mp) bitmap = bd_set_flags (vm, bd_index, flags, mp->is_set); out: - /* *INDENT-OFF* */ REPLY_MACRO2(VL_API_BRIDGE_FLAGS_REPLY, ({ rmp->resulting_feature_bitmap = ntohl(bitmap); })); - /* *INDENT-ON* */ } static void @@ -918,7 +944,6 @@ vl_api_bd_ip_mac_dump_t_handler (vl_api_bd_ip_mac_dump_t * mp) u64 mac64; bd_id = bd_config->bd_id; - /* *INDENT-OFF* */ hash_foreach (ip4_addr.as_u32, mac64, bd_config->mac_by_ip4, ({ ip46_address_t ip = { @@ -940,7 +965,6 @@ vl_api_bd_ip_mac_dump_t_handler (vl_api_bd_ip_mac_dump_t * mp) send_bd_ip_mac_entry (am, reg, bd_id, &ip, IP46_TYPE_IP6, &mac, mp->context); })); - /* *INDENT-ON* */ } } } @@ -1094,12 +1118,10 @@ vl_api_bvi_create_t_handler (vl_api_bvi_create_t * mp) rv = l2_bvi_create (ntohl (mp->user_instance), &mac, &sw_if_index); - /* *INDENT-OFF* */ REPLY_MACRO2(VL_API_BVI_CREATE_REPLY, ({ rmp->sw_if_index = ntohl (sw_if_index); })); - /* *INDENT-ON* */ } static void @@ -1193,13 +1215,11 @@ l2_arp_term_process (vlib_main_t * vm, vlib_node_runtime_t * rt, return 0; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (l2_arp_term_process_node) = { .function = l2_arp_term_process, .type = VLIB_NODE_TYPE_PROCESS, .name = "l2-arp-term-publisher", }; -/* *INDENT-ON* */ static void vl_api_want_l2_arp_term_events_t_handler (vl_api_want_l2_arp_term_events_t * @@ -1280,14 +1300,15 @@ l2_api_hookup (vlib_main_t * vm) { api_main_t *am = vlibapi_get_main (); - /* Mark VL_API_BRIDGE_DOMAIN_DUMP as mp safe */ - am->is_mp_safe[VL_API_BRIDGE_DOMAIN_DUMP] = 1; - /* * Set up the (msg_name, crc, message-id) table */ REPLY_MSG_ID_BASE = setup_message_id_table (); + /* Mark VL_API_BRIDGE_DOMAIN_DUMP as mp safe */ + vl_api_set_msg_thread_safe ( + am, REPLY_MSG_ID_BASE + VL_API_BRIDGE_DOMAIN_DUMP, 1); + return 0; } diff --git a/src/vnet/l2/l2_arp_term.c b/src/vnet/l2/l2_arp_term.c index 17c8b1d84d0..eed9b7af7c3 100644 --- a/src/vnet/l2/l2_arp_term.c +++ b/src/vnet/l2/l2_arp_term.c @@ -25,6 +25,7 @@ #include <vnet/ip/ip6_packet.h> #include <vnet/ip/icmp6.h> #include <vnet/ip/ip6.h> +#include <vnet/ip/ip.api_enum.h> #include <vnet/ip/format.h> #include <vnet/ethernet/arp_packet.h> @@ -289,6 +290,9 @@ arp_term_l2bd (vlib_main_t * vm, ethertype0 = clib_net_to_host_u16 (*(u16 *) (l3h0 - 2)); arp0 = (ethernet_arp_header_t *) l3h0; + if (p0->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED) + goto next_l2_feature; + if (ethertype0 != ETHERNET_TYPE_ARP) goto check_ip6_nd; @@ -445,7 +449,6 @@ arp_term_l2bd (vlib_main_t * vm, return frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (arp_term_l2bd_node, static) = { .function = arp_term_l2bd, .name = "arp-term-l2bd", @@ -460,7 +463,6 @@ VLIB_REGISTER_NODE (arp_term_l2bd_node, static) = { .format_buffer = format_ethernet_arp_header, .format_trace = format_arp_term_input_trace, }; -/* *INDENT-ON* */ clib_error_t * arp_term_init (vlib_main_t * vm) diff --git a/src/vnet/l2/l2_bd.c b/src/vnet/l2/l2_bd.c index 7e6ea60b440..c7392c03b58 100644 --- a/src/vnet/l2/l2_bd.c +++ b/src/vnet/l2/l2_bd.c @@ -102,12 +102,10 @@ bd_free_ip_mac_tables (l2_bridge_domain_t * bd) ip6_address_t *ip6_addr_key; hash_free (bd->mac_by_ip4); - /* *INDENT-OFF* */ hash_foreach_mem (ip6_addr_key, mac_addr, bd->mac_by_ip6, ({ clib_mem_free (ip6_addr_key); /* free memory used for ip6 addr key */ })); - /* *INDENT-ON* */ hash_free (bd->mac_by_ip6); } @@ -454,13 +452,11 @@ done: * Example of how to disable learning (where 200 is the bridge-domain-id): * @cliexcmd{set bridge-domain learn 200 disable} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (bd_learn_cli, static) = { .path = "set bridge-domain learn", .short_help = "set bridge-domain learn <bridge-domain-id> [disable]", .function = bd_learn, }; -/* *INDENT-ON* */ static clib_error_t * bd_default_learn_limit (vlib_main_t *vm, unformat_input_t *input, @@ -547,13 +543,11 @@ done: * Example of how to disable forwarding (where 200 is the bridge-domain-id): * @cliexcmd{set bridge-domain forward 200 disable} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (bd_fwd_cli, static) = { .path = "set bridge-domain forward", .short_help = "set bridge-domain forward <bridge-domain-id> [disable]", .function = bd_fwd, }; -/* *INDENT-ON* */ /** Set bridge-domain flood enable/disable. @@ -612,13 +606,11 @@ done: * Example of how to disable flooding (where 200 is the bridge-domain-id): * @cliexcmd{set bridge-domain flood 200 disable} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (bd_flood_cli, static) = { .path = "set bridge-domain flood", .short_help = "set bridge-domain flood <bridge-domain-id> [disable]", .function = bd_flood, }; -/* *INDENT-ON* */ /** Set bridge-domain unknown-unicast flood enable/disable. @@ -677,13 +669,11 @@ done: * Example of how to disable unknown-unicast flooding (where 200 is the bridge-domain-id): * @cliexcmd{set bridge-domain uu-flood 200 disable} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (bd_uu_flood_cli, static) = { .path = "set bridge-domain uu-flood", .short_help = "set bridge-domain uu-flood <bridge-domain-id> [disable]", .function = bd_uu_flood, }; -/* *INDENT-ON* */ /** Set bridge-domain arp-unicast forward enable/disable. @@ -742,13 +732,11 @@ done: * Example of how to disable arp-unicast forwarding (where 200 is the bridge-domain-id): * @cliexcmd{set bridge-domain arp-ufwd 200 disable} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (bd_arp_ufwd_cli, static) = { .path = "set bridge-domain arp-ufwd", .short_help = "set bridge-domain arp-ufwd <bridge-domain-id> [disable]", .function = bd_arp_ufwd, }; -/* *INDENT-ON* */ /** Set bridge-domain arp term enable/disable. @@ -854,13 +842,11 @@ done: * Example of how to disable mac aging (where 200 is the bridge-domain-id): * @cliexcmd{set bridge-domain flood 200 0} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (bd_mac_age_cli, static) = { .path = "set bridge-domain mac-age", .short_help = "set bridge-domain mac-age <bridge-domain-id> <mins>", .function = bd_mac_age, }; -/* *INDENT-ON* */ static clib_error_t * bd_learn_limit (vlib_main_t *vm, unformat_input_t *input, @@ -921,13 +907,11 @@ VLIB_CLI_COMMAND (bd_learn_limit_cli, static) = { * Example of how to disable ARP termination (where 200 is the bridge-domain-id): * @cliexcmd{set bridge-domain arp term 200 disable} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (bd_arp_term_cli, static) = { .path = "set bridge-domain arp term", .short_help = "set bridge-domain arp term <bridge-domain-id> [disable]", .function = bd_arp_term, }; -/* *INDENT-ON* */ /** @@ -1119,13 +1103,11 @@ done: * Example of how to delete an ARP entry (where 200 is the bridge-domain-id): * @cliexcmd{set bridge-domain arp entry 200 192.168.72.45 52:54:00:3b:83:1a del} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (bd_arp_entry_cli, static) = { .path = "set bridge-domain arp entry", .short_help = "set bridge-domain arp entry <bridge-domain-id> [<ip-addr> <mac-addr> [del] | del-all]", .function = bd_arp_entry, }; -/* *INDENT-ON* */ static u8 * format_uu_cfg (u8 * s, va_list * args) @@ -1289,7 +1271,6 @@ bd_show (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) vlib_cli_output (vm, "\n IP4/IP6 to MAC table for ARP Termination"); - /* *INDENT-OFF* */ hash_foreach (ip4_addr, mac_addr, bd_config->mac_by_ip4, ({ vlib_cli_output (vm, "%=40U => %=20U", @@ -1303,7 +1284,6 @@ bd_show (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) format_ip6_address, ip6_addr, format_ethernet_address, &mac_addr); })); - /* *INDENT-ON* */ } if ((detail || bd_tag) && (bd_config->bd_tag)) @@ -1349,13 +1329,11 @@ done: * @cliexend * @endparblock ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (bd_show_cli, static) = { .path = "show bridge-domain", .short_help = "show bridge-domain [bridge-domain-id [detail|int|arp|bd-tag]]", .function = bd_show, }; -/* *INDENT-ON* */ int bd_add_del (l2_bridge_domain_add_del_args_t * a) @@ -1493,8 +1471,15 @@ bd_add_del_command_fn (vlib_main_t * vm, unformat_input_t * input, if (bd_id == ~0) { - error = clib_error_return (0, "bridge-domain-id not specified"); - goto done; + if (is_add) + { + bd_id = bd_get_unused_id (); + } + else + { + error = clib_error_return (0, "bridge-domain-id not specified"); + goto done; + } } if (bd_id == 0) @@ -1587,7 +1572,6 @@ done: * @endparblock ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (bd_create_cli, static) = { .path = "create bridge-domain", .short_help = "create bridge-domain <bridge-domain-id>" @@ -1595,9 +1579,38 @@ VLIB_CLI_COMMAND (bd_create_cli, static) = { " [arp-ufwd <0|1>] [mac-age <nn>] [bd-tag <tag>] [del]", .function = bd_add_del_command_fn, }; -/* *INDENT-ON* */ +/* + * Returns an unused bridge domain id, and ~0 if it can't find one. + */ +u32 +bd_get_unused_id (void) +{ + bd_main_t *bdm = &bd_main; + int i, j; + static u32 seed = 0; + /* limit to 1M tries */ + for (j = 0; j < 1 << 10; j++) + { + seed = random_u32 (&seed); + for (i = 0; i < 1 << 10; i++) + { + /* + * iterate seed+0, seed+1, seed-1, seed+2, seed-2, ... to generate id + */ + seed += (2 * (i % 2) - 1) * i; + /* bd_id must be (1 <= bd_id <= L2_BD_ID_MAX) */ + seed &= L2_BD_ID_MAX; + if (seed == 0) + continue; + if (bd_find_index (bdm, seed) == ~0) + return seed; + } + } + + return ~0; +} /* * fd.io coding-style-patch-verification: ON diff --git a/src/vnet/l2/l2_bd.h b/src/vnet/l2/l2_bd.h index 0d77292519d..082d210b972 100644 --- a/src/vnet/l2/l2_bd.h +++ b/src/vnet/l2/l2_bd.h @@ -2,6 +2,7 @@ * l2_bd.h : layer 2 bridge domain * * Copyright (c) 2013 Cisco and/or its affiliates. + * Copyright (c) 2022 Nordix Foundation. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -166,7 +167,7 @@ u32 bd_set_flags (vlib_main_t * vm, u32 bd_index, bd_flags_t flags, void bd_set_mac_age (vlib_main_t * vm, u32 bd_index, u8 age); void bd_set_learn_limit (vlib_main_t *vm, u32 bd_index, u32 learn_limit); int bd_add_del (l2_bridge_domain_add_del_args_t * args); - +u32 bd_get_unused_id (void); /** * \brief Get a bridge domain. * diff --git a/src/vnet/l2/l2_bvi.c b/src/vnet/l2/l2_bvi.c index e5623682657..e39c4aae39d 100644 --- a/src/vnet/l2/l2_bvi.c +++ b/src/vnet/l2/l2_bvi.c @@ -58,14 +58,12 @@ bvi_mac_change (vnet_hw_interface_t * hi, return (NULL); } -/* *INDENT-OFF* */ VNET_DEVICE_CLASS (bvi_device_class) = { .name = "BVI", .format_device_name = format_bvi_name, .admin_up_down_function = bvi_admin_up_down, .mac_addr_change_function = bvi_mac_change, }; -/* *INDENT-ON* */ /* * Maintain a bitmap of allocated bvi instance numbers. @@ -138,13 +136,11 @@ l2_bvi_create (u32 user_instance, { vnet_main_t *vnm = vnet_get_main (); vlib_main_t *vm = vlib_get_main (); + vnet_eth_interface_registration_t eir = {}; u32 instance, hw_if_index, slot; vnet_hw_interface_t *hw_if; - clib_error_t *error; mac_address_t mac; - int rv = 0; - ASSERT (sw_if_indexp); *sw_if_indexp = (u32) ~ 0; @@ -178,17 +174,10 @@ l2_bvi_create (u32 user_instance, mac_address_copy (&mac, mac_in); } - error = ethernet_register_interface (vnm, - bvi_device_class.index, - instance, mac.bytes, &hw_if_index, - /* flag change */ 0); - - if (error) - { - rv = VNET_API_ERROR_INVALID_REGISTRATION; - clib_error_report (error); - return rv; - } + eir.dev_class_index = bvi_device_class.index; + eir.dev_instance = instance; + eir.address = mac.bytes; + hw_if_index = vnet_eth_register_interface (vnm, &eir); hw_if = vnet_get_hw_interface (vnm, hw_if_index); @@ -282,13 +271,11 @@ l2_bvi_create_cli (vlib_main_t * vm, * Example of how to create a bvi interface: * @cliexcmd{bvi create} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (l2_bvi_create_command, static) = { .path = "bvi create", .short_help = "bvi create [mac <mac-addr>] [instance <instance>]", .function = l2_bvi_create_cli, }; -/* *INDENT-ON* */ static clib_error_t * l2_bvi_delete_cli (vlib_main_t * vm, @@ -333,13 +320,11 @@ l2_bvi_delete_cli (vlib_main_t * vm, * Example of how to create a bvi interface: * @cliexcmd{bvi delete bvi0} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (l2_bvi_delete_command, static) = { .path = "bvi delete", .short_help = "bvi delete <interface>", .function = l2_bvi_delete_cli, }; -/* *INDENT-ON* */ /* diff --git a/src/vnet/l2/l2_classify.h b/src/vnet/l2/l2_classify.h index 68a2bb98e64..3c86fb5ca86 100644 --- a/src/vnet/l2/l2_classify.h +++ b/src/vnet/l2/l2_classify.h @@ -39,7 +39,6 @@ typedef enum L2_INPUT_CLASSIFY_NEXT_ETHERNET_INPUT, L2_INPUT_CLASSIFY_NEXT_IP4_INPUT, L2_INPUT_CLASSIFY_NEXT_IP6_INPUT, - L2_INPUT_CLASSIFY_NEXT_LI, L2_INPUT_CLASSIFY_N_NEXT, } l2_input_classify_next_t; diff --git a/src/vnet/l2/l2_efp_filter.c b/src/vnet/l2/l2_efp_filter.c index ad325b83df2..47256ffa5d3 100644 --- a/src/vnet/l2/l2_efp_filter.c +++ b/src/vnet/l2/l2_efp_filter.c @@ -461,7 +461,6 @@ VLIB_NODE_FN (l2_efp_filter_node) (vlib_main_t * vm, } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (l2_efp_filter_node) = { .name = "l2-efp-filter", .vector_size = sizeof (u32), @@ -478,7 +477,6 @@ VLIB_REGISTER_NODE (l2_efp_filter_node) = { [L2_EFP_FILTER_NEXT_DROP] = "error-drop", }, }; -/* *INDENT-ON* */ #ifndef CLIB_MARCH_VARIANT clib_error_t * @@ -559,13 +557,11 @@ done: * Example of how to disable a Layer 2 efp-filter on a sub-interface: * @cliexcmd{set interface l2 efp-filter GigabitEthernet0/8/0.200 disable} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (int_l2_efp_filter_cli, static) = { .path = "set interface l2 efp-filter", .short_help = "set interface l2 efp-filter <interface> [disable]", .function = int_l2_efp_filter, }; -/* *INDENT-ON* */ #endif /* CLIB_MARCH_VARIANT */ diff --git a/src/vnet/l2/l2_fib.c b/src/vnet/l2/l2_fib.c index d1ee82273b1..3dcd1e7ae26 100644 --- a/src/vnet/l2/l2_fib.c +++ b/src/vnet/l2/l2_fib.c @@ -95,8 +95,7 @@ format_vnet_sw_if_index_name_with_NA (u8 * s, va_list * args) if (!swif) return format (s, "Stale"); - return format (s, "%U", format_vnet_sw_interface_name, vnm, - vnet_get_sw_interface_or_null (vnm, sw_if_index)); + return format (s, "%U", format_vnet_sw_if_index_name, vnm, sw_if_index); } typedef struct l2fib_dump_walk_ctx_t_ @@ -353,13 +352,11 @@ show_l2fib (vlib_main_t * vm, * 3 l2fib entries * @cliexend ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_l2fib_cli, static) = { .path = "show l2fib", .short_help = "show l2fib [all] | [bd_id <nn> | bd_index <nn>] [learn | add] | [raw]", .function = show_l2fib, }; -/* *INDENT-ON* */ void l2fib_table_init (void) @@ -416,13 +413,11 @@ clear_l2fib (vlib_main_t * vm, * no l2fib entries * @cliexend ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (clear_l2fib_cli, static) = { .path = "clear l2fib", .short_help = "clear l2fib", .function = clear_l2fib, }; -/* *INDENT-ON* */ static l2fib_seq_num_t l2fib_cur_seq_num (u32 bd_index, u32 sw_if_index) @@ -593,20 +588,18 @@ done: * 3 l2fib entries * @cliexend ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (l2fib_add_cli, static) = { .path = "l2fib add", .short_help = "l2fib add <mac> <bridge-domain-id> filter | <intf> [static | bvi]", .function = l2fib_add, }; -/* *INDENT-ON* */ static clib_error_t * l2fib_test_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { - u8 mac[6], save_mac[6]; + u8 mac[8], save_mac[6]; u32 bd_index = 0; u32 sw_if_index = 8; u32 is_add = 0; @@ -724,13 +717,11 @@ l2fib_test_command_fn (vlib_main_t * vm, * @cliexcmd{test l2fib del mac 52:54:00:53:00:00 count 4} * @endparblock ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (l2fib_test_command, static) = { .path = "test l2fib", .short_help = "test l2fib [add|del|check] mac <base-addr> count <nn>", .function = l2fib_test_command_fn, }; -/* *INDENT-ON* */ /** @@ -833,13 +824,11 @@ done: * Example of how to delete a MAC Address entry from the L2 FIB table of a bridge-domain (where 200 is the bridge-domain-id): * @cliexcmd{l2fib del 52:54:00:53:18:33 200} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (l2fib_del_cli, static) = { .path = "l2fib del", .short_help = "l2fib del <mac> <bridge-domain-id> []", .function = l2fib_del, }; -/* *INDENT-ON* */ static clib_error_t * l2fib_set_scan_delay (vlib_main_t *vm, unformat_input_t *input, @@ -977,13 +966,11 @@ l2fib_flush_mac_all (vlib_main_t * vm, * Example of how to flush MAC Address entries learned on an interface from the L2 FIB table: * @cliexcmd{l2fib flush-mac interface GigabitEthernet2/1/0} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (l2fib_flush_mac_all_cli, static) = { .path = "l2fib flush-mac all", .short_help = "l2fib flush-mac all", .function = l2fib_flush_mac_all, }; -/* *INDENT-ON* */ /*? * This command kick off ager to delete all existing MAC Address entries, @@ -993,13 +980,11 @@ VLIB_CLI_COMMAND (l2fib_flush_mac_all_cli, static) = { * Example of how to flush MAC Address entries learned on an interface from the L2 FIB table: * @cliexcmd{l2fib flush-mac interface GigabitEthernet2/1/0} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (l2fib_flush_mac_int_cli, static) = { .path = "l2fib flush-mac interface", .short_help = "l2fib flush-mac interface <if-name>", .function = l2fib_flush_mac_int, }; -/* *INDENT-ON* */ /** Flush bridge-domain MACs except static ones. @@ -1042,13 +1027,11 @@ done: * Example of how to flush MAC Address entries learned in a bridge domain from the L2 FIB table: * @cliexcmd{l2fib flush-mac bridge-domain 1000} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (l2fib_flush_mac_bd_cli, static) = { .path = "l2fib flush-mac bridge-domain", .short_help = "l2fib flush-mac bridge-domain <bd-id>", .function = l2fib_flush_mac_bd, }; -/* *INDENT-ON* */ clib_error_t * l2fib_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags) @@ -1149,7 +1132,7 @@ l2fib_scan (vlib_main_t * vm, f64 start_time, u8 event_only) { for (k = 0; k < BIHASH_KVP_PER_PAGE; k++) { - if (v->kvp[k].key == ~0ULL && v->kvp[k].value == ~0ULL) + if (BV (clib_bihash_is_free) (&v->kvp[k])) continue; l2fib_entry_key_t key = {.raw = v->kvp[k].key }; @@ -1366,13 +1349,11 @@ l2fib_mac_age_scanner_process (vlib_main_t * vm, vlib_node_runtime_t * rt, return 0; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (l2fib_mac_age_scanner_process_node) = { .function = l2fib_mac_age_scanner_process, .type = VLIB_NODE_TYPE_PROCESS, .name = "l2fib-mac-age-scanner-process", }; -/* *INDENT-ON* */ clib_error_t * l2fib_init (vlib_main_t * vm) diff --git a/src/vnet/l2/l2_fib.h b/src/vnet/l2/l2_fib.h index 7f7cd761e20..e24d427b4e2 100644 --- a/src/vnet/l2/l2_fib.h +++ b/src/vnet/l2/l2_fib.h @@ -240,29 +240,9 @@ l2fib_compute_hash_bucket (l2fib_entry_key_t * key) always_inline u64 l2fib_make_key (const u8 * mac_address, u16 bd_index) { - u64 temp; - - /* - * The mac address in memory is A:B:C:D:E:F - * The bd id in register is H:L - */ -#if CLIB_ARCH_IS_LITTLE_ENDIAN - /* - * Create the in-register key as F:E:D:C:B:A:H:L - * In memory the key is L:H:A:B:C:D:E:F - */ - temp = CLIB_MEM_OVERFLOW_LOAD (*, (u64 *) mac_address) << 16; - temp = (temp & ~0xffff) | (u64) (bd_index); -#else - /* - * Create the in-register key as H:L:A:B:C:D:E:F - * In memory the key is H:L:A:B:C:D:E:F - */ - temp = CLIB_MEM_OVERFLOW_LOAD (*, (u64 *) mac_address) >> 16; - temp = temp | (((u64) bd_index) << 48); -#endif - - return temp; + l2fib_entry_key_t key = { .fields.bd_index = bd_index }; + clib_memcpy_fast (&key.fields.mac, mac_address, sizeof (key.fields.mac)); + return key.raw; } diff --git a/src/vnet/l2/l2_flood.c b/src/vnet/l2/l2_flood.c index c0d7bf8dfab..f8cb3cb5687 100644 --- a/src/vnet/l2/l2_flood.c +++ b/src/vnet/l2/l2_flood.c @@ -362,7 +362,6 @@ VLIB_NODE_FN (l2flood_node) (vlib_main_t * vm, } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (l2flood_node) = { .name = "l2-flood", .vector_size = sizeof (u32), @@ -380,7 +379,6 @@ VLIB_REGISTER_NODE (l2flood_node) = { [L2FLOOD_NEXT_DROP] = "error-drop", }, }; -/* *INDENT-ON* */ #ifndef CLIB_MARCH_VARIANT clib_error_t * @@ -468,13 +466,11 @@ done: * Example of how to disable flooding: * @cliexcmd{set interface l2 flood GigabitEthernet0/8/0 disable} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (int_flood_cli, static) = { .path = "set interface l2 flood", .short_help = "set interface l2 flood <interface> [disable]", .function = int_flood, }; -/* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON diff --git a/src/vnet/l2/l2_fwd.c b/src/vnet/l2/l2_fwd.c index 3414f6c490e..503dfc27957 100644 --- a/src/vnet/l2/l2_fwd.c +++ b/src/vnet/l2/l2_fwd.c @@ -215,8 +215,7 @@ l2fwd_process (vlib_main_t * vm, * unless some other feature is inserted before uu_flood */ if (vnet_buffer (b0)->l2.feature_bitmap & - (L2INPUT_FEAT_UU_FLOOD | - L2INPUT_FEAT_UU_FWD | L2INPUT_FEAT_GBP_FWD)) + (L2INPUT_FEAT_UU_FLOOD | L2INPUT_FEAT_UU_FWD)) { *next0 = vnet_l2_feature_next (b0, msm->feat_next_node_index, L2INPUT_FEAT_FWD); @@ -289,7 +288,6 @@ l2fwd_node_inline (vlib_main_t * vm, vlib_node_runtime_t * node, #ifdef COUNTERS em->counters[node_counter_base_index + L2FWD_ERROR_L2FWD] += 4; #endif - /* *INDENT-OFF* */ l2fib_lookup_4 (msm->mac_table, &cached_key, &cached_result, h0->dst_address, h1->dst_address, h2->dst_address, h3->dst_address, @@ -305,7 +303,6 @@ l2fwd_node_inline (vlib_main_t * vm, vlib_node_runtime_t * node, &result1, &result2, &result3); - /* *INDENT-ON* */ l2fwd_process (vm, node, msm, em, b[0], sw_if_index0, &result0, next); l2fwd_process (vm, node, msm, em, b[1], sw_if_index1, &result1, next + 1); @@ -415,7 +412,6 @@ VLIB_NODE_FN (l2fwd_node) (vlib_main_t * vm, return l2fwd_node_inline (vm, node, frame, 0 /* do_trace */ ); } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (l2fwd_node) = { .name = "l2-fwd", .vector_size = sizeof (u32), @@ -433,7 +429,6 @@ VLIB_REGISTER_NODE (l2fwd_node) = { [L2FWD_NEXT_DROP] = "error-drop", }, }; -/* *INDENT-ON* */ #ifndef CLIB_MARCH_VARIANT clib_error_t * @@ -528,13 +523,11 @@ done: * Example of how to disable forwarding: * @cliexcmd{set interface l2 forward GigabitEthernet0/8/0 disable} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (int_fwd_cli, static) = { .path = "set interface l2 forward", .short_help = "set interface l2 forward <interface> [disable]", .function = int_fwd, }; -/* *INDENT-ON* */ #endif diff --git a/src/vnet/l2/l2_in_out_acl.c b/src/vnet/l2/l2_in_out_acl.c index f8293c1feee..2e2cb1e7f36 100644 --- a/src/vnet/l2/l2_in_out_acl.c +++ b/src/vnet/l2/l2_in_out_acl.c @@ -278,7 +278,7 @@ l2_in_out_acl_node_fn (vlib_main_t * vm, u32 table_index0; vnet_classify_table_t *t0; vnet_classify_entry_t *e0; - u64 hash0; + u32 hash0; u8 *h0; u8 error0; @@ -288,7 +288,7 @@ l2_in_out_acl_node_fn (vlib_main_t * vm, vlib_buffer_t *p1 = vlib_get_buffer (vm, from[3]); vnet_classify_table_t *tp1; u32 table_index1; - u64 phash1; + u32 phash1; table_index1 = vnet_buffer (p1)->l2_classify.table_index; @@ -464,7 +464,6 @@ VLIB_NODE_FN (l2_outacl_node) (vlib_main_t * vm, IN_OUT_ACL_OUTPUT_TABLE_GROUP); } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (l2_inacl_node) = { .name = "l2-input-acl", .vector_size = sizeof (u32), @@ -498,7 +497,6 @@ VLIB_REGISTER_NODE (l2_outacl_node) = { [ACL_NEXT_INDEX_DENY] = "error-drop", }, }; -/* *INDENT-ON* */ #ifndef CLIB_MARCH_VARIANT diff --git a/src/vnet/l2/l2_in_out_feat_arc.c b/src/vnet/l2/l2_in_out_feat_arc.c index b3b4a8cbb73..26fbd3eb776 100644 --- a/src/vnet/l2/l2_in_out_feat_arc.c +++ b/src/vnet/l2/l2_in_out_feat_arc.c @@ -257,7 +257,8 @@ l2_in_out_feat_arc_node_fn (vlib_main_t * vm, sw_if_index = sw_if_indices; n_left = frame->n_vectors; - CLIB_PREFETCH (next_node_indices, 2 * CLIB_CACHE_LINE_BYTES, LOAD); + CLIB_PREFETCH (next_node_indices, + sizeof (fam->feat_next_node_index[is_output]), LOAD); while (n_left > 3 * L2_FEAT_ARC_VEC_SIZE) { @@ -395,7 +396,6 @@ vnet_l2_in_out_feat_arc_enable_disable (u32 sw_if_index, int is_output, } #endif /* CLIB_MARCH_VARIANT */ -/* *INDENT-OFF* */ VNET_FEATURE_ARC_INIT (l2_in_ip4_arc, static) = { .arc_name = "l2-input-ip4", @@ -437,10 +437,8 @@ VNET_FEATURE_ARC_INIT (l2_in_nonip_arc, static) = }; -/* *INDENT-ON* */ -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (l2_in_feat_arc_node) = { .name = "l2-input-feat-arc", .vector_size = sizeof (u32), @@ -520,7 +518,6 @@ VNET_FEATURE_INIT (l2_out_nonip_arc_end, static) = .node_name = "l2-output-feat-arc-end", .runs_before = 0, /* not before any other features */ }; -/* *INDENT-ON* */ #ifndef CLIB_MARCH_VARIANT diff --git a/src/vnet/l2/l2_input.c b/src/vnet/l2/l2_input.c index de22cef600e..23bd5cc9958 100644 --- a/src/vnet/l2/l2_input.c +++ b/src/vnet/l2/l2_input.c @@ -646,13 +646,11 @@ done: * Example of how to remove an interface from a Layer2 bridge-domain: * @cliexcmd{set interface l3 GigabitEthernet0/a/0.200} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (int_l2_bridge_cli, static) = { .path = "set interface l2 bridge", .short_help = "set interface l2 bridge <interface> <bridge-domain-id> [bvi|uu-fwd] [shg]", .function = int_l2_bridge, }; -/* *INDENT-ON* */ /** * Set subinterface in xconnect mode with another interface. @@ -712,13 +710,11 @@ done: * @cliexcmd{set interface l3 GigabitEthernet0/8/0.300} * @cliexcmd{set interface l3 GigabitEthernet0/9/0.300} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (int_l2_xc_cli, static) = { .path = "set interface l2 xconnect", .short_help = "set interface l2 xconnect <interface> <peer interface>", .function = int_l2_xc, }; -/* *INDENT-ON* */ /** * Set subinterface in L3 mode. @@ -762,13 +758,11 @@ done: * Example of how to set the mode of an interface to Layer 3: * @cliexcmd{set interface l3 GigabitEthernet0/8/0.200} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (int_l3_cli, static) = { .path = "set interface l3", .short_help = "set interface l3 <interface>", .function = int_l3, }; -/* *INDENT-ON* */ /** * Show interface mode. @@ -809,10 +803,8 @@ show_int_mode (vlib_main_t * vm, { /* Gather interfaces. */ sis = vec_new (vnet_sw_interface_t, pool_elts (im->sw_interfaces)); - _vec_len (sis) = 0; - /* *INDENT-OFF* */ + vec_set_len (sis, 0); pool_foreach (si, im->sw_interfaces) { vec_add1 (sis, si[0]); } - /* *INDENT-ON* */ } vec_foreach (si, sis) @@ -878,13 +870,11 @@ done: * l2 bridge GigabitEthernet0/8/0.200 bd_id 200 shg 0 * @cliexend ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_l2_mode, static) = { .path = "show mode", .short_help = "show mode [<if-name1> <if-name2> ...]", .function = show_int_mode, }; -/* *INDENT-ON* */ #define foreach_l2_init_function \ _(feat_bitmap_drop_init) \ diff --git a/src/vnet/l2/l2_input.h b/src/vnet/l2/l2_input.h index ba4c4b6ed31..3de1537b45e 100644 --- a/src/vnet/l2/l2_input.h +++ b/src/vnet/l2/l2_input.h @@ -27,6 +27,7 @@ #include <vnet/ethernet/packet.h> #include <vnet/ip/ip4_inlines.h> #include <vnet/ip/ip6_inlines.h> +#include <vnet/mpls/mpls_lookup.h> /* l2 connection type */ typedef enum l2_input_flags_t_ @@ -136,17 +137,10 @@ l2input_bd_config (u32 bd_index) _(ARP_UFWD, "l2-uu-fwd") \ _(ARP_TERM, "arp-term-l2bd") \ _(UU_FLOOD, "l2-flood") \ - _(GBP_FWD, "gbp-fwd") \ _(UU_FWD, "l2-uu-fwd") \ _(FWD, "l2-fwd") \ _(RW, "l2-rw") \ _(LEARN, "l2-learn") \ - _(L2_EMULATION, "l2-emulation") \ - _(GBP_LEARN, "gbp-learn-l2") \ - _(GBP_LPM_ANON_CLASSIFY, "l2-gbp-lpm-anon-classify") \ - _(GBP_NULL_CLASSIFY, "gbp-null-classify") \ - _(GBP_SRC_CLASSIFY, "gbp-src-classify") \ - _(GBP_LPM_CLASSIFY, "l2-gbp-lpm-classify") \ _(VTR, "l2-input-vtr") \ _(L2_IP_QOS_RECORD, "l2-ip-qos-record") \ _(VPATH, "vpath-input-l2") \ @@ -334,7 +328,7 @@ vnet_update_l2_len (vlib_buffer_t *b) /* * Compute flow hash of an ethernet packet, use 5-tuple hash if L3 packet - * is ip4 or ip6. Otherwise hash on smac/dmac/etype. + * is ip4, ip6, or mpls. Otherwise hash on smac/dmac/etype. * The vlib buffer current pointer is expected to be at ethernet header * and vnet l2.l2_len is expected to be setup already. */ @@ -349,6 +343,9 @@ vnet_l2_compute_flow_hash (vlib_buffer_t * b) return ip4_compute_flow_hash ((ip4_header_t *) l3h, IP_FLOW_HASH_DEFAULT); else if (ethertype == ETHERNET_TYPE_IP6) return ip6_compute_flow_hash ((ip6_header_t *) l3h, IP_FLOW_HASH_DEFAULT); + else if (ethertype == ETHERNET_TYPE_MPLS) + return mpls_compute_flow_hash ((mpls_unicast_header_t *) l3h, + IP_FLOW_HASH_DEFAULT); else { u32 a, b, c; diff --git a/src/vnet/l2/l2_input_classify.c b/src/vnet/l2/l2_input_classify.c index 53d46399daf..cc031bd46a5 100644 --- a/src/vnet/l2/l2_input_classify.c +++ b/src/vnet/l2/l2_input_classify.c @@ -179,8 +179,7 @@ VLIB_NODE_FN (l2_input_classify_node) (vlib_main_t * vm, int type_index0, type_index1; vnet_classify_table_t *t0, *t1; u32 table_index0, table_index1; - u64 hash0, hash1; - + u32 hash0, hash1; /* prefetch next iteration */ { @@ -265,7 +264,7 @@ VLIB_NODE_FN (l2_input_classify_node) (vlib_main_t * vm, u32 type_index0; vnet_classify_table_t *t0; u32 table_index0; - u64 hash0; + u32 hash0; bi0 = from[0]; b0 = vlib_get_buffer (vm, bi0); @@ -316,14 +315,14 @@ VLIB_NODE_FN (l2_input_classify_node) (vlib_main_t * vm, u32 next0 = ~0; /* next l2 input feature, please... */ ethernet_header_t *h0; u32 table_index0; - u64 hash0; + u32 hash0; vnet_classify_table_t *t0; vnet_classify_entry_t *e0; if (PREDICT_TRUE (n_left_from > 2)) { vlib_buffer_t *p2 = vlib_get_buffer (vm, from[2]); - u64 phash2; + u32 phash2; u32 table_index2; vnet_classify_table_t *tp2; @@ -443,7 +442,6 @@ VLIB_NODE_FN (l2_input_classify_node) (vlib_main_t * vm, return frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (l2_input_classify_node) = { .name = "l2-input-classify", .vector_size = sizeof (u32), @@ -463,10 +461,8 @@ VLIB_REGISTER_NODE (l2_input_classify_node) = { [L2_INPUT_CLASSIFY_NEXT_ETHERNET_INPUT] = "ethernet-input-not-l2", [L2_INPUT_CLASSIFY_NEXT_IP4_INPUT] = "ip4-input", [L2_INPUT_CLASSIFY_NEXT_IP6_INPUT] = "ip6-input", - [L2_INPUT_CLASSIFY_NEXT_LI] = "li-hit", }, }; -/* *INDENT-ON* */ #ifndef CLIB_MARCH_VARIANT /** l2 input classsifier feature initialization. */ @@ -643,7 +639,6 @@ int_l2_input_classify_command_fn (vlib_main_t * vm, * @todo This is incomplete. This needs a detailed description and a * practical example. ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (int_l2_input_classify_cli, static) = { .path = "set interface l2 input classify", .short_help = @@ -651,7 +646,6 @@ VLIB_CLI_COMMAND (int_l2_input_classify_cli, static) = { " [ip6-table <n>] [other-table <n>]", .function = int_l2_input_classify_command_fn, }; -/* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON diff --git a/src/vnet/l2/l2_input_node.c b/src/vnet/l2/l2_input_node.c index 3638a8aa00d..76b94809eb3 100644 --- a/src/vnet/l2/l2_input_node.c +++ b/src/vnet/l2/l2_input_node.c @@ -141,9 +141,8 @@ classify_and_dispatch (l2input_main_t * msm, vlib_buffer_t * b0, u16 * next0) u8 protocol = ((ip6_header_t *) l3h0)->protocol; /* Disable bridge forwarding (flooding will execute instead if not xconnect) */ - feat_mask &= ~(L2INPUT_FEAT_FWD | - L2INPUT_FEAT_UU_FLOOD | - L2INPUT_FEAT_UU_FWD | L2INPUT_FEAT_GBP_FWD); + feat_mask &= + ~(L2INPUT_FEAT_FWD | L2INPUT_FEAT_UU_FLOOD | L2INPUT_FEAT_UU_FWD); if (ethertype != ETHERNET_TYPE_ARP) feat_mask &= ~(L2INPUT_FEAT_ARP_UFWD); @@ -252,11 +251,11 @@ l2input_node_inline (vlib_main_t * vm, /* Prefetch next iteration. */ { - /* Prefetch the buffer header and packet for the N+2 loop iteration */ - vlib_prefetch_buffer_header (b[4], LOAD); - vlib_prefetch_buffer_header (b[5], LOAD); - vlib_prefetch_buffer_header (b[6], LOAD); - vlib_prefetch_buffer_header (b[7], LOAD); + /* Prefetch the buffer header for the N+2 loop iteration */ + clib_prefetch_store (b[4]); + clib_prefetch_store (b[5]); + clib_prefetch_store (b[6]); + clib_prefetch_store (b[7]); clib_prefetch_store (b[4]->data); clib_prefetch_store (b[5]->data); @@ -366,7 +365,6 @@ VLIB_NODE_FN (l2input_node) (vlib_main_t * vm, return l2input_node_inline (vm, node, frame, 0 /* do_trace */ ); } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (l2input_node) = { .name = "l2-input", .vector_size = sizeof (u32), @@ -386,7 +384,6 @@ VLIB_REGISTER_NODE (l2input_node) = { [L2INPUT_NEXT_DROP] = "error-drop", }, }; -/* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON diff --git a/src/vnet/l2/l2_input_vtr.c b/src/vnet/l2/l2_input_vtr.c index 3c1235bfa32..ccf3efa2390 100644 --- a/src/vnet/l2/l2_input_vtr.c +++ b/src/vnet/l2/l2_input_vtr.c @@ -319,7 +319,6 @@ VLIB_NODE_FN (l2_invtr_node) (vlib_main_t * vm, } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (l2_invtr_node) = { .name = "l2-input-vtr", .vector_size = sizeof (u32), @@ -336,7 +335,6 @@ VLIB_REGISTER_NODE (l2_invtr_node) = { [L2_INVTR_NEXT_DROP] = "error-drop", }, }; -/* *INDENT-ON* */ #ifndef CLIB_MARCH_VARIANT clib_error_t * diff --git a/src/vnet/l2/l2_learn.c b/src/vnet/l2/l2_learn.c index 6d90cee62a7..24b5389e55a 100644 --- a/src/vnet/l2/l2_learn.c +++ b/src/vnet/l2/l2_learn.c @@ -439,7 +439,6 @@ VLIB_NODE_FN (l2learn_node) (vlib_main_t * vm, return l2learn_node_inline (vm, node, frame, 0 /* do_trace */ ); } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (l2learn_node) = { .name = "l2-learn", .vector_size = sizeof (u32), @@ -457,7 +456,6 @@ VLIB_REGISTER_NODE (l2learn_node) = { [L2LEARN_NEXT_L2FWD] = "l2-fwd", }, }; -/* *INDENT-ON* */ #ifndef CLIB_MARCH_VARIANT clib_error_t * @@ -540,13 +538,11 @@ done: * Example of how to disable learning: * @cliexcmd{set interface l2 learn GigabitEthernet0/8/0 disable} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (int_learn_cli, static) = { .path = "set interface l2 learn", .short_help = "set interface l2 learn <interface> [disable]", .function = int_learn, }; -/* *INDENT-ON* */ static clib_error_t * diff --git a/src/vnet/l2/l2_output.c b/src/vnet/l2/l2_output.c index ba40de316d1..7c70cf9f4c7 100644 --- a/src/vnet/l2/l2_output.c +++ b/src/vnet/l2/l2_output.c @@ -22,6 +22,7 @@ #include <vppinfra/error.h> #include <vppinfra/hash.h> +#include <vppinfra/vector/count_equal.h> #include <vnet/l2/feat_bitmap.h> #include <vnet/l2/l2_output.h> @@ -442,7 +443,6 @@ VLIB_NODE_FN (l2output_node) (vlib_main_t * vm, return frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (l2output_node) = { .name = "l2-output", .vector_size = sizeof (u32), @@ -460,7 +460,6 @@ VLIB_REGISTER_NODE (l2output_node) = { [L2OUTPUT_NEXT_BAD_INTF] = "l2-output-bad-intf", }, }; -/* *INDENT-ON* */ #define foreach_l2output_bad_intf_error \ @@ -548,7 +547,6 @@ VLIB_NODE_FN (l2output_bad_intf_node) (vlib_main_t * vm, return frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (l2output_bad_intf_node) = { .name = "l2-output-bad-intf", .vector_size = sizeof (u32), @@ -564,7 +562,6 @@ VLIB_REGISTER_NODE (l2output_bad_intf_node) = { [0] = "error-drop", }, }; -/* *INDENT-ON* */ static clib_error_t * l2output_init (vlib_main_t * vm) diff --git a/src/vnet/l2/l2_output.h b/src/vnet/l2/l2_output.h index 1cc1e738841..201f5e195a4 100644 --- a/src/vnet/l2/l2_output.h +++ b/src/vnet/l2/l2_output.h @@ -81,9 +81,6 @@ extern vlib_node_registration_t l2output_node; #define foreach_l2output_feat \ _(OUTPUT, "interface-output") \ _(SPAN, "span-l2-output") \ - _(GBP_POLICY_LPM, "gbp-policy-lpm") \ - _(GBP_POLICY_PORT, "gbp-policy-port") \ - _(GBP_POLICY_MAC, "gbp-policy-mac") \ _(CFM, "feature-bitmap-drop") \ _(QOS, "feature-bitmap-drop") \ _(ACL, "l2-output-acl") \ diff --git a/src/vnet/l2/l2_output_classify.c b/src/vnet/l2/l2_output_classify.c index 96d0b14753a..33a7c927386 100644 --- a/src/vnet/l2/l2_output_classify.c +++ b/src/vnet/l2/l2_output_classify.c @@ -172,8 +172,7 @@ VLIB_NODE_FN (l2_output_classify_node) (vlib_main_t * vm, int type_index0, type_index1; vnet_classify_table_t *t0, *t1; u32 table_index0, table_index1; - u64 hash0, hash1; - + u32 hash0, hash1; /* prefetch next iteration */ { @@ -257,7 +256,7 @@ VLIB_NODE_FN (l2_output_classify_node) (vlib_main_t * vm, u32 type_index0; vnet_classify_table_t *t0; u32 table_index0; - u64 hash0; + u32 hash0; bi0 = from[0]; b0 = vlib_get_buffer (vm, bi0); @@ -308,14 +307,14 @@ VLIB_NODE_FN (l2_output_classify_node) (vlib_main_t * vm, u32 next0 = ~0; ethernet_header_t *h0; u32 table_index0; - u64 hash0; + u32 hash0; vnet_classify_table_t *t0; vnet_classify_entry_t *e0; if (PREDICT_TRUE (n_left_from > 2)) { vlib_buffer_t *p2 = vlib_get_buffer (vm, from[2]); - u64 phash2; + u32 phash2; u32 table_index2; vnet_classify_table_t *tp2; @@ -436,7 +435,6 @@ VLIB_NODE_FN (l2_output_classify_node) (vlib_main_t * vm, return frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (l2_output_classify_node) = { .name = "l2-output-classify", .vector_size = sizeof (u32), @@ -455,7 +453,6 @@ VLIB_REGISTER_NODE (l2_output_classify_node) = { [L2_OUTPUT_CLASSIFY_NEXT_DROP] = "error-drop", }, }; -/* *INDENT-ON* */ #ifndef CLIB_MARCH_VARIANT /** l2 output classsifier feature initialization. */ @@ -635,7 +632,6 @@ int_l2_output_classify_command_fn (vlib_main_t * vm, * @todo This is incomplete. This needs a detailed description and a * practical example. ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (int_l2_output_classify_cli, static) = { .path = "set interface l2 output classify", .short_help = @@ -643,7 +639,6 @@ VLIB_CLI_COMMAND (int_l2_output_classify_cli, static) = { " [ip6-table <n>] [other-table <n>]", .function = int_l2_output_classify_command_fn, }; -/* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON diff --git a/src/vnet/l2/l2_patch.c b/src/vnet/l2/l2_patch.c index 6de4e50a298..f85938ed799 100644 --- a/src/vnet/l2/l2_patch.c +++ b/src/vnet/l2/l2_patch.c @@ -206,7 +206,6 @@ VLIB_NODE_FN (l2_patch_node) (vlib_main_t * vm, return frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (l2_patch_node) = { .name = "l2-patch", .vector_size = sizeof (u32), @@ -223,7 +222,6 @@ VLIB_REGISTER_NODE (l2_patch_node) = { [L2_PATCH_NEXT_DROP] = "error-drop", }, }; -/* *INDENT-ON* */ extern int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index, int is_add); @@ -270,6 +268,8 @@ vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index, int is_add) vnet_feature_enable_disable ("device-input", "l2-patch", rxhi->sw_if_index, 1, 0, 0); + vnet_feature_enable_disable ("port-rx-eth", "l2-patch", + rxhi->sw_if_index, 1, 0, 0); } else { @@ -278,6 +278,8 @@ vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index, int is_add) vnet_feature_enable_disable ("device-input", "l2-patch", rxhi->sw_if_index, 0, 0, 0); + vnet_feature_enable_disable ("port-rx-eth", "l2-patch", + rxhi->sw_if_index, 0, 0, 0); if (vec_len (l2pm->tx_next_by_rx_sw_if_index) > rx_sw_if_index) { l2pm->tx_next_by_rx_sw_if_index[rx_sw_if_index] = ~0; @@ -369,13 +371,11 @@ done: * @todo This is incomplete. This needs a detailed description and a * practical example. ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (test_patch_command, static) = { .path = "test l2patch", .short_help = "test l2patch rx <intfc> tx <intfc> [del]", .function = test_patch_command_fn, }; -/* *INDENT-ON* */ /** Display the contents of the l2patch table. */ static clib_error_t * @@ -421,13 +421,11 @@ show_l2patch (vlib_main_t * vm, * @todo This is incomplete. This needs a detailed description and a * practical example. ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_l2patch_cli, static) = { .path = "show l2patch", .short_help = "Show l2 interface cross-connect entries", .function = show_l2patch, }; -/* *INDENT-ON* */ static clib_error_t * l2_patch_init (vlib_main_t * vm) diff --git a/src/vnet/l2/l2_rw.c b/src/vnet/l2/l2_rw.c index b6de2faffc5..c0e8ec489fc 100644 --- a/src/vnet/l2/l2_rw.c +++ b/src/vnet/l2/l2_rw.c @@ -109,6 +109,7 @@ l2_rw_rewrite (l2_rw_entry_t * rwe, u8 * h) /* FALLTHROUGH */ case 1: d[0] = (d[0] & ~rwe->mask[0]) | rwe->value[0]; + rwe->hit_count++; break; default: abort (); @@ -332,6 +333,7 @@ l2_rw_mod_entry (u32 * index, return 0; } + e->hit_count = 0; e->skip_n_vectors = skip / sizeof (u32x4); skip -= e->skip_n_vectors * sizeof (u32x4); e->rewrite_n_vectors = (skip + len - 1) / sizeof (u32x4) + 1; @@ -398,17 +400,19 @@ l2_rw_entry_cli_fn (vlib_main_t * vm, * the provisioned mask and value, modifies the packet header. * * @cliexpar - * @todo This is incomplete. This needs a detailed description and a - * practical example. + * Example of how to add an l2 rewrite entry to change the destination mac of + * the packet to 00:8a:00:0d:0e:02 (where parameter mask is Ethernet header's +mask, + * parameter value is Ethernet header's value): + * @cliexcmd{l2 rewrite entry mask ffffffffffff00000000000000000000 value +008a000d0e0200000000000000000000} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (l2_rw_entry_cli, static) = { .path = "l2 rewrite entry", .short_help = "l2 rewrite entry [index <index>] [mask <hex-mask>] [value <hex-value>] [skip <n_bytes>] [del]", .function = l2_rw_entry_cli_fn, }; -/* *INDENT-ON* */ #ifndef CLIB_MARCH_VARIANT int @@ -468,21 +472,36 @@ l2_rw_interface_cli_fn (vlib_main_t * vm, } /*? - * Layer 2-Rewrite node uses classify tables to match packets. Then, using - * the provisioned mask and value, modifies the packet header. + * Apply the rule to the interface. The following example shows how to use +classify + * entry and Layer 2-Rewrite entry to modify the packet ethernet header on the + * interface. * * @cliexpar - * @todo This is incomplete. This needs a detailed description and a - * practical example. + * Example use the classify to filter packets that do not need to be modified +(where + * 192.168.68.34 is the destination ip of the data packet, 8080 is the +destination port + * of the packet): + * @cliexcmd{classify table mask l3 ip4 dst l4 dst_port} + * @cliexcmd{classify session acl-hit-next permit table-index 0 match l3 ip4 +dst 192.168.68.34 l4 dst_port 8080} + * + * @cliexpar + * Example apply classify and l2 rewrite rules to the interface (where +YusurK2Eth6/0/1/3 + * is interface, \"table 0\" means Table Id is 0, \"miss 0\" means the packet +that matches + * the classify. miss will be modified according to the l2 rewrite entry with +index 0): + * @cliexcmd{set interface l2 rewrite YusurK2Eth6/0/1/3 table 0 miss-index 0} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (l2_rw_interface_cli, static) = { .path = "set interface l2 rewrite", .short_help = "set interface l2 rewrite <interface> [table <table index>] [miss-index <entry-index>]", .function = l2_rw_interface_cli_fn, }; -/* *INDENT-ON* */ static clib_error_t * l2_rw_show_interfaces_cli_fn (vlib_main_t * vm, @@ -494,30 +513,27 @@ l2_rw_show_interfaces_cli_fn (vlib_main_t * vm, vlib_cli_output (vm, "No interface is currently using l2 rewrite\n"); uword i; - /* *INDENT-OFF* */ clib_bitmap_foreach (i, rw->configs_bitmap) { vlib_cli_output (vm, "sw_if_index:%d %U\n", i, format_l2_rw_config, &rw->configs[i]); } - /* *INDENT-ON* */ return 0; } /*? - * Layer 2-Rewrite node uses classify tables to match packets. Then, using - * the provisioned mask and value, modifies the packet header. + * This command displays the l2 rewrite entries of the interfaces. * * @cliexpar - * @todo This is incomplete. This needs a detailed description and a - * practical example. + * Example of how to display the l2 rewrite rules on the interface: + * @cliexstart{show l2 rewrite interfaces} + * sw_if_index:4 table-index:0 miss-index:0 + * @cliexend ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (l2_rw_show_interfaces_cli, static) = { .path = "show l2 rewrite interfaces", .short_help = "show l2 rewrite interfaces", .function = l2_rw_show_interfaces_cli_fn, }; -/* *INDENT-ON* */ static clib_error_t * l2_rw_show_entries_cli_fn (vlib_main_t * vm, @@ -528,30 +544,29 @@ l2_rw_show_entries_cli_fn (vlib_main_t * vm, if (pool_elts (rw->entries) == 0) vlib_cli_output (vm, "No entries\n"); - /* *INDENT-OFF* */ pool_foreach (e, rw->entries) { vlib_cli_output (vm, "%U\n", format_l2_rw_entry, e); } - /* *INDENT-ON* */ return 0; } /*? - * Layer 2-Rewrite node uses classify tables to match packets. Then, using - * the provisioned mask and value, modifies the packet header. + * This command displays all l2 rewrite entries. * * @cliexpar - * @todo This is incomplete. This needs a detailed description and a - * practical example. + * Example of how to display all l2 rewrite entries: + * @cliexstart{show l2 rewrite entries} + * 0 - mask:ffffffffffff00000000000000000000 +value:aabbccddeeff00000000000000000000 + * hits:0 skip_bytes:0 + * @cliexend ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (l2_rw_show_entries_cli, static) = { .path = "show l2 rewrite entries", .short_help = "show l2 rewrite entries", .function = l2_rw_show_entries_cli_fn, }; -/* *INDENT-ON* */ static int l2_rw_enable_disable (u32 bridge_domain, u8 disable) @@ -587,21 +602,22 @@ l2_rw_set_cli_fn (vlib_main_t * vm, } /*? - * Layer 2-Rewrite node uses classify tables to match packets. Then, using - * the provisioned mask and value, modfies the packet header. + * Layer 2 rewrite can be enabled and disabled on each interface and on each +bridge-domain. + * Use this command to manage l2 rewrite on bridge-domain. * * @cliexpar - * @todo This is incomplete. This needs a detailed description and a - * practical example. + * Example of how to enable rewrite (where 100 is the bridge-domain-id): + * @cliexcmd{set bridge-domain rewrite 100} + * Example of how to disable rewrite (where 100 is the bridge-domain-id): + * @cliexcmd{set bridge-domain rewrite 100 disable} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (l2_rw_set_cli, static) = { .path = "set bridge-domain rewrite", .short_help = "set bridge-domain rewrite <bridge-domain> [disable]", .function = l2_rw_set_cli_fn, }; -/* *INDENT-ON* */ static clib_error_t * l2_rw_init (vlib_main_t * vm) @@ -643,7 +659,6 @@ static char *l2_rw_error_strings[] = { #undef _ }; -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (l2_rw_node) = { .name = "l2-rw", .vector_size = sizeof (u32), @@ -655,7 +670,6 @@ VLIB_REGISTER_NODE (l2_rw_node) = { .n_next_nodes = L2_RW_N_NEXT, .next_nodes = { [L2_RW_NEXT_DROP] = "error-drop"}, }; -/* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON diff --git a/src/vnet/l2/l2_rw.h b/src/vnet/l2/l2_rw.h index f9b10333f43..6d12a21fe55 100644 --- a/src/vnet/l2/l2_rw.h +++ b/src/vnet/l2/l2_rw.h @@ -27,7 +27,6 @@ #include <vnet/l2/l2_input.h> -/* *INDENT-OFF* */ typedef CLIB_PACKED(struct _l2_rw_entry { u16 skip_n_vectors; u16 rewrite_n_vectors; @@ -35,15 +34,12 @@ typedef CLIB_PACKED(struct _l2_rw_entry { u32x4 *mask; u32x4 *value; }) l2_rw_entry_t; -/* *INDENT-ON* */ /* l2_rw configuration for one interface */ -/* *INDENT-OFF* */ typedef CLIB_PACKED(struct _l2_rw_config { u32 table_index; /* Which classify table to use */ u32 miss_index; /* Rewrite entry to use if table does not match */ }) l2_rw_config_t; -/* *INDENT-ON* */ typedef struct { diff --git a/src/vnet/l2/l2_test.c b/src/vnet/l2/l2_test.c new file mode 100644 index 00000000000..b78e388a9f1 --- /dev/null +++ b/src/vnet/l2/l2_test.c @@ -0,0 +1,1435 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright(c) 2021 Cisco Systems, Inc. + * Copyright(c) 2022 Nordix Foundation. + */ + +#include <vat/vat.h> +#include <vlibapi/api.h> +#include <vlibmemory/api.h> +#include <vppinfra/error.h> +#include <vpp/api/types.h> +#include <inttypes.h> + +#include <vnet/l2/l2_classify.h> +#include <vnet/l2/l2_vtr.h> +#include <vnet/ip/ip_types_api.h> + +#define __plugin_msg_base l2_test_main.msg_id_base +#include <vlibapi/vat_helper_macros.h> + +#include <vlibmemory/vlib.api_enum.h> +#include <vlibmemory/vlib.api_types.h> + +/* Declare message IDs */ +#include <vnet/format_fns.h> +#include <vnet/l2/l2.api_enum.h> +#include <vnet/l2/l2.api_types.h> + +#define vl_endianfun /* define message structures */ +#include <vnet/l2/l2.api.h> +#undef vl_endianfun + +#define vl_calcsizefun +#include <vnet/l2/l2.api.h> +#undef vl_calcsizefun + +typedef struct +{ + /* API message ID base */ + u16 msg_id_base; + u32 ping_id; + vat_main_t *vat_main; +} l2_test_main_t; + +static l2_test_main_t l2_test_main; + +static void +vl_api_l2_fib_table_details_t_handler (vl_api_l2_fib_table_details_t *mp) +{ + vat_main_t *vam = l2_test_main.vat_main; + + fformat ( + vam->ofp, "%3" PRIu32 " %U %3" PRIu32 " %d %d %d", + ntohl (mp->bd_id), format_ethernet_address, mp->mac, + ntohl (mp->sw_if_index), mp->static_mac, mp->filter_mac, mp->bvi_mac); +} + +static int +api_l2_fib_table_dump (vat_main_t *vam) +{ + unformat_input_t *i = vam->input; + vl_api_l2_fib_table_dump_t *mp; + vl_api_control_ping_t *mp_ping; + u32 bd_id; + u8 bd_id_set = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "bd_id %d", &bd_id)) + bd_id_set = 1; + else + break; + } + + if (bd_id_set == 0) + { + errmsg ("missing bridge domain"); + return -99; + } + + fformat (vam->ofp, "BD-ID Mac Address sw-ndx Static Filter BVI"); + + /* Get list of l2 fib entries */ + M (L2_FIB_TABLE_DUMP, mp); + + mp->bd_id = ntohl (bd_id); + S (mp); + + /* Use a control ping for synchronization */ + PING (&l2_test_main, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static void +vl_api_l2_xconnect_details_t_handler (vl_api_l2_xconnect_details_t *mp) +{ + vat_main_t *vam = l2_test_main.vat_main; + fformat (vam->ofp, "%15d%15d", ntohl (mp->rx_sw_if_index), + ntohl (mp->tx_sw_if_index)); +} + +static int +api_l2_xconnect_dump (vat_main_t *vam) +{ + vl_api_l2_xconnect_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + if (!vam->json_output) + { + print (vam->ofp, "%15s%15s", "rx_sw_if_index", "tx_sw_if_index"); + } + + M (L2_XCONNECT_DUMP, mp); + + S (mp); + + /* Use a control ping for synchronization */ + PING (&l2_test_main, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static int +api_want_l2_arp_term_events (vat_main_t *vam) +{ + return -1; +} + +static int +api_want_l2_macs_events (vat_main_t *vam) +{ + unformat_input_t *line_input = vam->input; + vl_api_want_l2_macs_events_t *mp; + u8 enable_disable = 1; + u32 scan_delay = 0; + u32 max_macs_in_event = 0; + u32 learn_limit = 0; + int ret; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "learn-limit %d", &learn_limit)) + ; + else if (unformat (line_input, "scan-delay %d", &scan_delay)) + ; + else if (unformat (line_input, "max-entries %d", &max_macs_in_event)) + ; + else if (unformat (line_input, "disable")) + enable_disable = 0; + else + break; + } + + M (WANT_L2_MACS_EVENTS, mp); + mp->enable_disable = enable_disable; + mp->pid = htonl (getpid ()); + mp->learn_limit = htonl (learn_limit); + mp->scan_delay = (u8) scan_delay; + mp->max_macs_in_event = (u8) (max_macs_in_event / 10); + S (mp); + W (ret); + return ret; +} + +static int +api_l2fib_flush_all (vat_main_t *vam) +{ + return -1; +} + +static void +increment_mac_address (u8 *mac) +{ + u64 tmp = *((u64 *) mac); + tmp = clib_net_to_host_u64 (tmp); + tmp += 1 << 16; /* skip unused (least significant) octets */ + tmp = clib_host_to_net_u64 (tmp); + + clib_memcpy (mac, &tmp, 6); +} + +static int +api_l2fib_add_del (vat_main_t *vam) +{ + vnet_main_t *vnm = vnet_get_main (); + unformat_input_t *i = vam->input; + vl_api_l2fib_add_del_t *mp; + f64 timeout; + u8 mac[8] = { 0 }; + u8 mac_set = 0; + u32 bd_id; + u8 bd_id_set = 0; + u32 sw_if_index = 0; + u8 sw_if_index_set = 0; + u8 is_add = 1; + u8 static_mac = 0; + u8 filter_mac = 0; + u8 bvi_mac = 0; + int count = 1; + f64 before = 0; + int j; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "mac %U", unformat_ethernet_address, mac)) + mac_set = 1; + else if (unformat (i, "bd_id %d", &bd_id)) + bd_id_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if")) + { + if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", unformat_vnet_sw_interface, vnm, + &sw_if_index)) + sw_if_index_set = 1; + } + else + break; + } + else if (unformat (i, "static")) + static_mac = 1; + else if (unformat (i, "filter")) + { + filter_mac = 1; + static_mac = 1; + } + else if (unformat (i, "bvi")) + { + bvi_mac = 1; + static_mac = 1; + } + else if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "count %d", &count)) + ; + else + break; + } + + if (mac_set == 0) + { + errmsg ("missing mac address"); + return -99; + } + + if (bd_id_set == 0) + { + errmsg ("missing bridge domain"); + return -99; + } + + if (is_add && sw_if_index_set == 0 && filter_mac == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + if (count > 1) + { + /* Turn on async mode */ + vam->async_mode = 1; + vam->async_errors = 0; + before = vat_time_now (vam); + } + + for (j = 0; j < count; j++) + { + M (L2FIB_ADD_DEL, mp); + + clib_memcpy (mp->mac, mac, 6); + mp->bd_id = ntohl (bd_id); + mp->is_add = is_add; + mp->sw_if_index = ntohl (sw_if_index); + + if (is_add) + { + mp->static_mac = static_mac; + mp->filter_mac = filter_mac; + mp->bvi_mac = bvi_mac; + } + increment_mac_address (mac); + /* send it... */ + S (mp); + } + + if (count > 1) + { + vl_api_control_ping_t *mp_ping; + f64 after; + + /* Shut off async mode */ + vam->async_mode = 0; + + PING (&l2_test_main, mp_ping); + S (mp_ping); + + timeout = vat_time_now (vam) + 1.0; + while (vat_time_now (vam) < timeout) + if (vam->result_ready == 1) + goto out; + vam->retval = -99; + + out: + if (vam->retval == -99) + errmsg ("timeout"); + + if (vam->async_errors > 0) + { + errmsg ("%d asynchronous errors", vam->async_errors); + vam->retval = -98; + } + vam->async_errors = 0; + after = vat_time_now (vam); + + print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec", count, + after - before, count / (after - before)); + } + else + { + int ret; + + /* Wait for a reply... */ + W (ret); + return ret; + } + /* Return the good/bad news */ + return (vam->retval); +} + +static int +api_l2fib_flush_int (vat_main_t *vam) +{ + vnet_main_t *vnm = vnet_get_main (); + unformat_input_t *i = vam->input; + vl_api_l2fib_flush_int_t *mp; + u32 sw_if_index = ~0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "sw_if_index %d", &sw_if_index)) + ; + else if (unformat (i, "%U", unformat_vnet_sw_interface, vnm, + &sw_if_index)) + ; + else + break; + } + + if (sw_if_index == ~0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + M (L2FIB_FLUSH_INT, mp); + + mp->sw_if_index = ntohl (sw_if_index); + + S (mp); + W (ret); + return ret; +} + +static int +api_l2_fib_clear_table (vat_main_t *vam) +{ + vl_api_l2_fib_clear_table_t *mp; + int ret; + + M (L2_FIB_CLEAR_TABLE, mp); + + S (mp); + W (ret); + return ret; +} + +static int +api_bridge_domain_set_mac_age (vat_main_t *vam) +{ + unformat_input_t *i = vam->input; + vl_api_bridge_domain_set_mac_age_t *mp; + u32 bd_id = ~0; + u32 mac_age = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "bd_id %d", &bd_id)) + ; + else if (unformat (i, "mac-age %d", &mac_age)) + ; + else + break; + } + + if (bd_id == ~0) + { + errmsg ("missing bridge domain"); + return -99; + } + + if (mac_age > 255) + { + errmsg ("mac age must be less than 256 "); + return -99; + } + + M (BRIDGE_DOMAIN_SET_MAC_AGE, mp); + + mp->bd_id = htonl (bd_id); + mp->mac_age = (u8) mac_age; + + S (mp); + W (ret); + return ret; +} + +static int +api_l2fib_set_scan_delay (vat_main_t *vam) +{ + return -1; +} + +static int +api_want_l2_macs_events2 (vat_main_t *vam) +{ + return -1; +} + +static int +api_l2_flags (vat_main_t *vam) +{ + vnet_main_t *vnm = vnet_get_main (); + unformat_input_t *i = vam->input; + vl_api_l2_flags_t *mp; + u32 sw_if_index; + u32 flags = 0; + u8 sw_if_index_set = 0; + u8 is_set = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if")) + { + if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", unformat_vnet_sw_interface, vnm, + &sw_if_index)) + sw_if_index_set = 1; + } + else + break; + } + else if (unformat (i, "learn")) + flags |= L2_LEARN; + else if (unformat (i, "forward")) + flags |= L2_FWD; + else if (unformat (i, "flood")) + flags |= L2_FLOOD; + else if (unformat (i, "uu-flood")) + flags |= L2_UU_FLOOD; + else if (unformat (i, "arp-term")) + flags |= L2_ARP_TERM; + else if (unformat (i, "off")) + is_set = 0; + else if (unformat (i, "disable")) + is_set = 0; + else + break; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + M (L2_FLAGS, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->feature_bitmap = ntohl (flags); + mp->is_set = is_set; + + S (mp); + W (ret); + return ret; +} + +static void +vl_api_l2_flags_reply_t_handler (vl_api_l2_flags_reply_t *mp) +{ + vat_main_t *vam = l2_test_main.vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->result_ready = 1; + } +} + +static int +api_l2fib_flush_bd (vat_main_t *vam) +{ + unformat_input_t *i = vam->input; + vl_api_l2fib_flush_bd_t *mp; + u32 bd_id = ~0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "bd_id %d", &bd_id)) + ; + else + break; + } + + if (bd_id == ~0) + { + errmsg ("missing bridge domain"); + return -99; + } + + M (L2FIB_FLUSH_BD, mp); + + mp->bd_id = htonl (bd_id); + + S (mp); + W (ret); + return ret; +} + +static int +api_bridge_domain_add_del (vat_main_t *vam) +{ + unformat_input_t *i = vam->input; + vl_api_bridge_domain_add_del_t *mp; + u32 bd_id = ~0; + u8 is_add = 1; + u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = 0; + u8 *bd_tag = NULL; + u32 mac_age = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "bd_id %d", &bd_id)) + ; + else if (unformat (i, "flood %d", &flood)) + ; + else if (unformat (i, "uu-flood %d", &uu_flood)) + ; + else if (unformat (i, "forward %d", &forward)) + ; + else if (unformat (i, "learn %d", &learn)) + ; + else if (unformat (i, "arp-term %d", &arp_term)) + ; + else if (unformat (i, "mac-age %d", &mac_age)) + ; + else if (unformat (i, "bd-tag %s", &bd_tag)) + ; + else if (unformat (i, "del")) + { + is_add = 0; + flood = uu_flood = forward = learn = 0; + } + else + break; + } + + if (bd_id == ~0) + { + errmsg ("missing bridge domain"); + ret = -99; + goto done; + } + + if (mac_age > 255) + { + errmsg ("mac age must be less than 256 "); + ret = -99; + goto done; + } + + if ((bd_tag) && (vec_len (bd_tag) > 63)) + { + errmsg ("bd-tag cannot be longer than 63"); + ret = -99; + goto done; + } + + M (BRIDGE_DOMAIN_ADD_DEL, mp); + + mp->bd_id = ntohl (bd_id); + mp->flood = flood; + mp->uu_flood = uu_flood; + mp->forward = forward; + mp->learn = learn; + mp->arp_term = arp_term; + mp->is_add = is_add; + mp->mac_age = (u8) mac_age; + if (bd_tag) + { + clib_memcpy (mp->bd_tag, bd_tag, vec_len (bd_tag)); + mp->bd_tag[vec_len (bd_tag)] = 0; + } + S (mp); + W (ret); + +done: + vec_free (bd_tag); + return ret; +} + +static int +api_bridge_domain_add_del_v2 (vat_main_t *vam) +{ + return -1; +} + +static void +vl_api_bridge_domain_add_del_v2_reply_t_handler ( + vl_api_bridge_domain_add_del_v2_reply_t *mp) +{ +} + +#define foreach_pbb_vtr_op \ + _ ("disable", L2_VTR_DISABLED) \ + _ ("pop", L2_VTR_POP_2) \ + _ ("push", L2_VTR_PUSH_2) + +static int +api_l2_interface_pbb_tag_rewrite (vat_main_t *vam) +{ + vnet_main_t *vnm = vnet_get_main (); + unformat_input_t *i = vam->input; + vl_api_l2_interface_pbb_tag_rewrite_t *mp; + u32 sw_if_index = ~0, vtr_op = ~0; + u16 outer_tag = ~0; + u8 dmac[6], smac[6]; + u8 dmac_set = 0, smac_set = 0; + u16 vlanid = 0; + u32 sid = ~0; + u32 tmp; + int ret; + + /* Shut up coverity */ + clib_memset (dmac, 0, sizeof (dmac)); + clib_memset (smac, 0, sizeof (smac)); + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index)) + ; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + ; + else if (unformat (i, "vtr_op %d", &vtr_op)) + ; +#define _(n, v) \ + else if (unformat (i, n)) { vtr_op = v; } + foreach_pbb_vtr_op +#undef _ + else if (unformat (i, "translate_pbb_stag")) + { + if (unformat (i, "%d", &tmp)) + { + vtr_op = L2_VTR_TRANSLATE_2_1; + outer_tag = tmp; + } + else + { + errmsg ( + "translate_pbb_stag operation requires outer tag definition"); + return -99; + } + } + else if (unformat (i, "dmac %U", unformat_ethernet_address, dmac)) + dmac_set++; + else if (unformat (i, "smac %U", unformat_ethernet_address, smac)) + smac_set++; + else if (unformat (i, "sid %d", &sid)); + else if (unformat (i, "vlanid %d", &tmp)) vlanid = tmp; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if ((sw_if_index == ~0) || (vtr_op == ~0)) + { + errmsg ("missing sw_if_index or vtr operation"); + return -99; + } + if (((vtr_op == L2_VTR_PUSH_2) || (vtr_op == L2_VTR_TRANSLATE_2_2)) && + ((dmac_set == 0) || (smac_set == 0) || (sid == ~0))) + { + errmsg ("push and translate_qinq operations require dmac, smac, sid and " + "optionally vlanid"); + return -99; + } + + M (L2_INTERFACE_PBB_TAG_REWRITE, mp); + mp->sw_if_index = ntohl (sw_if_index); + mp->vtr_op = ntohl (vtr_op); + mp->outer_tag = ntohs (outer_tag); + clib_memcpy (mp->b_dmac, dmac, sizeof (dmac)); + clib_memcpy (mp->b_smac, smac, sizeof (smac)); + mp->b_vlanid = ntohs (vlanid); + mp->i_sid = ntohl (sid); + + S (mp); + W (ret); + return ret; +} + +static int +api_sw_interface_set_l2_xconnect (vat_main_t *vam) +{ + vnet_main_t *vnm = vnet_get_main (); + unformat_input_t *i = vam->input; + vl_api_sw_interface_set_l2_xconnect_t *mp; + u32 rx_sw_if_index; + u8 rx_sw_if_index_set = 0; + u32 tx_sw_if_index; + u8 tx_sw_if_index_set = 0; + u8 enable = 1; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index)) + rx_sw_if_index_set = 1; + else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index)) + tx_sw_if_index_set = 1; + else if (unformat (i, "rx")) + { + if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", unformat_vnet_sw_interface, vnm, + &rx_sw_if_index)) + rx_sw_if_index_set = 1; + } + else + break; + } + else if (unformat (i, "tx")) + { + if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", unformat_vnet_sw_interface, vnm, + &tx_sw_if_index)) + tx_sw_if_index_set = 1; + } + else + break; + } + else if (unformat (i, "enable")) + enable = 1; + else if (unformat (i, "disable")) + enable = 0; + else + break; + } + + if (rx_sw_if_index_set == 0) + { + errmsg ("missing rx interface name or rx_sw_if_index"); + return -99; + } + + if (enable && (tx_sw_if_index_set == 0)) + { + errmsg ("missing tx interface name or tx_sw_if_index"); + return -99; + } + + M (SW_INTERFACE_SET_L2_XCONNECT, mp); + + mp->rx_sw_if_index = ntohl (rx_sw_if_index); + mp->tx_sw_if_index = ntohl (tx_sw_if_index); + mp->enable = enable; + + S (mp); + W (ret); + return ret; +} + +static int +api_l2_interface_efp_filter (vat_main_t *vam) +{ + vnet_main_t *vnm = vnet_get_main (); + unformat_input_t *i = vam->input; + vl_api_l2_interface_efp_filter_t *mp; + u32 sw_if_index; + u8 enable = 1; + u8 sw_if_index_set = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "enable")) + enable = 1; + else if (unformat (i, "disable")) + enable = 0; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (sw_if_index_set == 0) + { + errmsg ("missing sw_if_index"); + return -99; + } + + M (L2_INTERFACE_EFP_FILTER, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->enable_disable = enable; + + S (mp); + W (ret); + return ret; +} + +static void +vl_api_bd_ip_mac_details_t_handler (vl_api_bd_ip_mac_details_t *mp) +{ + vat_main_t *vam = &vat_main; + + print (vam->ofp, "\n%-5d %U %U", ntohl (mp->entry.bd_id), + format_vl_api_mac_address, mp->entry.mac, format_vl_api_address, + &mp->entry.ip); +} + +static void +vl_api_bvi_create_reply_t_handler (vl_api_bvi_create_reply_t *mp) +{ +} + +static int +api_sw_interface_set_l2_bridge (vat_main_t *vam) +{ + vnet_main_t *vnm = vnet_get_main (); + unformat_input_t *i = vam->input; + vl_api_sw_interface_set_l2_bridge_t *mp; + vl_api_l2_port_type_t port_type; + u32 rx_sw_if_index; + u8 rx_sw_if_index_set = 0; + u32 bd_id; + u8 bd_id_set = 0; + u32 shg = 0; + u8 enable = 1; + int ret; + + port_type = L2_API_PORT_TYPE_NORMAL; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "sw_if_index %d", &rx_sw_if_index)) + rx_sw_if_index_set = 1; + else if (unformat (i, "bd_id %d", &bd_id)) + bd_id_set = 1; + else if (unformat (i, "%U", unformat_vnet_sw_interface, vnm, + &rx_sw_if_index)) + rx_sw_if_index_set = 1; + else if (unformat (i, "shg %d", &shg)) + ; + else if (unformat (i, "bvi")) + port_type = L2_API_PORT_TYPE_BVI; + else if (unformat (i, "uu-fwd")) + port_type = L2_API_PORT_TYPE_UU_FWD; + else if (unformat (i, "enable")) + enable = 1; + else if (unformat (i, "disable")) + enable = 0; + else + break; + } + + if (rx_sw_if_index_set == 0) + { + errmsg ("missing rx interface name or sw_if_index"); + return -99; + } + + if (enable && (bd_id_set == 0)) + { + errmsg ("missing bridge domain"); + return -99; + } + + M (SW_INTERFACE_SET_L2_BRIDGE, mp); + + mp->rx_sw_if_index = ntohl (rx_sw_if_index); + mp->bd_id = ntohl (bd_id); + mp->shg = (u8) shg; + mp->port_type = ntohl (port_type); + mp->enable = enable; + + S (mp); + W (ret); + return ret; +} + +static int +api_sw_interface_set_vpath (vat_main_t *vam) +{ + vnet_main_t *vnm = vnet_get_main (); + unformat_input_t *i = vam->input; + vl_api_sw_interface_set_vpath_t *mp; + u32 sw_if_index = 0; + u8 sw_if_index_set = 0; + u8 is_enable = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "enable")) + is_enable = 1; + else if (unformat (i, "disable")) + is_enable = 0; + else + break; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + /* Construct the API message */ + M (SW_INTERFACE_SET_VPATH, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->enable = is_enable; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_l2_patch_add_del (vat_main_t *vam) +{ + vnet_main_t *vnm = vnet_get_main (); + unformat_input_t *i = vam->input; + vl_api_l2_patch_add_del_t *mp; + u32 rx_sw_if_index; + u8 rx_sw_if_index_set = 0; + u32 tx_sw_if_index; + u8 tx_sw_if_index_set = 0; + u8 is_add = 1; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index)) + rx_sw_if_index_set = 1; + else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index)) + tx_sw_if_index_set = 1; + else if (unformat (i, "rx")) + { + if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", unformat_vnet_sw_interface, vnm, + &rx_sw_if_index)) + rx_sw_if_index_set = 1; + } + else + break; + } + else if (unformat (i, "tx")) + { + if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", unformat_vnet_sw_interface, vnm, + &tx_sw_if_index)) + tx_sw_if_index_set = 1; + } + else + break; + } + else if (unformat (i, "del")) + is_add = 0; + else + break; + } + + if (rx_sw_if_index_set == 0) + { + errmsg ("missing rx interface name or rx_sw_if_index"); + return -99; + } + + if (tx_sw_if_index_set == 0) + { + errmsg ("missing tx interface name or tx_sw_if_index"); + return -99; + } + + M (L2_PATCH_ADD_DEL, mp); + + mp->rx_sw_if_index = ntohl (rx_sw_if_index); + mp->tx_sw_if_index = ntohl (tx_sw_if_index); + mp->is_add = is_add; + + S (mp); + W (ret); + return ret; +} + +static void +vl_api_bridge_flags_reply_t_handler (vl_api_bridge_flags_reply_t *mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->result_ready = 1; + } +} + +#define foreach_vtr_op \ + _ ("disable", L2_VTR_DISABLED) \ + _ ("push-1", L2_VTR_PUSH_1) \ + _ ("push-2", L2_VTR_PUSH_2) \ + _ ("pop-1", L2_VTR_POP_1) \ + _ ("pop-2", L2_VTR_POP_2) \ + _ ("translate-1-1", L2_VTR_TRANSLATE_1_1) \ + _ ("translate-1-2", L2_VTR_TRANSLATE_1_2) \ + _ ("translate-2-1", L2_VTR_TRANSLATE_2_1) \ + _ ("translate-2-2", L2_VTR_TRANSLATE_2_2) + +static int +api_l2_interface_vlan_tag_rewrite (vat_main_t *vam) +{ + vnet_main_t *vnm = vnet_get_main (); + unformat_input_t *i = vam->input; + vl_api_l2_interface_vlan_tag_rewrite_t *mp; + u32 sw_if_index; + u8 sw_if_index_set = 0; + u8 vtr_op_set = 0; + u32 vtr_op = 0; + u32 push_dot1q = 1; + u32 tag1 = ~0; + u32 tag2 = ~0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "vtr_op %d", &vtr_op)) + vtr_op_set = 1; +#define _(n, v) \ + else if (unformat (i, n)) \ + { \ + vtr_op = v; \ + vtr_op_set = 1; \ + } + foreach_vtr_op +#undef _ + else if (unformat (i, "push_dot1q %d", &push_dot1q)); + else if (unformat (i, "tag1 %d", &tag1)); + else if (unformat (i, "tag2 %d", &tag2)); + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if ((sw_if_index_set == 0) || (vtr_op_set == 0)) + { + errmsg ("missing vtr operation or sw_if_index"); + return -99; + } + + M (L2_INTERFACE_VLAN_TAG_REWRITE, mp); + mp->sw_if_index = ntohl (sw_if_index); + mp->vtr_op = ntohl (vtr_op); + mp->push_dot1q = ntohl (push_dot1q); + mp->tag1 = ntohl (tag1); + mp->tag2 = ntohl (tag2); + + S (mp); + W (ret); + return ret; +} + +static int +api_bridge_domain_set_learn_limit (vat_main_t *vam) +{ + return -1; +} + +static int +api_bd_ip_mac_add_del (vat_main_t *vam) +{ + vl_api_address_t ip = VL_API_ZERO_ADDRESS; + vl_api_mac_address_t mac = { 0 }; + unformat_input_t *i = vam->input; + vl_api_bd_ip_mac_add_del_t *mp; + u32 bd_id; + u8 is_add = 1; + u8 bd_id_set = 0; + u8 ip_set = 0; + u8 mac_set = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "bd_id %d", &bd_id)) + { + bd_id_set++; + } + else if (unformat (i, "%U", unformat_vl_api_address, &ip)) + { + ip_set++; + } + else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac)) + { + mac_set++; + } + else if (unformat (i, "del")) + is_add = 0; + else + break; + } + + if (bd_id_set == 0) + { + errmsg ("missing bridge domain"); + return -99; + } + else if (ip_set == 0) + { + errmsg ("missing IP address"); + return -99; + } + else if (mac_set == 0) + { + errmsg ("missing MAC address"); + return -99; + } + + M (BD_IP_MAC_ADD_DEL, mp); + + mp->entry.bd_id = ntohl (bd_id); + mp->is_add = is_add; + + clib_memcpy (&mp->entry.ip, &ip, sizeof (ip)); + clib_memcpy (&mp->entry.mac, &mac, sizeof (mac)); + + S (mp); + W (ret); + return ret; +} + +static void +vl_api_bridge_domain_details_t_handler (vl_api_bridge_domain_details_t *mp) +{ + vat_main_t *vam = l2_test_main.vat_main; + u32 n_sw_ifs = ntohl (mp->n_sw_ifs); + int i; + + print (vam->ofp, "\n%-3s %-3s %-3s %-3s %-3s %-6s %-3s", " ID", "LRN", "FWD", + "FLD", "BVI", "UU-FWD", "#IF"); + + print (vam->ofp, "%3d %3d %3d %3d %3d %6d %3d", ntohl (mp->bd_id), mp->learn, + mp->forward, mp->flood, ntohl (mp->bvi_sw_if_index), + ntohl (mp->uu_fwd_sw_if_index), n_sw_ifs); + + if (n_sw_ifs) + { + vl_api_bridge_domain_sw_if_t *sw_ifs; + print (vam->ofp, "\n\n%s %s %s", "sw_if_index", "SHG", + "Interface Name"); + + sw_ifs = mp->sw_if_details; + for (i = 0; i < n_sw_ifs; i++) + { + u8 *sw_if_name = 0; + u32 sw_if_index; + hash_pair_t *p; + + sw_if_index = ntohl (sw_ifs->sw_if_index); + + hash_foreach_pair (p, vam->sw_if_index_by_interface_name, ({ + if ((u32) p->value[0] == sw_if_index) + { + sw_if_name = (u8 *) (p->key); + break; + } + })); + print (vam->ofp, "%7d %3d %s", sw_if_index, sw_ifs->shg, + sw_if_name ? (char *) sw_if_name : "sw_if_index not found!"); + + sw_ifs++; + } + } +} + +static int +api_bridge_domain_dump (vat_main_t *vam) +{ + unformat_input_t *i = vam->input; + vl_api_bridge_domain_dump_t *mp; + vl_api_control_ping_t *mp_ping; + u32 bd_id = ~0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "bd_id %d", &bd_id)) + ; + else + break; + } + + M (BRIDGE_DOMAIN_DUMP, mp); + mp->bd_id = ntohl (bd_id); + S (mp); + + /* Use a control ping for synchronization */ + PING (&l2_test_main, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static int +api_bridge_domain_set_default_learn_limit (vat_main_t *vam) +{ + return -1; +} + +static int +api_bd_ip_mac_flush (vat_main_t *vam) +{ + unformat_input_t *i = vam->input; + vl_api_bd_ip_mac_flush_t *mp; + u32 bd_id; + u8 bd_id_set = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "bd_id %d", &bd_id)) + { + bd_id_set++; + } + else + break; + } + + if (bd_id_set == 0) + { + errmsg ("missing bridge domain"); + return -99; + } + + M (BD_IP_MAC_FLUSH, mp); + + mp->bd_id = ntohl (bd_id); + + S (mp); + W (ret); + return ret; +} + +static int +api_bd_ip_mac_dump (vat_main_t *vam) +{ + unformat_input_t *i = vam->input; + vl_api_bd_ip_mac_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + u32 bd_id; + u8 bd_id_set = 0; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "bd_id %d", &bd_id)) + { + bd_id_set++; + } + else + break; + } + + fformat (vam->ofp, "\n%-5s %-7s %-20s %-30s", "bd_id", "is_ipv6", + "mac_address", "ip_address"); + + /* Dump Bridge Domain Ip to Mac entries */ + M (BD_IP_MAC_DUMP, mp); + + if (bd_id_set) + mp->bd_id = htonl (bd_id); + else + mp->bd_id = ~0; + + S (mp); + + /* Use a control ping for synchronization */ + PING (&l2_test_main, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static int +api_bvi_create (vat_main_t *vam) +{ + return -1; +} + +static int +api_bvi_delete (vat_main_t *vam) +{ + return -1; +} + +static int +api_bridge_flags (vat_main_t *vam) +{ + unformat_input_t *i = vam->input; + vl_api_bridge_flags_t *mp; + u32 bd_id; + u8 bd_id_set = 0; + u8 is_set = 1; + bd_flags_t flags = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "bd_id %d", &bd_id)) + bd_id_set = 1; + else if (unformat (i, "learn")) + flags |= BRIDGE_API_FLAG_LEARN; + else if (unformat (i, "forward")) + flags |= BRIDGE_API_FLAG_FWD; + else if (unformat (i, "flood")) + flags |= BRIDGE_API_FLAG_FLOOD; + else if (unformat (i, "uu-flood")) + flags |= BRIDGE_API_FLAG_UU_FLOOD; + else if (unformat (i, "arp-term")) + flags |= BRIDGE_API_FLAG_ARP_TERM; + else if (unformat (i, "off")) + is_set = 0; + else if (unformat (i, "disable")) + is_set = 0; + else + break; + } + + if (bd_id_set == 0) + { + errmsg ("missing bridge domain"); + return -99; + } + + M (BRIDGE_FLAGS, mp); + + mp->bd_id = ntohl (bd_id); + mp->flags = ntohl (flags); + mp->is_set = is_set; + + S (mp); + W (ret); + return ret; +} + +#include <vnet/l2/l2.api_test.c> + +/* + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vnet/l2/l2_uu_fwd.c b/src/vnet/l2/l2_uu_fwd.c index fb3571d159c..4a510b658d7 100644 --- a/src/vnet/l2/l2_uu_fwd.c +++ b/src/vnet/l2/l2_uu_fwd.c @@ -211,7 +211,6 @@ VLIB_NODE_FN (l2_uu_fwd_node) (vlib_main_t * vm, return frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (l2_uu_fwd_node) = { .name = "l2-uu-fwd", .vector_size = sizeof (u32), @@ -228,7 +227,6 @@ VLIB_REGISTER_NODE (l2_uu_fwd_node) = { [L2_UU_FWD_NEXT_L2_OUTPUT] = "l2-output", }, }; -/* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON diff --git a/src/vnet/l2/l2_vtr.c b/src/vnet/l2/l2_vtr.c index bfd1dcb9280..4053c0fc1cb 100644 --- a/src/vnet/l2/l2_vtr.c +++ b/src/vnet/l2/l2_vtr.c @@ -670,13 +670,11 @@ done: * @cliexend * @endparblock ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (int_l2_vtr_cli, static) = { .path = "set interface l2 tag-rewrite", .short_help = "set interface l2 tag-rewrite <interface> [disable | pop {1|2} | push {dot1q|dot1ad} <tag> <tag>]", .function = int_l2_vtr, }; -/* *INDENT-ON* */ /** * Get pbb tag rewrite on the given interface. @@ -816,13 +814,11 @@ done: return error; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (int_l2_pbb_vtr_cli, static) = { .path = "set interface l2 pbb-tag-rewrite", .short_help = "set interface l2 pbb-tag-rewrite <interface> [disable | pop | push | translate_pbb_stag <outer_tag> dmac <address> smac <address> s_id <nn> [b_vlanid <nn>]]", .function = int_l2_pbb_vtr, }; -/* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON diff --git a/src/vnet/l2/l2_xcrw.c b/src/vnet/l2/l2_xcrw.c index c2c325a796f..9edd8b6ba57 100644 --- a/src/vnet/l2/l2_xcrw.c +++ b/src/vnet/l2/l2_xcrw.c @@ -238,7 +238,6 @@ VLIB_NODE_FN (l2_xcrw_node) (vlib_main_t * vm, return frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (l2_xcrw_node) = { .name = "l2-xcrw", .vector_size = sizeof (u32), @@ -255,7 +254,6 @@ VLIB_REGISTER_NODE (l2_xcrw_node) = { [L2_XCRW_NEXT_DROP] = "error-drop", }, }; -/* *INDENT-ON* */ #ifndef CLIB_MARCH_VARIANT clib_error_t * @@ -279,18 +277,17 @@ format_xcrw_name (u8 * s, va_list * args) return format (s, "xcrw%d", dev_instance); } -/* *INDENT-OFF* */ VNET_DEVICE_CLASS (xcrw_device_class,static) = { .name = "Xcrw", .format_device_name = format_xcrw_name, }; -/* *INDENT-ON* */ /* Create a sham tunnel interface and return its sw_if_index */ static u32 create_xcrw_interface (vlib_main_t * vm) { vnet_main_t *vnm = vnet_get_main (); + vnet_eth_interface_registration_t eir = {}; static u32 instance; u8 address[6]; u32 hw_if_index; @@ -301,10 +298,9 @@ create_xcrw_interface (vlib_main_t * vm) clib_memset (address, 0, sizeof (address)); address[2] = 0x12; - /* can returns error iff phy != 0 */ - (void) ethernet_register_interface - (vnm, xcrw_device_class.index, instance++, address, &hw_if_index, - /* flag change */ 0); + eir.dev_class_index = xcrw_device_class.index; + eir.dev_instance = instance++, eir.address = address; + hw_if_index = vnet_eth_register_interface (vnm, &eir); hi = vnet_get_hw_interface (vnm, hw_if_index); sw_if_index = hi->sw_if_index; @@ -496,7 +492,6 @@ done: * @todo This is incomplete. This needs a detailed description and a * practical example. ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (set_l2_xcrw_command, static) = { .path = "set interface l2 xcrw", .short_help = @@ -504,7 +499,6 @@ VLIB_CLI_COMMAND (set_l2_xcrw_command, static) = { " [del] [tx-fib-id <id>] [ipv6] rw <hex-bytes>", .function = set_l2_xcrw_command_fn, }; -/* *INDENT-ON* */ #endif /* CLIB_MARCH_VARIANT */ @@ -568,12 +562,10 @@ show_l2xcrw_command_fn (vlib_main_t * vm, vlib_cli_output (vm, "%U", format_l2xcrw, 0, 0); - /* *INDENT-OFF* */ pool_foreach (t, xcm->tunnels) { vlib_cli_output (vm, "%U", format_l2xcrw, vnm, t); } - /* *INDENT-ON* */ return 0; } @@ -585,13 +577,11 @@ show_l2xcrw_command_fn (vlib_main_t * vm, * @todo This is incomplete. This needs a detailed description and a * practical example. ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_l2xcrw_command, static) = { .path = "show l2xcrw", .short_help = "show l2xcrw", .function = show_l2xcrw_command_fn, }; -/* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON |