+ bd_main_t *bdm = &bd_main;
+ l2input_main_t *l2im = &l2input_main;
+ vl_api_registration_t *reg;
+ u32 bd_id, bd_index, end;
+
+ reg = vl_api_client_index_to_registration (mp->client_index);
+ if (!reg)
+ return;
+
+ bd_id = ntohl (mp->bd_id);
+ if (bd_id == 0)
+ return;
+
+ if (bd_id == ~0)
+ bd_index = 0, end = vec_len (l2im->bd_configs);
+ else
+ {
+ bd_index = bd_find_index (bdm, bd_id);
+ if (bd_index == ~0)
+ return;
+
+ end = bd_index + 1;
+ }
+
+ for (; bd_index < end; bd_index++)
+ {
+ l2_bridge_domain_t *bd_config =
+ l2input_bd_config_from_index (l2im, bd_index);
+ /* skip dummy bd_id 0 */
+ if (bd_config && (bd_config->bd_id > 0))
+ send_bridge_domain_details (l2im, reg, bd_config,
+ vec_len (bd_config->members),
+ mp->context);
+ }
+}
+
+static bd_flags_t
+bd_flags_decode (vl_api_bd_flags_t v)
+{
+ bd_flags_t f = L2_NONE;
+
+ v = ntohl (v);
+
+ if (v & BRIDGE_API_FLAG_LEARN)
+ f |= L2_LEARN;
+ if (v & BRIDGE_API_FLAG_FWD)
+ f |= L2_FWD;
+ if (v & BRIDGE_API_FLAG_FLOOD)
+ f |= L2_FLOOD;
+ if (v & BRIDGE_API_FLAG_UU_FLOOD)
+ f |= L2_UU_FLOOD;
+ if (v & BRIDGE_API_FLAG_ARP_TERM)
+ f |= L2_ARP_TERM;
+
+ return (f);
+}
+
+static void
+vl_api_bridge_flags_t_handler (vl_api_bridge_flags_t * mp)
+{
+ vlib_main_t *vm = vlib_get_main ();
+ bd_main_t *bdm = &bd_main;
+ vl_api_bridge_flags_reply_t *rmp;
+ int rv = 0;
+
+ bd_flags_t flags = bd_flags_decode (mp->flags);
+ u32 bd_id = ntohl (mp->bd_id);
+ if (bd_id == 0)
+ {
+ rv = VNET_API_ERROR_BD_NOT_MODIFIABLE;
+ goto out;
+ }
+
+ u32 bd_index = bd_find_index (bdm, bd_id);
+ if (bd_index == ~0)
+ {
+ rv = VNET_API_ERROR_NO_SUCH_ENTRY;
+ goto out;
+ }
+
+ u32 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
+ vl_api_l2_interface_vlan_tag_rewrite_t_handler
+ (vl_api_l2_interface_vlan_tag_rewrite_t * mp)
+{
+ int rv = 0;
+ vl_api_l2_interface_vlan_tag_rewrite_reply_t *rmp;
+ vnet_main_t *vnm = vnet_get_main ();
+ vlib_main_t *vm = vlib_get_main ();
+ u32 vtr_op;
+
+ VALIDATE_SW_IF_INDEX (mp);
+
+ vtr_op = ntohl (mp->vtr_op);
+
+ /* The L2 code is unsuspicious */
+ switch (vtr_op)
+ {
+ case L2_VTR_DISABLED:
+ case L2_VTR_PUSH_1:
+ case L2_VTR_PUSH_2:
+ case L2_VTR_POP_1:
+ case L2_VTR_POP_2:
+ case L2_VTR_TRANSLATE_1_1:
+ case L2_VTR_TRANSLATE_1_2:
+ case L2_VTR_TRANSLATE_2_1:
+ case L2_VTR_TRANSLATE_2_2:
+ break;
+
+ default:
+ rv = VNET_API_ERROR_INVALID_VALUE;
+ goto bad_sw_if_index;
+ }
+
+ rv = l2vtr_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
+ ntohl (mp->push_dot1q), ntohl (mp->tag1),
+ ntohl (mp->tag2));
+
+ BAD_SW_IF_INDEX_LABEL;
+
+ REPLY_MACRO (VL_API_L2_INTERFACE_VLAN_TAG_REWRITE_REPLY);
+}
+
+static void
+ vl_api_l2_interface_pbb_tag_rewrite_t_handler
+ (vl_api_l2_interface_pbb_tag_rewrite_t * mp)
+{
+ vl_api_l2_interface_pbb_tag_rewrite_reply_t *rmp;
+ vnet_main_t *vnm = vnet_get_main ();
+ vlib_main_t *vm = vlib_get_main ();
+ u32 vtr_op;
+ int rv = 0;
+
+ VALIDATE_SW_IF_INDEX (mp);
+
+ vtr_op = ntohl (mp->vtr_op);
+
+ switch (vtr_op)
+ {
+ case L2_VTR_DISABLED:
+ case L2_VTR_PUSH_2:
+ case L2_VTR_POP_2:
+ case L2_VTR_TRANSLATE_2_1:
+ break;
+
+ default:
+ rv = VNET_API_ERROR_INVALID_VALUE;
+ goto bad_sw_if_index;
+ }
+
+ rv = l2pbb_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
+ mp->b_dmac, mp->b_smac, ntohs (mp->b_vlanid),
+ ntohl (mp->i_sid), ntohs (mp->outer_tag));
+
+ BAD_SW_IF_INDEX_LABEL;
+
+ REPLY_MACRO (VL_API_L2_INTERFACE_PBB_TAG_REWRITE_REPLY);
+}
+
+static void
+ vl_api_sw_interface_set_l2_xconnect_t_handler
+ (vl_api_sw_interface_set_l2_xconnect_t * mp)
+{
+ vl_api_sw_interface_set_l2_xconnect_reply_t *rmp;
+ int rv = 0;
+ u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
+ u32 tx_sw_if_index = ntohl (mp->tx_sw_if_index);
+ vlib_main_t *vm = vlib_get_main ();
+ vnet_main_t *vnm = vnet_get_main ();
+
+ VALIDATE_RX_SW_IF_INDEX (mp);
+
+ if (mp->enable)
+ {
+ VALIDATE_TX_SW_IF_INDEX (mp);
+ rv = set_int_l2_mode (vm, vnm, MODE_L2_XC,
+ rx_sw_if_index, 0,
+ L2_BD_PORT_TYPE_NORMAL, 0, tx_sw_if_index);
+ }
+ else
+ {
+ rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0,
+ L2_BD_PORT_TYPE_NORMAL, 0, 0);
+ }
+
+ BAD_RX_SW_IF_INDEX_LABEL;
+ BAD_TX_SW_IF_INDEX_LABEL;
+
+ REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_XCONNECT_REPLY);
+}
+
+static int
+l2_bd_port_type_decode (vl_api_l2_port_type_t v, l2_bd_port_type_t * l)
+{
+ v = clib_net_to_host_u32 (v);
+
+ switch (v)
+ {
+ case L2_API_PORT_TYPE_NORMAL:
+ *l = L2_BD_PORT_TYPE_NORMAL;
+ return 0;
+ case L2_API_PORT_TYPE_BVI:
+ *l = L2_BD_PORT_TYPE_BVI;
+ return 0;
+ case L2_API_PORT_TYPE_UU_FWD:
+ *l = L2_BD_PORT_TYPE_UU_FWD;
+ return 0;
+ }
+
+ return (VNET_API_ERROR_INVALID_VALUE);
+}
+
+static void
+ vl_api_sw_interface_set_l2_bridge_t_handler
+ (vl_api_sw_interface_set_l2_bridge_t * mp)
+{
+ bd_main_t *bdm = &bd_main;
+ vl_api_sw_interface_set_l2_bridge_reply_t *rmp;
+ int rv = 0;
+ vlib_main_t *vm = vlib_get_main ();
+ vnet_main_t *vnm = vnet_get_main ();
+ l2_bd_port_type_t pt;
+
+ VALIDATE_RX_SW_IF_INDEX (mp);
+ u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
+ rv = l2_bd_port_type_decode (mp->port_type, &pt);
+
+ if (0 != rv)
+ goto out;
+ if (mp->enable)
+ {
+ VALIDATE_BD_ID (mp);
+ u32 bd_id = ntohl (mp->bd_id);
+ u32 bd_index = bd_find_or_add_bd_index (bdm, bd_id);
+
+ rv = set_int_l2_mode (vm, vnm, MODE_L2_BRIDGE,
+ rx_sw_if_index, bd_index, pt, mp->shg, 0);
+ }
+ else
+ {
+ rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0, pt, 0, 0);
+ }
+
+ BAD_RX_SW_IF_INDEX_LABEL;
+ BAD_BD_ID_LABEL;
+out:
+ REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_BRIDGE_REPLY);
+}
+
+static void
+send_bd_ip_mac_entry (vpe_api_main_t * am,
+ vl_api_registration_t * reg,
+ u32 bd_id, u8 is_ipv6,
+ u8 * ip_address, u8 * mac_address, u32 context)
+{
+ vl_api_bd_ip_mac_details_t *mp;