Skip to content

Commit

Permalink
Updated handling of VRF_VNI mapping and VLAN_VNI mapping for same VNI…
Browse files Browse the repository at this point in the history
… ID (sonic-net#2538)

* Updated handling of VRF_VNI mapping and VLAN_VNI mapping for same VNI ID
  • Loading branch information
tapashdas committed Dec 22, 2022
1 parent 0d91125 commit a443945
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 23 deletions.
13 changes: 13 additions & 0 deletions orchagent/vrforch.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,19 @@ class VRFOrch : public Orch2
return (-1);
}
}

bool isL3VniVlan(const uint32_t vni) const
{
if (l3vni_table_.find(vni) != std::end(l3vni_table_))
{
return l3vni_table_.at(vni).l3_vni;
}
else
{
return false;
}
}

int updateL3VniVlan(uint32_t vni, uint16_t vlan_id);
private:
virtual bool addOperation(const Request& request);
Expand Down
96 changes: 93 additions & 3 deletions orchagent/vxlanorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1903,6 +1903,7 @@ bool VxlanTunnelMapOrch::addOperation(const Request& request)

sai_vlan_id_t vlan_id = (sai_vlan_id_t)request.getAttrVlan("vlan");
Port tempPort;
bool isL3Vni = false;

const auto full_tunnel_map_entry_name = request.getFullKey();
SWSS_LOG_INFO("Full name = %s",full_tunnel_map_entry_name.c_str());
Expand Down Expand Up @@ -1974,11 +1975,21 @@ bool VxlanTunnelMapOrch::addOperation(const Request& request)
tunnel_obj->vlan_vrf_vni_count++;
SWSS_LOG_INFO("vni count increased to %d",tunnel_obj->vlan_vrf_vni_count);

VRFOrch* vrf_orch = gDirectory.get<VRFOrch*>();
isL3Vni = vrf_orch->isL3VniVlan(vni_id);

