Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement IPv6 PCEP connections #7

Merged
merged 1 commit into from
Apr 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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