pathd. TED support . Validation of candidate path - [part 2/4]

- Explicit segment list nai will be resolved to corresponded sid.
    - Dynamic segment list (from pce) will be validated.
    - If segment list could not be resolved or validated won't be used.
    - Now this new config is supported

segment-list sl-1
 index 10  nai prefix 10.1.2.1/32 iface 1
 index 30  nai adjacency 10.2.5.2 10.2.5.5
 index 40  nai prefix 10.10.10.5/32 algorithm 0

Signed-off-by: Javier Garcia <javier.garcia@voltanet.io>
This commit is contained in:
Javier Garcia 2021-04-22 16:04:42 +02:00
parent 75c69d151c
commit f2b9485d6f
8 changed files with 747 additions and 119 deletions

View File

@ -34,6 +34,7 @@
#ifndef VTYSH_EXTRACT_PL
#include "pathd/path_cli_clippy.c"
#endif
#include "pathd/path_ted.h"
#define XPATH_MAXATTRSIZE 64
#define XPATH_MAXKEYSIZE 42
@ -47,6 +48,18 @@ static int config_write_segment_routing(struct vty *vty);
static int config_write_traffic_eng(struct vty *vty);
static int config_write_segment_lists(struct vty *vty);
static int config_write_sr_policies(struct vty *vty);
static int segment_list_has_src_dst(
struct vty *vty, char *xpath, long index, const char *index_str,
struct in_addr adj_src_ipv4, struct in_addr adj_dst_ipv4,
struct in6_addr adj_src_ipv6, struct in6_addr adj_dst_ipv6,
const char *adj_src_ipv4_str, const char *adj_dst_ipv4_str,
const char *adj_src_ipv6_str, const char *adj_dst_ipv6_str);
static int segment_list_has_prefix(
struct vty *vty, char *xpath, long index, const char *index_str,
const struct prefix_ipv4 *prefix_ipv4, const char *prefix_ipv4_str,
const struct prefix_ipv6 *prefix_ipv6, const char *prefix_ipv6_str,
const char *has_algo, long algo, const char *algo_str,
const char *has_iface_id, long iface_id, const char *iface_id_str);
DEFINE_MTYPE_STATIC(PATHD, PATH_CLI, "Client");
@ -144,6 +157,7 @@ DEFPY(show_srte_policy,
return CMD_SUCCESS;
}
/*
* Show detailed SR-TE info
*/
@ -295,56 +309,227 @@ void cli_show_srte_segment_list(struct vty *vty, struct lyd_node *dnode,
yang_dnode_get_string(dnode, "./name"));
}
static int segment_list_has_src_dst(
struct vty *vty, char *xpath, long index, const char *index_str,
struct in_addr adj_src_ipv4, struct in_addr adj_dst_ipv4,
struct in6_addr adj_src_ipv6, struct in6_addr adj_dst_ipv6,
const char *adj_src_ipv4_str, const char *adj_dst_ipv4_str,
const char *adj_src_ipv6_str, const char *adj_dst_ipv6_str)
{
const char *node_src_id;
uint32_t ted_sid = MPLS_LABEL_NONE;
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;
ip_dst.ipa_type = IPADDR_V4;
ip_dst.ip._v4_addr = adj_dst_ipv4;
} else if (adj_src_ipv6_str != NULL) {
ip_src.ipa_type = IPADDR_V6;
ip_src.ip._v6_addr = adj_src_ipv6;
ip_dst.ipa_type = IPADDR_V6;
ip_dst.ip._v6_addr = adj_dst_ipv6;
} else {
return CMD_ERR_NO_MATCH;
}
ted_sid = path_ted_query_type_f(&ip_src, &ip_dst);
if (ted_sid == MPLS_LABEL_NONE) {
zlog_warn(
"%s: [rcv ted] CLI NOT FOUND Continue query_type_f SRC (%pIA) DST (%pIA)!",
__func__, &ip_src, &ip_dst);
}
/* type */
snprintf(xpath, XPATH_MAXLEN, "./segment[index='%s']/nai/type",
index_str);
if (adj_src_ipv4_str != NULL) {
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
"ipv4_adjacency");
node_src_id = adj_src_ipv4_str;
} else if (adj_src_ipv6_str != NULL) {
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
"ipv6_adjacency");
node_src_id = adj_src_ipv6_str;
} else {
return CMD_ERR_NO_MATCH;
}
/* addresses */
snprintf(xpath, XPATH_MAXLEN, "./segment[index='%s']/nai/local-address",
index_str);
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, node_src_id);
snprintf(xpath, XPATH_MAXLEN,
"./segment[index='%s']/nai/remote-address", index_str);
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
adj_dst_ipv4_str ? adj_dst_ipv4_str
: adj_dst_ipv6_str);
return CMD_SUCCESS;
}
int segment_list_has_prefix(
struct vty *vty, char *xpath, long index, const char *index_str,
const struct prefix_ipv4 *prefix_ipv4, const char *prefix_ipv4_str,
const struct prefix_ipv6 *prefix_ipv6, const char *prefix_ipv6_str,
const char *has_algo, long algo, const char *algo_str,
const char *has_iface_id, long iface_id, const char *iface_id_str)
{
char buf_prefix[INET6_ADDRSTRLEN];
uint32_t ted_sid = MPLS_LABEL_NONE;
struct prefix prefix_cli = {};
struct ipaddr pre_ipaddr = {};
/* prefix with algorithm or local interface id */
/* Type */
snprintf(xpath, XPATH_MAXLEN, "./segment[index='%s']/nai/type",
index_str);
if (has_iface_id != NULL) {
if (prefix_ipv4_str != NULL) {
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
"ipv4_local_iface");
} else if (prefix_ipv6_str != NULL) {
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
"ipv6_local_iface");
} else {
return CMD_ERR_NO_MATCH;
}
} else {
if (prefix_ipv4_str != NULL) {
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
"ipv4_algo");
} else if (prefix_ipv6_str != NULL) {
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
"ipv6_algo");
} else {
return CMD_ERR_NO_MATCH;
}
}
/* Prefix */
if (prefix_ipv4_str != NULL) {
if (!str2prefix(prefix_ipv4_str, &prefix_cli)) {
vty_out(vty, "%% Malformed prefix\n");
return CMD_WARNING_CONFIG_FAILED;
}
inet_ntop(AF_INET, &prefix_cli.u.prefix4, buf_prefix,
sizeof(buf_prefix));
pre_ipaddr.ipa_type = IPADDR_V4;
pre_ipaddr.ip._v4_addr = prefix_cli.u.prefix4;
} else if (prefix_ipv6_str != NULL) {
if (!str2prefix(prefix_ipv6_str, &prefix_cli)) {
vty_out(vty, "%% Malformed prefix\n");
return CMD_WARNING_CONFIG_FAILED;
}
inet_ntop(AF_INET6, &prefix_cli.u.prefix6, buf_prefix,
sizeof(buf_prefix));
pre_ipaddr.ipa_type = IPADDR_V6;
pre_ipaddr.ip._v6_addr = prefix_cli.u.prefix6;
} else {
return CMD_ERR_NO_MATCH;
}
snprintf(xpath, XPATH_MAXLEN, "./segment[index='%s']/nai/local-address",
index_str);
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, buf_prefix);
snprintf(xpath, XPATH_MAXLEN,
"./segment[index='%s']/nai/local-prefix-len", index_str);
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
prefix_ipv4_str
? strchr(prefix_ipv4_str, '/') + 1
: strchr(prefix_ipv6_str, '/') + 1);
/* Alg / Iface */
if (has_algo != NULL) {
snprintf(xpath, XPATH_MAXLEN,
"./segment[index='%s']/nai/algorithm", index_str);
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, algo_str);
} else {
if (has_iface_id != NULL) {
snprintf(xpath, XPATH_MAXLEN,
"./segment[index='%s']/nai/local-interface",
index_str);
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
iface_id_str);
}
}
if (has_algo != NULL) {
ted_sid = path_ted_query_type_c(&prefix_cli, algo);
if (ted_sid == MPLS_LABEL_NONE) {
zlog_err(
"%s: [rcv ted] CLI NOT FOUND Continue query_type_c PREFIX (%pIA/%d) ALGO (%ld) sid:(%d)!",
__func__, &pre_ipaddr, prefix_cli.prefixlen,
algo, ted_sid);
}
}
if (has_iface_id != NULL) {
ted_sid = path_ted_query_type_e(&prefix_cli, iface_id);
if (ted_sid == MPLS_LABEL_NONE) {
zlog_err(
"%s: [rcv ted] CLI NOT FOUND Continue query_type_e PREFIX (%pIA/%d) IFACE (%ld) sid:(%d)!",
__func__, &pre_ipaddr, prefix_cli.prefixlen,
iface_id, ted_sid);
}
}
return CMD_SUCCESS;
}
/*
* XPath: /frr-pathd:pathd/srte/segment-list/segment
*/
DEFPY(srte_segment_list_segment,
srte_segment_list_segment_cmd,
"index (0-4294967295)$index mpls label (16-1048575)$label "
/* clang-format off */
DEFPY(srte_segment_list_segment, srte_segment_list_segment_cmd,
"index (0-4294967295)$index <[mpls$has_mpls_label label (16-1048575)$label] "
"|"
"[nai$has_nai <"
"node <A.B.C.D$node_ipv4|X:X::X:X$node_ipv6>"
">]",
"prefix <A.B.C.D/M$prefix_ipv4|X:X::X:X/M$prefix_ipv6>"
"<algorithm$has_algo (0-1)$algo| iface$has_iface_id (0-4294967295)$iface_id>"
"| adjacency$has_adj "
"<A.B.C.D$adj_src_ipv4 A.B.C.D$adj_dst_ipv4|X:X::X:X$adj_src_ipv6 X:X::X:X$adj_dst_ipv6>"
">]"
">",
"Index\n"
"Index Value\n"
"MPLS or IP Label\n"
"Label\n"
"Label Value\n"
"Segment NAI\n"
"NAI node identifier\n"
"NAI IPv4 node identifier\n"
"NAI IPv6 node identifier\n")
"NAI prefix identifier\n"
"NAI IPv4 prefix identifier\n"
"NAI IPv6 prefix identifier\n"
"IGP Algorithm\n"
"Algorithm Value SPF or Strict-SPF\n"
"Interface Id\n"
"Interface Value\n"
"ADJ identifier\n"
"ADJ IPv4 src identifier\n"
"ADJ IPv4 dst identifier\n"
"ADJ IPv6 src identifier\n"
"ADJ IPv6 dst identifier\n")
/* clang-format on */
{
char xpath[XPATH_MAXLEN];
const char *node_id;
int status = CMD_SUCCESS;
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']/sid-value",
index_str);
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, label_str);
if (has_nai != NULL) {
snprintf(xpath, sizeof(xpath), "./segment[index='%s']/nai/type",
index_str);
if (node_ipv4_str != NULL) {
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
"ipv4_node");
node_id = node_ipv4_str;
} else if (node_ipv6_str != NULL) {
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
"ipv6_node");
node_id = node_ipv6_str;
} else {
return CMD_ERR_NO_MATCH;
}
if (has_mpls_label != NULL) {
snprintf(xpath, sizeof(xpath),
"./segment[index='%s']/nai/local-address", index_str);
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, node_id);
"./segment[index='%s']/sid-value", index_str);
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, label_str);
return nb_cli_apply_changes(vty, NULL);
}
if (has_adj != NULL) {
status = segment_list_has_src_dst(vty, xpath, index, index_str,
adj_src_ipv4, adj_dst_ipv4,
adj_src_ipv6, adj_dst_ipv6,
adj_src_ipv4_str, adj_dst_ipv4_str,
adj_dst_ipv6_str, adj_src_ipv6_str);
if (status != CMD_SUCCESS)
return status;
} else {
snprintf(xpath, sizeof(xpath), "./segment[index='%s']/nai",
index_str);
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
segment_list_has_prefix(
vty, xpath, index, index_str, prefix_ipv4,
prefix_ipv4_str, prefix_ipv6, prefix_ipv6_str, has_algo,
algo, algo_str, has_iface_id, iface_id, iface_id_str);
if (status != CMD_SUCCESS)
return status;
}
return nb_cli_apply_changes(vty, NULL);
@ -369,23 +554,60 @@ void cli_show_srte_segment_list_segment(struct vty *vty,
struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " index %s mpls label %s",
yang_dnode_get_string(dnode, "./index"),
yang_dnode_get_string(dnode, "./sid-value"));
vty_out(vty, " index %s ", yang_dnode_get_string(dnode, "./index"));
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;
switch (yang_dnode_get_enum(dnode, "./nai/type")) {
case SRTE_SEGMENT_NAI_TYPE_IPV4_NODE:
case SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE:
case SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM:
yang_dnode_get_ip(&addr, dnode, "./nai/local-address");
vty_out(vty, " nai node %pI4", &addr.ipaddr_v4);
vty_out(vty, " nai prefix %pI4", &addr.ipaddr_v4);
break;
case SRTE_SEGMENT_NAI_TYPE_IPV6_NODE:
case SRTE_SEGMENT_NAI_TYPE_IPV6_LOCAL_IFACE:
case SRTE_SEGMENT_NAI_TYPE_IPV6_ALGORITHM:
yang_dnode_get_ip(&addr, dnode, "./nai/local-address");
vty_out(vty, " nai node %pI6", &addr.ipaddr_v6);
vty_out(vty, " nai prefix %pI6", &addr.ipaddr_v6);
break;
case SRTE_SEGMENT_NAI_TYPE_IPV4_ADJACENCY:
yang_dnode_get_ip(&addr, dnode, "./nai/local-address");
yang_dnode_get_ip(&addr_rmt, dnode,
"./nai/remote-address");
vty_out(vty, " nai adjacency %pI4", &addr.ipaddr_v4);
vty_out(vty, " %pI4", &addr_rmt.ipaddr_v4);
break;
case SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY:
yang_dnode_get_ip(&addr, dnode, "./nai/local-address");
yang_dnode_get_ip(&addr_rmt, dnode,
"./nai/remote-address");
vty_out(vty, " nai adjacency %pI6", &addr.ipaddr_v6);
vty_out(vty, " %pI6", &addr_rmt.ipaddr_v6);
break;
default:
break;
}
if (yang_dnode_exists(dnode, "./nai/local-prefix-len")) {
vty_out(vty, "/%s",
yang_dnode_get_string(
dnode, "./nai/local-prefix-len"));
}
if (yang_dnode_exists(dnode, "./nai/local-interface")) {
vty_out(vty, " iface %s",
yang_dnode_get_string(dnode,
"./nai/local-interface"));
}
if (yang_dnode_exists(dnode, "./nai/algorithm")) {
vty_out(vty, " algorithm %s",
yang_dnode_get_string(dnode,
"./nai/algorithm"));
}
}
vty_out(vty, "\n");
}
@ -1038,6 +1260,7 @@ int config_write_segment_routing(struct vty *vty)
int config_write_traffic_eng(struct vty *vty)
{
vty_out(vty, " traffic-eng\n");
path_ted_config_write(vty);
return 1;
}