try
{
auto tunnel_map_entry_id = create_tunnel_map_entry(MAP_T::VNI_TO_VLAN_ID,
tunnel_map_id, vni_id, vlan_id);
vxlan_tunnel_map_table_[full_tunnel_map_entry_name].map_entry_id = tunnel_map_entry_id;
if (isL3Vni == false)
{
auto tunnel_map_entry_id = create_tunnel_map_entry(MAP_T::VNI_TO_VLAN_ID,
tunnel_map_id, vni_id, vlan_id);
vxlan_tunnel_map_table_[full_tunnel_map_entry_name].map_entry_id = tunnel_map_entry_id;
}
else
{
vxlan_tunnel_map_table_[full_tunnel_map_entry_name].map_entry_id = SAI_NULL_OBJECT_ID;
}
vxlan_tunnel_map_table_[full_tunnel_map_entry_name].vlan_id = vlan_id;
vxlan_tunnel_map_table_[full_tunnel_map_entry_name].vni_id = vni_id;
}
Expand Down Expand Up @@ -2124,9 +2135,13 @@ bool VxlanTunnelMapOrch::delOperation(const Request& request)
bool VxlanVrfMapOrch::addOperation(const Request& request)
{
SWSS_LOG_ENTER();
std::string vniVlanMapName;
uint32_t vlan_id = 0;
sai_object_id_t tnl_map_entry_id = SAI_NULL_OBJECT_ID;

auto tunnel_name = request.getKeyString(0);
VxlanTunnelOrch* tunnel_orch = gDirectory.get<VxlanTunnelOrch*>();
VxlanTunnelMapOrch* vxlan_tun_map_orch = gDirectory.get<VxlanTunnelMapOrch*>();
if (!tunnel_orch->isTunnelExists(tunnel_name))
{
SWSS_LOG_WARN("Vxlan tunnel '%s' doesn't exist", tunnel_name.c_str());
Expand Down Expand Up @@ -2188,6 +2203,15 @@ bool VxlanVrfMapOrch::addOperation(const Request& request)
vrf_map_entry_t entry;
try
{
entry.isL2Vni = vxlan_tun_map_orch->isVniVlanMapExists(vni_id, vniVlanMapName, &tnl_map_entry_id, &vlan_id);
entry.vni_id = vni_id;
if (entry.isL2Vni)
{
entry.vniVlanMapName = vniVlanMapName;
entry.vlan_id = vlan_id;
remove_tunnel_map_entry(tnl_map_entry_id);
SWSS_LOG_DEBUG("remove_tunnel_map_entry name %s, vlan %d, vni %d\n", entry.vniVlanMapName.c_str(), entry.vlan_id, entry.vni_id);
}
/*
* Create encap and decap mapper
*/
Expand Down Expand Up @@ -2219,7 +2243,12 @@ bool VxlanVrfMapOrch::delOperation(const Request& request)
SWSS_LOG_ENTER();

VRFOrch* vrf_orch = gDirectory.get<VRFOrch*>();
VxlanTunnelOrch* tunnel_orch = gDirectory.get<VxlanTunnelOrch*>();
VxlanTunnelMapOrch* vxlan_tun_map_orch = gDirectory.get<VxlanTunnelMapOrch*>();
const auto full_map_entry_name = request.getFullKey();
std::string vniVlanMapName;
uint32_t vlan_id = 0;
sai_object_id_t tnl_map_entry_id = SAI_NULL_OBJECT_ID;

if (!isVrfMapExists(full_map_entry_name))
{
Expand All @@ -2241,6 +2270,9 @@ bool VxlanVrfMapOrch::delOperation(const Request& request)
return false;
}
SWSS_LOG_NOTICE("VxlanVrfMapOrch VRF VNI mapping '%s' remove vrf %s", full_map_entry_name.c_str(), vrf_name.c_str());
auto tunnel_name = request.getKeyString(0);
auto tunnel_obj = tunnel_orch->getVxlanTunnel(tunnel_name);

vrf_map_entry_t entry;
try
{
Expand All @@ -2256,6 +2288,32 @@ bool VxlanVrfMapOrch::delOperation(const Request& request)
vrf_orch->decreaseVrfRefCount(vrf_name);
remove_tunnel_map_entry(entry.decap_id);
vrf_orch->decreaseVrfRefCount(vrf_name);

if (!entry.isL2Vni)
{
entry.isL2Vni = vxlan_tun_map_orch->isVniVlanMapExists(entry.vni_id, vniVlanMapName, &tnl_map_entry_id, &vlan_id);
SWSS_LOG_NOTICE("VxlanVrfMapOrch vni %d, isL2Vni %d\n", entry.vni_id, entry.isL2Vni);

if (entry.isL2Vni)
{
entry.vniVlanMapName = vniVlanMapName;
entry.vlan_id = vlan_id;
SWSS_LOG_DEBUG("add_tunnel_map_entry name %s, vlan %d, vni %d\n", entry.vniVlanMapName.c_str(), entry.vlan_id, entry.vni_id);
}
}
if(entry.isL2Vni)
{
const auto tunnel_map_id = tunnel_obj->getDecapMapId(TUNNEL_MAP_T_VLAN);
SWSS_LOG_NOTICE("Adding tunnel map entry. Tunnel: %s %s",tunnel_name.c_str(),entry.vniVlanMapName.c_str());

SWSS_LOG_DEBUG("create_tunnel_map_entry vni %d, vlan %d\n", entry.vni_id, entry.vlan_id);
auto tunnel_map_entry_id = create_tunnel_map_entry(MAP_T::VNI_TO_VLAN_ID,
tunnel_map_id, entry.vni_id, (uint16_t)entry.vlan_id);
SWSS_LOG_DEBUG("updateTnlMapId name %s\n", entry.vniVlanMapName.c_str());

vxlan_tun_map_orch->updateTnlMapId(entry.vniVlanMapName, tunnel_map_entry_id);
}

vxlan_vrf_table_.erase(full_map_entry_name);
vxlan_vrf_tunnel_.erase(vrf_name);
}
Expand Down Expand Up @@ -2599,3 +2657,35 @@ bool EvpnNvoOrch::delOperation(const Request& request)

return true;
}

bool VxlanTunnelMapOrch::isVniVlanMapExists(uint32_t vni_id, std::string& vniVlanMapName, sai_object_id_t *tnl_map_entry_id, uint32_t *vlan_id)
{
SWSS_LOG_ENTER();
bool map_entry_exists = false;
std::map<std::string, tunnel_map_entry_t>::iterator it;
for(it = vxlan_tunnel_map_table_.begin(); it != vxlan_tunnel_map_table_.end(); it++)
{
auto full_tunnel_map_entry_name = it->first;
tunnel_map_entry_t tunnel_map_entry = it->second;

if (vni_id == tunnel_map_entry.vni_id)
{
vniVlanMapName = full_tunnel_map_entry_name;
*tnl_map_entry_id = tunnel_map_entry.map_entry_id;
*vlan_id = tunnel_map_entry.vlan_id;
map_entry_exists = true;
SWSS_LOG_NOTICE("vniVlanMapName %s, vlan %d\n", vniVlanMapName.c_str(), *vlan_id);
break;
}
}

return map_entry_exists;
}

void VxlanTunnelMapOrch::updateTnlMapId(std::string vniVlanMapName, sai_object_id_t tunnel_map_id)
{
SWSS_LOG_ENTER();
SWSS_LOG_NOTICE("name %s\n", vniVlanMapName.c_str());
vxlan_tunnel_map_table_[vniVlanMapName].map_entry_id = tunnel_map_id;
}

8 changes: 8 additions & 0 deletions orchagent/vxlanorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,10 @@ class VxlanTunnelMapOrch : public Orch2
{
return vxlan_tunnel_map_table_.find(name) != std::end(vxlan_tunnel_map_table_);
}

bool isVniVlanMapExists(uint32_t vni_id, std::string& vniVlanMapName, sai_object_id_t *tnl_map_entry_id, uint32_t *vlan_id);

void updateTnlMapId(std::string vniVlanMapName, sai_object_id_t tunnel_map_id);
private:
virtual bool addOperation(const Request& request);
virtual bool delOperation(const Request& request);
Expand All @@ -436,6 +440,10 @@ class VxlanVrfRequest : public Request
struct vrf_map_entry_t {
sai_object_id_t encap_id;
sai_object_id_t decap_id;
bool isL2Vni;
std::string vniVlanMapName;
uint32_t vlan_id;
uint32_t vni_id;
};

typedef std::map<string, vrf_map_entry_t> VxlanVrfTable;
Expand Down
25 changes: 21 additions & 4 deletions tests/evpn_tunnel.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,22 @@ def check_vxlan_tunnel_map_entry(self, dvs, tunnel_name, vidlist, vnidlist):
(exitcode, out) = dvs.runcmd(iplinkcmd)
assert exitcode == 0, "Kernel device not created"

def check_vxlan_tunnel_map_entry_removed(self, dvs, tunnel_name, vidlist, vnidlist):
asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0)

expected_attributes_1 = {
'SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE': 'SAI_TUNNEL_MAP_TYPE_VNI_TO_VLAN_ID',
'SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP': self.tunnel_map_map[tunnel_name][0],
'SAI_TUNNEL_MAP_ENTRY_ATTR_VLAN_ID_VALUE': vidlist[0],
'SAI_TUNNEL_MAP_ENTRY_ATTR_VNI_ID_KEY': vnidlist[0],
}

for x in range(len(vidlist)):
expected_attributes_1['SAI_TUNNEL_MAP_ENTRY_ATTR_VLAN_ID_VALUE'] = vidlist[x]
expected_attributes_1['SAI_TUNNEL_MAP_ENTRY_ATTR_VNI_ID_KEY'] = vnidlist[x]
ret = self.helper.get_key_with_attr(asic_db, self.ASIC_TUNNEL_MAP_ENTRY, expected_attributes_1)
assert len(ret) == 0, "SIP TunnelMap entry not removed"

def check_vxlan_sip_tunnel_delete(self, dvs, tunnel_name, sip, ignore_bp = True):
asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0)
app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0)
Expand Down Expand Up @@ -517,7 +533,8 @@ def check_vxlan_sip_tunnel_delete(self, dvs, tunnel_name, sip, ignore_bp = True)
assert status == False, "Tunnel bridgeport entry not deleted"

