diff options
| author | Russ White <russ@riw.us> | 2025-02-26 09:52:08 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-02-26 09:52:08 -0500 |
| commit | 9a939d6ed60b31946a41d8a78953774f4f66bfb4 (patch) | |
| tree | cd10743b4ac4f309b214e5a38dc7de723cadfc8d /staticd | |
| parent | 1016090a8a5df21ccc11b489d00933fcbc7267b6 (diff) | |
| parent | 35b40cc996e9c5359e7ea724ed907986e5a05694 (diff) | |
Merge pull request #18198 from cscarpitta/feature/srv6_staticd_ua
staticd: Add support for SRv6 uA behavior
Diffstat (limited to 'staticd')
| -rw-r--r-- | staticd/static_nb.c | 21 | ||||
| -rw-r--r-- | staticd/static_nb.h | 16 | ||||
| -rw-r--r-- | staticd/static_nb_config.c | 107 | ||||
| -rw-r--r-- | staticd/static_vty.c | 46 | ||||
| -rw-r--r-- | staticd/static_zebra.c | 53 |
5 files changed, 237 insertions, 6 deletions
diff --git a/staticd/static_nb.c b/staticd/static_nb.c index ef363bfe7e..60dc3dc788 100644 --- a/staticd/static_nb.c +++ b/staticd/static_nb.c @@ -157,6 +157,27 @@ const struct frr_yang_module_info frr_staticd_info = { } }, { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/segment-routing/srv6/static-sids/sid/paths", + .cbs = { + .create = routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_create, + .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/segment-routing/srv6/static-sids/sid/paths/interface", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_interface_modify, + .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_interface_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/segment-routing/srv6/static-sids/sid/paths/next-hop", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_next_hop_modify, + .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_next_hop_destroy, + } + }, + { .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/segment-routing/srv6/static-sids/sid/locator-name", .cbs = { .modify = routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_locator_name_modify, diff --git a/staticd/static_nb.h b/staticd/static_nb.h index aa11f34021..282c9dcf11 100644 --- a/staticd/static_nb.h +++ b/staticd/static_nb.h @@ -96,6 +96,18 @@ int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routi struct nb_cb_modify_args *args); int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_vrf_name_destroy( struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_create( + struct nb_cb_create_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_interface_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_interface_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_next_hop_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_next_hop_destroy( + struct nb_cb_destroy_args *args); int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_locator_name_modify( struct nb_cb_modify_args *args); int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_locator_name_destroy( @@ -183,6 +195,10 @@ int routing_control_plane_protocols_name_validate( #define FRR_STATIC_SRV6_SID_LOCATOR_NAME_XPATH "/locator-name" +#define FRR_STATIC_SRV6_SID_INTERFACE_XPATH "/paths[path-index=%u]/interface" + +#define FRR_STATIC_SRV6_SID_NEXTHOP_XPATH "/paths[path-index=%u]/next-hop" + #ifdef __cplusplus } #endif diff --git a/staticd/static_nb_config.c b/staticd/static_nb_config.c index e2ab1f2ffe..71df15fa61 100644 --- a/staticd/static_nb_config.c +++ b/staticd/static_nb_config.c @@ -1231,6 +1231,113 @@ int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routi /* * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/segment-routing/srv6/locators/locator/static-sids/sid/paths + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_create( + struct nb_cb_create_args *args) +{ + /* Actual setting is done in apply_finish */ + return NB_OK; +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_destroy( + struct nb_cb_destroy_args *args) +{ + return NB_OK; +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/segment-routing/srv6/locators/locator/static-sids/sid/paths/interface + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_interface_modify( + struct nb_cb_modify_args *args) +{ + struct static_srv6_sid *sid; + const char *ifname; + + if (args->event != NB_EV_APPLY) + return NB_OK; + + sid = nb_running_get_entry(args->dnode, NULL, true); + + /* Release and uninstall existing SID, if any, before requesting the new one */ + if (CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID)) { + static_zebra_release_srv6_sid(sid); + UNSET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID); + } + + if (CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA)) { + static_zebra_srv6_sid_uninstall(sid); + UNSET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA); + } + + ifname = yang_dnode_get_string(args->dnode, "../interface"); + snprintf(sid->attributes.ifname, sizeof(sid->attributes.ifname), "%s", ifname); + + return NB_OK; +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_interface_destroy( + struct nb_cb_destroy_args *args) +{ + return NB_OK; +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/segment-routing/srv6/locators/locator/static-sids/sid/paths/next-hop + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_next_hop_modify( + struct nb_cb_modify_args *args) +{ + struct static_srv6_sid *sid; + struct ipaddr nexthop; + + switch (args->event) { + case NB_EV_VALIDATE: + zlog_info("validating nexthop %pI6", &nexthop.ipaddr_v6); + yang_dnode_get_ip(&nexthop, args->dnode, "../next-hop"); + if (!IS_IPADDR_V6(&nexthop)) { + snprintf(args->errmsg, args->errmsg_len, + "%% Nexthop must be an IPv6 address"); + return NB_ERR_VALIDATION; + } + break; + case NB_EV_ABORT: + case NB_EV_PREPARE: + break; + case NB_EV_APPLY: + sid = nb_running_get_entry(args->dnode, NULL, true); + + /* Release and uninstall existing SID, if any, before requesting the new one */ + if (CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID)) { + static_zebra_release_srv6_sid(sid); + UNSET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID); + } + + if (CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA)) { + static_zebra_srv6_sid_uninstall(sid); + UNSET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA); + } + + yang_dnode_get_ip(&nexthop, args->dnode, "../next-hop"); + sid->attributes.nh6 = nexthop.ipaddr_v6; + + break; + } + + return NB_OK; +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_next_hop_destroy( + struct nb_cb_destroy_args *args) +{ + return NB_OK; +} + +/* + * XPath: * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/segment-routing/srv6/locators/locator/static-sids/sid/vrf-name */ int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_locator_name_modify( diff --git a/staticd/static_vty.c b/staticd/static_vty.c index 5c19d23883..6e9087363d 100644 --- a/staticd/static_vty.c +++ b/staticd/static_vty.c @@ -1199,13 +1199,18 @@ DEFUN_NOSH (static_srv6_sids, static_srv6_sids_cmd, } DEFPY_YANG(srv6_sid, srv6_sid_cmd, - "sid X:X::X:X/M locator NAME$locator_name behavior <uN | uDT6 vrf VIEWVRFNAME | uDT4 vrf VIEWVRFNAME | uDT46 vrf VIEWVRFNAME>", + "sid X:X::X:X/M locator NAME$locator_name behavior <uN | uA interface INTERFACE$interface [nexthop X:X::X:X$nh6] | uDT6 vrf VIEWVRFNAME | uDT4 vrf VIEWVRFNAME | uDT46 vrf VIEWVRFNAME>", "Configure SRv6 SID\n" "Specify SRv6 SID\n" "Locator name\n" "Specify Locator name\n" "Specify SRv6 SID behavior\n" "Apply the code to a uN SID\n" + "Behavior uA\n" + "Configure the interface\n" + "Interface name\n" + "Configure the nexthop\n" + "IPv6 address of the nexthop\n" "Apply the code to an uDT6 SID\n" "Configure VRF name\n" "Specify VRF name\n" @@ -1223,7 +1228,10 @@ DEFPY_YANG(srv6_sid, srv6_sid_cmd, char xpath_sid[XPATH_MAXLEN]; char xpath_behavior[XPATH_MAXLEN]; char xpath_vrf_name[XPATH_MAXLEN]; + char xpath_ifname[XPATH_MAXLEN]; + char xpath_nexthop[XPATH_MAXLEN]; char xpath_locator_name[XPATH_MAXLEN]; + char ab_xpath[XPATH_MAXLEN]; if (argv_find(argv, argc, "uN", &idx)) { behavior = SRV6_ENDPOINT_BEHAVIOR_END_NEXT_CSID; @@ -1236,6 +1244,8 @@ DEFPY_YANG(srv6_sid, srv6_sid_cmd, } else if (argv_find(argv, argc, "uDT46", &idx)) { behavior = SRV6_ENDPOINT_BEHAVIOR_END_DT46_USID; vrf_name = argv[idx + 2]->arg; + } else if (argv_find(argv, argc, "uA", &idx)) { + behavior = SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID; } snprintf(xpath_srv6, sizeof(xpath_srv6), FRR_STATIC_SRV6_INFO_KEY_XPATH, @@ -1259,6 +1269,22 @@ DEFPY_YANG(srv6_sid, srv6_sid_cmd, nb_cli_enqueue_change(vty, xpath_vrf_name, NB_OP_MODIFY, vrf_name); } + if (interface) { + snprintf(ab_xpath, sizeof(ab_xpath), FRR_STATIC_SRV6_SID_INTERFACE_XPATH, 0); + strlcpy(xpath_ifname, xpath_sid, sizeof(xpath_ifname)); + strlcat(xpath_ifname, ab_xpath, sizeof(xpath_ifname)); + + nb_cli_enqueue_change(vty, xpath_ifname, NB_OP_MODIFY, interface); + } + + if (nh6_str) { + snprintf(ab_xpath, sizeof(ab_xpath), FRR_STATIC_SRV6_SID_NEXTHOP_XPATH, 0); + strlcpy(xpath_nexthop, xpath_sid, sizeof(xpath_nexthop)); + strlcat(xpath_nexthop, ab_xpath, sizeof(xpath_nexthop)); + + nb_cli_enqueue_change(vty, xpath_nexthop, NB_OP_MODIFY, nh6_str); + } + strlcpy(xpath_locator_name, xpath_sid, sizeof(xpath_locator_name)); strlcat(xpath_locator_name, FRR_STATIC_SRV6_SID_LOCATOR_NAME_XPATH, sizeof(xpath_locator_name)); @@ -1269,7 +1295,7 @@ DEFPY_YANG(srv6_sid, srv6_sid_cmd, } DEFPY_YANG(no_srv6_sid, no_srv6_sid_cmd, - "no sid X:X::X:X/M [locator NAME$locator_name] [behavior <uN | uDT6 vrf VIEWVRFNAME | uDT4 vrf VIEWVRFNAME | uDT46 vrf VIEWVRFNAME>]", + "no sid X:X::X:X/M [locator NAME$locator_name] [behavior <uN | uA interface INTERFACE$interface [nexthop X:X::X:X$nh6] | uDT6 vrf VIEWVRFNAME | uDT4 vrf VIEWVRFNAME | uDT46 vrf VIEWVRFNAME>]", NO_STR "Configure SRv6 SID\n" "Specify SRv6 SID\n" @@ -1277,6 +1303,11 @@ DEFPY_YANG(no_srv6_sid, no_srv6_sid_cmd, "Specify Locator name\n" "Specify SRv6 SID behavior\n" "Apply the code to a uN SID\n" + "Behavior uA\n" + "Configure the interface\n" + "Interface name\n" + "Configure the nexthop\n" + "IPv6 address of the nexthop\n" "Apply the code to an uDT6 SID\n" "Configure VRF name\n" "Specify VRF name\n" @@ -1685,6 +1716,7 @@ static void srv6_sid_cli_show(struct vty *vty, const struct lyd_node *sid, bool { enum srv6_endpoint_behavior_codepoint srv6_behavior; struct prefix_ipv6 sid_value; + struct ipaddr nexthop; yang_dnode_get_ipv6p(&sid_value, sid, "sid"); @@ -1756,6 +1788,16 @@ static void srv6_sid_cli_show(struct vty *vty, const struct lyd_node *sid, bool if (yang_dnode_exists(sid, "vrf-name")) vty_out(vty, " vrf %s", yang_dnode_get_string(sid, "vrf-name")); + if (yang_dnode_exists(sid, "paths[path-index=0]/interface")) { + vty_out(vty, " interface %s", + yang_dnode_get_string(sid, "paths[path-index=0]/interface")); + + if (yang_dnode_exists(sid, "paths[path-index=0]/next-hop")) { + yang_dnode_get_ip(&nexthop, sid, "paths[path-index=0]/next-hop"); + vty_out(vty, " nexthop %pI6", &nexthop.ipaddr_v6); + } + } + vty_out(vty, "\n"); } diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index 3faeb3d37a..a6521cccc6 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -706,12 +706,24 @@ void static_zebra_srv6_sid_install(struct static_srv6_sid *sid) return; } break; + case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID: + action = ZEBRA_SEG6_LOCAL_ACTION_END_X; + ctx.nh6 = sid->attributes.nh6; + ifp = if_lookup_by_name(sid->attributes.ifname, VRF_DEFAULT); + if (!ifp) { + zlog_warn("Failed to install SID %pFX: failed to get interface %s", + &sid->addr, sid->attributes.ifname); + return; + } + SET_SRV6_FLV_OP(ctx.flv.flv_ops, ZEBRA_SEG6_LOCAL_FLV_OP_NEXT_CSID); + ctx.flv.lcblock_len = sid->locator->block_bits_length; + ctx.flv.lcnode_func_len = sid->locator->node_bits_length; + break; case SRV6_ENDPOINT_BEHAVIOR_END_PSP_USD: case SRV6_ENDPOINT_BEHAVIOR_END_NEXT_CSID_PSP_USD: case SRV6_ENDPOINT_BEHAVIOR_END_X: case SRV6_ENDPOINT_BEHAVIOR_END_X_PSP: case SRV6_ENDPOINT_BEHAVIOR_END_X_PSP_USD: - case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID: case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID_PSP: case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID_PSP_USD: case SRV6_ENDPOINT_BEHAVIOR_OPAQUE: @@ -834,12 +846,20 @@ void static_zebra_srv6_sid_uninstall(struct static_srv6_sid *sid) return; } break; + case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID: + ctx.nh6 = sid->attributes.nh6; + ifp = if_lookup_by_name(sid->attributes.ifname, VRF_DEFAULT); + if (!ifp) { + zlog_warn("Failed to install SID %pFX: failed to get interface %s", + &sid->addr, sid->attributes.ifname); + return; + } + break; case SRV6_ENDPOINT_BEHAVIOR_END_PSP_USD: case SRV6_ENDPOINT_BEHAVIOR_END_NEXT_CSID_PSP_USD: case SRV6_ENDPOINT_BEHAVIOR_END_X: case SRV6_ENDPOINT_BEHAVIOR_END_X_PSP: case SRV6_ENDPOINT_BEHAVIOR_END_X_PSP_USD: - case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID: case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID_PSP: case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID_PSP_USD: case SRV6_ENDPOINT_BEHAVIOR_OPAQUE: @@ -894,6 +914,7 @@ extern void static_zebra_request_srv6_sid(struct static_srv6_sid *sid) struct srv6_sid_ctx ctx = {}; int ret = 0; struct vrf *vrf; + struct interface *ifp; if (!sid) return; @@ -945,12 +966,22 @@ extern void static_zebra_request_srv6_sid(struct static_srv6_sid *sid) } break; + case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID: + ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END_X; + ctx.nh6 = sid->attributes.nh6; + ifp = if_lookup_by_name(sid->attributes.ifname, VRF_DEFAULT); + if (!ifp) { + zlog_warn("Failed to request SRv6 SID %pFX: interface %s does not exist", + &sid->addr, sid->attributes.ifname); + return; + } + ctx.ifindex = ifp->ifindex; + break; case SRV6_ENDPOINT_BEHAVIOR_END_PSP_USD: case SRV6_ENDPOINT_BEHAVIOR_END_NEXT_CSID_PSP_USD: case SRV6_ENDPOINT_BEHAVIOR_END_X: case SRV6_ENDPOINT_BEHAVIOR_END_X_PSP: case SRV6_ENDPOINT_BEHAVIOR_END_X_PSP_USD: - case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID: case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID_PSP: case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID_PSP_USD: case SRV6_ENDPOINT_BEHAVIOR_OPAQUE: @@ -970,6 +1001,7 @@ extern void static_zebra_release_srv6_sid(struct static_srv6_sid *sid) struct srv6_sid_ctx ctx = {}; struct vrf *vrf; int ret = 0; + struct interface *ifp; if (!sid || !CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID)) return; @@ -1021,12 +1053,22 @@ extern void static_zebra_release_srv6_sid(struct static_srv6_sid *sid) } break; + case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID: + ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END_X; + ctx.nh6 = sid->attributes.nh6; + ifp = if_lookup_by_name(sid->attributes.ifname, VRF_DEFAULT); + if (!ifp) { + zlog_warn("Failed to request SRv6 SID %pFX: interface %s does not exist", + &sid->addr, sid->attributes.ifname); + return; + } + ctx.ifindex = ifp->ifindex; + break; case SRV6_ENDPOINT_BEHAVIOR_END_PSP_USD: case SRV6_ENDPOINT_BEHAVIOR_END_NEXT_CSID_PSP_USD: case SRV6_ENDPOINT_BEHAVIOR_END_X: case SRV6_ENDPOINT_BEHAVIOR_END_X_PSP: case SRV6_ENDPOINT_BEHAVIOR_END_X_PSP_USD: - case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID: case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID_PSP: case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID_PSP_USD: case SRV6_ENDPOINT_BEHAVIOR_OPAQUE: @@ -1244,6 +1286,9 @@ static int static_zebra_srv6_sid_notify(ZAPI_CALLBACK_ARGS) return 0; } + if (!IPV6_ADDR_SAME(&ctx.nh6, &in6addr_any)) + sid->attributes.nh6 = ctx.nh6; + SET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID); /* |
