diff --git a/vslib/HostInterfaceInfo.cpp b/vslib/HostInterfaceInfo.cpp index c558d2a70..cbd7189af 100644 --- a/vslib/HostInterfaceInfo.cpp +++ b/vslib/HostInterfaceInfo.cpp @@ -22,6 +22,8 @@ #include #include +extern bool g_vpp; + using namespace saivs; HostInterfaceInfo::HostInterfaceInfo( @@ -42,6 +44,12 @@ HostInterfaceInfo::HostInterfaceInfo( m_run_thread = true; + if (g_vpp) // VPP + { + // threads are disabled for vpp + return; + } + m_e2t = std::make_shared(&HostInterfaceInfo::veth2tap_fun, this); m_t2e = std::make_shared(&HostInterfaceInfo::tap2veth_fun, this); } diff --git a/vslib/MACsecAttr.h b/vslib/MACsecAttr.h index 106b7b07b..7eedaa077 100644 --- a/vslib/MACsecAttr.h +++ b/vslib/MACsecAttr.h @@ -7,8 +7,10 @@ namespace saivs { + using macsec_sci_t = std::string; using macsec_an_t = std::uint16_t; using macsec_pn_t = std::uint64_t; + using macsec_ssci_t = std::uint32_t; struct MACsecAttr { @@ -50,11 +52,12 @@ namespace saivs std::string m_authKey; std::string m_sak; std::string m_sci; - std::string m_ssci; + std::string m_ssciStr; std::string m_salt; macsec_an_t m_an; macsec_pn_t m_pn; + macsec_ssci_t m_ssci; bool m_sendSci; bool m_encryptionEnable; diff --git a/vslib/MACsecManager.cpp b/vslib/MACsecManager.cpp index 6688bad41..0324c1b48 100644 --- a/vslib/MACsecManager.cpp +++ b/vslib/MACsecManager.cpp @@ -450,7 +450,7 @@ bool MACsecManager::create_macsec_egress_sa( << ( attr.is_xpn() ? " xpn " : " pn ") << attr.m_pn << ( attr.is_xpn() ? " ssci " : "" ) - << ( attr.is_xpn() ? attr.m_ssci : "" ) + << ( attr.is_xpn() ? attr.m_ssciStr : "" ) << ( attr.is_xpn() ? " salt " : "" ) << ( attr.is_xpn() ? attr.m_salt : "" ) << " on key " @@ -487,7 +487,7 @@ bool MACsecManager::create_macsec_ingress_sa( << ( attr.is_xpn() ? " xpn " : " pn " ) << attr.m_pn << ( attr.is_xpn() ? " ssci " : "" ) - << ( attr.is_xpn() ? attr.m_ssci : "" ) + << ( attr.is_xpn() ? attr.m_ssciStr : "" ) << ( attr.is_xpn() ? " salt " : "" ) << ( attr.is_xpn() ? attr.m_salt : "" ) << " on key " diff --git a/vslib/Makefile.am b/vslib/Makefile.am index ab6b68a31..36ccd1f4f 100644 --- a/vslib/Makefile.am +++ b/vslib/Makefile.am @@ -5,6 +5,10 @@ lib_LTLIBRARIES = libsaivs.la noinst_LIBRARIES = libSaiVS.a libSaiVS_a_SOURCES = \ + vppxlate/SaiAclStats.c \ + vppxlate/SaiIntfStats.c \ + vppxlate/SaiVppStats.c \ + vppxlate/SaiVppXlate.c \ Buffer.cpp \ ContextConfigContainer.cpp \ ContextConfig.cpp \ @@ -54,10 +58,21 @@ libSaiVS_a_SOURCES = \ SwitchStateBaseFdb.cpp \ SwitchStateBaseHostif.cpp \ SwitchStateBaseMACsec.cpp \ + SaiObjectDB.cpp \ + SwitchStateBaseFdbVpp.cpp \ + SwitchStateBaseAcl.cpp \ + SwitchStateBaseBfd.cpp \ + SwitchStateBaseNbr.cpp \ + SwitchStateBaseNexthop.cpp \ + SwitchStateBaseRif.cpp \ + SwitchStateBaseRoute.cpp \ + SwitchStateBaseUtils.cpp \ + TunnelManager.cpp \ SwitchState.cpp \ TrafficFilterPipes.cpp \ TrafficForwarder.cpp \ VirtualSwitchSaiInterface.cpp \ + VirtualSwitchSaiInterfaceVpp.cpp \ VirtualSwitchSaiInterfaceFdb.cpp \ VirtualSwitchSaiInterfacePort.cpp diff --git a/vslib/SwitchStateBase.cpp b/vslib/SwitchStateBase.cpp index 8fa4d7761..6d8e3c32b 100644 --- a/vslib/SwitchStateBase.cpp +++ b/vslib/SwitchStateBase.cpp @@ -8,6 +8,8 @@ #include +extern bool g_vpp; + #define SAI_VS_MAX_PORTS 1024 using namespace saivs; @@ -17,7 +19,9 @@ SwitchStateBase::SwitchStateBase( _In_ std::shared_ptr manager, _In_ std::shared_ptr config): SwitchState(switch_id, config), - m_realObjectIdManager(manager) + m_realObjectIdManager(manager), + m_object_db(this), + m_tunnel_mgr(this) { SWSS_LOG_ENTER(); @@ -30,12 +34,19 @@ SwitchStateBase::SwitchStateBase( _In_ std::shared_ptr config, _In_ std::shared_ptr warmBootState): SwitchState(switch_id, config), - m_realObjectIdManager(manager) + m_realObjectIdManager(manager), + m_object_db(this), + m_tunnel_mgr(this) { SWSS_LOG_ENTER(); m_macsecManager.cleanup_macsec_device(); + if (g_vpp) + { + vpp_dp_initialize(); + } + if (warmBootState) { for (auto& kvp: warmBootState->m_objectHash) @@ -158,6 +169,57 @@ sai_status_t SwitchStateBase::create( return createHostif(object_id, switch_id, attr_count, attr_list); } + if (g_vpp) // VPP + { + if (object_type == SAI_OBJECT_TYPE_ROUTER_INTERFACE) + { + sai_object_id_t object_id; + sai_deserialize_object_id(serializedObjectId, object_id); + return createRouterif(object_id, switch_id, attr_count, attr_list); + } + + if (object_type == SAI_OBJECT_TYPE_ROUTE_ENTRY) + { + return addIpRoute(serializedObjectId, switch_id, attr_count, attr_list); + } + + if (object_type == SAI_OBJECT_TYPE_NEXT_HOP) + { + return createNexthop(serializedObjectId, switch_id, attr_count, attr_list); + } + + if (object_type == SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER) + { + return createNexthopGroupMember(serializedObjectId, switch_id, attr_count, attr_list); + } + + if (object_type == SAI_OBJECT_TYPE_NEIGHBOR_ENTRY) + { + return addIpNbr(serializedObjectId, switch_id, attr_count, attr_list); + } + + if (object_type == SAI_OBJECT_TYPE_ACL_ENTRY) + { + sai_object_id_t object_id; + sai_deserialize_object_id(serializedObjectId, object_id); + return createAclEntry(object_id, switch_id, attr_count, attr_list); + } + + if (object_type == SAI_OBJECT_TYPE_ACL_TABLE) + { + sai_object_id_t object_id; + sai_deserialize_object_id(serializedObjectId, object_id); + return aclTableCreate(object_id, switch_id, attr_count, attr_list); + } + + if (object_type == SAI_OBJECT_TYPE_ACL_TABLE_GROUP_MEMBER) + { + sai_object_id_t object_id; + sai_deserialize_object_id(serializedObjectId, object_id); + return createAclGrpMbr(object_id, switch_id, attr_count, attr_list); + } + } + if (object_type == SAI_OBJECT_TYPE_MACSEC_PORT) { sai_object_id_t object_id; @@ -185,6 +247,26 @@ sai_status_t SwitchStateBase::create( return createVoqSystemNeighborEntry(serializedObjectId, switch_id, attr_count, attr_list); } + if (g_vpp) // VPP + { + if (object_type == SAI_OBJECT_TYPE_VLAN_MEMBER) + { + sai_object_id_t object_id; + sai_deserialize_object_id(serializedObjectId, object_id); + return createVlanMember(object_id, switch_id, attr_count, attr_list); + } + + if (object_type == SAI_OBJECT_TYPE_FDB_ENTRY) + { + return FdbEntryadd(serializedObjectId, switch_id, attr_count, attr_list); + } + + if (object_type == SAI_OBJECT_TYPE_BFD_SESSION) + { + return bfd_session_add(serializedObjectId, switch_id, attr_count, attr_list); + } + } + return create_internal(object_type, serializedObjectId, switch_id, attr_count, attr_list); } @@ -250,6 +332,11 @@ sai_status_t SwitchStateBase::create_internal( objectHash[serializedObjectId][a->getAttrMetadata()->attridname] = a; } + if (g_vpp) // VPP + { + m_object_db.create_or_update(object_type, serializedObjectId, attr_count, attr_list, true /*is_create*/); + } + return SAI_STATUS_SUCCESS; } @@ -300,6 +387,11 @@ sai_status_t SwitchStateBase::createPort( { SWSS_LOG_ENTER(); + if (g_vpp) + { + UpdatePort(object_id, attr_count, attr_list); + } + auto sid = sai_serialize_object_id(object_id); CHECK_STATUS(create_internal(SAI_OBJECT_TYPE_PORT, sid, switch_id, attr_count, attr_list)); @@ -379,6 +471,63 @@ sai_status_t SwitchStateBase::remove( return removeHostif(objectId); } + if (g_vpp) // VPP + { + if (object_type == SAI_OBJECT_TYPE_ROUTER_INTERFACE) + { + sai_object_id_t objectId; + sai_deserialize_object_id(serializedObjectId, objectId); + return removeRouterif(objectId); + } + + if (object_type == SAI_OBJECT_TYPE_VIRTUAL_ROUTER) + { + sai_object_id_t objectId; + sai_deserialize_object_id(serializedObjectId, objectId); + return removeVrf(objectId); + } + + if (object_type == SAI_OBJECT_TYPE_ROUTE_ENTRY) + { + return removeIpRoute(serializedObjectId); + } + + if (object_type == SAI_OBJECT_TYPE_NEXT_HOP) + { + return removeNexthop(serializedObjectId); + } + + if (object_type == SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER) + { + return removeNexthopGroupMember(serializedObjectId); + } + + if (object_type == SAI_OBJECT_TYPE_NEIGHBOR_ENTRY) + { + return removeIpNbr(serializedObjectId); + } + + if (object_type == SAI_OBJECT_TYPE_ACL_ENTRY) + { + return removeAclEntry(serializedObjectId); + } + + if (object_type == SAI_OBJECT_TYPE_ACL_TABLE) + { + return aclTableRemove(serializedObjectId); + } + + if (object_type == SAI_OBJECT_TYPE_ACL_TABLE_GROUP_MEMBER) + { + return removeAclGrpMbr(serializedObjectId); + } + + if (object_type == SAI_OBJECT_TYPE_ACL_TABLE_GROUP) + { + return removeAclGrp(serializedObjectId); + } + } + if (object_type == SAI_OBJECT_TYPE_MACSEC_PORT) { sai_object_id_t objectId; @@ -398,6 +547,24 @@ sai_status_t SwitchStateBase::remove( return removeMACsecSA(objectId); } + if (g_vpp) // VPP + { + if (object_type == SAI_OBJECT_TYPE_VLAN_MEMBER) + { + sai_object_id_t objectId; + sai_deserialize_object_id(serializedObjectId, objectId); + return removeVlanMember(objectId); + } + else if (object_type == SAI_OBJECT_TYPE_FDB_ENTRY) + { + return FdbEntrydel(serializedObjectId); + } + else if (object_type == SAI_OBJECT_TYPE_BFD_SESSION) + { + return bfd_session_del(serializedObjectId); + } + } + return remove_internal(object_type, serializedObjectId); } @@ -409,6 +576,11 @@ sai_status_t SwitchStateBase::remove_internal( SWSS_LOG_INFO("removing object: %s", serializedObjectId.c_str()); + if (g_vpp) // VPP + { + m_object_db.remove(object_type, serializedObjectId); + } + auto &objectHash = m_objectHash.at(object_type); auto it = objectHash.find(serializedObjectId); @@ -433,6 +605,15 @@ sai_status_t SwitchStateBase::setPort( { SWSS_LOG_ENTER(); + if (g_vpp) // VPP + { + UpdatePort(portId, 1, attr); + + auto sid = sai_serialize_object_id(portId); + + return set_internal(SAI_OBJECT_TYPE_PORT, sid, attr); + } + if (attr && attr->id == SAI_PORT_ATTR_ADMIN_STATE && m_switchConfig->m_useTapDevice) { bool up = attr->value.booldata; @@ -498,6 +679,27 @@ sai_status_t SwitchStateBase::setAclEntry( auto sid = sai_serialize_object_id(entry_id); + if (g_vpp) // VPP + { + set_internal(SAI_OBJECT_TYPE_ACL_ENTRY, sid, attr); + + sai_object_id_t tbl_oid; + + if (getAclTableId(entry_id, &tbl_oid) != SAI_STATUS_SUCCESS) + { + return SAI_STATUS_FAILURE; + } + + auto status = AclAddRemoveCheck(tbl_oid); + + SWSS_LOG_NOTICE("ACL entry %s set in table %s set status %d", + sid.c_str(), + sai_serialize_object_id(tbl_oid).c_str(), + status); + + return status; + } + return set_internal(SAI_OBJECT_TYPE_ACL_ENTRY, sid, attr); } @@ -515,6 +717,45 @@ sai_status_t SwitchStateBase::set( return setPort(objectId, attr); } + if (g_vpp) // VPP + { + if (objectType == SAI_OBJECT_TYPE_ROUTER_INTERFACE) + { + sai_object_id_t objectId; + sai_deserialize_object_id(serializedObjectId, objectId); + return vpp_update_router_interface(objectId, 1, attr); + } + + if (objectType == SAI_OBJECT_TYPE_ACL_TABLE_GROUP_MEMBER) + { + sai_object_id_t objectId; + sai_deserialize_object_id(serializedObjectId, objectId); + return setAclGrpMbr(objectId, attr); + } + + if (objectType == SAI_OBJECT_TYPE_ROUTE_ENTRY) + { + return updateIpRoute(serializedObjectId, attr); + } + + if (objectType == SAI_OBJECT_TYPE_SWITCH) + { + switch(attr->id) + { + case SAI_SWITCH_ATTR_VXLAN_DEFAULT_ROUTER_MAC: + { + m_tunnel_mgr.set_router_mac(attr); + break; + } + case SAI_SWITCH_ATTR_VXLAN_DEFAULT_PORT: + { + m_tunnel_mgr.set_vxlan_port(attr); + break; + } + } + } + } + if (objectType == SAI_OBJECT_TYPE_ACL_ENTRY) { sai_object_id_t objectId; @@ -539,6 +780,12 @@ sai_status_t SwitchStateBase::set_internal( { SWSS_LOG_ENTER(); + if (g_vpp) // VPP + { + //Update child-parent relationship before updating the attribute + m_object_db.create_or_update(objectType, serializedObjectId, 1, attr, false /*is_create*/); + } + auto it = m_objectHash.at(objectType).find(serializedObjectId); if (it == m_objectHash.at(objectType).end()) @@ -593,6 +840,16 @@ sai_status_t SwitchStateBase::get( { SWSS_LOG_ENTER(); + if (g_vpp) // VPP + { + if (objectType == SAI_OBJECT_TYPE_ACL_COUNTER) + { + sai_object_id_t object_id; + + sai_deserialize_object_id(serializedObjectId, object_id); + return getAclEntryStats(object_id, attr_count, attr_list); + } + } const auto &objectHash = m_objectHash.at(objectType); auto it = objectHash.find(serializedObjectId); @@ -664,6 +921,11 @@ sai_status_t SwitchStateBase::get( if (ait == attrHash.end()) { + if (g_vpp) + { + return SAI_STATUS_ITEM_NOT_FOUND; + } + SWSS_LOG_WARN("%s not implemented on %s", meta->attridname, serializedObjectId.c_str()); @@ -735,7 +997,14 @@ sai_status_t SwitchStateBase::bulkCreate( for (it = 0; it < object_count; it++) { - object_statuses[it] = create(object_type, serialized_object_ids[it], switch_id, attr_count[it], attr_list[it]); + if (g_vpp) // VPP + { + object_statuses[it] = create_internal(object_type, serialized_object_ids[it], switch_id, attr_count[it], attr_list[it]); + } + else + { + object_statuses[it] = create(object_type, serialized_object_ids[it], switch_id, attr_count[it], attr_list[it]); + } if (object_statuses[it] != SAI_STATUS_SUCCESS) { @@ -779,7 +1048,14 @@ sai_status_t SwitchStateBase::bulkRemove( for (it = 0; it < object_count; it++) { - object_statuses[it] = remove(object_type, serialized_object_ids[it]); + if (g_vpp) // VPP + { + object_statuses[it] = remove_internal(object_type, serialized_object_ids[it]); + } + else + { + object_statuses[it] = remove(object_type, serialized_object_ids[it]); + } if (object_statuses[it] != SAI_STATUS_SUCCESS) { @@ -3864,3 +4140,107 @@ sai_status_t SwitchStateBase::queryAttributeCapability( return SAI_STATUS_SUCCESS; } + +// VPP + +sai_status_t SwitchStateBase::get( + _In_ sai_object_type_t objectType, + _In_ const std::string &serializedObjectId, + _In_ const uint32_t max_attr_count, + _Out_ uint32_t *attr_count, + _Out_ sai_attribute_t *attr_list) +{ + SWSS_LOG_ENTER(); + + *attr_count = 0; + + const auto &objectHash = m_objectHash.at(objectType); + + auto it = objectHash.find(serializedObjectId); + + if (it == objectHash.end()) + { + SWSS_LOG_ERROR("not found %s:%s", + sai_serialize_object_type(objectType).c_str(), + serializedObjectId.c_str()); + + return SAI_STATUS_ITEM_NOT_FOUND; + } + + /* + * We need reference here since we can potentially update attr hash for RO + * object. + */ + + auto& attrHash = it->second; + + /* + * Some of the list query maybe for length, so we can't do + * normal serialize, maybe with count only. + */ + + sai_status_t final_status = SAI_STATUS_SUCCESS, status; + uint32_t idx = 0; + sai_attribute_t *dst_attr; + + for (auto &kvp: attrHash) + { + auto attr = kvp.second->getAttr(); + + dst_attr = &attr_list[idx]; + dst_attr->id = attr->id; + + status = transfer_attributes(objectType, 1, attr, dst_attr, false); + + if (status == SAI_STATUS_BUFFER_OVERFLOW) + { + /* + * This is considered partial success, since we get correct list + * length. Note that other items ARE processes on the list. + */ + + SWSS_LOG_NOTICE("BUFFER_OVERFLOW %s: %d", + serializedObjectId.c_str(), + attr->id); + + /* + * We still continue processing other attributes for get as long as + * we only will be getting buffer overflow error. + */ + + final_status = status; + continue; + } + + if (status != SAI_STATUS_SUCCESS) + { + // all other errors + + SWSS_LOG_ERROR("get failed %s: %d: %s", + serializedObjectId.c_str(), + attr->id, + sai_serialize_status(status).c_str()); + + return status; + } + + ++idx; + + if (idx == max_attr_count) + break; + } + + *attr_count = idx; + + return final_status; +} + +std::shared_ptr SwitchStateBase::get_sai_object( + _In_ sai_object_type_t object_type, + _In_ const std::string &serializedObjectId) +{ + SWSS_LOG_ENTER(); + + return m_object_db.get(object_type, serializedObjectId); +} + diff --git a/vslib/SwitchStateBase.h b/vslib/SwitchStateBase.h index 22e111a34..1b2df5c02 100644 --- a/vslib/SwitchStateBase.h +++ b/vslib/SwitchStateBase.h @@ -9,9 +9,19 @@ #include "EventPayloadNetLinkMsg.h" #include "MACsecManager.h" +// VPP +#include "IpVrfInfo.h" +#include "SaiObjectDB.h" +#include "BitResourcePool.h" +#include "TunnelManager.h" +#include "SwitchStateBaseNexthop.h" +#include "SwitchStateBaseAcl.h" +#include "vppxlate/SaiVppXlate.h" + #include #include #include +#include #define SAI_VS_FDB_INFO "SAI_VS_FDB_INFO" @@ -23,6 +33,9 @@ sai_status_t _status = (status); \ if (_status != SAI_STATUS_SUCCESS) { return _status; } } +// VPP +#define BFD_MUTEX std::lock_guard lock(bfdMapMutex); + namespace saivs { class SwitchStateBase: @@ -111,8 +124,10 @@ namespace saivs _In_ const sai_system_port_config_t *sys_port_cfg_list); sai_status_t create_voqs(); + sai_status_t create_voq_per_sysport( _In_ sai_object_id_t sys_port_id); + sai_status_t set_system_port_list(); public: @@ -121,6 +136,125 @@ namespace saivs _In_ uint32_t attr_count, _In_ const sai_attribute_t *attr_list); + public: // VPP + + sai_status_t vpp_dp_initialize(); + + sai_status_t vpp_create_default_1q_bridge(); + + sai_status_t createVlanMember( + _In_ sai_object_id_t object_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + sai_status_t vpp_create_vlan_member( + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + sai_status_t removeVlanMember( + _In_ sai_object_id_t objectId); + + sai_status_t vpp_remove_vlan_member( + _In_ sai_object_id_t vlan_member_oid); + + sai_status_t vpp_create_bvi_interface( + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + sai_status_t vpp_delete_bvi_interface( + _In_ sai_object_id_t bvi_obj_id); + + /* FDB Entry and Flush SAI Objects */ + sai_status_t FdbEntryadd( + _In_ const std::string &serializedObjectId, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + sai_status_t vpp_fdbentry_add( + _In_ const std::string &serializedObjectId, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + sai_status_t FdbEntrydel( + _In_ const std::string &serializedObjectId); + + sai_status_t vpp_fdbentry_del( + _In_ const std::string &serializedObjectId); + + sai_status_t vpp_fdbentry_flush( + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + /* BFD Session */ + sai_status_t bfd_session_add( + _In_ const std::string &serializedObjectId, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + sai_status_t vpp_bfd_session_add( + _In_ const std::string &serializedObjectId, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + sai_status_t bfd_session_del( + _In_ const std::string &serializedObjectId); + + sai_status_t vpp_bfd_session_del( + _In_ const std::string &serializedObjectId); + + private: // VPP // BFD related + + typedef struct _vpp_bfd_info_t // TODO to separate file + { + //uint32_t sw_if_index; + bool multihop; + sai_ip_address_t local_addr; + sai_ip_address_t peer_addr; + + // Define the < operator for comparison + bool operator<(const _vpp_bfd_info_t& other) const + { + // compare local IP address first + int cmp = std::memcmp(&local_addr, &other.local_addr, sizeof(sai_ip_address_t)); + + if (cmp != 0) + { + return cmp < 0; + } + + // compare peer IP address + cmp = std::memcmp(&peer_addr, &other.peer_addr, sizeof(sai_ip_address_t)); + + if (cmp != 0) + { + return cmp < 0; + } + + // compare multihop flag + return multihop < other.multihop; + } + } vpp_bfd_info_t; + + std::map m_bfd_info_map; + std::mutex bfdMapMutex; + + void send_bfd_state_change_notification( + _In_ sai_object_id_t bfd_oid, + _In_ sai_bfd_session_state_t state, + _In_ bool force); + + void update_bfd_session_state( + _In_ sai_object_id_t bfd_oid, + _In_ sai_bfd_session_state_t state); + + sai_status_t asyncBfdStateUpdate(vpp_bfd_state_notif_t *bfd_notif); + protected: virtual sai_status_t create_port_dependencies( @@ -272,6 +406,16 @@ namespace saivs _In_ uint32_t attr_count, _Out_ sai_attribute_t *attr_list); + public: // VPP + virtual sai_status_t get( + _In_ sai_object_type_t objectType, + _In_ const std::string &serializedObjectId, + _In_ const uint32_t max_attr_count, + _Out_ uint32_t *attr_count, + _Out_ sai_attribute_t *attr_list); + + public: + virtual sai_status_t bulkCreate( _In_ sai_object_id_t switch_id, _In_ sai_object_type_t object_type, @@ -294,7 +438,7 @@ namespace saivs _In_ sai_bulk_op_error_mode_t mode, _Out_ sai_status_t *object_statuses); - virtual sai_status_t queryAttrEnumValuesCapability( + virtual sai_status_t queryAttrEnumValuesCapability( _In_ sai_object_id_t switch_id, _In_ sai_object_type_t object_type, _In_ sai_attr_id_t attr_id, @@ -306,6 +450,12 @@ namespace saivs _In_ sai_attr_id_t attr_id, _Out_ sai_attr_capability_t *attr_capability); + public: // VPP + + std::shared_ptr get_sai_object( + _In_ sai_object_type_t object_type, + _In_ const std::string &serialized_object_id); + protected: virtual sai_status_t remove_internal( @@ -715,5 +865,555 @@ namespace saivs std::map> m_hostif_info_map; std::shared_ptr m_realObjectIdManager; + + public: // VPP + + friend class TunnelManager; + + private: // VPP + + SaiObjectDB m_object_db; + TunnelManager m_tunnel_mgr; + + private: // VPP + + std::map> vrf_objMap; + bool nbr_env_read = false; + bool nbr_active = false; + std::map m_intf_prefix_map; + std::unordered_map lpbInstMap; + std::unordered_map lpbIpToHostIfMap; + std::unordered_map lpbIpToIfMap; + std::unordered_map lpbHostIfToVppIfMap; + + protected: // VPP + + sai_status_t fillNHGrpMember( + nexthop_grp_member_t *nxt_grp_member, + sai_object_id_t next_hop_oid, + uint32_t next_hop_weight, + uint32_t next_hop_sequence); + + sai_status_t IpRouteNexthopGroupEntry( + _In_ sai_object_id_t next_hop_grp_oid, + _Out_ nexthop_grp_config_t **nxthop_group); + + sai_status_t IpRouteNexthopEntry( + _In_ sai_object_id_t next_hop_oid, + _Out_ nexthop_grp_config_t **nxthop_group_cfg); + + sai_status_t createNexthop( + _In_ const std::string& serializedObjectId, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + sai_status_t removeNexthop( + _In_ const std::string &serializedObjectId); + + sai_status_t createNexthopGroupMember( + _In_ const std::string& serializedObjectId, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + sai_status_t removeNexthopGroupMember( + _In_ const std::string& serializedObjectId); + + protected: // VPP + + sai_status_t createRouterif( + _In_ sai_object_id_t object_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + sai_status_t removeRouterif( + _In_ sai_object_id_t objectId); + + sai_status_t vpp_create_router_interface( + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + sai_status_t vpp_update_router_interface( + _In_ sai_object_id_t object_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + sai_status_t vpp_remove_router_interface( + _In_ sai_object_id_t objectId); + + sai_status_t vpp_router_interface_remove_vrf( + _In_ sai_object_id_t obj_id); + + sai_status_t vpp_add_del_intf_ip_addr ( + _In_ sai_ip_prefix_t& ip_prefix, + _In_ sai_object_id_t nexthop_oid, + _In_ bool is_add); + + sai_status_t vpp_add_del_intf_ip_addr_norif ( + _In_ const std::string& ip_prefix_key, + _In_ sai_route_entry_t& route_entry, + _In_ bool is_add); + + sai_status_t vpp_interface_ip_address_update ( + _In_ const char *hw_ifname, + _In_ const std::string &serializedObjectId, + _In_ bool is_add); + + sai_status_t process_interface_loopback ( + _In_ const std::string &serializedObjectId, + _In_ bool &isLoopback, + _In_ bool is_add); + + sai_status_t vpp_add_lpb_intf_ip_addr ( + _In_ const std::string &serializedObjectId); + + sai_status_t vpp_del_lpb_intf_ip_addr ( + _In_ const std::string &serializedObjectId); + + sai_status_t vpp_get_router_intf_name ( + _In_ sai_ip_prefix_t& ip_prefix, + _In_ sai_object_id_t rif_id, + std::string& nexthop_ifname); + + int getNextLoopbackInstance(); + + void markLoopbackInstanceDeleted( + _In_ int instance); + + bool vpp_intf_get_prefix_entry( + _In_ const std::string& intf_name, + _In_ std::string& ip_prefix); + + void vpp_intf_remove_prefix_entry( + _Inout_ const std::string& intf_name); + + sai_status_t asyncIntfStateUpdate( + _In_ const char *hwif_name, + _In_ bool link_up); + + sai_status_t vpp_set_interface_state ( + _In_ sai_object_id_t object_id, + _In_ uint32_t vlan_id, + _In_ bool is_up); + sai_status_t vpp_set_port_mtu ( + _In_ sai_object_id_t object_id, + _In_ uint32_t vlan_id, + _In_ uint32_t mtu); + sai_status_t vpp_set_interface_mtu ( + _In_ sai_object_id_t object_id, + _In_ uint32_t vlan_id, + _In_ uint32_t mtu, + _In_ int type); + + sai_status_t UpdatePort( + _In_ sai_object_id_t object_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + sai_status_t removeVrf( + _In_ sai_object_id_t objectId); + + std::shared_ptr vpp_get_ip_vrf( + _In_ sai_object_id_t objectId); + + sai_status_t addRemoveIpNbr( + _In_ const std::string &serializedObjectId, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list, + _In_ bool is_add); + + sai_status_t addIpNbr( + _In_ const std::string &serializedObjectId, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + sai_status_t removeIpNbr( + _In_ const std::string &serializedObjectId); + + bool is_ip_nbr_active(); + + sai_status_t addIpRoute( + _In_ const std::string &serializedObjectId, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + sai_status_t removeIpRoute( + _In_ const std::string &serializedObjectId); + + sai_status_t IpRouteNexthopEntry( + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list, + sai_ip_address_t *ip_address, + sai_object_id_t *next_rif_oid); + + std::string convertIPToString( + _In_ const sai_ip_addr_t &ipAddress); + + std::string convertIPv6ToString( + _In_ const sai_ip_addr_t &ipAddress, + _In_ int ipFamily); + + std::string extractDestinationIP( + _In_ const std::string &serializedObjectId); + + unsigned long ipToInteger( + _In_ const std::string &ipAddress); + + sai_status_t IpRouteAddRemove( + _In_ const SaiObject* route_obj, + _In_ bool is_add); + + sai_status_t updateIpRoute( + _In_ const std::string &serializedObjectId, + _In_ const sai_attribute_t *attr_list); + + int vpp_add_ip_vrf( + _In_ sai_object_id_t objectId, + _In_ uint32_t vrf_id); + + int vpp_del_ip_vrf( + _In_ sai_object_id_t objectId); + + int vpp_get_vrf_id( + _In_ const char *linux_ifname, + _Out_ uint32_t *vrf_id); + + private: // VPP + + typedef struct vpp_ace_cntr_info_ // TODO to separate file + { + sai_object_id_t tbl_oid; + sai_object_id_t ace_oid; + uint32_t acl_index; + uint32_t ace_index; + + } vpp_ace_cntr_info_t; + + std::map> m_acl_tbl_rules_map; + std::map> m_acl_tbl_hw_ports_map; + std::map m_acl_swindex_map; + std::map m_tunterm_acl_swindex_map; + std::map> m_acl_tbl_grp_mbr_map; + std::map> m_acl_tbl_grp_ports_map; + std::map m_ace_cntr_info_map; + + protected: // VPP + + sai_status_t createAclEntry( + _In_ sai_object_id_t object_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + sai_status_t removeAclEntry( + _In_ const std::string &serializedObjectId); + + sai_status_t addRemoveAclEntrytoMap( + _In_ sai_object_id_t entry_id, + _In_ sai_object_id_t tbl_oid, + _In_ bool is_add); + + sai_status_t getAclTableId( + _In_ sai_object_id_t entry_id, sai_object_id_t *tbl_oid); + + sai_status_t AclTblConfig( + _In_ sai_object_id_t tbl_oid); + + sai_status_t AclTblRemove( + _In_ sai_object_id_t tbl_oid); + + sai_status_t AclAddRemoveCheck( + _In_ sai_object_id_t tbl_oid); + + sai_status_t aclTableRemove( + _In_ const std::string &serializedObjectId); + + /** + * @brief Retrieves ACEs and list of ordered ACE info for a given table. + * + * @param[in] tbl_oid The object ID of the table for which to retrieve ACEs. + * @param[out] n_total_entries The total number of ACEs. + * @param[out] aces Pointer to the array of ACEs. + * @param[out] ordered_aces Ordered ACE info list. + * @return SAI_STATUS_SUCCESS on success, or an appropriate error code otherwise. + */ + sai_status_t get_sorted_aces( + _In_ sai_object_id_t tbl_oid, + _Out_ size_t &n_total_entries, + _Out_ acl_tbl_entries_t *&aces, + _Out_ std::list &ordered_aces); + + /** + * @brief Cleans up AclTblConfig variables. + * + * @param[in] aces Pointer to the ACEs to be cleaned up. + * @param[in] ordered_aces Ordered ACE list to be cleaned up. + * @param[in] acl Pointer to the VS ACL to be cleaned up. + * @param[in] tunterm_acl Pointer to the VS tunnel termination ACL to be cleaned up. + */ + void cleanup_acl_tbl_config( + _In_ acl_tbl_entries_t *&aces, + _In_ std::list &ordered_aces, + _In_ vpp_acl_t *&acl, + _In_ vpp_tunterm_acl_t *&tunterm_acl); + + /** + * @brief Fills ACL and tunnel termination ACL rules based on the provided ACEs. + * + * @param[in] aces Pointer to ACEs. + * @param[in] ordered_aces Reference to Ordered ACE list. + * @param[in] acl Pointer to the allocated VS ACL. + * @param[in] tunterm_acl Pointer to the allocated VS tunnel termination ACL. + * @return SAI_STATUS_SUCCESS on success, or an appropriate error code otherwise. + */ + sai_status_t fill_acl_rules( + _In_ acl_tbl_entries_t *aces, + _In_ std::list &ordered_aces, + _In_ vpp_acl_t *acl, + _In_ vpp_tunterm_acl_t *tunterm_acl); + + /** + * @brief Creates or replaces the provided ACL in VS. + * + * @param[in] acl Pointer to the VS ACL to be added or replaced. + * @param[in] tbl_oid Object ID of the ACL table where the entry will be added or replaced. + * @param[in] aces Pointer to the ACEs. + * @param[in] ordered_aces Ordered ACE list. + * @return SAI_STATUS_SUCCESS on success, or an appropriate error code otherwise. + */ + sai_status_t acl_add_replace( + _In_ vpp_acl_t *&acl, + _In_ sai_object_id_t tbl_oid, + _In_ acl_tbl_entries_t *aces, + _In_ std::list &ordered_aces); + + /** + * @brief Allocates memory for VS ACL. + * + * @param[in] n_entries Number of entries in the ACL. + * @param[in] tbl_oid Object ID of the table to which the ACL belongs. + * @param[out] acl_name Name of the allocated ACL. + * @param[out] acl Pointer to the allocated ACL. + * @return SAI_STATUS_SUCCESS on success, or an appropriate error code otherwise. + */ + sai_status_t allocate_acl( + _In_ size_t n_entries, + _In_ sai_object_id_t tbl_oid, + _Out_ char (&acl_name)[64], + _Out_ vpp_acl_t *&acl); + + /** + * @brief Allocates memory for VS tunnel termination ACL. + * + * @param[in] n_tunterm_entries Number of tunnel termination entries to allocate. + * @param[in] tbl_oid Object ID of the ACL table. + * @param[out] acl_name Name of the allocated ACL. + * @param[out] tunterm_acl Pointer to the allocated tunnel termination ACL. + * @return SAI_STATUS_SUCCESS on success, or an appropriate error code otherwise. + */ + sai_status_t allocate_tunterm_acl( + _In_ size_t n_tunterm_entries, + _In_ sai_object_id_t tbl_oid, + _Out_ char (&acl_name)[64], + _Out_ vpp_tunterm_acl_t *&tunterm_acl); + + /** + * @brief Counts the total number of ACL rules and tunnel termination ACL rules, and sets is_tunterm in the ordered ACE list. + * + * @param[in] aces Pointer to ACEs. + * @param[in] ordered_aces Reference to the ordered ACE list. + * @param[out] n_entries Reference to the number of ACL entries. + * @param[out] n_tunterm_entries Reference to the number of tunnel termination ACL entries. + */ + void count_tunterm_acl_rules( + _In_ acl_tbl_entries_t *aces, + _In_ std::list &ordered_aces, + _Out_ size_t &n_entries, + _Out_ size_t &n_tunterm_entries); + + /** + * @brief Deletes the hardware ports map associated with the given table object ID. + * + * @param[in] tbl_oid The object ID of the table whose hardware ports map is to be deleted. + * @return SAI_STATUS_SUCCESS on success, or an appropriate error code otherwise. + */ + sai_status_t tbl_hw_ports_map_delete( + _In_ sai_object_id_t tbl_oid); + + /** + * @brief Deletes a tunnel termination ACL in VS. + * + * @param[in] tbl_oid The object ID of the ACL table. + * @param[in] table_delete Boolean flag indicating whether the overall ACL table is being deleted. + * @return SAI_STATUS_SUCCESS on success, or an appropriate error code otherwise. + */ + sai_status_t tunterm_acl_delete( + _In_ sai_object_id_t tbl_oid, + _In_ bool table_delete); + + /** + * @brief Creates or replaces the provided tunnel termination ACL in VS. + * + * @param[in] acl Pointer to the tunnel termination ACL. + * @param[in] tbl_oid Object ID of the ACL table where the entry will be added or replaced. + * @return SAI_STATUS_SUCCESS on success, or an appropriate error code otherwise. + */ + sai_status_t tunterm_acl_add_replace( + _In_ vpp_tunterm_acl_t *acl, + _In_ sai_object_id_t tbl_oid); + + /** + * @brief Sets the redirect action for a tunnel termination ACL rule. + * + * @param[in] attr_id The ID of the SAI attribute to be updated. + * @param[in] value Pointer to the SAI attribute value. + * @param[in] rule Pointer to the tunnel termination ACL rule to be updated. + * @return SAI_STATUS_SUCCESS on success, or an appropriate error code otherwise. + */ + sai_status_t tunterm_set_action_redirect( + _In_ sai_acl_entry_attr_t attr_id, + _In_ const sai_attribute_value_t *value, + _In_ vpp_tunterm_acl_rule_t *rule); + + /** + * @brief Updates an ACE field for a tunnel termination ACL rule. + * + * @param[in] attr_id The ID of the SAI attribute to be updated. + * @param[in] value Pointer to the SAI attribute value. + * @param[in] rule Pointer to the tunnel termination ACL rule to be updated. + * @return SAI_STATUS_SUCCESS on success, or an appropriate error code otherwise. + */ + sai_status_t tunterm_acl_rule_field_update( + _In_ sai_acl_entry_attr_t attr_id, + _In_ const sai_attribute_value_t *value, + _In_ vpp_tunterm_acl_rule_t *rule); + + /** + * @brief Binds or unbinds a tunnel termination ACL table to/from an interface. + * + * @param[in] tbl_oid The object ID of the ACL table to be bound or unbound. + * @param[in] is_add A boolean flag indicating whether to bind (true) or unbind (false) the ACL table. + * @param[in] hwif_name The name of the hardware interface to which the ACL table is to be bound or from which it is to be unbound. + * @return SAI_STATUS_SUCCESS on success, or an appropriate error code otherwise. + */ + sai_status_t tunterm_acl_bindunbind( + _In_ sai_object_id_t tbl_oid, + _In_ bool is_add, + _In_ std::string hwif_name); + + sai_status_t aclTableCreate( + _In_ sai_object_id_t object_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + sai_status_t aclDefaultAllowConfigure( + _In_ sai_object_id_t tbl_oid); + + sai_status_t acl_rule_range_get( + _In_ const sai_object_list_t *range_list, + _Out_ sai_u32_range_t *range_limit_list, + _Out_ sai_acl_range_type_t *range_type_list, + _Out_ uint32_t *range_count); + + sai_status_t acl_range_attr_get( + _In_ const std::string &serializedObjectId, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list, + _Out_ sai_attribute_t *attr_range); + + sai_status_t removeAclGrp( + _In_ const std::string &serializedObjectId); + + sai_status_t setAclGrpMbr( + _In_ sai_object_id_t member_oid, + _In_ const sai_attribute_t* attr); + + sai_status_t removeAclGrpMbr( + _In_ const std::string &serializedObjectId); + + sai_status_t createAclGrpMbr( + _In_ sai_object_id_t object_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + sai_status_t addRemoveAclGrpMbr( + _In_ sai_object_id_t member_id, + _In_ sai_object_id_t tbl_grp_oid, + _In_ bool is_add); + + sai_status_t getAclTableGroupId( + _In_ sai_object_id_t member_id, + _Out_ sai_object_id_t *tbl_grp_oid); + + sai_status_t addRemovePortTblGrp( + _In_ sai_object_id_t port_oid, + _In_ sai_object_id_t tbl_grp_oid, + _In_ bool is_add); + + sai_status_t aclBindUnbindPort( + _In_ sai_object_id_t port_oid, + _In_ sai_object_id_t tbl_grp_oid, + _In_ bool is_input, + _In_ bool is_bind); + + sai_status_t aclBindUnbindPorts( + _In_ sai_object_id_t tbl_grp_oid, + _In_ sai_object_id_t tbl_oid, + _In_ bool is_bind); + + sai_status_t getAclEntryStats( + _In_ sai_object_id_t ace_cntr_oid, + _In_ uint32_t attr_count, + _Out_ sai_attribute_t *attr_list); + + public: // VPP + + sai_status_t aclGetVppIndices( + _In_ sai_object_id_t ace_oid, + _Out_ uint32_t *acl_index, + _Out_ uint32_t *ace_index); + + bool vpp_get_hwif_name ( + _In_ sai_object_id_t object_id, + _In_ uint32_t vlan_id, + _Out_ std::string& ifname); + + protected: // VPP + + void populate_if_mapping(); + + const char *tap_to_hwif_name(const char *name); + + const char *hwif_to_tap_name(const char *name); + + void vppProcessEvents (); + + void startVppEventsThread(); + + private: // VPP + + std::map m_hostif_hwif_map; + std::map m_hwif_hostif_map; + int mapping_init = 0; + bool m_run_vpp_events_thread = true; + bool VppEventsThreadStarted = false; + std::shared_ptr m_vpp_thread; + + private: // VPP + + static int currentMaxInstance; + + std::set availableInstances; + + //1-4095 BD are statically allocated for VLAN by VLAN-ID. Use 4K-16K for dynamic allocation + static const uint32_t dynamic_bd_id_base = 4*1024; + static const uint16_t dynamic_bd_id_pool_size = 12*1024; + + BitResourcePool dynamic_bd_id_pool = BitResourcePool(dynamic_bd_id_pool_size, dynamic_bd_id_base); }; } diff --git a/vslib/SwitchStateBaseHostif.cpp b/vslib/SwitchStateBaseHostif.cpp index 855ac43e7..686d3acc6 100644 --- a/vslib/SwitchStateBaseHostif.cpp +++ b/vslib/SwitchStateBaseHostif.cpp @@ -27,6 +27,10 @@ #include #include +#include "vppxlate/SaiVppXlate.h" + +extern bool g_vpp; + using namespace saivs; // XXX set must also be supported when we change operational status up/down and @@ -55,6 +59,11 @@ int SwitchStateBase::vs_create_tap_device( return -1; } + if (g_vpp) // VPP + { + return fd; + } + struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); @@ -297,6 +306,11 @@ int SwitchStateBase::promisc( { SWSS_LOG_ENTER(); + if (g_vpp) // VPP + { + return 0; + } + int s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) @@ -601,7 +615,16 @@ sai_status_t SwitchStateBase::vs_create_hostif_tap_interface( SWSS_LOG_INFO("creating hostif %s", name.c_str()); - int tapfd = vs_create_tap_device(name.c_str(), IFF_TAP | IFF_MULTI_QUEUE | IFF_NO_PI); + int tapfd; + + if (g_vpp) // VPP + { + tapfd = vs_create_tap_device(name.c_str(), IFF_TAP | IFF_MULTI_QUEUE | IFF_NO_PI | IFF_VNET_HDR); + } + else + { + tapfd = vs_create_tap_device(name.c_str(), IFF_TAP | IFF_MULTI_QUEUE | IFF_NO_PI); + } if (tapfd < 0) { @@ -612,6 +635,28 @@ sai_status_t SwitchStateBase::vs_create_hostif_tap_interface( SWSS_LOG_INFO("created TAP device for %s, fd: %d", name.c_str(), tapfd); + if (g_vpp) // VPP + { + const char *dev = name.c_str(); + const char *hwif_name = tap_to_hwif_name(dev); + + configure_lcp_interface(hwif_name, dev, true); + + { + bool link_up = false; + + interface_get_state(hwif_name, &link_up); + + auto state = link_up ? SAI_PORT_OPER_STATUS_UP : SAI_PORT_OPER_STATUS_DOWN; + + send_port_oper_status_notification(obj_id, state, true); + + SWSS_LOG_NOTICE("VPP interface %s(%s) oper state %s", hwif_name, dev, + (link_up ? "UP" : "DOWN")); + } + + } + sai_attribute_t attr; memset(&attr, 0, sizeof(attr)); @@ -640,6 +685,34 @@ sai_status_t SwitchStateBase::vs_create_hostif_tap_interface( return SAI_STATUS_FAILURE; } + if (g_vpp) // VPP + { + const char *dev = name.c_str(); + const char *hwif_name = tap_to_hwif_name(dev); + + err = sw_interface_set_mac(hwif_name, attr.value.mac); + + if (err < 0) + { + SWSS_LOG_ERROR("failed to set MAC address %s for %s", + sai_serialize_mac(attr.value.mac).c_str(), + hwif_name); + + close(tapfd); + + return SAI_STATUS_FAILURE; + } + + SWSS_LOG_INFO("Successfully set mac to %s for %s", sai_serialize_mac(attr.value.mac).c_str(), name.c_str()); + + setIfNameToPortId(name, obj_id); + setPortIdToTapName(obj_id, name); + + SWSS_LOG_INFO("created tap interface %s", name.c_str()); + + return SAI_STATUS_SUCCESS; + } + std::string vname = vs_get_veth_name(name, obj_id); int mtu = ETH_FRAME_BUFFER_SIZE; @@ -786,6 +859,40 @@ sai_status_t SwitchStateBase::vs_remove_hostif_tap_interface( // TODO this should be hosif_id or if index ? std::string name = std::string(attr.value.chardata); + if (g_vpp) // VPP + { + /* + auto it = m_hostif_info_map.find(name); + + if (it == m_hostif_info_map.end()) + { + SWSS_LOG_ERROR("failed to find host info entry for tap device: %s", name.c_str()); + + return SAI_STATUS_FAILURE; + } + + SWSS_LOG_NOTICE("attempting to remove tap device: %s", name.c_str()); + + auto info = it->second; // destructor will stop threads + */ + // remove host info entry from map + + // m_hostif_info_map.erase(it); + + // remove interface mapping + + // std::string vname = vpp_get_veth_name(name, info->m_portId); + + sai_object_id_t port_id = getPortIdFromIfName(name); + + removeIfNameToPortId(name); + removePortIdToTapName(port_id); + + SWSS_LOG_NOTICE("successfully removed hostif tap device: %s", name.c_str()); + + return SAI_STATUS_SUCCESS; + } + auto it = m_hostif_info_map.find(name); if (it == m_hostif_info_map.end()) @@ -861,6 +968,14 @@ bool SwitchStateBase::hasIfIndex( { SWSS_LOG_ENTER(); + if (g_vpp) // VPP + { + if (m_hostif_info_map.size() == 0) + { + return false; + } + } + for (auto& kvp: m_hostif_info_map) { if (kvp.second->m_ifindex == ifindex) @@ -966,3 +1081,89 @@ void SwitchStateBase::syncOnLinkMsg( send_port_oper_status_notification(portId, state, false); } + +// VPP + +// TODO to config +static const char *sonic_vpp_ifmap = "/usr/share/sonic/hwsku/sonic_vpp_ifmap.ini"; + +void SwitchStateBase::populate_if_mapping() +{ + SWSS_LOG_ENTER(); + + if (mapping_init) + { + return; + } + + FILE *fp; + char sonic_name[64], vpp_name[64]; + + fp = fopen(sonic_vpp_ifmap, "r"); + + if (!fp) + { + return; + } + + while (fscanf(fp, "%s %s", sonic_name, vpp_name) != EOF) + { + std::string tap_name, hwif_name; + + tap_name = std::string(sonic_name); + hwif_name = std::string(vpp_name); + + m_hostif_hwif_map[tap_name] = hwif_name; + m_hwif_hostif_map[hwif_name] = tap_name; + } + + mapping_init = 1; + + fclose(fp); +} + +const char* SwitchStateBase::tap_to_hwif_name( + _In_ const char *name) +{ + SWSS_LOG_ENTER(); + + populate_if_mapping(); + + std::string tap_name = std::string(name); + + auto it = m_hostif_hwif_map.find(tap_name); + + if (it == m_hostif_hwif_map.end()) + { + SWSS_LOG_ERROR("failed to find hwif info entry for hostif device: %s", tap_name.c_str()); + + return "Unknown"; + } + + SWSS_LOG_DEBUG("Found hwif %s info entry for hostif device: %s", it->second.c_str(), tap_name.c_str()); + + return it->second.c_str(); +} + +const char* SwitchStateBase::hwif_to_tap_name( + _In_ const char *name) +{ + SWSS_LOG_ENTER(); + + populate_if_mapping(); + + std::string tap_name = std::string(name); + + auto it = m_hwif_hostif_map.find(tap_name); + + if (it == m_hwif_hostif_map.end()) + { + SWSS_LOG_ERROR("failed to find hostif info entry for hwif device: %s", tap_name.c_str()); + + return "Unknown"; + } + + SWSS_LOG_DEBUG("Found hostif %s info entry for hwif device: %s", it->second.c_str(), tap_name.c_str()); + + return it->second.c_str(); +} diff --git a/vslib/SwitchStateBaseMACsec.cpp b/vslib/SwitchStateBaseMACsec.cpp index e08f3f30a..6b6db3bf2 100644 --- a/vslib/SwitchStateBaseMACsec.cpp +++ b/vslib/SwitchStateBaseMACsec.cpp @@ -17,6 +17,8 @@ using namespace saivs; +extern bool g_vpp; + #define SAI_VS_MACSEC_PREFIX "macsec_" #define MACSEC_SYSTEM_IDENTIFIER (12) #define MACSEC_PORT_IDENTIFIER (4) @@ -555,7 +557,19 @@ sai_status_t SwitchStateBase::loadMACsecAttrFromMACsecSC( std::stringstream sciHexStr; sciHexStr << std::setw(MACSEC_SCI_LENGTH) << std::setfill('0'); - sciHexStr << std::hex << htobe64(sci); + + if (g_vpp) // VPP + { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + sciHexStr << std::hex << bswap_64(sci); +#else + sciHexStr << std::hex << sci; +#endif + } + else + { + sciHexStr << std::hex << htobe64(sci); + } macsecAttr.m_sci = sciHexStr.str(); @@ -712,7 +726,8 @@ sai_status_t SwitchStateBase::loadMACsecAttrFromMACsecSA( ssciHexStr << std::hex << attr->value.u32; - macsecAttr.m_ssci = ssciHexStr.str(); + macsecAttr.m_ssciStr = ssciHexStr.str(); + macsecAttr.m_ssci = htonl(attr->value.u32); SAI_METADATA_GET_ATTR_BY_ID(attr, SAI_MACSEC_SA_ATTR_SALT, attrCount, attrList); diff --git a/vslib/VirtualSwitchSaiInterface.cpp b/vslib/VirtualSwitchSaiInterface.cpp index d866f5ac1..e49a63f80 100644 --- a/vslib/VirtualSwitchSaiInterface.cpp +++ b/vslib/VirtualSwitchSaiInterface.cpp @@ -16,6 +16,8 @@ #include "SwitchMLNX2700.h" #include "SwitchNvdaMBF2H536C.h" +#include "vppxlate/SaiIntfStats.h" + #include /* @@ -25,6 +27,8 @@ #define MAX_HARDWARE_INFO_LENGTH 0x1000 +extern bool g_vpp; + using namespace saivs; using namespace saimeta; using namespace sairediscommon; @@ -95,7 +99,7 @@ std::shared_ptr VirtualSwitchSaiInterface::extractWarmBootState( return state; } -bool VirtualSwitchSaiInterface::validate_switch_warm_boot_atributes( +bool VirtualSwitchSaiInterface::validate_switch_warm_boot_attributes( _In_ uint32_t attr_count, _In_ const sai_attribute_t *attr_list) const { @@ -668,7 +672,7 @@ sai_status_t VirtualSwitchSaiInterface::create( if (config->m_bootType == SAI_VS_BOOT_TYPE_WARM) { - if (!validate_switch_warm_boot_atributes(attr_count, attr_list)) + if (!validate_switch_warm_boot_attributes(attr_count, attr_list)) { SWSS_LOG_ERROR("invalid attribute passed during warm boot"); @@ -890,6 +894,23 @@ sai_status_t VirtualSwitchSaiInterface::queryAttributeCapability( { SWSS_LOG_ENTER(); + if (g_vpp) // VPP + { + // TODO move to SwitchState + // + // TODO: We should generate this metadata for the virtual switch rather + // than hard-coding it here. + + // in virtual switch by default all apis are implemented for all + // objects. SUCCESS for all attributes + + capability->create_implemented = true; + capability->set_implemented = true; + capability->get_implemented = true; + + return SAI_STATUS_SUCCESS; + } + auto ss = m_switchStateMap.at(switch_id); return ss->queryAttributeCapability(switch_id, object_type, attr_id, capability); } @@ -961,6 +982,14 @@ sai_status_t VirtualSwitchSaiInterface::getStats( { SWSS_LOG_ENTER(); + if (g_vpp) // VPP + { + if (object_type == SAI_OBJECT_TYPE_PORT) + { + setPortStats(object_id); + } + } + /* * Get stats is the same as get stats ext with mode == SAI_STATS_MODE_READ. */ diff --git a/vslib/VirtualSwitchSaiInterface.h b/vslib/VirtualSwitchSaiInterface.h index 25855fdec..a4c38fbf5 100644 --- a/vslib/VirtualSwitchSaiInterface.h +++ b/vslib/VirtualSwitchSaiInterface.h @@ -256,6 +256,19 @@ namespace saivs _In_ sai_object_id_t objectId, _In_ const sai_attribute_t *attr); + private: // VPP + + void setPortStats( + _In_ sai_object_id_t oid); + + bool port_to_hostif_list( + _In_ sai_object_id_t oid, + _Inout_ std::string& if_name); + + bool port_to_hwifname( + _In_ sai_object_id_t oid, + _Inout_ std::string& if_name); + private: void update_local_metadata( @@ -267,7 +280,7 @@ namespace saivs std::shared_ptr extractWarmBootState( _In_ sai_object_id_t switch_id); - bool validate_switch_warm_boot_atributes( + bool validate_switch_warm_boot_attributes( _In_ uint32_t attr_count, _In_ const sai_attribute_t *attr_list) const; @@ -326,5 +339,9 @@ namespace saivs std::shared_ptr m_realObjectIdManager; SwitchStateBase::SwitchStateMap m_switchStateMap; + + private: // VPP + + std::map m_phMap; }; } diff --git a/vslib/VirtualSwitchSaiInterfaceFdb.cpp b/vslib/VirtualSwitchSaiInterfaceFdb.cpp index bba539ed9..53d7dc7f1 100644 --- a/vslib/VirtualSwitchSaiInterfaceFdb.cpp +++ b/vslib/VirtualSwitchSaiInterfaceFdb.cpp @@ -4,6 +4,8 @@ #include "swss/logger.h" #include "meta/sai_serialize.h" +extern bool g_vpp; + using namespace saivs; bool VirtualSwitchSaiInterface::doesFdbEntryNotMatchFlushAttr( @@ -279,6 +281,12 @@ sai_status_t VirtualSwitchSaiInterface::flushFdbEntries( data.fdb_entry.bv_id = vlanid->value.oid; } + if (g_vpp) // VPP + { + /* Flushing the FDB Entrys based on Bridge port ID and VLAN ID sent to VS*/ + ss->vpp_fdbentry_flush(switch_id, attr_count, attr_list); + } + if (static_fdbs.size()) { SWSS_LOG_NOTICE("flushing %zu static entries", static_fdbs.size()); @@ -308,6 +316,11 @@ void VirtualSwitchSaiInterface::ageFdbs() { SWSS_LOG_ENTER(); + if (g_vpp) // VPP + { + return; + } + for (auto& it: m_switchStateMap) { it.second->processFdbEntriesForAging();