Skip to content

Commit

Permalink
pathd: Traffic Engineering Database support
Browse files Browse the repository at this point in the history
- pathd will act as a client to for the configured igp.
- pathd must be configured to activate and receive data from igp.
- 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.
- As an example of igp config this ospf snippet

! igp ospfv2 snippet
interface eth0
 ip ospf network point-to-point
!
router ospf$
 mpls-te on
 mpls-te export
 ...

!pathd snippet
segment-routing
 traffic-eng
  mpls-te on
  mpls-te import ospfv2

segment-list sl-1
index 10  nai adjacency 10.1.2.11 10.1.2.1
index 20  nai adjacency 10.1.20.1 10.1.20.2
index 30  nai adjacency 10.2.5.2 10.2.5.5
!
policy color 5 endpoint 10.10.10.5
name five
binding-sid 5555
candidate-path preference 600 name cp51 explicit segment-list sl-1
candidate-path preference 500 name cp52-dyn dynamic

Signed-off-by: Javier Garcia <javier.garcia@voltanet.io>
Signed-off-by: Javier Garcia <rampxxxx@gmail.com>
Signed-off-by: Javier Garcia <javier.garcia@voltanet.io>
  • Loading branch information
Javier Garcia committed Apr 20, 2021
1 parent 8d31c67 commit 82cde94
Show file tree
Hide file tree
Showing 50 changed files with 4,193 additions and 114 deletions.
40 changes: 21 additions & 19 deletions doc/user/pathd.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,8 @@ documented elsewhere.
PCEP Support
============

To build the PCC for pathd, the externall library `pceplib 1.2 <https://github.com/volta-networks/pceplib/tree/devel-1.2>`_ is required.
A pceplib is included in the frr source tree and build by default.

To build FRR with support for PCEP the following steps must be followed:

- Checkout and build pceplib:

```
$ git clone https://github.com/volta-networks/pceplib
$ cd pceplib
$ make
$ make install
$ export PCEPLIB_ROOT=$PWD
```

- Configure FRR with the extra parameters:

```
--enable-pcep LDFLAGS="-L${PCEPLIB_ROOT}/install/lib" CPPFLAGS="-I${PCEPLIB_ROOT}/install/include"
```

To start pathd with pcep support the extra parameter `-M pathd_pcep` should be
passed to the pathd daemon.
Expand All @@ -62,10 +45,18 @@ Example:
debug pathd pcep basic
segment-routing
traffic-eng
mpls-te on
mpls-te import ospfv2
segment-list SL1
index 10 mpls label 16010
index 20 mpls label 16030
!
segment-list SL2
index 10 nai prefix 10.1.2.1/32 iface 1
index 20 nai adjacency 10.1.20.1 10.1.20.2
index 30 nai prefix 10.10.10.5/32 algorithm 0
index 40 mpls label 18001
!
policy color 1 endpoint 1.1.1.1
name default
binding-sid 4000
Expand Down Expand Up @@ -113,11 +104,22 @@ Configuration Commands

Configure segment routing traffic engineering.

.. clicmd:: [no] mpls-te <on|off>

Activate/Deactivate use of internal Traffic Engineering Database

.. clicmd:: [no] mpls-te import <ospfv2|ospfv3|isis>

Load data from the igp selected

.. clicmd:: segment-list NAME

Delete or start a segment list definition.

.. clicmd:: index INDEX mpls label LABEL [nai node ADDRESS]
.. clicmd:: index INDEX mpls label LABEL
.. clicmd:: index INDEX nai adjacency A.B.C.D A.B.C.D
.. clicmd:: index INDEX nai prefix A.B.C.D/M algorithm <0|1>
.. clicmd:: index INDEX nai prefix A.B.C.D/M iface (0-65535)

Delete or specify a segment in a segment list definition.

Expand Down
252 changes: 223 additions & 29 deletions pathd/path_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,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
Expand Down Expand Up @@ -142,6 +143,7 @@ DEFPY(show_srte_policy,
return CMD_SUCCESS;
}


/*
* Show detailed SR-TE info
*/
Expand Down Expand Up @@ -296,49 +298,204 @@ void cli_show_srte_segment_list(struct vty *vty, struct lyd_node *dnode,
/*
* 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;
const char *node_src_id;
char buf_prefix[INET6_ADDRSTRLEN];

char buf[INET6_ADDRSTRLEN];
char buf2[INET6_ADDRSTRLEN];
uint32_t ted_sid = MPLS_LABEL_NONE;
struct prefix prefix_cli = {0};

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_mpls_label != 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) {
if (has_adj != NULL) {
struct ipaddr ip_src = {.ipa_type = IPADDR_V4,
.ip._v4_addr = adj_src_ipv4};
struct ipaddr ip_dst = {.ipa_type = IPADDR_V4,
.ip._v4_addr = adj_dst_ipv4};
ted_sid = path_ted_query_type_f(&ip_src, &ip_dst);
if (ted_sid == MPLS_LABEL_NONE) {
inet_ntop(AF_INET, &adj_src_ipv4, buf,
sizeof(buf));
inet_ntop(AF_INET, &adj_dst_ipv4, buf,
sizeof(buf2));
zlog_warn(
"%s: [rcv ted] CLI NOT FOUND Continue query_type_f SRC (%pIA) DST (%pIA)!",
__func__, &ip_src, &ip_dst);
}
/* type */
snprintf(xpath, sizeof(xpath),
"./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, sizeof(xpath),
"./segment[index='%s']/nai/local-address",
index_str);
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
"ipv4_node");
node_id = node_ipv4_str;
} else if (node_ipv6_str != NULL) {
node_src_id);
snprintf(xpath, sizeof(xpath),
"./segment[index='%s']/nai/remote-address",
index_str);
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
"ipv6_node");
node_id = node_ipv6_str;
adj_dst_ipv4_str
? adj_dst_ipv4_str
: adj_dst_ipv6_str);
} else {
return CMD_ERR_NO_MATCH;
/* prefix with algorithm or local interface id */
/* Type */
snprintf(xpath, sizeof(xpath),
"./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));
} else {
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));
}
snprintf(xpath, sizeof(xpath),
"./segment[index='%s']/nai/local-address",
index_str);
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
buf_prefix);
snprintf(xpath, sizeof(xpath),
"./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, sizeof(xpath),
"./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, sizeof(xpath),
"./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) {
inet_ntop(AF_INET,
&prefix_cli.u.prefix4, buf,
sizeof(buf));
zlog_err(
"%s: [rcv ted] CLI NOT FOUND Continue query_type_c PREFIX (%s(%d)) ALGO (%ld) sid:(%d)!",
__func__, buf,
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) {
inet_ntop(AF_INET,
&prefix_cli.u.prefix4, buf,
sizeof(buf));
zlog_err(
"%s: [rcv ted] CLI NOT FOUND Continue query_type_e PREFIX (%s/%d) IFACE (%ld) sid:(%d)!",
__func__, buf,
prefix_cli.prefixlen, iface_id,
ted_sid);
}
}
}
snprintf(xpath, sizeof(xpath),
"./segment[index='%s']/nai/local-address", index_str);
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, node_id);
} else {
snprintf(xpath, sizeof(xpath), "./segment[index='%s']/nai",
index_str);
Expand Down Expand Up @@ -367,23 +524,59 @@ 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");
}
Expand Down Expand Up @@ -1036,6 +1229,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;
}

Expand Down
Loading

0 comments on commit 82cde94

Please sign in to comment.