diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/bfd.c | 27 | ||||
| -rw-r--r-- | lib/bfd.h | 4 | ||||
| -rw-r--r-- | lib/command.h | 12 | ||||
| -rw-r--r-- | lib/libfrr.c | 10 | ||||
| -rw-r--r-- | lib/nexthop.c | 127 | ||||
| -rw-r--r-- | lib/nexthop.h | 25 | ||||
| -rw-r--r-- | lib/nexthop_group.c | 81 | ||||
| -rw-r--r-- | lib/nexthop_group.h | 6 | ||||
| -rw-r--r-- | lib/pbr.h | 7 | ||||
| -rwxr-xr-x | lib/route_types.pl | 2 | ||||
| -rw-r--r-- | lib/stream.c | 14 | ||||
| -rw-r--r-- | lib/subdir.am | 3 | ||||
| -rw-r--r-- | lib/vrf.c | 6 | ||||
| -rw-r--r-- | lib/zclient.c | 37 | ||||
| -rw-r--r-- | lib/zclient.h | 5 | ||||
| -rw-r--r-- | lib/zlog.c | 6 |
16 files changed, 273 insertions, 99 deletions
@@ -94,7 +94,8 @@ int bfd_validate_param(struct vty *vty, const char *dm_str, const char *rx_str, * bfd_set_param - Set the configured BFD paramter values */ void bfd_set_param(struct bfd_info **bfd_info, uint32_t min_rx, uint32_t min_tx, - uint8_t detect_mult, int defaults, int *command) + uint8_t detect_mult, const char *profile, int defaults, + int *command) { if (!*bfd_info) { *bfd_info = bfd_info_create(); @@ -102,7 +103,8 @@ void bfd_set_param(struct bfd_info **bfd_info, uint32_t min_rx, uint32_t min_tx, } else { if (((*bfd_info)->required_min_rx != min_rx) || ((*bfd_info)->desired_min_tx != min_tx) - || ((*bfd_info)->detect_mult != detect_mult)) + || ((*bfd_info)->detect_mult != detect_mult) + || (profile && strcmp((*bfd_info)->profile, profile))) *command = ZEBRA_BFD_DEST_UPDATE; } @@ -110,6 +112,11 @@ void bfd_set_param(struct bfd_info **bfd_info, uint32_t min_rx, uint32_t min_tx, (*bfd_info)->required_min_rx = min_rx; (*bfd_info)->desired_min_tx = min_tx; (*bfd_info)->detect_mult = detect_mult; + if (profile) + strlcpy((*bfd_info)->profile, profile, + BFD_PROFILE_NAME_LEN); + else + (*bfd_info)->profile[0] = '\0'; } if (!defaults) @@ -121,6 +128,8 @@ void bfd_set_param(struct bfd_info **bfd_info, uint32_t min_rx, uint32_t min_tx, /* * bfd_peer_sendmsg - Format and send a peer register/Unregister * command to Zebra to be forwarded to BFD + * + * DEPRECATED: use zclient_bfd_command instead */ void bfd_peer_sendmsg(struct zclient *zclient, struct bfd_info *bfd_info, int family, void *dst_ip, void *src_ip, char *if_name, @@ -161,6 +170,11 @@ void bfd_peer_sendmsg(struct zclient *zclient, struct bfd_info *bfd_info, args.min_rx = bfd_info->required_min_rx; args.min_tx = bfd_info->desired_min_tx; args.detection_multiplier = bfd_info->detect_mult; + if (bfd_info->profile[0]) { + args.profilelen = strlen(bfd_info->profile); + strlcpy(args.profile, bfd_info->profile, + sizeof(args.profile)); + } } addrlen = family == AF_INET ? sizeof(struct in_addr) @@ -425,6 +439,15 @@ int zclient_bfd_command(struct zclient *zc, struct bfd_session_arg *args) struct stream *s; size_t addrlen; + /* Individual reg/dereg messages are suppressed during shutdown. */ + if (CHECK_FLAG(bfd_gbl.flags, BFD_GBL_FLAG_IN_SHUTDOWN)) { + if (bfd_debug) + zlog_debug( + "%s: Suppressing BFD peer reg/dereg messages", + __func__); + return -1; + } + /* Check socket. */ if (!zc || zc->sock < 0) { if (bfd_debug) @@ -92,8 +92,8 @@ extern int bfd_validate_param(struct vty *vty, const char *dm_str, uint32_t *tx_val); extern void bfd_set_param(struct bfd_info **bfd_info, uint32_t min_rx, - uint32_t min_tx, uint8_t detect_mult, int defaults, - int *command); + uint32_t min_tx, uint8_t detect_mult, + const char *profile, int defaults, int *command); extern void bfd_peer_sendmsg(struct zclient *zclient, struct bfd_info *bfd_info, int family, void *dst_ip, void *src_ip, char *if_name, int ttl, int multihop, int cbit, diff --git a/lib/command.h b/lib/command.h index 21bb613540..1acca90665 100644 --- a/lib/command.h +++ b/lib/command.h @@ -328,18 +328,6 @@ struct cmd_node { DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, \ CMD_ATTR_DEPRECATED, daemon) -#else /* VTYSH_EXTRACT_PL */ -#define DEFPY(funcname, cmdname, cmdstr, helpstr) \ - DEFUN(funcname, cmdname, cmdstr, helpstr) - -#define DEFPY_NOSH(funcname, cmdname, cmdstr, helpstr) \ - DEFUN_NOSH(funcname, cmdname, cmdstr, helpstr) - -#define DEFPY_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \ - DEFUN_ATTR(funcname, cmdname, cmdstr, helpstr, attr) - -#define DEFPY_HIDDEN(funcname, cmdname, cmdstr, helpstr) \ - DEFUN_HIDDEN(funcname, cmdname, cmdstr, helpstr) #endif /* VTYSH_EXTRACT_PL */ /* Some macroes */ diff --git a/lib/libfrr.c b/lib/libfrr.c index b3df7de6d3..2597eb61e2 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -105,6 +105,7 @@ static const struct option lo_always[] = { {"daemon", no_argument, NULL, 'd'}, {"module", no_argument, NULL, 'M'}, {"profile", required_argument, NULL, 'F'}, + {"pathspace", required_argument, NULL, 'N'}, {"vty_socket", required_argument, NULL, OPTION_VTYSOCK}, {"moduledir", required_argument, NULL, OPTION_MODULEDIR}, {"log", required_argument, NULL, OPTION_LOG}, @@ -113,12 +114,13 @@ static const struct option lo_always[] = { {"command-log-always", no_argument, NULL, OPTION_LOGGING}, {NULL}}; static const struct optspec os_always = { - "hvdM:F:", + "hvdM:F:N:", " -h, --help Display this help and exit\n" " -v, --version Print program version\n" " -d, --daemon Runs in daemon mode\n" " -M, --module Load specified module\n" " -F, --profile Use specified configuration profile\n" + " -N, --pathspace Insert prefix into config & socket paths\n" " --vty_socket Override vty socket path\n" " --moduledir Override modules directory\n" " --log Set Logging to stdout, syslog, or file:<name>\n" @@ -133,18 +135,16 @@ static const struct option lo_cfg_pid_dry[] = { #ifdef HAVE_SQLITE3 {"db_file", required_argument, NULL, OPTION_DB_FILE}, #endif - {"pathspace", required_argument, NULL, 'N'}, {"dryrun", no_argument, NULL, 'C'}, {"terminal", no_argument, NULL, 't'}, {NULL}}; static const struct optspec os_cfg_pid_dry = { - "f:i:CtN:", + "f:i:Ct", " -f, --config_file Set configuration file name\n" " -i, --pid_file Set process identifier file name\n" #ifdef HAVE_SQLITE3 " --db_file Set database file name\n" #endif - " -N, --pathspace Insert prefix into config & socket paths\n" " -C, --dryrun Check configuration for validity and exit\n" " -t, --terminal Open terminal session on stdio\n" " -d -t Daemonize after terminal session ends\n", @@ -428,8 +428,6 @@ static int frr_opt(int opt) di->config_file = optarg; break; case 'N': - if (di->flags & FRR_NO_CFG_PID_DRY) - return 1; if (di->pathspace) { fprintf(stderr, "-N/--pathspace option specified more than once!\n"); diff --git a/lib/nexthop.c b/lib/nexthop.c index 3496081d47..28d96a539c 100644 --- a/lib/nexthop.c +++ b/lib/nexthop.c @@ -157,6 +157,10 @@ static int _nexthop_cmp_no_labels(const struct nexthop *next1, goto done; if (!CHECK_FLAG(next1->flags, NEXTHOP_FLAG_HAS_BACKUP) && + !CHECK_FLAG(next2->flags, NEXTHOP_FLAG_HAS_BACKUP)) + return 0; + + if (!CHECK_FLAG(next1->flags, NEXTHOP_FLAG_HAS_BACKUP) && CHECK_FLAG(next2->flags, NEXTHOP_FLAG_HAS_BACKUP)) return -1; @@ -164,12 +168,18 @@ static int _nexthop_cmp_no_labels(const struct nexthop *next1, !CHECK_FLAG(next2->flags, NEXTHOP_FLAG_HAS_BACKUP)) return 1; - if (next1->backup_idx < next2->backup_idx) + if (next1->backup_num == 0 && next2->backup_num == 0) + goto done; + + if (next1->backup_num < next2->backup_num) return -1; - if (next1->backup_idx > next2->backup_idx) + if (next1->backup_num > next2->backup_num) return 1; + ret = memcmp(next1->backup_idx, + next2->backup_idx, next1->backup_num); + done: return ret; } @@ -515,11 +525,12 @@ struct nexthop *nexthop_next_active_resolved(const struct nexthop *nexthop) return next; } -unsigned int nexthop_level(struct nexthop *nexthop) +unsigned int nexthop_level(const struct nexthop *nexthop) { unsigned int rv = 0; - for (struct nexthop *par = nexthop->rparent; par; par = par->rparent) + for (const struct nexthop *par = nexthop->rparent; + par; par = par->rparent) rv++; return rv; @@ -529,14 +540,15 @@ unsigned int nexthop_level(struct nexthop *nexthop) uint32_t nexthop_hash_quick(const struct nexthop *nexthop) { uint32_t key = 0x45afe398; - uint32_t val; + int i; key = jhash_3words(nexthop->type, nexthop->vrf_id, nexthop->nh_label_type, key); if (nexthop->nh_label) { int labels = nexthop->nh_label->num_labels; - int i = 0; + + i = 0; while (labels >= 3) { key = jhash_3words(nexthop->nh_label->label[i], @@ -559,14 +571,35 @@ uint32_t nexthop_hash_quick(const struct nexthop *nexthop) key = jhash_1word(nexthop->nh_label->label[i], key); } - val = 0; - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) - val = (uint32_t)nexthop->backup_idx; - - key = jhash_3words(nexthop->ifindex, - CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK), val, + key = jhash_2words(nexthop->ifindex, + CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK), key); + /* Include backup nexthops, if present */ + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) { + int backups = nexthop->backup_num; + + i = 0; + + while (backups >= 3) { + key = jhash_3words(nexthop->backup_idx[i], + nexthop->backup_idx[i + 1], + nexthop->backup_idx[i + 2], key); + backups -= 3; + i += 3; + } + + while (backups >= 2) { + key = jhash_2words(nexthop->backup_idx[i], + nexthop->backup_idx[i + 1], key); + backups -= 2; + i += 2; + } + + if (backups >= 1) + key = jhash_1word(nexthop->backup_idx[i], key); + } + return key; } @@ -604,7 +637,12 @@ void nexthop_copy_no_recurse(struct nexthop *copy, copy->type = nexthop->type; copy->flags = nexthop->flags; copy->weight = nexthop->weight; - copy->backup_idx = nexthop->backup_idx; + + assert(nexthop->backup_num < NEXTHOP_MAX_BACKUPS); + copy->backup_num = nexthop->backup_num; + if (copy->backup_num > 0) + memcpy(copy->backup_idx, nexthop->backup_idx, copy->backup_num); + memcpy(©->gate, &nexthop->gate, sizeof(nexthop->gate)); memcpy(©->src, &nexthop->src, sizeof(nexthop->src)); memcpy(©->rmap_src, &nexthop->rmap_src, sizeof(nexthop->rmap_src)); @@ -621,7 +659,7 @@ void nexthop_copy(struct nexthop *copy, const struct nexthop *nexthop, nexthop_copy_no_recurse(copy, nexthop, rparent); /* Bit of a special case here, we need to handle the case - * of a nexthop resolving to agroup. Hence, we need to + * of a nexthop resolving to a group. Hence, we need to * use a nexthop_group API. */ if (CHECK_FLAG(copy->flags, NEXTHOP_FLAG_RECURSIVE)) @@ -647,6 +685,67 @@ struct nexthop *nexthop_dup(const struct nexthop *nexthop, } /* + * Parse one or more backup index values, as comma-separated numbers, + * into caller's array of uint8_ts. The array must be NEXTHOP_MAX_BACKUPS + * in size. Mails back the number of values converted, and returns 0 on + * success, <0 if an error in parsing. + */ +int nexthop_str2backups(const char *str, int *num_backups, + uint8_t *backups) +{ + char *ostr; /* copy of string (start) */ + char *lstr; /* working copy of string */ + char *nump; /* pointer to next segment */ + char *endp; /* end pointer */ + int i, ret; + uint8_t tmp[NEXTHOP_MAX_BACKUPS]; + uint32_t lval; + + /* Copy incoming string; the parse is destructive */ + lstr = ostr = XSTRDUP(MTYPE_TMP, str); + *num_backups = 0; + ret = 0; + + for (i = 0; i < NEXTHOP_MAX_BACKUPS && lstr; i++) { + nump = strsep(&lstr, ","); + lval = strtoul(nump, &endp, 10); + + /* Format check */ + if (*endp != '\0') { + ret = -1; + break; + } + + /* Empty value */ + if (endp == nump) { + ret = -1; + break; + } + + /* Limit to one octet */ + if (lval > 255) { + ret = -1; + break; + } + + tmp[i] = lval; + } + + /* Excess values */ + if (ret == 0 && i == NEXTHOP_MAX_BACKUPS && lstr) + ret = -1; + + if (ret == 0) { + *num_backups = i; + memcpy(backups, tmp, i); + } + + XFREE(MTYPE_TMP, ostr); + + return ret; +} + +/* * nexthop printing variants: * %pNHvv * via 1.2.3.4 diff --git a/lib/nexthop.h b/lib/nexthop.h index eda88efc08..ed40cc7eed 100644 --- a/lib/nexthop.h +++ b/lib/nexthop.h @@ -65,6 +65,12 @@ enum nh_encap_type { NET_VXLAN = 100, /* value copied from FPM_NH_ENCAP_VXLAN. */ }; +/* Fixed limit on the number of backup nexthops per primary nexthop */ +#define NEXTHOP_MAX_BACKUPS 8 + +/* Backup index value is limited */ +#define NEXTHOP_BACKUP_IDX_MAX 255 + /* Nexthop structure. */ struct nexthop { struct nexthop *next; @@ -124,10 +130,11 @@ struct nexthop { /* Weight of the nexthop ( for unequal cost ECMP ) */ uint8_t weight; - /* Index of a corresponding backup nexthop in a backup list; + /* Count and index of corresponding backup nexthop(s) in a backup list; * only meaningful if the HAS_BACKUP flag is set. */ - uint8_t backup_idx; + uint8_t backup_num; + uint8_t backup_idx[NEXTHOP_MAX_BACKUPS]; /* Encapsulation information. */ enum nh_encap_type nh_encap_type; @@ -136,9 +143,6 @@ struct nexthop { } nh_encap; }; -/* Backup index value is limited */ -#define NEXTHOP_BACKUP_IDX_MAX 255 - /* Utility to append one nexthop to another. */ #define NEXTHOP_APPEND(to, new) \ do { \ @@ -216,7 +220,7 @@ extern const char *nexthop2str(const struct nexthop *nexthop, extern struct nexthop *nexthop_next(const struct nexthop *nexthop); extern struct nexthop * nexthop_next_active_resolved(const struct nexthop *nexthop); -extern unsigned int nexthop_level(struct nexthop *nexthop); +extern unsigned int nexthop_level(const struct nexthop *nexthop); /* Copies to an already allocated nexthop struct */ extern void nexthop_copy(struct nexthop *copy, const struct nexthop *nexthop, struct nexthop *rparent); @@ -231,6 +235,15 @@ extern struct nexthop *nexthop_dup(const struct nexthop *nexthop, extern struct nexthop *nexthop_dup_no_recurse(const struct nexthop *nexthop, struct nexthop *rparent); +/* + * Parse one or more backup index values, as comma-separated numbers, + * into caller's array of uint8_ts. The array must be NEXTHOP_MAX_BACKUPS + * in size. Mails back the number of values converted, and returns 0 on + * success, <0 if an error in parsing. + */ +int nexthop_str2backups(const char *str, int *num_backups, + uint8_t *backups); + #ifdef _FRR_ATTRIBUTE_PRINTFRR #pragma FRR printfrr_ext "%pNH" (struct nexthop *) #endif diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c index 4f0c72af27..97815ceeb9 100644 --- a/lib/nexthop_group.c +++ b/lib/nexthop_group.c @@ -43,12 +43,9 @@ struct nexthop_hold { char *intf; char *labels; 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 { void (*new)(const char *name); 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 union sockunion *addr, 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; @@ -694,7 +692,8 @@ static void nexthop_group_save_nhop(struct nexthop_group_cmd *nhgc, 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); } @@ -741,10 +740,11 @@ static bool nexthop_group_parse_nexthop(struct nexthop *nhop, const union sockunion *addr, const char *intf, const char *name, const char *labels, int *lbl_ret, - uint32_t weight, int backup_idx) + uint32_t weight, const char *backup_str) { int ret = 0; struct vrf *vrf; + int num; memset(nhop, 0, sizeof(*nhop)); @@ -800,13 +800,15 @@ static bool nexthop_group_parse_nexthop(struct nexthop *nhop, nhop->weight = weight; - if (backup_idx != NHH_BACKUP_IDX_INVALID) { - /* Validate index value */ - if (backup_idx > NEXTHOP_BACKUP_IDX_MAX) + if (backup_str) { + /* Parse backup indexes */ + 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; - - SET_FLAG(nhop->flags, NEXTHOP_FLAG_HAS_BACKUP); - nhop->backup_idx = backup_idx; } return true; @@ -820,7 +822,7 @@ static bool nexthop_group_parse_nhh(struct nexthop *nhop, { return (nexthop_group_parse_nexthop(nhop, nhh->addr, nhh->intf, nhh->nhvrf_name, nhh->labels, NULL, - nhh->weight, nhh->backup_idx)); + nhh->weight, nhh->backup_str)); } DEFPY(ecmp_nexthops, ecmp_nexthops_cmd, @@ -833,7 +835,7 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd, nexthop-vrf NAME$vrf_name \ |label WORD \ |weight (1-255) \ - |backup-idx$bi_str (0-254)$idx \ + |backup-idx WORD \ }]", NO_STR "Specify one of the nexthops in this ECMP group\n" @@ -847,19 +849,26 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd, "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 value to be used\n" - "Backup nexthop index in another group\n" - "Nexthop index value\n") + "Specify backup nexthop indexes in another group\n" + "One or more indexes in the range (0-254) separated by ','\n") { VTY_DECLVAR_CONTEXT(nexthop_group_cmd, nhgc); struct nexthop nhop; struct nexthop *nh; int lbl_ret = 0; bool legal; - int backup_idx = idx; + int num; + uint8_t backups[NEXTHOP_MAX_BACKUPS]; bool yes = !no; - if (bi_str == NULL) - backup_idx = NHH_BACKUP_IDX_INVALID; + /* Pre-parse backup string to validate */ + 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, &lbl_ret, weight, backup_idx); @@ -943,10 +952,11 @@ static struct cmd_node nexthop_group_node = { .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]; struct vrf *vrf; + int i; vty_out(vty, "nexthop "); @@ -991,16 +1001,22 @@ void nexthop_group_write_nexthop(struct vty *vty, struct nexthop *nh) if (nh->weight) vty_out(vty, " weight %u", nh->weight); - if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_HAS_BACKUP)) - vty_out(vty, " backup-idx %d", nh->backup_idx); + if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_HAS_BACKUP)) { + 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"); } -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]; struct vrf *vrf; + json_object *json_backups = NULL; + int i; switch (nh->type) { case NEXTHOP_TYPE_IFINDEX: @@ -1047,12 +1063,19 @@ void nexthop_group_json_nexthop(json_object *j, struct nexthop *nh) if (nh->weight) json_object_int_add(j, "weight", nh->weight); - if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_HAS_BACKUP)) - json_object_int_add(j, "backupIdx", nh->backup_idx); + if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_HAS_BACKUP)) { + 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, - struct nexthop_hold *nh) + const struct nexthop_hold *nh) { char buf[100]; @@ -1073,8 +1096,8 @@ static void nexthop_group_write_nexthop_internal(struct vty *vty, if (nh->weight) vty_out(vty, " weight %u", nh->weight); - if (nh->backup_idx != NHH_BACKUP_IDX_INVALID) - vty_out(vty, " backup-idx %d", nh->backup_idx); + if (nh->backup_str) + vty_out(vty, " backup-idx %s", nh->backup_str); vty_out(vty, "\n"); } diff --git a/lib/nexthop_group.h b/lib/nexthop_group.h index 9888dad982..0b5ac91bb2 100644 --- a/lib/nexthop_group.h +++ b/lib/nexthop_group.h @@ -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 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 */ extern uint8_t nexthop_group_nexthop_num(const struct nexthop_group *nhg); @@ -49,6 +49,10 @@ struct pbr_filter { #define PBR_FILTER_PROTO (1 << 5) #define PBR_FILTER_SRC_PORT_RANGE (1 << 6) #define PBR_FILTER_DST_PORT_RANGE (1 << 7) +#define PBR_FILTER_DSFIELD (1 << 8) + +#define PBR_DSFIELD_DSCP (0xfc) /* Upper 6 bits of DS field: DSCP */ +#define PBR_DSFIELD_ECN (0x03) /* Lower 2 bits of DS field: BCN */ /* Source and Destination IP address with masks. */ struct prefix src_ip; @@ -58,6 +62,9 @@ struct pbr_filter { uint16_t src_port; uint16_t dst_port; + /* Filter by Differentiated Services field */ + uint8_t dsfield; /* DSCP (6 bits) & ECN (2 bits) */ + /* Filter with fwmark */ uint32_t fwmark; }; diff --git a/lib/route_types.pl b/lib/route_types.pl index f297096633..e007de4d69 100755 --- a/lib/route_types.pl +++ b/lib/route_types.pl @@ -121,7 +121,7 @@ sub codelist { } $str =~ s/ $//; push @lines, $str . "\\n\" \\\n"; - push @lines, " \" > - selected route, * - FIB route, q - queued route, r - rejected route\\n\\n\""; + push @lines, " \" > - selected route, * - FIB route, q - queued, r - rejected, b - backup\\n\\n\""; return join("", @lines); } diff --git a/lib/stream.c b/lib/stream.c index 17520f978e..d3afebbf13 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -55,15 +55,19 @@ DEFINE_MTYPE_STATIC(LIB, STREAM_FIFO, "Stream FIFO") * using stream_put..._at() functions. */ #define STREAM_WARN_OFFSETS(S) \ - flog_warn(EC_LIB_STREAM, \ - "&(struct stream): %p, size: %lu, getp: %lu, endp: %lu\n", \ - (void *)(S), (unsigned long)(S)->size, \ - (unsigned long)(S)->getp, (unsigned long)(S)->endp) + do { \ + flog_warn(EC_LIB_STREAM, \ + "&(struct stream): %p, size: %lu, getp: %lu, endp: %lu\n", \ + (void *)(S), (unsigned long)(S)->size, \ + (unsigned long)(S)->getp, (unsigned long)(S)->endp); \ + zlog_backtrace(LOG_WARNING); \ + } while (0) #define STREAM_VERIFY_SANE(S) \ do { \ - if (!(GETP_VALID(S, (S)->getp) && ENDP_VALID(S, (S)->endp))) \ + if (!(GETP_VALID(S, (S)->getp) && ENDP_VALID(S, (S)->endp))) { \ STREAM_WARN_OFFSETS(S); \ + } \ assert(GETP_VALID(S, (S)->getp)); \ assert(ENDP_VALID(S, (S)->endp)); \ } while (0) diff --git a/lib/subdir.am b/lib/subdir.am index f185841c76..34ad30f968 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -124,9 +124,6 @@ nodist_lib_libfrr_la_SOURCES = \ yang/ietf/ietf-interfaces.yang.c \ yang/frr-module-translator.yang.c \ yang/frr-nexthop.yang.c \ - yang/frr-igmp.yang.c \ - yang/frr-pim.yang.c \ - yang/frr-pim-rp.yang.c \ # end vtysh_scan += \ @@ -757,10 +757,8 @@ DEFUN (no_vrf, vrfp = vrf_lookup_by_name(vrfname); - if (vrfp == NULL) { - vty_out(vty, "%% VRF %s does not exist\n", vrfname); - return CMD_WARNING_CONFIG_FAILED; - } + if (vrfp == NULL) + return CMD_SUCCESS; if (CHECK_FLAG(vrfp->status, VRF_ACTIVE)) { vty_out(vty, "%% Only inactive VRFs can be deleted\n"); diff --git a/lib/zclient.c b/lib/zclient.c index d8f311fcec..92ff2537d5 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -888,7 +888,7 @@ static void zapi_nexthop_group_sort(struct zapi_nexthop *nh_grp, int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh, uint32_t api_flags) { - int ret = 0; + int i, ret = 0; int nh_flags = api_nh->flags; stream_putl(s, api_nh->vrf_id); @@ -951,8 +951,17 @@ int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh, sizeof(struct ethaddr)); /* Index of backup nexthop */ - if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) - stream_putc(s, api_nh->backup_idx); + if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) { + /* Validate backup count */ + if (api_nh->backup_num > NEXTHOP_MAX_BACKUPS) { + ret = -1; + goto done; + } + + stream_putc(s, api_nh->backup_num); + for (i = 0; i < api_nh->backup_num; i++) + stream_putc(s, api_nh->backup_idx[i]); + } done: return ret; @@ -1111,7 +1120,7 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api) static int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh, uint32_t api_flags) { - int ret = -1; + int i, ret = -1; STREAM_GETL(s, api_nh->vrf_id); STREAM_GETC(s, api_nh->type); @@ -1163,8 +1172,15 @@ static int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh, sizeof(struct ethaddr)); /* Backup nexthop index */ - if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) - STREAM_GETC(s, api_nh->backup_idx); + if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) { + STREAM_GETC(s, api_nh->backup_num); + + if (api_nh->backup_num > NEXTHOP_MAX_BACKUPS) + return -1; + + for (i = 0; i < api_nh->backup_num; i++) + STREAM_GETC(s, api_nh->backup_idx[i]); + } /* Success */ ret = 0; @@ -1483,7 +1499,8 @@ struct nexthop *nexthop_from_zapi_nexthop(const struct zapi_nexthop *znh) if (CHECK_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) { SET_FLAG(n->flags, NEXTHOP_FLAG_HAS_BACKUP); - n->backup_idx = znh->backup_idx; + n->backup_num = znh->backup_num; + memcpy(n->backup_idx, znh->backup_idx, n->backup_num); } return n; @@ -1519,8 +1536,12 @@ int zapi_nexthop_from_nexthop(struct zapi_nexthop *znh, } if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_HAS_BACKUP)) { + if (nh->backup_num > NEXTHOP_MAX_BACKUPS) + return -1; + SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP); - znh->backup_idx = nh->backup_idx; + znh->backup_num = nh->backup_num; + memcpy(znh->backup_idx, nh->backup_idx, znh->backup_num); } return 0; diff --git a/lib/zclient.h b/lib/zclient.h index 3ded2f55d7..250824e612 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -394,8 +394,9 @@ struct zapi_nexthop { uint32_t weight; - /* Index of backup nexthop */ - uint8_t backup_idx; + /* Backup nexthops, for IP-FRR, TI-LFA, etc */ + uint8_t backup_num; + uint8_t backup_idx[NEXTHOP_MAX_BACKUPS]; }; /* diff --git a/lib/zlog.c b/lib/zlog.c index 45726755f8..8dfd20371b 100644 --- a/lib/zlog.c +++ b/lib/zlog.c @@ -246,10 +246,10 @@ void zlog_tls_buffer_init(void) fchown(mmfd, zlog_uid, zlog_gid); #ifdef HAVE_POSIX_FALLOCATE - if (posix_fallocate(mmfd, 0, TLS_LOG_BUF_SIZE) < 0) { -#else - if (ftruncate(mmfd, TLS_LOG_BUF_SIZE) < 0) { + if (posix_fallocate(mmfd, 0, TLS_LOG_BUF_SIZE) != 0) + /* note next statement is under above if() */ #endif + if (ftruncate(mmfd, TLS_LOG_BUF_SIZE) < 0) { zlog_err("failed to allocate thread log buffer \"%s\": %s", mmpath, strerror(errno)); goto out_anon_unlink; |
