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 <rajasekarr@nvidia.com>
This commit is contained in:
Rajasekar Raja 2025-04-04 13:27:03 -07:00
parent 259ffe1dfe
commit dbd9fed0b3
2 changed files with 56 additions and 19 deletions

View file

@ -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` */

View file

@ -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