View File

@ -90,6 +90,7 @@ const struct frr_yang_module_info frr_pathd_info = {
.xpath = "/frr-pathd:pathd/srte/segment-list/segment/sid-value",
.cbs = {
.modify = pathd_srte_segment_list_segment_sid_value_modify,
.destroy = pathd_srte_segment_list_segment_sid_value_destroy,
},
.priority = NB_DFLT_PRIORITY - 1
},
@ -114,6 +115,10 @@ const struct frr_yang_module_info frr_pathd_info = {
.xpath = "/frr-pathd:pathd/srte/segment-list/segment/nai/local-interface",
.cbs = {.modify = dummy_modify, .destroy = dummy_destroy}
},
{
.xpath = "/frr-pathd:pathd/srte/segment-list/segment/nai/local-prefix-len",
.cbs = {.modify = dummy_modify, .destroy = dummy_destroy}
},
{
.xpath = "/frr-pathd:pathd/srte/segment-list/segment/nai/remote-address",
.cbs = {.modify = dummy_modify, .destroy = dummy_destroy}
@ -122,6 +127,10 @@ const struct frr_yang_module_info frr_pathd_info = {
.xpath = "/frr-pathd:pathd/srte/segment-list/segment/nai/remote-interface",
.cbs = {.modify = dummy_modify, .destroy = dummy_destroy}
},
{
.xpath = "/frr-pathd:pathd/srte/segment-list/segment/nai/algorithm",
.cbs = {.modify = dummy_modify, .destroy = dummy_destroy}
},
{
.xpath = "/frr-pathd:pathd/srte/policy",
.cbs = {

View File

@ -43,6 +43,8 @@ int pathd_srte_segment_list_segment_nai_destroy(
struct nb_cb_destroy_args *args);
void pathd_srte_segment_list_segment_nai_apply_finish(
struct nb_cb_apply_finish_args *args);
int pathd_srte_segment_list_segment_sid_value_destroy(
struct nb_cb_destroy_args *args);
int pathd_srte_policy_create(struct nb_cb_create_args *args);
int pathd_srte_policy_destroy(struct nb_cb_destroy_args *args);
const void *pathd_srte_policy_get_next(struct nb_cb_get_next_args *args);

View File

@ -160,6 +160,22 @@ int pathd_srte_segment_list_segment_sid_value_modify(
return NB_OK;
}
int pathd_srte_segment_list_segment_sid_value_destroy(
struct nb_cb_destroy_args *args)
{
struct srte_segment_entry *segment;
if (args->event != NB_EV_APPLY)
return NB_OK;
segment = nb_running_get_entry(args->dnode, NULL, true);
segment->sid_value = MPLS_LABEL_NONE;
SET_FLAG(segment->segment_list->flags, F_SEGMENT_LIST_MODIFIED);
return NB_OK;
}
int pathd_srte_segment_list_segment_nai_destroy(struct nb_cb_destroy_args *args)
{
struct srte_segment_entry *segment;
@ -184,6 +200,8 @@ void pathd_srte_segment_list_segment_nai_apply_finish(
enum srte_segment_nai_type type;
struct ipaddr local_addr, remote_addr;
uint32_t local_iface = 0, remote_iface = 0;
uint8_t algo = 0, local_prefix_len = 0;
const char *algo_buf, *local_prefix_len_buf;
segment = nb_running_get_entry(args->dnode, NULL, true);
type = yang_dnode_get_enum(args->dnode, "./type");
@ -207,12 +225,31 @@ void pathd_srte_segment_list_segment_nai_apply_finish(
remote_iface = yang_dnode_get_uint32(args->dnode,
"./remote-interface");
break;
case SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM:
algo_buf = yang_dnode_get_string(args->dnode, "./algorithm");
algo = atoi(algo_buf);
local_prefix_len_buf = yang_dnode_get_string(
args->dnode, "./local-prefix-len");
local_prefix_len = atoi(local_prefix_len_buf);
break;
case SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE:
local_iface =
yang_dnode_get_uint32(args->dnode, "./local-interface");
local_prefix_len_buf = yang_dnode_get_string(
args->dnode, "./local-prefix-len");
local_prefix_len = atoi(local_prefix_len_buf);
break;
default:
break;
}
srte_segment_entry_set_nai(segment, type, &local_addr, local_iface,
&remote_addr, remote_iface);
zlog_debug(" Segment list name (%d) index (%s) ", segment->index,
segment->segment_list->name);
if (srte_segment_entry_set_nai(segment, type, &local_addr, local_iface,
&remote_addr, remote_iface, algo,
local_prefix_len))
SET_FLAG(segment->segment_list->flags,
F_SEGMENT_LIST_SID_CONFLICT);
}
/*

View File

@ -246,6 +246,10 @@ path_pcep_config_list_path_hops(struct srte_segment_list *segment_list)
switch (segment->nai_type) {
case SRTE_SEGMENT_NAI_TYPE_IPV4_NODE:
case SRTE_SEGMENT_NAI_TYPE_IPV6_NODE:
case SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE:
case SRTE_SEGMENT_NAI_TYPE_IPV6_LOCAL_IFACE:
case SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM:
case SRTE_SEGMENT_NAI_TYPE_IPV6_ALGORITHM:
memcpy(&hop->nai.local_addr, &segment->nai_local_addr,
sizeof(struct ipaddr));
break;
@ -278,6 +282,7 @@ int path_pcep_config_update_path(struct path *path)
assert(path->nbkey.preference != 0);
assert(path->nbkey.endpoint.ipa_type == IPADDR_V4);
int number_of_sid_clashed = 0;
struct path_hop *hop;
struct path_metric *metric;
int index;
@ -297,40 +302,44 @@ int path_pcep_config_update_path(struct path *path)
if (candidate->lsp->segment_list) {
SET_FLAG(candidate->lsp->segment_list->flags,
F_SEGMENT_LIST_DELETED);
srte_segment_list_del(candidate->lsp->segment_list);
candidate->lsp->segment_list = NULL;
}
if (path->first_hop != NULL) {
snprintf(segment_list_name_buff, sizeof(segment_list_name_buff),
"%s-%u", path->name, path->plsp_id);
segment_list_name = segment_list_name_buff;
if (path->first_hop == NULL)
return PATH_NB_ERR;
segment_list = srte_segment_list_add(segment_list_name);
segment_list->protocol_origin = path->update_origin;
strlcpy(segment_list->originator, path->originator,
sizeof(segment_list->originator));
SET_FLAG(segment_list->flags, F_SEGMENT_LIST_NEW);
SET_FLAG(segment_list->flags, F_SEGMENT_LIST_MODIFIED);
snprintf(segment_list_name_buff, sizeof(segment_list_name_buff),
"%s-%u", path->name, path->plsp_id);
segment_list_name = segment_list_name_buff;
for (hop = path->first_hop, index = 10; hop != NULL;
hop = hop->next, index += 10) {
assert(hop->has_sid);
assert(hop->is_mpls);
segment_list = srte_segment_list_add(segment_list_name);
segment_list->protocol_origin = path->update_origin;
strlcpy(segment_list->originator, path->originator,
sizeof(segment_list->originator));
SET_FLAG(segment_list->flags, F_SEGMENT_LIST_NEW);
SET_FLAG(segment_list->flags, F_SEGMENT_LIST_MODIFIED);
segment = srte_segment_entry_add(segment_list, index);
for (hop = path->first_hop, index = 10; hop != NULL;
hop = hop->next, index += 10) {
assert(hop->has_sid);
assert(hop->is_mpls);
segment->sid_value = (mpls_label_t)hop->sid.mpls.label;
SET_FLAG(segment->segment_list->flags,
F_SEGMENT_LIST_MODIFIED);
segment = srte_segment_entry_add(segment_list, index);
if (hop->has_nai)
srte_segment_entry_set_nai(
segment, srte_nai_type(hop->nai.type),
&hop->nai.local_addr,
hop->nai.local_iface,
&hop->nai.remote_addr,
hop->nai.remote_iface);
}
segment->sid_value = (mpls_label_t)hop->sid.mpls.label;
SET_FLAG(segment->segment_list->flags, F_SEGMENT_LIST_MODIFIED);
if (!hop->has_nai)
continue;
if (srte_segment_entry_set_nai(
segment, srte_nai_type(hop->nai.type),
&hop->nai.local_addr, hop->nai.local_iface,
&hop->nai.remote_addr, hop->nai.remote_iface, 0, 0)
== PATH_SID_ERROR)
/* TED queries don't match PCE */
/* Don't apply srte,zebra changes */
number_of_sid_clashed++;
}
candidate->lsp->segment_list = segment_list;
@ -352,7 +361,11 @@ int path_pcep_config_update_path(struct path *path)
candidate->lsp->objfun = path->pce_objfun;
}
srte_apply_changes();
if (number_of_sid_clashed)
SET_FLAG(segment->segment_list->flags,
F_SEGMENT_LIST_SID_CONFLICT);
else
srte_apply_changes();
return 0;
}
@ -402,6 +415,16 @@ enum pcep_sr_subobj_nai pcep_nai_type(enum srte_segment_nai_type type)
return PCEP_SR_SUBOBJ_NAI_IPV6_ADJACENCY;
case SRTE_SEGMENT_NAI_TYPE_IPV4_UNNUMBERED_ADJACENCY:
return PCEP_SR_SUBOBJ_NAI_UNNUMBERED_IPV4_ADJACENCY;
case SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY_LINK_LOCAL_ADDRESSES:
return PCEP_SR_SUBOBJ_NAI_LINK_LOCAL_IPV6_ADJACENCY;
case SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE:
return PCEP_SR_SUBOBJ_NAI_IPV4_NODE;
case SRTE_SEGMENT_NAI_TYPE_IPV6_LOCAL_IFACE:
return PCEP_SR_SUBOBJ_NAI_IPV6_NODE;
case SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM:
return PCEP_SR_SUBOBJ_NAI_IPV4_NODE;
case SRTE_SEGMENT_NAI_TYPE_IPV6_ALGORITHM:
return PCEP_SR_SUBOBJ_NAI_IPV6_NODE;
default:
return PCEP_SR_SUBOBJ_NAI_UNKNOWN;
}

