Skip to content

Commit

Permalink
pathd: pathd support IPv6 address SID list
Browse files Browse the repository at this point in the history
command:

router2(config-sr-te)# segment-list test_srv6
router2(config-sr-te-segment-list)# index 10 ipv6-address
  X:X::X:X  IPv6 address
router2(config-sr-te-segment-list)# index 10 ipv6-address 100:1::1
router2(config-sr-te-segment-list)# index 20 ipv6-address 200:1::1
router2(config-sr-te-segment-list)# index 30 mpls label
  (16-1048575)  Label Value
router2(config-sr-te-segment-list)# index 30 mpls label 100
% Configuration failed.

Error type: validation
Error description: The Segment List(test_srv6) Type must be SRv6!
router2(config-sr-te-segment-list)#
router2(config-sr-te)# segment-list test_mpls
router2(config-sr-te-segment-list)# index 10 mpls label 100
router2(config-sr-te-segment-list)# index 20 mpls label 200
router2(config-sr-te-segment-list)# index 30 ipv6-address 1:1::1
% Configuration failed.

Error type: validation
Error description: The Segment List(test_mpls) Type must be MPLS!
router2(config-sr-te-segment-list)#

router2# configure
router2(config)# seg
router2(config-sr)# traffic-eng
router2(config-sr-te)# policy color 100 endpoint
  A.B.C.D   SR Policy endpoint IPv4 address
  X:X::X:X  SR Policy endpoint IPv6 address
router2(config-sr-te)# policy color 100 endpoint 1.1.1.1
  <cr>
router2(config-sr-te)# policy color 100 endpoint 1.1.1.1
router2(config-sr-te-policy)# candidate-path preference 1 name mpls explicit segment-list test_mpls
  <cr>
router2(config-sr-te-policy)# candidate-path preference 1 name mpls explicit segment-list test_mpls
router2(config-sr-te-policy)# candidate-path preference 2 name srv6 explicit segment-list test_srv6
% Configuration failed.

Error type: validation
Error description: The Segment List type(2) and Policy type(1) must match!
router2(config-sr-te-policy)# exit
router2(config-sr-te)# policy color 200 endpoint 1:1::1
router2(config-sr-te-policy)# candidate-path preference 1 name srv6 explicit segment-list test_srv6
router2(config-sr-te-policy)# candidate-path preference 2 name mpls explicit segment-list test_mpls
% Configuration failed.

Error type: validation
Error description: The Segment List type(1) and Policy type(2) must match!

config:

segment-routing
 traffic-eng
  segment-list test_srv6
   index 10 ipv6-address 100:1::1
   index 20 ipv6-address 200:1::1
  exit
  segment-list test_mpls
   index 10 mpls label 100
   index 20 mpls label 200
  exit
  policy color 100 endpoint 1.1.1.1
   candidate-path preference 1 name mpls explicit segment-list test_mpls
  exit
  policy color 200 endpoint 1:1::1
   candidate-path preference 1 name srv6 explicit segment-list test_srv6
  exit
 exit
exit
!
end

show:
router2# show sr-te policy detail

Endpoint: 1.1.1.1  Color: 100  Name:   BSID: -  Status: Inactive Type: MPLS
  * Preference: 1  Name: mpls  Type: explicit  Segment-List: test_mpls  Protocol-Origin: Local

Endpoint: 1:1::1  Color: 200  Name:   BSID: -  Status: Active Type: SRV6
  * Preference: 1  Name: srv6  Type: explicit  Segment-List: test_srv6  Protocol-Origin: Local

router2#

Signed-off-by: guozhongfeng.gzf <[email protected]>
  • Loading branch information
guoguojia2021 committed Dec 19, 2024
1 parent 8aa781b commit bed448b
Show file tree
Hide file tree
Showing 19 changed files with 545 additions and 130 deletions.
4 changes: 3 additions & 1 deletion lib/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,9 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_TC_FILTER_ADD),
DESC_ENTRY(ZEBRA_TC_FILTER_DELETE),
DESC_ENTRY(ZEBRA_OPAQUE_NOTIFY),
DESC_ENTRY(ZEBRA_SRV6_SID_NOTIFY)
DESC_ENTRY(ZEBRA_SRV6_SID_NOTIFY),
DESC_ENTRY(ZEBRA_SRV6_POLICY_SET),
DESC_ENTRY(ZEBRA_SRV6_POLICY_DELETE)
};
#undef DESC_ENTRY

