From e1654ba5548625981d2b9ff580b2fb6e2ae9d5dc Mon Sep 17 00:00:00 2001 From: Carmine Scarpitta Date: Fri, 7 Feb 2025 17:47:45 +0100 Subject: [PATCH 1/3] staticd: Fix SRv6 SID installation and deletion The SRv6 support in staticd (PR #16894) does not set the correct SID parameters (block length, node length, function length). This commit fixes the issue and computes the correct parameters. Signed-off-by: Carmine Scarpitta --- staticd/static_zebra.c | 62 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index 6da2dfec90..9a794d4d02 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -615,6 +615,9 @@ 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) return; @@ -696,10 +699,30 @@ void static_zebra_srv6_sid_install(struct static_srv6_sid *sid) break; } - ctx.block_len = sid->locator->block_bits_length; - ctx.node_len = sid->locator->node_bits_length; - ctx.function_len = sid->locator->function_bits_length; - ctx.argument_len = sid->locator->argument_bits_length; + 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; + } + + sid_locator = sid->addr; + sid_locator.prefixlen = sid->locator->block_bits_length + sid->locator->node_bits_length; + apply_mask(&sid_locator); + + if (prefix_same(&sid_locator, &sid->locator->prefix)) + ctx.node_len = sid->locator->node_bits_length; + + ctx.function_len = sid->addr.prefixlen - (ctx.block_len + ctx.node_len); /* Attach the SID to the SRv6 interface */ if (!ifp) { @@ -724,6 +747,9 @@ void static_zebra_srv6_sid_uninstall(struct static_srv6_sid *sid) struct interface *ifp = NULL; struct seg6local_context ctx = {}; struct vrf *vrf; + struct prefix_ipv6 sid_block = {}; + struct prefix_ipv6 locator_block = {}; + struct prefix_ipv6 sid_locator = {}; if (!sid) return; @@ -803,10 +829,30 @@ void static_zebra_srv6_sid_uninstall(struct static_srv6_sid *sid) } } - ctx.block_len = sid->locator->block_bits_length; - ctx.node_len = sid->locator->node_bits_length; - ctx.function_len = sid->locator->function_bits_length; - ctx.argument_len = sid->locator->argument_bits_length; + 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; + } + + sid_locator = sid->addr; + sid_locator.prefixlen = sid->locator->block_bits_length + sid->locator->node_bits_length; + apply_mask(&sid_locator); + + if (prefix_same(&sid_locator, &sid->locator->prefix)) + ctx.node_len = sid->locator->node_bits_length; + + ctx.function_len = sid->addr.prefixlen - (ctx.block_len + ctx.node_len); static_zebra_send_localsid(ZEBRA_ROUTE_DELETE, &sid->addr.prefix, sid->addr.prefixlen, ifp->ifindex, action, &ctx); From 312f7b3f8c7382afef6993aa2110326db2327c35 Mon Sep 17 00:00:00 2001 From: Carmine Scarpitta Date: Sat, 8 Feb 2025 22:17:09 +0100 Subject: [PATCH 2/3] lib: Add sidStructure in SRv6 SIDs JSON output The `show ipv6 route json` command displays the IPv6 routing table in JSON format, including SRv6 SIDs. For each SRv6 SID, it provides behavior and SID attributes. However, it does not include the SID structure. This commit adds the SID structure to the SRv6 SID JSON output. Signed-off-by: Carmine Scarpitta --- lib/nexthop.c | 5 +++++ lib/srv6.c | 8 ++++++++ lib/srv6.h | 1 + 3 files changed, 14 insertions(+) diff --git a/lib/nexthop.c b/lib/nexthop.c index ee6c2b7ec0..c377b9cb00 100644 --- a/lib/nexthop.c +++ b/lib/nexthop.c @@ -1153,6 +1153,7 @@ void nexthop_json_helper(json_object *json_nexthop, json_object *json_backups = NULL; json_object *json_seg6local = NULL; json_object *json_seg6local_context = NULL; + json_object *json_srv6_sid_structure = NULL; json_object *json_seg6 = NULL; json_object *json_segs = NULL; int i; @@ -1328,6 +1329,10 @@ void nexthop_json_helper(json_object *json_nexthop, json_object_object_add(json_nexthop, "seg6localContext", json_seg6local_context); + json_srv6_sid_structure = json_object_new_object(); + srv6_sid_structure2json(&nexthop->nh_srv6->seg6local_ctx, json_srv6_sid_structure); + json_object_object_add(json_seg6local, "sidStructure", json_srv6_sid_structure); + if (nexthop->nh_srv6->seg6_segs && nexthop->nh_srv6->seg6_segs->num_segs == 1) { json_seg6 = json_object_new_object(); diff --git a/lib/srv6.c b/lib/srv6.c index e6fc375fbb..c00aca3cab 100644 --- a/lib/srv6.c +++ b/lib/srv6.c @@ -71,6 +71,14 @@ int snprintf_seg6_segs(char *str, return strlen(str); } +void srv6_sid_structure2json(const struct seg6local_context *ctx, json_object *json) +{ + json_object_int_add(json, "blockLen", ctx->block_len); + json_object_int_add(json, "nodeLen", ctx->node_len); + json_object_int_add(json, "funcLen", ctx->function_len); + json_object_int_add(json, "argLen", ctx->argument_len); +} + void seg6local_context2json(const struct seg6local_context *ctx, uint32_t action, json_object *json) { diff --git a/lib/srv6.h b/lib/srv6.h index 7e4fb97ad1..011705504e 100644 --- a/lib/srv6.h +++ b/lib/srv6.h @@ -363,6 +363,7 @@ const char *seg6local_context2str(char *str, size_t size, uint32_t action); void seg6local_context2json(const struct seg6local_context *ctx, uint32_t action, json_object *json); +void srv6_sid_structure2json(const struct seg6local_context *ctx, json_object *json); static inline const char *srv6_sid_ctx2str(char *str, size_t size, const struct srv6_sid_ctx *ctx) From a6d02fe2fb38b8e0c2e1c25fd863f6f96c2c40a6 Mon Sep 17 00:00:00 2001 From: Carmine Scarpitta Date: Sat, 8 Feb 2025 22:26:13 +0100 Subject: [PATCH 3/3] tests: Extend SRv6 static SIDs topotest to verify SID structure The `static_srv6_sids` topotest verifies that staticd correctly programs the SIDs in the zebra RIB. Currently, the topotest only validates the programmed behavior and SID attributes. This commit extends the topotest to also validate the SID structure. Signed-off-by: Carmine Scarpitta --- .../static_srv6_sids/expected_srv6_sids.json | 32 ++++++++++++++++--- .../expected_srv6_sids_sid_delete_1.json | 24 ++++++++++++-- .../expected_srv6_sids_sid_delete_2.json | 16 ++++++++-- 3 files changed, 63 insertions(+), 9 deletions(-) diff --git a/tests/topotests/static_srv6_sids/expected_srv6_sids.json b/tests/topotests/static_srv6_sids/expected_srv6_sids.json index 5799d97988..de78878445 100644 --- a/tests/topotests/static_srv6_sids/expected_srv6_sids.json +++ b/tests/topotests/static_srv6_sids/expected_srv6_sids.json @@ -25,7 +25,13 @@ "active": true, "weight": 1, "seg6local": { - "action": "End" + "action": "End", + "sidStructure": { + "blockLen": 32, + "nodeLen": 16, + "funcLen": 0, + "argLen": 0 + } }, "seg6localContext": { @@ -60,7 +66,13 @@ "active": true, "weight": 1, "seg6local": { - "action": "End.DT4" + "action": "End.DT4", + "sidStructure": { + "blockLen": 32, + "nodeLen": 16, + "funcLen": 16, + "argLen": 0 + } }, "seg6localContext": { "table": 10 @@ -95,7 +107,13 @@ "active": true, "weight": 1, "seg6local": { - "action": "End.DT6" + "action": "End.DT6", + "sidStructure": { + "blockLen": 32, + "nodeLen": 16, + "funcLen": 16, + "argLen": 0 + } }, "seg6localContext": { "table": 20 @@ -130,7 +148,13 @@ "active": true, "weight": 1, "seg6local": { - "action": "End.DT46" + "action": "End.DT46", + "sidStructure": { + "blockLen": 32, + "nodeLen": 16, + "funcLen": 16, + "argLen": 0 + } }, "seg6localContext": { "table": 30 diff --git a/tests/topotests/static_srv6_sids/expected_srv6_sids_sid_delete_1.json b/tests/topotests/static_srv6_sids/expected_srv6_sids_sid_delete_1.json index e1a2a16afe..dd0850fb3c 100644 --- a/tests/topotests/static_srv6_sids/expected_srv6_sids_sid_delete_1.json +++ b/tests/topotests/static_srv6_sids/expected_srv6_sids_sid_delete_1.json @@ -25,7 +25,13 @@ "active": true, "weight": 1, "seg6local": { - "action": "End.DT4" + "action": "End.DT4", + "sidStructure": { + "blockLen": 32, + "nodeLen": 16, + "funcLen": 16, + "argLen": 0 + } }, "seg6localContext": { "table": 10 @@ -60,7 +66,13 @@ "active": true, "weight": 1, "seg6local": { - "action": "End.DT6" + "action": "End.DT6", + "sidStructure": { + "blockLen": 32, + "nodeLen": 16, + "funcLen": 16, + "argLen": 0 + } }, "seg6localContext": { "table": 20 @@ -95,7 +107,13 @@ "active": true, "weight": 1, "seg6local": { - "action": "End.DT46" + "action": "End.DT46", + "sidStructure": { + "blockLen": 32, + "nodeLen": 16, + "funcLen": 16, + "argLen": 0 + } }, "seg6localContext": { "table": 30 diff --git a/tests/topotests/static_srv6_sids/expected_srv6_sids_sid_delete_2.json b/tests/topotests/static_srv6_sids/expected_srv6_sids_sid_delete_2.json index b5801d354b..4051c01425 100644 --- a/tests/topotests/static_srv6_sids/expected_srv6_sids_sid_delete_2.json +++ b/tests/topotests/static_srv6_sids/expected_srv6_sids_sid_delete_2.json @@ -25,7 +25,13 @@ "active": true, "weight": 1, "seg6local": { - "action": "End.DT4" + "action": "End.DT4", + "sidStructure": { + "blockLen": 32, + "nodeLen": 16, + "funcLen": 16, + "argLen": 0 + } }, "seg6localContext": { "table": 10 @@ -60,7 +66,13 @@ "active": true, "weight": 1, "seg6local": { - "action": "End.DT46" + "action": "End.DT46", + "sidStructure": { + "blockLen": 32, + "nodeLen": 16, + "funcLen": 16, + "argLen": 0 + } }, "seg6localContext": { "table": 30