Skip to content

Commit

Permalink
Implement IPv6 PCEP connections
Browse files Browse the repository at this point in the history
  • Loading branch information
Brady Johnson committed Apr 16, 2020
1 parent bcddd9c commit 979d122
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 55 deletions.
105 changes: 78 additions & 27 deletions pathd/path_pcep.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,31 +248,43 @@ DEFUN(show_pcep_counters, show_pcep_counters_cmd, "show pcep counters",
}

DEFUN_NOSH(pcep_cli_pcc, pcep_cli_pcc_cmd,
"pcc [ip A.B.C.D] [port (1024-65535)] [force_stateless]",
"pcc [ip A.B.C.D | ipv6 X:X::X:X] [port (1024-65535)] [force_stateless]",
"PCC configuration\n"
"PCC source ip\n"
"PCC source IPv4 address\n"
"PCC source ip\n"
"PCC source IPv6 address\n"
"PCC source port\n"
"PCC source port value\n"
"Force the PCC to use computation requests\n")
{
/* TODO: Add support for IPv6 */

struct in_addr pcc_addr;
struct ipaddr pcc_addr;
uint32_t pcc_port = PCEP_DEFAULT_PORT;
struct pcc_opts *opts, *opts_copy;
bool force_stateless = false;
int i = 1;

pcc_addr.s_addr = INADDR_ANY;
pcc_addr.ipaddr_v6 = in6addr_any;

while (i < argc) {
if (0 == strcmp("ipv6", argv[i]->arg)) {
i++;
if (i >= argc)
return CMD_ERR_NO_MATCH;
if (!inet_pton(AF_INET6, argv[i]->arg, &pcc_addr.ipaddr_v6))
return CMD_ERR_INCOMPLETE;
pcc_addr.ipa_type = IPADDR_V6;
i++;
continue;
}
if (0 == strcmp("ip", argv[i]->arg)) {
i++;
if (i >= argc)
return CMD_ERR_NO_MATCH;
if (!inet_pton(AF_INET, argv[i]->arg, &pcc_addr.s_addr))
if (!inet_pton(AF_INET, argv[i]->arg, &pcc_addr.ipaddr_v4.s_addr))
return CMD_ERR_INCOMPLETE;
pcc_addr.ipa_type = IPADDR_V4;
i++;
continue;
}
Expand All @@ -295,7 +307,12 @@ DEFUN_NOSH(pcep_cli_pcc, pcep_cli_pcc_cmd,
}

opts = XCALLOC(MTYPE_PCEP, sizeof(*opts));
opts->addr = pcc_addr;
opts->addr.ipa_type = pcc_addr.ipa_type;
if (IS_IPADDR_V6(&pcc_addr)) {
memcpy(&opts->addr.ipaddr_v6, &pcc_addr.ipaddr_v6, sizeof(struct in6_addr));
} else {
opts->addr.ipaddr_v4.s_addr = pcc_addr.ipaddr_v4.s_addr;
}
opts->port = pcc_port;
opts->force_stateless = force_stateless;

Expand All @@ -314,32 +331,49 @@ DEFUN_NOSH(pcep_cli_pcc, pcep_cli_pcc_cmd,
}

DEFUN(pcep_cli_pce_opts, pcep_cli_pce_opts_cmd,
"pce ip A.B.C.D [port (1024-65535)] [sr-draft07]",
"pce [ip A.B.C.D | ipv6 X:X::X:X] [port (1024-65535)] [sr-draft07]",
"PCE configuration\n"
"PCE address\n"
"PCE IPv4 address\n"
"Remote PCE server IPv4 address\n"
"PCE IPv6 address\n"
"Remote PCE server IPv6 address\n"
"Remote PCE server port\n"
"Remote PCE server port value\n"
"Use the draft 07 of PCEP segemnt routing\n")
{
/* TODO: Add support for multiple PCE */
/* TODO: Add support for IPv6 */

struct in_addr pce_addr;
struct ipaddr pce_addr;
uint32_t pce_port = PCEP_DEFAULT_PORT;
struct pce_opts *pce_opts, *pce_opts_copy;
bool draft07 = false;
int i = 1;

if (0 != strcmp("ip", argv[i]->arg))
/* Get the first argument, should be either ip or ipv6 */
pce_addr.ipa_type = IPADDR_V4;
if (0 == strcmp("ipv6", argv[i]->arg)) {
pce_addr.ipa_type = IPADDR_V6;
} else if (0 != strcmp("ip", argv[i]->arg)) {
return CMD_ERR_NO_MATCH;
}

/* Get the first argument value */
i++;
if (i >= argc)
if (i >= argc) {
return CMD_ERR_NO_MATCH;
if (!inet_pton(AF_INET, argv[i]->arg, &pce_addr.s_addr))
return CMD_ERR_INCOMPLETE;
i++;
}
if (IS_IPADDR_V6(&pce_addr)) {
if (!inet_pton(AF_INET6, argv[i]->arg, &pce_addr.ipaddr_v6)) {
return CMD_ERR_INCOMPLETE;
}
} else {
if (!inet_pton(AF_INET, argv[i]->arg, &pce_addr.ipaddr_v4)) {
return CMD_ERR_INCOMPLETE;
}
}

/* Handle the rest of the arguments */
i++;
while (i < argc) {
if (0 == strcmp("port", argv[i]->arg)) {
i++;
Expand All @@ -360,7 +394,12 @@ DEFUN(pcep_cli_pce_opts, pcep_cli_pce_opts_cmd,
}

pce_opts = XCALLOC(MTYPE_PCEP, sizeof(*pce_opts));
pce_opts->addr = pce_addr;
pce_opts->addr.ipa_type = pce_addr.ipa_type;
if (IS_IPADDR_V6(&pce_addr)) {
memcpy(&pce_opts->addr.ipaddr_v6, &pce_addr.ipaddr_v6, sizeof(struct in6_addr));
} else {
pce_opts->addr.ipaddr_v4 = pce_addr.ipaddr_v4;
}
pce_opts->port = pce_port;
pce_opts->draft07 = draft07;

Expand Down Expand Up @@ -457,15 +496,21 @@ int pcep_cli_debug_set_all(uint32_t flags, bool set)

int pcep_cli_pcc_config_write(struct vty *vty)
{
/* TODO: Add support for IPv6 */

char buff[128] = "";
int lines = 0;

if (NULL != pcep_g->pcc_opts) {
if (INADDR_ANY != pcep_g->pcc_opts->addr.s_addr)
csnprintfrr(buff, sizeof(buff), " ip %pI4",
&pcep_g->pcc_opts->addr);
if (IS_IPADDR_V6(&pcep_g->pcc_opts->addr)) {
if (0 != memcmp(&in6addr_any, &pcep_g->pcc_opts->addr.ipaddr_v6, sizeof(struct in6_addr))) {
csnprintfrr(buff, sizeof(buff), " ip %pI6",
&pcep_g->pcc_opts->addr.ipaddr_v6);
}
} else {
if (INADDR_ANY != pcep_g->pcc_opts->addr.ipaddr_v4.s_addr) {
csnprintfrr(buff, sizeof(buff), " ip %pI4",
&pcep_g->pcc_opts->addr.ipaddr_v4);
}
}
if (PCEP_DEFAULT_PORT != pcep_g->pcc_opts->port)
csnprintfrr(buff, sizeof(buff), " port %d",
pcep_g->pcc_opts->port);
Expand All @@ -476,14 +521,20 @@ int pcep_cli_pcc_config_write(struct vty *vty)
for (int i = 0; i < MAX_PCC; i++) {
struct pce_opts *pce_opts = pcep_g->pce_opts[i];
if (NULL != pce_opts) {
if (PCEP_DEFAULT_PORT != pce_opts->port)
if (PCEP_DEFAULT_PORT != pce_opts->port) {
csnprintfrr(buff, sizeof(buff),
" port %d", pce_opts->port);
if (true == pce_opts->draft07)
csnprintfrr(buff, sizeof(buff),
" sr-draft07");
vty_out(vty, " pce ip %pI4%s\n",
&pce_opts->addr, buff);
}
if (true == pce_opts->draft07) {
csnprintfrr(buff, sizeof(buff), " sr-draft07");
}
if (IS_IPADDR_V6(&pce_opts->addr)) {
vty_out(vty, " pce ipv6 %pI6%s\n",
&pce_opts->addr.ipaddr_v6, buff);
} else {
vty_out(vty, " pce ip %pI4%s\n",
&pce_opts->addr.ipaddr_v4, buff);
}
buff[0] = 0;
lines++;
}
Expand Down
4 changes: 2 additions & 2 deletions pathd/path_pcep.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,13 @@
} while (0)

struct pce_opts {
struct in_addr addr;
struct ipaddr addr;
short port;
bool draft07;
};

struct pcc_opts {
struct in_addr addr;
struct ipaddr addr;
short port;
bool force_stateless;
};
Expand Down
6 changes: 4 additions & 2 deletions pathd/path_pcep_controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,10 @@ int pcep_ctrl_initialize(struct thread_master *main_thread,
ctrl_state->t_poll = NULL;
ctrl_state->pcc_count = 0;
ctrl_state->pcc_opts =
XCALLOC(MTYPE_PCEP, sizeof(*ctrl_state->pcc_opts));
ctrl_state->pcc_opts->addr.s_addr = INADDR_ANY;
XCALLOC(MTYPE_PCEP, sizeof(*ctrl_state->pcc_opts));
/* Default to IPv4 */
ctrl_state->pcc_opts->addr.ipa_type = IPADDR_V4;
ctrl_state->pcc_opts->addr.ipaddr_v4.s_addr = INADDR_ANY;
ctrl_state->pcc_opts->port = PCEP_DEFAULT_PORT;

/* Keep the state reference for events */
Expand Down
12 changes: 10 additions & 2 deletions pathd/path_pcep_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,11 @@ void _format_pcc_opts(int ps, struct pcc_opts *opts)
} else {
int ps2 = ps + DEBUG_IDENT_SIZE;
PCEP_FORMAT("\n");
PCEP_FORMAT("%*saddr: %pI4\n", ps2, "", &opts->addr);
if (IS_IPADDR_V6(&opts->addr)) {
PCEP_FORMAT("%*saddr: %pI6\n", ps2, "", &opts->addr.ipaddr_v6);
} else {
PCEP_FORMAT("%*saddr: %pI4\n", ps2, "", &opts->addr.ipaddr_v4);
}
PCEP_FORMAT("%*sport: %i\n", ps2, "", opts->port);
}
}
Expand All @@ -582,7 +586,11 @@ void _format_pce_opts(int ps, struct pce_opts *opts)
} else {
int ps2 = ps + DEBUG_IDENT_SIZE;
PCEP_FORMAT("\n");
PCEP_FORMAT("%*saddr: %pI4\n", ps2, "", &opts->addr);
if (IS_IPADDR_V6(&opts->addr)) {
PCEP_FORMAT("%*saddr: %pI6\n", ps2, "", &opts->addr.ipaddr_v6);
} else {
PCEP_FORMAT("%*saddr: %pI4\n", ps2, "", &opts->addr.ipaddr_v4);
}
PCEP_FORMAT("%*sport: %i\n", ps2, "", opts->port);
}
}
Expand Down
33 changes: 24 additions & 9 deletions pathd/path_pcep_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,13 @@ pcep_session *pcep_lib_connect(struct pcc_opts *pcc_opts,
config = create_default_pcep_configuration();
config->dst_pcep_port = pce_opts->port;
config->src_pcep_port = pcc_opts->port;
config->src_ip = pcc_opts->addr;
if (IS_IPADDR_V6(&pcc_opts->addr)) {
config->is_src_ipv6 = true;
memcpy(&config->src_ip.src_ipv6, &pcc_opts->addr.ipaddr_v6, sizeof(struct in6_addr));
} else {
config->is_src_ipv6 = false;
config->src_ip.src_ipv4 = pcc_opts->addr.ipaddr_v4;
}

config->support_stateful_pce_lsp_update = !pcc_opts->force_stateless;
config->support_pce_lsp_instantiation = false;
Expand All @@ -99,7 +105,11 @@ pcep_session *pcep_lib_connect(struct pcc_opts *pcc_opts,
config->pcep_msg_versioning->draft_ietf_pce_segment_routing_07 =
pce_opts->draft07;

sess = connect_pce(config, &pce_opts->addr);
if (IS_IPADDR_V6(&pce_opts->addr)) {
sess = connect_pce_ipv6(config, &pce_opts->addr.ipaddr_v6);
} else {
sess = connect_pce(config, &pce_opts->addr.ipaddr_v4);
}
destroy_pcep_configuration(config);
return sess;
}
Expand All @@ -119,23 +129,28 @@ struct pcep_message *pcep_lib_format_report(struct path *path)
struct pcep_message *pcep_lib_format_request(uint32_t reqid, struct ipaddr *src,
struct ipaddr *dst)
{
/* TODO: Add support for IPv6 */
assert(IS_IPADDR_V4(src));
assert(IS_IPADDR_V4(dst));
assert(src->ipa_type ==dst->ipa_type);

double_linked_list *rp_tlvs;
struct pcep_object_tlv_path_setup_type *setup_type_tlv;
struct pcep_object_rp *rp;
struct pcep_object_endpoints_ipv4 *endpoints;
struct pcep_object_endpoints_ipv4 *endpoints_ipv4;
struct pcep_object_endpoints_ipv6 *endpoints_ipv6;

rp_tlvs = dll_initialize();
setup_type_tlv = pcep_tlv_create_path_setup_type(SR_TE_PST);
dll_append(rp_tlvs, setup_type_tlv);

rp = pcep_obj_create_rp(0, false, false, false, reqid, rp_tlvs);
endpoints =
pcep_obj_create_endpoint_ipv4(&src->ipaddr_v4, &dst->ipaddr_v4);
return pcep_msg_create_request(rp, endpoints, NULL);
if (IS_IPADDR_V6(src)) {
endpoints_ipv6 =
pcep_obj_create_endpoint_ipv6(&src->ipaddr_v6, &dst->ipaddr_v6);
return pcep_msg_create_request_ipv6(rp, endpoints_ipv6, NULL);
} else {
endpoints_ipv4 =
pcep_obj_create_endpoint_ipv4(&src->ipaddr_v4, &dst->ipaddr_v4);
return pcep_msg_create_request(rp, endpoints_ipv4, NULL);
}
}

struct path *pcep_lib_parse_path(struct pcep_message *msg)
Expand Down
49 changes: 36 additions & 13 deletions pathd/path_pcep_pcc.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,21 @@ int pcep_pcc_enable(struct ctrl_state *ctrl_state, struct pcc_state *pcc_state)
pcep_lib_connect(pcc_state->pcc_opts, pcc_state->pce_opts);

if (NULL == pcc_state->sess) {
flog_warn(EC_PATH_PCEP_LIB_CONNECT,
"failed to connect to PCE %pI4:%d from %pI4:%d",
&pcc_state->pce_opts->addr, pcc_state->pce_opts->port,
&pcc_state->pcc_opts->addr,
pcc_state->pcc_opts->port);
if (IS_IPADDR_V6(&pcc_state->pce_opts->addr)) {
flog_warn(EC_PATH_PCEP_LIB_CONNECT,
"failed to connect to PCE %pI6:%d from %pI6:%d",
&pcc_state->pce_opts->addr.ipaddr_v6,
pcc_state->pce_opts->port,
&pcc_state->pcc_opts->addr.ipaddr_v6,
pcc_state->pcc_opts->port);
} else {
flog_warn(EC_PATH_PCEP_LIB_CONNECT,
"failed to connect to PCE %pI4:%d from %pI4:%d",
&pcc_state->pce_opts->addr.ipaddr_v4,
pcc_state->pce_opts->port,
&pcc_state->pcc_opts->addr.ipaddr_v4,
pcc_state->pcc_opts->port);
}
schedule_reconnect(ctrl_state, pcc_state);
return 0;
}
Expand Down Expand Up @@ -402,8 +412,13 @@ void handle_pcep_lsp_update(struct ctrl_state *ctrl_state,
{
struct path *path;
path = pcep_lib_parse_path(msg);
path->sender.ipa_type = IPADDR_V4;
path->sender.ipaddr_v4 = pcc_state->pce_opts->addr;
if (IS_IPADDR_V6(&pcc_state->pce_opts->addr)) {
path->sender.ipa_type = IPADDR_V6;
memcpy(&path->sender.ipaddr_v6, &pcc_state->pce_opts->addr.ipaddr_v6, sizeof(struct in6_addr));
} else {
path->sender.ipa_type = IPADDR_V4;
path->sender.ipaddr_v4 = pcc_state->pce_opts->addr.ipaddr_v4;
}
lookup_nbkey(pcc_state, path);

push_srpid(pcc_state, path);
Expand Down Expand Up @@ -509,20 +524,28 @@ void send_comp_request(struct ctrl_state *ctrl_state,
struct pcep_message *msg;
struct ipaddr src;

/* TODO: Add support for IPv6 */
assert(IS_IPADDR_V4(&nbkey->endpoint));
/* The source address need to be defined explicitly for now */
assert(INADDR_ANY != pcc_state->pcc_opts->addr.s_addr);
if (IS_IPADDR_V6(&pcc_state->pcc_opts->addr)) {
assert(0 != memcmp(&in6addr_any, &pcc_state->pcc_opts->addr.ipaddr_v6,
sizeof(struct in6_addr)));
} else {
assert(INADDR_ANY != pcc_state->pcc_opts->addr.ipaddr_v4.s_addr);
}

reqid = push_req(pcc_state, nbkey);
/* TODO: Add a timer to retry the computation request */

PCEP_DEBUG("%s Sending computation request for path from %pI4 to %pI4",
pcc_state->tag, &pcc_state->pcc_opts->addr,
pcc_state->tag, &pcc_state->pcc_opts->addr.ipaddr_v4,
&nbkey->endpoint.ipaddr_v4);

src.ipa_type = IPADDR_V4;
src.ipaddr_v4.s_addr = pcc_state->pcc_opts->addr.s_addr;
src.ipa_type = pcc_state->pcc_opts->addr.ipa_type;
if (IS_IPADDR_V6(&pcc_state->pcc_opts->addr)) {
memcpy(&src.ipaddr_v6, &pcc_state->pcc_opts->addr.ipaddr_v6,
sizeof(struct in6_addr));
} else {
src.ipaddr_v4.s_addr = pcc_state->pcc_opts->addr.ipaddr_v4.s_addr;
}

msg = pcep_lib_format_request(reqid, &src, &nbkey->endpoint);
send_pcep_message(ctrl_state, pcc_state, msg);
Expand Down

0 comments on commit 979d122

Please sign in to comment.