Skip to content

Commit

Permalink
Support for multiple pce's
Browse files Browse the repository at this point in the history
Signed-off-by: Javier Garcia <javier.garcia@voltanet.io>
  • Loading branch information
Javier Garcia committed Jun 10, 2020
1 parent ef87269 commit 0e03b93
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 21 deletions.
68 changes: 59 additions & 9 deletions pathd/path_pcep.c
Original file line number Diff line number Diff line change
Expand Up @@ -417,22 +417,25 @@ DEFUN(pcep_cli_no_pcc, pcep_cli_no_pcc_cmd, "no pcc",
}

DEFUN(pcep_cli_pce, pcep_cli_pce_cmd,
"pce <ip A.B.C.D | ipv6 X:X::X:X> [port (1024-65535)] [sr-draft07]",
"pce <ip A.B.C.D | ipv6 X:X::X:X> [port (1024-65535)] [sr-draft07] [precedence (0-255)]",
"PCE configuration\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")
"Use the draft 07 of PCEP segment routing\n"
"Priority when multiple pce, the lower the more precedence\n"
"Priority value , (default 255)\n")
{
/* TODO: Add support for multiple PCE */

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

/* Get the first argument, should be either ip or ipv6 */
Expand Down Expand Up @@ -476,22 +479,35 @@ DEFUN(pcep_cli_pce, pcep_cli_pce_cmd,
i++;
continue;
}
if (strcmp("precedence", argv[i]->arg) == 0) {
i++;
if (i >= argc)
return CMD_ERR_NO_MATCH;
pce_precedence = atoi(argv[i]->arg);
i++;
continue;
}
return CMD_ERR_NO_MATCH;
}

pce_opts = XCALLOC(MTYPE_PCEP, sizeof(*pce_opts));
IPADDR_COPY(&pce_opts->addr, &pce_addr);
pce_opts->port = pce_port;
pce_opts->draft07 = draft07;
pce_opts->precedence = pce_precedence;

if (pcep_ctrl_update_pce_options(pcep_g->fpt, 1, pce_opts))
int current_pcc_id = get_pcc_id_by_ip(pcep_g->fpt, &pce_addr);
if (!current_pcc_id) {
current_pcc_id = pcep_ctrl_get_free_pcc_id(pcep_g->fpt);
}
if (pcep_ctrl_update_pce_options(pcep_g->fpt, current_pcc_id, pce_opts))
return CMD_WARNING;

if (pcep_g->pce_opts[0] != NULL)
if (pcep_g->pce_opts[current_pcc_id - 1] != NULL)
XFREE(MTYPE_PCEP, pcep_g->pce_opts[0]);
pce_opts_copy = XCALLOC(MTYPE_PCEP, sizeof(*pce_opts));
pce_opts_copy = memcpy(pce_opts_copy, pce_opts, sizeof(*pce_opts));
pcep_g->pce_opts[0] = pce_opts_copy;
pcep_g->pce_opts[current_pcc_id - 1] = pce_opts_copy;

return CMD_SUCCESS;
}
Expand All @@ -508,11 +524,39 @@ DEFUN(pcep_cli_no_pce, pcep_cli_no_pce_cmd,
"Remote PCE server port value\n")
{
/* TODO: Add support for multiple PCE */
int i = 2;
struct ipaddr pce_addr;
pce_addr.ipa_type = IPADDR_V4;
SET_IPADDR_V4(&pce_addr);
if (strcmp("ipv6", argv[i]->arg) == 0) {
SET_IPADDR_V6(&pce_addr);
} else if (strcmp("ip", argv[i]->arg) != 0) {
return CMD_ERR_NO_MATCH;
}

pcep_ctrl_remove_pcc(pcep_g->fpt, 1);
if (pcep_g->pce_opts[0] != NULL) {
XFREE(MTYPE_PCEP, pcep_g->pce_opts[0]);
pcep_g->pce_opts[0] = NULL;
/* Get the first argument value */
i++;
if (i >= argc) {
return CMD_ERR_NO_MATCH;
}
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;
}
}