def check_vxlan_sip_tunnel(self, dvs, tunnel_name, src_ip, vidlist, vnidlist,
dst_ip = '0.0.0.0', skip_dst_ip = 'True', ignore_bp = True):
dst_ip = '0.0.0.0', skip_dst_ip = 'True', ignore_bp = True,
tunnel_map_entry_count = 3):
asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0)
app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0)

Expand All @@ -527,7 +544,7 @@ def check_vxlan_sip_tunnel(self, dvs, tunnel_name, src_ip, vidlist, vnidlist,

# check that the vxlan tunnel termination are there
assert self.helper.how_many_entries_exist(asic_db, self.ASIC_TUNNEL_MAP) == (len(self.tunnel_map_ids) + 4), "The TUNNEL_MAP wasn't created"
assert self.helper.how_many_entries_exist(asic_db, self.ASIC_TUNNEL_MAP_ENTRY) == (len(self.tunnel_map_entry_ids) + 3), "The TUNNEL_MAP_ENTRY is created"
assert self.helper.how_many_entries_exist(asic_db, self.ASIC_TUNNEL_MAP_ENTRY) == (len(self.tunnel_map_entry_ids) + tunnel_map_entry_count), "The TUNNEL_MAP_ENTRY is created"
assert self.helper.how_many_entries_exist(asic_db, self.ASIC_TUNNEL_TABLE) == (len(self.tunnel_ids) + 1), "The TUNNEL wasn't created"
assert self.helper.how_many_entries_exist(asic_db, self.ASIC_TUNNEL_TERM_ENTRY) == (len(self.tunnel_term_ids) + 1), "The TUNNEL_TERM_TABLE_ENTRY wasm't created"

Expand Down Expand Up @@ -798,10 +815,10 @@ def check_vxlan_tunnel_entry(self, dvs, tunnel_name, vnet_name, vni_id):
def check_vxlan_tunnel_vrf_map_entry(self, dvs, tunnel_name, vrf_name, vni_id):
asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0)

