diff --git a/orchagent/srv6orch.cpp b/orchagent/srv6orch.cpp index 948d20b135..4b19973c68 100644 --- a/orchagent/srv6orch.cpp +++ b/orchagent/srv6orch.cpp @@ -125,18 +125,18 @@ bool Srv6Orch::getLocatorCfgFromDb(const string& locator, MySidLocatorCfg& cfg) bool Srv6Orch::reverseLookupLocator(const vector& 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; } } @@ -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()) diff --git a/tests/test_srv6.py b/tests/test_srv6.py index 1c7491b70a..326a03c25c 100644 --- a/tests/test_srv6.py +++ b/tests/test_srv6.py @@ -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): @@ -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) @@ -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) @@ -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) @@ -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)) @@ -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 """