lib: support multiple backup nexthops in nexthop group cli

Revise the nexthop-group cli to support multiple backups for
a single primary nexthop.

Signed-off-by: Mark Stapp <mjs@voltanet.io>
This commit is contained in:
Mark Stapp 2020-07-01 15:56:37 -04:00
parent 0cac0cf4a7
commit 28593bccc2
2 changed files with 55 additions and 31 deletions

View File

@ -43,12 +43,9 @@ struct nexthop_hold {
char *intf; char *intf;
char *labels; char *labels;
uint32_t weight; uint32_t weight;
int backup_idx; /* Index of backup nexthop, if >= 0 */ char *backup_str;
}; };
/* Invalid/unset value for nexthop_hold's backup_idx */
#define NHH_BACKUP_IDX_INVALID -1
struct nexthop_group_hooks { struct nexthop_group_hooks {
void (*new)(const char *name); void (*new)(const char *name);
void (*add_nexthop)(const struct nexthop_group_cmd *nhg, void (*add_nexthop)(const struct nexthop_group_cmd *nhg,
@ -677,7 +674,8 @@ static void nexthop_group_save_nhop(struct nexthop_group_cmd *nhgc,
const char *nhvrf_name, const char *nhvrf_name,
const union sockunion *addr, const union sockunion *addr,
const char *intf, const char *labels, const char *intf, const char *labels,
const uint32_t weight, int backup_idx) const uint32_t weight,
const char *backup_str)
{ {
struct nexthop_hold *nh; struct nexthop_hold *nh;
@ -694,7 +692,8 @@ static void nexthop_group_save_nhop(struct nexthop_group_cmd *nhgc,
nh->weight = weight; nh->weight = weight;
nh->backup_idx = backup_idx; if (backup_str)
nh->backup_str = XSTRDUP(MTYPE_TMP, backup_str);
listnode_add_sort(nhgc->nhg_list, nh); listnode_add_sort(nhgc->nhg_list, nh);
} }
@ -741,10 +740,11 @@ static bool nexthop_group_parse_nexthop(struct nexthop *nhop,
const union sockunion *addr, const union sockunion *addr,
const char *intf, const char *name, const char *intf, const char *name,
const char *labels, int *lbl_ret, const char *labels, int *lbl_ret,
uint32_t weight, int backup_idx) uint32_t weight, const char *backup_str)
{ {
int ret = 0; int ret = 0;
struct vrf *vrf; struct vrf *vrf;
int num;
memset(nhop, 0, sizeof(*nhop)); memset(nhop, 0, sizeof(*nhop));
@ -800,14 +800,15 @@ static bool nexthop_group_parse_nexthop(struct nexthop *nhop,
nhop->weight = weight; nhop->weight = weight;
if (backup_idx != NHH_BACKUP_IDX_INVALID) { if (backup_str) {
/* Validate index value */ /* Parse backup indexes */
if (backup_idx > NEXTHOP_BACKUP_IDX_MAX) ret = nexthop_str2backups(backup_str,
&num, nhop->backup_idx);
if (ret == 0) {
SET_FLAG(nhop->flags, NEXTHOP_FLAG_HAS_BACKUP);
nhop->backup_num = num;
} else
return false; return false;
SET_FLAG(nhop->flags, NEXTHOP_FLAG_HAS_BACKUP);
nhop->backup_num = 1;
nhop->backup_idx[0] = backup_idx;
} }
return true; return true;
@ -821,7 +822,7 @@ static bool nexthop_group_parse_nhh(struct nexthop *nhop,
{ {
return (nexthop_group_parse_nexthop(nhop, nhh->addr, nhh->intf, return (nexthop_group_parse_nexthop(nhop, nhh->addr, nhh->intf,
nhh->nhvrf_name, nhh->labels, NULL, nhh->nhvrf_name, nhh->labels, NULL,
nhh->weight, nhh->backup_idx)); nhh->weight, nhh->backup_str));
} }
DEFPY(ecmp_nexthops, ecmp_nexthops_cmd, DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
@ -834,7 +835,7 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
nexthop-vrf NAME$vrf_name \ nexthop-vrf NAME$vrf_name \
|label WORD \ |label WORD \
|weight (1-255) \ |weight (1-255) \
|backup-idx$bi_str (0-254)$idx \ |backup-idx WORD \
}]", }]",
NO_STR NO_STR
"Specify one of the nexthops in this ECMP group\n" "Specify one of the nexthops in this ECMP group\n"
@ -848,19 +849,26 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
"One or more labels in the range (16-1048575) separated by '/'\n" "One or more labels in the range (16-1048575) separated by '/'\n"
"Weight to be used by the nexthop for purposes of ECMP\n" "Weight to be used by the nexthop for purposes of ECMP\n"
"Weight value to be used\n" "Weight value to be used\n"
"Backup nexthop index in another group\n" "Specify backup nexthop indexes in another group\n"
"Nexthop index value\n") "One or more indexes in the range (0-254) separated by ','\n")
{ {
VTY_DECLVAR_CONTEXT(nexthop_group_cmd, nhgc); VTY_DECLVAR_CONTEXT(nexthop_group_cmd, nhgc);
struct nexthop nhop; struct nexthop nhop;
struct nexthop *nh; struct nexthop *nh;
int lbl_ret = 0; int lbl_ret = 0;
bool legal; bool legal;
int backup_idx = idx; int num;
uint8_t backups[NEXTHOP_MAX_BACKUPS];
bool yes = !no; bool yes = !no;
if (bi_str == NULL) /* Pre-parse backup string to validate */
backup_idx = NHH_BACKUP_IDX_INVALID; if (backup_idx) {
lbl_ret = nexthop_str2backups(backup_idx, &num, backups);
if (lbl_ret < 0) {
vty_out(vty, "%% Invalid backups\n");
return CMD_WARNING_CONFIG_FAILED;
}
}
legal = nexthop_group_parse_nexthop(&nhop, addr, intf, vrf_name, label, legal = nexthop_group_parse_nexthop(&nhop, addr, intf, vrf_name, label,
&lbl_ret, weight, backup_idx); &lbl_ret, weight, backup_idx);
@ -944,10 +952,11 @@ static struct cmd_node nexthop_group_node = {
.config_write = nexthop_group_write, .config_write = nexthop_group_write,
}; };
void nexthop_group_write_nexthop(struct vty *vty, struct nexthop *nh) void nexthop_group_write_nexthop(struct vty *vty, const struct nexthop *nh)
{ {
char buf[100]; char buf[100];
struct vrf *vrf; struct vrf *vrf;
int i;
vty_out(vty, "nexthop "); vty_out(vty, "nexthop ");
@ -992,16 +1001,22 @@ void nexthop_group_write_nexthop(struct vty *vty, struct nexthop *nh)
if (nh->weight) if (nh->weight)
vty_out(vty, " weight %u", nh->weight); vty_out(vty, " weight %u", nh->weight);
if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_HAS_BACKUP)) if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
vty_out(vty, " backup-idx %d", nh->backup_idx[0]); vty_out(vty, " backup-idx %d", nh->backup_idx[0]);
for (i = 1; i < nh->backup_num; i++)
vty_out(vty, ",%d", nh->backup_idx[i]);
}
vty_out(vty, "\n"); vty_out(vty, "\n");
} }
void nexthop_group_json_nexthop(json_object *j, struct nexthop *nh) void nexthop_group_json_nexthop(json_object *j, const struct nexthop *nh)
{ {
char buf[100]; char buf[100];
struct vrf *vrf; struct vrf *vrf;
json_object *json_backups = NULL;
int i;
switch (nh->type) { switch (nh->type) {
case NEXTHOP_TYPE_IFINDEX: case NEXTHOP_TYPE_IFINDEX:
@ -1048,12 +1063,19 @@ void nexthop_group_json_nexthop(json_object *j, struct nexthop *nh)
if (nh->weight) if (nh->weight)
json_object_int_add(j, "weight", nh->weight); json_object_int_add(j, "weight", nh->weight);
if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_HAS_BACKUP)) if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
json_object_int_add(j, "backupIdx", nh->backup_idx[0]); json_backups = json_object_new_array();
for (i = 0; i < nh->backup_num; i++)
json_object_array_add(
json_backups,
json_object_new_int(nh->backup_idx[i]));
json_object_object_add(j, "backupIdx", json_backups);
}
} }
static void nexthop_group_write_nexthop_internal(struct vty *vty, static void nexthop_group_write_nexthop_internal(struct vty *vty,
struct nexthop_hold *nh) const struct nexthop_hold *nh)
{ {
char buf[100]; char buf[100];
@ -1074,8 +1096,8 @@ static void nexthop_group_write_nexthop_internal(struct vty *vty,
if (nh->weight) if (nh->weight)
vty_out(vty, " weight %u", nh->weight); vty_out(vty, " weight %u", nh->weight);
if (nh->backup_idx != NHH_BACKUP_IDX_INVALID) if (nh->backup_str)
vty_out(vty, " backup-idx %d", nh->backup_idx); vty_out(vty, " backup-idx %s", nh->backup_str);
vty_out(vty, "\n"); vty_out(vty, "\n");
} }

View File

@ -135,9 +135,11 @@ extern bool nexthop_group_equal(const struct nexthop_group *nhg1,
extern struct nexthop_group_cmd *nhgc_find(const char *name); extern struct nexthop_group_cmd *nhgc_find(const char *name);
extern void nexthop_group_write_nexthop(struct vty *vty, struct nexthop *nh); extern void nexthop_group_write_nexthop(struct vty *vty,
const struct nexthop *nh);
extern void nexthop_group_json_nexthop(json_object *j, struct nexthop *nh); extern void nexthop_group_json_nexthop(json_object *j,
const struct nexthop *nh);
/* Return the number of nexthops in this nhg */ /* Return the number of nexthops in this nhg */
extern uint8_t nexthop_group_nexthop_num(const struct nexthop_group *nhg); extern uint8_t nexthop_group_nexthop_num(const struct nexthop_group *nhg);