int current_pcc_id = get_pcc_id_by_ip(pcep_g->fpt, &pce_addr);
if (current_pcc_id) {
pcep_ctrl_remove_pcc(pcep_g->fpt, current_pcc_id);
if (pcep_g->pce_opts[current_pcc_id - 1] != NULL) {
XFREE(MTYPE_PCEP, pcep_g->pce_opts[current_pcc_id - 1]);
pcep_g->pce_opts[current_pcc_id - 1] = NULL;
}
}
return CMD_SUCCESS;
}
Expand Down Expand Up @@ -622,6 +666,12 @@ int pcep_cli_pcc_config_write(struct vty *vty)
csnprintfrr(buff, sizeof(buff),
" sr-draft07");
}
if (pce_opts->precedence
!= PCE_DEFAULT_PRECEDENCE) {
csnprintfrr(buff, sizeof(buff),
" precedence %d",
pce_opts->precedence);
}
if (IS_IPADDR_V6(&pce_opts->addr)) {
vty_out(vty, " pce ipv6 %pI6%s\n",
&pce_opts->addr.ipaddr_v6,
Expand Down
4 changes: 3 additions & 1 deletion pathd/path_pcep.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@
#include "pathd/pathd.h"
#include "pathd/path_pcep_memory.h"

#define PCE_DEFAULT_PRECEDENCE 255
#define PCC_DEFAULT_MSD 4
#define PCEP_DEFAULT_PORT 4189
#define MAX_PCC 1
#define MAX_PCC 3
#define MAX_TAG_SIZE 50
#define PCEP_DEBUG_MODE_BASIC 0x01
#define PCEP_DEBUG_MODE_PATH 0x02
Expand Down Expand Up @@ -84,6 +85,7 @@ struct pce_opts {
struct ipaddr addr;
short port;
bool draft07;
uint8_t precedence;
};

struct pcc_opts {
Expand Down
73 changes: 64 additions & 9 deletions pathd/path_pcep_controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ int pcep_ctrl_initialize(struct thread_master *main_thread,
ctrl_state->pcc_count = 0;
ctrl_state->pcc_opts =
XCALLOC(MTYPE_PCEP, sizeof(*ctrl_state->pcc_opts));
memset(ctrl_state->pcc, 0, sizeof(ctrl_state->pcc[0]) * MAX_PCC);
/* Default to no PCC address defined */
UNSET_FLAG(ctrl_state->pcc_opts->flags, F_PCC_OPTS_IPV4);
UNSET_FLAG(ctrl_state->pcc_opts->flags, F_PCC_OPTS_IPV6);
Expand Down Expand Up @@ -659,6 +660,10 @@ int pcep_thread_event_update_pce_options(struct ctrl_state *ctrl_state,
set_pcc_state(ctrl_state, pcc_state);
} else {
pcc_state = get_pcc_state(ctrl_state, pcc_id);
if (!pcc_state) {
pcc_state = pcep_pcc_initialize(ctrl_state, pcc_id);
set_pcc_state(ctrl_state, pcc_state);
}
}

/* Copy the pcc options to delegate it to the update function */
Expand All @@ -677,11 +682,9 @@ int pcep_thread_event_remove_pcc(struct ctrl_state *ctrl_state, int pcc_id)
{
struct pcc_state *pcc_state;

if (pcc_id <= ctrl_state->pcc_count) {
pcc_state = get_pcc_state(ctrl_state, pcc_id);
remove_pcc_state(ctrl_state, pcc_state);
pcep_pcc_finalize(ctrl_state, pcc_state);
}

return 0;
}
Expand Down Expand Up @@ -710,6 +713,7 @@ int pcep_thread_event_pathd_event(struct ctrl_state *ctrl_state,

for (i = 0; i < ctrl_state->pcc_count; i++) {
struct pcc_state *pcc_state = ctrl_state->pcc[i];
path->is_delegated = is_best_pce(ctrl_state, i);
pcep_pcc_pathd_event_handler(ctrl_state, pcc_state, type, path);
}

Expand Down Expand Up @@ -753,7 +757,43 @@ int pcep_main_event_handler(struct thread *thread)


/* ------------ Helper functions ------------ */
int is_best_pce(struct ctrl_state *ctrl_state, int pce)
{
bool is_best = false;
int best_precedence = PCE_DEFAULT_PRECEDENCE;
int best_pce = 0;
for (int i = 0; i < ctrl_state->pcc_count; i++) {
if (ctrl_state->pcc[i]->pce_opts->precedence
< best_precedence) {
best_precedence =
ctrl_state->pcc[i]->pce_opts->precedence;
best_pce = i;
}
}
if (is_best = best_pce == pce) {
zlog_debug("best pce (%i) delegate to (%d)", pce + 1, is_best);
} else {
zlog_debug("not best pce (%i) delegate to (%d)", pce + 1,
is_best);
}
return is_best;
}
int pcep_ctrl_get_free_pcc_id(struct frr_pthread *fpt)
{
struct ctrl_state *ctrl_state = get_ctrl_state(fpt);
if (ctrl_state->pcc_count == 0) {
return 1;
}

for (int pcc_id = 0; pcc_id < MAX_PCC; pcc_id++) {
if (ctrl_state->pcc[pcc_id] == NULL) {
zlog_debug("new pcc_id (%d)", pcc_id + 1);
return pcc_id + 1;
}
}

return 0;
}
void set_ctrl_state(struct frr_pthread *fpt, struct ctrl_state *ctrl_state)
{
assert(fpt != NULL);
Expand All @@ -771,16 +811,32 @@ struct ctrl_state *get_ctrl_state(struct frr_pthread *fpt)
return ctrl_state;
}

int get_pcc_id_by_ip(struct frr_pthread *fpt, struct ipaddr *pce_ip)
{
struct ctrl_state *ctrl_state = get_ctrl_state(fpt);
for (int pcc_id = 0; pcc_id < MAX_PCC; pcc_id++) {
if (ctrl_state->pcc[pcc_id]) {
if (ipaddr_cmp((const struct ipaddr *)&ctrl_state
->pcc[pcc_id]
->pce_opts->addr,
(const struct ipaddr *)pce_ip)
== 0) {
zlog_debug("found pcc_id (%d)", pcc_id + 1);
return pcc_id + 1;
}
}
}
return 0;
}

struct pcc_state *get_pcc_state(struct ctrl_state *ctrl_state, int pcc_id)
{
assert(ctrl_state != NULL);
assert(pcc_id >= 0);
assert(pcc_id <= MAX_PCC);
assert(pcc_id <= ctrl_state->pcc_count);

struct pcc_state *pcc_state;
pcc_state = ctrl_state->pcc[pcc_id - 1];
assert(pcc_state != NULL);
return pcc_state;
}

Expand All @@ -789,11 +845,10 @@ void set_pcc_state(struct ctrl_state *ctrl_state, struct pcc_state *pcc_state)
assert(ctrl_state != NULL);
assert(pcc_state->id >= 0);
assert(pcc_state->id <= MAX_PCC);
assert(pcc_state->id > ctrl_state->pcc_count);
assert(ctrl_state->pcc[pcc_state->id - 1] == NULL);

ctrl_state->pcc[pcc_state->id - 1] = pcc_state;
ctrl_state->pcc_count = pcc_state->id;
ctrl_state->pcc_count++;
zlog_debug("added pce pcc_id (%d)", pcc_state->id);
}

void remove_pcc_state(struct ctrl_state *ctrl_state,
Expand All @@ -804,11 +859,11 @@ void remove_pcc_state(struct ctrl_state *ctrl_state,
assert(pcc_state->id <= MAX_PCC);
/* FIXME: Can only remove the last PCC for now,
* we have only one anyway */
assert(pcc_state->id == ctrl_state->pcc_count);
assert(ctrl_state->pcc[pcc_state->id - 1] != NULL);
// assert(ctrl_state->pcc[pcc_state->id - 1] != NULL);

ctrl_state->pcc[pcc_state->id - 1] = NULL;
ctrl_state->pcc_count--;
zlog_debug("removed pce pcc_id (%d)", pcc_state->id);
}

uint32_t backoff_delay(uint32_t max, uint32_t base, uint32_t retry_count)
Expand Down
3 changes: 3 additions & 0 deletions pathd/path_pcep_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ struct pcep_ctrl_socket_data {
typedef int (*pcep_ctrl_thread_callback)(struct thread *);

/* Functions called from the main thread */
int is_best_pce(struct ctrl_state *ctrl_state, int pce);
int get_pcc_id_by_ip(struct frr_pthread *fpt, struct ipaddr *pce_ip);
int pcep_ctrl_get_free_pcc_id(struct frr_pthread *fpt);
int pcep_ctrl_initialize(struct thread_master *main_thread,
struct frr_pthread **fpt,
pcep_main_event_handler_t event_handler);
Expand Down
4 changes: 2 additions & 2 deletions pathd/path_pcep_pcc.c
Original file line number Diff line number Diff line change
Expand Up @@ -773,8 +773,8 @@ void specialize_output_path(struct pcc_state *pcc_state, struct path *path)
}

path->pcc_id = pcc_state->id;
path->go_active = is_delegated;
path->is_delegated = is_delegated;
path->go_active = (is_delegated & path->is_delegated);
path->is_delegated = (is_delegated & path->is_delegated);
path->was_created = was_created;
}

Expand Down

0 comments on commit 0e03b93

Please sign in to comment.