Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions vslib/vpp/SwitchVpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,20 @@ sai_status_t SwitchVpp::create(
return status;
}

if (object_type == SAI_OBJECT_TYPE_TUNNEL)
{
sai_object_id_t object_id;
sai_deserialize_object_id(serializedObjectId, object_id);

CHECK_STATUS(create_internal(object_type, serializedObjectId, switch_id, attr_count, attr_list));

uint32_t sw_if_index;
sai_status_t status = m_tunnel_mgr.create_l2_vxlan_tunnel(object_id, sw_if_index);
SWSS_LOG_INFO("L2 VXLAN tunnel create for %s: status=%d sw_if_index=%u",
serializedObjectId.c_str(), status, sw_if_index);
return status;
}

return create_internal(object_type, serializedObjectId, switch_id, attr_count, attr_list);
}

Expand Down Expand Up @@ -1307,6 +1321,20 @@ sai_status_t SwitchVpp::remove(
return status;
}

if (object_type == SAI_OBJECT_TYPE_TUNNEL)
{
sai_object_id_t object_id;
sai_deserialize_object_id(serializedObjectId, object_id);

sai_status_t status = m_tunnel_mgr.remove_l2_vxlan_tunnel(object_id);
if (status != SAI_STATUS_SUCCESS) {
SWSS_LOG_ERROR("Failed to remove L2 VXLAN tunnel resources");
}

// still need to clean up internal SAI state
return remove_internal(object_type, serializedObjectId);
}

return remove_internal(object_type, serializedObjectId);
}

Expand Down
14 changes: 14 additions & 0 deletions vslib/vpp/SwitchVpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,20 @@ namespace saivs
_In_ uint32_t attr_count,
_In_ const sai_attribute_t *attr_list);

/**
* @brief Check if a bridge port is of type TUNNEL.
*
* Tunnel bridge ports carry SAI_BRIDGE_PORT_ATTR_TUNNEL_ID instead of
* SAI_BRIDGE_PORT_ATTR_PORT_ID. VPP functions that dereference PORT_ID
* must call this first to avoid null-pointer crashes.
*
* @param[in] br_port_id The bridge port object ID to check.
* @return true if the bridge port type is SAI_BRIDGE_PORT_TYPE_TUNNEL.
*/
bool is_tunnel_bridge_port(
_In_ sai_object_id_t br_port_id);


/* BFD Session */
sai_status_t bfd_session_add(
_In_ const std::string &serializedObjectId,
Expand Down
77 changes: 76 additions & 1 deletion vslib/vpp/SwitchVppFdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,37 @@ using namespace saivs;
FLUSH_ALL = 4, /* Flushing all DYNAMIC FDB_ENTRY on all */
} fdb_flush_mode;

// utility function to check whether a bridge port is of type TUNNEL
bool SwitchVpp::is_tunnel_bridge_port(
_In_ sai_object_id_t br_port_id)
{
SWSS_LOG_ENTER();

try
{
auto br_port_attrs = m_objectHash.at(SAI_OBJECT_TYPE_BRIDGE_PORT)
.at(sai_serialize_object_id(br_port_id));

auto meta = sai_metadata_get_attr_metadata(
SAI_OBJECT_TYPE_BRIDGE_PORT, SAI_BRIDGE_PORT_ATTR_TYPE);

auto it = br_port_attrs.find(meta->attridname);

if (it != br_port_attrs.end() &&
it->second->getAttr()->value.s32 == SAI_BRIDGE_PORT_TYPE_TUNNEL)
{
return true;
}
}
catch (const std::exception &e)
{
SWSS_LOG_WARN("is_tunnel_bridge_port: exception for %s: %s",
sai_serialize_object_id(br_port_id).c_str(), e.what());
}

return false;
}