Expand Down
18 changes: 18 additions & 0 deletions lib/prefix.c
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,24 @@ const char *prefix2str(union prefixconstptr pu, char *str, int size)
return str;
}

int prefix2ipaddr(union prefixconstptr pu, struct ipaddr *ip)
{
const struct prefix *p = pu.p;

memset(ip, 0, sizeof(struct ipaddr));

if (p->family == AF_INET) {
ip->ipa_type = IPADDR_V4;
IPV4_ADDR_COPY(&ip->ipaddr_v4, &p->u.prefix4);
} else if (p->family == AF_INET6) {
ip->ipa_type = IPADDR_V6;
IPV6_ADDR_COPY(&ip->ipaddr_v6, &p->u.prefix6);
} else
return -1;

return 0;
}

void prefix_mcast_ip_dump(const char *onfail, const struct ipaddr *addr,
char *buf, int buf_size)
{
Expand Down
1 change: 1 addition & 0 deletions lib/prefix.h
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ extern void prefix_mcast_inet4_dump(const char *onfail, struct in_addr addr,
extern const char *prefix_sg2str(const struct prefix_sg *sg, char *str);
extern const char *prefix2str(union prefixconstptr upfx, char *buffer,
int size);
extern int prefix2ipaddr(union prefixconstptr pu, struct ipaddr *ip);
extern int evpn_type5_prefix_match(const struct prefix *evpn_pfx,
const struct prefix *match_pfx);
extern int prefix_match(union prefixconstptr unet, union prefixconstptr upfx);
Expand Down
15 changes: 15 additions & 0 deletions lib/srv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,21 @@ int snprintf_seg6_segs(char *str,
return strlen(str);
}

int snprintf_seg6_seg_stack(char *str,
size_t size, const struct seg6_seg_stack *segs)
{
str[0] = '\0';
for (size_t i = 0; i < segs->num_segs; i++) {
char addr[INET6_ADDRSTRLEN];
bool not_last = (i + 1) < segs->num_segs;

inet_ntop(AF_INET6, &segs->seg[i], addr, sizeof(addr));
strlcat(str, addr, size);
strlcat(str, not_last ? "," : "", size);
}
return strlen(str);
}

void seg6local_context2json(const struct seg6local_context *ctx,
uint32_t action, json_object *json)
{
Expand Down
3 changes: 2 additions & 1 deletion lib/srv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,8 @@ static inline const char *srv6_sid_ctx2str(char *str, size_t size,

int snprintf_seg6_segs(char *str,
size_t size, const struct seg6_segs *segs);

int snprintf_seg6_seg_stack(char *str,
size_t size, const struct seg6_seg_stack *segs);
extern struct srv6_locator *srv6_locator_alloc(const char *name);
extern struct srv6_locator_chunk *srv6_locator_chunk_alloc(void);
extern void srv6_locator_free(struct srv6_locator *locator);
Expand Down
69 changes: 67 additions & 2 deletions lib/zclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -3849,8 +3849,14 @@ int tm_release_table_chunk(struct zclient *zclient, uint32_t start,
enum zclient_send_status zebra_send_sr_policy(struct zclient *zclient, int cmd,
struct zapi_sr_policy *zp)
{
if (zapi_sr_policy_encode(zclient->obuf, cmd, zp) < 0)
return ZCLIENT_SEND_FAILURE;
if (cmd == ZEBRA_SR_POLICY_SET || cmd == ZEBRA_SR_POLICY_DELETE) {
if (zapi_sr_policy_encode(zclient->obuf, cmd, zp) < 0)
return ZCLIENT_SEND_FAILURE;
} else if (cmd == ZEBRA_SRV6_POLICY_SET || cmd == ZEBRA_SRV6_POLICY_DELETE) {
if (zapi_srv6_policy_encode(zclient->obuf, cmd, zp) < 0)
return ZCLIENT_SEND_FAILURE;
}

return zclient_send_message(zclient);
}

Expand Down Expand Up @@ -3916,6 +3922,65 @@ int zapi_sr_policy_decode(struct stream *s, struct zapi_sr_policy *zp)
return -1;
}

int zapi_srv6_policy_encode(struct stream *s, int cmd, struct zapi_sr_policy *zp)
{
struct zapi_srv6te_tunnel *zt = &zp->segment_list_v6;

stream_reset(s);

zclient_create_header(s, cmd, VRF_DEFAULT);
stream_putl(s, zp->color);
stream_put_ipaddr(s, &zp->endpoint);
stream_write(s, &zp->name, SRTE_POLICY_NAME_MAX_LENGTH);

if (zt->seg_num > SRV6_MAX_SEGS) {
flog_err(EC_LIB_ZAPI_ENCODE,
"%s: seg: can't encode %u segs (maximum is %u)",
__func__, zt->seg_num, SRV6_MAX_SEGS);
return -1;
}

stream_putw(s, zt->seg_num);

for (int i = 0; i < zt->seg_num; i++)
stream_put_ipaddr(s, &zt->segs[i]);

/* Put length at the first point of the stream. */
stream_putw_at(s, 0, stream_get_endp(s));

return 0;
}

int zapi_srv6_policy_decode(struct stream *s, struct zapi_sr_policy *zp)
{
memset(zp, 0, sizeof(*zp));

struct zapi_srv6te_tunnel *zt = &zp->segment_list_v6;

STREAM_GETL(s, zp->color);
STREAM_GET_IPADDR(s, &zp->endpoint);
STREAM_GET(&zp->name, s, SRTE_POLICY_NAME_MAX_LENGTH);

/* segment list of active candidate path */
STREAM_GETW(s, zt->seg_num);

if (zt->seg_num > SRV6_MAX_SEGS) {
flog_err(EC_LIB_ZAPI_ENCODE,
"%s: seg: can't decode %u segs (maximum is %u)",
__func__, zt->seg_num, SRV6_MAX_SEGS);
return -1;
}

for (int i = 0; i < zt->seg_num; i++)
STREAM_GET_IPADDR(s, &zt->segs[i]);

return 0;

stream_failure:
return -1;
}


int zapi_sr_policy_notify_status_decode(struct stream *s,
struct zapi_sr_policy *zp)
{
Expand Down
10 changes: 10 additions & 0 deletions lib/zclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ typedef uint16_t zebra_size_t;
#define NEXTHOP_REGISTER_FLAG_RESOLVE_VIA_DEFAULT (1 << 1)
#define NEXTHOP_REGISTER_FLAG_COLOR (1 << 2)


/* Client capabilities */
enum zserv_client_capabilities {
ZEBRA_CLIENT_GR_CAPABILITIES = 1,
Expand Down Expand Up @@ -242,6 +243,8 @@ typedef enum {
ZEBRA_TC_FILTER_DELETE,
ZEBRA_OPAQUE_NOTIFY,
ZEBRA_SRV6_SID_NOTIFY,
ZEBRA_SRV6_POLICY_SET,
ZEBRA_SRV6_POLICY_DELETE,
} zebra_message_types_t;
/* Zebra message types. Please update the corresponding
* command_types array with any changes!
Expand Down Expand Up @@ -640,11 +643,16 @@ struct zapi_srte_tunnel {
mpls_label_t labels[MPLS_MAX_LABELS];
};

struct zapi_srv6te_tunnel {
uint8_t seg_num;
struct ipaddr segs[SRV6_MAX_SEGS];
};
struct zapi_sr_policy {
uint32_t color;
struct ipaddr endpoint;
char name[SRTE_POLICY_NAME_MAX_LENGTH];
struct zapi_srte_tunnel segment_list;
struct zapi_srv6te_tunnel segment_list_v6;
int status;
};

Expand Down Expand Up @@ -1110,6 +1118,8 @@ extern int zapi_sr_policy_decode(struct stream *s, struct zapi_sr_policy *zp);
extern int zapi_sr_policy_notify_status_decode(struct stream *s,
struct zapi_sr_policy *zp);

extern int zapi_srv6_policy_encode(struct stream *s, int cmd, struct zapi_sr_policy *zp);
extern int zapi_srv6_policy_decode(struct stream *s, struct zapi_sr_policy *zp);
extern enum zclient_send_status zebra_send_mpls_labels(struct zclient *zclient,
int cmd,
struct zapi_labels *zl);
Expand Down
116 changes: 84 additions & 32 deletions pathd/path_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ DEFPY(show_srte_policy,

/* Prepare table. */
tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
ttable_add_row(tt, "Endpoint|Color|Name|BSID|Status");
ttable_add_row(tt, "Endpoint|Color|Name|BSID|Status|Type");
tt->style.cell.rpad = 2;
tt->style.corner = '+';
ttable_restyle(tt);
Expand All @@ -121,11 +121,12 @@ DEFPY(show_srte_policy,
snprintf(binding_sid, sizeof(binding_sid), "%u",
policy->binding_sid);

ttable_add_row(tt, "%s|%u|%s|%s|%s", endpoint, policy->color,
policy->name, binding_sid,
policy->status == SRTE_POLICY_STATUS_UP
? "Active"
: "Inactive");
ttable_add_row(tt, "%s|%u|%s|%s|%s|%s", endpoint, policy->color,
policy->name, binding_sid,
policy->status == SRTE_POLICY_STATUS_UP ? "Active" : "Inactive",
policy->type == SRTE_POLICY_TYPE_MPLS
? "MPLS"
: (policy->type == SRTE_POLICY_TYPE_SRV6 ? "SRV6" : "Undefined"));
}

/* Dump the generated table. */
Expand Down Expand Up @@ -172,37 +173,60 @@ DEFPY(show_srte_policy_detail,
snprintf(binding_sid, sizeof(binding_sid), "%u",
policy->binding_sid);
vty_out(vty,
"Endpoint: %s Color: %u Name: %s BSID: %s Status: %s\n",
"Endpoint: %s Color: %u Name: %s BSID: %s Status: %s Type: %s\n",
endpoint, policy->color, policy->name, binding_sid,
policy->status == SRTE_POLICY_STATUS_UP ? "Active"
: "Inactive");
policy->status == SRTE_POLICY_STATUS_UP ? "Active" : "Inactive",
policy->type == SRTE_POLICY_TYPE_MPLS
? "MPLS"
: (policy->type == SRTE_POLICY_TYPE_SRV6 ? "SRV6" : "Undefined"));

RB_FOREACH (candidate, srte_candidate_head,
&policy->candidate_paths) {
struct srte_segment_list *segment_list;

segment_list = candidate->lsp->segment_list;
if (segment_list == NULL)
segment_list_info = undefined_info;
else if (segment_list->protocol_origin
== SRTE_ORIGIN_PCEP)
segment_list_info = created_by_pce_info;
else
segment_list_info =
candidate->lsp->segment_list->name;

vty_out(vty,
" %s Preference: %d Name: %s Type: %s Segment-List: %s Protocol-Origin: %s\n",
CHECK_FLAG(candidate->flags, F_CANDIDATE_BEST)
? "*"
: " ",
candidate->preference, candidate->name,
candidate->type == SRTE_CANDIDATE_TYPE_EXPLICIT
? "explicit"
: "dynamic",
segment_list_info,
srte_origin2str(
candidate->lsp->protocol_origin));
if (policy->type == SRTE_POLICY_TYPE_MPLS) {
segment_list = candidate->lsp->segment_list;
if (segment_list == NULL)
segment_list_info = undefined_info;
else if (segment_list->protocol_origin
== SRTE_ORIGIN_PCEP)
segment_list_info = created_by_pce_info;
else
segment_list_info =
candidate->lsp->segment_list->name;

vty_out(vty,
" %s Preference: %d Name: %s Type: %s Segment-List: %s Protocol-Origin: %s\n",
CHECK_FLAG(candidate->flags, F_CANDIDATE_BEST)
? "*"
: " ",
candidate->preference, candidate->name,
candidate->type == SRTE_CANDIDATE_TYPE_EXPLICIT
? "explicit"
: "dynamic",
segment_list_info,
srte_origin2str(
candidate->lsp->protocol_origin));
} else if (policy->type == SRTE_POLICY_TYPE_SRV6) {
segment_list = candidate->segment_list;
if (segment_list == NULL)
segment_list_info = undefined_info;
else
segment_list_info =
candidate->segment_list->name;

vty_out(vty,
" %s Preference: %d Name: %s Type: %s Segment-List: %s Protocol-Origin: %s\n",
CHECK_FLAG(candidate->flags, F_CANDIDATE_BEST)
? "*"
: " ",
candidate->preference, candidate->name,
candidate->type == SRTE_CANDIDATE_TYPE_EXPLICIT
? "explicit"
: "dynamic",
segment_list_info,
srte_origin2str(
candidate->protocol_origin));
}
}

vty_out(vty, "\n");
Expand Down Expand Up @@ -308,6 +332,7 @@ static int segment_list_has_src_dst(

struct ipaddr ip_src = {};
struct ipaddr ip_dst = {};

if (adj_src_ipv4_str != NULL) {
ip_src.ipa_type = IPADDR_V4;
ip_src.ip._v4_addr = adj_src_ipv4;
Expand Down Expand Up @@ -527,6 +552,24 @@ DEFPY(srte_segment_list_segment, srte_segment_list_segment_cmd,
return nb_cli_apply_changes(vty, NULL);
}

DEFPY_YANG(srv6te_segment_list_segment, srv6te_segment_list_segment_cmd,
"index (0-4294967295)$index ipv6-address X:X::X:X$ipv6_addr",
"Index\n"
"Index Value\n"
IPV6_STR
"IPv6 address\n")
{
char xpath[XPATH_MAXLEN];

snprintf(xpath, sizeof(xpath), "./segment[index='%s']", index_str);
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);

snprintf(xpath, sizeof(xpath),
"./segment[index='%s']/srv6-sid-value", index_str);
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, ipv6_addr_str);
return nb_cli_apply_changes(vty, NULL);
}

DEFPY(srte_segment_list_no_segment,
srte_segment_list_no_segment_cmd,
"no index (0-4294967295)$index",
Expand All @@ -547,10 +590,17 @@ void cli_show_srte_segment_list_segment(struct vty *vty,
bool show_defaults)
{
vty_out(vty, " index %s", yang_dnode_get_string(dnode, "index"));

if (yang_dnode_exists(dnode, "srv6-sid-value")) {
vty_out(vty, " ipv6-address %s",
yang_dnode_get_string(dnode, "srv6-sid-value"));
}

if (yang_dnode_exists(dnode, "sid-value")) {
vty_out(vty, " mpls label %s",
yang_dnode_get_string(dnode, "sid-value"));
}

if (yang_dnode_exists(dnode, "nai")) {
struct ipaddr addr;
struct ipaddr addr_rmt;
Expand Down Expand Up @@ -1331,6 +1381,8 @@ void path_cli_init(void)
install_element(SR_TRAFFIC_ENG_NODE, &srte_no_segment_list_cmd);
install_element(SR_SEGMENT_LIST_NODE,
&srte_segment_list_segment_cmd);
install_element(SR_SEGMENT_LIST_NODE,
&srv6te_segment_list_segment_cmd);
install_element(SR_SEGMENT_LIST_NODE,
&srte_segment_list_no_segment_cmd);
install_element(SR_TRAFFIC_ENG_NODE, &srte_policy_cmd);
Expand Down
8 changes: 8 additions & 0 deletions pathd/path_nb.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ const struct frr_yang_module_info frr_pathd_info = {
},
.priority = NB_DFLT_PRIORITY - 1
},
{
.xpath = "/frr-pathd:pathd/srte/segment-list/segment/srv6-sid-value",
.cbs = {
.modify = pathd_srte_segment_list_segment_v6_sid_value_modify,
.destroy = pathd_srte_segment_list_segment_v6_sid_value_destroy,
},
.priority = NB_DFLT_PRIORITY - 1
},
{
.xpath = "/frr-pathd:pathd/srte/segment-list/segment/nai",
.cbs = {
Expand Down
Loading

0 comments on commit bed448b

Please sign in to comment.