diff --git a/saivpp/src/SwitchStateBaseNexthop.cpp b/saivpp/src/SwitchStateBaseNexthop.cpp index f551c11..6072f60 100644 --- a/saivpp/src/SwitchStateBaseNexthop.cpp +++ b/saivpp/src/SwitchStateBaseNexthop.cpp @@ -194,9 +194,36 @@ SwitchStateBase::fillNHGrpMember(nexthop_grp_member_t *nxt_grp_member, sai_objec switch (next_hop_type) { case SAI_NEXT_HOP_TYPE_IP: - attr.id = SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID; - if (get(SAI_OBJECT_TYPE_NEXT_HOP, next_hop_oid, 1, &attr) == SAI_STATUS_SUCCESS) { - nxt_grp_member->rif_oid = attr.value.oid; + { + uint32_t rif_type; + sai_object_id_t port_oid; + uint16_t vlan_id = 0; + attr.id = SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID; + if (nh_obj->get_attr(attr) == SAI_STATUS_SUCCESS) + { + nxt_grp_member->rif_oid = attr.value.oid; + } + auto rif_obj = nh_obj->get_linked_object(SAI_OBJECT_TYPE_ROUTER_INTERFACE, SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID); + + attr.id = SAI_ROUTER_INTERFACE_ATTR_PORT_ID; + CHECK_STATUS_QUIET(rif_obj->get_mandatory_attr(attr)); + port_oid = attr.value.oid; + + attr.id = SAI_ROUTER_INTERFACE_ATTR_TYPE; + CHECK_STATUS_QUIET(rif_obj->get_mandatory_attr(attr)); + rif_type = attr.value.u16; + if (rif_type == SAI_ROUTER_INTERFACE_TYPE_SUB_PORT) { + attr.id = SAI_ROUTER_INTERFACE_ATTR_OUTER_VLAN_ID; + CHECK_STATUS_QUIET(rif_obj->get_mandatory_attr(attr)); + vlan_id = attr.value.u16; + } + std::string if_name; + if (vpp_get_hwif_name(port_oid, vlan_id, if_name)) { + strncpy(nxt_grp_member->if_name, if_name.c_str(), sizeof(nxt_grp_member->if_name) - 1); + } else { + nxt_grp_member->if_name[0] = 0; + } + break; } break; case SAI_NEXT_HOP_TYPE_TUNNEL_ENCAP: { @@ -231,7 +258,7 @@ SwitchStateBase::createNexthop( SWSS_LOG_ENTER(); CHECK_STATUS(find_attrib_in_list(attr_count, attr_list, SAI_NEXT_HOP_ATTR_TYPE, &next_hop_type, &attr_index)); - if (next_hop_type->s32 == SAI_NEXT_HOP_TYPE_TUNNEL_ENCAP) { + if (next_hop_type->u32 == SAI_NEXT_HOP_TYPE_TUNNEL_ENCAP) { //Deligate the creation of tunnel encap nexthop to tunnel manager CHECK_STATUS(m_tunnel_mgr.create_tunnel_encap_nexthop(serializedObjectId, switch_id, attr_count, attr_list)); } @@ -254,7 +281,7 @@ sai_status_t SwitchStateBase::removeNexthop( if(status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Missing SAI_NEXT_HOP_ATTR_TYPE in %s", serializedObjectId); } - else if (attr.value.s32 == SAI_NEXT_HOP_TYPE_TUNNEL_ENCAP) { + else if (attr.value.u32 == SAI_NEXT_HOP_TYPE_TUNNEL_ENCAP) { CHECK_STATUS(m_tunnel_mgr.remove_tunnel_encap_nexthop(serializedObjectId)); } } diff --git a/saivpp/src/SwitchStateBaseNexthop.h b/saivpp/src/SwitchStateBaseNexthop.h index 27c77c9..4691971 100644 --- a/saivpp/src/SwitchStateBaseNexthop.h +++ b/saivpp/src/SwitchStateBaseNexthop.h @@ -25,6 +25,7 @@ typedef struct nexthop_grp_member_ { uint32_t weight; uint32_t seq_id; uint32_t sw_if_index; + char if_name[64]; } nexthop_grp_member_t; typedef struct nexthop_grp_config_ { diff --git a/saivpp/src/SwitchStateBaseRoute.cpp b/saivpp/src/SwitchStateBaseRoute.cpp index 706a7c0..864d1f0 100644 --- a/saivpp/src/SwitchStateBaseRoute.cpp +++ b/saivpp/src/SwitchStateBaseRoute.cpp @@ -70,7 +70,6 @@ void create_route_prefix_entry ( void create_vpp_nexthop_entry ( nexthop_grp_member_t *nxt_grp_member, - const char *hwif_name, vpp_nexthop_type_e type, vpp_ip_nexthop_t *vpp_nexthop) { @@ -97,7 +96,12 @@ void create_vpp_nexthop_entry ( } } vpp_nexthop->type = type; - vpp_nexthop->hwif_name = hwif_name; + + if (strlen(nxt_grp_member->if_name) > 0) { + vpp_nexthop->hwif_name = nxt_grp_member->if_name; + } else { + vpp_nexthop->hwif_name = NULL; + } vpp_nexthop->sw_if_index = nxt_grp_member->sw_if_index; vpp_nexthop->weight = (uint8_t) nxt_grp_member->weight; vpp_nexthop->preference = 0; @@ -120,7 +124,6 @@ sai_status_t SwitchStateBase::IpRouteAddRemove( next_hop_oid = attr.value.oid; sai_route_entry_t route_entry; - const char *hwif_name = NULL; vpp_nexthop_type_e nexthop_type = VPP_NEXTHOP_NORMAL; bool config_ip_route = false; @@ -182,7 +185,7 @@ sai_status_t SwitchStateBase::IpRouteAddRemove( size_t i; for (i = 0; i < nxthop_group->nmembers; i++) { - create_vpp_nexthop_entry(nxt_grp_member, hwif_name, nexthop_type, &ip_route->nexthop[i]); + create_vpp_nexthop_entry(nxt_grp_member, nexthop_type, &ip_route->nexthop[i]); nxt_grp_member++; } ip_route->nexthop_cnt = nxthop_group->nmembers; diff --git a/vppbld/vpp.patch b/vppbld/vpp.patch index 74a6016..ac0bee9 100644 --- a/vppbld/vpp.patch +++ b/vppbld/vpp.patch @@ -1,8 +1,8 @@ diff --git a/Makefile b/Makefile -index 98866e9be..f9d5b349e 100644 +index 3144905f3..04560cf2c 100644 --- a/Makefile +++ b/Makefile -@@ -76,7 +76,7 @@ DEB_DEPENDS += libffi-dev python3-ply libunwind-dev +@@ -78,7 +78,7 @@ DEB_DEPENDS += libffi-dev python3-ply libunwind-dev DEB_DEPENDS += cmake ninja-build python3-jsonschema python3-yaml DEB_DEPENDS += python3-venv # ensurepip DEB_DEPENDS += python3-dev python3-pip @@ -11,7 +11,7 @@ index 98866e9be..f9d5b349e 100644 # DEB_DEPENDS += enchant # for docs DEB_DEPENDS += python3-virtualenv DEB_DEPENDS += libssl-dev -@@ -85,7 +85,7 @@ DEB_DEPENDS += iperf3 # for 'make test TEST=vcl' +@@ -87,7 +87,7 @@ DEB_DEPENDS += iperf3 # for 'make test TEST=vcl' DEB_DEPENDS += nasm DEB_DEPENDS += iperf ethtool # for 'make test TEST=vm_vpp_interfaces' DEB_DEPENDS += libpcap-dev @@ -21,10 +21,10 @@ index 98866e9be..f9d5b349e 100644 LIBFFI=libffi6 # works on all but 20.04 and debian-testing diff --git a/build/external/packages/xdp-tools.mk b/build/external/packages/xdp-tools.mk -index b9285971f..c38acc598 100644 +index 08d94e424..1fbbef9b7 100644 --- a/build/external/packages/xdp-tools.mk +++ b/build/external/packages/xdp-tools.mk -@@ -24,7 +24,7 @@ define xdp-tools_config_cmds +@@ -25,7 +25,7 @@ define xdp-tools_config_cmds endef define xdp-tools_build_cmds @@ -33,6 +33,164 @@ index b9285971f..c38acc598 100644 endef define xdp-tools_install_cmds +diff --git a/src/plugins/linux-cp/lcp_node.c b/src/plugins/linux-cp/lcp_node.c +index 241cc5e4b..5438d536d 100644 +--- a/src/plugins/linux-cp/lcp_node.c ++++ b/src/plugins/linux-cp/lcp_node.c +@@ -1033,6 +1033,153 @@ VNET_FEATURE_INIT (lcp_arp_host_arp_feat, static) = { + .runs_before = VNET_FEATURES ("arp-reply"), + }; + ++typedef struct l2_punt_trace_t_ ++{ ++ u8 direction; // 0 = punt, 1 = inject ++ u32 phy_sw_if_index; ++ u32 host_sw_if_index; ++} l2_punt_trace_t; ++ ++static u8 * ++format_l2_punt_trace (u8 *s, va_list *args) ++{ ++ CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); ++ CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); ++ l2_punt_trace_t *t = va_arg (*args, l2_punt_trace_t *); ++ ++ if (t->direction) ++ { ++ s = format (s, "l2-punt: %u -> %u", t->host_sw_if_index, ++ t->phy_sw_if_index); ++ } ++ else ++ { ++ s = format (s, "l2-punt: %u -> %u", t->phy_sw_if_index, ++ t->host_sw_if_index); ++ } ++ ++ return s; ++} ++ ++VLIB_NODE_FN (l2_punt_node) ++(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame) ++{ ++ u32 n_left_from, *from, *to_next, n_left_to_next; ++ lip_punt_next_t next_index; ++ ++ next_index = node->cached_next_index; ++ n_left_from = frame->n_vectors; ++ from = vlib_frame_vector_args (frame); ++ ++ while (n_left_from > 0) ++ { ++ vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); ++ ++ while (n_left_from > 0 && n_left_to_next > 0) ++ { ++ vlib_buffer_t *b0; ++ const lcp_itf_pair_t *lip0 = NULL; ++ u32 next0 = ~0; ++ u32 bi0, lipi0; ++ u32 sw_if_index0; ++ u8 direction = 0; ++ u8 len0; ++ ++ bi0 = to_next[0] = from[0]; ++ ++ from += 1; ++ to_next += 1; ++ n_left_from -= 1; ++ n_left_to_next -= 1; ++ next0 = LIP_PUNT_NEXT_DROP; ++ ++ b0 = vlib_get_buffer (vm, bi0); ++ ++ sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; ++ // check if RX sw_if_index is a phy (meaning this could require a punt, direction = 0) ++ lipi0 = lcp_itf_pair_find_by_phy (sw_if_index0); ++ if (lipi0 == INDEX_INVALID) ++ { ++ // check if RX sw_if_index is a host (meaning this could require an inject, direction = 1) ++ lipi0 = lcp_itf_pair_find_by_host (sw_if_index0); ++ if (lipi0 == INDEX_INVALID) ++ goto trace0; ++ ++ direction = 1; ++ } ++ ++ lip0 = lcp_itf_pair_get (lipi0); ++ next0 = LIP_PUNT_NEXT_IO; ++ // if direction is 1 (inject), set TX to phy ++ // if direction is 0 (punt), set TX to host ++ vnet_buffer (b0)->sw_if_index[VLIB_TX] = ++ direction ? lip0->lip_phy_sw_if_index : lip0->lip_host_sw_if_index; ++ ++ if (PREDICT_TRUE (lip0->lip_host_type == LCP_ITF_HOST_TAP)) ++ { ++ /* ++ * rewind to ethernet header ++ */ ++ len0 = ((u8 *) vlib_buffer_get_current (b0) - ++ (u8 *) ethernet_buffer_get_header (b0)); ++ vlib_buffer_advance (b0, -len0); ++ } ++ ++ trace0: ++ if (PREDICT_FALSE ((b0->flags & VLIB_BUFFER_IS_TRACED))) ++ { ++ l2_punt_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t)); ++ t->direction = direction; ++ if (direction) ++ { ++ t->phy_sw_if_index = ++ (lipi0 == INDEX_INVALID) ? ~0 : lip0->lip_phy_sw_if_index; ++ t->host_sw_if_index = sw_if_index0; ++ } ++ else ++ { ++ ++ t->phy_sw_if_index = sw_if_index0; ++ t->host_sw_if_index = ++ (lipi0 == INDEX_INVALID) ? ~0 : lip0->lip_host_sw_if_index; ++ } ++ } ++ ++ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, ++ n_left_to_next, bi0, next0); ++ } ++ ++ vlib_put_next_frame (vm, node, next_index, n_left_to_next); ++ } ++ ++ return frame->n_vectors; ++} ++ ++VLIB_REGISTER_NODE (l2_punt_node) = { ++ .name = "linux-cp-punt-l2", ++ .vector_size = sizeof (u32), ++ .format_trace = format_l2_punt_trace, ++ .type = VLIB_NODE_TYPE_INTERNAL, ++ ++ .n_next_nodes = LIP_PUNT_N_NEXT, ++ .next_nodes = { ++ [LIP_PUNT_NEXT_DROP] = "error-drop", ++ [LIP_PUNT_NEXT_IO] = "interface-output", ++ }, ++ }; ++ ++static clib_error_t * ++lcp_lacp_init (vlib_main_t *vm) ++{ ++ ethernet_register_input_type (vm, ETHERNET_TYPE_SLOW_PROTOCOLS /* LACP */ , ++ l2_punt_node.index); ++ icmp6_register_type (vm, ICMP6_router_solicitation, l2_punt_node.index); ++ icmp6_register_type (vm, ICMP6_router_advertisement, l2_punt_node.index); ++ ++ return NULL; ++} ++ ++VLIB_INIT_FUNCTION (lcp_lacp_init); + /* + * fd.io coding-style-patch-verification: ON + * diff --git a/src/plugins/vxlan/vxlan.c b/src/plugins/vxlan/vxlan.c index 0885550d2..8b8cd66e4 100644 --- a/src/plugins/vxlan/vxlan.c