tunnel_map_entry_id = self.helper.get_created_entries(asic_db, self.ASIC_TUNNEL_MAP_ENTRY, self.tunnel_map_entry_ids, 3)
tunnel_map_entry_id = self.helper.get_created_entries(asic_db, self.ASIC_TUNNEL_MAP_ENTRY, self.tunnel_map_entry_ids, 2)

# check that the vxlan tunnel termination are there
assert self.helper.how_many_entries_exist(asic_db, self.ASIC_TUNNEL_MAP_ENTRY) == (len(self.tunnel_map_entry_ids) + 3), "The TUNNEL_MAP_ENTRY is created too early"
assert self.helper.how_many_entries_exist(asic_db, self.ASIC_TUNNEL_MAP_ENTRY) == (len(self.tunnel_map_entry_ids) + 2), "The TUNNEL_MAP_ENTRY is created too early"

ret = self.helper.get_key_with_attr(asic_db, self.ASIC_TUNNEL_MAP_ENTRY,
{
Expand Down
20 changes: 12 additions & 8 deletions tests/test_evpn_l3_vxlan.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ def test_sip_tunnel_vrf_vni_map(self, dvs, testlog):
helper.check_object(self.pdb, "VXLAN_VRF_TABLE", "%s:%s" % (tunnel_name, vrf_map_name), exp_attr1)

print ("\tTesting SIP Tunnel Creation")
vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist)
vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, tunnel_map_entry_count = 2)

print ("\tTesting Tunnel Vlan VNI Map Entry")
vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist)
vxlan_obj.check_vxlan_tunnel_map_entry_removed(dvs, tunnel_name, vlanlist, vnilist)