sai_status_t SwitchVpp::createVlanMember(
_In_ sai_object_id_t object_id,
_In_ sai_object_id_t switch_id,
Expand Down Expand Up @@ -68,6 +99,14 @@ sai_status_t SwitchVpp::vpp_create_vlan_member(
return SAI_STATUS_FAILURE;
}

// Skip VPP operations for tunnel bridge ports -- they have no physical port
if (is_tunnel_bridge_port(br_port_id))
{
SWSS_LOG_NOTICE("Skipping VLAN member VPP create for tunnel bridge port %s",
sai_serialize_object_id(br_port_id).c_str());
return SAI_STATUS_SUCCESS;
}

const char *hwifname = nullptr;
uint32_t lag_swif_idx;

Expand Down Expand Up @@ -262,8 +301,17 @@ sai_status_t SwitchVpp::vpp_remove_vlan_member(
return SAI_STATUS_FAILURE;
}

// Skip VPP operations for tunnel bridge ports -- they have no physical port
if (is_tunnel_bridge_port(br_port_oid))
{
SWSS_LOG_NOTICE("Skipping vlan member remove for TUNNEL bridge port %s",
sai_serialize_object_id(br_port_oid).c_str());
return SAI_STATUS_SUCCESS;
}

const char *hw_ifname = nullptr;
auto br_port_attrs = m_objectHash.at(SAI_OBJECT_TYPE_BRIDGE_PORT).at(sai_serialize_object_id(br_port_oid));

auto meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_BRIDGE_PORT, SAI_BRIDGE_PORT_ATTR_PORT_ID);
auto bp_attr = br_port_attrs[meta->attridname];
auto port_id = bp_attr->getAttr()->value.oid;
Expand Down Expand Up @@ -974,6 +1022,15 @@ sai_status_t SwitchVpp::vpp_fdbentry_add(
return SAI_STATUS_FAILURE;
}

// Skip VPP FDB add for tunnel bridge ports -- L2 VXLAN FDB is handled
// separately via the EVPN remote-MAC path, not the per-port FDB path
if (is_tunnel_bridge_port(br_port_id))
{
SWSS_LOG_NOTICE("Skipping FDB add for tunnel bridge port %s",
sai_serialize_object_id(br_port_id).c_str());
return SAI_STATUS_SUCCESS;
}

auto br_port_attrs = m_objectHash.at(SAI_OBJECT_TYPE_BRIDGE_PORT).at(sai_serialize_object_id(br_port_id));
auto meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_BRIDGE_PORT, SAI_BRIDGE_PORT_ATTR_PORT_ID);
auto bp_attr = br_port_attrs[meta->attridname];
Expand Down Expand Up @@ -1081,6 +1138,14 @@ sai_status_t SwitchVpp::vpp_fdbentry_del(
return SAI_STATUS_FAILURE;
}

// Skip VPP FDB delete for tunnel bridge ports
if (is_tunnel_bridge_port(br_port_id))
{
SWSS_LOG_NOTICE("Skipping FDB delete for tunnel bridge port %s",
sai_serialize_object_id(br_port_id).c_str());
return SAI_STATUS_SUCCESS;
}

auto br_port_attrs = m_objectHash.at(SAI_OBJECT_TYPE_BRIDGE_PORT).at(sai_serialize_object_id(br_port_id));
auto meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_BRIDGE_PORT, SAI_BRIDGE_PORT_ATTR_PORT_ID);
auto bp_attr = br_port_attrs[meta->attridname];
Expand Down Expand Up @@ -1201,6 +1266,16 @@ sai_status_t SwitchVpp::vpp_fdbentry_flush(
case FLUSH_BY_INTERFACE:
case FLUSH_BY_INTERFACE | FLUSH_ALL:/*flush by interface*/
{
// Tunnel bridge ports have no physical port -- fall back to flush all
if (is_tunnel_bridge_port(br_port_id))
{
SWSS_LOG_NOTICE("Tunnel bridge port %s: falling back to flush all",
sai_serialize_object_id(br_port_id).c_str());
auto ret = l2fib_flush_all();
SWSS_LOG_NOTICE("Flush ALL (tunnel bridge port fallback) ret_val: %d", ret);
break;
}

auto br_port_attrs = m_objectHash.at(SAI_OBJECT_TYPE_BRIDGE_PORT).at(sai_serialize_object_id(br_port_id));
auto meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_BRIDGE_PORT, SAI_BRIDGE_PORT_ATTR_PORT_ID);
auto bp_attr = br_port_attrs[meta->attridname];
Expand Down Expand Up @@ -1255,4 +1330,4 @@ sai_status_t SwitchVpp::vpp_fdbentry_flush(
}

return SAI_STATUS_SUCCESS;
}
}
Loading
Loading