From: Rajasekar Raja Date: Fri, 4 Apr 2025 20:27:03 +0000 (-0700) Subject: staticd: Avoid requesting SRv6 sid from zebra when loc and sid block dont match X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=dbd9fed0b30dd1d3475686f71f87d326eeafd26c;p=matthieu%2Ffrr.git staticd: Avoid requesting SRv6 sid from zebra when loc and sid block dont match Currently, when the locator block and sid block differs, staticd would still go ahead and request zebra to allocate the SID which it does if there is atleast one match (from any locators). Only when staticd tries to install the route, it sees that the locator block and sid block are different and avoids installing the route. Fix: Check if the locator block and sid block match before even requesting Zebra to allocate one. Signed-off-by: Rajasekar Raja --- diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index 3ed525f386..e3b646a392 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -625,8 +625,6 @@ void static_zebra_srv6_sid_install(struct static_srv6_sid *sid) struct seg6local_context ctx = {}; struct interface *ifp = NULL; struct vrf *vrf; - struct prefix_ipv6 sid_block = {}; - struct prefix_ipv6 locator_block = {}; struct prefix_ipv6 sid_locator = {}; if (!sid) @@ -738,22 +736,7 @@ void static_zebra_srv6_sid_install(struct static_srv6_sid *sid) break; } - sid_block = sid->addr; - sid_block.prefixlen = sid->locator->block_bits_length; - apply_mask(&sid_block); - - locator_block = sid->locator->prefix; - locator_block.prefixlen = sid->locator->block_bits_length; - apply_mask(&locator_block); - - if (prefix_same(&sid_block, &locator_block)) - ctx.block_len = sid->locator->block_bits_length; - else { - zlog_warn("SID block %pFX does not match locator block %pFX", &sid_block, - &locator_block); - return; - } - + ctx.block_len = sid->locator->block_bits_length; sid_locator = sid->addr; sid_locator.prefixlen = sid->locator->block_bits_length + sid->locator->node_bits_length; apply_mask(&sid_locator); @@ -915,6 +898,30 @@ void static_zebra_srv6_sid_uninstall(struct static_srv6_sid *sid) UNSET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA); } +/* Validate if the sid block and locator block are the same */ +static bool static_zebra_sid_locator_block_check(struct static_srv6_sid *sid) +{ + struct prefix_ipv6 sid_block = {}; + struct prefix_ipv6 locator_block = {}; + + sid_block = sid->addr; + sid_block.prefixlen = sid->locator->block_bits_length; + apply_mask(&sid_block); + + locator_block = sid->locator->prefix; + locator_block.prefixlen = sid->locator->block_bits_length; + apply_mask(&locator_block); + + if (!prefix_same(&sid_block, &locator_block)) { + zlog_warn("SID block %pFX does not match locator block %pFX", &sid_block, + &locator_block); + + return false; + } + + return true; +} + extern void static_zebra_request_srv6_sid(struct static_srv6_sid *sid) { struct srv6_sid_ctx ctx = {}; @@ -922,7 +929,7 @@ extern void static_zebra_request_srv6_sid(struct static_srv6_sid *sid) struct vrf *vrf; struct interface *ifp; - if (!sid) + if (!sid || !static_zebra_sid_locator_block_check(sid)) return; /* convert `srv6_endpoint_behavior_codepoint` to `seg6local_action_t` */ diff --git a/tests/topotests/static_srv6_sids/test_static_srv6_sids.py b/tests/topotests/static_srv6_sids/test_static_srv6_sids.py index 1ea94c8c07..abf49df046 100755 --- a/tests/topotests/static_srv6_sids/test_static_srv6_sids.py +++ b/tests/topotests/static_srv6_sids/test_static_srv6_sids.py @@ -210,6 +210,36 @@ def test_srv6_static_sids_sid_modify(): check_srv6_static_sids(router, "expected_srv6_sids_sid_modify.json") +def test_srv6_static_sids_wrong_sid_block(): + """ + The purpose of this test is to verify how FRR behaves when the user + provides an invalid configuration. + Add a new static Sid with a mismatch in locator and sid block + to make sure no Sid is allocated by zebra (TBD: Strict verify once show cmd + commit is merged (#16836)) + """ + router = get_topogen().gears["r1"] + router.vtysh_cmd( + """ + configure terminal + segment-routing + srv6 + locators + locator MAIN1 + prefix fcbb:1234:1::/48 block-len 32 node-len 16 func-bits 16 + srv6 + static-sids + sid fcbb:bbbb:1:fe50::/64 locator MAIN1 behavior uA interface sr0 nexthop 2001::3 + """ + ) + + output = json.loads(router.vtysh_cmd("show ipv6 route static json")) + if "fcbb:bbbb:1:fe50::/64" in output: + assert ( + False + ), "Failed. Expected no entry for fcbb:bbbb:1:fe50::/64 since loc and node block dont match" + + def test_srv6_static_sids_sid_delete_all(): """ Remove all static SIDs and verify they get removed