print ("\tTesting Tunnel VRF VNI Map Entry")
vxlan_obj.check_vxlan_tunnel_vrf_map_entry(dvs, tunnel_name, 'Vrf-RED', '1000')
Expand All @@ -82,6 +82,7 @@ def test_sip_tunnel_vrf_vni_map(self, dvs, testlog):
vxlan_obj.check_vxlan_tunnel_vrf_map_entry_remove(dvs, tunnel_name, 'Vrf-RED', '1000')

print ("\tTesting Tunnel Vlan VNI Map entry removal")
vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist)
vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100')
vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist)

Expand Down Expand Up @@ -143,10 +144,10 @@ def test_prefix_route_create_dip_tunnel(self, dvs, testlog):
helper.check_object(self.pdb, "VXLAN_VRF_TABLE", "%s:%s" % (tunnel_name, vrf_map_name), exp_attr1)

print ("\tTesting SIP Tunnel Creation")
vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist)
vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, tunnel_map_entry_count = 2)

print ("\tTesting Tunnel Vlan Map Entry")
vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist)
vxlan_obj.check_vxlan_tunnel_map_entry_removed(dvs, tunnel_name, vlanlist, vnilist)

print ("\tTesting Tunnel Vrf Map Entry")
vxlan_obj.check_vxlan_tunnel_vrf_map_entry(dvs, tunnel_name, 'Vrf-RED', '1000')
Expand Down Expand Up @@ -180,6 +181,7 @@ def test_prefix_route_create_dip_tunnel(self, dvs, testlog):
vxlan_obj.check_del_router_interface(dvs, "Vlan100")

print ("\tTesting Tunnel Map entry removal")
vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist)
vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100')
vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist)

Expand Down Expand Up @@ -242,10 +244,10 @@ def test_dip_tunnel_ipv4_routes(self, dvs, testlog):
helper.check_object(self.pdb, "VXLAN_VRF_TABLE", "%s:%s" % (tunnel_name, vrf_map_name), exp_attr1)

print ("\tTesting SIP Tunnel Creation")
vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist)
vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, tunnel_map_entry_count = 2)

print ("\tTesting Tunnel Vlan Map Entry")
vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist)
vxlan_obj.check_vxlan_tunnel_map_entry_removed(dvs, tunnel_name, vlanlist, vnilist)

print ("\tTesting Tunnel Vrf Map Entry")
vxlan_obj.check_vxlan_tunnel_vrf_map_entry(dvs, tunnel_name, 'Vrf-RED', '1000')
Expand Down Expand Up @@ -386,6 +388,7 @@ def test_dip_tunnel_ipv4_routes(self, dvs, testlog):
vxlan_obj.check_del_router_interface(dvs, "Vlan100")

print ("\tTesting Tunnel Map entry removal")
vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist)
vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100')
vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist)

Expand Down Expand Up @@ -449,10 +452,10 @@ def test_dip_tunnel_ipv6_routes(self, dvs, testlog):
helper.check_object(self.pdb, "VXLAN_VRF_TABLE", "%s:%s" % (tunnel_name, vrf_map_name), exp_attr1)

print ("\tTesting SIP Tunnel Creation")
vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist)
vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, tunnel_map_entry_count = 2)

print ("\tTesting Tunnel Vlan Map Entry")
vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist)
vxlan_obj.check_vxlan_tunnel_map_entry_removed(dvs, tunnel_name, vlanlist, vnilist)

print ("\tTesting Tunnel Vrf Map Entry")
vxlan_obj.check_vxlan_tunnel_vrf_map_entry(dvs, tunnel_name, 'Vrf-RED', '1000')
Expand Down Expand Up @@ -594,6 +597,7 @@ def test_dip_tunnel_ipv6_routes(self, dvs, testlog):
vxlan_obj.check_del_router_interface(dvs, "Vlan100")

print ("\tTesting Tunnel Map entry removal")
vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist)
vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100')
vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist)

Expand Down
Loading

0 comments on commit a443945

Please sign in to comment.