View File

@ -189,14 +189,20 @@ void srte_segment_entry_del(struct srte_segment_entry *segment)
* @param type The remote address of the adjacency
* @param type The remote interface index of the unumbered adjacency
*/
void srte_segment_entry_set_nai(struct srte_segment_entry *segment,
enum srte_segment_nai_type type,
struct ipaddr *local_ip, uint32_t local_iface,
struct ipaddr *remote_ip, uint32_t remote_iface)
int srte_segment_entry_set_nai(struct srte_segment_entry *segment,
enum srte_segment_nai_type type,
struct ipaddr *local_ip, uint32_t local_iface,
struct ipaddr *remote_ip, uint32_t remote_iface,
uint8_t algo, uint8_t pref_len)
{
int32_t status = 0;
struct prefix pre = {0};
segment->nai_type = type;
memcpy(&segment->nai_local_addr, local_ip, sizeof(struct ipaddr));
if (!segment || !local_ip || !remote_ip)
return 1;
switch (type) {
case SRTE_SEGMENT_NAI_TYPE_IPV4_NODE:
case SRTE_SEGMENT_NAI_TYPE_IPV6_NODE:
@ -205,6 +211,7 @@ void srte_segment_entry_set_nai(struct srte_segment_entry *segment,
case SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY:
memcpy(&segment->nai_remote_addr, remote_ip,
sizeof(struct ipaddr));
status = srte_ted_do_query_type_f(segment, local_ip, remote_ip);
break;
case SRTE_SEGMENT_NAI_TYPE_IPV4_UNNUMBERED_ADJACENCY:
memcpy(&segment->nai_remote_addr, remote_ip,
@ -212,12 +219,68 @@ void srte_segment_entry_set_nai(struct srte_segment_entry *segment,
segment->nai_local_iface = local_iface;
segment->nai_remote_iface = remote_iface;
break;
case SRTE_SEGMENT_NAI_TYPE_IPV6_ALGORITHM:
pre.family = AF_INET6;
pre.prefixlen = pref_len;
pre.u.prefix6 = local_ip->ip._v6_addr;
segment->nai_local_prefix_len = pref_len;
segment->nai_algorithm = algo;
status = srte_ted_do_query_type_c(segment, &pre, algo);
break;
case SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM:
pre.family = AF_INET;
pre.prefixlen = pref_len;
pre.u.prefix4 = local_ip->ip._v4_addr;
segment->nai_local_prefix_len = pref_len;
segment->nai_algorithm = algo;
status = srte_ted_do_query_type_c(segment, &pre, algo);
break;
case SRTE_SEGMENT_NAI_TYPE_IPV6_LOCAL_IFACE:
pre.family = AF_INET6;
pre.prefixlen = pref_len;
pre.u.prefix6 = local_ip->ip._v6_addr;
segment->nai_local_prefix_len = pref_len;
segment->nai_local_iface = local_iface;
status = srte_ted_do_query_type_e(segment, &pre, local_iface);
break;
case SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE:
pre.family = AF_INET;
pre.prefixlen = pref_len;
pre.u.prefix4 = local_ip->ip._v4_addr;
segment->nai_local_prefix_len = pref_len;
segment->nai_local_iface = local_iface;
status = srte_ted_do_query_type_e(segment, &pre, local_iface);
break;
default:
segment->nai_local_addr.ipa_type = IPADDR_NONE;
segment->nai_local_iface = 0;
segment->nai_remote_addr.ipa_type = IPADDR_NONE;
segment->nai_remote_iface = 0;
}
return status;
}
/**
* Mark segment as modified depending in protocol and sid conditions
*
* @param protocol_origin Origin of the segment list
* @param s_list Ptr to segment list with flags,sid to modidy
* @param s_entry Ptr to segment entry with sid to modidy
* @param ted_sid The sid from ted query
* @return void
*/
void srte_segment_set_local_modification(struct srte_segment_list *s_list,
struct srte_segment_entry *s_entry,
uint32_t ted_sid)
{
if (!s_list || !s_entry)
return;
if (s_list->protocol_origin == SRTE_ORIGIN_LOCAL
&& s_entry->sid_value != ted_sid) {
s_entry->sid_value = ted_sid;
SET_FLAG(s_list->flags, F_SEGMENT_LIST_MODIFIED);
}
}
/**
@ -288,6 +351,105 @@ struct srte_policy *srte_policy_find(uint32_t color, struct ipaddr *endpoint)
return RB_FIND(srte_policy_head, &srte_policies, &search);
}
/*
* After new data from igp,local and pce the segment list :
* Mark as invalid for origin pce if cannot be validated
* Updated for origin local
*/
int srte_policy_update_ted_sid(void)
{
int number_of_sid_clashed = 0;
struct srte_segment_list *s_list;
struct srte_segment_entry *s_entry;
if (!path_ted_is_initialized())
return 0;
if (RB_EMPTY(srte_segment_list_head, &srte_segment_lists))
return 0;
RB_FOREACH (s_list, srte_segment_list_head, &srte_segment_lists) {
if (CHECK_FLAG(s_list->flags, F_SEGMENT_LIST_DELETED))
continue;
RB_FOREACH (s_entry, srte_segment_entry_head,
&s_list->segments) {
PATH_TED_DEBUG(
"%s:PATHD-TED: SL: Name: %s index:(%d) sid:(%d) prefix_len:(%d) local iface:(%d) algorithm:(%d)",
__func__, s_list->name, s_entry->index,
s_entry->sid_value,
s_entry->nai_local_prefix_len,
s_entry->nai_local_iface,
s_entry->nai_algorithm);
struct prefix prefix_cli = {0};
switch (s_entry->nai_type) {
case SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY:
case SRTE_SEGMENT_NAI_TYPE_IPV4_ADJACENCY:
number_of_sid_clashed +=
srte_ted_do_query_type_f(
s_entry,
&s_entry->nai_local_addr,
&s_entry->nai_remote_addr);
break;
case SRTE_SEGMENT_NAI_TYPE_IPV6_LOCAL_IFACE:
prefix_cli.family = AF_INET6;
prefix_cli.prefixlen =
s_entry->nai_local_prefix_len;
prefix_cli.u.prefix6 =
s_entry->nai_local_addr.ip._v6_addr;
number_of_sid_clashed +=
srte_ted_do_query_type_e(
s_entry, &prefix_cli,
s_entry->nai_local_iface);
break;
case SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE:
prefix_cli.family = AF_INET;
prefix_cli.prefixlen =
s_entry->nai_local_prefix_len;
prefix_cli.u.prefix4 =
s_entry->nai_local_addr.ip._v4_addr;
number_of_sid_clashed +=
srte_ted_do_query_type_e(
s_entry, &prefix_cli,
s_entry->nai_local_iface);
break;
case SRTE_SEGMENT_NAI_TYPE_IPV6_ALGORITHM:
prefix_cli.family = AF_INET6;
prefix_cli.prefixlen =
s_entry->nai_local_prefix_len;
prefix_cli.u.prefix6 =
s_entry->nai_local_addr.ip._v6_addr;
number_of_sid_clashed +=
srte_ted_do_query_type_c(
s_entry, &prefix_cli,
s_entry->nai_algorithm);
break;
case SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM:
prefix_cli.family = AF_INET;
prefix_cli.prefixlen =
s_entry->nai_local_prefix_len;
prefix_cli.u.prefix4 =
s_entry->nai_local_addr.ip._v4_addr;
number_of_sid_clashed +=
srte_ted_do_query_type_c(
s_entry, &prefix_cli,
s_entry->nai_algorithm);
break;
default:
break;
}
}
if (number_of_sid_clashed) {
SET_FLAG(s_list->flags, F_SEGMENT_LIST_SID_CONFLICT);
number_of_sid_clashed = 0;
} else
UNSET_FLAG(s_list->flags, F_SEGMENT_LIST_SID_CONFLICT);
}
srte_apply_changes();
return 0;
}
/**
* Update a policy binding SID.
*
@ -323,7 +485,9 @@ srte_policy_best_candidate(const struct srte_policy *policy)
&policy->candidate_paths) {
/* search for highest preference with existing segment list */
if (!CHECK_FLAG(candidate->flags, F_CANDIDATE_DELETED)
&& candidate->lsp->segment_list)
&& candidate->lsp->segment_list
&& (!CHECK_FLAG(candidate->lsp->segment_list->flags,
F_SEGMENT_LIST_SID_CONFLICT)))
return candidate;
}
@ -535,6 +699,7 @@ void srte_candidate_set_bandwidth(struct srte_candidate *candidate,
{
struct srte_policy *policy = candidate->policy;
char endpoint[46];
ipaddr2str(&policy->endpoint, endpoint, sizeof(endpoint));
zlog_debug(
"SR-TE(%s, %u): candidate %s %sconfig bandwidth set to %f B/s",
@ -1139,3 +1304,91 @@ const char *srte_candidate_metric_name(enum srte_candidate_metric_type type)
return "UNKNOWN";
}
}
int32_t srte_ted_do_query_type_c(struct srte_segment_entry *entry,
struct prefix *prefix_cli, uint32_t algo)
{
int32_t status = 0;
uint32_t ted_sid = MPLS_LABEL_NONE;
if (!entry || !prefix_cli)
return 0;
if (!path_ted_is_initialized())
return 0;
ted_sid = path_ted_query_type_c(prefix_cli, algo);
if (ted_sid == MPLS_LABEL_NONE) {
zlog_warn(" %s: PATHD-TED: SL: ERROR query C : ted-sid (%d)",
__func__, ted_sid);
} else {
zlog_debug("%s: PATHD-TED: SL: Sucess query C : ted-sid (%d)",
__func__, ted_sid);
}
if (CHECK_SID(entry->segment_list->protocol_origin, ted_sid,
entry->sid_value)) {
status = PATH_SID_ERROR;
} else
srte_segment_set_local_modification(entry->segment_list, entry,
ted_sid);
return status;
}
int32_t srte_ted_do_query_type_e(struct srte_segment_entry *entry,
struct prefix *prefix_cli,
uint32_t local_iface)
{
int32_t status = 0;
uint32_t ted_sid = MPLS_LABEL_NONE;
if (!entry || !prefix_cli)
return 0;
if (!path_ted_is_initialized())
return 0;
ted_sid = path_ted_query_type_e(prefix_cli, local_iface);
if (ted_sid == MPLS_LABEL_NONE) {
zlog_warn(" %s: PATHD-TED: SL: ERROR query E : ted-sid (%d)",
__func__, ted_sid);
} else {
zlog_debug("%s: PATHD-TED: SL: Sucess query E : ted-sid (%d)",
__func__, ted_sid);
}
if (CHECK_SID(entry->segment_list->protocol_origin, ted_sid,
entry->sid_value)) {
status = PATH_SID_ERROR;
} else
srte_segment_set_local_modification(entry->segment_list, entry,
ted_sid);
return status;
}
int32_t srte_ted_do_query_type_f(struct srte_segment_entry *entry,
struct ipaddr *local, struct ipaddr *remote)
{
int32_t status = 0;
uint32_t ted_sid = MPLS_LABEL_NONE;
if (!entry || !local || !remote)
return 0;
if (!path_ted_is_initialized())
return status;
ted_sid = path_ted_query_type_f(local, remote);
if (ted_sid == MPLS_LABEL_NONE) {
zlog_warn("%s:SL: ERROR query F : ted-sid (%d)", __func__,
ted_sid);
} else {
zlog_debug("%s:SL: Sucess query F : ted-sid (%d)", __func__,
ted_sid);
}
if (CHECK_SID(entry->segment_list->protocol_origin, ted_sid,
entry->sid_value)) {
status = PATH_SID_ERROR;
} else
srte_segment_set_local_modification(entry->segment_list, entry,
ted_sid);
return status;
}

View File

@ -24,6 +24,13 @@
#include "lib/ipaddr.h"
#include "lib/srte.h"
#include "lib/hook.h"
#include "lib/prefix.h"
#define PATH_SID_ERROR 1
#define PATH_SID_NO_ERROR 0
#define CHECK_SID(or, ts, es) \
((or == SRTE_ORIGIN_PCEP && (ts == MPLS_LABEL_NONE || es != ts)) \
|| (or == SRTE_ORIGIN_LOCAL && ts == MPLS_LABEL_NONE))
DECLARE_MGROUP(PATHD);
@ -100,7 +107,12 @@ enum srte_segment_nai_type {
SRTE_SEGMENT_NAI_TYPE_IPV6_NODE = 2,
SRTE_SEGMENT_NAI_TYPE_IPV4_ADJACENCY = 3,
SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY = 4,
SRTE_SEGMENT_NAI_TYPE_IPV4_UNNUMBERED_ADJACENCY = 5
SRTE_SEGMENT_NAI_TYPE_IPV4_UNNUMBERED_ADJACENCY = 5,
SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY_LINK_LOCAL_ADDRESSES = 6,
SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE = 7,
SRTE_SEGMENT_NAI_TYPE_IPV6_LOCAL_IFACE = 8,
SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM = 9,
SRTE_SEGMENT_NAI_TYPE_IPV6_ALGORITHM = 10
};
enum objfun_type {
@ -175,6 +187,9 @@ struct srte_segment_entry {
/* NAI remote interface when nai type is not IPv4 unnumbered adjacency
*/
uint32_t nai_remote_iface;
/* Support draft-ietf-spring-segment-routing-policy sl types queries*/
uint8_t nai_local_prefix_len;
uint8_t nai_algorithm;
};
RB_HEAD(srte_segment_entry_head, srte_segment_entry);
RB_PROTOTYPE(srte_segment_entry_head, srte_segment_entry, entry,
@ -200,6 +215,7 @@ struct srte_segment_list {
#define F_SEGMENT_LIST_NEW 0x0002
#define F_SEGMENT_LIST_MODIFIED 0x0004
#define F_SEGMENT_LIST_DELETED 0x0008
#define F_SEGMENT_LIST_SID_CONFLICT 0x0010
};
RB_HEAD(srte_segment_list_head, srte_segment_list);
RB_PROTOTYPE(srte_segment_list_head, srte_segment_list, entry,
@ -361,14 +377,18 @@ struct srte_segment_list *srte_segment_list_find(const char *name);
struct srte_segment_entry *
srte_segment_entry_add(struct srte_segment_list *segment_list, uint32_t index);
void srte_segment_entry_del(struct srte_segment_entry *segment);
void srte_segment_entry_set_nai(struct srte_segment_entry *segment,
enum srte_segment_nai_type type,
struct ipaddr *local_ip, uint32_t local_iface,
struct ipaddr *remote_ip,
uint32_t remote_iface);
int srte_segment_entry_set_nai(struct srte_segment_entry *segment,
enum srte_segment_nai_type type,
struct ipaddr *local_ip, uint32_t local_iface,
struct ipaddr *remote_ip, uint32_t remote_iface,
uint8_t algo, uint8_t pref_len);
void srte_segment_set_local_modification(struct srte_segment_list *s_list,
struct srte_segment_entry *s_entry,
uint32_t ted_sid);
struct srte_policy *srte_policy_add(uint32_t color, struct ipaddr *endpoint);
void srte_policy_del(struct srte_policy *policy);
struct srte_policy *srte_policy_find(uint32_t color, struct ipaddr *endpoint);
int srte_policy_update_ted_sid(void);
void srte_policy_update_binding_sid(struct srte_policy *policy,
uint32_t binding_sid);
void srte_apply_changes(void);
@ -414,4 +434,40 @@ void pathd_shutdown(void);
/* path_cli.c */
void path_cli_init(void);
/**
* Search for sid based in prefix and algorithm
*
* @param Prefix The prefix to use
* @param algo Algorithm we want to query for
* @param ted_sid Sid to query
*
* @return void
*/
int32_t srte_ted_do_query_type_c(struct srte_segment_entry *entry,
struct prefix *prefix_cli, uint32_t algo);
/**
* Search for sid based in prefix and interface id
*
* @param Prefix The prefix to use
* @param local_iface The id of interface
* @param ted_sid Sid to query
*
* @return void
*/
int32_t srte_ted_do_query_type_e(struct srte_segment_entry *entry,
struct prefix *prefix_cli,
uint32_t local_iface);
/**
* Search for sid based in local and remote ip
*
* @param entry entry to update
* @param local Local addr for query
* @param remote Local addr for query
*
* @return void
*/
int32_t srte_ted_do_query_type_f(struct srte_segment_entry *entry,
struct ipaddr *local, struct ipaddr *remote);
#endif /* _FRR_PATHD_H_ */

View File

@ -84,51 +84,71 @@ module frr-pathd {
leaf index {
type uint32;
description "Segment index";
}
leaf sid-value {
type rt-types:mpls-label;
}
leaf sid-value {
type rt-types:mpls-label;
description "MPLS label value";
}
container nai {
presence "The segment has a Node or Adjacency Identifier";
leaf type {
description "NAI type";
mandatory true;
description "MPLS label value";
}
container nai {
presence "The segement has a Node or Adjacency Identifier";
leaf type {
description "NAI type";
mandatory true;
type enumeration {
enum ipv4_node {
value 1;
description "IPv4 node identifier";
}
enum ipv6_node {
value 2;
description "IPv6 node identifier";
}
enum ipv4_adjacency {
value 3;
description "IPv4 adjacency";
}
enum ipv6_adjacency {
value 4;
description "IPv6 adjacency";
}
enum ipv4_unnumbered_adjacency {
value 5;
description "IPv4 unnumbered adjacency";
}
type enumeration {
enum ipv4_node {
value 1;
description "IPv4 node identifier";
}
enum ipv6_node {
value 2;
description "IPv6 node identifier";
}
enum ipv4_adjacency {
value 3;
description "IPv4 adjacency";
}
enum ipv6_adjacency {
value 4;
description "IPv6 adjacency";
}
enum ipv4_unnumbered_adjacency {
value 5;
description "IPv4 unnumbered adjacency";
}
enum ipv4_local_iface {
value 7;
description "IPv4 prefix with local interface id";
}
enum ipv6_local_iface {
value 8;
description "IPv6 prefix with local interface id";
}
enum ipv4_algo {
value 9;
description "IPv4 prefix with optional algorithm";
}
enum ipv6_algo {
value 10;
description "IPv6 prefix with optional algorithm";
}
}
leaf local-address {
type inet:ip-address;
mandatory true;
}
leaf local-interface {
type uint32;
mandatory true;
when "../type = 'ipv4_unnumbered_adjacency'";
}
leaf remote-address {
type inet:ip-address;
}
leaf local-address {
type inet:ip-address;
mandatory true;
}
leaf local-prefix-len {
type uint8;
mandatory true;
when "../type = 'ipv4_local_iface' or ../type = 'ipv6_local_iface' or ../type = 'ipv4_algo' or ../type = 'ipv6_algo'";
}
leaf local-interface {
type uint32;
mandatory true;
when "../type = 'ipv4_local_iface' or ../type = 'ipv6_local_iface' or ../type = 'ipv4_unnumbered_adjacency'";
}
leaf remote-address {
type inet:ip-address;
mandatory true;
when "../type = 'ipv4_adjacency' or ../type = 'ipv6_adjacency' or ../type = 'ipv4_unnumbered_adjacency'";
}
@ -137,6 +157,11 @@ module frr-pathd {
mandatory true;
when "../type = 'ipv4_unnumbered_adjacency'";
}
leaf algorithm {
type uint8;
mandatory true;
when "../type = 'ipv4_algo' or ../type = 'ipv6_algo'";
}
}
}
}