mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 15:33:56 +00:00
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:
parent
0cac0cf4a7
commit
28593bccc2
@ -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");
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user