Skip to content

Commit

Permalink
SRv6: fix MySID prefix mask calculation
Browse files Browse the repository at this point in the history
* use func_len to calculate MySID entry prefix for CONFIG_DB key
* update the vstest to test different func_len values
* add a test for the "locator reverse lookup"

Signed-off-by: Yakiv Huryk <[email protected]>
  • Loading branch information
Yakiv-Huryk committed Jan 24, 2025
1 parent b13ac29 commit 0bba0ae
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 35 deletions.
10 changes: 5 additions & 5 deletions orchagent/srv6orch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,18 +125,18 @@ bool Srv6Orch::getLocatorCfgFromDb(const string& locator, MySidLocatorCfg& cfg)

bool Srv6Orch::reverseLookupLocator(const vector<string>& candidates, const MySidLocatorCfg& locator_cfg, string& locator)
{
for (const auto& canididate: candidates)
for (const auto& candidate: candidates)
{
MySidLocatorCfg cfg;
auto ok = getLocatorCfgFromDb(canididate, cfg);
auto ok = getLocatorCfgFromDb(candidate, cfg);
if (!ok) {
continue;
}

if (locator_cfg == cfg)
{
SWSS_LOG_DEBUG("Found a locator %s matching the config", canididate.c_str());
locator = canididate;
SWSS_LOG_DEBUG("Found a locator %s matching the config", candidate.c_str());
locator = candidate;
return true;
}
}
Expand Down Expand Up @@ -200,7 +200,7 @@ void Srv6Orch::mySidCfgCacheRefresh()

bool Srv6Orch::getMySidEntryDscpMode(const string& my_sid_addr, const MySidLocatorCfg& locator_cfg, sai_tunnel_dscp_mode_t& dscp_mode)
{
auto my_sid_prefix = my_sid_addr + "/" + to_string(locator_cfg.block_len + locator_cfg.node_len);
auto my_sid_prefix = my_sid_addr + "/" + to_string(locator_cfg.block_len + locator_cfg.node_len + locator_cfg.func_len);

auto cfg_cache = my_sid_dscp_cfg_cache_.equal_range(my_sid_prefix);
if (cfg_cache.first == my_sid_dscp_cfg_cache_.end())
Expand Down
137 changes: 107 additions & 30 deletions tests/test_srv6.py
Original file line number Diff line number Diff line change
Expand Up @@ -1303,14 +1303,30 @@ def verify_attribute_value(self, table, key, attribute, expected_value):
if fv[0] == attribute:
assert fv[1] == expected_value

def add_mysid_cfgdb(self, locator, prefix, addr, dscp_mode):
self.cdb.create_entry("SRV6_MY_LOCATORS", locator, {"prefix": prefix, "block_len": "32", "node_len": "16", "func_len": "16", "arg_len": "0"})
self.cdb.create_entry("SRV6_MY_SIDS", f'{locator}|{addr}/48', {"decap_dscp_mode": dscp_mode})

def remove_mysid_cfgdb(self, locator, addr):
self.cdb.delete_entry("SRV6_MY_SIDS", f"{locator}|{addr}/48")
def add_mysid_cfgdb(self, locator, addr, prefix="", dscp_mode="uniform", func_len=0):
if not prefix:
prefix = addr
self.cdb.create_entry("SRV6_MY_LOCATORS", locator, {"prefix": prefix, "block_len": "32", "node_len": "16", "func_len": str(func_len), "arg_len": "0"})
self.cdb.create_entry("SRV6_MY_SIDS", f'{locator}|{addr}/{48 + func_len}', {"decap_dscp_mode": dscp_mode})

def remove_mysid_cfgdb(self, locator, addr, func_len=0):
self.cdb.delete_entry("SRV6_MY_SIDS", f"{locator}|{addr}/{48 + func_len}")
self.cdb.delete_entry("SRV6_MY_LOCATORS", locator)

def add_mysid_vtysh(self, dvs, locator, addr, prefix="", func_len=0):
if not prefix:
prefix = addr
loc_cmd = f'vtysh -c "configure terminal" -c "segment-routing" -c "srv6" -c "locators" -c "locator {locator}" -c "prefix {prefix}/48 block-len 32 node-len 16 func-bits {func_len}" -c "behavior usid"'
sid_cmd = f'vtysh -c "configure terminal" -c "segment-routing" -c "srv6" -c "static-sids" -c "sid {addr}/{48 + func_len} locator {locator} behavior uN"'
dvs.runcmd(loc_cmd)
dvs.runcmd(sid_cmd)

def remove_mysid_vtysh(self, dvs, locator, addr, func_len=0):
sid_cmd = f'vtysh -c "configure terminal" -c "segment-routing" -c "srv6" -c "static-sids" -c "no sid {addr}/{48 + func_len} locator {locator} behavior uN"'
loc_cmd = f'vtysh -c "configure terminal" -c "segment-routing" -c "srv6" -c "locators" -c "no locator {locator}"'
dvs.runcmd(sid_cmd)
dvs.runcmd(loc_cmd)

@pytest.mark.skipif(LooseVersion(platform.release()) < LooseVersion('5.14'),
reason="This test requires Linux kernel 5.14 or higher")
def test_Srv6MySidUNTunnelDscpMode(self, dvs, testlog):
Expand All @@ -1327,16 +1343,19 @@ def test_Srv6MySidUNTunnelDscpMode(self, dvs, testlog):
tunnel_entries = get_exist_entries(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL")
tunnel_term_entries = get_exist_entries(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_TERM_TABLE_ENTRY")

mysid1 = "fc00:0:1::"
mysid2 = "fd00:0:1::"
mysid3 = "fe00:0:1:aabb::"

# Confiure the dcsp_mode in config db
self.add_mysid_cfgdb("loc1", "fc00:0:2::", "fc00:0:2:ff05::", "uniform")
self.add_mysid_cfgdb("loc2", "fd00:0:2::", "fd00:0:2:ff05::", "pipe")
self.add_mysid_cfgdb("loc3", "fe00:0:2::", "fe00:0:2:ff05::", "pipe")
self.add_mysid_cfgdb("loc1", mysid1, dscp_mode="uniform")
self.add_mysid_cfgdb("loc2", mysid2, dscp_mode="pipe")
self.add_mysid_cfgdb("loc3", mysid3, "fe00:0:1::", dscp_mode="pipe", func_len=16)

# Create MySID entry with dscp_mode uniform
dvs.runcmd("vtysh -c \"configure terminal\" -c \"segment-routing\" -c \"srv6\" -c \"locators\" -c \"locator loc1\" -c \"prefix fc00:0:2::/48 block-len 32 node-len 16 func-bits 16\" -c \"behavior usid\"")
dvs.runcmd("ip -6 route add fc00:0:2:ff05::/128 encap seg6local action End vrftable {} dev sr0".format(self.vrf_table_id))
# Create MySID entry with dscp_mode uniformß
self.add_mysid_vtysh(dvs, "loc1", mysid1)

self.pdb.wait_for_entry("SRV6_MY_SID_TABLE", "32:16:16:0:fc00:0:2:ff05::")
self.pdb.wait_for_entry("SRV6_MY_SID_TABLE", f"32:16:0:0:{mysid1}")
self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY", len(self.initial_my_sid_entries) + 1)
self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL", len(tunnel_entries) + 1)
self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_TERM_TABLE_ENTRY", len(tunnel_term_entries) + 1)
Expand All @@ -1345,10 +1364,9 @@ def test_Srv6MySidUNTunnelDscpMode(self, dvs, testlog):
mysid_uniform_term_entry = get_created_entry(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_TERM_TABLE_ENTRY", tunnel_term_entries)

# Create MySID entry with dscp_mode pipe
dvs.runcmd("vtysh -c \"configure terminal\" -c \"segment-routing\" -c \"srv6\" -c \"locators\" -c \"locator loc1\" -c \"prefix fd00:0:2::/48 block-len 32 node-len 16 func-bits 16\" -c \"behavior usid\"")
dvs.runcmd("ip -6 route add fd00:0:2:ff05::/128 encap seg6local action End vrftable {} dev sr0".format(self.vrf_table_id))
self.add_mysid_vtysh(dvs, "loc2", mysid2)

self.pdb.wait_for_entry("SRV6_MY_SID_TABLE", "32:16:16:0:fd00:0:2:ff05::")
self.pdb.wait_for_entry("SRV6_MY_SID_TABLE", f"32:16:0:0:{mysid2}")
self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY", len(self.initial_my_sid_entries) + 2)
self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL", len(tunnel_entries) + 2)
self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_TERM_TABLE_ENTRY", len(tunnel_term_entries) + 2)
Expand All @@ -1366,15 +1384,14 @@ def test_Srv6MySidUNTunnelDscpMode(self, dvs, testlog):

# Validate tunnel term configuration
self.verify_attribute_value(tunnel_term_table, mysid_uniform_term_entry, "SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_ACTION_TUNNEL_ID", tunnel_uniform)
self.verify_attribute_value(tunnel_term_table, mysid_uniform_term_entry, "SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_DST_IP", "fc00:0:2:ff05::")
self.verify_attribute_value(tunnel_term_table, mysid_uniform_term_entry, "SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_DST_IP", mysid1)
self.verify_attribute_value(tunnel_term_table, mysid_pipe_term_entry, "SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_ACTION_TUNNEL_ID", tunnel_pipe)
self.verify_attribute_value(tunnel_term_table, mysid_pipe_term_entry, "SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_DST_IP", "fd00:0:2:ff05::")
self.verify_attribute_value(tunnel_term_table, mysid_pipe_term_entry, "SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_DST_IP", mysid2)

# Add another MySID entry with dscp_mode pipe
dvs.runcmd("vtysh -c \"configure terminal\" -c \"segment-routing\" -c \"srv6\" -c \"locators\" -c \"locator loc1\" -c \"prefix fe00:0:2::/48 block-len 32 node-len 16 func-bits 16\" -c \"behavior usid\"")
dvs.runcmd("ip -6 route add fe00:0:2:ff05::/128 encap seg6local action End vrftable {} dev sr0".format(self.vrf_table_id))
self.add_mysid_vtysh(dvs, "loc3", mysid3, prefix="fe00:0:1::", func_len=16)

self.pdb.wait_for_entry("SRV6_MY_SID_TABLE", "32:16:16:0:fe00:0:2:ff05::")
self.pdb.wait_for_entry("SRV6_MY_SID_TABLE", f"32:16:16:0:{mysid3}")
self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY", len(self.initial_my_sid_entries) + 3)
self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL_TERM_TABLE_ENTRY", len(tunnel_term_entries) + 3)

Expand All @@ -1384,17 +1401,17 @@ def test_Srv6MySidUNTunnelDscpMode(self, dvs, testlog):
self.verify_attribute_value(my_sid_table, my_sid_pipe2, "SAI_MY_SID_ENTRY_ATTR_TUNNEL_ID", tunnel_pipe)

# Remove MySID entries
dvs.runcmd("ip -6 route del fc00:0:2:ff05::/128 encap seg6local action End vrftable {} dev sr0".format(self.vrf_table_id))
dvs.runcmd("ip -6 route del fd00:0:2:ff05::/128 encap seg6local action End vrftable {} dev sr0".format(self.vrf_table_id))
dvs.runcmd("ip -6 route del fe00:0:2:ff05::/128 encap seg6local action End vrftable {} dev sr0".format(self.vrf_table_id))
self.remove_mysid_vtysh(dvs, "loc1", mysid1)
self.remove_mysid_vtysh(dvs, "loc2", mysid2)
self.remove_mysid_vtysh(dvs, "loc3", mysid3, func_len=16)

self.pdb.wait_for_deleted_entry("SRV6_MY_SID_TABLE", "32:16:16:0:fc00:0:2:ff05::")
self.pdb.wait_for_deleted_entry("SRV6_MY_SID_TABLE", "32:16:16:0:fd00:0:2:ff05::")
self.pdb.wait_for_deleted_entry("SRV6_MY_SID_TABLE", "32:16:16:0:fe00:0:2:ff05::")
self.pdb.wait_for_deleted_entry("SRV6_MY_SID_TABLE", f"32:16:0:0:{mysid1}")
self.pdb.wait_for_deleted_entry("SRV6_MY_SID_TABLE", f"32:16:0:0:{mysid2}")
self.pdb.wait_for_deleted_entry("SRV6_MY_SID_TABLE", f"32:16:16:0:{mysid3}")

self.remove_mysid_cfgdb("loc1", "fc00:0:2:ff05::")
self.remove_mysid_cfgdb("loc2", "fd00:0:2:ff05::")
self.remove_mysid_cfgdb("loc3", "fe00:0:2:ff05::")
self.remove_mysid_cfgdb("loc1", mysid1)
self.remove_mysid_cfgdb("loc2", mysid2)
self.remove_mysid_cfgdb("loc3", mysid3, func_len=16)

# Verify that the MySID and tunnel configuration is removed
self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY", len(self.initial_my_sid_entries))
Expand All @@ -1406,6 +1423,66 @@ def test_Srv6MySidUNTunnelDscpMode(self, dvs, testlog):

self.teardown_srv6(dvs)

@pytest.mark.skipif(LooseVersion(platform.release()) < LooseVersion('5.14'),
reason="This test requires Linux kernel 5.14 or higher")
def test_Srv6MySidUNTunnelDscpModeAmbiguity(self, dvs, testlog):
_, output = dvs.runcmd(f"vtysh -c 'show zebra dplane providers'")
if 'dplane_fpm_sonic' not in output:
pytest.skip("'dplane_fpm_sonic' required for this test is not available, skipping", allow_module_level=True)

self.setup_srv6(dvs)

tunnel_table = swsscommon.Table(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL")
tunnel_entries = get_exist_entries(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL")

loc1_prefix = "aaaa:bbbb:1::"
loc2_prefix = "aaaa:bbbb:1:2::"
sid_addr = "aaaa:bbbb:1:2::/64"

# Add locator 1
dvs.runcmd(f'vtysh -c "configure terminal" -c "segment-routing" -c "srv6" -c "locators" -c "locator loc1" -c "prefix {loc1_prefix}/48 block-len 32 node-len 16 func-bits 16" -c "behavior usid"')
self.cdb.create_entry("SRV6_MY_LOCATORS", "loc1", {"prefix": loc1_prefix, "block_len": "32", "node_len": "16", "func_len": "16", "arg_len": "0"})

# Add locator 2
dvs.runcmd(f'vtysh -c "configure terminal" -c "segment-routing" -c "srv6" -c "locators" -c "locator loc2" -c "prefix {loc2_prefix}/64 block-len 32 node-len 32 func-bits 0" -c "behavior usid"')
self.cdb.create_entry("SRV6_MY_LOCATORS", "loc2", {"prefix": loc2_prefix, "block_len": "32", "node_len": "32", "func_len": "0", "arg_len": "0"})

# Add SIDs CONIFG_DB
self.cdb.create_entry("SRV6_MY_SIDS", f'loc1|{sid_addr}', {"decap_dscp_mode": "uniform"})
self.cdb.create_entry("SRV6_MY_SIDS", f'loc2|{sid_addr}', {"decap_dscp_mode": "pipe"})

# Add first SID
dvs.runcmd(f'vtysh -c "configure terminal" -c "segment-routing" -c "srv6" -c "static-sids" -c "sid {sid_addr} locator loc1 behavior uN"')

self.pdb.wait_for_entry("SRV6_MY_SID_TABLE", f"32:16:16:0:aaaa:bbbb:1:2::")
self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY", len(self.initial_my_sid_entries) + 1)
self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL", len(tunnel_entries) + 1)
tunnel_uniform = get_created_entry(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL", tunnel_entries)

# Add second SID
dvs.runcmd(f'vtysh -c "configure terminal" -c "segment-routing" -c "srv6" -c "static-sids" -c "sid {sid_addr} locator loc2 behavior uN"')

self.pdb.wait_for_entry("SRV6_MY_SID_TABLE", f"32:32:0:0:aaaa:bbbb:1:2::")
self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY", len(self.initial_my_sid_entries) + 2)
self.adb.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL", len(tunnel_entries) + 2)
tunnel_pipe = get_created_entry(self.adb.db_connection, "ASIC_STATE:SAI_OBJECT_TYPE_TUNNEL", tunnel_entries | set([tunnel_uniform]))

self.verify_attribute_value(tunnel_table, tunnel_uniform, "SAI_TUNNEL_ATTR_DECAP_DSCP_MODE", "SAI_TUNNEL_DSCP_MODE_UNIFORM_MODEL")
self.verify_attribute_value(tunnel_table, tunnel_pipe, "SAI_TUNNEL_ATTR_DECAP_DSCP_MODE", "SAI_TUNNEL_DSCP_MODE_PIPE_MODEL")

# Cleanup
dvs.runcmd(f'vtysh -c "configure terminal" -c "segment-routing" -c "srv6" -c "static-sids" -c "no sid {sid_addr} locator loc1 behavior uN"')
dvs.runcmd(f'vtysh -c "configure terminal" -c "segment-routing" -c "srv6" -c "static-sids" -c "no sid {sid_addr} locator loc2 behavior uN"')
dvs.runcmd(f'vtysh -c "configure terminal" -c "segment-routing" -c "srv6" -c "locators" -c "no locator loc1"')
dvs.runcmd(f'vtysh -c "configure terminal" -c "segment-routing" -c "srv6" -c "locators" -c "no locator loc2"')

self.cdb.delete_entry("SRV6_MY_SIDS", f'loc1|{sid_addr}')
self.cdb.delete_entry("SRV6_MY_SIDS", f'loc2|{sid_addr}')
self.cdb.delete_entry("SRV6_MY_LOCATORS", "loc1")
self.cdb.delete_entry("SRV6_MY_LOCATORS", "loc2")

dvs.runcmd("vtysh -c \"configure terminal\" -c \"segment-routing\" -c \"no srv6\"")
self.teardown_srv6(dvs)

class TestSrv6VpnFpmsyncd(object):
""" Functionality tests for SRv6 VPN handling in fpmsyncd """
Expand Down

0 comments on commit 0bba0ae

Please sign in to comment.