diff options
317 files changed, 13223 insertions, 4450 deletions
diff --git a/babeld/babel_interface.c b/babeld/babel_interface.c index 772aec1234..1702d9277c 100644 --- a/babeld/babel_interface.c +++ b/babeld/babel_interface.c @@ -692,8 +692,7 @@ interface_recalculate(struct interface *ifp) rc = resize_receive_buffer(mtu); if(rc < 0) - zlog_warn("couldn't resize " - "receive buffer for interface %s (%d) (%d bytes).\n", + zlog_warn("couldn't resize receive buffer for interface %s (%d) (%d bytes).\n", ifp->name, ifp->ifindex, mtu); memset(&mreq, 0, sizeof(mreq)); @@ -896,8 +895,7 @@ static void show_babel_neighbour_sub (struct vty *vty, struct neighbour *neigh) { vty_out (vty, - "Neighbour %s dev %s reach %04x rxcost %d txcost %d " - "rtt %s rttcost %d%s.\n", + "Neighbour %s dev %s reach %04x rxcost %d txcost %d rtt %s rttcost %d%s.\n", format_address(neigh->address), neigh->ifp->name, neigh->reach, @@ -988,8 +986,7 @@ show_babel_routes_sub(struct babel_route *route, struct vty *vty, } vty_out (vty, - "%s metric %d refmetric %d id %s seqno %d%s age %d " - "via %s neigh %s%s%s%s\n", + "%s metric %d refmetric %d id %s seqno %d%s age %d via %s neigh %s%s%s%s\n", format_prefix(route->src->prefix, route->src->plen), route_metric(route), route->refmetric, format_eui64(route->src->id), diff --git a/babeld/message.c b/babeld/message.c index d88790824c..c9a10cb1c0 100644 --- a/babeld/message.c +++ b/babeld/message.c @@ -710,8 +710,7 @@ fill_rtt_message(struct interface *ifp) DO_HTONL(babel_ifp->sendbuf + babel_ifp->buffered_hello + 10, time); return 1; } else { - flog_err(EC_BABEL_PACKET, "No space left for timestamp sub-TLV " - "(this shouldn't happen)"); + flog_err(EC_BABEL_PACKET, "No space left for timestamp sub-TLV (this shouldn't happen)"); return -1; } } diff --git a/babeld/route.c b/babeld/route.c index ab104aa2b1..0f6f6486f2 100644 --- a/babeld/route.c +++ b/babeld/route.c @@ -399,16 +399,14 @@ install_route(struct babel_route *route) return; if(!route_feasible(route)) - flog_err(EC_BABEL_ROUTE, "WARNING: installing unfeasible route " - "(this shouldn't happen)."); + flog_err(EC_BABEL_ROUTE, "WARNING: installing unfeasible route (this shouldn't happen)."); i = find_route_slot(route->src->prefix, route->src->plen, NULL); assert(i >= 0 && i < route_slots); if(routes[i] != route && routes[i]->installed) { flog_err(EC_BABEL_ROUTE, - "WARNING: attempting to install duplicate route " - "(this shouldn't happen)."); + "WARNING: attempting to install duplicate route (this shouldn't happen)."); return; } @@ -465,8 +463,7 @@ switch_routes(struct babel_route *old, struct babel_route *new) return; if(!route_feasible(new)) - flog_err(EC_BABEL_ROUTE, "WARNING: switching to unfeasible route " - "(this shouldn't happen)."); + flog_err(EC_BABEL_ROUTE, "WARNING: switching to unfeasible route (this shouldn't happen)."); rc = kernel_route(ROUTE_MODIFY, old->src->prefix, old->src->plen, old->nexthop, old->neigh->ifp->ifindex, @@ -835,8 +832,7 @@ update_route(const unsigned char *router_id, in a timely manner. If the source remains the same, we ignore the update. */ if(!feasible && route->installed) { - debugf(BABEL_DEBUG_COMMON,"Unfeasible update for installed route to %s " - "(%s %d %d -> %s %d %d).", + debugf(BABEL_DEBUG_COMMON,"Unfeasible update for installed route to %s (%s %d %d -> %s %d %d).", format_prefix(src->prefix, src->plen), format_eui64(route->src->id), route->seqno, route->refmetric, diff --git a/bfdd/bfd.c b/bfdd/bfd.c index 7d6f4c1431..caa80ed51d 100644 --- a/bfdd/bfd.c +++ b/bfdd/bfd.c @@ -924,8 +924,7 @@ int ptm_bfd_sess_del(struct bfd_peer_cfg *bpc) /* This pointer is being referenced, don't let it be deleted. */ if (bs->refcount > 0) { - zlog_err("session-delete: refcount failure: %" PRIu64 - " references", + zlog_err("session-delete: refcount failure: %" PRIu64" references", bs->refcount); return -1; } @@ -1693,8 +1692,7 @@ struct bfd_session *bfd_key_lookup(struct bfd_key key) inet_ntop(bs.key.family, &bs.key.local, addr_buf, sizeof(addr_buf)); zlog_debug( - " peer %s found, but ifp %s" - " and loc-addr %s ignored", + " peer %s found, but ifp %s and loc-addr %s ignored", peer_buf, key.ifname, addr_buf); } return bsp; @@ -1716,8 +1714,7 @@ struct bfd_session *bfd_key_lookup(struct bfd_key key) bsp = ctx.result; if (bglobal.debug_peer_event) zlog_debug( - " peer %s found, but ifp" - " and/or loc-addr params ignored", + " peer %s found, but ifp and/or loc-addr params ignored", peer_buf); } return bsp; diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c index 166997e674..28c6cbee26 100644 --- a/bfdd/bfdd_cli.c +++ b/bfdd/bfdd_cli.c @@ -312,7 +312,7 @@ void bfd_cli_show_rx(struct vty *vty, struct lyd_node *dnode, BFD_DEFREQUIREDMINRX); else { value = yang_dnode_get_uint32(dnode, NULL); - vty_out(vty, " receive-interval %" PRIu32 "\n", value / 1000); + vty_out(vty, " receive-interval %u\n", value / 1000); } } @@ -341,7 +341,7 @@ void bfd_cli_show_tx(struct vty *vty, struct lyd_node *dnode, BFD_DEFDESIREDMINTX); else { value = yang_dnode_get_uint32(dnode, NULL); - vty_out(vty, " transmit-interval %" PRIu32 "\n", value / 1000); + vty_out(vty, " transmit-interval %u\n", value / 1000); } } @@ -391,7 +391,7 @@ void bfd_cli_show_echo_interval(struct vty *vty, struct lyd_node *dnode, BFD_DEF_REQ_MIN_ECHO); else { value = yang_dnode_get_uint32(dnode, NULL); - vty_out(vty, " echo-interval %" PRIu32 "\n", value / 1000); + vty_out(vty, " echo-interval %u\n", value / 1000); } } diff --git a/bfdd/bfdd_nb_config.c b/bfdd/bfdd_nb_config.c index de11997d1a..970b5f2d65 100644 --- a/bfdd/bfdd_nb_config.c +++ b/bfdd/bfdd_nb_config.c @@ -85,8 +85,7 @@ static int bfd_session_create(enum nb_event event, const struct lyd_node *dnode, if (p.family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6) && strlen(ifname) == 0) { zlog_warn( - "%s: when using link-local you must specify " - "an interface.", + "%s: when using link-local you must specify an interface.", __func__); return NB_ERR_VALIDATION; } @@ -257,6 +256,7 @@ int bfdd_bfd_profile_detection_multiplier_modify(struct nb_cb_modify_args *args) bp = nb_running_get_entry(args->dnode, NULL, true); bp->detection_multiplier = yang_dnode_get_uint8(args->dnode, NULL); + bfd_profile_update(bp); return NB_OK; } diff --git a/bfdd/bfdd_vty.c b/bfdd/bfdd_vty.c index f22e9277a1..8318ea9665 100644 --- a/bfdd/bfdd_vty.c +++ b/bfdd/bfdd_vty.c @@ -146,23 +146,23 @@ static void _display_peer(struct vty *vty, struct bfd_session *bs) CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG) ? "configured" : "dynamic"); vty_out(vty, "\t\tLocal timers:\n"); - vty_out(vty, "\t\t\tDetect-multiplier: %" PRIu32 "\n", + vty_out(vty, "\t\t\tDetect-multiplier: %u\n", bs->detect_mult); - vty_out(vty, "\t\t\tReceive interval: %" PRIu32 "ms\n", + vty_out(vty, "\t\t\tReceive interval: %ums\n", bs->timers.required_min_rx / 1000); - vty_out(vty, "\t\t\tTransmission interval: %" PRIu32 "ms\n", + vty_out(vty, "\t\t\tTransmission interval: %ums\n", bs->timers.desired_min_tx / 1000); - vty_out(vty, "\t\t\tEcho transmission interval: %" PRIu32 "ms\n", + vty_out(vty, "\t\t\tEcho transmission interval: %ums\n", bs->timers.required_min_echo / 1000); vty_out(vty, "\t\tRemote timers:\n"); - vty_out(vty, "\t\t\tDetect-multiplier: %" PRIu32 "\n", + vty_out(vty, "\t\t\tDetect-multiplier: %u\n", bs->remote_detect_mult); - vty_out(vty, "\t\t\tReceive interval: %" PRIu32 "ms\n", + vty_out(vty, "\t\t\tReceive interval: %ums\n", bs->remote_timers.required_min_rx / 1000); - vty_out(vty, "\t\t\tTransmission interval: %" PRIu32 "ms\n", + vty_out(vty, "\t\t\tTransmission interval: %ums\n", bs->remote_timers.desired_min_tx / 1000); - vty_out(vty, "\t\t\tEcho transmission interval: %" PRIu32 "ms\n", + vty_out(vty, "\t\t\tEcho transmission interval: %ums\n", bs->remote_timers.required_min_echo / 1000); vty_out(vty, "\n"); diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c index 1a23a690e0..8134807a14 100644 --- a/bfdd/ptm_adapter.c +++ b/bfdd/ptm_adapter.c @@ -152,8 +152,7 @@ static void _ptm_bfd_session_del(struct bfd_session *bs, uint8_t diag) */ if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG)) { zlog_err( - "ptm-del-session: [%s] session refcount is " - "zero but it was configured by CLI", + "ptm-del-session: [%s] session refcount is zero but it was configured by CLI", bs_to_string(bs)); } else { control_notify_config(BCM_NOTIFY_CONFIG_DELETE, bs); diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index 44962f5af3..5cf3c60fa2 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -1723,8 +1723,7 @@ struct aspath *aspath_reconcile_as4(struct aspath *aspath, if (hops < seg->length) { if (BGP_DEBUG(as4, AS4)) zlog_debug( - "[AS4] AS4PATHmangle: AS_CONFED_SEQUENCE falls" - " across 2/4 ASN boundary somewhere, broken.."); + "[AS4] AS4PATHmangle: AS_CONFED_SEQUENCE falls across 2/4 ASN boundary somewhere, broken.."); hops = seg->length; } /* fallthru */ diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index d8566fed9f..08e50fc4f2 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -765,8 +765,7 @@ static void attr_show_all_iterator(struct hash_bucket *bucket, struct vty *vty) inet_ntop(AF_INET6, &attr->srv6_vpn->sid, sid_str, BUFSIZ); vty_out(vty, - "\tflags: %" PRIu64 - " med: %u local_pref: %u origin: %u weight: %u label: %u sid: %s\n", + "\tflags: %" PRIu64" med: %u local_pref: %u origin: %u weight: %u label: %u sid: %s\n", attr->flag, attr->med, attr->local_pref, attr->origin, attr->weight, attr->label, sid_str); } @@ -1244,8 +1243,7 @@ bgp_attr_flags_diagnose(struct bgp_attr_parser_args *args, } if (!seen) { zlog_debug( - "Strange, %s called for attr %s, but no problem found with flags" - " (real flags 0x%x, desired 0x%x)", + "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)", __func__, lookup_msg(attr_str, attr_code, NULL), real_flags, desired_flags); } @@ -1311,16 +1309,14 @@ static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args *args) if (CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL)) { if (!CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)) { flog_err(EC_BGP_ATTR_FLAG, - "%s well-known attribute " - "must NOT have the partial flag set (%x)", + "%s well-known attribute must NOT have the partial flag set (%x)", lookup_msg(attr_str, attr_code, NULL), flags); return true; } if (CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL) && !CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS)) { flog_err(EC_BGP_ATTR_FLAG, - "%s optional + transitive attribute " - "must NOT have the partial flag set (%x)", + "%s optional + transitive attribute must NOT have the partial flag set (%x)", lookup_msg(attr_str, attr_code, NULL), flags); return true; } @@ -1773,10 +1769,7 @@ bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr, /* ignore */ if (BGP_DEBUG(as4, AS4)) zlog_debug( - "[AS4] %s BGP not AS4 capable peer" - " send AGGREGATOR != AS_TRANS and" - " AS4_AGGREGATOR, so ignore" - " AS4_AGGREGATOR and AS4_PATH", + "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH", peer->host); ignore_as4_path = 1; } else { @@ -1794,9 +1787,7 @@ bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr, */ if (BGP_DEBUG(as4, AS4)) zlog_debug( - "[AS4] %s BGP not AS4 capable peer send" - " AS4_AGGREGATOR but no AGGREGATOR, will take" - " it as if AGGREGATOR with AS_TRANS had been there", + "[AS4] %s BGP not AS4 capable peer send AS4_AGGREGATOR but no AGGREGATOR, will take it as if AGGREGATOR with AS_TRANS had been there", peer->host); attr->aggregator_as = as4_aggregator; /* sweep it under the carpet and simulate a "good" @@ -2407,8 +2398,7 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length, if (STREAM_READABLE(peer->curr) < length || length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH) { flog_err(EC_BGP_ATTR_LEN, - "Prefix SID label index length is %" PRIu16 - " instead of %u", + "Prefix SID label index length is %hu instead of %u", length, BGP_PREFIX_SID_LABEL_INDEX_LENGTH); return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, @@ -2435,8 +2425,7 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length, if (STREAM_READABLE(peer->curr) < length || length != BGP_PREFIX_SID_IPV6_LENGTH) { flog_err(EC_BGP_ATTR_LEN, - "Prefix SID IPv6 length is %" PRIu16 - " instead of %u", + "Prefix SID IPv6 length is %hu instead of %u", length, BGP_PREFIX_SID_IPV6_LENGTH); return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, @@ -2468,7 +2457,7 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length, if (length < (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH)) { flog_err( EC_BGP_ATTR_LEN, - "Prefix SID Originator SRGB length field claims length of %" PRIu16 " bytes, but the minimum for this TLV type is %u", + "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u", length, 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH); return bgp_attr_malformed( @@ -2482,7 +2471,7 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length, */ if (STREAM_READABLE(peer->curr) < length) { flog_err(EC_BGP_ATTR_LEN, - "Prefix SID Originator SRGB specifies length %" PRIu16 ", but only %zu bytes remain", + "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain", length, STREAM_READABLE(peer->curr)); return bgp_attr_malformed( args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, @@ -2499,7 +2488,7 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length, if (length % BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH) { flog_err( EC_BGP_ATTR_LEN, - "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %" PRIu16 "bytes, but it must be a multiple of %u", + "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u", length, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH); return bgp_attr_malformed( args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, @@ -2519,8 +2508,7 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length, if (STREAM_READABLE(peer->curr) < length || length != BGP_PREFIX_SID_VPN_SID_LENGTH) { flog_err(EC_BGP_ATTR_LEN, - "Prefix SID VPN SID length is %" PRIu16 - " instead of %u", + "Prefix SID VPN SID length is %hu instead of %u", length, BGP_PREFIX_SID_VPN_SID_LENGTH); return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, @@ -2560,8 +2548,7 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length, if (STREAM_READABLE(peer->curr) < length || length != BGP_PREFIX_SID_SRV6_L3_SERVICE_LENGTH) { flog_err(EC_BGP_ATTR_LEN, - "Prefix SID SRv6 L3-Service length is %" PRIu16 - " instead of %u", + "Prefix SID SRv6 L3-Service length is %hu instead of %u", length, BGP_PREFIX_SID_SRV6_L3_SERVICE_LENGTH); return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, @@ -2604,8 +2591,7 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length, if (STREAM_READABLE(peer->curr) < length) { flog_err( EC_BGP_ATTR_LEN, - "Prefix SID SRv6 length is %" PRIu16 - " - too long, only %zu remaining in this UPDATE", + "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE", length, STREAM_READABLE(peer->curr)); return bgp_attr_malformed( args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, @@ -2658,8 +2644,7 @@ bgp_attr_parse_ret_t bgp_attr_prefix_sid(struct bgp_attr_parser_args *args) if (STREAM_READABLE(peer->curr) < length) { flog_err( EC_BGP_ATTR_LEN, - "Malformed Prefix SID attribute - insufficient data (need %" PRIu16 - " for attribute body, have %zu remaining in UPDATE)", + "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)", length, STREAM_READABLE(peer->curr)); return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, @@ -2676,8 +2661,7 @@ bgp_attr_parse_ret_t bgp_attr_prefix_sid(struct bgp_attr_parser_args *args) if (psid_parsed_length > args->length) { flog_err( EC_BGP_ATTR_LEN, - "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu" - " for TLV length, have %zu overflowed in UPDATE)", + "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)", length + headersz, psid_parsed_length - (length + headersz)); return bgp_attr_malformed( args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index 54970af67b..67b8018c8e 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -351,8 +351,7 @@ static void bgp_bfd_peer_status_update(struct peer *peer, int status, if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_MODE) && CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE) && !remote_cbit) { - zlog_info("%s BFD DOWN message ignored in the process" - " of graceful restart when C bit is cleared", + zlog_info("%s BFD DOWN message ignored in the process of graceful restart when C bit is cleared", peer->host); return; } @@ -487,7 +486,7 @@ static int bgp_bfd_peer_param_set(struct peer *peer, uint32_t min_rx, int command = 0; bfd_set_param((struct bfd_info **)&(peer->bfd_info), min_rx, min_tx, - detect_mult, defaults, &command); + detect_mult, NULL, defaults, &command); /* This command overrides profile if it was previously applied. */ bi = peer->bfd_info; @@ -498,8 +497,8 @@ static int bgp_bfd_peer_param_set(struct peer *peer, uint32_t min_rx, for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { command = 0; bfd_set_param((struct bfd_info **)&(peer->bfd_info), - min_rx, min_tx, detect_mult, defaults, - &command); + min_rx, min_tx, detect_mult, NULL, + defaults, &command); /* * This command overrides profile if it was previously @@ -565,7 +564,7 @@ static int bgp_bfd_peer_param_type_set(struct peer *peer, if (!peer->bfd_info) bfd_set_param((struct bfd_info **)&(peer->bfd_info), BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, - BFD_DEF_DETECT_MULT, 1, &command); + BFD_DEF_DETECT_MULT, NULL, 1, &command); bfd_info = (struct bfd_info *)peer->bfd_info; bfd_info->type = type; @@ -578,7 +577,7 @@ static int bgp_bfd_peer_param_type_set(struct peer *peer, bfd_set_param( (struct bfd_info **)&(peer->bfd_info), BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, - BFD_DEF_DETECT_MULT, 1, &command); + BFD_DEF_DETECT_MULT, NULL, 1, &command); bfd_info = (struct bfd_info *)peer->bfd_info; bfd_info->type = type; @@ -613,7 +612,7 @@ static int bgp_bfd_peer_set_profile(struct peer *peer, const char *profile) struct bfd_info *bfd_info; bfd_set_param((struct bfd_info **)&(peer->bfd_info), BFD_DEF_MIN_RX, - BFD_DEF_MIN_TX, BFD_DEF_DETECT_MULT, 1, &command); + BFD_DEF_MIN_TX, BFD_DEF_DETECT_MULT, NULL, 1, &command); bfd_info = (struct bfd_info *)peer->bfd_info; @@ -629,7 +628,7 @@ static int bgp_bfd_peer_set_profile(struct peer *peer, const char *profile) command = 0; bfd_set_param((struct bfd_info **)&(peer->bfd_info), BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, - BFD_DEF_DETECT_MULT, 1, &command); + BFD_DEF_DETECT_MULT, NULL, 1, &command); bfd_info = (struct bfd_info *)peer->bfd_info; diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c index f1ad6a1e75..af88547ca9 100644 --- a/bgpd/bgp_bmp.c +++ b/bgpd/bgp_bmp.c @@ -951,8 +951,11 @@ afibreak: /* initialize syncrdpos to the first * mid-layer table entry */ - if (!bmp->syncrdpos) + if (!bmp->syncrdpos) { bmp->syncrdpos = bgp_table_top(table); + if (!bmp->syncrdpos) + goto eor; + } /* look for a valid mid-layer table */ do { @@ -1942,9 +1945,7 @@ DEFPY(no_bmp_listener_main, DEFPY(bmp_connect, bmp_connect_cmd, - "[no] bmp connect HOSTNAME port (1-65535) " - "{min-retry (100-86400000)" - "|max-retry (100-86400000)}", + "[no] bmp connect HOSTNAME port (1-65535) {min-retry (100-86400000)|max-retry (100-86400000)}", NO_STR BMP_STR "Actively establish connection to monitoring station\n" diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c index 97d625493f..565d0b8e19 100644 --- a/bgpd/bgp_damp.c +++ b/bgpd/bgp_damp.c @@ -50,6 +50,12 @@ static int bgp_reuse_index(int penalty, struct bgp_damp_config *bdc) unsigned int i; int index; + /* + * reuse_limit can't be zero, this is for Coverity + * to bypass division by zero test. + */ + assert(bdc->reuse_limit); + i = (int)(((double)penalty / bdc->reuse_limit - 1.0) * bdc->scale_factor); diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index 2ca9e5ee13..9f32d450b9 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -2144,7 +2144,7 @@ DEFUN_NOSH (show_debugging_bgp, bgp_debug_zebra_prefixes); if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) - vty_out(vty, " BGP graceful-restart debugging is on"); + vty_out(vty, " BGP graceful-restart debugging is on\n"); if (BGP_DEBUG(allow_martians, ALLOW_MARTIANS)) vty_out(vty, " BGP allow martian next hop debugging is on\n"); diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index 7d5cac4d62..d6c311bfa0 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -676,13 +676,10 @@ static int ecommunity_lb_str(char *buf, size_t bufsz, const uint8_t *pnt) are three types of format. route-map set extcommunity format - "rt 100:1 100:2" - "soo 100:3" + "rt 100:1 100:2soo 100:3" extcommunity-list - "rt 100:1 rt 100:2 soo 100:3" - - "show [ip] bgp" and extcommunity-list regular expression matching + "rt 100:1 rt 100:2 soo 100:3show [ip] bgp" and extcommunity-list regular expression matching "RT:100:1 RT:100:2 SoO:100:3" For each formath please use below definition for format: diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 1a0e5c0cd3..2584939378 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -345,8 +345,7 @@ static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp, vty_out(vty, "BGP table version is %" PRIu64 ", local router ID is %s\n", tbl_ver, inet_ntoa(bgp->router_id)); vty_out(vty, - "Status codes: s suppressed, d damped, h history, " - "* valid, > best, i - internal\n"); + "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n"); vty_out(vty, "Origin codes: i - IGP, e - EGP, ? - incomplete\n"); vty_out(vty, "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n"); @@ -680,7 +679,8 @@ static void show_esi_routes(struct bgp *bgp, if (json) json_path = json_object_new_array(); - route_vty_out(vty, p, pi, 0, SAFI_EVPN, json_path); + route_vty_out(vty, p, pi, 0, SAFI_EVPN, json_path, + false); if (json) json_object_array_add(json_paths, json_path); @@ -789,7 +789,7 @@ static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type, json_path); else route_vty_out(vty, p, pi, 0, SAFI_EVPN, - json_path); + json_path, false); if (json) json_object_array_add(json_paths, json_path); @@ -1315,7 +1315,7 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd, route_vty_out(vty, bgp_dest_get_prefix(rm), pi, no_display, SAFI_EVPN, - json_array); + json_array, false); no_display = 1; } @@ -2814,7 +2814,7 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type, SAFI_EVPN, json_path); } else route_vty_out(vty, p, pi, 0, SAFI_EVPN, - json_path); + json_path, false); if (json) json_object_array_add(json_paths, @@ -3899,6 +3899,12 @@ DEFPY (bgp_evpn_advertise_pip_ip_mac, struct listnode *node = NULL; struct bgpevpn *vpn = NULL; + /* + * At this point if bgp_evpn is NULL and evpn is enabled + * something stupid has gone wrong + */ + assert(bgp_evpn); + update_advertise_vrf_routes(bgp_vrf); /* Update (svi) type-2 routes */ diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c index 64a6c2ea8f..e309fa948e 100644 --- a/bgpd/bgp_flowspec_vty.c +++ b/bgpd/bgp_flowspec_vty.c @@ -376,11 +376,10 @@ void route_vty_out_flowspec(struct vty *vty, const struct prefix *p, bpr->priority, bpr->action->table_id); } - if (list_began) - vty_out(vty, ")"); - vty_out(vty, "\n"); } - if (!list_began) + if (list_began) + vty_out(vty, ")\n"); + else vty_out(vty, "\tnot installed in PBR\n"); } } diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index e78682a3bb..e133cde6a5 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -1553,8 +1553,7 @@ int bgp_start(struct peer *peer) if (BGP_PEER_START_SUPPRESSED(peer)) { if (bgp_debug_neighbor_events(peer)) flog_err(EC_BGP_FSM, - "%s [FSM] Trying to start suppressed peer" - " - this is never supposed to happen!", + "%s [FSM] Trying to start suppressed peer - this is never supposed to happen!", peer->host); if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) peer->last_reset = PEER_DOWN_USER_SHUTDOWN; @@ -2285,8 +2284,7 @@ int bgp_event_update(struct peer *peer, enum bgp_fsm_events event) if (!dyn_nbr && !passive_conn && peer->bgp) { flog_err( EC_BGP_FSM, - "%s [FSM] Failure handling event %s in state %s, " - "prior events %s, %s, fd %d", + "%s [FSM] Failure handling event %s in state %s, prior events %s, %s, fd %d", peer->host, bgp_event_str[peer->cur_event], lookup_msg(bgp_status_msg, peer->status, NULL), bgp_event_str[peer->last_event], diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c index 4121a8e4b7..fba954c432 100644 --- a/bgpd/bgp_label.c +++ b/bgpd/bgp_label.c @@ -394,8 +394,7 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr, /* There needs to be at least one label */ if (prefixlen < 24) { flog_err(EC_BGP_UPDATE_RCV, - "%s [Error] Update packet error" - " (wrong label length %d)", + "%s [Error] Update packet error (wrong label length %d)", peer->host, prefixlen); bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_INVAL_NETWORK); diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 33eaf9ae74..b082aa9c6a 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -133,19 +133,20 @@ void sighup(void) /* * This is turned off for the moment. There is all * sorts of config turned off by bgp_terminate - * that is not setup properly again in bgp_rest. + * that is not setup properly again in bgp_reset. * I see no easy way to do this nor do I see that * this is a desirable way to reload config * given the yang work. */ /* Terminate all thread. */ - bgp_terminate(); - bgp_reset(); - zlog_info("bgpd restarting!"); - - /* Reload config file. */ - vty_read_config(NULL, bgpd_di.config_file, config_default); + /* + * bgp_terminate(); + * bgp_reset(); + * zlog_info("bgpd restarting!"); + * Reload config file. + * vty_read_config(NULL, bgpd_di.config_file, config_default); + */ /* Try to return to normal operation. */ } diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c index 5dd1cf6de8..b7f516eaf7 100644 --- a/bgpd/bgp_mpath.c +++ b/bgpd/bgp_mpath.c @@ -739,8 +739,7 @@ void bgp_path_info_mpath_update(struct bgp_dest *dest, if (debug) zlog_debug( - "%pRN: New mpath count (incl newbest) %d mpath-change %s" - " all_paths_lb %d cum_bw u%" PRIu64, + "%pRN: New mpath count (incl newbest) %d mpath-change %s all_paths_lb %d cum_bw u%" PRIu64, bgp_dest_to_rnode(dest), mpath_count, mpath_changed ? "YES" : "NO", all_paths_lb, cum_bw); diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 86b1b3e3ac..314337d194 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -274,8 +274,7 @@ void vpn_leak_zebra_vrf_label_update(struct bgp *bgp, afi_t afi) if (bgp->vrf_id == VRF_UNKNOWN) { if (debug) { zlog_debug( - "%s: vrf %s: afi %s: vrf_id not set, " - "can't set zebra vrf label", + "%s: vrf %s: afi %s: vrf_id not set, can't set zebra vrf label", __func__, bgp->name_pretty, afi2str(afi)); } return; diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 00cc1f67a1..06aec9412c 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -501,8 +501,7 @@ static int bgp_accept(struct thread *thread) if (BGP_PEER_START_SUPPRESSED(peer1)) { if (bgp_debug_neighbor_events(peer1)) zlog_debug( - "[Event] Incoming BGP connection rejected from %s " - "due to maximum-prefix or shutdown", + "[Event] Incoming BGP connection rejected from %s due to maximum-prefix or shutdown", peer1->host); close(bgp_sock); return -1; @@ -518,8 +517,7 @@ static int bgp_accept(struct thread *thread) */ if (bgp_debug_neighbor_events(peer1)) zlog_debug( - "[Event] New active connection from peer %s, Killing" - " previous active connection", + "[Event] New active connection from peer %s, Killing previous active connection", peer1->host); peer_delete(peer1->doppelganger); } diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 4a2f7d5882..732c8e6753 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -332,8 +332,7 @@ static int bgp_capability_orf_entry(struct peer *peer, /* Convert AFI, SAFI to internal values, check. */ if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) { zlog_info( - "%s Addr-family %d/%d not supported." - " Ignoring the ORF capability", + "%s Addr-family %d/%d not supported. Ignoring the ORF capability", peer->host, pkt_afi, pkt_safi); return 0; } @@ -344,8 +343,7 @@ static int bgp_capability_orf_entry(struct peer *peer, /* validate number field */ if (CAPABILITY_CODE_ORF_LEN + (num * 2) > hdr->length) { zlog_info( - "%s ORF Capability entry length error," - " Cap length %u, num %u", + "%s ORF Capability entry length error, Cap length %u, num %u", peer->host, hdr->length, num); bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); @@ -407,8 +405,7 @@ static int bgp_capability_orf_entry(struct peer *peer, if (bgp_debug_neighbor_events(peer)) zlog_debug( - "%s OPEN has %s ORF capability" - " as %s for afi/safi: %s/%s", + "%s OPEN has %s ORF capability as %s for afi/safi: %s/%s", peer->host, lookup_msg(orf_type_str, type, NULL), lookup_msg(orf_mode_str, mode, NULL), @@ -490,15 +487,13 @@ static int bgp_capability_restart(struct peer *peer, if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) { if (bgp_debug_neighbor_events(peer)) zlog_debug( - "%s Addr-family %s/%s(afi/safi) not supported." - " Ignore the Graceful Restart capability for this AFI/SAFI", + "%s Addr-family %s/%s(afi/safi) not supported. Ignore the Graceful Restart capability for this AFI/SAFI", peer->host, iana_afi2str(pkt_afi), iana_safi2str(pkt_safi)); } else if (!peer->afc[afi][safi]) { if (bgp_debug_neighbor_events(peer)) zlog_debug( - "%s Addr-family %s/%s(afi/safi) not enabled." - " Ignore the Graceful Restart capability", + "%s Addr-family %s/%s(afi/safi) not enabled. Ignore the Graceful Restart capability", peer->host, iana_afi2str(pkt_afi), iana_safi2str(pkt_safi)); } else { @@ -581,16 +576,14 @@ static int bgp_capability_addpath(struct peer *peer, if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) { if (bgp_debug_neighbor_events(peer)) zlog_debug( - "%s Addr-family %s/%s(afi/safi) not supported." - " Ignore the Addpath Attribute for this AFI/SAFI", + "%s Addr-family %s/%s(afi/safi) not supported. Ignore the Addpath Attribute for this AFI/SAFI", peer->host, iana_afi2str(pkt_afi), iana_safi2str(pkt_safi)); continue; } else if (!peer->afc[afi][safi]) { if (bgp_debug_neighbor_events(peer)) zlog_debug( - "%s Addr-family %s/%s(afi/safi) not enabled." - " Ignore the AddPath capability for this AFI/SAFI", + "%s Addr-family %s/%s(afi/safi) not enabled. Ignore the AddPath capability for this AFI/SAFI", peer->host, iana_afi2str(pkt_afi), iana_safi2str(pkt_safi)); continue; @@ -640,8 +633,7 @@ static int bgp_capability_enhe(struct peer *peer, struct capability_header *hdr) if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) { if (bgp_debug_neighbor_events(peer)) zlog_debug( - "%s Addr-family %s/%s(afi/safi) not supported." - " Ignore the ENHE Attribute for this AFI/SAFI", + "%s Addr-family %s/%s(afi/safi) not supported. Ignore the ENHE Attribute for this AFI/SAFI", peer->host, iana_afi2str(pkt_afi), iana_safi2str(pkt_safi)); continue; @@ -662,8 +654,7 @@ static int bgp_capability_enhe(struct peer *peer, struct capability_header *hdr) || safi == SAFI_LABELED_UNICAST)) { flog_warn( EC_BGP_CAPABILITY_INVALID_DATA, - "%s Unexpected afi/safi/next-hop afi: %s/%s/%u " - "in Extended Next-hop capability, ignoring", + "%s Unexpected afi/safi/next-hop afi: %s/%s/%u in Extended Next-hop capability, ignoring", peer->host, iana_afi2str(pkt_afi), iana_safi2str(pkt_safi), pkt_nh_afi); continue; @@ -875,8 +866,7 @@ static int bgp_capability_parse(struct peer *peer, size_t length, /* Check length. */ if (caphdr.length < cap_minsizes[caphdr.code]) { zlog_info( - "%s %s Capability length error: got %u," - " expected at least %u", + "%s %s Capability length error: got %u, expected at least %u", peer->host, lookup_msg(capcode_str, caphdr.code, NULL), @@ -889,8 +879,7 @@ static int bgp_capability_parse(struct peer *peer, size_t length, if (caphdr.length && caphdr.length % cap_modsizes[caphdr.code] != 0) { zlog_info( - "%s %s Capability length error: got %u," - " expected a multiple of %u", + "%s %s Capability length error: got %u, expected a multiple of %u", peer->host, lookup_msg(capcode_str, caphdr.code, NULL), @@ -1036,8 +1025,7 @@ as_t peek_for_as4_capability(struct peer *peer, uint8_t length) if (BGP_DEBUG(as4, AS4)) zlog_debug( - "%s [AS4] rcv OPEN w/ OPTION parameter len: %u," - " peeking for as4", + "%s [AS4] rcv OPEN w/ OPTION parameter len: %u, peeking for as4", peer->host, length); /* the error cases we DONT handle, we ONLY try to read as4 out of * correctly formatted options. @@ -1211,8 +1199,7 @@ int bgp_open_option_parse(struct peer *peer, uint8_t length, int *mp_capability) && !peer->afc_nego[AFI_IP6][SAFI_FLOWSPEC] && !peer->afc_nego[AFI_L2VPN][SAFI_EVPN]) { flog_err(EC_BGP_PKT_OPEN, - "%s [Error] Configured AFI/SAFIs do not " - "overlap with received MP capabilities", + "%s [Error] Configured AFI/SAFIs do not overlap with received MP capabilities", peer->host); if (error != error_data) diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 29c03f4014..7692a200ee 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -408,6 +408,9 @@ int bgp_generate_updgrp_packets(struct thread *thread) if (peer->bgp->main_peers_update_hold) return 0; + if (peer->t_routeadv) + return 0; + do { s = NULL; FOREACH_AFI_SAFI (afi, safi) { @@ -1110,8 +1113,7 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size) /* Receive OPEN message log */ if (bgp_debug_neighbor_events(peer)) zlog_debug( - "%s rcv OPEN, version %d, remote-as (in open) %u," - " holdtime %d, id %s", + "%s rcv OPEN, version %d, remote-as (in open) %u, holdtime %d, id %s", peer->host, version, remote_as, holdtime, inet_ntoa(remote_id)); @@ -1177,13 +1179,11 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size) if (!as4 && BGP_DEBUG(as4, AS4)) zlog_debug( - "%s [AS4] OPEN remote_as is AS_TRANS, but no AS4." - " Odd, but proceeding.", + "%s [AS4] OPEN remote_as is AS_TRANS, but no AS4. Odd, but proceeding.", peer->host); else if (as4 < BGP_AS_MAX && BGP_DEBUG(as4, AS4)) zlog_debug( - "%s [AS4] OPEN remote_as is AS_TRANS, but AS4 (%u) fits " - "in 2-bytes, very odd peer.", + "%s [AS4] OPEN remote_as is AS_TRANS, but AS4 (%u) fits in 2-bytes, very odd peer.", peer->host, as4); if (as4) remote_as = as4; @@ -1197,8 +1197,7 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size) /* raise error, log this, close session */ flog_err( EC_BGP_PKT_OPEN, - "%s bad OPEN, got AS4 capability, but remote_as %u" - " mismatch with 16bit 'myasn' %u in open", + "%s bad OPEN, got AS4 capability, but remote_as %u mismatch with 16bit 'myasn' %u in open", peer->host, as4, remote_as); bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_BAD_PEER_AS, @@ -1493,8 +1492,7 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size) Subcode is set to Malformed Attribute List. */ if (stream_pnt(s) + 2 > end) { flog_err(EC_BGP_UPDATE_RCV, - "%s [Error] Update packet error" - " (packet length is short for unfeasible length)", + "%s [Error] Update packet error (packet length is short for unfeasible length)", peer->host); bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_MAL_ATTR); @@ -1507,8 +1505,7 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size) /* Unfeasible Route Length check. */ if (stream_pnt(s) + withdraw_len > end) { flog_err(EC_BGP_UPDATE_RCV, - "%s [Error] Update packet error" - " (packet unfeasible length overflow %d)", + "%s [Error] Update packet error (packet unfeasible length overflow %d)", peer->host, withdraw_len); bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_MAL_ATTR); @@ -2063,8 +2060,7 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size) if (!ok || (ok && ret != CMD_SUCCESS)) { zlog_info( - "%s Received misformatted prefixlist ORF." - " Remove All pfxlist", + "%s Received misformatted prefixlist ORF. Remove All pfxlist", peer->host); prefix_bgp_orf_remove_all(afi, name); @@ -2194,8 +2190,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt, &safi)) { if (bgp_debug_neighbor_events(peer)) zlog_debug( - "%s Dynamic Capability MP_EXT afi/safi invalid " - "(%s/%s)", + "%s Dynamic Capability MP_EXT afi/safi invalid (%s/%s)", peer->host, iana_afi2str(pkt_afi), iana_safi2str(pkt_safi)); diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c index 535a45690b..7c3e8cd70e 100644 --- a/bgpd/bgp_pbr.c +++ b/bgpd/bgp_pbr.c @@ -486,8 +486,7 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api) */ if (api->match_protocol_num > 1) { if (BGP_DEBUG(pbr, PBR)) - zlog_debug("BGP: match protocol operations:" - "multiple protocols ( %d). ignoring.", + zlog_debug("BGP: match protocol operations:multiple protocols ( %d). ignoring.", api->match_protocol_num); return 0; } @@ -496,21 +495,18 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api) api->protocol[0].value != PROTOCOL_ICMP && api->protocol[0].value != PROTOCOL_TCP) { if (BGP_DEBUG(pbr, PBR)) - zlog_debug("BGP: match protocol operations:" - "protocol (%d) not supported. ignoring", + zlog_debug("BGP: match protocol operations:protocol (%d) not supported. ignoring", api->match_protocol_num); return 0; } if (!bgp_pbr_extract(api->src_port, api->match_src_port_num, NULL)) { if (BGP_DEBUG(pbr, PBR)) - zlog_debug("BGP: match src port operations:" - "too complex. ignoring."); + zlog_debug("BGP: match src port operations:too complex. ignoring."); return 0; } if (!bgp_pbr_extract(api->dst_port, api->match_dst_port_num, NULL)) { if (BGP_DEBUG(pbr, PBR)) - zlog_debug("BGP: match dst port operations:" - "too complex. ignoring."); + zlog_debug("BGP: match dst port operations:too complex. ignoring."); return 0; } if (!bgp_pbr_extract_enumerate(api->tcpflags, @@ -519,8 +515,7 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api) OPERATOR_UNARY_OR, NULL, FLOWSPEC_TCP_FLAGS)) { if (BGP_DEBUG(pbr, PBR)) - zlog_debug("BGP: match tcp flags:" - "too complex. ignoring."); + zlog_debug("BGP: match tcp flags:too complex. ignoring."); return 0; } if (!bgp_pbr_extract(api->icmp_type, api->match_icmp_type_num, NULL)) { @@ -529,8 +524,7 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api) OPERATOR_UNARY_OR, NULL, FLOWSPEC_ICMP_TYPE)) { if (BGP_DEBUG(pbr, PBR)) - zlog_debug("BGP: match icmp type operations:" - "too complex. ignoring."); + zlog_debug("BGP: match icmp type operations:too complex. ignoring."); return 0; } enumerate_icmp = true; @@ -541,22 +535,18 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api) OPERATOR_UNARY_OR, NULL, FLOWSPEC_ICMP_CODE)) { if (BGP_DEBUG(pbr, PBR)) - zlog_debug("BGP: match icmp code operations:" - "too complex. ignoring."); + zlog_debug("BGP: match icmp code operations:too complex. ignoring."); return 0; } else if (api->match_icmp_type_num > 1 && !enumerate_icmp) { if (BGP_DEBUG(pbr, PBR)) - zlog_debug("BGP: match icmp code is enumerate" - ", and icmp type is not." - " too complex. ignoring."); + zlog_debug("BGP: match icmp code is enumerate, and icmp type is not. too complex. ignoring."); return 0; } } if (!bgp_pbr_extract(api->port, api->match_port_num, NULL)) { if (BGP_DEBUG(pbr, PBR)) - zlog_debug("BGP: match port operations:" - "too complex. ignoring."); + zlog_debug("BGP: match port operations:too complex. ignoring."); return 0; } if (api->match_packet_length_num) { @@ -572,8 +562,7 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api) NULL, FLOWSPEC_PKT_LEN); if (!ret) { if (BGP_DEBUG(pbr, PBR)) - zlog_debug("BGP: match packet length operations:" - "too complex. ignoring."); + zlog_debug("BGP: match packet length operations:too complex. ignoring."); return 0; } } @@ -582,8 +571,7 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api) OPERATOR_UNARY_OR | OPERATOR_UNARY_AND, NULL, FLOWSPEC_DSCP)) { if (BGP_DEBUG(pbr, PBR)) - zlog_debug("BGP: match DSCP operations:" - "too complex. ignoring."); + zlog_debug("BGP: match DSCP operations:too complex. ignoring."); return 0; } } @@ -629,16 +617,14 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api) if (api->match_src_port_num + api->match_dst_port_num + api->match_port_num > 3) { if (BGP_DEBUG(pbr, PBR)) - zlog_debug("BGP: match multiple port operations:" - " too complex. ignoring."); + zlog_debug("BGP: match multiple port operations: too complex. ignoring."); return 0; } if ((api->match_src_port_num || api->match_dst_port_num || api->match_port_num) && (api->match_icmp_type_num || api->match_icmp_code_num)) { if (BGP_DEBUG(pbr, PBR)) - zlog_debug("BGP: match multiple port/imcp operations:" - " too complex. ignoring."); + zlog_debug("BGP: match multiple port/imcp operations: too complex. ignoring."); return 0; } /* iprule only supports redirect IP */ @@ -650,24 +636,21 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api) api->actions[i].u.r.rate == 0) { if (BGP_DEBUG(pbr, PBR)) { bgp_pbr_print_policy_route(api); - zlog_debug("BGP: iprule match actions" - " drop not supported"); + zlog_debug("BGP: iprule match actions drop not supported"); } return 0; } if (api->actions[i].action == ACTION_MARKING) { if (BGP_DEBUG(pbr, PBR)) { bgp_pbr_print_policy_route(api); - zlog_warn("PBR: iprule set DSCP %u" - " not supported", + zlog_warn("PBR: iprule set DSCP %u not supported", api->actions[i].u.marking_dscp); } } if (api->actions[i].action == ACTION_REDIRECT) { if (BGP_DEBUG(pbr, PBR)) { bgp_pbr_print_policy_route(api); - zlog_warn("PBR: iprule redirect VRF %u" - " not supported", + zlog_warn("PBR: iprule redirect VRF %u not supported", api->actions[i].u.redirect_vrf); } } @@ -677,9 +660,7 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api) !(api->match_bitmask & PREFIX_DST_PRESENT)) { if (BGP_DEBUG(pbr, PBR)) { bgp_pbr_print_policy_route(api); - zlog_debug("BGP: match actions without src" - " or dst address can not operate." - " ignoring."); + zlog_debug("BGP: match actions without src or dst address can not operate. ignoring."); } return 0; } @@ -845,8 +826,7 @@ int bgp_pbr_build_and_validate_entry(const struct prefix *p, if (valid_prefix && afi != family2afi(dst->family)) { if (BGP_DEBUG(pbr, PBR)) { bgp_pbr_print_policy_route(api); - zlog_debug("%s: inconsistency:" - " no match for afi src and dst (%u/%u)", + zlog_debug("%s: inconsistency: no match for afi src and dst (%u/%u)", __func__, afi, family2afi(dst->family)); } return -1; @@ -2097,8 +2077,7 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, listnode_lookup_nocheck(extra->bgp_fs_iprule, bpr)) { if (BGP_DEBUG(pbr, PBR_ERROR)) - zlog_err("%s: entry %p/%p already " - "installed in bgp pbr iprule", + zlog_err("%s: entry %p/%p already installed in bgp pbr iprule", __func__, path, bpr); return; } diff --git a/bgpd/bgp_rd.c b/bgpd/bgp_rd.c index e7f1108057..6ba56c7011 100644 --- a/bgpd/bgp_rd.c +++ b/bgpd/bgp_rd.c @@ -174,15 +174,15 @@ char *prefix_rd2str(const struct prefix_rd *prd, char *buf, size_t size) if (type == RD_TYPE_AS) { decode_rd_as(pnt + 2, &rd_as); - snprintf(buf, size, "%u:%" PRIu32, rd_as.as, rd_as.val); + snprintf(buf, size, "%u:%u", rd_as.as, rd_as.val); return buf; } else if (type == RD_TYPE_AS4) { decode_rd_as4(pnt + 2, &rd_as); - snprintf(buf, size, "%u:%" PRIu32, rd_as.as, rd_as.val); + snprintf(buf, size, "%u:%u", rd_as.as, rd_as.val); return buf; } else if (type == RD_TYPE_IP) { decode_rd_ip(pnt + 2, &rd_ip); - snprintf(buf, size, "%s:%" PRIu16, inet_ntoa(rd_ip.ip), + snprintf(buf, size, "%s:%hu", inet_ntoa(rd_ip.ip), rd_ip.val); return buf; } diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 966d9a3385..e8d5b431d6 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1644,8 +1644,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi); if (!bgp_is_valid_label(&label)) { if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) - zlog_debug("u%" PRIu64 ":s%" PRIu64 - " %s/%d is filtered - no label (%p)", + zlog_debug("u%" PRIu64 ":s%" PRIu64" %s/%d is filtered - no label (%p)", subgrp->update_group->id, subgrp->id, inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), @@ -1690,8 +1689,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) { if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) zlog_debug( - "%s [Update:SEND] %s originator-id is same as " - "remote router-id", + "%s [Update:SEND] %s originator-id is same as remote router-id", onlypeer->host, prefix2str(p, buf, sizeof(buf))); return false; @@ -1729,8 +1727,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, && aspath_loop_check(piattr->aspath, onlypeer->as)) { if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) zlog_debug( - "%s [Update:SEND] suppress announcement to peer AS %u " - "that is part of AS path.", + "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.", onlypeer->host, onlypeer->as); return false; } @@ -1740,8 +1737,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, if (aspath_loop_check(piattr->aspath, bgp->confed_id)) { if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) zlog_debug( - "%s [Update:SEND] suppress announcement to peer AS %u" - " is AS path.", + "%s [Update:SEND] suppress announcement to peer AS %u is AS path.", peer->host, bgp->confed_id); return false; } @@ -2994,8 +2990,7 @@ bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi, return false; zlog_info( - "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32 - " exceed, limit %" PRIu32, + "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u", get_afi_safi_str(afi, safi, false), peer->host, peer->pcount[afi][safi], peer->pmax[afi][safi]); SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT); @@ -3056,8 +3051,7 @@ bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi, return false; zlog_info( - "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32 - ", max %" PRIu32, + "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u", get_afi_safi_str(afi, safi, false), peer->host, peer->pcount[afi][safi], peer->pmax[afi][safi]); SET_FLAG(peer->af_sflags[afi][safi], @@ -7413,7 +7407,7 @@ void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type, /* Static function to display route. */ static void route_vty_out_route(const struct prefix *p, struct vty *vty, - json_object *json) + json_object *json, bool wide) { int len = 0; char buf[BUFSIZ]; @@ -7468,7 +7462,7 @@ static void route_vty_out_route(const struct prefix *p, struct vty *vty, } if (!json) { - len = 17 - len; + len = wide ? (45 - len) : (17 - len); if (len < 1) vty_out(vty, "\n%*s", 20, " "); else @@ -7571,7 +7565,7 @@ static char *bgp_nexthop_hostname(struct peer *peer, /* called from terminal list command */ void route_vty_out(struct vty *vty, const struct prefix *p, struct bgp_path_info *path, int display, safi_t safi, - json_object *json_paths) + json_object *json_paths, bool wide) { int len; struct attr *attr = path->attr; @@ -7598,11 +7592,11 @@ void route_vty_out(struct vty *vty, const struct prefix *p, if (!json_paths) { /* print prefix and mask */ if (!display) - route_vty_out_route(p, vty, json_path); + route_vty_out_route(p, vty, json_path, wide); else - vty_out(vty, "%*s", 17, " "); + vty_out(vty, "%*s", (wide ? 45 : 17), " "); } else { - route_vty_out_route(p, vty, json_path); + route_vty_out_route(p, vty, json_path, wide); } /* @@ -7692,7 +7686,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p, else len = vty_out(vty, "%s%s", nexthop, vrf_id_str); - len = 16 - len; + len = wide ? (41 - len) : (16 - len); if (len < 1) vty_out(vty, "\n%*s", 36, " "); else @@ -7722,7 +7716,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p, len = vty_out(vty, "%pI4%s", &attr->nexthop, vrf_id_str); - len = 16 - len; + len = wide ? (41 - len) : (16 - len); if (len < 1) vty_out(vty, "\n%*s", 36, " "); else @@ -7758,7 +7752,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p, &attr->nexthop, vrf_id_str); - len = 16 - len; + len = wide ? (41 - len) : (16 - len); if (len < 1) vty_out(vty, "\n%*s", 36, " "); else @@ -7789,7 +7783,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p, len = vty_out(vty, "%pI4%s", &attr->nexthop, vrf_id_str); - len = 16 - len; + len = wide ? (41 - len) : (16 - len); if (len < 1) vty_out(vty, "\n%*s", 36, " "); else @@ -7862,10 +7856,9 @@ void route_vty_out(struct vty *vty, const struct prefix *p, if (path->peer->conf_if) { len = vty_out(vty, "%s", path->peer->conf_if); - len = 16 - len; /* len of IPv6 - addr + max - len of def - ifname */ + /* len of IPv6 addr + max len of def + * ifname */ + len = wide ? (41 - len) : (16 - len); if (len < 1) vty_out(vty, "\n%*s", 36, " "); @@ -7884,7 +7877,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p, &attr->mp_nexthop_local, vrf_id_str); - len = 16 - len; + len = wide ? (41 - len) : (16 - len); if (len < 1) vty_out(vty, "\n%*s", 36, " "); @@ -7902,7 +7895,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p, &attr->mp_nexthop_global, vrf_id_str); - len = 16 - len; + len = wide ? (41 - len) : (16 - len); if (len < 1) vty_out(vty, "\n%*s", 36, " "); @@ -7916,10 +7909,16 @@ void route_vty_out(struct vty *vty, const struct prefix *p, if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) if (json_paths) json_object_int_add(json_path, "metric", attr->med); + else if (wide) + vty_out(vty, "%7u", attr->med); else vty_out(vty, "%10u", attr->med); - else if (!json_paths) - vty_out(vty, " "); + else if (!json_paths) { + if (wide) + vty_out(vty, "%*s", 7, " "); + else + vty_out(vty, "%*s", 10, " "); + } /* Local Pref */ if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) @@ -8023,7 +8022,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p, /* called from terminal list command */ void route_vty_out_tmp(struct vty *vty, const struct prefix *p, struct attr *attr, safi_t safi, bool use_json, - json_object *json_ar) + json_object *json_ar, bool wide) { json_object *json_status = NULL; json_object *json_net = NULL; @@ -8055,7 +8054,7 @@ void route_vty_out_tmp(struct vty *vty, const struct prefix *p, json_object_string_add(json_net, "network", buff); } } else - route_vty_out_route(p, vty, NULL); + route_vty_out_route(p, vty, NULL, wide); /* Print attribute */ if (attr) { @@ -8116,6 +8115,9 @@ void route_vty_out_tmp(struct vty *vty, const struct prefix *p, vty_out(vty, "%-16s", inet_ntoa( attr->mp_nexthop_global_in)); + else if (wide) + vty_out(vty, "%-41s", + inet_ntoa(attr->nexthop)); else vty_out(vty, "%-16s", inet_ntoa(attr->nexthop)); @@ -8128,7 +8130,7 @@ void route_vty_out_tmp(struct vty *vty, const struct prefix *p, inet_ntop(AF_INET6, &attr->mp_nexthop_global, buf, BUFSIZ)); - len = 16 - len; + len = wide ? (41 - len) : (16 - len); if (len < 1) vty_out(vty, "\n%*s", 36, " "); else @@ -8136,7 +8138,12 @@ void route_vty_out_tmp(struct vty *vty, const struct prefix *p, } if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) - vty_out(vty, "%10u", attr->med); + if (wide) + vty_out(vty, "%7u", attr->med); + else + vty_out(vty, "%10u", attr->med); + else if (wide) + vty_out(vty, " "); else vty_out(vty, " "); @@ -8187,7 +8194,7 @@ void route_vty_out_tag(struct vty *vty, const struct prefix *p, /* print prefix and mask */ if (json == NULL) { if (!display) - route_vty_out_route(p, vty, NULL); + route_vty_out_route(p, vty, NULL, false); else vty_out(vty, "%*s", 17, " "); } @@ -8284,7 +8291,7 @@ void route_vty_out_overlay(struct vty *vty, const struct prefix *p, /* print prefix and mask */ if (!display) - route_vty_out_route(p, vty, json_path); + route_vty_out_route(p, vty, json_path, false); else vty_out(vty, "%*s", 17, " "); @@ -8399,7 +8406,7 @@ static void damp_route_vty_out(struct vty *vty, const struct prefix *p, /* print prefix and mask */ if (!use_json) { if (!display) - route_vty_out_route(p, vty, NULL); + route_vty_out_route(p, vty, NULL, false); else vty_out(vty, "%*s", 17, " "); } @@ -8470,7 +8477,7 @@ static void flap_route_vty_out(struct vty *vty, const struct prefix *p, /* print prefix and mask */ if (!use_json) { if (!display) - route_vty_out_route(p, vty, NULL); + route_vty_out_route(p, vty, NULL, false); else vty_out(vty, "%*s", 17, " "); } @@ -9585,7 +9592,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, void *output_arg, bool use_json, char *rd, int is_last, unsigned long *output_cum, unsigned long *total_cum, - unsigned long *json_header_depth) + unsigned long *json_header_depth, bool wide) { struct bgp_path_info *pi; struct bgp_dest *dest; @@ -9602,8 +9609,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, if (use_json && !*json_header_depth) { vty_out(vty, - "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64 - ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n" + "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n" " \"localAS\": %u,\n \"routes\": { ", bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id, bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT @@ -9788,8 +9794,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, } if (!use_json && header) { - vty_out(vty, "BGP table version is %" PRIu64 - ", local router ID is %s, vrf id ", + vty_out(vty, "BGP table version is %" PRIu64", local router ID is %s, vrf id ", table->version, inet_ntoa(bgp->router_id)); if (bgp->vrf_id == VRF_UNKNOWN) @@ -9810,7 +9815,8 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, || type == bgp_show_type_flap_neighbor) vty_out(vty, BGP_SHOW_FLAP_HEADER); else - vty_out(vty, BGP_SHOW_HEADER); + vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE + : BGP_SHOW_HEADER)); header = 0; } if (rd != NULL && !display && !output_count) { @@ -9831,7 +9837,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, json_paths); else route_vty_out(vty, dest_p, pi, display, safi, - json_paths); + json_paths, wide); display++; } @@ -9938,7 +9944,7 @@ int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi, prefix_rd2str(&prd, rd, sizeof(rd)); bgp_show_table(vty, bgp, safi, itable, type, output_arg, use_json, rd, next == NULL, &output_cum, - &total_cum, &json_header_depth); + &total_cum, &json_header_depth, false); if (next == NULL) show_msg = false; } @@ -9955,7 +9961,8 @@ int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi, return CMD_SUCCESS; } static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, - enum bgp_show_type type, void *output_arg, bool use_json) + enum bgp_show_type type, void *output_arg, bool use_json, + bool wide) { struct bgp_table *table; unsigned long json_header_depth = 0; @@ -9989,11 +9996,12 @@ static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, safi = SAFI_UNICAST; return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json, - NULL, 1, NULL, NULL, &json_header_depth); + NULL, 1, NULL, NULL, &json_header_depth, wide); } static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi, - safi_t safi, bool use_json) + safi_t safi, bool use_json, + bool wide) { struct listnode *node, *nnode; struct bgp *bgp; @@ -10022,7 +10030,7 @@ static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi, : bgp->name); } bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL, - use_json); + use_json, wide); } if (use_json) @@ -10509,8 +10517,8 @@ static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc, return bgp_show(vty, bgp, afi, safi, (exact ? bgp_show_type_lcommunity_exact - : bgp_show_type_lcommunity), - lcom, uj); + : bgp_show_type_lcommunity), + lcom, uj, false); } static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp, @@ -10529,8 +10537,8 @@ static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp, return bgp_show(vty, bgp, afi, safi, (exact ? bgp_show_type_lcommunity_list_exact - : bgp_show_type_lcommunity_list), - list, uj); + : bgp_show_type_lcommunity_list), + list, uj, false); } DEFUN (show_ip_bgp_large_community_list, @@ -10609,9 +10617,11 @@ DEFUN (show_ip_bgp_large_community, exact_match, afi, safi, uj); } else return bgp_show(vty, bgp, afi, safi, - bgp_show_type_lcommunity_all, NULL, uj); + bgp_show_type_lcommunity_all, NULL, uj, false); } +static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi, struct json_object *json_array); static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, struct json_object *json); @@ -10631,7 +10641,7 @@ DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd, bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, &bgp, false); - if (!bgp) + if (!idx) return CMD_WARNING; if (uj) @@ -10831,7 +10841,7 @@ DEFUN(show_ip_bgp, show_ip_bgp_cmd, } /* BGP route print out function with JSON */ -DEFUN (show_ip_bgp_json, +DEFPY (show_ip_bgp_json, show_ip_bgp_json_cmd, "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\ [cidr-only\ @@ -10841,7 +10851,7 @@ DEFUN (show_ip_bgp_json, |accept-own|accept-own-nexthop|route-filter-v6\ |route-filter-v4|route-filter-translated-v6\ |route-filter-translated-v4] [exact-match]\ - ] [json]", + ] [json$uj | wide$wide]", SHOW_STR IP_STR BGP_STR @@ -10869,7 +10879,8 @@ DEFUN (show_ip_bgp_json, "RT translated VPNv6 route filtering (well-known community)\n" "RT translated VPNv4 route filtering (well-known community)\n" "Exact match of the communities\n" - JSON_STR) + JSON_STR + "Increase table width for longer prefixes\n") { afi_t afi = AFI_IP6; safi_t safi = SAFI_UNICAST; @@ -10877,7 +10888,6 @@ DEFUN (show_ip_bgp_json, struct bgp *bgp = NULL; int idx = 0; int exact_match = 0; - bool uj = use_json(argc, argv); if (uj) argc--; @@ -10889,16 +10899,17 @@ DEFUN (show_ip_bgp_json, if (argv_find(argv, argc, "cidr-only", &idx)) return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only, - NULL, uj); + NULL, uj, wide); if (argv_find(argv, argc, "dampening", &idx)) { if (argv_find(argv, argc, "dampened-paths", &idx)) return bgp_show(vty, bgp, afi, safi, - bgp_show_type_dampend_paths, NULL, uj); + bgp_show_type_dampend_paths, NULL, uj, + wide); else if (argv_find(argv, argc, "flap-statistics", &idx)) return bgp_show(vty, bgp, afi, safi, - bgp_show_type_flap_statistics, NULL, - uj); + bgp_show_type_flap_statistics, NULL, uj, + wide); } if (argv_find(argv, argc, "community", &idx)) { @@ -10924,17 +10935,16 @@ DEFUN (show_ip_bgp_json, exact_match, afi, safi, uj); else return (bgp_show(vty, bgp, afi, safi, - bgp_show_type_community_all, NULL, - uj)); + bgp_show_type_community_all, NULL, uj, + wide)); } - return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj); + return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj, wide); } DEFUN (show_ip_bgp_route, show_ip_bgp_route_cmd, - "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]" - "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]", + "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]", SHOW_STR IP_STR BGP_STR @@ -11040,22 +11050,22 @@ DEFUN (show_ip_bgp_regexp, bgp_show_type_regexp, uj); } -DEFUN (show_ip_bgp_instance_all, +DEFPY (show_ip_bgp_instance_all, show_ip_bgp_instance_all_cmd, - "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json]", + "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]", SHOW_STR IP_STR BGP_STR BGP_INSTANCE_ALL_HELP_STR BGP_AFI_HELP_STR BGP_SAFI_WITH_LABEL_HELP_STR - JSON_STR) + JSON_STR + "Increase table width for longer prefixes\n") { afi_t afi = AFI_IP; safi_t safi = SAFI_UNICAST; struct bgp *bgp = NULL; int idx = 0; - bool uj = use_json(argc, argv); if (uj) argc--; @@ -11065,7 +11075,7 @@ DEFUN (show_ip_bgp_instance_all, if (!idx) return CMD_WARNING; - bgp_show_all_instances_routes_vty(vty, afi, safi, uj); + bgp_show_all_instances_routes_vty(vty, afi, safi, uj, wide); return CMD_SUCCESS; } @@ -11088,7 +11098,7 @@ static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr, return CMD_WARNING; } - rc = bgp_show(vty, bgp, afi, safi, type, regex, use_json); + rc = bgp_show(vty, bgp, afi, safi, type, regex, use_json, false); bgp_regex_free(regex); return rc; } @@ -11106,7 +11116,7 @@ static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp, return CMD_WARNING; } - return bgp_show(vty, bgp, afi, safi, type, plist, 0); + return bgp_show(vty, bgp, afi, safi, type, plist, 0, false); } static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp, @@ -11122,7 +11132,7 @@ static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp, return CMD_WARNING; } - return bgp_show(vty, bgp, afi, safi, type, as_list, 0); + return bgp_show(vty, bgp, afi, safi, type, as_list, 0, false); } static int bgp_show_route_map(struct vty *vty, struct bgp *bgp, @@ -11137,7 +11147,7 @@ static int bgp_show_route_map(struct vty *vty, struct bgp *bgp, return CMD_WARNING; } - return bgp_show(vty, bgp, afi, safi, type, rmap, 0); + return bgp_show(vty, bgp, afi, safi, type, rmap, 0, false); } static int bgp_show_community(struct vty *vty, struct bgp *bgp, @@ -11156,7 +11166,7 @@ static int bgp_show_community(struct vty *vty, struct bgp *bgp, ret = bgp_show(vty, bgp, afi, safi, (exact ? bgp_show_type_community_exact : bgp_show_type_community), - com, use_json); + com, use_json, false); community_free(&com); return ret; @@ -11177,7 +11187,7 @@ static int bgp_show_community_list(struct vty *vty, struct bgp *bgp, return bgp_show(vty, bgp, afi, safi, (exact ? bgp_show_type_community_list_exact : bgp_show_type_community_list), - list, 0); + list, 0, false); } static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp, @@ -11195,7 +11205,7 @@ static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp, return CMD_WARNING; } - ret = bgp_show(vty, bgp, afi, safi, type, p, 0); + ret = bgp_show(vty, bgp, afi, safi, type, p, 0, false); prefix_free(&p); return ret; } @@ -11390,8 +11400,18 @@ static int bgp_table_stats_walker(struct thread *t) return 0; } -static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi, - safi_t safi, struct json_object *json_array) +static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi, + struct json_object *json_array) +{ + struct listnode *node, *nnode; + struct bgp *bgp; + + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) + bgp_table_stats_single(vty, bgp, afi, safi, json_array); +} + +static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi, struct json_object *json_array) { struct bgp_table_stats ts; unsigned int i; @@ -11419,8 +11439,10 @@ static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi, } if (!json) - vty_out(vty, "BGP %s RIB statistics\n", - get_afi_safi_str(afi, safi, false)); + vty_out(vty, "BGP %s RIB statistics (%s)\n", + get_afi_safi_str(afi, safi, false), bgp->name_pretty); + else + json_object_string_add(json, "instance", bgp->name_pretty); /* labeled-unicast routes live in the unicast table */ if (safi == SAFI_LABELED_UNICAST) @@ -11609,6 +11631,17 @@ end_table_stats: return ret; } +static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi, struct json_object *json_array) +{ + if (!bgp) { + bgp_table_stats_all(vty, afi, safi, json_array); + return CMD_SUCCESS; + } + + return bgp_table_stats_single(vty, bgp, afi, safi, json_array); +} + enum bgp_pcounts { PCOUNT_ADJ_IN = 0, PCOUNT_DAMPED, @@ -11784,7 +11817,7 @@ static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi, get_afi_safi_str(afi, safi, false)); } - vty_out(vty, "PfxCt: %" PRIu32 "\n", peer->pcount[afi][safi]); + vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]); vty_out(vty, "\nCounts from RIB table walk:\n\n"); for (i = 0; i < PCOUNT_MAX; i++) @@ -11803,8 +11836,7 @@ static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi, DEFUN (show_ip_bgp_instance_neighbor_prefix_counts, show_ip_bgp_instance_neighbor_prefix_counts_cmd, - "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] " - "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]", + "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]", SHOW_STR IP_STR BGP_STR @@ -11938,7 +11970,7 @@ DEFUN (show_bgp_l2vpn_evpn_route_prefix, static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, enum bgp_show_adj_route_type type, const char *rmap_name, bool use_json, - json_object *json) + json_object *json, bool wide) { struct bgp_table *table; struct bgp_adj_in *ain; @@ -12018,8 +12050,7 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, json, "bgpOriginatingDefaultNetwork", (afi == AFI_IP) ? "0.0.0.0/0" : "::/0"); } else { - vty_out(vty, "BGP table version is %" PRIu64 - ", local router ID is %s, vrf id ", + vty_out(vty, "BGP table version is %" PRIu64", local router ID is %s, vrf id ", table->version, inet_ntoa(bgp->router_id)); if (bgp->vrf_id == VRF_UNKNOWN) vty_out(vty, "%s", VRFID_NONE_STR); @@ -12095,7 +12126,9 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, } if (header2) { if (!use_json) - vty_out(vty, BGP_SHOW_HEADER); + vty_out(vty, + (wide ? BGP_SHOW_HEADER_WIDE + : BGP_SHOW_HEADER)); header2 = 0; } @@ -12128,7 +12161,7 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, filtered_count++; route_vty_out_tmp(vty, rn_p, &attr, safi, - use_json, json_ar); + use_json, json_ar, wide); bgp_attr_undup(&attr, ain->attr); output_count++; } @@ -12166,8 +12199,7 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, json_ocode); } else { vty_out(vty, - "BGP table version is %" PRIu64 - ", local router ID is %s, vrf id ", + "BGP table version is %" PRIu64", local router ID is %s, vrf id ", table->version, inet_ntoa( bgp->router_id)); @@ -12200,7 +12232,8 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, if (header2) { if (!use_json) vty_out(vty, - BGP_SHOW_HEADER); + (wide ? BGP_SHOW_HEADER_WIDE + : BGP_SHOW_HEADER)); header2 = 0; } @@ -12215,7 +12248,8 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, if (ret != RMAP_DENY) { route_vty_out_tmp( vty, rn_p, &attr, safi, - use_json, json_ar); + use_json, json_ar, + wide); output_count++; } else { filtered_count++; @@ -12254,7 +12288,7 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, enum bgp_show_adj_route_type type, - const char *rmap_name, bool use_json) + const char *rmap_name, bool use_json, bool wide) { json_object *json = NULL; @@ -12291,15 +12325,15 @@ static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi, return CMD_WARNING; } - show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json); + show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json, + wide); return CMD_SUCCESS; } -DEFUN (show_ip_bgp_instance_neighbor_advertised_route, +DEFPY (show_ip_bgp_instance_neighbor_advertised_route, show_ip_bgp_instance_neighbor_advertised_route_cmd, - "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] " - "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]", + "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json$uj | wide$wide]", SHOW_STR IP_STR BGP_STR @@ -12315,7 +12349,8 @@ DEFUN (show_ip_bgp_instance_neighbor_advertised_route, "Display the filtered routes received from neighbor\n" "Route-map to modify the attributes\n" "Name of the route map\n" - JSON_STR) + JSON_STR + "Increase table width for longer prefixes\n") { afi_t afi = AFI_IP6; safi_t safi = SAFI_UNICAST; @@ -12325,7 +12360,6 @@ DEFUN (show_ip_bgp_instance_neighbor_advertised_route, struct peer *peer; enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised; int idx = 0; - bool uj = use_json(argc, argv); if (uj) argc--; @@ -12353,7 +12387,7 @@ DEFUN (show_ip_bgp_instance_neighbor_advertised_route, if (argv_find(argv, argc, "route-map", &idx)) rmap_name = argv[++idx]->arg; - return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj); + return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj, wide); } DEFUN (show_ip_bgp_neighbor_received_prefix_filter, @@ -12461,7 +12495,8 @@ static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer, return CMD_WARNING; } - return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json); + return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json, + false); } DEFUN (show_ip_bgp_flowspec_routes_detailed, @@ -12490,13 +12525,13 @@ DEFUN (show_ip_bgp_flowspec_routes_detailed, if (!idx) return CMD_WARNING; - return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj); + return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj, + false); } DEFUN (show_ip_bgp_neighbor_routes, show_ip_bgp_neighbor_routes_cmd, - "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] " - "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]", + "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]", SHOW_STR IP_STR BGP_STR diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index ee52dcc8c6..0767d2912f 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -72,6 +72,7 @@ enum bgp_show_adj_route_type { #define BGP_SHOW_OCODE_HEADER "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n" #define BGP_SHOW_NCODE_HEADER "Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self\n" #define BGP_SHOW_HEADER " Network Next Hop Metric LocPrf Weight Path\n" +#define BGP_SHOW_HEADER_WIDE " Network Next Hop Metric LocPrf Weight Path\n" /* Maximum number of labels we can process or send with a prefix. We * really do only 1 for MPLS (BGP-LU) but we can do 2 for EVPN-VxLAN. @@ -618,13 +619,13 @@ extern struct bgp_path_info *info_make(int type, int sub_type, extern void route_vty_out(struct vty *vty, const struct prefix *p, struct bgp_path_info *path, int display, safi_t safi, - json_object *json_paths); + json_object *json_paths, bool wide); extern void route_vty_out_tag(struct vty *vty, const struct prefix *p, struct bgp_path_info *path, int display, safi_t safi, json_object *json); extern void route_vty_out_tmp(struct vty *vty, const struct prefix *p, struct attr *attr, safi_t safi, bool use_json, - json_object *json_ar); + json_object *json_ar, bool wide); extern void route_vty_out_overlay(struct vty *vty, const struct prefix *p, struct bgp_path_info *path, int display, json_object *json); diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index aafeb14762..97153cfb72 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -3756,8 +3756,7 @@ static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name, if (BGP_DEBUG(zebra, ZEBRA)) zlog_debug( - "Processing route_map %s update on " - "table map", + "Processing route_map %s update on table map", rmap_name); if (route_update) bgp_zebra_announce_table(bgp, afi, safi); diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c index d904b9f6f1..63cfacf678 100644 --- a/bgpd/bgp_rpki.c +++ b/bgpd/bgp_rpki.c @@ -1123,9 +1123,7 @@ DEFUN_HIDDEN (no_rpki_synchronisation_timeout, DEFPY (rpki_cache, rpki_cache_cmd, - "rpki cache <A.B.C.D|WORD>" - "<TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY SSH_PUBKEY [SERVER_PUBKEY]> " - "preference (1-255)", + "rpki cache <A.B.C.D|WORD><TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY SSH_PUBKEY [SERVER_PUBKEY]> preference (1-255)", RPKI_OUTPUT_STRING "Install a cache server to current group\n" "IP address of cache server\n Hostname of cache server\n" @@ -1161,9 +1159,7 @@ DEFPY (rpki_cache, #else return_value = SUCCESS; vty_out(vty, - "ssh sockets are not supported. " - "Please recompile rtrlib and frr with ssh support. " - "If you want to use it\n"); + "ssh sockets are not supported. Please recompile rtrlib and frr with ssh support. If you want to use it\n"); #endif } else { // use tcp connection return_value = add_tcp_cache(cache, tcpport, preference); @@ -1323,8 +1319,7 @@ DEFUN (show_rpki_cache_server, #if defined(FOUND_SSH) } else if (cache->type == SSH) { vty_out(vty, - "host: %s port: %d username: %s " - "server_hostkey_path: %s client_privkey_path: %s\n", + "host: %s port: %d username: %s server_hostkey_path: %s client_privkey_path: %s\n", cache->tr_config.ssh_config->host, cache->tr_config.ssh_config->port, cache->tr_config.ssh_config->username, diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c index 426b84f91f..ace18000f8 100644 --- a/bgpd/bgp_updgrp.c +++ b/bgpd/bgp_updgrp.c @@ -1075,10 +1075,7 @@ static void update_subgroup_merge(struct update_subgroup *subgrp, SUBGRP_INCR_STAT(target, merge_events); if (BGP_DEBUG(update_groups, UPDATE_GROUPS)) - zlog_debug("u%" PRIu64 ":s%" PRIu64 - " (%d peers) merged into u%" PRIu64 ":s%" PRIu64 - ", " - "trigger: %s", + zlog_debug("u%" PRIu64 ":s%" PRIu64" (%d peers) merged into u%" PRIu64 ":s%" PRIu64", trigger: %s", subgrp->update_group->id, subgrp->id, peer_count, target->update_group->id, target->id, reason ? reason : "unknown"); @@ -1368,8 +1365,7 @@ static int updgrp_policy_update_walkcb(struct update_group *updgrp, void *arg) if (changed) { if (bgp_debug_update(NULL, NULL, updgrp, 0)) zlog_debug( - "u%" PRIu64 ":s%" PRIu64 - " announcing routes upon policy %s (type %d) change", + "u%" PRIu64 ":s%" PRIu64" announcing routes upon policy %s (type %d) change", updgrp->id, subgrp->id, ctx->policy_name, ctx->policy_type); subgroup_announce_route(subgrp); @@ -1377,8 +1373,7 @@ static int updgrp_policy_update_walkcb(struct update_group *updgrp, void *arg) if (def_changed) { if (bgp_debug_update(NULL, NULL, updgrp, 0)) zlog_debug( - "u%" PRIu64 ":s%" PRIu64 - " announcing default upon default routemap %s change", + "u%" PRIu64 ":s%" PRIu64" announcing default upon default routemap %s change", updgrp->id, subgrp->id, ctx->policy_name); subgroup_default_originate(subgrp, 0); @@ -1484,8 +1479,7 @@ void update_subgroup_split_peer(struct peer_af *paf, UPDGRP_PEER_DBG_EN(updgrp); } if (BGP_DEBUG(update_groups, UPDATE_GROUPS)) - zlog_debug("u%" PRIu64 ":s%" PRIu64 - " peer %s moved to u%" PRIu64 ":s%" PRIu64, + zlog_debug("u%" PRIu64 ":s%" PRIu64" peer %s moved to u%" PRIu64 ":s%" PRIu64, old_id, subgrp->id, paf->peer->host, updgrp->id, subgrp->id); @@ -1519,9 +1513,7 @@ void update_subgroup_split_peer(struct peer_af *paf, update_subgroup_copy_packets(subgrp, paf->next_pkt_to_send); if (BGP_DEBUG(update_groups, UPDATE_GROUPS)) - zlog_debug("u%" PRIu64 ":s%" PRIu64 - " peer %s split and moved into u%" PRIu64 - ":s%" PRIu64, + zlog_debug("u%" PRIu64 ":s%" PRIu64" peer %s split and moved into u%" PRIu64":s%" PRIu64, paf->subgroup->update_group->id, paf->subgroup->id, paf->peer->host, updgrp->id, subgrp->id); @@ -1837,8 +1829,7 @@ void peer_af_announce_route(struct peer_af *paf, int combine) assert(subgrp && subgrp->update_group); if (bgp_debug_update(paf->peer, NULL, subgrp->update_group, 0)) - zlog_debug("u%" PRIu64 ":s%" PRIu64 - " %s announcing routes", + zlog_debug("u%" PRIu64 ":s%" PRIu64" %s announcing routes", subgrp->update_group->id, subgrp->id, paf->peer->host); @@ -1859,8 +1850,7 @@ void peer_af_announce_route(struct peer_af *paf, int combine) } if (bgp_debug_update(paf->peer, NULL, subgrp->update_group, 0)) - zlog_debug("u%" PRIu64 ":s%" PRIu64 - " announcing routes to %s, combined into %d peers", + zlog_debug("u%" PRIu64 ":s%" PRIu64" announcing routes to %s, combined into %d peers", subgrp->update_group->id, subgrp->id, paf->peer->host, subgrp->peer_count); diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index e1c2865220..ecdcaa38b8 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -246,8 +246,7 @@ static void subgrp_show_adjq_vty(struct update_subgroup *subgrp, if (adj->subgroup == subgrp) { if (header1) { vty_out(vty, - "BGP table version is %" PRIu64 - ", local router ID is %s\n", + "BGP table version is %" PRIu64", local router ID is %s\n", table->version, inet_ntoa(bgp->router_id)); vty_out(vty, BGP_SHOW_SCODE_HEADER); @@ -263,14 +262,15 @@ static void subgrp_show_adjq_vty(struct update_subgroup *subgrp, route_vty_out_tmp(vty, dest_p, adj->adv->baa->attr, SUBGRP_SAFI(subgrp), - 0, NULL); + 0, NULL, false); output_count++; } if ((flags & UPDWALK_FLAGS_ADVERTISED) && adj->attr) { - route_vty_out_tmp( - vty, dest_p, adj->attr, - SUBGRP_SAFI(subgrp), 0, NULL); + route_vty_out_tmp(vty, dest_p, + adj->attr, + SUBGRP_SAFI(subgrp), + 0, NULL, false); output_count++; } } @@ -314,8 +314,7 @@ static int subgroup_coalesce_timer(struct thread *thread) subgrp = THREAD_ARG(thread); if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0)) - zlog_debug("u%" PRIu64 ":s%" PRIu64 - " announcing routes upon coalesce timer expiry(%u ms)", + zlog_debug("u%" PRIu64 ":s%" PRIu64" announcing routes upon coalesce timer expiry(%u ms)", (SUBGRP_UPDGRP(subgrp))->id, subgrp->id, subgrp->v_coalesce); subgrp->t_coalesce = NULL; @@ -896,8 +895,7 @@ void subgroup_announce_all(struct update_subgroup *subgrp) */ if (!subgrp->v_coalesce) { if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0)) - zlog_debug("u%" PRIu64 ":s%" PRIu64 - " announcing all routes", + zlog_debug("u%" PRIu64 ":s%" PRIu64" announcing all routes", subgrp->update_group->id, subgrp->id); subgroup_announce_route(subgrp); return; diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c index f87e372540..4de5ec3b04 100644 --- a/bgpd/bgp_updgrp_packet.c +++ b/bgpd/bgp_updgrp_packet.c @@ -488,8 +488,7 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt, stream_put_in_addr_at(s, offset_nh, mod_v4nh); if (bgp_debug_update(peer, NULL, NULL, 0)) - zlog_debug("u%" PRIu64 ":s%" PRIu64 - " %s send UPDATE w/ nexthop %s%s", + zlog_debug("u%" PRIu64 ":s%" PRIu64" %s send UPDATE w/ nexthop %s%s", PAF_SUBGRP(paf)->update_group->id, PAF_SUBGRP(paf)->id, peer->host, inet_ntoa(*mod_v4nh), @@ -594,8 +593,7 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt, if (nhlen == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL || nhlen == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) zlog_debug( - "u%" PRIu64 ":s%" PRIu64 - " %s send UPDATE w/ mp_nexthops %s, %s%s", + "u%" PRIu64 ":s%" PRIu64" %s send UPDATE w/ mp_nexthops %s, %s%s", PAF_SUBGRP(paf)->update_group->id, PAF_SUBGRP(paf)->id, peer->host, inet_ntop(AF_INET6, mod_v6nhg, buf, @@ -606,8 +604,7 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt, ? " and RD" : "")); else - zlog_debug("u%" PRIu64 ":s%" PRIu64 - " %s send UPDATE w/ mp_nexthop %s%s", + zlog_debug("u%" PRIu64 ":s%" PRIu64" %s send UPDATE w/ mp_nexthop %s%s", PAF_SUBGRP(paf)->update_group->id, PAF_SUBGRP(paf)->id, peer->host, inet_ntop(AF_INET6, mod_v6nhg, buf, @@ -633,8 +630,7 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt, stream_put_in_addr_at(s, vec->offset + 1, mod_v4nh); if (bgp_debug_update(peer, NULL, NULL, 0)) - zlog_debug("u%" PRIu64 ":s%" PRIu64 - " %s send UPDATE w/ nexthop %s", + zlog_debug("u%" PRIu64 ":s%" PRIu64" %s send UPDATE w/ nexthop %s", PAF_SUBGRP(paf)->update_group->id, PAF_SUBGRP(paf)->id, peer->host, inet_ntoa(*mod_v4nh)); @@ -750,8 +746,7 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp) if (BGP_DEBUG(update, UPDATE_OUT) || BGP_DEBUG(update, UPDATE_PREFIX)) { zlog_debug( - "%s reached maximum prefix to be send (%" PRIu32 - ")", + "%s reached maximum prefix to be send (%u)", peer->host, peer->pmax_out[afi][safi]); } goto next; @@ -815,8 +810,7 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp) if (space_remaining < space_needed) { flog_err( EC_BGP_UPDGRP_ATTR_LEN, - "u%" PRIu64 ":s%" PRIu64 - " attributes too long, cannot send UPDATE", + "u%" PRIu64 ":s%" PRIu64" attributes too long, cannot send UPDATE", subgrp->update_group->id, subgrp->id); /* Flush the FIFO update queue */ @@ -872,8 +866,7 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp) char pfx_buf[BGP_PRD_PATH_STRLEN]; if (!send_attr_printed) { - zlog_debug("u%" PRIu64 ":s%" PRIu64 - " send UPDATE w/ attr: %s", + zlog_debug("u%" PRIu64 ":s%" PRIu64" send UPDATE w/ attr: %s", subgrp->update_group->id, subgrp->id, send_attr_str); if (!stream_empty(snlri)) { @@ -883,8 +876,7 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp) pkt_afi = afi_int2iana(afi); pkt_safi = safi_int2iana(safi); zlog_debug( - "u%" PRIu64 ":s%" PRIu64 - " send MP_REACH for afi/safi %d/%d", + "u%" PRIu64 ":s%" PRIu64" send MP_REACH for afi/safi %d/%d", subgrp->update_group->id, subgrp->id, pkt_afi, pkt_safi); } @@ -928,8 +920,7 @@ next: packet = stream_dup(s); bgp_packet_set_size(packet); if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0)) - zlog_debug("u%" PRIu64 ":s%" PRIu64 - " send UPDATE len %zd numpfx %d", + zlog_debug("u%" PRIu64 ":s%" PRIu64" send UPDATE len %zd numpfx %d", subgrp->update_group->id, subgrp->id, (stream_get_endp(packet) - stream_get_getp(packet)), @@ -1043,8 +1034,7 @@ struct bpacket *subgroup_withdraw_packet(struct update_subgroup *subgrp) if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0)) zlog_debug( - "u%" PRIu64 ":s%" PRIu64 - " send MP_UNREACH for afi/safi %d/%d", + "u%" PRIu64 ":s%" PRIu64" send MP_UNREACH for afi/safi %d/%d", subgrp->update_group->id, subgrp->id, pkt_afi, pkt_safi); } @@ -1062,8 +1052,7 @@ struct bpacket *subgroup_withdraw_packet(struct update_subgroup *subgrp) bgp_debug_rdpfxpath2str(afi, safi, prd, dest_p, NULL, 0, addpath_encode, addpath_tx_id, pfx_buf, sizeof(pfx_buf)); - zlog_debug("u%" PRIu64 ":s%" PRIu64 - " send UPDATE %s -- unreachable", + zlog_debug("u%" PRIu64 ":s%" PRIu64" send UPDATE %s -- unreachable", subgrp->update_group->id, subgrp->id, pfx_buf); } @@ -1091,8 +1080,7 @@ struct bpacket *subgroup_withdraw_packet(struct update_subgroup *subgrp) } bgp_packet_set_size(s); if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0)) - zlog_debug("u%" PRIu64 ":s%" PRIu64 - " send UPDATE (withdraw) len %zd numpfx %d", + zlog_debug("u%" PRIu64 ":s%" PRIu64" send UPDATE (withdraw) len %zd numpfx %d", subgrp->update_group->id, subgrp->id, (stream_get_endp(s) - stream_get_getp(s)), num_pfx); @@ -1235,8 +1223,7 @@ void subgroup_default_withdraw_packet(struct update_subgroup *subgrp) " with addpath ID %u", BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); - zlog_debug("u%" PRIu64 ":s%" PRIu64 - " send UPDATE %s%s -- unreachable", + zlog_debug("u%" PRIu64 ":s%" PRIu64" send UPDATE %s%s -- unreachable", (SUBGRP_UPDGRP(subgrp))->id, subgrp->id, prefix2str(&p, buf, sizeof(buf)), tx_id_buf); } diff --git a/bgpd/bgp_vpn.c b/bgpd/bgp_vpn.c index c8b8e2391d..0b5d156e6d 100644 --- a/bgpd/bgp_vpn.c +++ b/bgpd/bgp_vpn.c @@ -226,7 +226,7 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer, rd_header = 0; } route_vty_out_tmp(vty, bgp_dest_get_prefix(rm), attr, - safi, use_json, json_routes); + safi, use_json, json_routes, false); output_count++; } diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 6774040c4c..cfdad6d6c3 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -4330,8 +4330,7 @@ static int peer_flag_modify_vty(struct vty *vty, const char *ip_str, */ if (peer->conf_if && (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)) { vty_out(vty, - "%s is directly connected peer, cannot accept disable-" - "connected-check\n", + "%s is directly connected peer, cannot accept disable-connected-check\n", ip_str); return CMD_WARNING_CONFIG_FAILED; } @@ -9352,8 +9351,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, memory_order_relaxed); vty_out(vty, - "4 %10u %9u %9u %8" PRIu64 - " %4zu %4zu %8s", + "4 %10u %9u %9u %8" PRIu64" %4zu %4zu %8s", peer->as, PEER_TOTAL_RX(peer), PEER_TOTAL_TX(peer), peer->version[afi][safi], inq_count, @@ -9372,7 +9370,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, "(Policy)"); else vty_out(vty, - " %12" PRIu32, + " %12u", peer->pcount [afi] [pfx_rcd_safi]); @@ -9390,7 +9388,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, "(Policy)"); else vty_out(vty, - " %8" PRIu32, + " %8u", (PAF_SUBGRP( paf)) ->scount); @@ -9407,7 +9405,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, lookup_msg(bgp_status_msg, peer->status, NULL)); - vty_out(vty, " %8" PRIu32, 0); + vty_out(vty, " %8u", 0); } vty_out(vty, "\n"); } @@ -10430,8 +10428,7 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi, paf = peer_af_find(p, afi, safi); if (paf && PAF_SUBGRP(paf)) { - vty_out(vty, " Update group %" PRIu64 - ", subgroup %" PRIu64 "\n", + vty_out(vty, " Update group %" PRIu64", subgroup %" PRIu64 "\n", PAF_UPDGRP(paf)->id, PAF_SUBGRP(paf)->id); vty_out(vty, " Packet Queue length %d\n", bpacket_queue_virtual_length(paf)); @@ -10682,20 +10679,20 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi, filter->usmap.name); /* Receive prefix count */ - vty_out(vty, " %" PRIu32 " accepted prefixes\n", + vty_out(vty, " %u accepted prefixes\n", p->pcount[afi][safi]); /* maximum-prefix-out */ if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT)) vty_out(vty, - " Maximum allowed prefixes sent %" PRIu32 "\n", + " Maximum allowed prefixes sent %u\n", p->pmax_out[afi][safi]); /* Maximum prefix */ if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) { vty_out(vty, - " Maximum prefixes allowed %" PRIu32 "%s\n", + " Maximum prefixes allowed %u%s\n", p->pmax[afi][safi], CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING) @@ -13521,10 +13518,10 @@ static int bgp_show_one_peer_group(struct vty *vty, struct peer_group *group) conf = group->conf; if (conf->as_type == AS_SPECIFIED || conf->as_type == AS_EXTERNAL) { - vty_out(vty, "\nBGP peer-group %s, remote AS %" PRIu32 "\n", + vty_out(vty, "\nBGP peer-group %s, remote AS %u\n", group->name, conf->as); } else if (conf->as_type == AS_INTERNAL) { - vty_out(vty, "\nBGP peer-group %s, remote AS %" PRIu32 "\n", + vty_out(vty, "\nBGP peer-group %s, remote AS %u\n", group->name, group->bgp->as); } else { vty_out(vty, "\nBGP peer-group %s\n", group->name); @@ -15043,7 +15040,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, /* maximum-prefix. */ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_MAX_PREFIX)) { - vty_out(vty, " neighbor %s maximum-prefix %" PRIu32, addr, + vty_out(vty, " neighbor %s maximum-prefix %u", addr, peer->pmax[afi][safi]); if (peer->pmax_threshold[afi][safi] @@ -15061,7 +15058,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, /* maximum-prefix-out */ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_MAX_PREFIX_OUT)) - vty_out(vty, " neighbor %s maximum-prefix-out %" PRIu32 "\n", + vty_out(vty, " neighbor %s maximum-prefix-out %u\n", addr, peer->pmax_out[afi][safi]); /* Route server client. */ @@ -18096,8 +18093,7 @@ static int community_list_config_write(struct vty *vty) for (list = cm->str.head; list; list = list->next) for (entry = list->head; entry; entry = entry->next) { vty_out(vty, - "bgp extcommunity-list %s %s seq %" PRId64 - " %s %s\n", + "bgp extcommunity-list %s %s seq %" PRId64" %s %s\n", entry->style == EXTCOMMUNITY_LIST_STANDARD ? "standard" : "expanded", @@ -18115,8 +18111,7 @@ static int community_list_config_write(struct vty *vty) for (list = cm->num.head; list; list = list->next) for (entry = list->head; entry; entry = entry->next) { vty_out(vty, - "bgp large-community-list %s seq %" PRId64 - " %s %s\n", + "bgp large-community-list %s seq %" PRId64" %s %s\n", list->name, entry->seq, community_direct_str(entry->direct), community_list_config_str(entry)); @@ -18125,8 +18120,7 @@ static int community_list_config_write(struct vty *vty) for (list = cm->str.head; list; list = list->next) for (entry = list->head; entry; entry = entry->next) { vty_out(vty, - "bgp large-community-list %s %s seq %" PRId64 - " %s %s\n", + "bgp large-community-list %s %s seq %" PRId64" %s %s\n", entry->style == LARGE_COMMUNITY_LIST_STANDARD ? "standard" diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 518532cb51..0a55a46ed4 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1178,7 +1178,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, struct bgp_path_info *info, struct bgp *bgp, afi_t afi, safi_t safi) { - struct zapi_route api; + struct zapi_route api = { 0 }; struct zapi_nexthop *api_nh; int nh_family; unsigned int valid_nh_count = 0; @@ -1224,7 +1224,6 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, nh_othervrf = 1; /* Make Zebra API structure. */ - memset(&api, 0, sizeof(api)); api.vrf_id = bgp->vrf_id; api.type = ZEBRA_ROUTE_BGP; api.safi = safi; diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 14bfc20b22..f0ee800287 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -2174,14 +2174,6 @@ int peer_deactivate(struct peer *peer, afi_t afi, safi_t safi) return ret; } -int peer_afc_set(struct peer *peer, afi_t afi, safi_t safi, int enable) -{ - if (enable) - return peer_activate(peer, afi, safi); - else - return peer_deactivate(peer, afi, safi); -} - void peer_nsf_stop(struct peer *peer) { afi_t afi; @@ -2707,8 +2699,7 @@ int peer_group_listen_range_del(struct peer_group *group, struct prefix *range) if (prefix_match(prefix, &prefix2)) { if (bgp_debug_neighbor_events(peer)) zlog_debug( - "Deleting dynamic neighbor %s group %s upon " - "delete of listen range %s", + "Deleting dynamic neighbor %s group %s upon delete of listen range %s", peer->host, group->name, buf); peer_delete(peer); } diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 4efc068dea..8eea2a5f60 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1838,7 +1838,6 @@ extern void peer_group_notify_unconfig(struct peer_group *group); extern int peer_activate(struct peer *, afi_t, safi_t); extern int peer_deactivate(struct peer *, afi_t, safi_t); -extern int peer_afc_set(struct peer *, afi_t, safi_t, int); extern int peer_group_bind(struct bgp *, union sockunion *, struct peer *, struct peer_group *, as_t *); diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c index c935496280..0ff4b2c825 100644 --- a/bgpd/rfapi/rfapi.c +++ b/bgpd/rfapi/rfapi.c @@ -3747,8 +3747,7 @@ int rfapi_set_autord_from_vn(struct prefix_rd *rd, struct rfapi_ip_addr *vn) vnc_zlog_debug_verbose("%s: auto-assigning RD", __func__); if (vn->addr_family != AF_INET && vn->addr_family != AF_INET6) { vnc_zlog_debug_verbose( - "%s: can't auto-assign RD, VN addr family is not IPv4" - "|v6", + "%s: can't auto-assign RD, VN addr family is not IPv4|v6", __func__); return EAFNOSUPPORT; } diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c index 95b8582b95..e068eb7af6 100644 --- a/bgpd/rfapi/rfapi_rib.c +++ b/bgpd/rfapi/rfapi_rib.c @@ -646,9 +646,7 @@ static void rfapiRibBi2Ri(struct bgp_path_info *bpi, struct rfapi_info *ri, pEncap->length - 2); if (hop->length > pEncap->length - 2) { zlog_warn( - "%s: VNC subtlv length mismatch: " - "RFP option says %d, attr says %d " - "(shrinking)", + "%s: VNC subtlv length mismatch: RFP option says %d, attr says %d (shrinking)", __func__, hop->length, pEncap->length - 2); hop->length = pEncap->length - 2; diff --git a/doc/manpages/frr-watchfrr.rst b/doc/manpages/frr-watchfrr.rst index dceb423f82..d8c82eafa9 100644 --- a/doc/manpages/frr-watchfrr.rst +++ b/doc/manpages/frr-watchfrr.rst @@ -35,6 +35,22 @@ OPTIONS Set the VTY socket directory (the default value is "/var/run/frr"). +.. option:: -N <name>, --pathspace <name> + + Insert the given name into paths used by the FRR daemons. This is appended + to the VTY socket directory and passed to the daemons which also add it to + their paths in /etc. + +.. option:: --netns[=<name>] + + (Linux only.) Switch network namespaces when starting watchfrr. The name + defaults to the value passed with -N (which it should be used in conjunction + with.) If the name is not specified, the option has no effect. + + If the network namespace does not exist, it is created in a manner + compatible with iproute2. Network namespaces are not removed by FRR, this + must be done with "ip netns delete". + .. option:: -l <level>, --loglevel <level> Set the logging level (the default value is "6"). The value should range from 0 (LOG_EMERG) to 7 (LOG_DEBUG), but higher number can be supplied if extra debugging messages are required. diff --git a/doc/user/bfd.rst b/doc/user/bfd.rst index 618d90a85e..47792317ad 100644 --- a/doc/user/bfd.rst +++ b/doc/user/bfd.rst @@ -254,7 +254,7 @@ IS-IS BFD Configuration The following commands are available inside the interface configuration node. .. index:: isis bfd -.. clicmd:: ip isis bfd +.. clicmd:: isis bfd Listen for BFD events on peers created on the interface. Every time a new neighbor is found a BFD peer is created to monitor the link @@ -269,6 +269,15 @@ The following commands are available inside the interface configuration node. IPv4 and IPv6 support are configured then just a IPv6 based session is created. +.. index:: isis bfd profile BFDPROF +.. clicmd:: isis bfd profile BFDPROF + + Use a BFD profile BFDPROF as provided in the BFD configuration. + +.. index:: no isis bfd profile BFDPROF +.. clicmd:: no isis bfd profile BFDPROF + + Removes any BFD profile if present. .. _bfd-ospf-peer-config: diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index bb968735b9..d776b32a88 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -1191,6 +1191,13 @@ Defining Peers ``net.core.optmem_max`` to allow the kernel to allocate the necessary option memory. +.. index:: [no] coalesce-time (0-4294967295) +.. clicmd:: [no] coalesce-time (0-4294967295) + + The time in milliseconds that BGP will delay before deciding what peers + can be put into an update-group together in order to generate a single + update for them. The default time is 1000. + .. _bgp-configuring-peers: Configuring Peers @@ -2425,72 +2432,6 @@ This makes possible to separate not only layer 3 networks like VRF-lite networks Also, VRF netns based make possible to separate layer 2 networks on separate VRF instances. -.. _bgp-cisco-compatibility: - -Cisco Compatibility -------------------- - -FRR has commands that change some configuration syntax and default behavior to -behave more closely to Cisco conventions. These are deprecated and will be -removed in a future version of FRR. - -.. deprecated:: 5.0 - Please transition to using the FRR specific syntax for your configuration. - -.. index:: bgp config-type cisco -.. clicmd:: bgp config-type cisco - - Cisco compatible BGP configuration output. - - When this configuration line is specified: - - - ``no synchronization`` is displayed. This command does nothing and is for - display purposes only. - - ``no auto-summary`` is displayed. - - The ``network`` and ``aggregate-address`` arguments are displayed as: - - :: - - A.B.C.D M.M.M.M - - FRR: network 10.0.0.0/8 - Cisco: network 10.0.0.0 - - FRR: aggregate-address 192.168.0.0/24 - Cisco: aggregate-address 192.168.0.0 255.255.255.0 - - Community attribute handling is also different. If no configuration is - specified community attribute and extended community attribute are sent to - the neighbor. If a user manually disables the feature, the community - attribute is not sent to the neighbor. When ``bgp config-type cisco`` is - specified, the community attribute is not sent to the neighbor by default. - To send the community attribute user has to specify - :clicmd:`neighbor A.B.C.D send-community` like so: - - .. code-block:: frr - - ! - router bgp 1 - neighbor 10.0.0.1 remote-as 1 - address-family ipv4 unicast - no neighbor 10.0.0.1 send-community - exit-address-family - ! - router bgp 1 - neighbor 10.0.0.1 remote-as 1 - address-family ipv4 unicast - neighbor 10.0.0.1 send-community - exit-address-family - ! - -.. deprecated:: 5.0 - Please transition to using the FRR specific syntax for your configuration. - -.. index:: bgp config-type zebra -.. clicmd:: bgp config-type zebra - - FRR style BGP configuration. This is the default. - .. _bgp-debugging: Debugging diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst index cd095af862..6295ba9293 100644 --- a/doc/user/ospf6d.rst +++ b/doc/user/ospf6d.rst @@ -20,8 +20,11 @@ OSPF6 router Set router's Router-ID. -.. index:: interface IFNAME area AREA -.. clicmd:: interface IFNAME area AREA +.. index:: interface IFNAME area (0-4294967295) +.. clicmd:: interface IFNAME area (0-4294967295) + +.. index:: interface IFNAME area A.B.C.D +.. clicmd:: interface IFNAME area A.B.C.D Bind interface to specified area, and start sending OSPF packets. `area` can be specified as 0. diff --git a/doc/user/pbr.rst b/doc/user/pbr.rst index 149949e863..99ef258cb2 100644 --- a/doc/user/pbr.rst +++ b/doc/user/pbr.rst @@ -123,6 +123,22 @@ end destination. on another platform it will be denied. This mark translates to the underlying `ip rule .... fwmark XXXX` command. +.. clicmd:: match dscp (DSCP|0-63) + + Match packets according to the specified differentiated services code point + (DSCP) in the IP header; if this value matches then forward the packet + according to the nexthop(s) specified. The passed DSCP value may also be a + standard name for a differentiated service code point like cs0 or af11. + + You may only specify one dscp per route map sequence; to match on multiple + dscp values you will need to create several sequences, one for each value. + +.. clicmd:: match ecn (0-3) + + Match packets according to the specified explicit congestion notification + (ECN) field in the IP header; if this value matches then forward the packet + according to the nexthop(s) specified. + .. clicmd:: set nexthop-group NAME Use the nexthop-group NAME as the place to forward packets when the match diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst index fcf5c40307..7b028fd674 100644 --- a/doc/user/zebra.rst +++ b/doc/user/zebra.rst @@ -1050,11 +1050,20 @@ Many routing protocols require a router-id to be configured. To have a consistent router-id across all daemons, the following commands are available to configure and display the router-id: -.. index:: [no] router-id A.B.C.D [vrf NAME] -.. clicmd:: [no] router-id A.B.C.D [vrf NAME] +.. index:: [no] router-id A.B.C.D +.. clicmd:: [no] router-id A.B.C.D - Configure the router-id of this router. + Allow entering of the router-id. This command also works under the + vrf subnode, to allow router-id's per vrf. +.. index:: [no] router-id A.B.C.D vrf NAME +.. clicmd:: [no] router-id A.B.C.D vrf NAME + + Configure the router-id of this router from the configure NODE. + A show run of this command will display the router-id command + under the vrf sub node. This command is deprecated and will + be removed at some point in time in the future. + .. index:: show router-id [vrf NAME] .. clicmd:: show router-id [vrf NAME] diff --git a/eigrpd/eigrp_dump.c b/eigrpd/eigrp_dump.c index a3d6eb2e9e..0874ce3f19 100644 --- a/eigrpd/eigrp_dump.c +++ b/eigrpd/eigrp_dump.c @@ -234,8 +234,7 @@ void show_ip_eigrp_topology_header(struct vty *vty, struct eigrp *eigrp) vty_out(vty, "\nEIGRP Topology Table for AS(%d)/ID(%s)\n\n", eigrp->AS, inet_ntoa(eigrp->router_id)); vty_out(vty, - "Codes: P - Passive, A - Active, U - Update, Q - Query, " - "R - Reply\n r - reply Status, s - sia Status\n\n"); + "Codes: P - Passive, A - Active, U - Update, Q - Query, R - Reply\n r - reply Status, s - sia Status\n\n"); } void show_ip_eigrp_prefix_entry(struct vty *vty, struct eigrp_prefix_entry *tn) diff --git a/eigrpd/eigrp_network.c b/eigrpd/eigrp_network.c index 072ff29705..92b5ce3482 100644 --- a/eigrpd/eigrp_network.c +++ b/eigrpd/eigrp_network.c @@ -160,8 +160,7 @@ int eigrp_if_ipmulticast(struct eigrp *top, struct prefix *p, ret = setsockopt_ipv4_multicast_if(top->fd, p->u.prefix4, ifindex); if (ret < 0) zlog_warn( - "can't setsockopt IP_MULTICAST_IF (fd %d, addr %s, " - "ifindex %u): %s", + "can't setsockopt IP_MULTICAST_IF (fd %d, addr %s, ifindex %u): %s", top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); @@ -179,9 +178,7 @@ int eigrp_if_add_allspfrouters(struct eigrp *top, struct prefix *p, htonl(EIGRP_MULTICAST_ADDRESS), ifindex); if (ret < 0) zlog_warn( - "can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " - "ifindex %u, AllSPFRouters): %s; perhaps a kernel limit " - "on # of multicast group memberships has been exceeded?", + "can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, ifindex %u, AllSPFRouters): %s; perhaps a kernel limit on # of multicast group memberships has been exceeded?", top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); else @@ -201,8 +198,7 @@ int eigrp_if_drop_allspfrouters(struct eigrp *top, struct prefix *p, htonl(EIGRP_MULTICAST_ADDRESS), ifindex); if (ret < 0) zlog_warn( - "can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " - "ifindex %u, AllSPFRouters): %s", + "can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, ifindex %u, AllSPFRouters): %s", top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); else diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c index 6090a1ef13..cfff63f839 100644 --- a/eigrpd/eigrp_packet.c +++ b/eigrpd/eigrp_packet.c @@ -449,8 +449,7 @@ int eigrp_write(struct thread *thread) if (ret < 0) zlog_warn( - "*** sendmsg in eigrp_write failed to %s, " - "id %d, off %d, len %d, interface %s, mtu %u: %s", + "*** sendmsg in eigrp_write failed to %s, id %d, off %d, len %d, interface %s, mtu %u: %s", inet_ntoa(iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len, ei->ifp->name, ei->ifp->mtu, safe_strerror(errno)); @@ -578,8 +577,7 @@ int eigrp_read(struct thread *thread) if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) zlog_debug( - "ignoring packet from router %s sent to %s, " - "received on a passive interface, %s", + "ignoring packet from router %s sent to %s, received on a passive interface, %s", inet_ntop(AF_INET, &eigrph->vrid, buf[0], sizeof(buf[0])), inet_ntop(AF_INET, &iph->ip_dst, buf[1], @@ -736,8 +734,7 @@ static struct stream *eigrp_recv_packet(struct eigrp *eigrp, if ((unsigned int)ret < sizeof(*iph)) /* ret must be > 0 now */ { zlog_warn( - "eigrp_recv_packet: discarding runt packet of length %d " - "(ip header size is %u)", + "eigrp_recv_packet: discarding runt packet of length %d (ip header size is %u)", ret, (unsigned int)sizeof(*iph)); return NULL; } @@ -782,8 +779,7 @@ static struct stream *eigrp_recv_packet(struct eigrp *eigrp, if (ret != ip_len) { zlog_warn( - "eigrp_recv_packet read length mismatch: ip_len is %d, " - "but recvmsg returned %d", + "eigrp_recv_packet read length mismatch: ip_len is %d, but recvmsg returned %d", ip_len, ret); return NULL; } diff --git a/isisd/fabricd.c b/isisd/fabricd.c index e13078a7e8..e9dfd46010 100644 --- a/isisd/fabricd.c +++ b/isisd/fabricd.c @@ -372,8 +372,7 @@ static uint8_t fabricd_calculate_fabric_tier(struct isis_area *area) return ISIS_TIER_UNDEFINED; } - zlog_info("OpenFabric: Found %s as furthest t0 from local system, dist == %" - PRIu32, rawlspid_print(furthest_t0->N.id), furthest_t0->d_N); + zlog_info("OpenFabric: Found %s as furthest t0 from local system, dist == %u", rawlspid_print(furthest_t0->N.id), furthest_t0->d_N); struct isis_spftree *remote_tree = isis_run_hopcount_spf(area, furthest_t0->N.id, NULL); @@ -386,8 +385,7 @@ static uint8_t fabricd_calculate_fabric_tier(struct isis_area *area) isis_spftree_del(remote_tree); return ISIS_TIER_UNDEFINED; } else { - zlog_info("OpenFabric: Found %s as furthest from remote dist == %" - PRIu32, rawlspid_print(furthest_from_remote->N.id), + zlog_info("OpenFabric: Found %s as furthest from remote dist == %u", rawlspid_print(furthest_from_remote->N.id), furthest_from_remote->d_N); } @@ -423,7 +421,7 @@ static int fabricd_tier_calculation_cb(struct thread *thread) if (tier == ISIS_TIER_UNDEFINED) return 0; - zlog_info("OpenFabric: Got tier %" PRIu8 " from algorithm. Arming timer.", + zlog_info("OpenFabric: Got tier %hhu from algorithm. Arming timer.", tier); f->tier_pending = tier; thread_add_timer(master, fabricd_tier_set_timer, f, @@ -463,7 +461,7 @@ static void fabricd_set_tier(struct fabricd *f, uint8_t tier) if (f->tier == tier) return; - zlog_info("OpenFabric: Set own tier to %" PRIu8, tier); + zlog_info("OpenFabric: Set own tier to %hhu", tier); f->tier = tier; fabricd_bump_tier_calculation_timer(f); @@ -522,7 +520,7 @@ int fabricd_write_settings(struct isis_area *area, struct vty *vty) return written; if (f->tier_config != ISIS_TIER_UNDEFINED) { - vty_out(vty, " fabric-tier %" PRIu8 "\n", f->tier_config); + vty_out(vty, " fabric-tier %hhu\n", f->tier_config); written++; } diff --git a/isisd/isis_bfd.c b/isisd/isis_bfd.c index 69c971ee2c..5729994baa 100644 --- a/isisd/isis_bfd.c +++ b/isisd/isis_bfd.c @@ -255,6 +255,43 @@ static void bfd_debug(int family, union g_addr *dst, union g_addr *src, command_str, dst_str, interface, src_str); } +static void bfd_command(int command, struct bfd_info *bfd_info, int family, + const void *dst_ip, const void *src_ip, + const char *if_name) +{ + struct bfd_session_arg args = {}; + size_t addrlen; + + args.cbit = 1; + args.family = family; + args.vrf_id = VRF_DEFAULT; + args.command = command; + args.bfd_info = bfd_info; + if (args.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) + : sizeof(struct in6_addr); + memcpy(&args.dst, dst_ip, addrlen); + if (src_ip) + memcpy(&args.src, src_ip, addrlen); + + if (if_name) { + strlcpy(args.ifname, if_name, sizeof(args.ifname)); + args.ifnamelen = strlen(args.ifname); + } + + zclient_bfd_command(zclient, &args); +} + static void bfd_handle_adj_down(struct isis_adjacency *adj) { if (!adj->bfd_session) @@ -264,17 +301,11 @@ static void bfd_handle_adj_down(struct isis_adjacency *adj) &adj->bfd_session->src_ip, adj->circuit->interface->name, ZEBRA_BFD_DEST_DEREGISTER); - bfd_peer_sendmsg(zclient, NULL, adj->bfd_session->family, - &adj->bfd_session->dst_ip, &adj->bfd_session->src_ip, - (adj->circuit->interface) - ? adj->circuit->interface->name - : NULL, - 0, /* ttl */ - 0, /* multihop */ - 1, /* control plane independent bit is on */ - ZEBRA_BFD_DEST_DEREGISTER, - 0, /* set_flag */ - VRF_DEFAULT); + bfd_command(ZEBRA_BFD_DEST_DEREGISTER, NULL, adj->bfd_session->family, + &adj->bfd_session->dst_ip, &adj->bfd_session->src_ip, + (adj->circuit->interface) ? adj->circuit->interface->name + : NULL); + bfd_session_free(&adj->bfd_session); } @@ -324,18 +355,12 @@ static void bfd_handle_adj_up(struct isis_adjacency *adj, int command) bfd_debug(adj->bfd_session->family, &adj->bfd_session->dst_ip, &adj->bfd_session->src_ip, circuit->interface->name, command); - bfd_peer_sendmsg(zclient, circuit->bfd_info, adj->bfd_session->family, - &adj->bfd_session->dst_ip, - &adj->bfd_session->src_ip, - (adj->circuit->interface) - ? adj->circuit->interface->name - : NULL, - 0, /* ttl */ - 0, /* multihop */ - 1, /* control plane independent bit is on */ - command, - 0, /* set flag */ - VRF_DEFAULT); + + bfd_command(command, circuit->bfd_info, family, + &adj->bfd_session->dst_ip, &adj->bfd_session->src_ip, + (adj->circuit->interface) ? adj->circuit->interface->name + : NULL); + return; out: bfd_handle_adj_down(adj); @@ -383,14 +408,14 @@ void isis_bfd_circuit_cmd(struct isis_circuit *circuit, int command) } } -void isis_bfd_circuit_param_set(struct isis_circuit *circuit, - uint32_t min_rx, uint32_t min_tx, - uint32_t detect_mult, int defaults) +void isis_bfd_circuit_param_set(struct isis_circuit *circuit, uint32_t min_rx, + uint32_t min_tx, uint32_t detect_mult, + const char *profile, int defaults) { int command = 0; - bfd_set_param(&circuit->bfd_info, min_rx, - min_tx, detect_mult, defaults, &command); + bfd_set_param(&circuit->bfd_info, min_rx, min_tx, detect_mult, profile, + defaults, &command); if (command) isis_bfd_circuit_cmd(circuit, command); diff --git a/isisd/isis_bfd.h b/isisd/isis_bfd.h index 3193f16061..6ce630688c 100644 --- a/isisd/isis_bfd.h +++ b/isisd/isis_bfd.h @@ -22,9 +22,9 @@ struct isis_circuit; void isis_bfd_circuit_cmd(struct isis_circuit *circuit, int command); -void isis_bfd_circuit_param_set(struct isis_circuit *circuit, - uint32_t min_rx, uint32_t min_tx, - uint32_t detect_mult, int defaults); +void isis_bfd_circuit_param_set(struct isis_circuit *circuit, uint32_t min_rx, + uint32_t min_tx, uint32_t detect_mult, + const char *profile, int defaults); void isis_bfd_init(void); #endif diff --git a/isisd/isis_bpf.c b/isisd/isis_bpf.c index 19695e7ab4..9599077771 100644 --- a/isisd/isis_bpf.c +++ b/isisd/isis_bpf.c @@ -273,8 +273,7 @@ int isis_send_pdu_bcast(struct isis_circuit *circuit, int level) buflen = stream_get_endp(circuit->snd_stream) + LLC_LEN + ETHER_HDR_LEN; if (buflen > sizeof(sock_buff)) { zlog_warn( - "isis_send_pdu_bcast: sock_buff size %zu is less than " - "output pdu size %zu on circuit %s", + "isis_send_pdu_bcast: sock_buff size %zu is less than output pdu size %zu on circuit %s", sizeof(sock_buff), buflen, circuit->interface->name); return ISIS_WARNING; } diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index e0e82e4725..253ba22667 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -914,15 +914,13 @@ void isis_circuit_print_vty(struct isis_circuit *circuit, struct vty *vty, vty_out(vty, ", Active neighbors: %u\n", circuit->upadjcount[0]); vty_out(vty, - " Hello interval: %u, " - "Holddown count: %u %s\n", + " Hello interval: %u, Holddown count: %u %s\n", circuit->hello_interval[0], circuit->hello_multiplier[0], (circuit->pad_hellos ? "(pad)" : "(no-pad)")); vty_out(vty, - " CNSP interval: %u, " - "PSNP interval: %u\n", + " CNSP interval: %u, PSNP interval: %u\n", circuit->csnp_interval[0], circuit->psnp_interval[0]); if (circuit->circ_type == CIRCUIT_T_BROADCAST) @@ -948,15 +946,13 @@ void isis_circuit_print_vty(struct isis_circuit *circuit, struct vty *vty, vty_out(vty, ", Active neighbors: %u\n", circuit->upadjcount[1]); vty_out(vty, - " Hello interval: %u, " - "Holddown count: %u %s\n", + " Hello interval: %u, Holddown count: %u %s\n", circuit->hello_interval[1], circuit->hello_multiplier[1], (circuit->pad_hellos ? "(pad)" : "(no-pad)")); vty_out(vty, - " CNSP interval: %u, " - "PSNP interval: %u\n", + " CNSP interval: %u, PSNP interval: %u\n", circuit->csnp_interval[1], circuit->psnp_interval[1]); if (circuit->circ_type == CIRCUIT_T_BROADCAST) diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c index df69b1c7be..d864053b15 100644 --- a/isisd/isis_cli.c +++ b/isisd/isis_cli.c @@ -330,8 +330,7 @@ void cli_show_ip_isis_ipv6(struct vty *vty, struct lyd_node *dnode, DEFPY(isis_bfd, isis_bfd_cmd, "[no] isis bfd", - NO_STR - PROTO_HELP + NO_STR PROTO_HELP "Enable BFD support\n") { const struct lyd_node *dnode; @@ -343,19 +342,53 @@ DEFPY(isis_bfd, return CMD_SUCCESS; } - nb_cli_enqueue_change(vty, "./frr-isisd:isis/bfd-monitoring", + nb_cli_enqueue_change(vty, "./frr-isisd:isis/bfd-monitoring/enabled", NB_OP_MODIFY, no ? "false" : "true"); return nb_cli_apply_changes(vty, NULL); } +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring/profile + */ +DEFPY(isis_bfd_profile, + isis_bfd_profile_cmd, + "[no] isis bfd profile WORD", + NO_STR PROTO_HELP + "Enable BFD support\n" + "Use a pre-configured profile\n" + "Profile name\n") +{ + const struct lyd_node *dnode; + + dnode = yang_dnode_get(vty->candidate_config->dnode, + "%s/frr-isisd:isis", VTY_CURR_XPATH); + if (dnode == NULL) { + vty_out(vty, "ISIS is not enabled on this circuit\n"); + return CMD_SUCCESS; + } + + nb_cli_enqueue_change(vty, "./frr-isisd:isis/bfd-monitoring/profile", + NB_OP_MODIFY, no ? NULL : profile); + + return nb_cli_apply_changes(vty, NULL); +} + void cli_show_ip_isis_bfd_monitoring(struct vty *vty, struct lyd_node *dnode, bool show_defaults) { - if (!yang_dnode_get_bool(dnode, NULL)) + const char *profile; + + if (!yang_dnode_get_bool(dnode, "./enabled")) vty_out(vty, " no"); vty_out(vty, " isis bfd\n"); + + if (yang_dnode_exists(dnode, "./profile")) { + profile = yang_dnode_get_string(dnode, "./profile"); + if (profile[0] != '\0') + vty_out(vty, " isis bfd profile %s\n", profile); + } } /* @@ -1111,9 +1144,7 @@ DEFPY(isis_mpls_te_inter_as, isis_mpls_te_inter_as_cmd, * XPath: /frr-isisd:isis/instance/default-information-originate */ DEFPY(isis_default_originate, isis_default_originate_cmd, - "[no] default-information originate <ipv4|ipv6>$ip" - " <level-1|level-2>$level [always]$always" - " [{metric (0-16777215)$metric|route-map WORD$rmap}]", + "[no] default-information originate <ipv4|ipv6>$ip <level-1|level-2>$level [always]$always [{metric (0-16777215)$metric|route-map WORD$rmap}]", NO_STR "Control distribution of default information\n" "Distribute a default route\n" @@ -1190,9 +1221,7 @@ void cli_show_isis_def_origin_ipv6(struct vty *vty, struct lyd_node *dnode, */ DEFPY(isis_redistribute, isis_redistribute_cmd, "[no] redistribute <ipv4|ipv6>$ip " PROTO_REDIST_STR - "$proto" - " <level-1|level-2>$level" - " [{metric (0-16777215)|route-map WORD}]", + "$proto <level-1|level-2>$level [{metric (0-16777215)|route-map WORD}]", NO_STR REDIST_STR "Redistribute IPv4 routes\n" "Redistribute IPv6 routes\n" PROTO_REDIST_HELP @@ -1250,15 +1279,7 @@ void cli_show_isis_redistribute_ipv6(struct vty *vty, struct lyd_node *dnode, * XPath: /frr-isisd:isis/instance/multi-topology */ DEFPY(isis_topology, isis_topology_cmd, - "[no] topology " - "<ipv4-unicast" - "|ipv4-mgmt" - "|ipv6-unicast" - "|ipv4-multicast" - "|ipv6-multicast" - "|ipv6-mgmt" - "|ipv6-dstsrc>$topology " - "[overload]$overload", + "[no] topology <ipv4-unicast|ipv4-mgmt|ipv6-unicast|ipv4-multicast|ipv6-multicast|ipv6-mgmt|ipv6-dstsrc>$topology [overload]$overload", NO_STR "Configure IS-IS topologies\n" "IPv4 unicast topology\n" @@ -2011,15 +2032,7 @@ void cli_show_ip_isis_psnp_interval(struct vty *vty, struct lyd_node *dnode, * XPath: /frr-interface:lib/interface/frr-isisd:isis/multi-topology */ DEFPY(circuit_topology, circuit_topology_cmd, - "[no] isis topology" - "<ipv4-unicast" - "|ipv4-mgmt" - "|ipv6-unicast" - "|ipv4-multicast" - "|ipv6-multicast" - "|ipv6-mgmt" - "|ipv6-dstsrc" - ">$topology", + "[no] isis topology<ipv4-unicast|ipv4-mgmt|ipv6-unicast|ipv4-multicast|ipv6-multicast|ipv6-mgmt|ipv6-dstsrc>$topology", NO_STR "IS-IS routing protocol\n" "Configure interface IS-IS topologies\n" @@ -2301,6 +2314,7 @@ void isis_cli_init(void) install_element(INTERFACE_NODE, &ip6_router_isis_cmd); install_element(INTERFACE_NODE, &no_ip_router_isis_cmd); install_element(INTERFACE_NODE, &isis_bfd_cmd); + install_element(INTERFACE_NODE, &isis_bfd_profile_cmd); install_element(ISIS_NODE, &net_cmd); diff --git a/isisd/isis_dlpi.c b/isisd/isis_dlpi.c index 5c15d1d29d..06fb41430c 100644 --- a/isisd/isis_dlpi.c +++ b/isisd/isis_dlpi.c @@ -566,8 +566,7 @@ int isis_send_pdu_bcast(struct isis_circuit *circuit, int level) buflen = stream_get_endp(circuit->snd_stream) + LLC_LEN; if ((size_t)buflen > sizeof(sock_buff)) { zlog_warn( - "isis_send_pdu_bcast: sock_buff size %zu is less than " - "output pdu size %d on circuit %s", + "isis_send_pdu_bcast: sock_buff size %zu is less than output pdu size %d on circuit %s", sizeof(sock_buff), buflen, circuit->interface->name); return ISIS_WARNING; } diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 63303e2308..bf15163cbf 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -200,16 +200,12 @@ int lsp_compare(char *areatag, struct isis_lsp *lsp, uint32_t seqno, || (lsp->hdr.rem_lifetime != 0 && rem_lifetime != 0))) { if (IS_DEBUG_SNP_PACKETS) { zlog_debug( - "ISIS-Snp (%s): Compare LSP %s seq 0x%08" PRIx32 - ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 - "s", + "ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04hx, lifetime %hus", areatag, rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.seqno, lsp->hdr.checksum, lsp->hdr.rem_lifetime); zlog_debug( - "ISIS-Snp (%s): is equal to ours seq 0x%08" PRIx32 - ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 - "s", + "ISIS-Snp (%s): is equal to ours seq 0x%08x, cksum 0x%04hx, lifetime %hus", areatag, seqno, checksum, rem_lifetime); } return LSP_EQUAL; @@ -234,28 +230,22 @@ int lsp_compare(char *areatag, struct isis_lsp *lsp, uint32_t seqno, && lsp->hdr.rem_lifetime)))) { if (IS_DEBUG_SNP_PACKETS) { zlog_debug( - "ISIS-Snp (%s): Compare LSP %s seq 0x%08" PRIx32 - ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 - "s", + "ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04hx, lifetime %hus", areatag, rawlspid_print(lsp->hdr.lsp_id), seqno, checksum, rem_lifetime); zlog_debug( - "ISIS-Snp (%s): is newer than ours seq 0x%08" PRIx32 - ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 - "s", + "ISIS-Snp (%s): is newer than ours seq 0x%08x, cksum 0x%04hx, lifetime %hus", areatag, lsp->hdr.seqno, lsp->hdr.checksum, lsp->hdr.rem_lifetime); } return LSP_NEWER; } if (IS_DEBUG_SNP_PACKETS) { - zlog_debug("ISIS-Snp (%s): Compare LSP %s seq 0x%08" PRIx32 - ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 "s", + zlog_debug("ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04hx, lifetime %hus", areatag, rawlspid_print(lsp->hdr.lsp_id), seqno, checksum, rem_lifetime); zlog_debug( - "ISIS-Snp (%s): is older than ours seq 0x%08" PRIx32 - ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 "s", + "ISIS-Snp (%s): is older than ours seq 0x%08x, cksum 0x%04hx, lifetime %hus", areatag, lsp->hdr.seqno, lsp->hdr.checksum, lsp->hdr.rem_lifetime); } @@ -656,15 +646,15 @@ void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost) lspid_print(lsp->hdr.lsp_id, LSPid, dynhost, 1); vty_out(vty, "%-21s%c ", LSPid, lsp->own_lsp ? '*' : ' '); - vty_out(vty, "%5" PRIu16 " ", lsp->hdr.pdu_len); - vty_out(vty, "0x%08" PRIx32 " ", lsp->hdr.seqno); - vty_out(vty, "0x%04" PRIx16 " ", lsp->hdr.checksum); + vty_out(vty, "%5hu ", lsp->hdr.pdu_len); + vty_out(vty, "0x%08x ", lsp->hdr.seqno); + vty_out(vty, "0x%04hx ", lsp->hdr.checksum); if (lsp->hdr.rem_lifetime == 0) { snprintf(age_out, sizeof(age_out), "(%d)", lsp->age_out); age_out[7] = '\0'; vty_out(vty, "%7s ", age_out); } else - vty_out(vty, " %5" PRIu16 " ", lsp->hdr.rem_lifetime); + vty_out(vty, " %5hu ", lsp->hdr.rem_lifetime); vty_out(vty, "%s\n", lsp_bits2string(lsp->hdr.lsp_bits, b, sizeof(b))); } @@ -994,7 +984,7 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area) if (fabricd) { lsp_debug( - "ISIS (%s): Adding tier %" PRIu8 " spine-leaf-extension tlv.", + "ISIS (%s): Adding tier %hhu spine-leaf-extension tlv.", area->area_tag, fabricd_tier(area)); isis_tlvs_add_spine_leaf(lsp->tlvs, fabricd_tier(area), true, false, false, false); @@ -1256,9 +1246,7 @@ int lsp_generate(struct isis_area *area, int level) &area->t_lsp_refresh[level - 1]); if (IS_DEBUG_UPDATE_PACKETS) { - zlog_debug("ISIS-Upd (%s): Building L%d LSP %s, len %" PRIu16 - ", seq 0x%08" PRIx32 ", cksum 0x%04" PRIx16 - ", lifetime %" PRIu16 "s refresh %" PRIu16 "s", + zlog_debug("ISIS-Upd (%s): Building L%d LSP %s, len %hu, seq 0x%08x, cksum 0x%04hx, lifetime %hus refresh %hus", area->area_tag, level, rawlspid_print(newlsp->hdr.lsp_id), newlsp->hdr.pdu_len, newlsp->hdr.seqno, @@ -1341,9 +1329,7 @@ static int lsp_regenerate(struct isis_area *area, int level) if (IS_DEBUG_UPDATE_PACKETS) { zlog_debug( - "ISIS-Upd (%s): Refreshed our L%d LSP %s, len %" PRIu16 - ", seq 0x%08" PRIx32 ", cksum 0x%04" PRIx16 - ", lifetime %" PRIu16 "s refresh %" PRIu16 "s", + "ISIS-Upd (%s): Refreshed our L%d LSP %s, len %hu, seq 0x%08x, cksum 0x%04hx, lifetime %hus refresh %hus", area->area_tag, level, rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.pdu_len, lsp->hdr.seqno, lsp->hdr.checksum, lsp->hdr.rem_lifetime, refresh_time); @@ -1413,8 +1399,7 @@ int _lsp_regenerate_schedule(struct isis_area *area, int level, return ISIS_ERROR; sched_debug( - "ISIS (%s): Scheduling regeneration of %s LSPs, %sincluding PSNs" - " Caller: %s %s:%d", + "ISIS (%s): Scheduling regeneration of %s LSPs, %sincluding PSNs Caller: %s %s:%d", area->area_tag, circuit_t2string(level), all_pseudo ? "" : "not ", func, file, line); @@ -1444,8 +1429,7 @@ int _lsp_regenerate_schedule(struct isis_area *area, int level, struct timeval remain = thread_timer_remain( area->t_lsp_refresh[lvl - 1]); sched_debug( - "ISIS (%s): Regeneration is already pending, nothing todo." - " (Due in %lld.%03lld seconds)", + "ISIS (%s): Regeneration is already pending, nothing todo. (Due in %lld.%03lld seconds)", area->area_tag, (long long)remain.tv_sec, (long long)remain.tv_usec / 1000); continue; @@ -1656,9 +1640,7 @@ int lsp_generate_pseudo(struct isis_circuit *circuit, int level) if (IS_DEBUG_UPDATE_PACKETS) { zlog_debug( - "ISIS-Upd (%s): Built L%d Pseudo LSP %s, len %" PRIu16 - ", seq 0x%08" PRIx32 ", cksum 0x%04" PRIx16 - ", lifetime %" PRIu16 "s, refresh %" PRIu16 "s", + "ISIS-Upd (%s): Built L%d Pseudo LSP %s, len %hu, seq 0x%08x, cksum 0x%04hx, lifetime %hus, refresh %hus", circuit->area->area_tag, level, rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.pdu_len, lsp->hdr.seqno, lsp->hdr.checksum, @@ -1713,9 +1695,7 @@ static int lsp_regenerate_pseudo(struct isis_circuit *circuit, int level) if (IS_DEBUG_UPDATE_PACKETS) { zlog_debug( - "ISIS-Upd (%s): Refreshed L%d Pseudo LSP %s, len %" PRIu16 - ", seq 0x%08" PRIx32 ", cksum 0x%04" PRIx16 - ", lifetime %" PRIu16 "s, refresh %" PRIu16 "s", + "ISIS-Upd (%s): Refreshed L%d Pseudo LSP %s, len %hu, seq 0x%08x, cksum 0x%04hx, lifetime %hus, refresh %hus", circuit->area->area_tag, level, rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.pdu_len, lsp->hdr.seqno, lsp->hdr.checksum, @@ -1817,8 +1797,7 @@ int lsp_regenerate_schedule_pseudo(struct isis_circuit *circuit, int level) struct timeval remain = thread_timer_remain( circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1]); sched_debug( - "ISIS (%s): Regenerate is already pending, nothing todo." - " (Due in %lld.%03lld seconds)", + "ISIS (%s): Regenerate is already pending, nothing todo. (Due in %lld.%03lld seconds)", area->area_tag, (long long)remain.tv_sec, (long long)remain.tv_usec / 1000); continue; @@ -1851,8 +1830,7 @@ int lsp_regenerate_schedule_pseudo(struct isis_circuit *circuit, int level) } else { timeout = 100; sched_debug( - "ISIS (%s): Last generation was more than lsp_gen_interval ago." - " Scheduling for execution in %ld ms.", + "ISIS (%s): Last generation was more than lsp_gen_interval ago. Scheduling for execution in %ld ms.", area->area_tag, timeout); } @@ -1930,8 +1908,7 @@ int lsp_tick(struct thread *thread) if (lsp->age_out == 0) { zlog_debug( - "ISIS-Upd (%s): L%u LSP %s seq " - "0x%08" PRIx32 " aged out", + "ISIS-Upd (%s): L%u LSP %s seq 0x%08x aged out", area->area_tag, lsp->level, rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.seqno); diff --git a/isisd/isis_main.c b/isisd/isis_main.c index cb5b47bbd6..2317b166c6 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -185,8 +185,7 @@ FRR_DAEMON_INFO(isisd, ISIS, .vty_port = ISISD_VTY_PORT, .proghelp = "Implementation of the IS-IS routing protocol.", #endif .copyright = - "Copyright (c) 2001-2002 Sampo Saaristo," - " Ofer Wald and Hannes Gredler", + "Copyright (c) 2001-2002 Sampo Saaristo, Ofer Wald and Hannes Gredler", .signals = isisd_signals, .n_signals = array_size(isisd_signals), diff --git a/isisd/isis_misc.c b/isisd/isis_misc.c index 27d06e8da7..86725173c4 100644 --- a/isisd/isis_misc.c +++ b/isisd/isis_misc.c @@ -190,7 +190,7 @@ const char *nlpid2str(uint8_t nlpid) case NLPID_ESIS: return "ES-IS"; default: - snprintf(buf, sizeof(buf), "%" PRIu8, nlpid); + snprintf(buf, sizeof(buf), "%hhu", nlpid); return buf; } } diff --git a/isisd/isis_mt.c b/isisd/isis_mt.c index 5c262049a9..9465c5e75c 100644 --- a/isisd/isis_mt.c +++ b/isisd/isis_mt.c @@ -72,7 +72,7 @@ const char *isis_mtid2str(uint16_t mtid) case ISIS_MT_IPV6_DSTSRC: return "ipv6-dstsrc"; default: - snprintf(buf, sizeof(buf), "%" PRIu16, mtid); + snprintf(buf, sizeof(buf), "%hu", mtid); return buf; } } diff --git a/isisd/isis_nb.c b/isisd/isis_nb.c index 1d842eb13b..2b8b02e3f1 100644 --- a/isisd/isis_nb.c +++ b/isisd/isis_nb.c @@ -574,11 +574,24 @@ const struct frr_yang_module_info frr_isisd_info = { { .xpath = "/frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring", .cbs = { - .modify = lib_interface_isis_bfd_monitoring_modify, + .apply_finish = lib_interface_isis_bfd_monitoring_apply_finish, .cli_show = cli_show_ip_isis_bfd_monitoring, } }, { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring/enabled", + .cbs = { + .modify = lib_interface_isis_bfd_monitoring_enabled_modify, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring/profile", + .cbs = { + .modify = lib_interface_isis_bfd_monitoring_profile_modify, + .destroy = lib_interface_isis_bfd_monitoring_profile_destroy, + } + }, + { .xpath = "/frr-interface:lib/interface/frr-isisd:isis/csnp-interval", .cbs = { .cli_show = cli_show_ip_isis_csnp_interval, diff --git a/isisd/isis_nb.h b/isisd/isis_nb.h index e887b1a388..a9401bc86a 100644 --- a/isisd/isis_nb.h +++ b/isisd/isis_nb.h @@ -171,7 +171,14 @@ int lib_interface_isis_area_tag_modify(struct nb_cb_modify_args *args); int lib_interface_isis_ipv4_routing_modify(struct nb_cb_modify_args *args); int lib_interface_isis_ipv6_routing_modify(struct nb_cb_modify_args *args); int lib_interface_isis_circuit_type_modify(struct nb_cb_modify_args *args); -int lib_interface_isis_bfd_monitoring_modify(struct nb_cb_modify_args *args); +void lib_interface_isis_bfd_monitoring_apply_finish( + struct nb_cb_apply_finish_args *args); +int lib_interface_isis_bfd_monitoring_enabled_modify( + struct nb_cb_modify_args *args); +int lib_interface_isis_bfd_monitoring_profile_modify( + struct nb_cb_modify_args *args); +int lib_interface_isis_bfd_monitoring_profile_destroy( + struct nb_cb_destroy_args *args); int isis_instance_segment_routing_enabled_modify( struct nb_cb_modify_args *args); int isis_instance_segment_routing_enabled_modify( diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c index c17433cb27..6873c652f2 100644 --- a/isisd/isis_nb_config.c +++ b/isisd/isis_nb_config.c @@ -1503,7 +1503,7 @@ int isis_instance_segment_routing_srgb_lower_bound_modify( switch (args->event) { case NB_EV_VALIDATE: if (!IS_MPLS_UNRESERVED_LABEL(lower_bound)) { - zlog_warn("Invalid SRGB lower bound: %" PRIu32, + zlog_warn("Invalid SRGB lower bound: %u", lower_bound); return NB_ERR_VALIDATION; } @@ -1528,7 +1528,7 @@ int isis_instance_segment_routing_srgb_upper_bound_modify( switch (args->event) { case NB_EV_VALIDATE: if (!IS_MPLS_UNRESERVED_LABEL(upper_bound)) { - zlog_warn("Invalid SRGB upper bound: %" PRIu32, + zlog_warn("Invalid SRGB upper bound: %u", upper_bound); return NB_ERR_VALIDATION; } @@ -1601,7 +1601,7 @@ int isis_instance_segment_routing_srlb_lower_bound_modify( switch (args->event) { case NB_EV_VALIDATE: if (!IS_MPLS_UNRESERVED_LABEL(lower_bound)) { - zlog_warn("Invalid SRLB lower bound: %" PRIu32, + zlog_warn("Invalid SRLB lower bound: %u", lower_bound); return NB_ERR_VALIDATION; } @@ -1626,7 +1626,7 @@ int isis_instance_segment_routing_srlb_upper_bound_modify( switch (args->event) { case NB_EV_VALIDATE: if (!IS_MPLS_UNRESERVED_LABEL(upper_bound)) { - zlog_warn("Invalid SRLB upper bound: %" PRIu32, + zlog_warn("Invalid SRLB upper bound: %u", upper_bound); return NB_ERR_VALIDATION; } @@ -1854,8 +1854,7 @@ int lib_interface_isis_create(struct nb_cb_create_args *args) #endif /* ifndef FABRICD */ if (actual_mtu < min_mtu) { snprintf(args->errmsg, args->errmsg_len, - "Interface %s has MTU %" PRIu32 - ", minimum MTU for the area is %" PRIu32 "", + "Interface %s has MTU %u, minimum MTU for the area is %u", ifp->name, actual_mtu, min_mtu); return NB_ERR_VALIDATION; } @@ -2030,26 +2029,53 @@ int lib_interface_isis_ipv6_routing_modify(struct nb_cb_modify_args *args) /* * XPath: /frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring */ -int lib_interface_isis_bfd_monitoring_modify(struct nb_cb_modify_args *args) +void lib_interface_isis_bfd_monitoring_apply_finish( + struct nb_cb_apply_finish_args *args) { struct isis_circuit *circuit; - bool bfd_monitoring; - - if (args->event != NB_EV_APPLY) - return NB_OK; + bool enabled; + const char *profile = NULL; circuit = nb_running_get_entry(args->dnode, NULL, true); - bfd_monitoring = yang_dnode_get_bool(args->dnode, NULL); + enabled = yang_dnode_get_bool(args->dnode, "./enabled"); + + if (yang_dnode_exists(args->dnode, "./profile")) + profile = yang_dnode_get_string(args->dnode, "./profile"); - if (bfd_monitoring) { + if (enabled) { isis_bfd_circuit_param_set(circuit, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, BFD_DEF_DETECT_MULT, - true); + profile, true); } else { isis_bfd_circuit_cmd(circuit, ZEBRA_BFD_DEST_DEREGISTER); bfd_info_free(&circuit->bfd_info); } +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring/enabled + */ +int lib_interface_isis_bfd_monitoring_enabled_modify( + struct nb_cb_modify_args *args) +{ + /* Everything done in apply_finish */ + return NB_OK; +} +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring/profile + */ +int lib_interface_isis_bfd_monitoring_profile_modify( + struct nb_cb_modify_args *args) +{ + /* Everything done in apply_finish */ + return NB_OK; +} + +int lib_interface_isis_bfd_monitoring_profile_destroy( + struct nb_cb_destroy_args *args) +{ + /* Everything done in apply_finish */ return NB_OK; } diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index b5377142b6..72548e0425 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -427,8 +427,7 @@ static int process_p2p_hello(struct iih_info *iih) if (IS_DEBUG_ADJ_PACKETS) { zlog_debug( - "ISIS-Adj (%s): Rcvd P2P IIH from (%s), cir type %s," - " cir id %hhu, length %" PRIu16, + "ISIS-Adj (%s): Rcvd P2P IIH from (%s), cir type %s, cir id %hhu, length %hu", iih->circuit->area->area_tag, iih->circuit->interface->name, circuit_t2string(iih->circuit->is_type), @@ -647,7 +646,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, if (pdu_len_validate(iih.pdu_len, circuit)) { zlog_warn( - "ISIS-Adj (%s): Rcvd %s from (%s) with invalid pdu length %" PRIu16, + "ISIS-Adj (%s): Rcvd %s from (%s) with invalid pdu length %hu", circuit->area->area_tag, pdu_name, circuit->interface->name, iih.pdu_len); circuit->rej_adjacencies++; @@ -860,16 +859,14 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, #endif /* ifndef FABRICD */ if (pdu_len_validate(hdr.pdu_len, circuit)) { - zlog_debug("ISIS-Upd (%s): LSP %s invalid LSP length %" PRIu16, + zlog_debug("ISIS-Upd (%s): LSP %s invalid LSP length %hu", circuit->area->area_tag, rawlspid_print(hdr.lsp_id), hdr.pdu_len); return ISIS_WARNING; } if (IS_DEBUG_UPDATE_PACKETS) { - zlog_debug("ISIS-Upd (%s): Rcvd L%d LSP %s, seq 0x%08" PRIx32 - ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 - "s, len %" PRIu16 ", on %s", + zlog_debug("ISIS-Upd (%s): Rcvd L%d LSP %s, seq 0x%08x, cksum 0x%04hx, lifetime %hus, len %hu, on %s", circuit->area->area_tag, level, rawlspid_print(hdr.lsp_id), hdr.seqno, hdr.checksum, hdr.rem_lifetime, hdr.pdu_len, @@ -879,7 +876,7 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, /* lsp is_type check */ if ((hdr.lsp_bits & IS_LEVEL_1) != IS_LEVEL_1) { zlog_debug( - "ISIS-Upd (%s): LSP %s invalid LSP is type 0x%" PRIx8, + "ISIS-Upd (%s): LSP %s invalid LSP is type 0x%x", circuit->area->area_tag, rawlspid_print(hdr.lsp_id), hdr.lsp_bits & IS_LEVEL_1_AND_2); /* continue as per RFC1122 Be liberal in what you accept, and @@ -891,7 +888,7 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, if (iso_csum_verify(STREAM_DATA(circuit->rcv_stream) + 12, hdr.pdu_len - 12, hdr.checksum, 12)) { zlog_debug( - "ISIS-Upd (%s): LSP %s invalid LSP checksum 0x%04" PRIx16, + "ISIS-Upd (%s): LSP %s invalid LSP checksum 0x%04hx", circuit->area->area_tag, rawlspid_print(hdr.lsp_id), hdr.checksum); return ISIS_WARNING; @@ -900,8 +897,7 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, /* 7.3.15.1 a) 1 - external domain circuit will discard lsps */ if (circuit->ext_domain) { zlog_debug( - "ISIS-Upd (%s): LSP %s received at level %d over circuit with " - "externalDomain = true", + "ISIS-Upd (%s): LSP %s received at level %d over circuit with externalDomain = true", circuit->area->area_tag, rawlspid_print(hdr.lsp_id), level); return ISIS_WARNING; @@ -910,8 +906,7 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, /* 7.3.15.1 a) 2,3 - manualL2OnlyMode not implemented */ if (!(circuit->is_type & level)) { zlog_debug( - "ISIS-Upd (%s): LSP %s received at level %d over circuit of" - " type %s", + "ISIS-Upd (%s): LSP %s received at level %d over circuit of type %s", circuit->area->area_tag, rawlspid_print(hdr.lsp_id), level, circuit_t2string(circuit->is_type)); return ISIS_WARNING; @@ -986,9 +981,7 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, if (circuit->circ_type == CIRCUIT_T_BROADCAST) { if (!isis_adj_lookup_snpa(ssnpa, circuit->u.bc.adjdb[level - 1])) { - zlog_debug("(%s): DS ======= LSP %s, seq 0x%08" PRIx32 - ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 - "s on %s", + zlog_debug("(%s): DS ======= LSP %s, seq 0x%08x, cksum 0x%04hx, lifetime %hus on %s", circuit->area->area_tag, rawlspid_print(hdr.lsp_id), hdr.seqno, hdr.checksum, hdr.rem_lifetime, @@ -1029,8 +1022,7 @@ dontcheckadj: if (lsp && (lsp->hdr.seqno == hdr.seqno) && (lsp->hdr.checksum != hdr.checksum) && hdr.rem_lifetime) { - zlog_warn("ISIS-Upd (%s): LSP %s seq 0x%08" PRIx32 - " with confused checksum received.", + zlog_warn("ISIS-Upd (%s): LSP %s seq 0x%08x with confused checksum received.", circuit->area->area_tag, rawlspid_print(hdr.lsp_id), hdr.seqno); hdr.rem_lifetime = 0; @@ -1125,9 +1117,7 @@ dontcheckadj: } if (IS_DEBUG_UPDATE_PACKETS) zlog_debug( - "ISIS-Upd (%s): (1) " - "re-originating LSP %s new seq " - "0x%08" PRIx32, + "ISIS-Upd (%s): (1) re-originating LSP %s new seq 0x%08x", circuit->area->area_tag, rawlspid_print(hdr.lsp_id), lsp->hdr.seqno); @@ -1169,7 +1159,7 @@ dontcheckadj: #endif /* ifndef FABRICD */ if (IS_DEBUG_UPDATE_PACKETS) { zlog_debug( - "ISIS-Upd (%s): (2) re-originating LSP %s new seq 0x%08" PRIx32, + "ISIS-Upd (%s): (2) re-originating LSP %s new seq 0x%08x", circuit->area->area_tag, rawlspid_print(hdr.lsp_id), lsp->hdr.seqno); @@ -1314,8 +1304,7 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit, if (circuit->ext_domain) { zlog_debug( - "ISIS-Snp (%s): Rcvd L%d %cSNP on %s, " - "skipping: circuit externalDomain = true", + "ISIS-Snp (%s): Rcvd L%d %cSNP on %s, skipping: circuit externalDomain = true", circuit->area->area_tag, level, typechar, circuit->interface->name); @@ -1325,8 +1314,7 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit, /* 7.3.15.2 a) 2,3 - manualL2OnlyMode not implemented */ if (!(circuit->is_type & level)) { zlog_debug( - "ISIS-Snp (%s): Rcvd L%d %cSNP on %s, " - "skipping: circuit type %s does not match level %d", + "ISIS-Snp (%s): Rcvd L%d %cSNP on %s, skipping: circuit type %s does not match level %d", circuit->area->area_tag, level, typechar, circuit->interface->name, circuit_t2string(circuit->is_type), level); @@ -1338,8 +1326,7 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit, if (!is_csnp && (circuit->circ_type == CIRCUIT_T_BROADCAST) && !circuit->u.bc.is_dr[level - 1]) { zlog_debug( - "ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s, " - "skipping: we are not the DIS", + "ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s, skipping: we are not the DIS", circuit->area->area_tag, level, typechar, snpa_print(ssnpa), circuit->interface->name); @@ -1419,8 +1406,7 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit, for (struct isis_lsp_entry *entry = entry_head; entry; entry = entry->next) { zlog_debug( - "ISIS-Snp (%s): %cSNP entry %s, seq 0x%08" PRIx32 - ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 "s", + "ISIS-Snp (%s): %cSNP entry %s, seq 0x%08x, cksum 0x%04hx, lifetime %hus", circuit->area->area_tag, typechar, rawlspid_print(entry->id), entry->seqno, entry->checksum, entry->rem_lifetime); @@ -1613,18 +1599,18 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) if (idrp == ISO9542_ESIS) { flog_err(EC_LIB_DEVELOPMENT, - "No support for ES-IS packet IDRP=%" PRIx8, idrp); + "No support for ES-IS packet IDRP=%hhx", idrp); return ISIS_ERROR; } if (idrp != ISO10589_ISIS) { - flog_err(EC_ISIS_PACKET, "Not an IS-IS packet IDRP=%" PRIx8, + flog_err(EC_ISIS_PACKET, "Not an IS-IS packet IDRP=%hhx", idrp); return ISIS_ERROR; } if (version1 != 1) { - zlog_warn("Unsupported ISIS version %" PRIu8, version1); + zlog_warn("Unsupported ISIS version %hhu", version1); #ifndef FABRICD /* send northbound notification */ isis_notif_version_skew(circuit, version1, raw_pdu); @@ -1635,8 +1621,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) if (id_len != 0 && id_len != ISIS_SYS_ID_LEN) { flog_err( EC_ISIS_PACKET, - "IDFieldLengthMismatch: ID Length field in a received PDU %" PRIu8 - ", while the parameter for this IS is %u", + "IDFieldLengthMismatch: ID Length field in a received PDU %hhu, while the parameter for this IS is %u", id_len, ISIS_SYS_ID_LEN); circuit->id_len_mismatches++; #ifndef FABRICD @@ -1648,14 +1633,13 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) uint8_t expected_length; if (pdu_size(pdu_type, &expected_length)) { - zlog_warn("Unsupported ISIS PDU %" PRIu8, pdu_type); + zlog_warn("Unsupported ISIS PDU %hhu", pdu_type); return ISIS_WARNING; } if (length != expected_length) { flog_err(EC_ISIS_PACKET, - "Expected fixed header length = %" PRIu8 - " but got %" PRIu8, + "Expected fixed header length = %hhu but got %hhu", expected_length, length); return ISIS_ERROR; } @@ -1668,7 +1652,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) } if (version2 != 1) { - zlog_warn("Unsupported ISIS PDU version %" PRIu8, version2); + zlog_warn("Unsupported ISIS PDU version %hhu", version2); #ifndef FABRICD /* send northbound notification */ isis_notif_version_skew(circuit, version2, raw_pdu); @@ -1688,8 +1672,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) && max_area_addrs != isis->max_area_addrs) { flog_err( EC_ISIS_PACKET, - "maximumAreaAddressesMismatch: maximumAreaAdresses in a received PDU %" PRIu8 - " while the parameter for this IS is %u", + "maximumAreaAddressesMismatch: maximumAreaAdresses in a received PDU %hhu while the parameter for this IS is %u", max_area_addrs, isis->max_area_addrs); circuit->max_area_addr_mismatches++; #ifndef FABRICD @@ -2409,9 +2392,7 @@ void send_lsp(struct isis_circuit *circuit, struct isis_lsp *lsp, if (stream_get_endp(lsp->pdu) > stream_get_size(circuit->snd_stream)) { flog_err( EC_ISIS_PACKET, - "ISIS-Upd (%s): Can't send L%d LSP %s, seq 0x%08" PRIx32 - ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 - "s on %s. LSP Size is %zu while interface stream size is %zu.", + "ISIS-Upd (%s): Can't send L%d LSP %s, seq 0x%08x, cksum 0x%04hx, lifetime %hus on %s. LSP Size is %zu while interface stream size is %zu.", circuit->area->area_tag, lsp->level, rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.seqno, lsp->hdr.checksum, lsp->hdr.rem_lifetime, @@ -2439,9 +2420,7 @@ void send_lsp(struct isis_circuit *circuit, struct isis_lsp *lsp, } if (IS_DEBUG_UPDATE_PACKETS) { - zlog_debug("ISIS-Upd (%s): Sending %sL%d LSP %s, seq 0x%08" PRIx32 - ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 - "s on %s", + zlog_debug("ISIS-Upd (%s): Sending %sL%d LSP %s, seq 0x%08x, cksum 0x%04hx, lifetime %hus on %s", circuit->area->area_tag, (tx_type == TX_LSP_CIRCUIT_SCOPED) ? "Circuit scoped " : "", diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c index 82f42a86d9..4a884877f0 100644 --- a/isisd/isis_pfpacket.c +++ b/isisd/isis_pfpacket.c @@ -102,8 +102,7 @@ static int isis_multicast_join(int fd, int registerto, int if_num) } #ifdef EXTREME_DEBUG zlog_debug( - "isis_multicast_join(): fd=%d, reg_to=%d, if_num=%d, " - "address = %02x:%02x:%02x:%02x:%02x:%02x", + "isis_multicast_join(): fd=%d, reg_to=%d, if_num=%d, address = %02x:%02x:%02x:%02x:%02x:%02x", fd, registerto, if_num, mreq.mr_address[0], mreq.mr_address[1], mreq.mr_address[2], mreq.mr_address[3], mreq.mr_address[4], mreq.mr_address[5]); @@ -247,16 +246,13 @@ int isis_recv_pdu_bcast(struct isis_circuit *circuit, uint8_t *ssnpa) || (s_addr.sll_ifindex != (int)circuit->interface->ifindex)) { if (bytesread < 0) { zlog_warn( - "isis_recv_packet_bcast(): ifname %s, fd %d, " - "bytesread %d, recvfrom(): %s", + "isis_recv_packet_bcast(): ifname %s, fd %d, bytesread %d, recvfrom(): %s", circuit->interface->name, circuit->fd, bytesread, safe_strerror(errno)); } if (s_addr.sll_ifindex != (int)circuit->interface->ifindex) { zlog_warn( - "packet is received on multiple interfaces: " - "socket interface %d, circuit interface %d, " - "packet type %u", + "packet is received on multiple interfaces: socket interface %d, circuit interface %d, packet type %u", s_addr.sll_ifindex, circuit->interface->ifindex, s_addr.sll_pkttype); } diff --git a/isisd/isis_redist.c b/isisd/isis_redist.c index dc23e8ea49..45e79b46da 100644 --- a/isisd/isis_redist.c +++ b/isisd/isis_redist.c @@ -100,8 +100,7 @@ static void isis_redist_install(struct isis_area *area, int level, if (!er_table) { zlog_warn( - "%s: External reachability table of area %s" - " is not initialized.", + "%s: External reachability table of area %s is not initialized.", __func__, area->area_tag); return; } @@ -134,8 +133,7 @@ static void isis_redist_uninstall(struct isis_area *area, int level, if (!er_table) { zlog_warn( - "%s: External reachability table of area %s" - " is not initialized.", + "%s: External reachability table of area %s is not initialized.", __func__, area->area_tag); return; } @@ -310,8 +308,7 @@ void isis_redist_delete(int type, struct prefix *p, struct prefix_ipv6 *src_p) char buf[BUFSIZ]; prefix2str(p, buf, sizeof(buf)); zlog_warn( - "%s: Got a delete for %s route %s, but that route" - " was never added.", + "%s: Got a delete for %s route %s, but that route was never added.", __func__, zebra_route_string(type), buf); if (ei_node) route_unlock_node(ei_node); @@ -605,8 +602,7 @@ DEFUN (no_isis_redistribute, DEFUN (isis_default_originate, isis_default_originate_cmd, - "default-information originate <ipv4|ipv6>" - " [always] [{metric (0-16777215)|route-map WORD}]", + "default-information originate <ipv4|ipv6> [always] [{metric (0-16777215)|route-map WORD}]", "Control distribution of default information\n" "Distribute a default route\n" "Distribute default route for IPv4\n" diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index fb1aad8c49..c092721ab4 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -877,8 +877,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree, if (lsp == NULL || lsp->hdr.rem_lifetime == 0) zlog_warn( - "ISIS-Spf: No LSP %s found for IS adjacency " - "L%d on %s (ID %u)", + "ISIS-Spf: No LSP %s found for IS adjacency L%d on %s (ID %u)", rawlspid_print(lsp_id), spftree->level, circuit->interface->name, @@ -915,8 +914,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree, /* if no adj, we are the dis or error */ if (!adj && !circuit->u.bc.is_dr[spftree->level - 1]) { zlog_warn( - "ISIS-Spf: No adjacency found from root " - "to L%d DR %s on %s (ID %d)", + "ISIS-Spf: No adjacency found from root to L%d DR %s on %s (ID %d)", spftree->level, rawlspid_print(lsp_id), circuit->interface->name, circuit->circuit_id); @@ -927,8 +925,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree, lsp_id); if (lsp == NULL || lsp->hdr.rem_lifetime == 0) { zlog_warn( - "ISIS-Spf: No lsp (%p) found from root " - "to L%d DR %s on %s (ID %d)", + "ISIS-Spf: No lsp (%p) found from root to L%d DR %s on %s (ID %d)", (void *)lsp, spftree->level, rawlspid_print(lsp_id), circuit->interface->name, @@ -1022,8 +1019,7 @@ static void add_to_paths(struct isis_spftree *spftree, spftree->route_table); else if (IS_DEBUG_SPF_EVENTS) zlog_debug( - "ISIS-Spf: no adjacencies do not install route for " - "%s depth %d dist %d", + "ISIS-Spf: no adjacencies do not install route for %s depth %d dist %d", vid2string(vertex, buff, sizeof(buff)), vertex->depth, vertex->d_N); } @@ -1262,8 +1258,7 @@ int _isis_spf_schedule(struct isis_area *area, int level, if (IS_DEBUG_SPF_EVENTS) { zlog_debug( - "ISIS-Spf (%s) L%d SPF schedule called, lastrun %d sec ago" - " Caller: %s %s:%d", + "ISIS-Spf (%s) L%d SPF schedule called, lastrun %d sec ago Caller: %s %s:%d", area->area_tag, level, diff, func, file, line); } diff --git a/isisd/isis_te.c b/isisd/isis_te.c index 133707d61d..a599909eb8 100644 --- a/isisd/isis_te.c +++ b/isisd/isis_te.c @@ -351,12 +351,12 @@ static void show_ext_sub(struct vty *vty, char *name, sbuf_reset(&buf); if (IS_SUBTLV(ext, EXT_ADM_GRP)) - sbuf_push(&buf, 4, "Administrative Group: 0x%" PRIx32 "\n", + sbuf_push(&buf, 4, "Administrative Group: 0x%x\n", ext->adm_group); if (IS_SUBTLV(ext, EXT_LLRI)) { - sbuf_push(&buf, 4, "Link Local ID: %" PRIu32 "\n", + sbuf_push(&buf, 4, "Link Local ID: %u\n", ext->local_llri); - sbuf_push(&buf, 4, "Link Remote ID: %" PRIu32 "\n", + sbuf_push(&buf, 4, "Link Remote ID: %u\n", ext->remote_llri); } if (IS_SUBTLV(ext, EXT_LOCAL_ADDR)) @@ -394,7 +394,7 @@ static void show_ext_sub(struct vty *vty, char *name, ext->te_metric); if (IS_SUBTLV(ext, EXT_RMT_AS)) sbuf_push(&buf, 4, - "Inter-AS TE Remote AS number: %" PRIu32 "\n", + "Inter-AS TE Remote AS number: %u\n", ext->remote_as); if (IS_SUBTLV(ext, EXT_RMT_IP)) sbuf_push(&buf, 4, @@ -402,19 +402,18 @@ static void show_ext_sub(struct vty *vty, char *name, inet_ntoa(ext->remote_ip)); if (IS_SUBTLV(ext, EXT_DELAY)) sbuf_push(&buf, 4, - "%s Average Link Delay: %" PRIu32 " (micro-sec)\n", + "%s Average Link Delay: %u (micro-sec)\n", IS_ANORMAL(ext->delay) ? "Anomalous" : "Normal", ext->delay); if (IS_SUBTLV(ext, EXT_MM_DELAY)) { - sbuf_push(&buf, 4, "%s Min/Max Link Delay: %" PRIu32 " / %" - PRIu32 " (micro-sec)\n", + sbuf_push(&buf, 4, "%s Min/Max Link Delay: %u / %u (micro-sec)\n", IS_ANORMAL(ext->min_delay) ? "Anomalous" : "Normal", ext->min_delay & TE_EXT_MASK, ext->max_delay & TE_EXT_MASK); } if (IS_SUBTLV(ext, EXT_DELAY_VAR)) sbuf_push(&buf, 4, - "Delay Variation: %" PRIu32 " (micro-sec)\n", + "Delay Variation: %u (micro-sec)\n", ext->delay_var & TE_EXT_MASK); if (IS_SUBTLV(ext, EXT_PKT_LOSS)) sbuf_push(&buf, 4, "%s Link Packet Loss: %g (%%)\n", diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c index f3c9c47691..a1f9cc236f 100644 --- a/isisd/isis_tlvs.c +++ b/isisd/isis_tlvs.c @@ -200,12 +200,12 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts, /* Standard metrics */ if (IS_SUBTLV(exts, EXT_ADM_GRP)) - sbuf_push(buf, indent, "Administrative Group: 0x%" PRIx32 "\n", + sbuf_push(buf, indent, "Administrative Group: 0x%x\n", exts->adm_group); if (IS_SUBTLV(exts, EXT_LLRI)) { - sbuf_push(buf, indent, "Link Local ID: %" PRIu32 "\n", + sbuf_push(buf, indent, "Link Local ID: %u\n", exts->local_llri); - sbuf_push(buf, indent, "Link Remote ID: %" PRIu32 "\n", + sbuf_push(buf, indent, "Link Remote ID: %u\n", exts->remote_llri); } if (IS_SUBTLV(exts, EXT_LOCAL_ADDR)) @@ -243,7 +243,7 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts, exts->te_metric); if (IS_SUBTLV(exts, EXT_RMT_AS)) sbuf_push(buf, indent, - "Inter-AS TE Remote AS number: %" PRIu32 "\n", + "Inter-AS TE Remote AS number: %u\n", exts->remote_as); if (IS_SUBTLV(exts, EXT_RMT_IP)) sbuf_push(buf, indent, @@ -252,19 +252,18 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts, /* Extended metrics */ if (IS_SUBTLV(exts, EXT_DELAY)) sbuf_push(buf, indent, - "%s Average Link Delay: %" PRIu32 " (micro-sec)\n", + "%s Average Link Delay: %u (micro-sec)\n", IS_ANORMAL(exts->delay) ? "Anomalous" : "Normal", exts->delay); if (IS_SUBTLV(exts, EXT_MM_DELAY)) { - sbuf_push(buf, indent, "%s Min/Max Link Delay: %" PRIu32 " / %" - PRIu32 " (micro-sec)\n", + sbuf_push(buf, indent, "%s Min/Max Link Delay: %u / %u (micro-sec)\n", IS_ANORMAL(exts->min_delay) ? "Anomalous" : "Normal", exts->min_delay & TE_EXT_MASK, exts->max_delay & TE_EXT_MASK); } if (IS_SUBTLV(exts, EXT_DELAY_VAR)) { sbuf_push(buf, indent, - "Delay Variation: %" PRIu32 " (micro-sec)\n", + "Delay Variation: %u (micro-sec)\n", exts->delay_var & TE_EXT_MASK); } if (IS_SUBTLV(exts, EXT_PKT_LOSS)) @@ -297,8 +296,7 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts, continue; sbuf_push( buf, indent, - "Adjacency-SID: %" PRIu32 ", Weight: %" PRIu8 - ", Flags: F:%c B:%c, V:%c, L:%c, S:%c, P:%c\n", + "Adjacency-SID: %u, Weight: %hhu, Flags: F:%c B:%c, V:%c, L:%c, S:%c, P:%c\n", adj->sid, adj->weight, adj->flags & EXT_SUBTLV_LINK_ADJ_SID_FFLG ? '1' : '0', @@ -327,9 +325,7 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts, && (lan->family != AF_INET6))) continue; sbuf_push(buf, indent, - "Lan-Adjacency-SID: %" PRIu32 - ", Weight: %" PRIu8 - ", Flags: F:%c B:%c, V:%c, L:%c, S:%c, P:%c\n" + "Lan-Adjacency-SID: %u, Weight: %hhu, Flags: F:%c B:%c, V:%c, L:%c, S:%c, P:%c\n" " Neighbor-ID: %s\n", lan->sid, lan->weight, lan->flags & EXT_SUBTLV_LINK_ADJ_SID_FFLG @@ -542,7 +538,7 @@ static int unpack_item_ext_subtlvs(uint16_t mtid, uint8_t len, struct stream *s, subtlv_type = stream_getc(s); subtlv_len = stream_getc(s); if (subtlv_len > len - sum) { - sbuf_push(log, indent, "TLV %" PRIu8 ": Available data %" PRIu8 " is less than TLV size %u !\n", + sbuf_push(log, indent, "TLV %hhu: Available data %u is less than TLV size %u !\n", subtlv_type, len - sum, subtlv_len); return 1; } @@ -812,11 +808,11 @@ static void format_item_prefix_sid(uint16_t mtid, struct isis_item *i, sbuf_push(buf, indent, "SR Prefix-SID "); if (sid->flags & ISIS_PREFIX_SID_VALUE) { - sbuf_push(buf, 0, "Label: %" PRIu32 ", ", sid->value); + sbuf_push(buf, 0, "Label: %u, ", sid->value); } else { - sbuf_push(buf, 0, "Index: %" PRIu32 ", ", sid->value); + sbuf_push(buf, 0, "Index: %u, ", sid->value); } - sbuf_push(buf, 0, "Algorithm: %" PRIu8 ", ", sid->algorithm); + sbuf_push(buf, 0, "Algorithm: %hhu, ", sid->algorithm); sbuf_push(buf, 0, "Flags:%s%s%s%s%s%s\n", sid->flags & ISIS_PREFIX_SID_READVERTISED ? " READVERTISED" : "", @@ -865,7 +861,7 @@ static int unpack_item_prefix_sid(uint16_t mtid, uint8_t len, struct stream *s, if (len < 5) { sbuf_push(log, indent, - "Not enough data left. (expected 5 or more bytes, got %" PRIu8 ")\n", + "Not enough data left. (expected 5 or more bytes, got %hhu)\n", len); return 1; } @@ -884,8 +880,7 @@ static int unpack_item_prefix_sid(uint16_t mtid, uint8_t len, struct stream *s, : ISIS_SUBTLV_PREFIX_SID_SIZE + 1; if (len != expected_size) { sbuf_push(log, indent, - "TLV size differs from expected size. " - "(expected %u but got %" PRIu8 ")\n", + "TLV size differs from expected size. (expected %u but got %hhu)\n", expected_size, len); return 1; } @@ -961,7 +956,7 @@ static int unpack_subtlv_ipv6_source_prefix(enum isis_tlv_context context, if (tlv_len < 1) { sbuf_push(log, indent, - "Not enough data left. (expected 1 or more bytes, got %" PRIu8 ")\n", + "Not enough data left. (expected 1 or more bytes, got %hhu)\n", tlv_len); return 1; } @@ -976,8 +971,7 @@ static int unpack_subtlv_ipv6_source_prefix(enum isis_tlv_context context, if (tlv_len != 1 + PSIZE(p.prefixlen)) { sbuf_push( log, indent, - "TLV size differs from expected size for the prefixlen. " - "(expected %u but got %" PRIu8 ")\n", + "TLV size differs from expected size for the prefixlen. (expected %u but got %hhu)\n", 1 + PSIZE(p.prefixlen), tlv_len); return 1; } @@ -1149,8 +1143,7 @@ static int unpack_item_area_address(uint16_t mtid, uint8_t len, if (len < 1) { sbuf_push( log, indent, - "Not enough data left. (Expected 1 byte of address length, got %" PRIu8 - ")\n", + "Not enough data left. (Expected 1 byte of address length, got %hhu)\n", len); goto out; } @@ -1159,15 +1152,14 @@ static int unpack_item_area_address(uint16_t mtid, uint8_t len, rv->len = stream_getc(s); if (len < 1 + rv->len) { - sbuf_push(log, indent, "Not enough data left. (Expected %" PRIu8 - " bytes of address, got %" PRIu8 ")\n", + sbuf_push(log, indent, "Not enough data left. (Expected %hhu bytes of address, got %u)\n", rv->len, len - 1); goto out; } if (rv->len < 1 || rv->len > 20) { sbuf_push(log, indent, - "Implausible area address length %" PRIu8 "\n", + "Implausible area address length %hhu\n", rv->len); goto out; } @@ -1199,7 +1191,7 @@ static void format_item_oldstyle_reach(uint16_t mtid, struct isis_item *i, { struct isis_oldstyle_reach *r = (struct isis_oldstyle_reach *)i; - sbuf_push(buf, indent, "IS Reachability: %s (Metric: %" PRIu8 ")\n", + sbuf_push(buf, indent, "IS Reachability: %s (Metric: %hhu)\n", isis_format_id(r->id, 7), r->metric); } @@ -1234,8 +1226,7 @@ static int unpack_item_oldstyle_reach(uint16_t mtid, uint8_t len, if (len < 11) { sbuf_push( log, indent, - "Not enough data left.(Expected 11 bytes of reach information, got %" PRIu8 - ")\n", + "Not enough data left.(Expected 11 bytes of reach information, got %hhu)\n", len); return 1; } @@ -1300,8 +1291,7 @@ static int unpack_item_lan_neighbor(uint16_t mtid, uint8_t len, if (len < 6) { sbuf_push( log, indent, - "Not enough data left.(Expected 6 bytes of mac, got %" PRIu8 - ")\n", + "Not enough data left.(Expected 6 bytes of mac, got %hhu)\n", len); return 1; } @@ -1334,8 +1324,7 @@ static void format_item_lsp_entry(uint16_t mtid, struct isis_item *i, struct isis_lsp_entry *e = (struct isis_lsp_entry *)i; sbuf_push(buf, indent, - "LSP Entry: %s, seq 0x%08" PRIx32 ", cksum 0x%04" PRIx16 - ", lifetime %" PRIu16 "s\n", + "LSP Entry: %s, seq 0x%08x, cksum 0x%04hx, lifetime %hus\n", isis_format_id(e->id, 8), e->seqno, e->checksum, e->rem_lifetime); } @@ -1369,7 +1358,7 @@ static int unpack_item_lsp_entry(uint16_t mtid, uint8_t len, struct stream *s, if (len < 16) { sbuf_push( log, indent, - "Not enough data left. (Expected 16 bytes of LSP info, got %" PRIu8, + "Not enough data left. (Expected 16 bytes of LSP info, got %hhu", len); return 1; } @@ -1467,8 +1456,7 @@ static int unpack_item_extended_reach(uint16_t mtid, uint8_t len, if (len < 11) { sbuf_push(log, indent, - "Not enough data left. (expected 11 or more bytes, got %" - PRIu8 ")\n", + "Not enough data left. (expected 11 or more bytes, got %hhu)\n", len); goto out; } @@ -1480,13 +1468,12 @@ static int unpack_item_extended_reach(uint16_t mtid, uint8_t len, if ((size_t)len < ((size_t)11) + subtlv_len) { sbuf_push(log, indent, - "Not enough data left for subtlv size %" PRIu8 - ", there are only %" PRIu8 " bytes left.\n", + "Not enough data left for subtlv size %hhu, there are only %u bytes left.\n", subtlv_len, len - 11); goto out; } - sbuf_push(log, indent, "Storing %" PRIu8 " bytes of subtlvs\n", + sbuf_push(log, indent, "Storing %hhu bytes of subtlvs\n", subtlv_len); if (subtlv_len) { @@ -1525,7 +1512,7 @@ static void format_item_oldstyle_ip_reach(uint16_t mtid, struct isis_item *i, struct isis_oldstyle_ip_reach *r = (struct isis_oldstyle_ip_reach *)i; char prefixbuf[PREFIX2STR_BUFFER]; - sbuf_push(buf, indent, "IP Reachability: %s (Metric: %" PRIu8 ")\n", + sbuf_push(buf, indent, "IP Reachability: %s (Metric: %hhu)\n", prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)), r->metric); } @@ -1563,8 +1550,7 @@ static int unpack_item_oldstyle_ip_reach(uint16_t mtid, uint8_t len, if (len < 12) { sbuf_push( log, indent, - "Not enough data left.(Expected 12 bytes of reach information, got %" PRIu8 - ")\n", + "Not enough data left.(Expected 12 bytes of reach information, got %hhu)\n", len); return 1; } @@ -1713,8 +1699,7 @@ static int unpack_item_ipv4_address(uint16_t mtid, uint8_t len, if (len < 4) { sbuf_push( log, indent, - "Not enough data left.(Expected 4 bytes of IPv4 address, got %" PRIu8 - ")\n", + "Not enough data left.(Expected 4 bytes of IPv4 address, got %hhu)\n", len); return 1; } @@ -1775,8 +1760,7 @@ static int unpack_item_ipv6_address(uint16_t mtid, uint8_t len, if (len < 16) { sbuf_push( log, indent, - "Not enough data left.(Expected 16 bytes of IPv6 address, got %" PRIu8 - ")\n", + "Not enough data left.(Expected 16 bytes of IPv6 address, got %hhu)\n", len); return 1; } @@ -1847,8 +1831,7 @@ static int unpack_item_mt_router_info(uint16_t mtid, uint8_t len, if (len < 2) { sbuf_push( log, indent, - "Not enough data left.(Expected 2 bytes of MT info, got %" PRIu8 - ")\n", + "Not enough data left.(Expected 2 bytes of MT info, got %hhu)\n", len); return 1; } @@ -2025,7 +2008,7 @@ static int unpack_item_extended_ip_reach(uint16_t mtid, uint8_t len, consume = 5; if (len < consume) { sbuf_push(log, indent, - "Not enough data left. (expected 5 or more bytes, got %" PRIu8 ")\n", + "Not enough data left. (expected 5 or more bytes, got %hhu)\n", len); goto out; } @@ -2075,8 +2058,7 @@ static int unpack_item_extended_ip_reach(uint16_t mtid, uint8_t len, consume += subtlv_len; if (len < consume) { sbuf_push(log, indent, - "Expected %" PRIu8 - " bytes of subtlvs, but only %u bytes available.\n", + "Expected %hhu bytes of subtlvs, but only %u bytes available.\n", subtlv_len, len - 6 - PSIZE(rv->prefix.prefixlen)); goto out; @@ -2209,7 +2191,7 @@ static void format_tlv_spine_leaf(const struct isis_spine_leaf *spine_leaf, if (spine_leaf->tier == ISIS_TIER_UNDEFINED) { sbuf_push(buf, indent, " Tier: undefined\n"); } else { - sbuf_push(buf, indent, " Tier: %" PRIu8 "\n", + sbuf_push(buf, indent, " Tier: %hhu\n", spine_leaf->tier); } } @@ -2342,14 +2324,14 @@ static void format_tlv_threeway_adj(const struct isis_threeway_adj *threeway_adj sbuf_push(buf, indent, " State: %s (%d)\n", isis_threeway_state_name(threeway_adj->state), threeway_adj->state); - sbuf_push(buf, indent, " Extended Local Circuit ID: %" PRIu32 "\n", + sbuf_push(buf, indent, " Extended Local Circuit ID: %u\n", threeway_adj->local_circuit_id); if (!threeway_adj->neighbor_set) return; sbuf_push(buf, indent, " Neighbor System ID: %s\n", isis_format_id(threeway_adj->neighbor_id, 6)); - sbuf_push(buf, indent, " Neighbor Extended Circuit ID: %" PRIu32 "\n", + sbuf_push(buf, indent, " Neighbor Extended Circuit ID: %u\n", threeway_adj->neighbor_circuit_id); } @@ -2508,8 +2490,7 @@ static int unpack_item_ipv6_reach(uint16_t mtid, uint8_t len, struct stream *s, consume = 6; if (len < consume) { sbuf_push(log, indent, - "Not enough data left. (expected 6 or more bytes, got %" - PRIu8 ")\n", + "Not enough data left. (expected 6 or more bytes, got %hhu)\n", len); goto out; } @@ -2561,8 +2542,7 @@ static int unpack_item_ipv6_reach(uint16_t mtid, uint8_t len, struct stream *s, consume += subtlv_len; if (len < consume) { sbuf_push(log, indent, - "Expected %" PRIu8 - " bytes of subtlvs, but only %u bytes available.\n", + "Expected %hhu bytes of subtlvs, but only %u bytes available.\n", subtlv_len, len - 6 - PSIZE(rv->prefix.prefixlen)); goto out; @@ -2912,12 +2892,12 @@ static void format_item_auth(uint16_t mtid, struct isis_item *i, case ISIS_PASSWD_TYPE_HMAC_MD5: for (unsigned int j = 0; j < 16; j++) { snprintf(obuf + 2 * j, sizeof(obuf) - 2 * j, - "%02" PRIx8, auth->value[j]); + "%02hhx", auth->value[j]); } sbuf_push(buf, indent, " HMAC-MD5: %s\n", obuf); break; default: - sbuf_push(buf, indent, " Unknown (%" PRIu8 ")\n", auth->type); + sbuf_push(buf, indent, " Unknown (%hhu)\n", auth->type); break; } } @@ -2963,8 +2943,7 @@ static int unpack_item_auth(uint16_t mtid, uint8_t len, struct stream *s, if (len < 1) { sbuf_push( log, indent, - "Not enough data left.(Expected 1 bytes of auth type, got %" PRIu8 - ")\n", + "Not enough data left.(Expected 1 bytes of auth type, got %hhu)\n", len); return 1; } @@ -2977,8 +2956,7 @@ static int unpack_item_auth(uint16_t mtid, uint8_t len, struct stream *s, if (rv->type == ISIS_PASSWD_TYPE_HMAC_MD5 && rv->length != 16) { sbuf_push( log, indent, - "Unexpected auth length for HMAC-MD5 (expected 16, got %" PRIu8 - ")\n", + "Unexpected auth length for HMAC-MD5 (expected 16, got %hhu)\n", rv->length); XFREE(MTYPE_ISIS_TLV, rv); return 1; @@ -3062,8 +3040,7 @@ static int unpack_tlv_purge_originator(enum isis_tlv_context context, sbuf_push(log, indent, "Unpacking Purge Originator Identification TLV...\n"); if (tlv_len < 7) { - sbuf_push(log, indent, "Not enough data left. (Expected at least 7 bytes, got %" - PRIu8 ")\n", tlv_len); + sbuf_push(log, indent, "Not enough data left. (Expected at least 7 bytes, got %hhu)\n", tlv_len); return 1; } @@ -3074,8 +3051,7 @@ static int unpack_tlv_purge_originator(enum isis_tlv_context context, } else if (number_of_ids == 2) { poi.sender_set = true; } else { - sbuf_push(log, indent, "Got invalid value for number of system IDs: %" - PRIu8 ")\n", number_of_ids); + sbuf_push(log, indent, "Got invalid value for number of system IDs: %hhu)\n", number_of_ids); return 1; } @@ -4019,7 +3995,7 @@ static int unpack_tlv_unknown(enum isis_tlv_context context, uint8_t tlv_type, { stream_forward_getp(s, tlv_len); sbuf_push(log, indent, - "Skipping unknown TLV %" PRIu8 " (%" PRIu8 " bytes)\n", + "Skipping unknown TLV %hhu (%hhu bytes)\n", tlv_type, tlv_len); return 0; } @@ -4045,12 +4021,12 @@ static int unpack_tlv(enum isis_tlv_context context, size_t avail_len, tlv_len = stream_getc(stream); sbuf_push(log, indent + 2, - "Found TLV of type %" PRIu8 " and len %" PRIu8 ".\n", + "Found TLV of type %hhu and len %hhu.\n", tlv_type, tlv_len); if (avail_len < ((size_t)tlv_len) + 2) { sbuf_push(log, indent + 2, - "Available data %zu too short for claimed TLV len %" PRIu8 ".\n", + "Available data %zu too short for claimed TLV len %hhu.\n", avail_len - 2, tlv_len); return 1; } @@ -4106,8 +4082,7 @@ int isis_unpack_tlvs(size_t avail_len, struct stream *stream, sbuf_reset(&logbuf); if (avail_len > STREAM_READABLE(stream)) { sbuf_push(&logbuf, indent, - "Stream doesn't contain sufficient data. " - "Claimed %zu, available %zu\n", + "Stream doesn't contain sufficient data. Claimed %zu, available %zu\n", avail_len, STREAM_READABLE(stream)); return 1; } diff --git a/isisd/isis_vty_fabricd.c b/isisd/isis_vty_fabricd.c index 09b8d28258..a574c5bd3f 100644 --- a/isisd/isis_vty_fabricd.c +++ b/isisd/isis_vty_fabricd.c @@ -136,8 +136,7 @@ static void lsp_print_flooding(struct vty *vty, struct isis_lsp *lsp) vty_out(vty, "%s ago)\n", buf); if (lsp->flooding_circuit_scoped) { - vty_out(vty, " Received as circuit-scoped LSP, so not " - "flooded.\n"); + vty_out(vty, " Received as circuit-scoped LSP, so not flooded.\n"); return; } @@ -316,8 +315,8 @@ DEFUN (isis_bfd, return CMD_SUCCESS; } - isis_bfd_circuit_param_set(circuit, BFD_DEF_MIN_RX, - BFD_DEF_MIN_TX, BFD_DEF_DETECT_MULT, true); + isis_bfd_circuit_param_set(circuit, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, + BFD_DEF_DETECT_MULT, NULL, true); return CMD_SUCCESS; } @@ -437,8 +436,7 @@ isis_vty_lsp_gen_interval_set(struct vty *vty, int level, uint16_t interval) if (interval >= area->lsp_refresh[lvl - 1]) { vty_out(vty, - "LSP gen interval %us must be less than " - "the LSP refresh interval %us\n", + "LSP gen interval %us must be less than the LSP refresh interval %us\n", interval, area->lsp_refresh[lvl - 1]); return CMD_WARNING_CONFIG_FAILED; } @@ -488,15 +486,13 @@ isis_vty_lsp_refresh_set(struct vty *vty, int level, uint16_t interval) continue; if (interval <= area->lsp_gen_interval[lvl - 1]) { vty_out(vty, - "LSP refresh interval %us must be greater than " - "the configured LSP gen interval %us\n", + "LSP refresh interval %us must be greater than the configured LSP gen interval %us\n", interval, area->lsp_gen_interval[lvl - 1]); return CMD_WARNING_CONFIG_FAILED; } if (interval > (area->max_lsp_lifetime[lvl - 1] - 300)) { vty_out(vty, - "LSP refresh interval %us must be less than " - "the configured LSP lifetime %us less 300\n", + "LSP refresh interval %us must be less than the configured LSP lifetime %us less 300\n", interval, area->max_lsp_lifetime[lvl - 1]); return CMD_WARNING_CONFIG_FAILED; } @@ -546,20 +542,17 @@ isis_vty_max_lsp_lifetime_set(struct vty *vty, int level, uint16_t interval) if (refresh_interval < area->lsp_refresh[lvl - 1]) { vty_out(vty, - "Level %d Max LSP lifetime %us must be 300s greater than " - "the configured LSP refresh interval %us\n", + "Level %d Max LSP lifetime %us must be 300s greater than the configured LSP refresh interval %us\n", lvl, interval, area->lsp_refresh[lvl - 1]); vty_out(vty, - "Automatically reducing level %d LSP refresh interval " - "to %us\n", + "Automatically reducing level %d LSP refresh interval to %us\n", lvl, refresh_interval); set_refresh_interval[lvl - 1] = 1; if (refresh_interval <= area->lsp_gen_interval[lvl - 1]) { vty_out(vty, - "LSP refresh interval %us must be greater than " - "the configured LSP gen interval %us\n", + "LSP refresh interval %us must be greater than the configured LSP gen interval %us\n", refresh_interval, area->lsp_gen_interval[lvl - 1]); return CMD_WARNING_CONFIG_FAILED; @@ -845,8 +838,7 @@ DEFUN (isis_metric, if (circuit->area && circuit->area->oldmetric == 1 && met > MAX_NARROW_LINK_METRIC) { vty_out(vty, - "Invalid metric %d - should be <0-63> " - "when narrow metric type enabled\n", + "Invalid metric %d - should be <0-63> when narrow metric type enabled\n", met); return CMD_WARNING_CONFIG_FAILED; } @@ -855,8 +847,7 @@ DEFUN (isis_metric, if (circuit->area && circuit->area->newmetric == 1 && met > MAX_WIDE_LINK_METRIC) { vty_out(vty, - "Invalid metric %d - should be <0-16777215> " - "when wide metric type enabled\n", + "Invalid metric %d - should be <0-16777215> when wide metric type enabled\n", met); return CMD_WARNING_CONFIG_FAILED; } diff --git a/isisd/isisd.c b/isisd/isisd.c index 53e48bd1cf..6f126b7faf 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -1344,7 +1344,7 @@ DEFUN (show_isis_summary, if (tier == ISIS_TIER_UNDEFINED) vty_out(vty, " Tier: undefined\n"); else - vty_out(vty, " Tier: %" PRIu8 "\n", tier); + vty_out(vty, " Tier: %hhu\n", tier); } if (listcount(area->area_addrs) > 0) { diff --git a/ldpd/hello.c b/ldpd/hello.c index a8d6e58cda..ac24704bca 100644 --- a/ldpd/hello.c +++ b/ldpd/hello.c @@ -234,8 +234,7 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af, * check)". */ if (flags & F_HELLO_TARGETED) { - log_debug("%s: lsr-id %s: invalid targeted hello " - "transport address %s", __func__, inet_ntoa(lsr_id), + log_debug("%s: lsr-id %s: invalid targeted hello transport address %s", __func__, inet_ntoa(lsr_id), log_addr(af, &trans_addr)); return; } @@ -250,8 +249,7 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af, * targeted LDP Hello packet's source or destination addresses". */ if (af == AF_INET6 && IN6_IS_SCOPE_EMBED(&src->v6)) { - log_debug("%s: lsr-id %s: targeted hello with " - "link-local source address", __func__, + log_debug("%s: lsr-id %s: targeted hello with link-local source address", __func__, inet_ntoa(lsr_id)); return; } @@ -318,8 +316,7 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af, * send a fatal Notification message with status code of * 'Transport Connection Mismatch' and reset the session". */ - log_debug("%s: lsr-id %s: remote transport preference does not " - "match the local preference", __func__, inet_ntoa(lsr_id)); + log_debug("%s: lsr-id %s: remote transport preference does not match the local preference", __func__, inet_ntoa(lsr_id)); if (nbr) session_shutdown(nbr, S_TRANS_MISMTCH, msg->id, msg->type); @@ -359,8 +356,7 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af, if (nbr && nbr->af == af && (ldp_addrcmp(af, &nbr->raddr, &trans_addr) || nbr->raddr_scope != scope_id)) { - log_warnx("%s: lsr-id %s: hello packet advertising a different " - "transport address", __func__, inet_ntoa(lsr_id)); + log_warnx("%s: lsr-id %s: hello packet advertising a different transport address", __func__, inet_ntoa(lsr_id)); if (adj) adj_del(adj, S_SHUTDOWN); return; @@ -368,8 +364,7 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af, if (nbr == NULL) { nbrt = nbr_find_addr(af, &trans_addr); if (nbrt) { - log_debug("%s: transport address %s is already being " - "used by lsr-id %s", __func__, log_addr(af, + log_debug("%s: transport address %s is already being used by lsr-id %s", __func__, log_addr(af, &trans_addr), inet_ntoa(nbrt->id)); if (adj) adj_del(adj, S_SHUTDOWN); diff --git a/ldpd/init.c b/ldpd/init.c index 8b2abe85e5..30b78315f9 100644 --- a/ldpd/init.c +++ b/ldpd/init.c @@ -146,8 +146,7 @@ recv_init(struct nbr *nbr, char *buf, uint16_t len) nbr->flags |= F_NBR_CAP_DYNAMIC; - log_debug("%s: lsr-id %s announced the Dynamic " - "Capability Announcement capability", __func__, + log_debug("%s: lsr-id %s announced the Dynamic Capability Announcement capability", __func__, inet_ntoa(nbr->id)); break; case TLV_TYPE_TWCARD_CAP: @@ -166,8 +165,7 @@ recv_init(struct nbr *nbr, char *buf, uint16_t len) nbr->flags |= F_NBR_CAP_TWCARD; - log_debug("%s: lsr-id %s announced the Typed Wildcard " - "FEC capability", __func__, inet_ntoa(nbr->id)); + log_debug("%s: lsr-id %s announced the Typed Wildcard FEC capability", __func__, inet_ntoa(nbr->id)); break; case TLV_TYPE_UNOTIF_CAP: if (tlv_len != CAP_TLV_UNOTIF_LEN) { @@ -185,8 +183,7 @@ recv_init(struct nbr *nbr, char *buf, uint16_t len) nbr->flags |= F_NBR_CAP_UNOTIF; - log_debug("%s: lsr-id %s announced the Unrecognized " - "Notification capability", __func__, + log_debug("%s: lsr-id %s announced the Unrecognized Notification capability", __func__, inet_ntoa(nbr->id)); break; default: @@ -321,8 +318,7 @@ recv_capability(struct nbr *nbr, char *buf, uint16_t len) else nbr->flags &= ~F_NBR_CAP_TWCARD; - log_debug("%s: lsr-id %s %s the Typed Wildcard FEC " - "capability", __func__, inet_ntoa(nbr->id), + log_debug("%s: lsr-id %s %s the Typed Wildcard FEC capability", __func__, inet_ntoa(nbr->id), (enable) ? "announced" : "withdrew"); break; case TLV_TYPE_UNOTIF_CAP: @@ -346,8 +342,7 @@ recv_capability(struct nbr *nbr, char *buf, uint16_t len) else nbr->flags &= ~F_NBR_CAP_UNOTIF; - log_debug("%s: lsr-id %s %s the Unrecognized " - "Notification capability", __func__, + log_debug("%s: lsr-id %s %s the Unrecognized Notification capability", __func__, inet_ntoa(nbr->id), (enable) ? "announced" : "withdrew"); break; diff --git a/ldpd/interface.c b/ldpd/interface.c index c7d6dea518..371c7d0bb1 100644 --- a/ldpd/interface.c +++ b/ldpd/interface.c @@ -528,8 +528,7 @@ if_leave_ipv4_group(struct iface *iface, struct in_addr *addr) if (setsockopt_ipv4_multicast(global.ipv4.ldp_disc_socket, IP_DROP_MEMBERSHIP, if_addr, addr->s_addr, iface->ifindex) < 0) { - log_warn("%s: error IP_DROP_MEMBERSHIP, interface %s " - "address %s", __func__, iface->name, inet_ntoa(*addr)); + log_warn("%s: error IP_DROP_MEMBERSHIP, interface %s address %s", __func__, iface->name, inet_ntoa(*addr)); return (-1); } diff --git a/ldpd/l2vpn.c b/ldpd/l2vpn.c index 0d479e77ba..2c68f3edbd 100644 --- a/ldpd/l2vpn.c +++ b/ldpd/l2vpn.c @@ -294,6 +294,16 @@ l2vpn_pw_reset(struct l2vpn_pw *pw) pw->flags |= F_PW_STATUSTLV; else pw->flags &= ~F_PW_STATUSTLV; + + if (pw->flags & F_PW_STATUSTLV_CONF) { + struct fec_node *fn; + struct fec fec; + l2vpn_pw_fec(pw, &fec); + fn = (struct fec_node *)fec_find(&ft, &fec); + if (fn) + pw->remote_status = fn->pw_remote_status; + } + } int @@ -433,6 +443,8 @@ l2vpn_recv_pw_status(struct lde_nbr *ln, struct notify_msg *nm) /* unknown fec */ return; + fn->pw_remote_status = nm->pw_status; + pw = (struct l2vpn_pw *) fn->data; if (pw == NULL) return; diff --git a/ldpd/lde.c b/ldpd/lde.c index afcbe6cd44..734c1ea230 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -296,7 +296,7 @@ lde_dispatch_imsg(struct thread *thread) switch (imsg.hdr.type) { case IMSG_LABEL_MAPPING: - lde_check_mapping(map, ln); + lde_check_mapping(map, ln, 1); break; case IMSG_LABEL_REQUEST: lde_check_request(map, ln); @@ -325,8 +325,7 @@ lde_dispatch_imsg(struct thread *thread) break; } if (lde_address_add(ln, lde_addr) < 0) { - log_debug("%s: cannot add address %s, it " - "already exists", __func__, + log_debug("%s: cannot add address %s, it already exists", __func__, log_addr(lde_addr->af, &lde_addr->addr)); } break; @@ -343,8 +342,7 @@ lde_dispatch_imsg(struct thread *thread) break; } if (lde_address_del(ln, lde_addr) < 0) { - log_debug("%s: cannot delete address %s, it " - "does not exist", __func__, + log_debug("%s: cannot delete address %s, it does not exist", __func__, log_addr(lde_addr->af, &lde_addr->addr)); } break; @@ -382,8 +380,7 @@ lde_dispatch_imsg(struct thread *thread) fatalx("lde_dispatch_imsg: wrong imsg len"); if (lde_nbr_find(imsg.hdr.peerid)) - fatalx("lde_dispatch_imsg: " - "neighbor already exists"); + fatalx("lde_dispatch_imsg: neighbor already exists"); lde_nbr_new(imsg.hdr.peerid, imsg.data); break; case IMSG_NEIGHBOR_DOWN: @@ -534,13 +531,11 @@ lde_dispatch_parent(struct thread *thread) break; case IMSG_SOCKET_IPC: if (iev_ldpe) { - log_warnx("%s: received unexpected imsg fd " - "to ldpe", __func__); + log_warnx("%s: received unexpected imsg fd to ldpe", __func__); break; } if ((fd = imsg.fd) == -1) { - log_warnx("%s: expected to receive imsg fd to " - "ldpe but didn't receive any", __func__); + log_warnx("%s: expected to receive imsg fd to ldpe but didn't receive any", __func__); break; } @@ -975,8 +970,7 @@ lde_send_labelmapping(struct lde_nbr *ln, struct fec_node *fn, int single) lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec); if (lw) { if (!fec_find(&ln->sent_map_pending, &fn->fec)) { - debug_evt("%s: FEC %s: scheduling to send label " - "mapping later (waiting for pending label release)", + debug_evt("%s: FEC %s: scheduling to send label mapping later (waiting for pending label release)", __func__, log_fec(&fn->fec)); lde_map_pending_add(ln, fn); } diff --git a/ldpd/lde.h b/ldpd/lde.h index 2895e00ae5..9e6db3a90b 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -125,6 +125,9 @@ struct fec_node { struct lde_map_head upstream; /* sent mappings */ uint32_t local_label; + + uint32_t pw_remote_status; + void *data; /* fec specific data */ }; @@ -209,7 +212,7 @@ void lde_kernel_insert(struct fec *, int, union ldpd_addr *, void lde_kernel_remove(struct fec *, int, union ldpd_addr *, ifindex_t, uint8_t, unsigned short); void lde_kernel_update(struct fec *); -void lde_check_mapping(struct map *, struct lde_nbr *); +void lde_check_mapping(struct map *, struct lde_nbr *, int); void lde_check_request(struct map *, struct lde_nbr *); void lde_check_request_wcard(struct map *, struct lde_nbr *); void lde_check_release(struct map *, struct lde_nbr *); diff --git a/ldpd/lde_lib.c b/ldpd/lde_lib.c index 8f524e0aa9..71fb0c7bf2 100644 --- a/ldpd/lde_lib.c +++ b/ldpd/lde_lib.c @@ -267,6 +267,9 @@ fec_add(struct fec *fec) RB_INIT(lde_map_head, &fn->downstream); LIST_INIT(&fn->nexthops); + if (fec->type == FEC_TYPE_PWID) + fn->pw_remote_status = PW_FORWARDING; + if (fec_insert(&ft, &fn->fec)) log_warnx("failed to add %s to ft tree", log_fec(&fn->fec)); @@ -455,13 +458,13 @@ lde_kernel_update(struct fec *fec) me = (struct lde_map *)fec_find(&ln->recv_map, &fn->fec); if (me) /* FEC.5 */ - lde_check_mapping(&me->map, ln); + lde_check_mapping(&me->map, ln, 0); } } } void -lde_check_mapping(struct map *map, struct lde_nbr *ln) +lde_check_mapping(struct map *map, struct lde_nbr *ln, int rcvd_label_mapping) { struct fec fec; struct fec_node *fn; @@ -507,8 +510,12 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln) lde_req_del(ln, lre, 1); /* RFC 4447 control word and status tlv negotiation */ - if (map->type == MAP_TYPE_PWID && l2vpn_pw_negotiate(ln, fn, map)) + if (map->type == MAP_TYPE_PWID && l2vpn_pw_negotiate(ln, fn, map)) { + if (rcvd_label_mapping && map->flags & F_MAP_PW_STATUS) + fn->pw_remote_status = map->pw_status; + return; + } /* * LMp.3 - LMp.8: loop detection - unnecessary for frame-mode @@ -570,8 +577,10 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln) pw->remote_group = map->fec.pwid.group_id; if (map->flags & F_MAP_PW_IFMTU) pw->remote_mtu = map->fec.pwid.ifmtu; - if (map->flags & F_MAP_PW_STATUS) + if (rcvd_label_mapping && map->flags & F_MAP_PW_STATUS) { pw->remote_status = map->pw_status; + fn->pw_remote_status = map->pw_status; + } else pw->remote_status = PW_FORWARDING; fnh->remote_label = map->label; diff --git a/ldpd/ldp_vty_conf.c b/ldpd/ldp_vty_conf.c index 3abd0817a8..03dee23b47 100644 --- a/ldpd/ldp_vty_conf.c +++ b/ldpd/ldp_vty_conf.c @@ -292,12 +292,10 @@ ldp_config_write(struct vty *vty) if (nbrp->flags & F_NBRP_GTSM) { if (nbrp->gtsm_enabled) - vty_out (vty, " neighbor %s ttl-security hops " - "%u\n", inet_ntoa(nbrp->lsr_id), + vty_out (vty, " neighbor %s ttl-security hops %u\n", inet_ntoa(nbrp->lsr_id), nbrp->gtsm_hops); else - vty_out (vty, " neighbor %s ttl-security " - "disable\n",inet_ntoa(nbrp->lsr_id)); + vty_out (vty, " neighbor %s ttl-security disable\n",inet_ntoa(nbrp->lsr_id)); } if (nbrp->auth.method == AUTH_MD5SIG) @@ -1079,8 +1077,7 @@ ldp_vty_neighbor_password(struct vty *vty, const char *negate, struct in_addr ls password_len = strlcpy(nbrp->auth.md5key, password_str, sizeof(nbrp->auth.md5key)); if (password_len >= sizeof(nbrp->auth.md5key)) - vty_out(vty, "%% password has been truncated to %zu " - "characters.", sizeof(nbrp->auth.md5key) - 1); + vty_out(vty, "%% password has been truncated to %zu characters.", sizeof(nbrp->auth.md5key) - 1); nbrp->auth.md5key_len = strlen(nbrp->auth.md5key); nbrp->auth.method = AUTH_MD5SIG; } diff --git a/ldpd/ldp_vty_exec.c b/ldpd/ldp_vty_exec.c index 7bc2623eb3..d8ed5ccccc 100644 --- a/ldpd/ldp_vty_exec.c +++ b/ldpd/ldp_vty_exec.c @@ -584,8 +584,7 @@ show_nbr_detail_msg(struct vty *vty, struct imsg *imsg, log_addr(nbr->af, &nbr->raddr),ntohs(nbr->rport)); vty_out (vty, " Authentication: %s\n", (nbr->auth_method == AUTH_MD5SIG) ? "TCP MD5 Signature" : "none"); - vty_out(vty, " Session Holdtime: %u secs; " - "KeepAlive interval: %u secs\n", nbr->holdtime, + vty_out(vty, " Session Holdtime: %u secs; KeepAlive interval: %u secs\n", nbr->holdtime, nbr->holdtime / KEEPALIVE_PER_PERIOD); vty_out(vty, " State: %s; Downstream-Unsolicited\n", nbr_state_name(nbr->nbr_state)); @@ -1252,8 +1251,7 @@ show_l2vpn_binding_msg(struct vty *vty, struct imsg *imsg, if (pw->local_label != NO_LABEL) { vty_out (vty, " Local Label: %u\n", pw->local_label); - vty_out (vty, "%-8sCbit: %u, VC Type: %s, " - "GroupID: %u\n", "", pw->local_cword, + vty_out (vty, "%-8sCbit: %u, VC Type: %s, GroupID: %u\n", "", pw->local_cword, pw_type_name(pw->type),pw->local_gid); vty_out (vty, "%-8sMTU: %u\n", "",pw->local_ifmtu); vty_out (vty, "%-8sLast failure: %s\n", "", @@ -1265,8 +1263,7 @@ show_l2vpn_binding_msg(struct vty *vty, struct imsg *imsg, if (pw->remote_label != NO_LABEL) { vty_out (vty, " Remote Label: %u\n", pw->remote_label); - vty_out (vty, "%-8sCbit: %u, VC Type: %s, " - "GroupID: %u\n", "", pw->remote_cword, + vty_out (vty, "%-8sCbit: %u, VC Type: %s, GroupID: %u\n", "", pw->remote_cword, pw_type_name(pw->type),pw->remote_gid); vty_out (vty, "%-8sMTU: %u\n", "",pw->remote_ifmtu); } else diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index e3b6f4dfcc..927c3a3c03 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -662,23 +662,19 @@ main_dispatch_lde(struct thread *thread) switch (imsg.hdr.type) { case IMSG_KPW_ADD: if (kmpw_add(imsg.data)) - log_warnx("%s: error adding " - "pseudowire", __func__); + log_warnx("%s: error adding pseudowire", __func__); break; case IMSG_KPW_DELETE: if (kmpw_del(imsg.data)) - log_warnx("%s: error deleting " - "pseudowire", __func__); + log_warnx("%s: error deleting pseudowire", __func__); break; case IMSG_KPW_SET: if (kmpw_set(imsg.data)) - log_warnx("%s: error setting " - "pseudowire", __func__); + log_warnx("%s: error setting pseudowire", __func__); break; case IMSG_KPW_UNSET: if (kmpw_unset(imsg.data)) - log_warnx("%s: error unsetting " - "pseudowire", __func__); + log_warnx("%s: error unsetting pseudowire", __func__); break; } break; @@ -857,8 +853,7 @@ main_imsg_send_net_socket(int af, enum socket_type type) fd = ldp_create_socket(af, type); if (fd == -1) { - log_warnx("%s: failed to create %s socket for address-family " - "%s", __func__, socket_name(type), af_name(af)); + log_warnx("%s: failed to create %s socket for address-family %s", __func__, socket_name(type), af_name(af)); return; } diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index 3f0a4fd33e..655313bf16 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -355,13 +355,11 @@ ldpe_dispatch_main(struct thread *thread) break; case IMSG_SOCKET_IPC: if (iev_lde) { - log_warnx("%s: received unexpected imsg fd " - "to lde", __func__); + log_warnx("%s: received unexpected imsg fd to lde", __func__); break; } if ((fd = imsg.fd) == -1) { - log_warnx("%s: expected to receive imsg fd to " - "lde but didn't receive any", __func__); + log_warnx("%s: expected to receive imsg fd to lde but didn't receive any", __func__); break; } @@ -617,8 +615,7 @@ ldpe_dispatch_lde(struct thread *thread) nbr = nbr_find_peerid(imsg.hdr.peerid); if (nbr == NULL) { - log_debug("ldpe_dispatch_lde: cannot find " - "neighbor"); + log_debug("ldpe_dispatch_lde: cannot find neighbor"); break; } if (nbr->state != NBR_STA_OPER) @@ -645,8 +642,7 @@ ldpe_dispatch_lde(struct thread *thread) case IMSG_WITHDRAW_ADD_END: nbr = nbr_find_peerid(imsg.hdr.peerid); if (nbr == NULL) { - log_debug("ldpe_dispatch_lde: cannot find " - "neighbor"); + log_debug("ldpe_dispatch_lde: cannot find neighbor"); break; } if (nbr->state != NBR_STA_OPER) @@ -679,8 +675,7 @@ ldpe_dispatch_lde(struct thread *thread) nbr = nbr_find_peerid(imsg.hdr.peerid); if (nbr == NULL) { - log_debug("ldpe_dispatch_lde: cannot find " - "neighbor"); + log_debug("ldpe_dispatch_lde: cannot find neighbor"); break; } if (nbr->state != NBR_STA_OPER) @@ -700,8 +695,7 @@ ldpe_dispatch_lde(struct thread *thread) case IMSG_NBR_SHUTDOWN: nbr = nbr_find_peerid(imsg.hdr.peerid); if (nbr == NULL) { - log_debug("ldpe_dispatch_lde: cannot find " - "neighbor"); + log_debug("ldpe_dispatch_lde: cannot find neighbor"); break; } if (nbr->state != NBR_STA_OPER) diff --git a/ldpd/neighbor.c b/ldpd/neighbor.c index 1aa53151e6..6143beb6b9 100644 --- a/ldpd/neighbor.c +++ b/ldpd/neighbor.c @@ -143,8 +143,7 @@ nbr_fsm(struct nbr *nbr, enum nbr_event event) if (nbr_fsm_tbl[i].state == -1) { /* event outside of the defined fsm, ignore it. */ - log_warnx("%s: lsr-id %s, event %s not expected in " - "state %s", __func__, inet_ntoa(nbr->id), + log_warnx("%s: lsr-id %s, event %s not expected in state %s", __func__, inet_ntoa(nbr->id), nbr_event_names[event], nbr_state_name(old_state)); return (0); } @@ -153,8 +152,7 @@ nbr_fsm(struct nbr *nbr, enum nbr_event event) nbr->state = new_state; if (old_state != nbr->state) { - log_debug("%s: event %s resulted in action %s and " - "changing state for lsr-id %s from %s to %s", + log_debug("%s: event %s resulted in action %s and changing state for lsr-id %s from %s to %s", __func__, nbr_event_names[event], nbr_action_names[nbr_fsm_tbl[i].action], inet_ntoa(nbr->id), nbr_state_name(old_state), diff --git a/ldpd/notification.c b/ldpd/notification.c index 6de26107e6..93be9d3cb0 100644 --- a/ldpd/notification.c +++ b/ldpd/notification.c @@ -309,8 +309,7 @@ void log_msg_notification(int out, struct nbr *nbr, struct notify_msg *nm) { if (nm->status_code & STATUS_FATAL) { - debug_msg(out, "notification: lsr-id %s, status %s " - "(fatal error)", inet_ntoa(nbr->id), + debug_msg(out, "notification: lsr-id %s, status %s (fatal error)", inet_ntoa(nbr->id), status_code_name(nm->status_code)); return; } diff --git a/ldpd/packet.c b/ldpd/packet.c index dfab30eeb3..c00008d120 100644 --- a/ldpd/packet.c +++ b/ldpd/packet.c @@ -77,8 +77,7 @@ send_packet(int fd, int af, union ldpd_addr *dst, struct iface_af *ia, if (ia && IN_MULTICAST(ntohl(dst->v4.s_addr))) { /* set outgoing interface for multicast traffic */ if (sock_set_ipv4_mcast(ia->iface) == -1) { - log_debug("%s: error setting multicast " - "interface, %s", __func__, ia->iface->name); + log_debug("%s: error setting multicast interface, %s", __func__, ia->iface->name); return (-1); } } @@ -87,8 +86,7 @@ send_packet(int fd, int af, union ldpd_addr *dst, struct iface_af *ia, if (ia && IN6_IS_ADDR_MULTICAST(&dst->v6)) { /* set outgoing interface for multicast traffic */ if (sock_set_ipv6_mcast(ia->iface) == -1) { - log_debug("%s: error setting multicast " - "interface, %s", __func__, ia->iface->name); + log_debug("%s: error setting multicast interface, %s", __func__, ia->iface->name); return (-1); } } @@ -368,8 +366,7 @@ session_accept(struct thread *thread) return (0); } if (nbr->state != NBR_STA_PRESENT) { - log_debug("%s: lsr-id %s: rejecting additional transport " - "connection", __func__, inet_ntoa(nbr->id)); + log_debug("%s: lsr-id %s: rejecting additional transport connection", __func__, inet_ntoa(nbr->id)); close(newfd); return (0); } @@ -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, @@ -143,8 +152,7 @@ void bfd_peer_sendmsg(struct zclient *zclient, struct bfd_info *bfd_info, if (!zclient || zclient->sock < 0) { if (bfd_debug) zlog_debug( - "%s: Can't send BFD peer register, Zebra client not " - "established", + "%s: Can't send BFD peer register, Zebra client not established", __func__); return; } @@ -162,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) @@ -217,8 +230,7 @@ struct interface *bfd_get_peer_info(struct stream *s, struct prefix *dp, if (ifp == NULL) { if (bfd_debug) zlog_debug( - "zebra_interface_bfd_read: " - "Can't find interface by ifindex: %d ", + "zebra_interface_bfd_read: Can't find interface by ifindex: %d ", ifindex); return NULL; } @@ -320,8 +332,7 @@ void bfd_show_param(struct vty *vty, struct bfd_info *bfd_info, int bfd_tag, json_bfd); } else { vty_out(vty, - " %s%sDetect Multiplier: %d, Min Rx interval: %d," - " Min Tx interval: %d\n", + " %s%sDetect Multiplier: %d, Min Rx interval: %d, Min Tx interval: %d\n", (extra_space) ? " " : "", (bfd_tag) ? "BFD: " : " ", bfd_info->detect_mult, bfd_info->required_min_rx, bfd_info->desired_min_tx); @@ -397,8 +408,7 @@ void bfd_client_sendmsg(struct zclient *zclient, int command, if (!zclient || zclient->sock < 0) { if (bfd_debug) zlog_debug( - "%s: Can't send BFD client register, Zebra client not " - "established", + "%s: Can't send BFD client register, Zebra client not established", __func__); return; } @@ -429,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/buffer.c b/lib/buffer.c index ff49bc83df..459d98e75d 100644 --- a/lib/buffer.c +++ b/lib/buffer.c @@ -327,8 +327,7 @@ buffer_status_t buffer_flush_window(struct buffer *b, int fd, int width, /* This should absolutely never occur. */ flog_err_sys( EC_LIB_SYSTEM_CALL, - "%s: corruption detected: iov_small overflowed; " - "head %p, tail %p, head->next %p", + "%s: corruption detected: iov_small overflowed; head %p, tail %p, head->next %p", __func__, (void *)b->head, (void *)b->tail, (void *)b->head->next); iov = XMALLOC(MTYPE_TMP, 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/ferr.c b/lib/ferr.c index ccf63dea17..7b923da177 100644 --- a/lib/ferr.c +++ b/lib/ferr.c @@ -130,7 +130,7 @@ void log_ref_display(struct vty *vty, uint32_t code, bool json) if (json) { char key[11]; - snprintf(key, sizeof(key), "%"PRIu32, ref->code); + snprintf(key, sizeof(key), "%u", ref->code); obj = json_object_new_object(); json_object_string_add(obj, "title", ref->title); json_object_string_add(obj, "description", @@ -142,7 +142,7 @@ void log_ref_display(struct vty *vty, uint32_t code, bool json) char pbuf[256]; char ubuf[256]; - snprintf(pbuf, sizeof(pbuf), "\nError %"PRIu32" - %s", + snprintf(pbuf, sizeof(pbuf), "\nError %u - %s", ref->code, ref->title); memset(ubuf, '=', strlen(pbuf)); ubuf[strlen(pbuf)] = '\0'; diff --git a/lib/filter.h b/lib/filter.h index 76e992bf8e..d41f3b65cd 100644 --- a/lib/filter.h +++ b/lib/filter.h @@ -170,11 +170,6 @@ enum yang_prefix_list_action { struct lyd_node; struct vty; -extern void access_list_legacy_show(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -extern void access_list_legacy_remark_show(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); extern void access_list_show(struct vty *vty, struct lyd_node *dnode, bool show_defaults); extern void access_list_remark_show(struct vty *vty, struct lyd_node *dnode, diff --git a/lib/filter_cli.c b/lib/filter_cli.c index fe8190d098..030039b3fe 100644 --- a/lib/filter_cli.c +++ b/lib/filter_cli.c @@ -193,7 +193,8 @@ DEFPY( * none given (backward compatibility). */ snprintf(xpath, sizeof(xpath), - "/frr-filter:lib/access-list-legacy[number='%s']", number_str); + "/frr-filter:lib/access-list[type='ipv4'][name='%s']", + number_str); nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); if (seq_str == NULL) { /* Use XPath to find the next sequence number. */ @@ -213,7 +214,7 @@ DEFPY( concat_addr_mask_v4(host_str, mask_str, ipmask, sizeof(ipmask)); nb_cli_enqueue_change(vty, "./network", NB_OP_MODIFY, ipmask); } else { - nb_cli_enqueue_change(vty, "./any", NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./source-any", NB_OP_CREATE, NULL); } return nb_cli_apply_changes(vty, xpath_entry); @@ -244,7 +245,7 @@ DEFPY( if (seq_str != NULL) { snprintf( xpath, sizeof(xpath), - "/frr-filter:lib/access-list-legacy[number='%s']/entry[sequence='%s']", + "/frr-filter:lib/access-list[type='ipv4'][name='%s']/entry[sequence='%s']", number_str, seq_str); nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); return nb_cli_apply_changes(vty, NULL); @@ -252,7 +253,8 @@ DEFPY( /* Otherwise, to keep compatibility, we need to figure it out. */ snprintf(xpath, sizeof(xpath), - "/frr-filter:lib/access-list-legacy[number='%s']", number_str); + "/frr-filter:lib/access-list[type='ipv4'][name='%s']", + number_str); /* Access-list must exist before entries. */ if (yang_dnode_exists(running_config->dnode, xpath) == false) @@ -308,7 +310,8 @@ DEFPY( * none given (backward compatibility). */ snprintf(xpath, sizeof(xpath), - "/frr-filter:lib/access-list-legacy[number='%s']", number_str); + "/frr-filter:lib/access-list[type='ipv4'][name='%s']", + number_str); nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); if (seq_str == NULL) { /* Use XPath to find the next sequence number. */ @@ -329,7 +332,7 @@ DEFPY( sizeof(ipmask)); nb_cli_enqueue_change(vty, "./network", NB_OP_MODIFY, ipmask); } else { - nb_cli_enqueue_change(vty, "./any", NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./source-any", NB_OP_CREATE, NULL); } if (dst_str != NULL && dst_mask_str == NULL) { @@ -379,7 +382,7 @@ DEFPY( if (seq_str != NULL) { snprintfrr( xpath, sizeof(xpath), - "/frr-filter:lib/access-list-legacy[number='%s']/entry[sequence='%s']", + "/frr-filter:lib/access-list[type='ipv4'][name='%s']/entry[sequence='%s']", number_str, seq_str); nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); return nb_cli_apply_changes(vty, NULL); @@ -387,7 +390,8 @@ DEFPY( /* Otherwise, to keep compatibility, we need to figure it out. */ snprintf(xpath, sizeof(xpath), - "/frr-filter:lib/access-list-legacy[number='%s']", number_str); + "/frr-filter:lib/access-list[type='ipv4'][name='%s']", + number_str); /* Access-list must exist before entries. */ if (yang_dnode_exists(running_config->dnode, xpath) == false) @@ -429,127 +433,6 @@ DEFPY( return nb_cli_apply_changes(vty, NULL); } -DEFPY( - no_access_list_legacy, no_access_list_legacy_cmd, - "no access-list <(1-99)|(100-199)|(1300-1999)|(2000-2699)>$number", - NO_STR - ACCESS_LIST_STR - ACCESS_LIST_XLEG_STR) -{ - char xpath[XPATH_MAXLEN]; - - snprintf(xpath, sizeof(xpath), - "/frr-filter:lib/access-list-legacy[number='%s']", number_str); - nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); - - return nb_cli_apply_changes(vty, NULL); -} - -void access_list_legacy_show(struct vty *vty, struct lyd_node *dnode, - bool show_defaults) -{ - uint16_t number = yang_dnode_get_uint16(dnode, "../number"); - bool extended; - struct prefix p; - struct in_addr mask; - - vty_out(vty, "access-list %d seq %s %s", number, - yang_dnode_get_string(dnode, "./sequence"), - yang_dnode_get_string(dnode, "./action")); - - extended = (number >= 100 && number <= 199) - || (number >= 2000 && number <= 2699); - if (extended) - vty_out(vty, " ip"); - - if (yang_dnode_exists(dnode, "./network")) { - yang_dnode_get_prefix(&p, dnode, "./network"); - masklen2ip(p.prefixlen, &mask); - vty_out(vty, " %pI4 %pI4", &p.u.prefix4, &mask); - } else if (yang_dnode_exists(dnode, "./host")) { - if (extended) - vty_out(vty, " host"); - - vty_out(vty, " %s", yang_dnode_get_string(dnode, "./host")); - } else if (yang_dnode_exists(dnode, "./any")) - vty_out(vty, " any"); - - if (extended) { - if (yang_dnode_exists(dnode, "./destination-network")) { - yang_dnode_get_prefix(&p, dnode, - "./destination-network"); - masklen2ip(p.prefixlen, &mask); - vty_out(vty, " %pI4 %pI4", &p.u.prefix4, &mask); - } else if (yang_dnode_exists(dnode, "./destination-host")) - vty_out(vty, " host %s", - yang_dnode_get_string(dnode, - "./destination-host")); - else if (yang_dnode_exists(dnode, "./destination-any")) - vty_out(vty, " any"); - } - - vty_out(vty, "\n"); -} - -DEFPY( - access_list_legacy_remark, access_list_legacy_remark_cmd, - "access-list <(1-99)|(100-199)|(1300-1999)|(2000-2699)>$number remark LINE...", - ACCESS_LIST_STR - ACCESS_LIST_XLEG_STR - ACCESS_LIST_REMARK_STR - ACCESS_LIST_REMARK_LINE_STR) -{ - int rv; - char *remark; - char xpath[XPATH_MAXLEN]; - - snprintf(xpath, sizeof(xpath), - "/frr-filter:lib/access-list-legacy[number='%s']", number_str); - nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); - - remark = argv_concat(argv, argc, 3); - nb_cli_enqueue_change(vty, "./remark", NB_OP_CREATE, remark); - rv = nb_cli_apply_changes(vty, xpath); - XFREE(MTYPE_TMP, remark); - - return rv; -} - -DEFPY( - no_access_list_legacy_remark, no_access_list_legacy_remark_cmd, - "no access-list <(1-99)|(100-199)|(1300-1999)|(2000-2699)>$number remark", - NO_STR - ACCESS_LIST_STR - ACCESS_LIST_XLEG_STR - ACCESS_LIST_REMARK_STR) -{ - char xpath[XPATH_MAXLEN]; - - snprintf(xpath, sizeof(xpath), - "/frr-filter:lib/access-list-legacy[number='%s']/remark", - number_str); - nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); - - return nb_cli_apply_changes(vty, NULL); -} - -ALIAS( - no_access_list_legacy_remark, no_access_list_legacy_remark_line_cmd, - "no access-list <(1-99)|(100-199)|(1300-1999)|(2000-2699)>$number remark LINE...", - NO_STR - ACCESS_LIST_STR - ACCESS_LIST_XLEG_STR - ACCESS_LIST_REMARK_STR - ACCESS_LIST_REMARK_LINE_STR) - -void access_list_legacy_remark_show(struct vty *vty, struct lyd_node *dnode, - bool show_defaults) -{ - vty_out(vty, "access-list %s remark %s\n", - yang_dnode_get_string(dnode, "../number"), - yang_dnode_get_string(dnode, NULL)); -} - /* * Zebra access lists. */ @@ -1077,6 +960,9 @@ void access_list_show(struct vty *vty, struct lyd_node *dnode, struct prefix p; bool is_any; bool is_exact = false; + bool cisco_style = false; + bool cisco_extended = false; + struct in_addr mask; char macstr[PREFIX2STR_BUFFER]; is_any = yang_dnode_exists(dnode, "./any"); @@ -1085,8 +971,19 @@ void access_list_show(struct vty *vty, struct lyd_node *dnode, if (is_any) break; - yang_dnode_get_prefix(&p, dnode, "./ipv4-prefix"); - is_exact = yang_dnode_get_bool(dnode, "./ipv4-exact-match"); + if (yang_dnode_exists(dnode, "./host") + || yang_dnode_exists(dnode, "./network") + || yang_dnode_exists(dnode, "./source-any")) { + cisco_style = true; + if (yang_dnode_exists(dnode, "./destination-host") + || yang_dnode_exists(dnode, "./destination-network") + || yang_dnode_exists(dnode, "./destination-any")) + cisco_extended = true; + } else { + yang_dnode_get_prefix(&p, dnode, "./ipv4-prefix"); + is_exact = yang_dnode_get_bool(dnode, + "./ipv4-exact-match"); + } break; case YALT_IPV6: /* ipv6 */ vty_out(vty, "ipv6 "); @@ -1110,6 +1007,48 @@ void access_list_show(struct vty *vty, struct lyd_node *dnode, yang_dnode_get_string(dnode, "./sequence"), yang_dnode_get_string(dnode, "./action")); + /* Handle Cisco style access lists. */ + if (cisco_style) { + if (cisco_extended) + vty_out(vty, " ip"); + + if (yang_dnode_exists(dnode, "./network")) { + yang_dnode_get_prefix(&p, dnode, "./network"); + masklen2ip(p.prefixlen, &mask); + vty_out(vty, " %pI4 %pI4", &p.u.prefix4, &mask); + } else if (yang_dnode_exists(dnode, "./host")) { + if (cisco_extended) + vty_out(vty, " host"); + + vty_out(vty, " %s", + yang_dnode_get_string(dnode, "./host")); + } else if (yang_dnode_exists(dnode, "./source-any")) + vty_out(vty, " any"); + + /* Not extended, exit earlier. */ + if (!cisco_extended) { + vty_out(vty, "\n"); + return; + } + + /* Handle destination address. */ + if (yang_dnode_exists(dnode, "./destination-network")) { + yang_dnode_get_prefix(&p, dnode, + "./destination-network"); + masklen2ip(p.prefixlen, &mask); + vty_out(vty, " %pI4 %pI4", &p.u.prefix4, &mask); + } else if (yang_dnode_exists(dnode, "./destination-host")) + vty_out(vty, " host %s", + yang_dnode_get_string(dnode, + "./destination-host")); + else if (yang_dnode_exists(dnode, "./destination-any")) + vty_out(vty, " any"); + + vty_out(vty, "\n"); + return; + } + + /* Zebra style access list. */ if (!is_any) { /* If type is MAC don't show '/mask'. */ if (type == 2 /* mac */) { @@ -1648,10 +1587,6 @@ void filter_cli_init(void) install_element(CONFIG_NODE, &no_access_list_std_cmd); install_element(CONFIG_NODE, &access_list_ext_cmd); install_element(CONFIG_NODE, &no_access_list_ext_cmd); - install_element(CONFIG_NODE, &no_access_list_legacy_cmd); - install_element(CONFIG_NODE, &access_list_legacy_remark_cmd); - install_element(CONFIG_NODE, &no_access_list_legacy_remark_cmd); - install_element(CONFIG_NODE, &no_access_list_legacy_remark_line_cmd); /* access-list zebra-style. */ install_element(CONFIG_NODE, &access_list_cmd); diff --git a/lib/filter_nb.c b/lib/filter_nb.c index 83cf586ed3..41bf3cf7f4 100644 --- a/lib/filter_nb.c +++ b/lib/filter_nb.c @@ -93,8 +93,7 @@ prefix_list_length_validate(const struct lyd_node *dnode) return NB_OK; log_and_fail: - zlog_info("prefix-list: invalid prefix range for %pFX: " - "Make sure that mask length < ge <= le", &p); + zlog_info("prefix-list: invalid prefix range for %pFX: Make sure that mask length < ge <= le", &p); return NB_ERR_VALIDATION; } @@ -112,24 +111,38 @@ static void prefix_list_entry_set_empty(struct prefix_list_entry *ple) } /* - * XPath: /frr-filter:lib/access-list-legacy + * XPath: /frr-filter:lib/access-list */ -static int lib_access_list_legacy_create(struct nb_cb_create_args *args) +static int lib_access_list_create(struct nb_cb_create_args *args) { - struct access_list *acl; + struct access_list *acl = NULL; const char *acl_name; + int type; if (args->event != NB_EV_APPLY) return NB_OK; - acl_name = yang_dnode_get_string(args->dnode, "./number"); - acl = access_list_get(AFI_IP, acl_name); + type = yang_dnode_get_enum(args->dnode, "./type"); + acl_name = yang_dnode_get_string(args->dnode, "./name"); + + switch (type) { + case YALT_IPV4: + acl = access_list_get(AFI_IP, acl_name); + break; + case YALT_IPV6: + acl = access_list_get(AFI_IP6, acl_name); + break; + case YALT_MAC: + acl = access_list_get(AFI_L2VPN, acl_name); + break; + } + nb_running_set_entry(args->dnode, acl); return NB_OK; } -static int lib_access_list_legacy_destroy(struct nb_cb_destroy_args *args) +static int lib_access_list_destroy(struct nb_cb_destroy_args *args) { struct access_master *am; struct access_list *acl; @@ -148,9 +161,9 @@ static int lib_access_list_legacy_destroy(struct nb_cb_destroy_args *args) } /* - * XPath: /frr-filter:lib/access-list-legacy/remark + * XPath: /frr-filter:lib/access-list/remark */ -static int lib_access_list_legacy_remark_modify(struct nb_cb_modify_args *args) +static int lib_access_list_remark_modify(struct nb_cb_modify_args *args) { struct access_list *acl; const char *remark; @@ -169,7 +182,7 @@ static int lib_access_list_legacy_remark_modify(struct nb_cb_modify_args *args) } static int -lib_access_list_legacy_remark_destroy(struct nb_cb_destroy_args *args) +lib_access_list_remark_destroy(struct nb_cb_destroy_args *args) { struct access_list *acl; @@ -183,31 +196,20 @@ lib_access_list_legacy_remark_destroy(struct nb_cb_destroy_args *args) return NB_OK; } + /* - * XPath: /frr-filter:lib/access-list-legacy/entry + * XPath: /frr-filter:lib/access-list/entry */ -static int lib_access_list_legacy_entry_create(struct nb_cb_create_args *args) +static int lib_access_list_entry_create(struct nb_cb_create_args *args) { - struct filter_cisco *fc; struct access_list *acl; struct filter *f; - uint32_t aclno; - - /* TODO: validate `filter_lookup_cisco` returns NULL. */ if (args->event != NB_EV_APPLY) return NB_OK; - aclno = yang_dnode_get_uint16(args->dnode, "../number"); - f = filter_new(); - f->cisco = 1; f->seq = yang_dnode_get_uint32(args->dnode, "./sequence"); - fc = &f->u.cfilter; - if ((aclno >= 1 && aclno <= 99) || (aclno >= 1300 && aclno <= 1999)) - fc->extended = 0; - else - fc->extended = 1; acl = nb_running_get_entry(args->dnode, NULL, true); f->acl = acl; @@ -217,7 +219,7 @@ static int lib_access_list_legacy_entry_create(struct nb_cb_create_args *args) return NB_OK; } -static int lib_access_list_legacy_entry_destroy(struct nb_cb_destroy_args *args) +static int lib_access_list_entry_destroy(struct nb_cb_destroy_args *args) { struct access_list *acl; struct filter *f; @@ -233,10 +235,10 @@ static int lib_access_list_legacy_entry_destroy(struct nb_cb_destroy_args *args) } /* - * XPath: /frr-filter:lib/access-list-legacy/entry/action + * XPath: /frr-filter:lib/access-list/entry/action */ static int -lib_access_list_legacy_entry_action_modify(struct nb_cb_modify_args *args) +lib_access_list_entry_action_modify(struct nb_cb_modify_args *args) { const char *filter_type; struct filter *f; @@ -255,86 +257,81 @@ lib_access_list_legacy_entry_action_modify(struct nb_cb_modify_args *args) } /* - * XPath: /frr-filter:lib/access-list-legacy/entry/host + * XPath: /frr-filter:lib/access-list/entry/ipv4-prefix */ static int -lib_access_list_legacy_entry_host_modify(struct nb_cb_modify_args *args) +lib_access_list_entry_ipv4_prefix_modify(struct nb_cb_modify_args *args) { - struct filter_cisco *fc; + struct filter_zebra *fz; struct filter *f; if (args->event != NB_EV_APPLY) return NB_OK; f = nb_running_get_entry(args->dnode, NULL, true); - fc = &f->u.cfilter; - yang_dnode_get_ipv4(&fc->addr, args->dnode, NULL); - fc->addr_mask.s_addr = INADDR_ANY; + f->cisco = 0; + fz = &f->u.zfilter; + yang_dnode_get_prefix(&fz->prefix, args->dnode, NULL); return NB_OK; } static int -lib_access_list_legacy_entry_host_destroy(struct nb_cb_destroy_args *args) +lib_access_list_entry_ipv4_prefix_destroy(struct nb_cb_destroy_args *args) { - struct filter_cisco *fc; + struct filter_zebra *fz; struct filter *f; if (args->event != NB_EV_APPLY) return NB_OK; f = nb_running_get_entry(args->dnode, NULL, true); - fc = &f->u.cfilter; - fc->addr.s_addr = INADDR_ANY; - fc->addr_mask.s_addr = INADDR_NONE; + fz = &f->u.zfilter; + memset(&fz->prefix, 0, sizeof(fz->prefix)); return NB_OK; } /* - * XPath: /frr-filter:lib/access-list-legacy/entry/network + * XPath: /frr-filter:lib/access-list/entry/ipv4-exact-match */ static int -lib_access_list_legacy_entry_network_modify(struct nb_cb_modify_args *args) +lib_access_list_entry_ipv4_exact_match_modify(struct nb_cb_modify_args *args) { - struct filter_cisco *fc; + struct filter_zebra *fz; struct filter *f; - struct prefix p; if (args->event != NB_EV_APPLY) return NB_OK; f = nb_running_get_entry(args->dnode, NULL, true); - fc = &f->u.cfilter; - yang_dnode_get_prefix(&p, args->dnode, NULL); - fc->addr.s_addr = ipv4_network_addr(p.u.prefix4.s_addr, p.prefixlen); - masklen2ip(p.prefixlen, &fc->addr_mask); + fz = &f->u.zfilter; + fz->exact = yang_dnode_get_bool(args->dnode, NULL); return NB_OK; } static int -lib_access_list_legacy_entry_network_destroy(struct nb_cb_destroy_args *args) +lib_access_list_entry_ipv4_exact_match_destroy(struct nb_cb_destroy_args *args) { - struct filter_cisco *fc; + struct filter_zebra *fz; struct filter *f; if (args->event != NB_EV_APPLY) return NB_OK; f = nb_running_get_entry(args->dnode, NULL, true); - fc = &f->u.cfilter; - fc->addr.s_addr = INADDR_ANY; - fc->addr_mask.s_addr = INADDR_NONE; + fz = &f->u.zfilter; + fz->exact = 0; return NB_OK; } /* - * XPath: /frr-filter:lib/access-list-legacy/entry/any + * XPath: /frr-filter:lib/access-list/entry/host */ static int -lib_access_list_legacy_entry_any_create(struct nb_cb_create_args *args) +lib_access_list_entry_host_modify(struct nb_cb_modify_args *args) { struct filter_cisco *fc; struct filter *f; @@ -343,15 +340,16 @@ lib_access_list_legacy_entry_any_create(struct nb_cb_create_args *args) return NB_OK; f = nb_running_get_entry(args->dnode, NULL, true); + f->cisco = 1; fc = &f->u.cfilter; - fc->addr.s_addr = INADDR_ANY; - fc->addr_mask.s_addr = INADDR_NONE; + yang_dnode_get_ipv4(&fc->addr, args->dnode, NULL); + fc->addr_mask.s_addr = INADDR_ANY; return NB_OK; } static int -lib_access_list_legacy_entry_any_destroy(struct nb_cb_destroy_args *args) +lib_access_list_entry_host_destroy(struct nb_cb_destroy_args *args) { struct filter_cisco *fc; struct filter *f; @@ -368,27 +366,30 @@ lib_access_list_legacy_entry_any_destroy(struct nb_cb_destroy_args *args) } /* - * XPath: /frr-filter:lib/access-list-legacy/entry/destination-host + * XPath: /frr-filter:lib/access-list/entry/network */ -static int lib_access_list_legacy_entry_destination_host_modify( - struct nb_cb_modify_args *args) +static int +lib_access_list_entry_network_modify(struct nb_cb_modify_args *args) { struct filter_cisco *fc; struct filter *f; + struct prefix p; if (args->event != NB_EV_APPLY) return NB_OK; f = nb_running_get_entry(args->dnode, NULL, true); + f->cisco = 1; fc = &f->u.cfilter; - yang_dnode_get_ipv4(&fc->mask, args->dnode, NULL); - fc->mask_mask.s_addr = INADDR_ANY; + yang_dnode_get_prefix(&p, args->dnode, NULL); + fc->addr.s_addr = ipv4_network_addr(p.u.prefix4.s_addr, p.prefixlen); + masklen2ip(p.prefixlen, &fc->addr_mask); return NB_OK; } -static int lib_access_list_legacy_entry_destination_host_destroy( - struct nb_cb_destroy_args *args) +static int +lib_access_list_entry_network_destroy(struct nb_cb_destroy_args *args) { struct filter_cisco *fc; struct filter *f; @@ -398,36 +399,35 @@ static int lib_access_list_legacy_entry_destination_host_destroy( f = nb_running_get_entry(args->dnode, NULL, true); fc = &f->u.cfilter; - fc->mask.s_addr = INADDR_ANY; - fc->mask_mask.s_addr = INADDR_NONE; + fc->addr.s_addr = INADDR_ANY; + fc->addr_mask.s_addr = INADDR_NONE; return NB_OK; } /* - * XPath: /frr-filter:lib/access-list-legacy/entry/destination-network + * XPath: /frr-filter:lib/access-list/entry/source-any */ -static int lib_access_list_legacy_entry_destination_network_modify( - struct nb_cb_modify_args *args) +static int +lib_access_list_entry_source_any_create(struct nb_cb_create_args *args) { struct filter_cisco *fc; struct filter *f; - struct prefix p; if (args->event != NB_EV_APPLY) return NB_OK; f = nb_running_get_entry(args->dnode, NULL, true); + f->cisco = 1; fc = &f->u.cfilter; - yang_dnode_get_prefix(&p, args->dnode, NULL); - fc->mask.s_addr = ipv4_network_addr(p.u.prefix4.s_addr, p.prefixlen); - masklen2ip(p.prefixlen, &fc->mask_mask); + fc->addr.s_addr = INADDR_ANY; + fc->addr_mask.s_addr = INADDR_NONE; return NB_OK; } -static int lib_access_list_legacy_entry_destination_network_destroy( - struct nb_cb_destroy_args *args) +static int +lib_access_list_entry_source_any_destroy(struct nb_cb_destroy_args *args) { struct filter_cisco *fc; struct filter *f; @@ -437,17 +437,17 @@ static int lib_access_list_legacy_entry_destination_network_destroy( f = nb_running_get_entry(args->dnode, NULL, true); fc = &f->u.cfilter; - fc->mask.s_addr = INADDR_ANY; - fc->mask_mask.s_addr = INADDR_NONE; + fc->addr.s_addr = INADDR_ANY; + fc->addr_mask.s_addr = INADDR_NONE; return NB_OK; } /* - * XPath: /frr-filter:lib/access-list-legacy/entry/destination-any + * XPath: /frr-filter:lib/access-list/entry/destination-host */ -static int lib_access_list_legacy_entry_destination_any_create( - struct nb_cb_create_args *args) +static int lib_access_list_entry_destination_host_modify( + struct nb_cb_modify_args *args) { struct filter_cisco *fc; struct filter *f; @@ -457,13 +457,14 @@ static int lib_access_list_legacy_entry_destination_any_create( f = nb_running_get_entry(args->dnode, NULL, true); fc = &f->u.cfilter; - fc->mask.s_addr = INADDR_ANY; - fc->mask_mask.s_addr = INADDR_NONE; + fc->extended = 1; + yang_dnode_get_ipv4(&fc->mask, args->dnode, NULL); + fc->mask_mask.s_addr = INADDR_ANY; return NB_OK; } -static int lib_access_list_legacy_entry_destination_any_destroy( +static int lib_access_list_entry_destination_host_destroy( struct nb_cb_destroy_args *args) { struct filter_cisco *fc; @@ -474,6 +475,7 @@ static int lib_access_list_legacy_entry_destination_any_destroy( f = nb_running_get_entry(args->dnode, NULL, true); fc = &f->u.cfilter; + fc->extended = 0; fc->mask.s_addr = INADDR_ANY; fc->mask_mask.s_addr = INADDR_NONE; @@ -481,160 +483,81 @@ static int lib_access_list_legacy_entry_destination_any_destroy( } /* - * XPath: /frr-filter:lib/access-list - */ -static int lib_access_list_create(struct nb_cb_create_args *args) -{ - struct access_list *acl = NULL; - const char *acl_name; - int type; - - if (args->event != NB_EV_APPLY) - return NB_OK; - - type = yang_dnode_get_enum(args->dnode, "./type"); - acl_name = yang_dnode_get_string(args->dnode, "./name"); - - switch (type) { - case YALT_IPV4: - acl = access_list_get(AFI_IP, acl_name); - break; - case YALT_IPV6: - acl = access_list_get(AFI_IP6, acl_name); - break; - case YALT_MAC: - acl = access_list_get(AFI_L2VPN, acl_name); - break; - } - - nb_running_set_entry(args->dnode, acl); - - return NB_OK; -} - -static int lib_access_list_destroy(struct nb_cb_destroy_args *args) -{ - struct access_master *am; - struct access_list *acl; - - if (args->event != NB_EV_APPLY) - return NB_OK; - - acl = nb_running_unset_entry(args->dnode); - am = acl->master; - if (am->delete_hook) - am->delete_hook(acl); - - access_list_delete(acl); - - return NB_OK; -} - -/* - * XPath: /frr-filter:lib/access-list/entry - */ -static int lib_access_list_entry_create(struct nb_cb_create_args *args) -{ - struct access_list *acl; - struct filter *f; - - /* TODO: validate `filter_lookup_zebra` returns NULL. */ - - if (args->event != NB_EV_APPLY) - return NB_OK; - - f = filter_new(); - f->seq = yang_dnode_get_uint32(args->dnode, "./sequence"); - - acl = nb_running_get_entry(args->dnode, NULL, true); - f->acl = acl; - access_list_filter_add(acl, f); - nb_running_set_entry(args->dnode, f); - - return NB_OK; -} - -static int lib_access_list_entry_destroy(struct nb_cb_destroy_args *args) -{ - struct access_list *acl; - struct filter *f; - - if (args->event != NB_EV_APPLY) - return NB_OK; - - f = nb_running_unset_entry(args->dnode); - acl = f->acl; - access_list_filter_delete(acl, f); - - return NB_OK; -} - -/* - * XPath: /frr-filter:lib/access-list/entry/ipv4-prefix + * XPath: /frr-filter:lib/access-list/entry/destination-network */ -static int -lib_access_list_entry_ipv4_prefix_modify(struct nb_cb_modify_args *args) +static int lib_access_list_entry_destination_network_modify( + struct nb_cb_modify_args *args) { - struct filter_zebra *fz; + struct filter_cisco *fc; struct filter *f; + struct prefix p; if (args->event != NB_EV_APPLY) return NB_OK; f = nb_running_get_entry(args->dnode, NULL, true); - fz = &f->u.zfilter; - yang_dnode_get_prefix(&fz->prefix, args->dnode, NULL); + fc = &f->u.cfilter; + fc->extended = 1; + yang_dnode_get_prefix(&p, args->dnode, NULL); + fc->mask.s_addr = ipv4_network_addr(p.u.prefix4.s_addr, p.prefixlen); + masklen2ip(p.prefixlen, &fc->mask_mask); return NB_OK; } -static int -lib_access_list_entry_ipv4_prefix_destroy(struct nb_cb_destroy_args *args) +static int lib_access_list_entry_destination_network_destroy( + struct nb_cb_destroy_args *args) { - struct filter_zebra *fz; + struct filter_cisco *fc; struct filter *f; if (args->event != NB_EV_APPLY) return NB_OK; f = nb_running_get_entry(args->dnode, NULL, true); - fz = &f->u.zfilter; - memset(&fz->prefix, 0, sizeof(fz->prefix)); + fc = &f->u.cfilter; + fc->extended = 0; + fc->mask.s_addr = INADDR_ANY; + fc->mask_mask.s_addr = INADDR_NONE; return NB_OK; } /* - * XPath: /frr-filter:lib/access-list/entry/ipv4-exact-match + * XPath: /frr-filter:lib/access-list/entry/destination-any */ -static int -lib_access_list_entry_ipv4_exact_match_modify(struct nb_cb_modify_args *args) +static int lib_access_list_entry_destination_any_create( + struct nb_cb_create_args *args) { - struct filter_zebra *fz; + struct filter_cisco *fc; struct filter *f; if (args->event != NB_EV_APPLY) return NB_OK; f = nb_running_get_entry(args->dnode, NULL, true); - fz = &f->u.zfilter; - fz->exact = yang_dnode_get_bool(args->dnode, NULL); + fc = &f->u.cfilter; + fc->extended = 1; + fc->mask.s_addr = INADDR_ANY; + fc->mask_mask.s_addr = INADDR_NONE; return NB_OK; } -static int -lib_access_list_entry_ipv4_exact_match_destroy(struct nb_cb_destroy_args *args) +static int lib_access_list_entry_destination_any_destroy( + struct nb_cb_destroy_args *args) { - struct filter_zebra *fz; + struct filter_cisco *fc; struct filter *f; if (args->event != NB_EV_APPLY) return NB_OK; f = nb_running_get_entry(args->dnode, NULL, true); - fz = &f->u.zfilter; - fz->exact = 0; + fc = &f->u.cfilter; + fc->extended = 0; + fc->mask.s_addr = INADDR_ANY; + fc->mask_mask.s_addr = INADDR_NONE; return NB_OK; } @@ -652,6 +575,7 @@ static int lib_access_list_entry_any_create(struct nb_cb_create_args *args) return NB_OK; f = nb_running_get_entry(args->dnode, NULL, true); + f->cisco = 0; fz = &f->u.zfilter; memset(&fz->prefix, 0, sizeof(fz->prefix)); @@ -1060,117 +984,88 @@ const struct frr_yang_module_info frr_filter_info = { .name = "frr-filter", .nodes = { { - .xpath = "/frr-filter:lib/access-list-legacy", - .cbs = { - .create = lib_access_list_legacy_create, - .destroy = lib_access_list_legacy_destroy, - } - }, - { - .xpath = "/frr-filter:lib/access-list-legacy/remark", - .cbs = { - .modify = lib_access_list_legacy_remark_modify, - .destroy = lib_access_list_legacy_remark_destroy, - .cli_show = access_list_legacy_remark_show, - } - }, - { - .xpath = "/frr-filter:lib/access-list-legacy/entry", - .cbs = { - .create = lib_access_list_legacy_entry_create, - .destroy = lib_access_list_legacy_entry_destroy, - .cli_show = access_list_legacy_show, - } - }, - { - .xpath = "/frr-filter:lib/access-list-legacy/entry/action", - .cbs = { - .modify = lib_access_list_legacy_entry_action_modify, - } - }, - { - .xpath = "/frr-filter:lib/access-list-legacy/entry/host", + .xpath = "/frr-filter:lib/access-list", .cbs = { - .modify = lib_access_list_legacy_entry_host_modify, - .destroy = lib_access_list_legacy_entry_host_destroy, + .create = lib_access_list_create, + .destroy = lib_access_list_destroy, } }, { - .xpath = "/frr-filter:lib/access-list-legacy/entry/network", + .xpath = "/frr-filter:lib/access-list/remark", .cbs = { - .modify = lib_access_list_legacy_entry_network_modify, - .destroy = lib_access_list_legacy_entry_network_destroy, + .modify = lib_access_list_remark_modify, + .destroy = lib_access_list_remark_destroy, + .cli_show = access_list_remark_show, } }, { - .xpath = "/frr-filter:lib/access-list-legacy/entry/any", + .xpath = "/frr-filter:lib/access-list/entry", .cbs = { - .create = lib_access_list_legacy_entry_any_create, - .destroy = lib_access_list_legacy_entry_any_destroy, + .create = lib_access_list_entry_create, + .destroy = lib_access_list_entry_destroy, + .cli_show = access_list_show, } }, { - .xpath = "/frr-filter:lib/access-list-legacy/entry/destination-host", + .xpath = "/frr-filter:lib/access-list/entry/action", .cbs = { - .modify = lib_access_list_legacy_entry_destination_host_modify, - .destroy = lib_access_list_legacy_entry_destination_host_destroy, + .modify = lib_access_list_entry_action_modify, } }, { - .xpath = "/frr-filter:lib/access-list-legacy/entry/destination-network", + .xpath = "/frr-filter:lib/access-list/entry/ipv4-prefix", .cbs = { - .modify = lib_access_list_legacy_entry_destination_network_modify, - .destroy = lib_access_list_legacy_entry_destination_network_destroy, + .modify = lib_access_list_entry_ipv4_prefix_modify, + .destroy = lib_access_list_entry_ipv4_prefix_destroy, } }, { - .xpath = "/frr-filter:lib/access-list-legacy/entry/destination-any", + .xpath = "/frr-filter:lib/access-list/entry/ipv4-exact-match", .cbs = { - .create = lib_access_list_legacy_entry_destination_any_create, - .destroy = lib_access_list_legacy_entry_destination_any_destroy, + .modify = lib_access_list_entry_ipv4_exact_match_modify, + .destroy = lib_access_list_entry_ipv4_exact_match_destroy, } }, { - .xpath = "/frr-filter:lib/access-list", + .xpath = "/frr-filter:lib/access-list/entry/host", .cbs = { - .create = lib_access_list_create, - .destroy = lib_access_list_destroy, + .modify = lib_access_list_entry_host_modify, + .destroy = lib_access_list_entry_host_destroy, } }, { - .xpath = "/frr-filter:lib/access-list/remark", + .xpath = "/frr-filter:lib/access-list/entry/network", .cbs = { - .modify = lib_access_list_legacy_remark_modify, - .destroy = lib_access_list_legacy_remark_destroy, - .cli_show = access_list_remark_show, + .modify = lib_access_list_entry_network_modify, + .destroy = lib_access_list_entry_network_destroy, } }, { - .xpath = "/frr-filter:lib/access-list/entry", + .xpath = "/frr-filter:lib/access-list/entry/source-any", .cbs = { - .create = lib_access_list_entry_create, - .destroy = lib_access_list_entry_destroy, - .cli_show = access_list_show, + .create = lib_access_list_entry_source_any_create, + .destroy = lib_access_list_entry_source_any_destroy, } }, { - .xpath = "/frr-filter:lib/access-list/entry/action", + .xpath = "/frr-filter:lib/access-list/entry/destination-host", .cbs = { - .modify = lib_access_list_legacy_entry_action_modify, + .modify = lib_access_list_entry_destination_host_modify, + .destroy = lib_access_list_entry_destination_host_destroy, } }, { - .xpath = "/frr-filter:lib/access-list/entry/ipv4-prefix", + .xpath = "/frr-filter:lib/access-list/entry/destination-network", .cbs = { - .modify = lib_access_list_entry_ipv4_prefix_modify, - .destroy = lib_access_list_entry_ipv4_prefix_destroy, + .modify = lib_access_list_entry_destination_network_modify, + .destroy = lib_access_list_entry_destination_network_destroy, } }, { - .xpath = "/frr-filter:lib/access-list/entry/ipv4-exact-match", + .xpath = "/frr-filter:lib/access-list/entry/destination-any", .cbs = { - .modify = lib_access_list_entry_ipv4_exact_match_modify, - .destroy = lib_access_list_entry_ipv4_exact_match_destroy, + .create = lib_access_list_entry_destination_any_create, + .destroy = lib_access_list_entry_destination_any_destroy, } }, { diff --git a/lib/id_alloc.c b/lib/id_alloc.c index 7c7f2c4689..95096fa5f0 100644 --- a/lib/id_alloc.c +++ b/lib/id_alloc.c @@ -108,7 +108,7 @@ static struct id_alloc_page *find_or_create_page(struct id_alloc *alloc, } else if (page != NULL && create) { flog_err( EC_LIB_ID_CONSISTENCY, - "ID Allocator %s attempt to re-create page at %" PRIu32, + "ID Allocator %s attempt to re-create page at %u", alloc->name, id); } @@ -131,8 +131,7 @@ void idalloc_free(struct id_alloc *alloc, uint32_t id) page = find_or_create_page(alloc, id, 0); if (!page) { flog_err(EC_LIB_ID_CONSISTENCY, - "ID Allocator %s cannot free #%" PRIu32 - ". ID Block does not exist.", + "ID Allocator %s cannot free #%u. ID Block does not exist.", alloc->name, id); return; } @@ -142,8 +141,7 @@ void idalloc_free(struct id_alloc *alloc, uint32_t id) if ((page->allocated_mask[word] & (1 << offset)) == 0) { flog_err(EC_LIB_ID_CONSISTENCY, - "ID Allocator %s cannot free #%" PRIu32 - ". ID was not allocated at the time of free.", + "ID Allocator %s cannot free #%u. ID was not allocated at the time of free.", alloc->name, id); return; } @@ -285,8 +283,7 @@ uint32_t idalloc_reserve(struct id_alloc *alloc, uint32_t id) if (page->allocated_mask[word] & (((uint32_t)1) << offset)) { flog_err(EC_LIB_ID_CONSISTENCY, - "ID Allocator %s could not reserve %" PRIu32 - " because it is already allocated.", + "ID Allocator %s could not reserve %u because it is already allocated.", alloc->name, id); return IDALLOC_INVALID; } @@ -785,8 +785,7 @@ static void if_dump(const struct interface *ifp) struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id); zlog_info( - "Interface %s vrf %s(%u) index %d metric %d mtu %d " - "mtu6 %d %s", + "Interface %s vrf %s(%u) index %d metric %d mtu %d mtu6 %d %s", ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex, ifp->metric, ifp->mtu, ifp->mtu6, if_flag_dump(ifp->flags)); 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"); @@ -273,8 +273,7 @@ void zlog_backtrace(int priority) if (size <= 0 || (size_t)size > array_size(array)) { flog_err_sys( EC_LIB_SYSTEM_CALL, - "Cannot get backtrace, returned invalid # of frames %d " - "(valid range is between 1 and %lu)", + "Cannot get backtrace, returned invalid # of frames %d (valid range is between 1 and %lu)", size, (unsigned long)(array_size(array))); return; } @@ -301,8 +300,7 @@ void zlog_thread_info(int log_level) if (tc) zlog(log_level, - "Current thread function %s, scheduled from " - "file %s, line %u", + "Current thread function %s, scheduled from file %s, line %u", tc->funcname, tc->schedfrom, tc->schedfrom_line); else zlog(log_level, "Current thread not known/applicable"); @@ -465,8 +463,7 @@ static const struct zebra_desc_table *zroute_lookup(unsigned int zroute) for (i = 0; i < array_size(route_types); i++) { if (zroute == route_types[i].type) { zlog_warn( - "internal error: route type table out of order " - "while searching for %u, please notify developers", + "internal error: route type table out of order while searching for %u, please notify developers", zroute); return &route_types[i]; } @@ -64,13 +64,13 @@ struct message { /* For logs which have error codes associated with them */ #define flog_err(ferr_id, format, ...) \ - zlog_err("[EC %" PRIu32 "] " format, ferr_id, ##__VA_ARGS__) + zlog_err("[EC %u] " format, ferr_id, ##__VA_ARGS__) #define flog_err_sys(ferr_id, format, ...) \ flog_err(ferr_id, format, ##__VA_ARGS__) #define flog_warn(ferr_id, format, ...) \ - zlog_warn("[EC %" PRIu32 "] " format, ferr_id, ##__VA_ARGS__) + zlog_warn("[EC %u] " format, ferr_id, ##__VA_ARGS__) #define flog(priority, ferr_id, format, ...) \ - zlog(priority, "[EC %" PRIu32 "] " format, ferr_id, ##__VA_ARGS__) + zlog(priority, "[EC %u] " format, ferr_id, ##__VA_ARGS__) extern void zlog_thread_info(int log_level); diff --git a/lib/memory.c b/lib/memory.c index 3a29404827..2c902d123b 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -157,8 +157,7 @@ static int qmem_exit_walker(void *arg, struct memgroup *mg, struct memtype *mt) if (!mt) { fprintf(eda->fp, - "%s: showing active allocations in " - "memory group %s\n", + "%s: showing active allocations in memory group %s\n", eda->prefix, mg->name); } else if (mt->n_alloc) { 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/privs.c b/lib/privs.c index eb0dbe0783..5c7e1240e2 100644 --- a/lib/privs.c +++ b/lib/privs.c @@ -558,8 +558,7 @@ static void zprivs_caps_init(struct zebra_privs_t *zprivs) /* nonsensical to have gotten here but not have capabilities */ if (!zprivs_state.syscaps_p) { fprintf(stderr, - "%s: capabilities enabled, " - "but no valid capabilities supplied\n", + "%s: capabilities enabled, but no valid capabilities supplied\n", __func__); } 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/routemap.c b/lib/routemap.c index 7749ea4cc7..22b4beb79d 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -353,8 +353,7 @@ int generic_match_add(struct vty *vty, struct route_map_index *index, "%% [%s] Argument form is unsupported or malformed.\n", frr_protonameinst); else - zlog_warn("Argument form is unsupported or malformed: " - "%s %s", command, arg); + zlog_warn("Argument form is unsupported or malformed: %s %s", command, arg); return CMD_WARNING_CONFIG_FAILED; case RMAP_COMPILE_SUCCESS: /* @@ -405,8 +404,7 @@ int generic_match_delete(struct vty *vty, struct route_map_index *index, "%% [%s] Argument form is unsupported or malformed.\n", frr_protonameinst); else - zlog_warn("Argument form is unsupported or malformed: " - "%s %s", command, arg); + zlog_warn("Argument form is unsupported or malformed: %s %s", command, arg); retval = CMD_WARNING_CONFIG_FAILED; break; case RMAP_COMPILE_SUCCESS: @@ -441,8 +439,7 @@ int generic_set_add(struct vty *vty, struct route_map_index *index, "%% [%s] Argument form is unsupported or malformed.\n", frr_protonameinst); else - zlog_warn("Argument form is unsupported or malformed: " - "%s %s", command, arg); + zlog_warn("Argument form is unsupported or malformed: %s %s", command, arg); return CMD_WARNING_CONFIG_FAILED; case RMAP_COMPILE_SUCCESS: break; @@ -470,8 +467,7 @@ int generic_set_delete(struct vty *vty, struct route_map_index *index, "%% [%s] Argument form is unsupported or malformed.\n", frr_protonameinst); else - zlog_warn("Argument form is unsupported or malformed: " - "%s %s", command, arg); + zlog_warn("Argument form is unsupported or malformed: %s %s", command, arg); return CMD_WARNING_CONFIG_FAILED; case RMAP_COMPILE_SUCCESS: break; @@ -1692,14 +1688,19 @@ route_map_get_index(struct route_map *map, const struct prefix *prefix, * more noops, we retain this return value and * return this eventually if there are no * matches. + * If a best match route-map index already + * exists, do not reset the match_ret. */ - if (*match_ret != RMAP_NOMATCH) + if (!best_index && (*match_ret != RMAP_NOMATCH)) *match_ret = ret; } else { /* * ret is RMAP_NOMATCH. + * If a best match route-map index already + * exists, do not reset the match_ret. */ - *match_ret = ret; + if (!best_index) + *match_ret = ret; } } diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c index 2c45f09751..31bee1310e 100644 --- a/lib/routemap_cli.c +++ b/lib/routemap_cli.c @@ -213,7 +213,7 @@ DEFPY( DEFPY( match_ip_address, match_ip_address_cmd, - "match ip address <(1-199)$acll|(1300-2699)$aclh|WORD$name>", + "match ip address <(1-199)|(1300-2699)|WORD>$name", MATCH_STR IP_STR "Match address of route\n" @@ -223,29 +223,10 @@ DEFPY( { const char *xpath = "./match-condition[condition='ipv4-address-list']"; char xpath_value[XPATH_MAXLEN + 32]; - int acln = acll ? acll : aclh; nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); - if (name) { - snprintf(xpath_value, sizeof(xpath_value), "%s/list-name", - xpath); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, name); - } else /* if (acll || aclh) */ { - if ((acln >= 1 && acln <= 99) - || (acln >= 1300 && acln <= 1999)) { - snprintf(xpath_value, sizeof(xpath_value), - "%s/access-list-num", xpath); - } else { - /* - * if ((acln >= 100 && acln <= 199) - * || (acln >= 2000 && acln <= 2699)) - */ - snprintf(xpath_value, sizeof(xpath_value), - "%s/access-list-num-extended", xpath); - } - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, - acll_str ? acll_str : aclh_str); - } + snprintf(xpath_value, sizeof(xpath_value), "%s/list-name", xpath); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, name); return nb_cli_apply_changes(vty, NULL); } @@ -307,7 +288,7 @@ DEFPY( DEFPY( match_ip_next_hop, match_ip_next_hop_cmd, - "match ip next-hop <(1-199)$acll|(1300-2699)$aclh|WORD$name>", + "match ip next-hop <(1-199)|(1300-2699)|WORD>$name", MATCH_STR IP_STR "Match next-hop address of route\n" @@ -317,29 +298,10 @@ DEFPY( { const char *xpath = "./match-condition[condition='ipv4-next-hop-list']"; char xpath_value[XPATH_MAXLEN + 32]; - int acln = acll ? acll : aclh; nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); - if (name) { - snprintf(xpath_value, sizeof(xpath_value), "%s/list-name", - xpath); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, name); - } else /* if (acll || aclh) */ { - if ((acln >= 1 && acln <= 99) - || (acln >= 1300 && acln <= 1999)) { - snprintf(xpath_value, sizeof(xpath_value), - "%s/access-list-num", xpath); - } else { - /* - * if ((acln >= 100 && acln <= 199) - * || (acln >= 2000 && acln <= 2699)) - */ - snprintf(xpath_value, sizeof(xpath_value), - "%s/access-list-num-extended", xpath); - } - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, - acll_str ? acll_str : aclh_str); - } + snprintf(xpath_value, sizeof(xpath_value), "%s/list-name", xpath); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, name); return nb_cli_apply_changes(vty, NULL); } @@ -610,8 +572,6 @@ void route_map_condition_show(struct vty *vty, struct lyd_node *dnode, bool show_defaults) { int condition = yang_dnode_get_enum(dnode, "./condition"); - struct lyd_node *ln; - const char *acl; switch (condition) { case 0: /* interface */ @@ -620,25 +580,14 @@ void route_map_condition_show(struct vty *vty, struct lyd_node *dnode, break; case 1: /* ipv4-address-list */ case 3: /* ipv4-next-hop-list */ - acl = NULL; - if ((ln = yang_dnode_get(dnode, "./list-name")) != NULL) - acl = yang_dnode_get_string(ln, NULL); - else if ((ln = yang_dnode_get(dnode, "./access-list-num")) - != NULL) - acl = yang_dnode_get_string(ln, NULL); - else if ((ln = yang_dnode_get(dnode, - "./access-list-num-extended")) - != NULL) - acl = yang_dnode_get_string(ln, NULL); - - assert(acl); - switch (condition) { case 1: - vty_out(vty, " match ip address %s\n", acl); + vty_out(vty, " match ip address %s\n", + yang_dnode_get_string(dnode, "./list-name")); break; case 3: - vty_out(vty, " match ip next-hop %s\n", acl); + vty_out(vty, " match ip next-hop %s\n", + yang_dnode_get_string(dnode, "./list-name")); break; } break; diff --git a/lib/routemap_northbound.c b/lib/routemap_northbound.c index f500a6c408..967f3fd4d4 100644 --- a/lib/routemap_northbound.c +++ b/lib/routemap_northbound.c @@ -516,77 +516,6 @@ static int lib_route_map_entry_match_condition_interface_destroy( } /* - * XPath: /frr-route-map:lib/route-map/entry/match-condition/access-list-num - */ -static int lib_route_map_entry_match_condition_access_list_num_modify( - struct nb_cb_modify_args *args) -{ - struct routemap_hook_context *rhc; - const char *acl; - int condition, rv; - - if (args->event != NB_EV_APPLY) - return NB_OK; - - /* Check for hook function. */ - rv = CMD_SUCCESS; - acl = yang_dnode_get_string(args->dnode, NULL); - rhc = nb_running_get_entry(args->dnode, NULL, true); - condition = yang_dnode_get_enum(args->dnode, "../condition"); - switch (condition) { - case 1: /* ipv4-address-list */ - if (rmap_match_set_hook.match_ip_address == NULL) - break; - rhc->rhc_mhook = rmap_match_set_hook.no_match_ip_address; - rhc->rhc_rule = "ip address"; - rhc->rhc_event = RMAP_EVENT_FILTER_DELETED; - rv = rmap_match_set_hook.match_ip_address( - NULL, rhc->rhc_rmi, "ip address", acl, - RMAP_EVENT_FILTER_ADDED); - break; - case 3: /* ipv4-next-hop-list */ - if (rmap_match_set_hook.match_ip_next_hop == NULL) - break; - rhc->rhc_mhook = rmap_match_set_hook.no_match_ip_next_hop; - rhc->rhc_rule = "ip next-hop"; - rhc->rhc_event = RMAP_EVENT_FILTER_DELETED; - rv = rmap_match_set_hook.match_ip_next_hop( - NULL, rhc->rhc_rmi, "ip next-hop", acl, - RMAP_EVENT_FILTER_ADDED); - break; - } - if (rv != CMD_SUCCESS) { - rhc->rhc_mhook = NULL; - return NB_ERR_INCONSISTENCY; - } - - return NB_OK; -} - -static int lib_route_map_entry_match_condition_access_list_num_destroy( - struct nb_cb_destroy_args *args) -{ - return lib_route_map_entry_match_destroy(args); -} - -/* - * XPath: - * /frr-route-map:lib/route-map/entry/match-condition/access-list-num-extended - */ -static int lib_route_map_entry_match_condition_access_list_num_extended_modify( - struct nb_cb_modify_args *args) -{ - return lib_route_map_entry_match_condition_access_list_num_modify(args); -} - -static int lib_route_map_entry_match_condition_access_list_num_extended_destroy( - struct nb_cb_destroy_args *args) -{ - return lib_route_map_entry_match_condition_access_list_num_destroy( - args); -} - -/* * XPath: /frr-route-map:lib/route-map/entry/match-condition/list-name */ static int lib_route_map_entry_match_condition_list_name_modify( @@ -1245,20 +1174,6 @@ const struct frr_yang_module_info frr_route_map_info = { } }, { - .xpath = "/frr-route-map:lib/route-map/entry/match-condition/access-list-num", - .cbs = { - .modify = lib_route_map_entry_match_condition_access_list_num_modify, - .destroy = lib_route_map_entry_match_condition_access_list_num_destroy, - } - }, - { - .xpath = "/frr-route-map:lib/route-map/entry/match-condition/access-list-num-extended", - .cbs = { - .modify = lib_route_map_entry_match_condition_access_list_num_extended_modify, - .destroy = lib_route_map_entry_match_condition_access_list_num_extended_destroy, - } - }, - { .xpath = "/frr-route-map:lib/route-map/entry/match-condition/list-name", .cbs = { .modify = lib_route_map_entry_match_condition_list_name_modify, diff --git a/lib/routing_nb.c b/lib/routing_nb.c new file mode 100644 index 0000000000..0160354a7e --- /dev/null +++ b/lib/routing_nb.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2018 Vmware + * Vishal Dhingra + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "northbound.h" +#include "libfrr.h" +#include "routing_nb.h" + + + +/* clang-format off */ +const struct frr_yang_module_info frr_routing_info = { + .name = "frr-routing", + .nodes = { + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol", + .cbs = { + .create = routing_control_plane_protocols_control_plane_protocol_create, + .destroy = routing_control_plane_protocols_control_plane_protocol_destroy, + } + }, + { + .xpath = NULL, + }, + } +}; diff --git a/lib/routing_nb.h b/lib/routing_nb.h new file mode 100644 index 0000000000..d1b59ea29e --- /dev/null +++ b/lib/routing_nb.h @@ -0,0 +1,24 @@ +#ifndef _FRR_ROUTING_NB_H_ +#define _FRR_ROUTING_NB_H_ + +extern const struct frr_yang_module_info frr_routing_info; + +/* Mandatory callbacks. */ +int routing_control_plane_protocols_control_plane_protocol_create( + struct nb_cb_create_args *args); +int routing_control_plane_protocols_control_plane_protocol_destroy( + struct nb_cb_destroy_args *args); + +#define FRR_ROUTING_XPATH \ + "/frr-routing:routing/control-plane-protocols/control-plane-protocol" + +#define FRR_ROUTING_KEY_XPATH \ + "/frr-routing:routing/control-plane-protocols/" \ + "control-plane-protocol[type='%s'][name='%s'][vrf='%s']" +/* + * callbacks for routing to handle configuration events + * based on the control plane protocol + */ +DECLARE_HOOK(routing_conf_event, (struct nb_cb_create_args *args), (args)) + +#endif /* _FRR_ROUTING_NB_H_ */ diff --git a/lib/routing_nb_config.c b/lib/routing_nb_config.c new file mode 100644 index 0000000000..b789e8494e --- /dev/null +++ b/lib/routing_nb_config.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2018 Vmware + * Vishal Dhingra + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "northbound.h" +#include "libfrr.h" +#include "vrf.h" +#include "lib_errors.h" +#include "routing_nb.h" + + +DEFINE_HOOK(routing_conf_event, (struct nb_cb_create_args *args), (args)) + +/* + * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol + */ + +int routing_control_plane_protocols_control_plane_protocol_create( + struct nb_cb_create_args *args) +{ + struct vrf *vrf; + const char *vrfname; + + switch (args->event) { + case NB_EV_VALIDATE: + if (hook_call(routing_conf_event, args)) + return NB_ERR_VALIDATION; + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrfname = yang_dnode_get_string(args->dnode, "./vrf"); + vrf = vrf_lookup_by_name(vrfname); + vrf = vrf ? vrf : vrf_get(VRF_UNKNOWN, vrfname); + if (!vrf) { + flog_warn(EC_LIB_NB_CB_CONFIG_APPLY, + "vrf creation %s failed", vrfname); + return NB_ERR; + } + nb_running_set_entry(args->dnode, vrf); + break; + }; + + return NB_OK; +} + +int routing_control_plane_protocols_control_plane_protocol_destroy( + struct nb_cb_destroy_args *args) +{ + struct vrf *vrf __attribute__((unused)); + + if (args->event != NB_EV_APPLY) + return NB_OK; + + vrf = nb_running_unset_entry(args->dnode); + + return NB_OK; +} diff --git a/lib/sockopt.c b/lib/sockopt.c index 45d9008796..21fddcd01d 100644 --- a/lib/sockopt.c +++ b/lib/sockopt.c @@ -264,8 +264,7 @@ int setsockopt_ipv4_multicast(int sock, int optname, struct in_addr if_addr, * up */ char buf[1][INET_ADDRSTRLEN]; zlog_info( - "setsockopt_ipv4_multicast attempting to drop and " - "re-add (fd %d, mcast %s, ifindex %u)", + "setsockopt_ipv4_multicast attempting to drop and re-add (fd %d, mcast %s, ifindex %u)", sock, inet_ntop(AF_INET, &mreqn.imr_multiaddr, buf[0], sizeof(buf[0])), ifindex); @@ -306,8 +305,7 @@ int setsockopt_ipv4_multicast(int sock, int optname, struct in_addr if_addr, * up */ char buf[1][INET_ADDRSTRLEN]; zlog_info( - "setsockopt_ipv4_multicast attempting to drop and " - "re-add (fd %d, mcast %s, ifindex %u)", + "setsockopt_ipv4_multicast attempting to drop and re-add (fd %d, mcast %s, ifindex %u)", sock, inet_ntop(AF_INET, &mreq.imr_multiaddr, buf[0], sizeof(buf[0])), ifindex); diff --git a/lib/sockunion.c b/lib/sockunion.c index 16df03847a..d77229797c 100644 --- a/lib/sockunion.c +++ b/lib/sockunion.c @@ -407,8 +407,7 @@ int sockopt_v6only(int family, int sock) sizeof(int)); if (ret < 0) { flog_err(EC_LIB_SOCKET, - "can't set sockopt IPV6_V6ONLY " - "to socket %d", + "can't set sockopt IPV6_V6ONLY to socket %d", sock); return -1; } diff --git a/lib/srcdest_table.c b/lib/srcdest_table.c index 66b735919b..8ffa0e9709 100644 --- a/lib/srcdest_table.c +++ b/lib/srcdest_table.c @@ -317,3 +317,13 @@ static ssize_t printfrr_rn(char *buf, size_t bsz, const char *fmt, srcdest2str(dst_p, (const struct prefix_ipv6 *)src_p, buf, bsz); return 2; } + +struct route_table *srcdest_srcnode_table(struct route_node *rn) +{ + if (rnode_is_dstnode(rn)) { + struct srcdest_rnode *srn = srcdest_rnode_from_rnode(rn); + + return srn->src_table; + } + return NULL; +} diff --git a/lib/srcdest_table.h b/lib/srcdest_table.h index 7982260777..79afef9bb0 100644 --- a/lib/srcdest_table.h +++ b/lib/srcdest_table.h @@ -100,6 +100,8 @@ static inline void *srcdest_rnode_table_info(struct route_node *rn) return route_table_get_info(srcdest_rnode_table(rn)); } +extern struct route_table *srcdest_srcnode_table(struct route_node *rn); + #ifdef __cplusplus } #endif 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 57b2cea832..34ad30f968 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -108,6 +108,8 @@ lib_libfrr_la_SOURCES = \ lib/printf/printf-pos.c \ lib/printf/vfprintf.c \ lib/printf/glue.c \ + lib/routing_nb.c \ + lib/routing_nb_config.c \ # end nodist_lib_libfrr_la_SOURCES = \ @@ -117,13 +119,11 @@ nodist_lib_libfrr_la_SOURCES = \ yang/frr-route-types.yang.c \ yang/frr-vrf.yang.c \ yang/frr-routing.yang.c \ + yang/frr-nexthop.yang.c \ yang/ietf/ietf-routing-types.yang.c \ 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 += \ @@ -266,6 +266,7 @@ pkginclude_HEADERS += \ lib/zlog.h \ lib/zlog_targets.h \ lib/pbr.h \ + lib/routing_nb.h \ # end diff --git a/lib/thread.c b/lib/thread.c index 9b2f5661ac..5c7c104842 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -305,8 +305,7 @@ DEFUN (show_thread_cpu, filter = parse_filter(argv[idx]->arg); if (!filter) { vty_out(vty, - "Invalid filter \"%s\" specified; must contain at least" - "one of 'RWTEXB'\n", + "Invalid filter \"%s\" specified; must contain at leastone of 'RWTEXB'\n", argv[idx]->arg); return CMD_WARNING; } @@ -393,8 +392,7 @@ DEFUN (clear_thread_cpu, filter = parse_filter(argv[idx]->arg); if (!filter) { vty_out(vty, - "Invalid filter \"%s\" specified; must contain at least" - "one of 'RWTEXB'\n", + "Invalid filter \"%s\" specified; must contain at leastone of 'RWTEXB'\n", argv[idx]->arg); return CMD_WARNING; } @@ -691,8 +691,7 @@ int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf, char *pathname, return CMD_SUCCESS; if (vty) vty_out(vty, - "NS %s is already configured" - " with VRF %u(%s)\n", + "NS %s is already configured with VRF %u(%s)\n", ns->name, vrf2->vrf_id, vrf2->name); else zlog_info("NS %s is already configured with VRF %u(%s)", @@ -758,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"); @@ -1244,8 +1244,7 @@ static int vty_telnet_option(struct vty *vty, unsigned char *buf, int nbytes) if (vty->sb_len != TELNET_NAWS_SB_LEN) flog_err( EC_LIB_SYSTEM_CALL, - "RFC 1073 violation detected: telnet NAWS option " - "should send %d characters, but we received %lu", + "RFC 1073 violation detected: telnet NAWS option should send %d characters, but we received %lu", TELNET_NAWS_SB_LEN, (unsigned long)vty->sb_len); else if (sizeof(vty->sb_buf) < TELNET_NAWS_SB_LEN) @@ -1261,8 +1260,7 @@ static int vty_telnet_option(struct vty *vty, unsigned char *buf, int nbytes) | vty->sb_buf[4]); #ifdef TELNET_OPTION_DEBUG vty_out(vty, - "TELNET NAWS window size negotiation completed: " - "width %d, height %d\n", + "TELNET NAWS window size negotiation completed: width %d, height %d\n", vty->width, vty->height); #endif } diff --git a/lib/yang.c b/lib/yang.c index 0714ddf7bb..db99c0339e 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -749,3 +749,147 @@ void yang_terminate(void) ly_ctx_destroy(ly_native_ctx, NULL); } + +const struct lyd_node *yang_dnode_get_parent(const struct lyd_node *dnode, + const char *name) +{ + const struct lyd_node *orig_dnode = dnode; + + while (orig_dnode) { + switch (orig_dnode->schema->nodetype) { + case LYS_LIST: + case LYS_CONTAINER: + if (!strcmp(orig_dnode->schema->name, name)) + return orig_dnode; + break; + default: + break; + } + + orig_dnode = orig_dnode->parent; + } + + return NULL; +} + +/* API to check if the given node is last node in the list */ +static bool yang_is_last_list_dnode(const struct lyd_node *dnode) +{ + return (((dnode->next == NULL) + || (dnode->next + && (strcmp(dnode->next->schema->name, dnode->schema->name) + != 0))) + && dnode->prev + && ((dnode->prev == dnode) + || (strcmp(dnode->prev->schema->name, dnode->schema->name) + != 0))); +} + +/* API to check if the given node is last node in the data tree level */ +static bool yang_is_last_level_dnode(const struct lyd_node *dnode) +{ + const struct lyd_node *parent; + const struct lys_node_list *snode; + const struct lyd_node *key_leaf; + uint8_t keys_size; + + switch (dnode->schema->nodetype) { + case LYS_LIST: + assert(dnode->parent); + parent = dnode->parent; + snode = (struct lys_node_list *)parent->schema; + key_leaf = dnode->prev; + for (keys_size = 1; keys_size < snode->keys_size; keys_size++) + key_leaf = key_leaf->prev; + if (key_leaf->prev == dnode) + return true; + break; + case LYS_CONTAINER: + return true; + default: + break; + } + + return false; +} + + +const struct lyd_node * +yang_get_subtree_with_no_sibling(const struct lyd_node *dnode) +{ + bool parent = true; + const struct lyd_node *node; + const struct lys_node_container *snode; + + node = dnode; + if (node->schema->nodetype != LYS_LIST) + return node; + + while (parent) { + switch (node->schema->nodetype) { + case LYS_CONTAINER: + snode = (struct lys_node_container *)node->schema; + if ((!snode->presence) + && yang_is_last_level_dnode(node)) { + if (node->parent + && (node->parent->schema->module + == dnode->schema->module)) + node = node->parent; + else + parent = false; + } else + parent = false; + break; + case LYS_LIST: + if (yang_is_last_list_dnode(node) + && yang_is_last_level_dnode(node)) { + if (node->parent + && (node->parent->schema->module + == dnode->schema->module)) + node = node->parent; + else + parent = false; + } else + parent = false; + break; + default: + parent = false; + break; + } + } + return node; +} + +uint32_t yang_get_list_pos(const struct lyd_node *node) +{ + return lyd_list_pos(node); +} + +uint32_t yang_get_list_elements_count(const struct lyd_node *node) +{ + unsigned int count; + struct lys_node *schema; + + if (!node + || ((node->schema->nodetype != LYS_LIST) + && (node->schema->nodetype != LYS_LEAFLIST))) { + return 0; + } + + schema = node->schema; + count = 0; + do { + if (node->schema == schema) + ++count; + node = node->next; + } while (node); + return count; +} + + +const struct lyd_node *yang_dnode_get_child(const struct lyd_node *dnode) +{ + if (dnode) + return dnode->child; + return NULL; +} diff --git a/lib/yang.h b/lib/yang.h index 85ef0d758c..d526d2f5d6 100644 --- a/lib/yang.h +++ b/lib/yang.h @@ -34,7 +34,7 @@ extern "C" { #endif /* Maximum XPath length. */ -#define XPATH_MAXLEN 512 +#define XPATH_MAXLEN 1024 /* Maximum list key length. */ #define LIST_MAXKEYS 8 @@ -551,6 +551,57 @@ extern void yang_init(bool embedded_modules); */ extern void yang_terminate(void); +/* + * API to return the parent dnode having a given schema-node name + * Use case: One has to access the parent dnode's private pointer + * for a given child node. + * For that there is a need to find parent dnode first. + * + * dnode The starting node to work on + * + * name The name of container/list schema-node + * + * Returns The dnode matched with the given name + */ +extern const struct lyd_node * +yang_dnode_get_parent(const struct lyd_node *dnode, const char *name); + + +/* + * In some cases there is a need to auto delete the parent nodes + * if the given node is last in the list. + * It tries to delete all the parents in a given tree in a given module. + * The use case is with static routes and route maps + * example : ip route 1.1.1.1/32 ens33 + * ip route 1.1.1.1/32 ens34 + * After this no ip route 1.1.1.1/32 ens34 came, now staticd + * has to find out upto which level it has to delete the dnodes. + * For this case it has to send delete nexthop + * After this no ip route 1.1.1.1/32 ens33 came, now staticd has to + * clear nexthop, path and route nodes. + * The same scheme is required for routemaps also + * dnode The starting node to work on + * + * Returns The final parent node selected for deletion + */ +extern const struct lyd_node * +yang_get_subtree_with_no_sibling(const struct lyd_node *dnode); + +/* To get the relative position of a node in list */ +extern uint32_t yang_get_list_pos(const struct lyd_node *node); + +/* To get the number of elements in a list + * + * dnode : The head of list + * Returns : The number of dnodes present in the list + */ +extern uint32_t yang_get_list_elements_count(const struct lyd_node *node); + + +/* To get the immediate child of a dnode */ +const struct lyd_node *yang_dnode_get_child(const struct lyd_node *dnode); + + #ifdef __cplusplus } #endif diff --git a/lib/yang_wrappers.c b/lib/yang_wrappers.c index c31ba3fcc0..8b0e89d52e 100644 --- a/lib/yang_wrappers.c +++ b/lib/yang_wrappers.c @@ -1191,3 +1191,38 @@ const char *yang_nexthop_type2str(uint32_t ntype) break; } } + + +const char *yang_afi_safi_value2identity(afi_t afi, safi_t safi) +{ + if (afi == AFI_IP && safi == SAFI_UNICAST) + return "frr-routing:ipv4-unicast"; + if (afi == AFI_IP6 && safi == SAFI_UNICAST) + return "frr-routing:ipv6-unicast"; + if (afi == AFI_IP && safi == SAFI_MULTICAST) + return "frr-routing:ipv4-multicast"; + if (afi == AFI_IP6 && safi == SAFI_MULTICAST) + return "frr-routing:ipv6-multicast"; + + return NULL; +} + +void yang_afi_safi_identity2value(const char *key, afi_t *afi, safi_t *safi) +{ + if (strmatch(key, "frr-routing:ipv4-unicast")) { + *afi = AFI_IP; + *safi = SAFI_UNICAST; + } else if (strmatch(key, "frr-routing:ipv6-unicast")) { + *afi = AFI_IP6; + *safi = SAFI_UNICAST; + } else if (strmatch(key, "frr-routing:ipv4-multicast")) { + *afi = AFI_IP; + *safi = SAFI_MULTICAST; + } else if (strmatch(key, "frr-routing:ipv6-multicast")) { + *afi = AFI_IP6; + *safi = SAFI_MULTICAST; + } else { + *afi = AFI_UNSPEC; + *safi = SAFI_UNSPEC; + } +} diff --git a/lib/yang_wrappers.h b/lib/yang_wrappers.h index ba2cf5139c..335ff319d5 100644 --- a/lib/yang_wrappers.h +++ b/lib/yang_wrappers.h @@ -191,6 +191,9 @@ extern struct yang_data *yang_data_new_date_and_time(const char *xpath, /* nexthop enum2str */ extern const char *yang_nexthop_type2str(uint32_t ntype); +const char *yang_afi_safi_value2identity(afi_t afi, safi_t safi); +void yang_afi_safi_identity2value(const char *key, afi_t *afi, safi_t *safi); + #ifdef __cplusplus } #endif diff --git a/lib/zclient.c b/lib/zclient.c index 793864243c..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; @@ -1924,8 +1945,7 @@ static int link_params_set_value(struct stream *s, struct if_link_params *iflp) if (i < bwclassnum) flog_err( EC_LIB_ZAPI_MISSMATCH, - "%s: received %d > %d (MAX_CLASS_TYPE) bw entries" - " - outdated library?", + "%s: received %d > %d (MAX_CLASS_TYPE) bw entries - outdated library?", __func__, bwclassnum, MAX_CLASS_TYPE); } STREAM_GETL(s, iflp->admin_grp); 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; diff --git a/m4/ax_python.m4 b/m4/ax_python.m4 index 9f43ea0ab1..91d12b99b4 100644 --- a/m4/ax_python.m4 +++ b/m4/ax_python.m4 @@ -186,7 +186,8 @@ AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_MSG_RESULT([yes]) PYTHON_CFLAGS="`\"$pycfg\" --includes`" - if test x"${py_ver}" = x"3.8" || test x"{py_ver}" = x"3.9"; then + minor_ver=${py_ver#*\.} + if test $((minor_ver)) -gt 7; then PYTHON_LIBS="`\"$pycfg\" --ldflags --embed`" else PYTHON_LIBS="`\"$pycfg\" --ldflags`" diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index f242c2e367..e4270f09a5 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -170,8 +170,7 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, prefix2str(&api.prefix, buf[0], sizeof(buf[0])); zlog_debug( - "Zebra send: route %s %s nexthop %s metric %u" - " count %d dev %s", + "Zebra send: route %s %s nexthop %s metric %u count %d dev %s", add ? "add" : "del", buf[0], nexthop ? inet_ntop(api.prefix.family, &api_nh->gate, buf[1], sizeof(buf[1])) diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c index 9fe077b544..713ce26ecb 100644 --- a/ospf6d/ospf6_area.c +++ b/ospf6d/ospf6_area.c @@ -379,22 +379,6 @@ void ospf6_area_show(struct vty *vty, struct ospf6_area *oa) vty_out(vty, "SPF has not been run\n"); } - -#define OSPF6_CMD_AREA_GET(str, oa) \ - { \ - char *ep; \ - uint32_t area_id = htonl(strtoul(str, &ep, 10)); \ - if (*ep && inet_pton(AF_INET, str, &area_id) != 1) { \ - vty_out(vty, "Malformed Area-ID: %s\n", str); \ - return CMD_SUCCESS; \ - } \ - int format = !*ep ? OSPF6_AREA_FMT_DECIMAL \ - : OSPF6_AREA_FMT_DOTTEDQUAD; \ - oa = ospf6_area_lookup(area_id, ospf6); \ - if (oa == NULL) \ - oa = ospf6_area_create(area_id, ospf6, format); \ - } - DEFUN (area_range, area_range_cmd, "area <A.B.C.D|(0-4294967295)> range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>]", diff --git a/ospf6d/ospf6_area.h b/ospf6d/ospf6_area.h index c77b6d89a9..f6287660d6 100644 --- a/ospf6d/ospf6_area.h +++ b/ospf6d/ospf6_area.h @@ -117,6 +117,21 @@ struct ospf6_area { #define IS_AREA_TRANSIT(oa) (CHECK_FLAG ((oa)->flag, OSPF6_AREA_TRANSIT)) #define IS_AREA_STUB(oa) (CHECK_FLAG ((oa)->flag, OSPF6_AREA_STUB)) +#define OSPF6_CMD_AREA_GET(str, oa) \ + { \ + char *ep; \ + uint32_t area_id = htonl(strtoul(str, &ep, 10)); \ + if (*ep && inet_pton(AF_INET, str, &area_id) != 1) { \ + vty_out(vty, "Malformed Area-ID: %s\n", str); \ + return CMD_SUCCESS; \ + } \ + int format = !*ep ? OSPF6_AREA_FMT_DECIMAL \ + : OSPF6_AREA_FMT_DOTTEDQUAD; \ + oa = ospf6_area_lookup(area_id, ospf6); \ + if (oa == NULL) \ + oa = ospf6_area_create(area_id, ospf6, format); \ + } + /* prototypes */ extern int ospf6_area_cmp(void *va, void *vb); diff --git a/ospf6d/ospf6_bfd.c b/ospf6d/ospf6_bfd.c index 4e7a0050aa..916e59baf0 100644 --- a/ospf6d/ospf6_bfd.c +++ b/ospf6d/ospf6_bfd.c @@ -308,7 +308,7 @@ static void ospf6_bfd_if_param_set(struct ospf6_interface *oi, uint32_t min_rx, int command = 0; bfd_set_param((struct bfd_info **)&(oi->bfd_info), min_rx, min_tx, - detect_mult, defaults, &command); + detect_mult, NULL, defaults, &command); if (command) ospf6_bfd_reg_dereg_all_nbr(oi, command); } diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 1209997514..d10329a93b 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -1966,8 +1966,7 @@ static int ospf6_ifp_up(struct interface *ifp) { if (IS_OSPF6_DEBUG_ZEBRA(RECV)) zlog_debug( - "Zebra Interface state change: " - "%s index %d flags %llx metric %d mtu %d bandwidth %d", + "Zebra Interface state change: %s index %d flags %llx metric %d mtu %d bandwidth %d", ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, ifp->metric, ifp->mtu6, ifp->bandwidth); @@ -1980,8 +1979,7 @@ static int ospf6_ifp_down(struct interface *ifp) { if (IS_OSPF6_DEBUG_ZEBRA(RECV)) zlog_debug( - "Zebra Interface state change: " - "%s index %d flags %llx metric %d mtu %d bandwidth %d", + "Zebra Interface state change: %s index %d flags %llx metric %d mtu %d bandwidth %d", ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, ifp->metric, ifp->mtu6, ifp->bandwidth); diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c index 80bff5795f..e75c132956 100644 --- a/ospf6d/ospf6_spf.c +++ b/ospf6d/ospf6_spf.c @@ -658,8 +658,7 @@ static int ospf6_spf_calculation_thread(struct thread *t) (long long)runtime.tv_usec); zlog_info( - "SPF processing: # Areas: %d, SPF runtime: %lld sec %lld usec, " - "Reason: %s\n", + "SPF processing: # Areas: %d, SPF runtime: %lld sec %lld usec, Reason: %s\n", areas_processed, (long long)runtime.tv_sec, (long long)runtime.tv_usec, rbuf); diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index dd672dd1c5..50687a7290 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -390,8 +390,7 @@ DEFUN(ospf6_router_id, for (ALL_LIST_ELEMENTS_RO(o->area_list, node, oa)) { if (oa->full_nbrs) { vty_out(vty, - "For this router-id change to take effect," - " save config and restart ospf6d\n"); + "For this router-id change to take effect, save config and restart ospf6d\n"); return CMD_SUCCESS; } } @@ -417,8 +416,7 @@ DEFUN(no_ospf6_router_id, for (ALL_LIST_ELEMENTS_RO(o->area_list, node, oa)) { if (oa->full_nbrs) { vty_out(vty, - "For this router-id change to take effect," - " save config and restart ospf6d\n"); + "For this router-id change to take effect, save config and restart ospf6d\n"); return CMD_SUCCESS; } } @@ -644,11 +642,12 @@ DEFUN (no_ospf6_distance_source, DEFUN (ospf6_interface_area, ospf6_interface_area_cmd, - "interface IFNAME area A.B.C.D", + "interface IFNAME area <A.B.C.D|(0-4294967295)>", "Enable routing on an IPv6 interface\n" IFNAME_STR "Specify the OSPF6 area ID\n" "OSPF6 area ID in IPv4 address notation\n" + "OSPF6 area ID in decimal notation\n" ) { VTY_DECLVAR_CONTEXT(ospf6, o); @@ -657,7 +656,6 @@ DEFUN (ospf6_interface_area, struct ospf6_area *oa; struct ospf6_interface *oi; struct interface *ifp; - uint32_t area_id; /* find/create ospf6 interface */ ifp = if_get_by_name(argv[idx_ifname]->arg, VRF_DEFAULT); @@ -671,15 +669,7 @@ DEFUN (ospf6_interface_area, } /* parse Area-ID */ - if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) { - vty_out(vty, "Invalid Area-ID: %s\n", argv[idx_ipv4]->arg); - return CMD_SUCCESS; - } - - /* find/create ospf6 area */ - oa = ospf6_area_lookup(area_id, o); - if (oa == NULL) - oa = ospf6_area_create(area_id, o, OSPF6_AREA_FMT_DOTTEDQUAD); + OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa); /* attach interface to area */ listnode_add(oa->if_list, oi); /* sort ?? */ @@ -703,12 +693,13 @@ DEFUN (ospf6_interface_area, DEFUN (no_ospf6_interface_area, no_ospf6_interface_area_cmd, - "no interface IFNAME area A.B.C.D", + "no interface IFNAME area <A.B.C.D|(0-4294967295)>", NO_STR "Disable routing on an IPv6 interface\n" IFNAME_STR "Specify the OSPF6 area ID\n" "OSPF6 area ID in IPv4 address notation\n" + "OSPF6 area ID in decimal notation\n" ) { int idx_ifname = 2; @@ -731,10 +722,8 @@ DEFUN (no_ospf6_interface_area, } /* parse Area-ID */ - if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) { - vty_out(vty, "Invalid Area-ID: %s\n", argv[idx_ipv4]->arg); - return CMD_SUCCESS; - } + if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) + area_id = htonl(strtoul(argv[idx_ipv4]->arg, NULL, 10)); /* Verify Area */ if (oi->area == NULL) { diff --git a/ospfd/ospf_abr.c b/ospfd/ospf_abr.c index eb3323997f..3dbc476172 100644 --- a/ospfd/ospf_abr.c +++ b/ospfd/ospf_abr.c @@ -348,8 +348,7 @@ static int ospf_abr_nssa_am_elected(struct ospf_area *area) if (IS_ROUTER_LSA_NT(rlsa)) { if (IS_DEBUG_OSPF_NSSA) zlog_debug( - "ospf_abr_nssa_am_elected: " - "router %s asserts Nt", + "ospf_abr_nssa_am_elected: router %s asserts Nt", inet_ntoa(lsa->data->id)); return 0; } @@ -391,15 +390,13 @@ static void ospf_abr_nssa_check_status(struct ospf *ospf) if (IS_DEBUG_OSPF(nssa, NSSA)) zlog_debug( - "ospf_abr_nssa_check_status: " - "checking area %s", + "ospf_abr_nssa_check_status: checking area %s", inet_ntoa(area->area_id)); if (!IS_OSPF_ABR(area->ospf)) { if (IS_DEBUG_OSPF(nssa, NSSA)) zlog_debug( - "ospf_abr_nssa_check_status: " - "not ABR"); + "ospf_abr_nssa_check_status: not ABR"); area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED; } else { @@ -409,8 +406,7 @@ static void ospf_abr_nssa_check_status(struct ospf *ospf) /* TODO: check previous state and flush? */ if (IS_DEBUG_OSPF(nssa, NSSA)) zlog_debug( - "ospf_abr_nssa_check_status: " - "never translate"); + "ospf_abr_nssa_check_status: never translate"); area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED; break; @@ -422,8 +418,7 @@ static void ospf_abr_nssa_check_status(struct ospf *ospf) */ if (IS_DEBUG_OSPF(nssa, NSSA)) zlog_debug( - "ospf_abr_nssa_check_status: " - "translate always"); + "ospf_abr_nssa_check_status: translate always"); area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_ENABLED; break; @@ -435,15 +430,13 @@ static void ospf_abr_nssa_check_status(struct ospf *ospf) OSPF_NSSA_TRANSLATE_ENABLED; if (IS_DEBUG_OSPF(nssa, NSSA)) zlog_debug( - "ospf_abr_nssa_check_status: " - "elected translator"); + "ospf_abr_nssa_check_status: elected translator"); } else { area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED; if (IS_DEBUG_OSPF(nssa, NSSA)) zlog_debug( - "ospf_abr_nssa_check_status: " - "not elected"); + "ospf_abr_nssa_check_status: not elected"); } break; } @@ -639,8 +632,7 @@ static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa) if (ext7->e[0].fwd_addr.s_addr == OSPF_DEFAULT_DESTINATION) { if (IS_DEBUG_OSPF_NSSA) zlog_debug( - "ospf_abr_translate_nssa(): LSA Id %s, " - "Forward address is 0, NO Translation", + "ospf_abr_translate_nssa(): LSA Id %s, Forward address is 0, NO Translation", inet_ntoa(lsa->data->id)); return 1; } @@ -652,8 +644,7 @@ static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa) if (old) { if (IS_DEBUG_OSPF_NSSA) zlog_debug( - "ospf_abr_translate_nssa(): " - "found old translated LSA Id %s, refreshing", + "ospf_abr_translate_nssa(): found old translated LSA Id %s, refreshing", inet_ntoa(old->data->id)); /* refresh */ @@ -661,8 +652,7 @@ static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa) if (!new) { if (IS_DEBUG_OSPF_NSSA) zlog_debug( - "ospf_abr_translate_nssa(): " - "could not refresh translated LSA Id %s", + "ospf_abr_translate_nssa(): could not refresh translated LSA Id %s", inet_ntoa(old->data->id)); } } else { @@ -673,8 +663,7 @@ static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa) if (ospf_translated_nssa_originate(area->ospf, lsa) == NULL) { if (IS_DEBUG_OSPF_NSSA) zlog_debug( - "ospf_abr_translate_nssa(): Could not translate " - "Type-7 for %s to Type-5", + "ospf_abr_translate_nssa(): Could not translate Type-7 for %s to Type-5", inet_ntoa(lsa->data->id)); return 1; } @@ -719,8 +708,7 @@ void ospf_abr_announce_network_to_area(struct prefix_ipv4 *p, uint32_t cost, if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_announce_network_to_area(): " - "old metric: %d, new metric: %d", + "ospf_abr_announce_network_to_area(): old metric: %d, new metric: %d", GET_METRIC(sl->metric), cost); if ((GET_METRIC(sl->metric) == full_cost) @@ -728,15 +716,13 @@ void ospf_abr_announce_network_to_area(struct prefix_ipv4 *p, uint32_t cost, /* unchanged. simply reapprove it */ if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_announce_network_to_area(): " - "old summary approved"); + "ospf_abr_announce_network_to_area(): old summary approved"); SET_FLAG(old->flags, OSPF_LSA_APPROVED); } else { /* LSA is changed, refresh it */ if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_announce_network_to_area(): " - "refreshing summary"); + "ospf_abr_announce_network_to_area(): refreshing summary"); set_metric(old, full_cost); lsa = ospf_lsa_refresh(area->ospf, old); @@ -758,8 +744,7 @@ void ospf_abr_announce_network_to_area(struct prefix_ipv4 *p, uint32_t cost, } else { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_announce_network_to_area(): " - "creating new summary"); + "ospf_abr_announce_network_to_area(): creating new summary"); lsa = ospf_summary_lsa_originate(p, full_cost, area); /* This will flood through area. */ @@ -776,8 +761,7 @@ void ospf_abr_announce_network_to_area(struct prefix_ipv4 *p, uint32_t cost, SET_FLAG(lsa->flags, OSPF_LSA_APPROVED); if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_announce_network_to_area(): " - "flooding new version of summary"); + "ospf_abr_announce_network_to_area(): flooding new version of summary"); } if (IS_DEBUG_OSPF_EVENT) @@ -875,8 +859,7 @@ static void ospf_abr_announce_network(struct ospf *ospf, struct prefix_ipv4 *p, if (!ospf_abr_should_accept(p, area)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_announce_network(): " - "prefix %s/%d was denied by import-list", + "ospf_abr_announce_network(): prefix %s/%d was denied by import-list", inet_ntoa(p->prefix), p->prefixlen); continue; } @@ -884,8 +867,7 @@ static void ospf_abr_announce_network(struct ospf *ospf, struct prefix_ipv4 *p, if (!ospf_abr_plist_in_check(area, or, p)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_announce_network(): " - "prefix %s/%d was denied by prefix-list", + "ospf_abr_announce_network(): prefix %s/%d was denied by prefix-list", inet_ntoa(p->prefix), p->prefixlen); continue; } @@ -894,8 +876,7 @@ static void ospf_abr_announce_network(struct ospf *ospf, struct prefix_ipv4 *p, && area->no_summary) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_announce_network(): " - "area %s is stub and no_summary", + "ospf_abr_announce_network(): area %s is stub and no_summary", inet_ntoa(area->area_id)); continue; } @@ -903,8 +884,7 @@ static void ospf_abr_announce_network(struct ospf *ospf, struct prefix_ipv4 *p, if (or->path_type == OSPF_PATH_INTER_AREA) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_announce_network(): this is " - "inter-area route to %s/%d", + "ospf_abr_announce_network(): this is inter-area route to %s/%d", inet_ntoa(p->prefix), p->prefixlen); if (!OSPF_IS_AREA_BACKBONE(area)) @@ -915,8 +895,7 @@ static void ospf_abr_announce_network(struct ospf *ospf, struct prefix_ipv4 *p, if (or->path_type == OSPF_PATH_INTRA_AREA) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_announce_network(): " - "this is intra-area route to %s/%d", + "ospf_abr_announce_network(): this is intra-area route to %s/%d", inet_ntoa(p->prefix), p->prefixlen); if ((range = ospf_area_range_match(or_area, p)) && !ospf_area_is_transit(area)) @@ -976,8 +955,7 @@ static void ospf_abr_process_nssa_translates(struct ospf *ospf) if (IS_DEBUG_OSPF_NSSA) zlog_debug( - "ospf_abr_process_nssa_translates(): " - "looking at area %s", + "ospf_abr_process_nssa_translates(): looking at area %s", inet_ntoa(area->area_id)); LSDB_LOOP (NSSA_LSDB(area), rn, lsa) @@ -1018,24 +996,21 @@ static void ospf_abr_process_network_rt(struct ospf *ospf, if (or->path_type >= OSPF_PATH_TYPE1_EXTERNAL) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_process_network_rt(): " - "this is an External router, skipping"); + "ospf_abr_process_network_rt(): this is an External router, skipping"); continue; } if (or->cost >= OSPF_LS_INFINITY) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_process_network_rt():" - " this route's cost is infinity, skipping"); + "ospf_abr_process_network_rt(): this route's cost is infinity, skipping"); continue; } if (or->type == OSPF_DESTINATION_DISCARD) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_process_network_rt():" - " this is a discard entry, skipping"); + "ospf_abr_process_network_rt(): this is a discard entry, skipping"); continue; } @@ -1065,8 +1040,7 @@ static void ospf_abr_process_network_rt(struct ospf *ospf, && !OSPF_IS_AREA_ID_BACKBONE(or->u.std.area_id)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_process_network_rt():" - " this is route is not backbone one, skipping"); + "ospf_abr_process_network_rt(): this is route is not backbone one, skipping"); continue; } @@ -1078,8 +1052,7 @@ static void ospf_abr_process_network_rt(struct ospf *ospf, or->path_type != OSPF_PATH_INTRA_AREA) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_process_network_rt(): ALT ABR: " - "No BB connection, skip not intra-area routes"); + "ospf_abr_process_network_rt(): ALT ABR: No BB connection, skip not intra-area routes"); continue; } @@ -1112,8 +1085,7 @@ static void ospf_abr_announce_rtr_to_area(struct prefix_ipv4 *p, uint32_t cost, if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_announce_network_to_area(): " - "old metric: %d, new metric: %d", + "ospf_abr_announce_network_to_area(): old metric: %d, new metric: %d", GET_METRIC(slsa->metric), cost); } @@ -1144,8 +1116,7 @@ static void ospf_abr_announce_rtr_to_area(struct prefix_ipv4 *p, uint32_t cost, if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_announce_rtr_to_area(): " - "flooding new version of summary"); + "ospf_abr_announce_rtr_to_area(): flooding new version of summary"); /* zlog_info ("ospf_abr_announce_rtr_to_area(): creating new @@ -1185,8 +1156,7 @@ static void ospf_abr_announce_rtr(struct ospf *ospf, struct prefix_ipv4 *p, if (area->external_routing != OSPF_AREA_DEFAULT) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_announce_rtr(): " - "area %s doesn't support external routing", + "ospf_abr_announce_rtr(): area %s doesn't support external routing", inet_ntoa(area->area_id)); continue; } @@ -1194,8 +1164,7 @@ static void ospf_abr_announce_rtr(struct ospf *ospf, struct prefix_ipv4 *p, if (or->path_type == OSPF_PATH_INTER_AREA) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_announce_rtr(): " - "this is inter-area route to %s", + "ospf_abr_announce_rtr(): this is inter-area route to %s", inet_ntoa(p->prefix)); if (!OSPF_IS_AREA_BACKBONE(area)) ospf_abr_announce_rtr_to_area(p, or->cost, @@ -1205,8 +1174,7 @@ static void ospf_abr_announce_rtr(struct ospf *ospf, struct prefix_ipv4 *p, if (or->path_type == OSPF_PATH_INTRA_AREA) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_announce_rtr(): " - "this is intra-area route to %s", + "ospf_abr_announce_rtr(): this is intra-area route to %s", inet_ntoa(p->prefix)); ospf_abr_announce_rtr_to_area(p, or->cost, area); } @@ -1255,8 +1223,7 @@ static void ospf_abr_process_router_rt(struct ospf *ospf, if (!CHECK_FLAG(or->u.std.flags, ROUTER_LSA_EXTERNAL)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_process_router_rt(): " - "This is not an ASBR, skipping"); + "ospf_abr_process_router_rt(): This is not an ASBR, skipping"); continue; } @@ -1272,8 +1239,7 @@ static void ospf_abr_process_router_rt(struct ospf *ospf, if (or != best) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_process_router_rt(): " - "This route is not the best among possible, skipping"); + "ospf_abr_process_router_rt(): This route is not the best among possible, skipping"); continue; } @@ -1283,16 +1249,14 @@ static void ospf_abr_process_router_rt(struct ospf *ospf, or->u.std.area_id)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_process_router_rt(): " - "This route is not a backbone one, skipping"); + "ospf_abr_process_router_rt(): This route is not a backbone one, skipping"); continue; } if (or->cost >= OSPF_LS_INFINITY) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_process_router_rt(): " - "This route has LS_INFINITY metric, skipping"); + "ospf_abr_process_router_rt(): This route has LS_INFINITY metric, skipping"); continue; } @@ -1302,8 +1266,7 @@ static void ospf_abr_process_router_rt(struct ospf *ospf, or->path_type != OSPF_PATH_INTRA_AREA) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_process_network_rt(): ALT ABR: " - "No BB connection, skip not intra-area routes"); + "ospf_abr_process_network_rt(): ALT ABR: No BB connection, skip not intra-area routes"); continue; } @@ -1333,8 +1296,7 @@ ospf_abr_unapprove_translates(struct ospf *ospf) /* For NSSA Translations */ UNSET_FLAG(lsa->flags, OSPF_LSA_APPROVED); if (IS_DEBUG_OSPF_NSSA) zlog_debug( - "ospf_abr_unapprove_translates(): " - "approved unset on link id %s", + "ospf_abr_unapprove_translates(): approved unset on link id %s", inet_ntoa(lsa->data->id)); } @@ -1355,15 +1317,13 @@ static void ospf_abr_unapprove_summaries(struct ospf *ospf) for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_unapprove_summaries(): " - "considering area %s", + "ospf_abr_unapprove_summaries(): considering area %s", inet_ntoa(area->area_id)); LSDB_LOOP (SUMMARY_LSDB(area), rn, lsa) if (ospf_lsa_is_self_originated(ospf, lsa)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_unapprove_summaries(): " - "approved unset on summary link id %s", + "ospf_abr_unapprove_summaries(): approved unset on summary link id %s", inet_ntoa(lsa->data->id)); UNSET_FLAG(lsa->flags, OSPF_LSA_APPROVED); } @@ -1372,8 +1332,7 @@ static void ospf_abr_unapprove_summaries(struct ospf *ospf) if (ospf_lsa_is_self_originated(ospf, lsa)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_unapprove_summaries(): " - "approved unset on asbr-summary link id %s", + "ospf_abr_unapprove_summaries(): approved unset on asbr-summary link id %s", inet_ntoa(lsa->data->id)); UNSET_FLAG(lsa->flags, OSPF_LSA_APPROVED); } @@ -1428,8 +1387,7 @@ static void ospf_abr_announce_aggregates(struct ospf *ospf) OSPF_AREA_RANGE_ADVERTISE)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_announce_aggregates():" - " discarding suppress-ranges"); + "ospf_abr_announce_aggregates(): discarding suppress-ranges"); continue; } @@ -1439,8 +1397,7 @@ static void ospf_abr_announce_aggregates(struct ospf *ospf) if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_announce_aggregates():" - " this is range: %s/%d", + "ospf_abr_announce_aggregates(): this is range: %s/%d", inet_ntoa(p.u.prefix4), p.prefixlen); @@ -1477,9 +1434,7 @@ static void ospf_abr_announce_aggregates(struct ospf *ospf) area)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_announce_aggregates(): Skipping " - "announcement of BB aggregate into" - " a transit area"); + "ospf_abr_announce_aggregates(): Skipping announcement of BB aggregate into a transit area"); continue; } ospf_abr_announce_network_to_area( @@ -1526,8 +1481,7 @@ ospf_abr_send_nssa_aggregates(struct ospf *ospf) /* temporarily turned off */ OSPF_AREA_RANGE_ADVERTISE)) { if (IS_DEBUG_OSPF_NSSA) zlog_debug( - "ospf_abr_send_nssa_aggregates():" - " discarding suppress-ranges"); + "ospf_abr_send_nssa_aggregates(): discarding suppress-ranges"); continue; } @@ -1537,8 +1491,7 @@ ospf_abr_send_nssa_aggregates(struct ospf *ospf) /* temporarily turned off */ if (IS_DEBUG_OSPF_NSSA) zlog_debug( - "ospf_abr_send_nssa_aggregates():" - " this is range: %s/%d", + "ospf_abr_send_nssa_aggregates(): this is range: %s/%d", inet_ntoa(p.prefix), p.prefixlen); if (CHECK_FLAG(range->flags, @@ -1598,8 +1551,7 @@ static void ospf_abr_announce_stub_defaults(struct ospf *ospf) if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_announce_stub_defaults(): " - "announcing 0.0.0.0/0 to area %s", + "ospf_abr_announce_stub_defaults(): announcing 0.0.0.0/0 to area %s", inet_ntoa(area->area_id)); ospf_abr_announce_network_to_area(&p, area->default_cost, area); } @@ -1614,8 +1566,7 @@ static int ospf_abr_remove_unapproved_translates_apply(struct ospf *ospf, if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT) && !CHECK_FLAG(lsa->flags, OSPF_LSA_APPROVED)) { zlog_info( - "ospf_abr_remove_unapproved_translates(): " - "removing unapproved translates, ID: %s", + "ospf_abr_remove_unapproved_translates(): removing unapproved translates, ID: %s", inet_ntoa(lsa->data->id)); /* FLUSH THROUGHOUT AS */ @@ -1656,8 +1607,7 @@ static void ospf_abr_remove_unapproved_summaries(struct ospf *ospf) for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_remove_unapproved_summaries(): " - "looking at area %s", + "ospf_abr_remove_unapproved_summaries(): looking at area %s", inet_ntoa(area->area_id)); LSDB_LOOP (SUMMARY_LSDB(area), rn, lsa) diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c index 49730063b9..73ce606504 100644 --- a/ospfd/ospf_apiserver.c +++ b/ospfd/ospf_apiserver.c @@ -889,8 +889,7 @@ int ospf_apiserver_register_opaque_type(struct ospf_apiserver *apiserv, if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "API: Add LSA-type(%d)/Opaque-type(%d) into" - " apiserv(%p), total#(%d)", + "API: Add LSA-type(%d)/Opaque-type(%d) into apiserv(%p), total#(%d)", lsa_type, opaque_type, (void *)apiserv, listcount(apiserv->opaque_types)); @@ -920,8 +919,7 @@ int ospf_apiserver_unregister_opaque_type(struct ospf_apiserver *apiserv, if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "API: Del LSA-type(%d)/Opaque-type(%d)" - " from apiserv(%p), total#(%d)", + "API: Del LSA-type(%d)/Opaque-type(%d) from apiserv(%p), total#(%d)", lsa_type, opaque_type, (void *)apiserv, listcount(apiserv->opaque_types)); diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c index 8747dd1f53..d2a30477b0 100644 --- a/ospfd/ospf_ase.c +++ b/ospfd/ospf_ase.c @@ -194,20 +194,17 @@ ospf_ase_calculate_asbr_route (struct ospf *ospf, if (al->e[0].fwd_addr.s_addr != 0) { if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("ospf_ase_calculate(): " - "Forwarding address is not 0.0.0.0."); + zlog_debug ("ospf_ase_calculate(): Forwarding address is not 0.0.0.0."); if (! ospf_ase_forward_address_check (ospf, al->e[0].fwd_addr)) { if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("ospf_ase_calculate(): " - "Forwarding address is one of our addresses, Ignore."); + zlog_debug ("ospf_ase_calculate(): Forwarding address is one of our addresses, Ignore."); return NULL; } if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("ospf_ase_calculate(): " - "Looking up in the Network Routing Table."); + zlog_debug ("ospf_ase_calculate(): Looking up in the Network Routing Table."); /* Looking up the path to the fwd_addr from Network route. */ asbr.family = AF_INET; @@ -219,8 +216,7 @@ ospf_ase_calculate_asbr_route (struct ospf *ospf, if (rn == NULL) { if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("ospf_ase_calculate(): " - "Couldn't find a route to the forwarding address."); + zlog_debug ("ospf_ase_calculate(): Couldn't find a route to the forwarding address."); return NULL; } @@ -229,8 +225,7 @@ ospf_ase_calculate_asbr_route (struct ospf *ospf, if ((asbr_route = rn->info) == NULL) { if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("ospf_ase_calculate(): " - "Somehow OSPF route to ASBR is lost"); + zlog_debug ("ospf_ase_calculate(): Somehow OSPF route to ASBR is lost"); return NULL; } } @@ -393,8 +388,7 @@ int ospf_ase_calculate_route(struct ospf *ospf, struct ospf_lsa *lsa) if (!ospf_ase_forward_address_check(ospf, al->e[0].fwd_addr)) { if (IS_DEBUG_OSPF(lsa, LSA)) zlog_debug( - "Route[External]: Forwarding address is our router " - "address"); + "Route[External]: Forwarding address is our router address"); return 0; } @@ -407,8 +401,7 @@ int ospf_ase_calculate_route(struct ospf *ospf, struct ospf_lsa *lsa) if (rn == NULL || (asbr_route = rn->info) == NULL) { if (IS_DEBUG_OSPF(lsa, LSA)) zlog_debug( - "Route[External]: Can't find route to forwarding " - "address"); + "Route[External]: Can't find route to forwarding address"); if (rn) route_unlock_node(rn); return 0; diff --git a/ospfd/ospf_bfd.c b/ospfd/ospf_bfd.c index b9e78f4cd3..d2c5090f2f 100644 --- a/ospfd/ospf_bfd.c +++ b/ospfd/ospf_bfd.c @@ -381,7 +381,7 @@ static void ospf_bfd_if_param_set(struct interface *ifp, uint32_t min_rx, params = IF_DEF_PARAMS(ifp); bfd_set_param((struct bfd_info **)&(params->bfd_info), min_rx, min_tx, - detect_mult, defaults, &command); + detect_mult, NULL, defaults, &command); if (command) ospf_bfd_reg_dereg_all_nbr(ifp, command); } diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index 3dcb2b481d..dcc479def6 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -53,10 +53,11 @@ unsigned long conf_debug_ospf_nssa = 0; unsigned long conf_debug_ospf_te = 0; unsigned long conf_debug_ospf_ext = 0; unsigned long conf_debug_ospf_sr = 0; +unsigned long conf_debug_ospf_defaultinfo = 0; /* Enable debug option variables -- valid only session. */ unsigned long term_debug_ospf_packet[5] = {0, 0, 0, 0, 0}; -unsigned long term_debug_ospf_event = 0; +unsigned long term_debug_ospf_event; unsigned long term_debug_ospf_ism = 0; unsigned long term_debug_ospf_nsm = 0; unsigned long term_debug_ospf_lsa = 0; @@ -65,6 +66,7 @@ unsigned long term_debug_ospf_nssa = 0; unsigned long term_debug_ospf_te = 0; unsigned long term_debug_ospf_ext = 0; unsigned long term_debug_ospf_sr = 0; +unsigned long term_debug_ospf_defaultinfo; const char *ospf_redist_string(unsigned int route_type) { @@ -1447,6 +1449,33 @@ DEFUN (no_debug_ospf_sr, return CMD_SUCCESS; } +DEFUN (debug_ospf_default_info, + debug_ospf_default_info_cmd, + "debug ospf default-information", + DEBUG_STR + OSPF_STR + "OSPF default information\n") +{ + if (vty->node == CONFIG_NODE) + CONF_DEBUG_ON(defaultinfo, DEFAULTINFO); + TERM_DEBUG_ON(defaultinfo, DEFAULTINFO); + return CMD_SUCCESS; +} + +DEFUN (no_debug_ospf_default_info, + no_debug_ospf_default_info_cmd, + "no debug ospf default-information", + NO_STR + DEBUG_STR + OSPF_STR + "OSPF default information\n") +{ + if (vty->node == CONFIG_NODE) + CONF_DEBUG_OFF(defaultinfo, DEFAULTINFO); + TERM_DEBUG_OFF(defaultinfo, DEFAULTINFO); + return CMD_SUCCESS; +} + DEFUN (no_debug_ospf, no_debug_ospf_cmd, "no debug ospf", @@ -1475,6 +1504,7 @@ DEFUN (no_debug_ospf, DEBUG_OFF(zebra, ZEBRA); DEBUG_OFF(zebra, ZEBRA_INTERFACE); DEBUG_OFF(zebra, ZEBRA_REDISTRIBUTE); + DEBUG_OFF(defaultinfo, DEFAULTINFO); for (i = 0; i < 5; i++) DEBUG_PACKET_OFF(i, flag); @@ -1501,6 +1531,7 @@ DEFUN (no_debug_ospf, TERM_DEBUG_OFF(zebra, ZEBRA); TERM_DEBUG_OFF(zebra, ZEBRA_INTERFACE); TERM_DEBUG_OFF(zebra, ZEBRA_REDISTRIBUTE); + TERM_DEBUG_OFF(defaultinfo, DEFAULTINFO); return CMD_SUCCESS; } @@ -1595,6 +1626,9 @@ static int show_debugging_ospf_common(struct vty *vty, struct ospf *ospf) " OSPF Zebra redistribute debugging is on\n"); } + if (IS_DEBUG_OSPF(defaultinfo, DEFAULTINFO) == OSPF_DEBUG_DEFAULTINFO) + vty_out(vty, "OSPF default information is on\n"); + /* Show debug status for NSSA. */ if (IS_DEBUG_OSPF(nssa, NSSA) == OSPF_DEBUG_NSSA) vty_out(vty, " OSPF NSSA debugging is on\n"); @@ -1797,6 +1831,7 @@ void ospf_debug_init(void) install_element(ENABLE_NODE, &debug_ospf_nssa_cmd); install_element(ENABLE_NODE, &debug_ospf_te_cmd); install_element(ENABLE_NODE, &debug_ospf_sr_cmd); + install_element(ENABLE_NODE, &debug_ospf_default_info_cmd); install_element(ENABLE_NODE, &no_debug_ospf_ism_cmd); install_element(ENABLE_NODE, &no_debug_ospf_nsm_cmd); install_element(ENABLE_NODE, &no_debug_ospf_lsa_cmd); @@ -1805,6 +1840,7 @@ void ospf_debug_init(void) install_element(ENABLE_NODE, &no_debug_ospf_nssa_cmd); install_element(ENABLE_NODE, &no_debug_ospf_te_cmd); install_element(ENABLE_NODE, &no_debug_ospf_sr_cmd); + install_element(ENABLE_NODE, &no_debug_ospf_default_info_cmd); install_element(ENABLE_NODE, &show_debugging_ospf_instance_cmd); install_element(ENABLE_NODE, &debug_ospf_packet_cmd); @@ -1834,6 +1870,7 @@ void ospf_debug_init(void) install_element(CONFIG_NODE, &debug_ospf_nssa_cmd); install_element(CONFIG_NODE, &debug_ospf_te_cmd); install_element(CONFIG_NODE, &debug_ospf_sr_cmd); + install_element(CONFIG_NODE, &debug_ospf_default_info_cmd); install_element(CONFIG_NODE, &no_debug_ospf_nsm_cmd); install_element(CONFIG_NODE, &no_debug_ospf_lsa_cmd); install_element(CONFIG_NODE, &no_debug_ospf_zebra_cmd); @@ -1841,6 +1878,7 @@ void ospf_debug_init(void) install_element(CONFIG_NODE, &no_debug_ospf_nssa_cmd); install_element(CONFIG_NODE, &no_debug_ospf_te_cmd); install_element(CONFIG_NODE, &no_debug_ospf_sr_cmd); + install_element(CONFIG_NODE, &no_debug_ospf_default_info_cmd); install_element(CONFIG_NODE, &debug_ospf_instance_nsm_cmd); install_element(CONFIG_NODE, &debug_ospf_instance_lsa_cmd); diff --git a/ospfd/ospf_dump.h b/ospfd/ospf_dump.h index 6b2ebb125a..8c01977ff8 100644 --- a/ospfd/ospf_dump.h +++ b/ospfd/ospf_dump.h @@ -59,6 +59,7 @@ #define OSPF_DEBUG_TE 0x04 #define OSPF_DEBUG_EXT 0x08 #define OSPF_DEBUG_SR 0x10 +#define OSPF_DEBUG_DEFAULTINFO 0x20 /* Macro for setting debug option. */ #define CONF_DEBUG_PACKET_ON(a, b) conf_debug_ospf_packet[a] |= (b) @@ -104,6 +105,8 @@ #define IS_DEBUG_OSPF_SR IS_DEBUG_OSPF(sr, SR) +#define IS_DEBUG_OSPF_DEFAULT_INFO IS_DEBUG_OSPF(defaultinfo, DEFAULTINFO) + #define IS_CONF_DEBUG_OSPF_PACKET(a, b) \ (conf_debug_ospf_packet[a] & OSPF_DEBUG_##b) #define IS_CONF_DEBUG_OSPF(a, b) (conf_debug_ospf_##a & OSPF_DEBUG_##b) @@ -122,6 +125,7 @@ extern unsigned long term_debug_ospf_nssa; extern unsigned long term_debug_ospf_te; extern unsigned long term_debug_ospf_ext; extern unsigned long term_debug_ospf_sr; +extern unsigned long term_debug_ospf_defaultinfo; /* Message Strings. */ extern char *ospf_lsa_type_str[]; diff --git a/ospfd/ospf_ext.c b/ospfd/ospf_ext.c index 86088a7137..6dd5d78bd0 100644 --- a/ospfd/ospf_ext.c +++ b/ospfd/ospf_ext.c @@ -491,8 +491,7 @@ uint32_t ospf_ext_schedule_prefix_index(struct interface *ifp, uint32_t index, return rc; if (p != NULL) { - osr_debug("EXT (%s): Schedule new prefix %pFX with index %u " - "on interface %s", __func__, p, index, ifp->name); + osr_debug("EXT (%s): Schedule new prefix %pFX with index %u on interface %s", __func__, p, index, ifp->name); /* Set first Extended Prefix then the Prefix SID information */ set_ext_prefix(exti, OSPF_PATH_INTRA_AREA, EXT_TLV_PREF_NFLG, @@ -1006,8 +1005,7 @@ static struct ospf_lsa *ospf_ext_pref_lsa_new(struct ospf_area *area, lsa_header_set(s, options, lsa_type, lsa_id, router_id); osr_debug( - "EXT (%s): LSA[Type%u:%pI4]: Create an Opaque-LSA Extended " - "Prefix Opaque LSA instance", + "EXT (%s): LSA[Type%u:%pI4]: Create an Opaque-LSA Extended Prefix Opaque LSA instance", __func__, lsa_type, &lsa_id); /* Set opaque-LSA body fields. */ @@ -1064,8 +1062,7 @@ static struct ospf_lsa *ospf_ext_link_lsa_new(struct ospf_area *area, lsa_id.s_addr = htonl(tmp); osr_debug( - "EXT (%s) LSA[Type%u:%pI4]: Create an Opaque-LSA Extended " - "Link Opaque LSA instance", + "EXT (%s) LSA[Type%u:%pI4]: Create an Opaque-LSA Extended Link Opaque LSA instance", __func__, lsa_type, &lsa_id); /* Set opaque-LSA header fields. */ @@ -1130,8 +1127,7 @@ static int ospf_ext_pref_lsa_originate1(struct ospf_area *area, ospf_flood_through_area(area, NULL /*nbr */, new); osr_debug( - "EXT (%s): LSA[Type%u:%pI4]: Originate Opaque-LSA" - "Extended Prefix Opaque LSA: Area(%pI4), Link(%s)", + "EXT (%s): LSA[Type%u:%pI4]: Originate Opaque-LSAExtended Prefix Opaque LSA: Area(%pI4), Link(%s)", __func__, new->data->type, &new->data->id, &area->area_id, exti->ifp->name); if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) @@ -1178,8 +1174,7 @@ static int ospf_ext_link_lsa_originate1(struct ospf_area *area, ospf_flood_through_area(area, NULL /*nbr */, new); osr_debug( - "EXT (%s): LSA[Type%u:%pI4]: Originate Opaque-LSA " - "Extended Link Opaque LSA: Area(%pI4), Link(%s)", + "EXT (%s): LSA[Type%u:%pI4]: Originate Opaque-LSA Extended Link Opaque LSA: Area(%pI4), Link(%s)", __func__, new->data->type, &new->data->id, &area->area_id, exti->ifp->name); if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) @@ -1237,8 +1232,7 @@ static int ospf_ext_pref_lsa_originate(void *arg) /* Ok, let's try to originate an LSA */ osr_debug( - "EXT (%s): Let's finally re-originate the LSA 7.0.0.%u " - "for Itf %s", __func__, exti->instance, + "EXT (%s): Let's finally re-originate the LSA 7.0.0.%u for Itf %s", __func__, exti->instance, exti->ifp ? exti->ifp->name : ""); ospf_ext_pref_lsa_originate1(area, exti); } @@ -1300,8 +1294,7 @@ static int ospf_ext_link_lsa_originate(void *arg) /* Ok, let's try to originate an LSA */ osr_debug( - "EXT (%s): Let's finally reoriginate the LSA 8.0.0.%u " - "for Itf %s through the Area %pI4", __func__, + "EXT (%s): Let's finally reoriginate the LSA 8.0.0.%u for Itf %s through the Area %pI4", __func__, exti->instance, exti->ifp ? exti->ifp->name : "-", &area->area_id); ospf_ext_link_lsa_originate1(area, exti); @@ -1625,8 +1618,7 @@ static uint16_t show_vty_ext_link_rmt_itf_addr(struct vty *vty, top = (struct ext_subtlv_rmt_itf_addr *)tlvh; vty_out(vty, - " Remote Interface Address Sub-TLV: Length %u\n " - "Address: %s\n", + " Remote Interface Address Sub-TLV: Length %u\n Address: %s\n", ntohs(top->header.length), inet_ntoa(top->value)); return TLV_SIZE(tlvh); @@ -1639,8 +1631,7 @@ static uint16_t show_vty_ext_link_adj_sid(struct vty *vty, struct ext_subtlv_adj_sid *top = (struct ext_subtlv_adj_sid *)tlvh; vty_out(vty, - " Adj-SID Sub-TLV: Length %u\n\tFlags: " - "0x%x\n\tMT-ID:0x%x\n\tWeight: 0x%x\n\t%s: %u\n", + " Adj-SID Sub-TLV: Length %u\n\tFlags: 0x%x\n\tMT-ID:0x%x\n\tWeight: 0x%x\n\t%s: %u\n", ntohs(top->header.length), top->flags, top->mtid, top->weight, CHECK_FLAG(top->flags, EXT_SUBTLV_LINK_ADJ_SID_VFLG) ? "Label" : "Index", @@ -1659,9 +1650,7 @@ static uint16_t show_vty_ext_link_lan_adj_sid(struct vty *vty, (struct ext_subtlv_lan_adj_sid *)tlvh; vty_out(vty, - " LAN-Adj-SID Sub-TLV: Length %u\n\tFlags: " - "0x%x\n\tMT-ID:0x%x\n\tWeight: 0x%x\n\tNeighbor ID: " - "%s\n\t%s: %u\n", + " LAN-Adj-SID Sub-TLV: Length %u\n\tFlags: 0x%x\n\tMT-ID:0x%x\n\tWeight: 0x%x\n\tNeighbor ID: %s\n\t%s: %u\n", ntohs(top->header.length), top->flags, top->mtid, top->weight, inet_ntoa(top->neighbor_id), CHECK_FLAG(top->flags, EXT_SUBTLV_LINK_ADJ_SID_VFLG) ? "Label" @@ -1749,8 +1738,7 @@ static uint16_t show_vty_ext_pref_pref_sid(struct vty *vty, (struct ext_subtlv_prefix_sid *)tlvh; vty_out(vty, - " Prefix SID Sub-TLV: Length %u\n\tAlgorithm: " - "%u\n\tFlags: 0x%x\n\tMT-ID:0x%x\n\t%s: %u\n", + " Prefix SID Sub-TLV: Length %u\n\tAlgorithm: %u\n\tFlags: 0x%x\n\tMT-ID:0x%x\n\t%s: %u\n", ntohs(top->header.length), top->algorithm, top->flags, top->mtid, CHECK_FLAG(top->flags, EXT_SUBTLV_PREFIX_SID_VFLG) ? "Label" diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index 818e7e72bc..58afb2b392 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -507,8 +507,7 @@ static int ospf_flood_through_interface(struct ospf_interface *oi, if (NBR_IS_DR(inbr) || NBR_IS_BDR(inbr)) { if (IS_DEBUG_OSPF_NSSA) zlog_debug( - "ospf_flood_through_interface(): " - "DR/BDR NOT SEND to int %s", + "ospf_flood_through_interface(): DR/BDR NOT SEND to int %s", IF_NAME(oi)); return 1; } @@ -522,8 +521,7 @@ static int ospf_flood_through_interface(struct ospf_interface *oi, if (oi->state == ISM_Backup) { if (IS_DEBUG_OSPF_NSSA) zlog_debug( - "ospf_flood_through_interface(): " - "ISM_Backup NOT SEND to int %s", + "ospf_flood_through_interface(): ISM_Backup NOT SEND to int %s", IF_NAME(oi)); return 1; } @@ -538,8 +536,7 @@ static int ospf_flood_through_interface(struct ospf_interface *oi, /* XXX HASSO: Is this IS_DEBUG_OSPF_NSSA really correct? */ if (IS_DEBUG_OSPF_NSSA) zlog_debug( - "ospf_flood_through_interface(): " - "DR/BDR sending upd to int %s", + "ospf_flood_through_interface(): DR/BDR sending upd to int %s", IF_NAME(oi)); /* RFC2328 Section 13.3 diff --git a/ospfd/ospf_ia.c b/ospfd/ospf_ia.c index f1ba8a31e8..87929e4369 100644 --- a/ospfd/ospf_ia.c +++ b/ospfd/ospf_ia.c @@ -88,8 +88,7 @@ static void ospf_ia_network_route(struct ospf *ospf, struct route_table *rt, if ((or = rn1->info)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_ia_network_route(): " - "Found a route to the same network"); + "ospf_ia_network_route(): Found a route to the same network"); /* Check the existing route. */ if ((res = ospf_route_cmp(ospf, new_or, or)) < 0) { /* New route is better, so replace old one. */ @@ -151,8 +150,7 @@ static void ospf_ia_router_route(struct ospf *ospf, struct route_table *rtrs, if (or) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_ia_router_route(): " - "a route to the same ABR through the same area exists"); + "ospf_ia_router_route(): a route to the same ABR through the same area exists"); /* New route is better */ if ((ret = ospf_route_cmp(ospf, new_or, or)) < 0) { listnode_delete(rn->info, or); @@ -329,8 +327,7 @@ static void ospf_update_network_route(struct ospf *ospf, struct route_table *rt, backbone paths */ if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_update_network_route(): " - "Allowing Shortcut ABR to add new route"); + "ospf_update_network_route(): Allowing Shortcut ABR to add new route"); new_or = ospf_route_new(); new_or->type = OSPF_DESTINATION_NETWORK; new_or->id = lsa->header.id; @@ -367,8 +364,7 @@ static void ospf_update_network_route(struct ospf *ospf, struct route_table *rt, or->u.std.area_id)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_update_network_route(): Shortcut: " - "this intra-area path is not backbone"); + "ospf_update_network_route(): Shortcut: this intra-area path is not backbone"); return; } } else /* Not Shortcut ABR */ @@ -376,8 +372,7 @@ static void ospf_update_network_route(struct ospf *ospf, struct route_table *rt, if (!OSPF_IS_AREA_ID_BACKBONE(or->u.std.area_id)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_update_network_route(): " - "route is not BB-associated"); + "ospf_update_network_route(): route is not BB-associated"); return; /* We can update only BB routes */ } } @@ -392,16 +387,14 @@ static void ospf_update_network_route(struct ospf *ospf, struct route_table *rt, if (or->cost == cost) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_update_network_route(): " - "new route is same distance, adding nexthops"); + "ospf_update_network_route(): new route is same distance, adding nexthops"); ospf_route_copy_nexthops(or, abr_or->paths); } if (or->cost > cost) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_update_network_route(): " - "new route is better, overriding nexthops"); + "ospf_update_network_route(): new route is better, overriding nexthops"); ospf_route_subst_nexthops(or, abr_or->paths); or->cost = cost; @@ -649,8 +642,7 @@ void ospf_ia_routing(struct ospf *ospf, struct route_table *rt, */ if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_ia_routing(): " - "Active BB connection not found"); + "ospf_ia_routing(): Active BB connection not found"); for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) OSPF_EXAMINE_SUMMARIES_ALL(area, rt, diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index 1622b2fd25..7977a2a9f4 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -839,8 +839,7 @@ struct ospf_interface *ospf_vl_new(struct ospf *ospf, if (vlink_count == OSPF_VL_MAX_COUNT) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_vl_new(): Alarm: " - "cannot create more than OSPF_MAX_VL_COUNT virtual links"); + "ospf_vl_new(): Alarm: cannot create more than OSPF_MAX_VL_COUNT virtual links"); return NULL; } @@ -1118,8 +1117,7 @@ void ospf_vl_up_check(struct ospf_area *area, struct in_addr rid, if (ospf_vl_set_params(vl_data, v)) { if (IS_DEBUG_OSPF(ism, ISM_EVENTS)) zlog_debug( - "ospf_vl_up_check: VL cost change," - " scheduling router lsa refresh"); + "ospf_vl_up_check: VL cost change, scheduling router lsa refresh"); if (ospf->backbone) ospf_router_lsa_update_area( ospf->backbone); diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index d089ea76cd..376310e4ff 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -525,8 +525,7 @@ static int lsa_link_broadcast_set(struct stream **s, struct ospf_interface *oi) if (oi->state == ISM_Waiting) { if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) zlog_debug( - "LSA[Type1]: Interface %s is in state Waiting. " - "Adding stub interface", + "LSA[Type1]: Interface %s is in state Waiting. Adding stub interface", oi->ifp->name); masklen2ip(oi->address->prefixlen, &mask); id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr; @@ -541,8 +540,7 @@ static int lsa_link_broadcast_set(struct stream **s, struct ospf_interface *oi) && ospf_nbr_count(oi, NSM_Full) > 0) { if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) zlog_debug( - "LSA[Type1]: Interface %s has a DR. " - "Adding transit interface", + "LSA[Type1]: Interface %s has a DR. Adding transit interface", oi->ifp->name); return link_info_set(s, DR(oi), oi->address->u.prefix4, LSA_LINK_TYPE_TRANSIT, 0, cost); @@ -551,8 +549,7 @@ static int lsa_link_broadcast_set(struct stream **s, struct ospf_interface *oi) else { if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) zlog_debug( - "LSA[Type1]: Interface %s has no DR. " - "Adding stub interface", + "LSA[Type1]: Interface %s has no DR. Adding stub interface", oi->ifp->name); masklen2ip(oi->address->prefixlen, &mask); id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr; @@ -1084,8 +1081,7 @@ static struct ospf_lsa *ospf_network_lsa_refresh(struct ospf_lsa *lsa) if (oi == NULL) { if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { zlog_debug( - "LSA[Type%d:%s]: network-LSA refresh: " - "no oi found, ick, ignoring.", + "LSA[Type%d:%s]: network-LSA refresh: no oi found, ick, ignoring.", lsa->data->type, inet_ntoa(lsa->data->id)); ospf_lsa_header_dump(lsa->data); } @@ -1761,8 +1757,7 @@ static struct ospf_lsa *ospf_lsa_translated_nssa_new(struct ospf *ospf, == NULL) { if (IS_DEBUG_OSPF_NSSA) zlog_debug( - "ospf_nssa_translate_originate(): Could not originate " - "Translated Type-5 for %s", + "ospf_nssa_translate_originate(): Could not originate Translated Type-5 for %s", inet_ntoa(ei.p.prefix)); return NULL; } @@ -1796,8 +1791,7 @@ struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf, if ((new = ospf_lsa_translated_nssa_new(ospf, type7)) == NULL) { if (IS_DEBUG_OSPF_NSSA) zlog_debug( - "ospf_translated_nssa_originate(): Could not translate " - "Type-7, Id %s, to Type-5", + "ospf_translated_nssa_originate(): Could not translate Type-7, Id %s, to Type-5", inet_ntoa(type7->data->id)); return NULL; } @@ -1806,8 +1800,7 @@ struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf, if (IS_DEBUG_OSPF_NSSA) { zlog_debug( - "ospf_translated_nssa_originate(): " - "translated Type 7, installed:"); + "ospf_translated_nssa_originate(): translated Type 7, installed:"); ospf_lsa_header_dump(new->data); zlog_debug(" Network mask: %d", ip_masklen(extnew->mask)); zlog_debug(" Forward addr: %s", @@ -1816,9 +1809,7 @@ struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf, if ((new = ospf_lsa_install(ospf, NULL, new)) == NULL) { flog_warn(EC_OSPF_LSA_INSTALL_FAILURE, - "ospf_lsa_translated_nssa_originate(): " - "Could not install LSA " - "id %s", + "ospf_lsa_translated_nssa_originate(): Could not install LSA id %s", inet_ntoa(type7->data->id)); return NULL; } @@ -1885,8 +1876,7 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf, if (!type7) { if (IS_DEBUG_OSPF_NSSA) zlog_debug( - "ospf_translated_nssa_refresh(): no Type-7 found for " - "Type-5 LSA Id %s", + "ospf_translated_nssa_refresh(): no Type-7 found for Type-5 LSA Id %s", inet_ntoa(type5->data->id)); return NULL; } @@ -1895,8 +1885,7 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf, if (type5 == NULL || !CHECK_FLAG(type5->flags, OSPF_LSA_LOCAL_XLT)) { if (IS_DEBUG_OSPF_NSSA) zlog_debug( - "ospf_translated_nssa_refresh(): No translated Type-5 " - "found for Type-7 with Id %s", + "ospf_translated_nssa_refresh(): No translated Type-5 found for Type-7 with Id %s", inet_ntoa(type7->data->id)); return NULL; } @@ -1908,8 +1897,7 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf, if ((new = ospf_lsa_translated_nssa_new(ospf, type7)) == NULL) { if (IS_DEBUG_OSPF_NSSA) zlog_debug( - "ospf_translated_nssa_refresh(): Could not translate " - "Type-7 for %s to Type-5", + "ospf_translated_nssa_refresh(): Could not translate Type-7 for %s to Type-5", inet_ntoa(type7->data->id)); return NULL; } @@ -2032,18 +2020,22 @@ struct ospf_lsa *ospf_external_lsa_originate(struct ospf *ospf, static struct external_info *ospf_default_external_info(struct ospf *ospf) { int type; - struct route_node *rn; struct prefix_ipv4 p; + struct external_info *default_ei; + int ret = 0; p.family = AF_INET; p.prefix.s_addr = 0; p.prefixlen = 0; + default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE, + ospf->instance, &p); + if (!default_ei) + return NULL; + /* First, lookup redistributed default route. */ for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { struct list *ext_list; - struct listnode *node; - struct ospf_external *ext; if (type == ZEBRA_ROUTE_OSPF) continue; @@ -2052,17 +2044,10 @@ static struct external_info *ospf_default_external_info(struct ospf *ospf) if (!ext_list) continue; - for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) { - rn = route_node_lookup(ext->external_info, - (struct prefix *)&p); - if (rn != NULL) { - route_unlock_node(rn); - assert(rn->info); - if (ospf_redistribute_check(ospf, rn->info, - NULL)) - return rn->info; - } - } + ret = ospf_external_default_routemap_apply_walk(ospf, ext_list, + default_ei); + if (ret) + return default_ei; } return NULL; @@ -2269,8 +2254,7 @@ struct ospf_lsa *ospf_external_lsa_refresh(struct ospf *ospf, if (!ospf_redistribute_check(ospf, ei, &changed)) { if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) zlog_debug( - "LSA[Type%d:%s]: Could not be refreshed, " - "redist check fail", + "LSA[Type%d:%s]: Could not be refreshed, redist check fail", lsa->data->type, inet_ntoa(lsa->data->id)); ospf_external_lsa_flush(ospf, ei->type, &ei->p, ei->ifindex /*, ei->nexthop */); @@ -2616,8 +2600,7 @@ struct ospf_lsa *ospf_lsa_install(struct ospf *ospf, struct ospf_interface *oi, if (IS_DEBUG_OSPF(lsa, LSA_REFRESH)) { zlog_debug( - "ospf_lsa_install() Premature Aging " - "lsa 0x%p, seqnum 0x%x", + "ospf_lsa_install() Premature Aging lsa 0x%p, seqnum 0x%x", (void *)lsa, ntohl(lsa->data->ls_seqnum)); ospf_lsa_header_dump(lsa->data); @@ -2625,8 +2608,7 @@ struct ospf_lsa *ospf_lsa_install(struct ospf *ospf, struct ospf_interface *oi, } else { if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { zlog_debug( - "ospf_lsa_install() got an lsa with seq 0x80000000 " - "that was not self originated. Ignoring\n"); + "ospf_lsa_install() got an lsa with seq 0x80000000 that was not self originated. Ignoring\n"); ospf_lsa_header_dump(lsa->data); } return old; @@ -3368,8 +3350,7 @@ struct in_addr ospf_lsa_unique_id(struct ospf *ospf, struct ospf_lsdb *lsdb, if (ip_masklen(al->mask) == p->prefixlen) { if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) zlog_debug( - "ospf_lsa_unique_id(): " - "Can't get Link State ID for %s/%d", + "ospf_lsa_unique_id(): Can't get Link State ID for %s/%d", inet_ntoa(p->prefix), p->prefixlen); /* id.s_addr = 0; */ id.s_addr = 0xffffffff; @@ -3386,8 +3367,7 @@ struct in_addr ospf_lsa_unique_id(struct ospf *ospf, struct ospf_lsdb *lsdb, if (lsa) { if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) zlog_debug( - "ospf_lsa_unique_id(): " - "Can't get Link State ID for %s/%d", + "ospf_lsa_unique_id(): Can't get Link State ID for %s/%d", inet_ntoa(p->prefix), p->prefixlen); /* id.s_addr = 0; */ @@ -3550,8 +3530,7 @@ void ospf_refresher_register_lsa(struct ospf *ospf, struct ospf_lsa *lsa) if (IS_DEBUG_OSPF(lsa, LSA_REFRESH)) zlog_debug( - "LSA[Refresh:Type%d:%s]: ospf_refresher_register_lsa(): " - "setting refresh_list on lsa %p (slod %d)", + "LSA[Refresh:Type%d:%s]: ospf_refresher_register_lsa(): setting refresh_list on lsa %p (slod %d)", lsa->data->type, inet_ntoa(lsa->data->id), (void *)lsa, index); } @@ -3609,8 +3588,7 @@ int ospf_lsa_refresh_walker(struct thread *t) i = (i + 1) % OSPF_LSA_REFRESHER_SLOTS) { if (IS_DEBUG_OSPF(lsa, LSA_REFRESH)) zlog_debug( - "LSA[Refresh]: ospf_lsa_refresh_walker(): " - "refresh index %d", + "LSA[Refresh]: ospf_lsa_refresh_walker(): refresh index %d", i); refresh_list = ospf->lsa_refresh_queue.qs[i]; @@ -3624,8 +3602,7 @@ int ospf_lsa_refresh_walker(struct thread *t) lsa)) { if (IS_DEBUG_OSPF(lsa, LSA_REFRESH)) zlog_debug( - "LSA[Refresh:Type%d:%s]: ospf_lsa_refresh_walker(): " - "refresh lsa %p (slot %d)", + "LSA[Refresh:Type%d:%s]: ospf_lsa_refresh_walker(): refresh lsa %p (slot %d)", lsa->data->type, inet_ntoa(lsa->data->id), (void *)lsa, i); diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c index b8e2dac70e..3a1547978a 100644 --- a/ospfd/ospf_network.c +++ b/ospfd/ospf_network.c @@ -53,9 +53,7 @@ int ospf_if_add_allspfrouters(struct ospf *top, struct prefix *p, if (ret < 0) flog_err( EC_LIB_SOCKET, - "can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " - "ifindex %u, AllSPFRouters): %s; perhaps a kernel limit " - "on # of multicast group memberships has been exceeded?", + "can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, ifindex %u, AllSPFRouters): %s; perhaps a kernel limit on # of multicast group memberships has been exceeded?", top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); else { @@ -78,8 +76,7 @@ int ospf_if_drop_allspfrouters(struct ospf *top, struct prefix *p, ifindex); if (ret < 0) flog_err(EC_LIB_SOCKET, - "can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " - "ifindex %u, AllSPFRouters): %s", + "can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, ifindex %u, AllSPFRouters): %s", top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); else { @@ -104,9 +101,7 @@ int ospf_if_add_alldrouters(struct ospf *top, struct prefix *p, if (ret < 0) flog_err( EC_LIB_SOCKET, - "can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " - "ifindex %u, AllDRouters): %s; perhaps a kernel limit " - "on # of multicast group memberships has been exceeded?", + "can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, ifindex %u, AllDRouters): %s; perhaps a kernel limit on # of multicast group memberships has been exceeded?", top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); else @@ -127,8 +122,7 @@ int ospf_if_drop_alldrouters(struct ospf *top, struct prefix *p, ifindex); if (ret < 0) flog_err(EC_LIB_SOCKET, - "can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " - "ifindex %u, AllDRouters): %s", + "can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, ifindex %u, AllDRouters): %s", top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); else @@ -167,8 +161,7 @@ int ospf_if_ipmulticast(struct ospf *top, struct prefix *p, ifindex_t ifindex) ret = setsockopt_ipv4_multicast_if(top->fd, p->u.prefix4, ifindex); if (ret < 0) flog_err(EC_LIB_SOCKET, - "can't setsockopt IP_MULTICAST_IF(fd %d, addr %s, " - "ifindex %u): %s", + "can't setsockopt IP_MULTICAST_IF(fd %d, addr %s, ifindex %u): %s", top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); #endif diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index 47688babbf..dffbfb7d17 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -683,8 +683,7 @@ static void nsm_change_state(struct ospf_neighbor *nbr, int state) if (CHECK_FLAG(oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) zlog_info( - "%s:[%s:%s], %s -> %s): " - "scheduling new router-LSA origination", + "%s:[%s:%s], %s -> %s): scheduling new router-LSA origination", __func__, inet_ntoa(nbr->router_id), ospf_get_name(oi->ospf), lookup_msg(ospf_nsm_state_msg, old_state, NULL), @@ -785,8 +784,7 @@ int ospf_nsm_event(struct thread *thread) */ flog_err( EC_OSPF_FSM_INVALID_STATE, - "NSM[%s:%s:%s]: %s (%s): " - "Warning: action tried to change next_state to %s", + "NSM[%s:%s:%s]: %s (%s): Warning: action tried to change next_state to %s", IF_NAME(nbr->oi), inet_ntoa(nbr->router_id), ospf_get_name(nbr->oi->ospf), lookup_msg(ospf_nsm_state_msg, nbr->state, diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index 35fa5da74b..061ada5b16 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -1781,8 +1781,7 @@ void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent, if (oipt->t_opaque_lsa_self != NULL) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "Type-%u Opaque-LSA has already scheduled to" - " RE-ORIGINATE: [opaque-type=%u]", + "Type-%u Opaque-LSA has already scheduled to RE-ORIGINATE: [opaque-type=%u]", lsa_type, GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr))); goto out; @@ -1799,8 +1798,7 @@ void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent, if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d" - " ms later: [opaque-type=%u]", + "Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d ms later: [opaque-type=%u]", lsa_type, delay, GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr))); @@ -1919,8 +1917,7 @@ static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread *t) if (n == 0 || !CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "Suspend re-origination of Type-10 Opaque-LSAs" - " (opaque-type=%u) for a while...", + "Suspend re-origination of Type-10 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type); oipt->status = PROC_SUSPEND; @@ -1930,8 +1927,7 @@ static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread *t) if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "Timer[Type10-LSA]: Re-originate Opaque-LSAs" - " (opaque-type=%u) for Area %s", + "Timer[Type10-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for Area %s", oipt->opaque_type, inet_ntoa(area->area_id)); rc = (*functab->lsa_originator)(area); diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index a39d19cc5a..b0dd5c6fc2 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -604,8 +604,7 @@ static void ospf_write_frags(int fd, struct ospf_packet *op, struct ip *iph, if (ret < 0) flog_err( EC_LIB_SOCKET, - "*** ospf_write_frags: sendmsg failed to %s," - " id %d, off %d, len %d, mtu %u failed with %s", + "*** ospf_write_frags: sendmsg failed to %s, id %d, off %d, len %d, mtu %u failed with %s", inet_ntoa(iph->ip_dst), iph->ip_id, iph->ip_off, iph->ip_len, mtu, safe_strerror(errno)); @@ -798,16 +797,14 @@ static int ospf_write(struct thread *thread) sockopt_iphdrincl_swab_systoh(&iph); if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_write to %s, " - "id %d, off %d, len %d, interface %s, mtu %u:", + "ospf_write to %s, id %d, off %d, len %d, interface %s, mtu %u:", inet_ntoa(iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len, oi->ifp->name, oi->ifp->mtu); if (ret < 0) flog_err( EC_LIB_SOCKET, - "*** sendmsg in ospf_write failed to %s, " - "id %d, off %d, len %d, interface %s, mtu %u: %s", + "*** sendmsg in ospf_write failed to %s, id %d, off %d, len %d, interface %s, mtu %u: %s", inet_ntoa(iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len, oi->ifp->name, oi->ifp->mtu, safe_strerror(errno)); @@ -897,8 +894,7 @@ static void ospf_hello(struct ip *iph, struct ospf_header *ospfh, if (IPV4_ADDR_SAME(&ospfh->router_id, &oi->ospf->router_id)) { if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV)) { zlog_debug( - "ospf_header[%s/%s]: selforiginated, " - "dropping.", + "ospf_header[%s/%s]: selforiginated, dropping.", lookup_msg(ospf_packet_type_str, ospfh->type, NULL), inet_ntoa(iph->ip_src)); @@ -927,8 +923,7 @@ static void ospf_hello(struct ip *iph, struct ospf_header *ospfh, /* Compare Router Dead Interval. */ if (OSPF_IF_PARAM(oi, v_wait) != ntohl(hello->dead_interval)) { flog_warn(EC_OSPF_PACKET, - "Packet %s [Hello:RECV]: RouterDeadInterval mismatch " - "(expected %u, but received %u).", + "Packet %s [Hello:RECV]: RouterDeadInterval mismatch (expected %u, but received %u).", inet_ntoa(ospfh->router_id), OSPF_IF_PARAM(oi, v_wait), ntohl(hello->dead_interval)); @@ -941,8 +936,7 @@ static void ospf_hello(struct ip *iph, struct ospf_header *ospfh, != ntohs(hello->hello_interval)) { flog_warn( EC_OSPF_PACKET, - "Packet %s [Hello:RECV]: HelloInterval mismatch " - "(expected %u, but received %u).", + "Packet %s [Hello:RECV]: HelloInterval mismatch (expected %u, but received %u).", inet_ntoa(ospfh->router_id), OSPF_IF_PARAM(oi, v_hello), ntohs(hello->hello_interval)); @@ -1213,8 +1207,7 @@ static void ospf_db_desc_proc(struct stream *s, struct ospf_interface *oi, */ if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "Packet [DD:RECV]: LSA received Type %d, " - "ID %s is not recent.", + "Packet [DD:RECV]: LSA received Type %d, ID %s is not recent.", lsah->type, inet_ntoa(lsah->id)); ospf_lsa_discard(new); } @@ -1402,8 +1395,7 @@ static void ospf_db_desc(struct ip *iph, struct ospf_header *ospfh, if (CHECK_FLAG(oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) zlog_info( - "Packet[DD]: Neighbor %s: Initial DBD from Slave, " - "ignoring.", + "Packet[DD]: Neighbor %s: Initial DBD from Slave, ignoring.", inet_ntoa(nbr->router_id)); break; } @@ -1527,8 +1519,7 @@ static void ospf_db_desc(struct ip *iph, struct ospf_header *ospfh, if (IS_SET_DD_MS(nbr->dd_flags)) { /* Master should discard duplicate DD packet. */ zlog_info( - "Packet[DD]: Neighbor %s duplicated, " - "packet discarded.", + "Packet[DD]: Neighbor %s duplicated, packet discarded.", inet_ntoa(nbr->router_id)); break; } else { @@ -1848,8 +1839,7 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph, if (nbr->state < NSM_Exchange) { if (IS_DEBUG_OSPF(nsm, NSM_EVENTS)) zlog_debug( - "Link State Update: " - "Neighbor[%s] state %s is less than Exchange", + "Link State Update: Neighbor[%s] state %s is less than Exchange", inet_ntoa(ospfh->router_id), lookup_msg(ospf_nsm_state_msg, nbr->state, NULL)); @@ -1948,8 +1938,7 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph, char buf3[INET_ADDRSTRLEN]; flog_err(EC_OSPF_ROUTER_LSA_MISMATCH, - "Incoming Router-LSA from %s with " - "Adv-ID[%s] != LS-ID[%s]", + "Incoming Router-LSA from %s with Adv-ID[%s] != LS-ID[%s]", inet_ntop(AF_INET, &ospfh->router_id, buf1, INET_ADDRSTRLEN), inet_ntop(AF_INET, &lsa->data->id, @@ -1959,8 +1948,7 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph, INET_ADDRSTRLEN)); flog_err( EC_OSPF_DOMAIN_CORRUPT, - "OSPF domain compromised by attack or corruption. " - "Verify correct operation of -ALL- OSPF routers."); + "OSPF domain compromised by attack or corruption. Verify correct operation of -ALL- OSPF routers."); DISCARD_LSA(lsa, 0); } @@ -2032,8 +2020,7 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph, if (current == NULL) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "LSA[%s]: Previously originated Opaque-LSA," - "not found in the LSDB.", + "LSA[%s]: Previously originated Opaque-LSA,not found in the LSDB.", dump_lsa_key(lsa)); SET_FLAG(lsa->flags, OSPF_LSA_SELF); @@ -2254,8 +2241,7 @@ static void ospf_ls_ack(struct ip *iph, struct ospf_header *ospfh, if (nbr->state < NSM_Exchange) { if (IS_DEBUG_OSPF(nsm, NSM_EVENTS)) zlog_debug( - "Link State Acknowledgment: " - "Neighbor[%s] state %s is less than Exchange", + "Link State Acknowledgment: Neighbor[%s] state %s is less than Exchange", inet_ntoa(ospfh->router_id), lookup_msg(ospf_nsm_state_msg, nbr->state, NULL)); @@ -2322,8 +2308,7 @@ static struct stream *ospf_recv_packet(struct ospf *ospf, int fd, if ((unsigned int)ret < sizeof(struct ip)) { flog_warn( EC_OSPF_PACKET, - "ospf_recv_packet: discarding runt packet of length %d " - "(ip header size is %u)", + "ospf_recv_packet: discarding runt packet of length %d (ip header size is %u)", ret, (unsigned int)sizeof(iph)); return NULL; } @@ -2369,8 +2354,7 @@ static struct stream *ospf_recv_packet(struct ospf *ospf, int fd, if (ret != ip_len) { flog_warn( EC_OSPF_PACKET, - "ospf_recv_packet read length mismatch: ip_len is %d, " - "but recvmsg returned %d", + "ospf_recv_packet read length mismatch: ip_len is %d, but recvmsg returned %d", ip_len, ret); return NULL; } @@ -3141,8 +3125,7 @@ static enum ospf_read_return_enum ospf_read_helper(struct ospf *ospf) if (ret < 0) { if (IS_DEBUG_OSPF_PACKET(0, RECV)) zlog_debug( - "ospf_read[%s]: Header check failed, " - "dropping.", + "ospf_read[%s]: Header check failed, dropping.", inet_ntoa(iph->ip_src)); return OSPF_READ_CONTINUE; } @@ -3992,17 +3975,13 @@ static struct ospf_packet *ospf_ls_upd_packet_new(struct list *update, if (!warned) { flog_warn( EC_OSPF_LARGE_LSA, - "ospf_ls_upd_packet_new: oversized LSA encountered!" - "will need to fragment. Not optimal. Try divide up" - " your network with areas. Use 'debug ospf packet send'" - " to see details, or look at 'show ip ospf database ..'"); + "ospf_ls_upd_packet_new: oversized LSA encountered!will need to fragment. Not optimal. Try divide up your network with areas. Use 'debug ospf packet send' to see details, or look at 'show ip ospf database ..'"); warned = 1; } if (IS_DEBUG_OSPF_PACKET(0, SEND)) zlog_debug( - "ospf_ls_upd_packet_new: oversized LSA id:%s," - " %d bytes originated by %s, will be fragmented!", + "ospf_ls_upd_packet_new: oversized LSA id:%s, %d bytes originated by %s, will be fragmented!", inet_ntoa(lsa->data->id), ntohs(lsa->data->length), inet_ntoa(lsa->data->adv_router)); @@ -4020,9 +3999,7 @@ static struct ospf_packet *ospf_ls_upd_packet_new(struct list *update, if (size > OSPF_MAX_PACKET_SIZE) { flog_warn(EC_OSPF_LARGE_LSA, - "ospf_ls_upd_packet_new: oversized LSA id:%s too big," - " %d bytes, packet size %ld, dropping it completely." - " OSPF routing is broken!", + "ospf_ls_upd_packet_new: oversized LSA id:%s too big, %d bytes, packet size %ld, dropping it completely. OSPF routing is broken!", inet_ntoa(lsa->data->id), ntohs(lsa->data->length), (long int)size); list_delete_node(update, ln); @@ -4153,8 +4130,7 @@ static int ospf_ls_upd_send_queue_event(struct thread *thread) if (again != 0) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_ls_upd_send_queue: update lists not cleared," - " %d nodes to try again, raising new event", + "ospf_ls_upd_send_queue: update lists not cleared, %d nodes to try again, raising new event", again); oi->t_ls_upd_event = NULL; thread_add_event(master, ospf_ls_upd_send_queue_event, oi, 0, diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c index a661c80a91..776f50b33a 100644 --- a/ospfd/ospf_route.c +++ b/ospfd/ospf_route.c @@ -322,8 +322,7 @@ void ospf_intra_add_router(struct route_table *rt, struct vertex *v, if (!IS_ROUTER_LSA_BORDER(lsa) && !IS_ROUTER_LSA_EXTERNAL(lsa)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_intra_add_router: " - "this router is neither ASBR nor ABR, skipping it"); + "ospf_intra_add_router: this router is neither ASBR nor ABR, skipping it"); return; } @@ -506,8 +505,7 @@ void ospf_intra_add_stub(struct route_table *rt, struct router_lsa_link *link, if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_intra_add_stub(): " - "another route to the same prefix found with cost %u", + "ospf_intra_add_stub(): another route to the same prefix found with cost %u", cur_or->cost); /* Compare this distance to the current best cost to the stub @@ -923,16 +921,14 @@ int ospf_add_discard_route(struct ospf *ospf, struct route_table *rt, if (or->path_type == OSPF_PATH_INTRA_AREA) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_add_discard_route(): " - "an intra-area route exists"); + "ospf_add_discard_route(): an intra-area route exists"); return 0; } if (or->type == OSPF_DESTINATION_DISCARD) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_add_discard_route(): " - "discard entry already installed"); + "ospf_add_discard_route(): discard entry already installed"); return 0; } @@ -941,8 +937,7 @@ int ospf_add_discard_route(struct ospf *ospf, struct route_table *rt, if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_add_discard_route(): " - "adding %s/%d", + "ospf_add_discard_route(): adding %s/%d", inet_ntoa(p->prefix), p->prefixlen); new_or = ospf_route_new(); @@ -967,8 +962,7 @@ void ospf_delete_discard_route(struct ospf *ospf, struct route_table *rt, if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_delete_discard_route(): " - "deleting %s/%d", + "ospf_delete_discard_route(): deleting %s/%d", inet_ntoa(p->prefix), p->prefixlen); rn = route_node_lookup(rt, (struct prefix *)p); @@ -985,16 +979,14 @@ void ospf_delete_discard_route(struct ospf *ospf, struct route_table *rt, if (or->path_type == OSPF_PATH_INTRA_AREA) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_delete_discard_route(): " - "an intra-area route exists"); + "ospf_delete_discard_route(): an intra-area route exists"); return; } if (or->type != OSPF_DESTINATION_DISCARD) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_delete_discard_route(): " - "not a discard entry"); + "ospf_delete_discard_route(): not a discard entry"); return; } diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c index 64c59c9abf..91fc20475d 100644 --- a/ospfd/ospf_spf.c +++ b/ospfd/ospf_spf.c @@ -540,8 +540,7 @@ static unsigned int ospf_nexthop_calculation(struct ospf_area *area, if (IS_DEBUG_OSPF_EVENT) { zlog_debug( - "%s: considering link:%s " - "type:%d link_id:%s link_data:%s", + "%s: considering link:%s type:%d link_id:%s link_data:%s", __func__, oi->ifp->name, l->m[0].type, inet_ntop(AF_INET, &l->link_id, buf1, BUFSIZ), inet_ntop(AF_INET, &l->link_data, buf2, @@ -676,8 +675,7 @@ static unsigned int ospf_nexthop_calculation(struct ospf_area *area, return 1; } else zlog_info( - "ospf_nexthop_calculation(): " - "vl_data for VL link not found"); + "ospf_nexthop_calculation(): vl_data for VL link not found"); } /* end virtual-link from V to W */ return 0; } /* end W is a Router vertex */ @@ -1183,8 +1181,7 @@ static void ospf_spf_calculate(struct ospf *ospf, struct ospf_area *area, if (!area->router_lsa_self) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_spf_calculate: " - "Skip area %s's calculation due to empty router_lsa_self", + "ospf_spf_calculate: Skip area %s's calculation due to empty router_lsa_self", inet_ntoa(area->area_id)); return; } diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c index 1a65bfa411..8110bc2d02 100644 --- a/ospfd/ospf_sr.c +++ b/ospfd/ospf_sr.c @@ -1022,8 +1022,7 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa) if ((srn != NULL) && (srn->instance != 0) && (srn->instance != ntohl(lsah->id.s_addr))) { flog_err(EC_OSPF_SR_INVALID_LSA_ID, - "SR (%s): Abort! Wrong " - "LSA ID 4.0.0.%u for SR node %pI4/%u", + "SR (%s): Abort! Wrong LSA ID 4.0.0.%u for SR node %pI4/%u", __func__, GET_OPAQUE_ID(ntohl(lsah->id.s_addr)), &lsah->adv_router, srn->instance); return; @@ -1638,8 +1637,7 @@ void ospf_sr_config_write_router(struct vty *vty) for (ALL_LIST_ELEMENTS_RO(OspfSR.self->ext_prefix, node, srp)) { vty_out(vty, - " segment-routing prefix %s/%u " - "index %u%s\n", + " segment-routing prefix %s/%u index %u%s\n", inet_ntoa(srp->prefv4.prefix), srp->prefv4.prefixlen, srp->sid, CHECK_FLAG(srp->flags, @@ -1665,8 +1663,7 @@ DEFUN(ospf_sr_enable, if (ospf->vrf_id != VRF_DEFAULT) { vty_out(vty, - "Segment Routing is only supported in default " - "VRF\n"); + "Segment Routing is only supported in default VRF\n"); return CMD_WARNING_CONFIG_FAILED; } @@ -1954,8 +1951,7 @@ DEFUN (sr_prefix_sid, */ listnode_add(OspfSR.self->ext_prefix, new); zlog_info( - "Interface for prefix %pFX not found. Deferred LSA " - "flooding", + "Interface for prefix %pFX not found. Deferred LSA flooding", &p); return CMD_SUCCESS; } @@ -2245,11 +2241,9 @@ static void show_sr_node(struct vty *vty, struct json_object *json, if (!json) { sbuf_push(&sbuf, 0, - "\n\n Prefix or Link Node or Adj. SID " - " Label Operation Interface Nexthop\n"); + "\n\n Prefix or Link Node or Adj. SID Label Operation Interface Nexthop\n"); sbuf_push(&sbuf, 0, - "------------------ --------------------- " - "-------------------- --------- ---------------\n"); + "------------------ --------------------- -------------------- --------- ---------------\n"); } for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, srp)) { if (json) { diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 4093837ba7..e8cc50c8d0 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -313,8 +313,7 @@ DEFPY (ospf_router_id, for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) if (area->full_nbrs) { vty_out(vty, - "For this router-id change to take effect," - " save config and restart ospfd\n"); + "For this router-id change to take effect, save config and restart ospfd\n"); return CMD_SUCCESS; } @@ -347,8 +346,7 @@ DEFUN_HIDDEN (ospf_router_id_old, for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) if (area->full_nbrs) { vty_out(vty, - "For this router-id change to take effect," - " save config and restart ospfd\n"); + "For this router-id change to take effect, save config and restart ospfd\n"); return CMD_SUCCESS; } @@ -381,8 +379,7 @@ DEFPY (no_ospf_router_id, for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) if (area->full_nbrs) { vty_out(vty, - "For this router-id change to take effect," - " save config and restart ospfd\n"); + "For this router-id change to take effect, save config and restart ospfd\n"); return CMD_SUCCESS; } @@ -700,6 +697,8 @@ DEFUN (ospf_area_range, str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); ospf_area_range_set(ospf, area_id, &p, OSPF_AREA_RANGE_ADVERTISE); + ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id), + format); if (argc > 5) { cost = strtoul(argv[idx_cost]->arg, NULL, 10); ospf_area_range_cost_set(ospf, area_id, &p, cost); @@ -1178,9 +1177,9 @@ DEFUN (no_ospf_area_vlink, "no area <A.B.C.D|(0-4294967295)> virtual-link A.B.C.D [authentication [<message-digest|null>]] [<message-digest-key (1-255) md5 KEY|authentication-key AUTH_KEY>]", NO_STR VLINK_HELPSTR_IPADDR - "Enable authentication on this virtual link\n" \ - "Use message-digest authentication\n" \ - "Use null authentication\n" \ + "Enable authentication on this virtual link\n" + "Use message-digest authentication\n" + "Use null authentication\n" VLINK_HELPSTR_AUTH_MD5 VLINK_HELPSTR_AUTH_SIMPLE) { @@ -1385,8 +1384,7 @@ DEFUN (ospf_area_shortcut, if (ospf->abr_type != OSPF_ABR_SHORTCUT) vty_out(vty, - "Shortcut area setting will take effect " - "only when the router is configured as Shortcut ABR\n"); + "Shortcut area setting will take effect only when the router is configured as Shortcut ABR\n"); return CMD_SUCCESS; } @@ -1718,8 +1716,7 @@ DEFUN (ospf_area_default_cost, p.prefixlen = 0; if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_announce_stub_defaults(): " - "announcing 0.0.0.0/0 to area %s", + "ospf_abr_announce_stub_defaults(): announcing 0.0.0.0/0 to area %s", inet_ntoa(area->area_id)); ospf_abr_announce_network_to_area(&p, area->default_cost, area); @@ -1762,8 +1759,7 @@ DEFUN (no_ospf_area_default_cost, p.prefixlen = 0; if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_abr_announce_stub_defaults(): " - "announcing 0.0.0.0/0 to area %s", + "ospf_abr_announce_stub_defaults(): announcing 0.0.0.0/0 to area %s", inet_ntoa(area->area_id)); ospf_abr_announce_network_to_area(&p, area->default_cost, area); @@ -2712,8 +2708,7 @@ static void show_ip_ospf_area(struct vty *vty, struct ospf_area *area, area->act_ints); } else vty_out(vty, - " Number of interfaces in this area: Total: %d, " - "Active: %d\n", + " Number of interfaces in this area: Total: %d, Active: %d\n", listcount(area->oiflist), area->act_ints); if (area->external_routing == OSPF_AREA_NSSA) { @@ -2871,8 +2866,7 @@ static void show_ip_ospf_area(struct vty *vty, struct ospf_area *area, } else { /* Show number of fully adjacent neighbors. */ vty_out(vty, - " Number of fully adjacent neighbors in this area:" - " %d\n", + " Number of fully adjacent neighbors in this area: %d\n", area->full_nbrs); /* Show authentication type. */ @@ -2886,8 +2880,7 @@ static void show_ip_ospf_area(struct vty *vty, struct ospf_area *area, if (!OSPF_IS_AREA_BACKBONE(area)) vty_out(vty, - " Number of full virtual adjacencies going through" - " this area: %d\n", + " Number of full virtual adjacencies going through this area: %d\n", area->full_vls); /* Show SPF calculation times. */ @@ -3173,8 +3166,7 @@ static int show_ip_ospf_common(struct vty *vty, struct ospf *ospf, "injectingExternalRoutingInformation"); else vty_out(vty, - " This router is an ASBR " - "(injecting external routing information)\n"); + " This router is an ASBR (injecting external routing information)\n"); } /* Show Number of AS-external-LSAs. */ @@ -10205,8 +10197,7 @@ static int config_write_virtual_link(struct vty *vty, struct ospf *ospf) ->auth_crypt, n2, ck)) vty_out(vty, - " area %s virtual-link %s" - " message-digest-key %d md5 %s\n", + " area %s virtual-link %s message-digest-key %d md5 %s\n", buf, inet_ntoa(vl_data->vl_peer), ck->key_id, ck->auth_key); } @@ -10385,8 +10376,7 @@ static int ospf_config_write_one(struct vty *vty, struct ospf *ospf) /* auto-cost reference-bandwidth configuration. */ if (ospf->ref_bandwidth != OSPF_DEFAULT_REF_BANDWIDTH) { vty_out(vty, - "! Important: ensure reference bandwidth " - "is consistent across all routers\n"); + "! Important: ensure reference bandwidth is consistent across all routers\n"); vty_out(vty, " auto-cost reference-bandwidth %d\n", ospf->ref_bandwidth); } diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 644ea7f922..e04eb539d8 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -56,6 +56,7 @@ DEFINE_MTYPE_STATIC(OSPFD, OSPF_EXTERNAL, "OSPF External route table") DEFINE_MTYPE_STATIC(OSPFD, OSPF_REDISTRIBUTE, "OSPF Redistriute") DEFINE_MTYPE_STATIC(OSPFD, OSPF_DIST_ARGS, "OSPF Distribute arguments") + /* Zebra structure to hold current status. */ struct zclient *zclient = NULL; @@ -397,6 +398,101 @@ struct ospf_external *ospf_external_add(struct ospf *ospf, uint8_t type, return ext; } +/* + * Walk all the ei received from zebra for a route type and apply + * default route-map. + */ +bool ospf_external_default_routemap_apply_walk(struct ospf *ospf, + struct list *ext_list, + struct external_info *default_ei) +{ + struct listnode *node; + struct ospf_external *ext; + struct route_node *rn; + struct external_info *ei = NULL; + int ret = 0; + + for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) { + if (!ext->external_info) + continue; + + for (rn = route_top(ext->external_info); rn; + rn = route_next(rn)) { + ei = rn->info; + if (!ei) + continue; + ret = ospf_external_info_apply_default_routemap( + ospf, ei, default_ei); + if (ret) + break; + } + } + + if (ret && ei) { + if (IS_DEBUG_OSPF_DEFAULT_INFO) + zlog_debug("Default originate routemap permit ei: %s", + inet_ntoa(ei->p.prefix)); + return true; + } + + return false; +} + +/* + * Function to originate or flush default after applying + * route-map on all ei. + */ +static int ospf_external_lsa_default_routemap_timer(struct thread *thread) +{ + struct list *ext_list; + struct ospf *ospf = THREAD_ARG(thread); + struct prefix_ipv4 p; + int type; + int ret = 0; + struct ospf_lsa *lsa; + struct external_info *default_ei; + + p.family = AF_INET; + p.prefixlen = 0; + p.prefix.s_addr = INADDR_ANY; + + /* Get the default extenal info. */ + default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE, + ospf->instance, &p); + if (!default_ei) { + /* Nothing to be done here. */ + if (IS_DEBUG_OSPF_DEFAULT_INFO) + zlog_debug("Default originate info not present"); + return 0; + } + + /* For all the ei apply route-map */ + for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { + ext_list = ospf->external[type]; + if (!ext_list || type == ZEBRA_ROUTE_OSPF) + continue; + + ret = ospf_external_default_routemap_apply_walk(ospf, ext_list, + default_ei); + if (ret) + break; + } + + /* Get the default LSA. */ + lsa = ospf_external_info_find_lsa(ospf, &p); + + /* If permit then originate default. */ + if (ret && !lsa) + ospf_external_lsa_originate(ospf, default_ei); + else if (ret && lsa && IS_LSA_MAXAGE(lsa)) + ospf_external_lsa_refresh(ospf, lsa, default_ei, true); + else if (!ret && lsa) + ospf_external_lsa_flush(ospf, DEFAULT_ROUTE, &default_ei->p, 0); + + return 1; +} + + void ospf_external_del(struct ospf *ospf, uint8_t type, unsigned short instance) { struct ospf_external *ext; @@ -414,6 +510,12 @@ void ospf_external_del(struct ospf *ospf, uint8_t type, unsigned short instance) XFREE(MTYPE_OSPF_EXTERNAL, ext); } + + /* + * Check if default needs to be flushed too. + */ + thread_add_event(master, ospf_external_lsa_default_routemap_timer, ospf, + 0, &ospf->t_default_routemap_timer); } /* Update NHLFE for Prefix SID */ @@ -770,8 +872,7 @@ static int ospf_external_lsa_originate_check(struct ospf *ospf, /* If prefix is multicast, then do not originate LSA. */ if (IN_MULTICAST(htonl(ei->p.prefix.s_addr))) { zlog_info( - "LSA[Type5:%s]: Not originate AS-external-LSA, " - "Prefix belongs multicast", + "LSA[Type5:%s]: Not originate AS-external-LSA, Prefix belongs multicast", inet_ntoa(ei->p.prefix)); return 0; } @@ -780,8 +881,7 @@ static int ospf_external_lsa_originate_check(struct ospf *ospf, if (is_prefix_default(&ei->p)) if (ospf->default_originate == DEFAULT_ORIGINATE_NONE) { zlog_info( - "LSA[Type5:0.0.0.0]: Not originate AS-external-LSA " - "for default"); + "LSA[Type5:0.0.0.0]: Not originate AS-external-LSA for default"); return 0; } @@ -801,6 +901,132 @@ int ospf_distribute_check_connected(struct ospf *ospf, struct external_info *ei) return 1; } + +/* Apply default route-map on ei received. */ +int ospf_external_info_apply_default_routemap(struct ospf *ospf, + struct external_info *ei, + struct external_info *default_ei) +{ + struct ospf_redist *red; + int type = default_ei->type; + struct prefix_ipv4 *p = &ei->p; + struct route_map_set_values save_values; + + + if (!ospf_external_lsa_originate_check(ospf, default_ei)) + return 0; + + save_values = default_ei->route_map_set; + ospf_reset_route_map_set_values(&default_ei->route_map_set); + + /* apply route-map if needed */ + red = ospf_redist_lookup(ospf, type, ospf->instance); + if (red && ROUTEMAP_NAME(red)) { + route_map_result_t ret; + + ret = route_map_apply(ROUTEMAP(red), (struct prefix *)p, + RMAP_OSPF, ei); + + if (ret == RMAP_DENYMATCH) { + ei->route_map_set = save_values; + return 0; + } + } + + return 1; +} + + +/* + * Default originated is based on route-map condition then + * apply route-map on received external info. Originate or + * flush based on route-map condition. + */ +static bool ospf_external_lsa_default_routemap_apply(struct ospf *ospf, + struct external_info *ei, + int cmd) +{ + struct external_info *default_ei; + struct prefix_ipv4 p; + struct ospf_lsa *lsa; + int ret; + + p.family = AF_INET; + p.prefixlen = 0; + p.prefix.s_addr = INADDR_ANY; + + + /* Get the default extenal info. */ + default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE, + ospf->instance, &p); + if (!default_ei) { + /* Nothing to be done here. */ + return false; + } + + if (IS_DEBUG_OSPF_DEFAULT_INFO) + zlog_debug("Apply default originate routemap on ei: %s cmd: %d", + inet_ntoa(ei->p.prefix), cmd); + + ret = ospf_external_info_apply_default_routemap(ospf, ei, default_ei); + + /* If deny then nothing to be done both in add and del case. */ + if (!ret) { + if (IS_DEBUG_OSPF_DEFAULT_INFO) + zlog_debug("Default originte routemap deny for ei: %s", + inet_ntoa(ei->p.prefix)); + return false; + } + + /* Get the default LSA. */ + lsa = ospf_external_info_find_lsa(ospf, &p); + + /* If this is add route and permit then ooriginate default. */ + if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) { + /* If permit and default already advertise then return. */ + if (lsa && !IS_LSA_MAXAGE(lsa)) { + if (IS_DEBUG_OSPF_DEFAULT_INFO) + zlog_debug("Defult lsa already originated"); + return true; + } + + if (IS_DEBUG_OSPF_DEFAULT_INFO) + zlog_debug("Originating/Refreshing default lsa"); + + if (lsa && IS_LSA_MAXAGE(lsa)) + /* Refresh lsa.*/ + ospf_external_lsa_refresh(ospf, lsa, default_ei, true); + else + /* If permit and default not advertised then advertise. + */ + ospf_external_lsa_originate(ospf, default_ei); + + } else if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL) { + /* If deny and lsa is not originated then nothing to be done.*/ + if (!lsa) { + if (IS_DEBUG_OSPF_DEFAULT_INFO) + zlog_debug( + "Default lsa not originated, not flushing"); + return true; + } + + if (IS_DEBUG_OSPF_DEFAULT_INFO) + zlog_debug( + "Running default route-map again as ei: %s deleted", + inet_ntoa(ei->p.prefix)); + /* + * if this route delete was permitted then we need to check + * there are any other external info which can still trigger + * default route origination else flush it. + */ + thread_add_event(master, + ospf_external_lsa_default_routemap_timer, ospf, + 0, &ospf->t_default_routemap_timer); + } + + return true; +} + /* return 1 if external LSA must be originated, 0 otherwise */ int ospf_redistribute_check(struct ospf *ospf, struct external_info *ei, int *changed) @@ -812,6 +1038,10 @@ int ospf_redistribute_check(struct ospf *ospf, struct external_info *ei, unsigned short instance = is_prefix_default(&ei->p) ? 0 : ei->instance; route_tag_t saved_tag = 0; + /* Default is handled differently. */ + if (type == DEFAULT_ROUTE) + return 1; + if (changed) *changed = 0; @@ -1004,8 +1234,24 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS) } } } + + /* + * Check if default-information originate is + * with some routemap prefix/access list match. + */ + ospf_external_lsa_default_routemap_apply(ospf, ei, cmd); + } else /* if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */ { + /* + * Check if default-information originate is + * with some routemap prefix/access list match. + * Apply before ei is deleted. + */ + ei = ospf_external_info_lookup(ospf, rt_type, api.instance, &p); + if (ei) + ospf_external_lsa_default_routemap_apply(ospf, ei, cmd); + ospf_external_info_delete(ospf, rt_type, api.instance, p); if (is_prefix_default(&p)) ospf_external_lsa_refresh_default(ospf); @@ -1014,6 +1260,7 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS) ifindex /*, nexthop */); } + return 0; } diff --git a/ospfd/ospf_zebra.h b/ospfd/ospf_zebra.h index 253d2e0a3f..80abf62369 100644 --- a/ospfd/ospf_zebra.h +++ b/ospfd/ospf_zebra.h @@ -92,5 +92,10 @@ extern int ospf_distance_unset(struct vty *, struct ospf *, const char *, extern void ospf_zebra_init(struct thread_master *, unsigned short); extern void ospf_zebra_vrf_register(struct ospf *ospf); extern void ospf_zebra_vrf_deregister(struct ospf *ospf); - +bool ospf_external_default_routemap_apply_walk( + struct ospf *ospf, struct list *ext_list, + struct external_info *default_ei); +int ospf_external_info_apply_default_routemap(struct ospf *ospf, + struct external_info *ei, + struct external_info *default_ei); #endif /* _ZEBRA_OSPF_ZEBRA_H */ diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index ea9c7c58c8..f9cc474d5c 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -686,6 +686,7 @@ static void ospf_finish_final(struct ospf *ospf) OSPF_TIMER_OFF(ospf->t_lsa_refresher); OSPF_TIMER_OFF(ospf->t_opaque_lsa_self); OSPF_TIMER_OFF(ospf->t_sr_update); + OSPF_TIMER_OFF(ospf->t_default_routemap_timer); LSDB_LOOP (OPAQUE_AS_LSDB(ospf), rn, lsa) ospf_discard_from_db(ospf, ospf->lsdb, lsa); diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index 5e91e6f8e6..cdeaa38dc0 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -249,6 +249,8 @@ struct ospf { struct thread *t_write; #define OSPF_WRITE_INTERFACE_COUNT_DEFAULT 20 + struct thread *t_default_routemap_timer; + int write_oi_count; /* Num of packets sent per thread invocation */ struct thread *t_read; int fd; diff --git a/pbrd/pbr_map.c b/pbrd/pbr_map.c index edc3f1d8da..10a75a9f54 100644 --- a/pbrd/pbr_map.c +++ b/pbrd/pbr_map.c @@ -444,6 +444,59 @@ static void pbr_map_add_interfaces(struct pbr_map *pbrm) } } +/* Decodes a standardized DSCP into its representative value */ +uint8_t pbr_map_decode_dscp_enum(const char *name) +{ + /* Standard Differentiated Services Field Codepoints */ + if (!strcmp(name, "cs0")) + return 0; + if (!strcmp(name, "cs1")) + return 8; + if (!strcmp(name, "cs2")) + return 16; + if (!strcmp(name, "cs3")) + return 24; + if (!strcmp(name, "cs4")) + return 32; + if (!strcmp(name, "cs5")) + return 40; + if (!strcmp(name, "cs6")) + return 48; + if (!strcmp(name, "cs7")) + return 56; + if (!strcmp(name, "af11")) + return 10; + if (!strcmp(name, "af12")) + return 12; + if (!strcmp(name, "af13")) + return 14; + if (!strcmp(name, "af21")) + return 18; + if (!strcmp(name, "af22")) + return 20; + if (!strcmp(name, "af23")) + return 22; + if (!strcmp(name, "af31")) + return 26; + if (!strcmp(name, "af32")) + return 28; + if (!strcmp(name, "af33")) + return 30; + if (!strcmp(name, "af41")) + return 34; + if (!strcmp(name, "af42")) + return 36; + if (!strcmp(name, "af43")) + return 38; + if (!strcmp(name, "ef")) + return 46; + if (!strcmp(name, "voice-admit")) + return 44; + + /* No match? Error out */ + return -1; +} + struct pbr_map_sequence *pbrms_get(const char *name, uint32_t seqno) { struct pbr_map *pbrm; @@ -547,7 +600,7 @@ pbr_map_sequence_check_nexthops_valid(struct pbr_map_sequence *pbrms) static void pbr_map_sequence_check_not_empty(struct pbr_map_sequence *pbrms) { - if (!pbrms->src && !pbrms->dst && !pbrms->mark) + if (!pbrms->src && !pbrms->dst && !pbrms->mark && !pbrms->dsfield) pbrms->reason |= PBR_MAP_INVALID_EMPTY; } @@ -603,7 +656,7 @@ bool pbr_map_check_valid(const char *name) return pbrm->valid; } -void pbr_map_schedule_policy_from_nhg(const char *nh_group) +void pbr_map_schedule_policy_from_nhg(const char *nh_group, bool installed) { struct pbr_map_sequence *pbrms; struct pbr_map *pbrm; @@ -618,7 +671,7 @@ void pbr_map_schedule_policy_from_nhg(const char *nh_group) if (pbrms->nhgrp_name && (strcmp(nh_group, pbrms->nhgrp_name) == 0)) { - pbrms->nhs_installed = true; + pbrms->nhs_installed = installed; pbr_map_check(pbrms, false); } @@ -626,7 +679,7 @@ void pbr_map_schedule_policy_from_nhg(const char *nh_group) if (pbrms->nhg && (strcmp(nh_group, pbrms->internal_nhg_name) == 0)) { - pbrms->nhs_installed = true; + pbrms->nhs_installed = installed; pbr_map_check(pbrms, false); } diff --git a/pbrd/pbr_map.h b/pbrd/pbr_map.h index 41f1703954..64c090d2e8 100644 --- a/pbrd/pbr_map.h +++ b/pbrd/pbr_map.h @@ -89,6 +89,7 @@ struct pbr_map_sequence { */ struct prefix *src; struct prefix *dst; + uint8_t dsfield; uint32_t mark; /* @@ -168,6 +169,8 @@ extern void pbr_map_add_interface(struct pbr_map *pbrm, struct interface *ifp); extern void pbr_map_interface_delete(struct pbr_map *pbrm, struct interface *ifp); +extern uint8_t pbr_map_decode_dscp_enum(const char *name); + /* Update maps installed on interface */ extern void pbr_map_policy_interface_update(const struct interface *ifp, bool state_up); @@ -194,7 +197,8 @@ extern void pbr_map_check(struct pbr_map_sequence *pbrms, bool changed); extern void pbr_map_check_nh_group_change(const char *nh_group); extern void pbr_map_reason_string(unsigned int reason, char *buf, int size); -extern void pbr_map_schedule_policy_from_nhg(const char *nh_group); +extern void pbr_map_schedule_policy_from_nhg(const char *nh_group, + bool installed); extern void pbr_map_install(struct pbr_map *pbrm); diff --git a/pbrd/pbr_nht.c b/pbrd/pbr_nht.c index 98be958fce..31da656793 100644 --- a/pbrd/pbr_nht.c +++ b/pbrd/pbr_nht.c @@ -328,27 +328,29 @@ static struct pbr_nexthop_cache *pbr_nht_lookup_nexthop(struct nexthop *nexthop) } #endif +static void +pbr_nht_find_nhg_from_table_update(struct pbr_nexthop_group_cache *pnhgc, + uint32_t table_id, bool installed) +{ + if (pnhgc->table_id == table_id) { + DEBUGD(&pbr_dbg_nht, "%s: %s: Table ID (%u) matches %s", + __func__, (installed ? "install" : "remove"), table_id, + pnhgc->name); + + pnhgc->installed = installed; + pnhgc->valid = installed; + pbr_map_schedule_policy_from_nhg(pnhgc->name, pnhgc->installed); + } +} + static void pbr_nht_find_nhg_from_table_install(struct hash_bucket *b, void *data) { struct pbr_nexthop_group_cache *pnhgc = (struct pbr_nexthop_group_cache *)b->data; - uint32_t *table_id = (uint32_t *)data; - - if (pnhgc->table_id == *table_id) { - DEBUGD(&pbr_dbg_nht, "%s: Table ID (%u) matches %s", __func__, - *table_id, pnhgc->name); + uint32_t table_id = *(uint32_t *)data; - /* - * If the table has been re-handled by zebra - * and we are already installed no need to do - * anything here. - */ - if (!pnhgc->installed) { - pnhgc->installed = true; - pbr_map_schedule_policy_from_nhg(pnhgc->name); - } - } + pbr_nht_find_nhg_from_table_update(pnhgc, table_id, true); } void pbr_nht_route_installed_for_table(uint32_t table_id) @@ -360,7 +362,11 @@ void pbr_nht_route_installed_for_table(uint32_t table_id) static void pbr_nht_find_nhg_from_table_remove(struct hash_bucket *b, void *data) { - ; + struct pbr_nexthop_group_cache *pnhgc = + (struct pbr_nexthop_group_cache *)b->data; + uint32_t table_id = *(uint32_t *)data; + + pbr_nht_find_nhg_from_table_update(pnhgc, table_id, false); } void pbr_nht_route_removed_for_table(uint32_t table_id) @@ -852,12 +858,15 @@ static void pbr_nht_nexthop_update_lookup(struct hash_bucket *b, void *data) */ pnhgc->valid = !!pnhi.valid; - if (pnhgc->valid) { - pbr_nexthop_group_cache_to_nexthop_group(&nhg, pnhgc); + pbr_nexthop_group_cache_to_nexthop_group(&nhg, pnhgc); + + if (pnhgc->valid) pbr_nht_install_nexthop_group(pnhgc, nhg); - /* Don't need copied nexthops anymore */ - nexthops_free(nhg.nexthop); - } + else + pbr_nht_uninstall_nexthop_group(pnhgc, nhg, 0); + + /* Don't need copied nexthops anymore */ + nexthops_free(nhg.nexthop); if (old_valid != pnhgc->valid) pbr_map_check_nh_group_change(pnhgc->name); diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c index cd9096cbc8..a73d885ea6 100644 --- a/pbrd/pbr_vty.c +++ b/pbrd/pbr_vty.c @@ -183,6 +183,91 @@ DEFPY(pbr_map_match_dst, pbr_map_match_dst_cmd, return CMD_SUCCESS; } +DEFPY(pbr_map_match_dscp, pbr_map_match_dscp_cmd, + "[no] match dscp DSCP$dscp", + NO_STR + "Match the rest of the command\n" + "Match based on IP DSCP field\n" + "DSCP value (below 64) or standard codepoint name\n") +{ + struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence); + char dscpname[100]; + uint8_t rawDscp; + + /* Discriminate dscp enums (cs0, cs1 etc.) and numbers */ + bool isANumber = true; + for (int i = 0; i < (int)strlen(dscp); i++) { + /* Letters are not numbers */ + if (!isdigit(dscp[i])) + isANumber = false; + + /* Lowercase the dscp enum (if needed) */ + if (isupper(dscp[i])) + dscpname[i] = tolower(dscp[i]); + else + dscpname[i] = dscp[i]; + } + dscpname[strlen(dscp)] = '\0'; + + if (isANumber) { + /* dscp passed is a regular number */ + long dscpAsNum = strtol(dscp, NULL, 0); + + if (dscpAsNum > PBR_DSFIELD_DSCP >> 2) { + /* Refuse to install on overflow */ + vty_out(vty, "dscp (%s) must be less than 64\n", dscp); + return CMD_WARNING_CONFIG_FAILED; + } + rawDscp = dscpAsNum; + } else { + /* check dscp if it is an enum like cs0 */ + rawDscp = pbr_map_decode_dscp_enum(dscpname); + if (rawDscp > PBR_DSFIELD_DSCP) { + vty_out(vty, "Invalid dscp value: %s\n", dscpname); + return CMD_WARNING_CONFIG_FAILED; + } + } + + if (!no) { + if (((pbrms->dsfield & PBR_DSFIELD_DSCP) >> 2) == rawDscp) + return CMD_SUCCESS; + + /* Set the DSCP bits of the DSField */ + pbrms->dsfield = + (pbrms->dsfield & ~PBR_DSFIELD_DSCP) | (rawDscp << 2); + } else { + pbrms->dsfield &= ~PBR_DSFIELD_DSCP; + } + + pbr_map_check(pbrms, true); + + return CMD_SUCCESS; +} + +DEFPY(pbr_map_match_ecn, pbr_map_match_ecn_cmd, + "[no] match ecn (0-3)$ecn", + NO_STR + "Match the rest of the command\n" + "Match based on IP ECN field\n" + "Explicit Congestion Notification\n") +{ + struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence); + + if (!no) { + if ((pbrms->dsfield & PBR_DSFIELD_ECN) == ecn) + return CMD_SUCCESS; + + /* Set the ECN bits of the DSField */ + pbrms->dsfield = (pbrms->dsfield & ~PBR_DSFIELD_ECN) | ecn; + } else { + pbrms->dsfield &= ~PBR_DSFIELD_ECN; + } + + pbr_map_check(pbrms, true); + + return CMD_SUCCESS; +} + DEFPY(pbr_map_match_mark, pbr_map_match_mark_cmd, "[no] match mark (1-4294967295)$mark", NO_STR @@ -559,6 +644,12 @@ static void vty_show_pbrms(struct vty *vty, if (pbrms->dst) vty_out(vty, " DST Match: %s\n", prefix2str(pbrms->dst, buf, sizeof(buf))); + if (pbrms->dsfield & PBR_DSFIELD_DSCP) + vty_out(vty, " DSCP Match: %u\n", + (pbrms->dsfield & PBR_DSFIELD_DSCP) >> 2); + if (pbrms->dsfield & PBR_DSFIELD_ECN) + vty_out(vty, " ECN Match: %u\n", + pbrms->dsfield & PBR_DSFIELD_ECN); if (pbrms->mark) vty_out(vty, " MARK Match: %u\n", pbrms->mark); @@ -653,6 +744,12 @@ static void vty_json_pbrms(json_object *j, struct vty *vty, prefix2str(pbrms->dst, buf, sizeof(buf))); if (pbrms->mark) json_object_int_add(jpbrm, "matchMark", pbrms->mark); + if (pbrms->dsfield & PBR_DSFIELD_DSCP) + json_object_int_add(jpbrm, "matchDscp", + (pbrms->dsfield & PBR_DSFIELD_DSCP) >> 2); + if (pbrms->dsfield & PBR_DSFIELD_ECN) + json_object_int_add(jpbrm, "matchEcn", + pbrms->dsfield & PBR_DSFIELD_ECN); json_object_array_add(j, jpbrm); } @@ -946,6 +1043,14 @@ static int pbr_vty_map_config_write_sequence(struct vty *vty, vty_out(vty, " match dst-ip %s\n", prefix2str(pbrms->dst, buff, sizeof(buff))); + if (pbrms->dsfield & PBR_DSFIELD_DSCP) + vty_out(vty, " match dscp %u\n", + (pbrms->dsfield & PBR_DSFIELD_DSCP) >> 2); + + if (pbrms->dsfield & PBR_DSFIELD_ECN) + vty_out(vty, " match ecn %u\n", + pbrms->dsfield & PBR_DSFIELD_ECN); + if (pbrms->mark) vty_out(vty, " match mark %u\n", pbrms->mark); @@ -1026,6 +1131,8 @@ void pbr_vty_init(void) install_element(INTERFACE_NODE, &pbr_policy_cmd); install_element(PBRMAP_NODE, &pbr_map_match_src_cmd); install_element(PBRMAP_NODE, &pbr_map_match_dst_cmd); + install_element(PBRMAP_NODE, &pbr_map_match_dscp_cmd); + install_element(PBRMAP_NODE, &pbr_map_match_ecn_cmd); install_element(PBRMAP_NODE, &pbr_map_match_mark_cmd); install_element(PBRMAP_NODE, &pbr_map_nexthop_group_cmd); install_element(PBRMAP_NODE, &no_pbr_map_nexthop_group_cmd); diff --git a/pbrd/pbr_zebra.c b/pbrd/pbr_zebra.c index de2a99e269..d0099a46e3 100644 --- a/pbrd/pbr_zebra.c +++ b/pbrd/pbr_zebra.c @@ -536,6 +536,7 @@ static void pbr_encode_pbr_map_sequence(struct stream *s, stream_putw(s, 0); /* src port */ pbr_encode_pbr_map_sequence_prefix(s, pbrms->dst, family); stream_putw(s, 0); /* dst port */ + stream_putc(s, pbrms->dsfield); stream_putl(s, pbrms->mark); if (pbrms->vrf_unchanged || pbrms->vrf_lookup) diff --git a/pimd/pim_bfd.c b/pimd/pim_bfd.c index 0df8ea6922..146b53fa8f 100644 --- a/pimd/pim_bfd.c +++ b/pimd/pim_bfd.c @@ -194,7 +194,7 @@ void pim_bfd_if_param_set(struct interface *ifp, uint32_t min_rx, if (!pim_ifp) return; - bfd_set_param(&(pim_ifp->bfd_info), min_rx, min_tx, detect_mult, + bfd_set_param(&(pim_ifp->bfd_info), min_rx, min_tx, detect_mult, NULL, defaults, &command); if (pim_ifp->bfd_info) { diff --git a/pimd/pim_bsm.c b/pimd/pim_bsm.c index d949c657bd..1c9005588f 100644 --- a/pimd/pim_bsm.c +++ b/pimd/pim_bsm.c @@ -1283,8 +1283,7 @@ int pim_bsm_process(struct interface *ifp, struct ip *ip_hdr, uint8_t *buf, pim_inet4_dump("<bsr?>", bshdr->bsr_addr.addr, bsr_str, sizeof(bsr_str)); if (bshdr->hm_len > 32) { - zlog_warn("Bad hashmask length for IPv4; got %" PRIu8 - ", expected value in range 0-32", + zlog_warn("Bad hashmask length for IPv4; got %hhu, expected value in range 0-32", bshdr->hm_len); pim->bsm_dropped++; return -1; diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 6919ed9a6d..db3f0b8b23 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -4979,8 +4979,7 @@ static void pim_show_mlag_help_string(struct vty *vty, bool uj) if (!uj) { vty_out(vty, "Owner codes:\n"); vty_out(vty, - "L: EVPN-MLAG Entry, I:PIM-MLAG Entry, " - "P: Peer Entry\n"); + "L: EVPN-MLAG Entry, I:PIM-MLAG Entry, P: Peer Entry\n"); } } @@ -6785,12 +6784,13 @@ static int pim_rp_cmd_worker(struct pim_instance *pim, struct vty *vty, if (result == PIM_GROUP_BAD_ADDR_MASK_COMBO) { vty_out(vty, "%% Inconsistent address and mask: %s\n", - group); + group ? group : "No Group Address"); return CMD_WARNING_CONFIG_FAILED; } if (result == PIM_GROUP_BAD_ADDRESS) { - vty_out(vty, "%% Bad group address specified: %s\n", group); + vty_out(vty, "%% Bad group address specified: %s\n", + group ? group : "No Group Address"); return CMD_WARNING_CONFIG_FAILED; } @@ -7159,7 +7159,8 @@ static int pim_no_rp_cmd_worker(struct pim_instance *pim, struct vty *vty, int result = pim_rp_del_config(pim, rp, group, plist); if (result == PIM_GROUP_BAD_ADDRESS) { - vty_out(vty, "%% Bad group address specified: %s\n", group); + vty_out(vty, "%% Bad group address specified: %s\n", + group ? group : "No Group Address"); return CMD_WARNING_CONFIG_FAILED; } @@ -8404,8 +8405,7 @@ DEFUN_HIDDEN (interface_ip_pim_ssm, } vty_out(vty, - "WARN: Enabled PIM SM on interface; configure PIM SSM " - "range if needed\n"); + "WARN: Enabled PIM SM on interface; configure PIM SSM range if needed\n"); return CMD_SUCCESS; } diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 89fd2bd215..212c77c039 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -139,8 +139,7 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) if (PIM_I_am_DualActive(pim_ifp)) { if (PIM_DEBUG_MLAG) zlog_debug( - "%s: if-chnanel-%s is deleted from a Dual " - "active Interface", + "%s: if-chnanel-%s is deleted from a Dual active Interface", __func__, ch->sg_str); /* Post Delete only if it is the last Dual-active Interface */ if (ch->upstream->dualactive_ifchannel_count == 1) { @@ -214,8 +213,7 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) else { if (PIM_DEBUG_PIM_TRACE) zlog_debug( - "%s: Avoiding deletion of upstream with ref_count %d " - "from ifchannel(%s): %s", + "%s: Avoiding deletion of upstream with ref_count %d from ifchannel(%s): %s", __func__, ch->upstream->ref_count, ch->interface->name, ch->sg_str); } @@ -622,8 +620,7 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, } if (PIM_DEBUG_MLAG) zlog_debug( - "%s: New Dual active if-chnanel is added to upstream:%s " - "count:%d, flags:0x%x", + "%s: New Dual active if-chnanel is added to upstream:%s count:%d, flags:0x%x", __func__, up->sg_str, up->dualactive_ifchannel_count, up->flags); } diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 851b00b2ac..a8612f91fa 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -351,9 +351,7 @@ static int igmp_recv_query(struct igmp_sock *igmp, int query_version, */ if (query_version != pim_ifp->igmp_version) { zlog_warn( - "Recv IGMP query v%d from %s on %s but we are using v%d, please " - "configure all PIM routers on this subnet to use the same " - "IGMP version", + "Recv IGMP query v%d from %s on %s but we are using v%d, please configure all PIM routers on this subnet to use the same IGMP version", query_version, from_str, ifp->name, pim_ifp->igmp_version); return 0; diff --git a/pimd/pim_igmp_mtrace.c b/pimd/pim_igmp_mtrace.c index cac6fab271..9e78b76008 100644 --- a/pimd/pim_igmp_mtrace.c +++ b/pimd/pim_igmp_mtrace.c @@ -231,9 +231,7 @@ static void mtrace_debug(struct pim_interface *pim_ifp, ra = mtracep->rsp_addr; zlog_debug( - "Rx mtrace packet incoming on %s: " - "hops=%d type=%d size=%d, grp=%s, src=%s," - " dst=%s rsp=%s ttl=%d qid=%ud", + "Rx mtrace packet incoming on %s: hops=%d type=%d size=%d, grp=%s, src=%s, dst=%s rsp=%s ttl=%d qid=%ud", inet_ntop(AF_INET, &(pim_ifp->primary_address), inc_str, sizeof(inc_str)), mtracep->hops, mtracep->type, mtrace_len, @@ -255,8 +253,7 @@ static void mtrace_debug(struct pim_interface *pim_ifp, if ((responses % sizeof(struct igmp_mtrace_rsp)) != 0) if (PIM_DEBUG_MTRACE) zlog_debug( - "Mtrace response block of wrong" - " length"); + "Mtrace response block of wrong length"); responses = responses / sizeof(struct igmp_mtrace_rsp); @@ -358,17 +355,14 @@ static int mtrace_send_packet(struct interface *ifp, if (sent < 0) { if (PIM_DEBUG_MTRACE) zlog_warn( - "Send mtrace request failed for %s on" - "%s: group=%s msg_size=%zd: errno=%d: " - " %s", + "Send mtrace request failed for %s on%s: group=%s msg_size=%zd: errno=%d: %s", dst_str, ifp->name, group_str, mtrace_buf_len, errno, safe_strerror(errno)); } else { if (PIM_DEBUG_MTRACE) zlog_warn( - "Send mtrace request failed for %s on" - " %s: group=%s msg_size=%zd: sent=%zd", + "Send mtrace request failed for %s on %s: group=%s msg_size=%zd: sent=%zd", dst_str, ifp->name, group_str, mtrace_buf_len, sent); } @@ -418,8 +412,7 @@ static int mtrace_un_forward_packet(struct pim_instance *pim, struct ip *ip_hdr, close(fd); if (PIM_DEBUG_MTRACE) zlog_warn( - "Dropping mtrace packet, " - "no route to destination"); + "Dropping mtrace packet, no route to destination"); return -1; } @@ -448,8 +441,7 @@ static int mtrace_un_forward_packet(struct pim_instance *pim, struct ip *ip_hdr, if (sent < 0) { if (PIM_DEBUG_MTRACE) zlog_warn( - "Failed to forward mtrace packet:" - " sendto errno=%d, %s", + "Failed to forward mtrace packet: sendto errno=%d, %s", errno, safe_strerror(errno)); return -1; } @@ -480,8 +472,7 @@ static int mtrace_mc_forward_packet(struct pim_instance *pim, struct ip *ip_hdr) if (c_oil == NULL) { if (PIM_DEBUG_MTRACE) { zlog_debug( - "Dropping mtrace multicast packet " - "len=%u to %s ttl=%u", + "Dropping mtrace multicast packet len=%u to %s ttl=%u", ntohs(ip_hdr->ip_len), inet_ntoa(ip_hdr->ip_dst), ip_hdr->ip_ttl); } @@ -532,8 +523,7 @@ static int mtrace_send_mc_response(struct pim_instance *pim, if (c_oil == NULL) { if (PIM_DEBUG_MTRACE) { zlog_debug( - "Dropping mtrace multicast response packet " - "len=%u to %s", + "Dropping mtrace multicast response packet len=%u to %s", (unsigned int)mtrace_len, inet_ntoa(mtracep->rsp_addr)); } @@ -595,8 +585,7 @@ static int mtrace_send_response(struct pim_instance *pim, if (!pim_nexthop_lookup(pim, &nexthop, mtracep->rsp_addr, 1)) { if (PIM_DEBUG_MTRACE) zlog_warn( - "Dropped response qid=%ud, no route to " - "response address", + "Dropped response qid=%ud, no route to response address", mtracep->qry_id); return -1; } @@ -645,8 +634,7 @@ int igmp_mtrace_recv_qry_req(struct igmp_sock *igmp, struct ip *ip_hdr, if (igmp_msg_len < (int)sizeof(struct igmp_mtrace)) { if (PIM_DEBUG_MTRACE) zlog_warn( - "Recv mtrace packet from %s on %s: too short," - " len=%d, min=%zu", + "Recv mtrace packet from %s on %s: too short, len=%d, min=%zu", from_str, ifp->name, igmp_msg_len, sizeof(struct igmp_mtrace)); return -1; @@ -663,8 +651,7 @@ int igmp_mtrace_recv_qry_req(struct igmp_sock *igmp, struct ip *ip_hdr, if (recv_checksum != checksum) { if (PIM_DEBUG_MTRACE) zlog_warn( - "Recv mtrace packet from %s on %s: checksum" - " mismatch: received=%x computed=%x", + "Recv mtrace packet from %s on %s: checksum mismatch: received=%x computed=%x", from_str, ifp->name, recv_checksum, checksum); return -1; } @@ -688,8 +675,7 @@ int igmp_mtrace_recv_qry_req(struct igmp_sock *igmp, struct ip *ip_hdr, if (IPV4_CLASS_DE(ntohl(ip_hdr->ip_dst.s_addr))) { if (PIM_DEBUG_MTRACE) zlog_debug( - "Dropping multicast query " - "on wrong interface"); + "Dropping multicast query on wrong interface"); return -1; } /* Unicast query on wrong interface */ @@ -700,8 +686,7 @@ int igmp_mtrace_recv_qry_req(struct igmp_sock *igmp, struct ip *ip_hdr, if (qry_id == mtracep->qry_id && qry_src == from.s_addr) { if (PIM_DEBUG_MTRACE) zlog_debug( - "Dropping multicast query with " - "duplicate source and id"); + "Dropping multicast query with duplicate source and id"); return -1; } qry_id = mtracep->qry_id; @@ -721,8 +706,7 @@ int igmp_mtrace_recv_qry_req(struct igmp_sock *igmp, struct ip *ip_hdr, } else { if (PIM_DEBUG_MTRACE) zlog_warn( - "Recv mtrace packet from %s on %s: " - "invalid length %d", + "Recv mtrace packet from %s on %s: invalid length %d", from_str, ifp->name, igmp_msg_len); return -1; } @@ -732,8 +716,7 @@ int igmp_mtrace_recv_qry_req(struct igmp_sock *igmp, struct ip *ip_hdr, && !IPV4_MC_LINKLOCAL(ntohl(ip_hdr->ip_dst.s_addr))) { if (PIM_DEBUG_MTRACE) zlog_warn( - "Recv mtrace packet from %s on %s:" - " not link-local multicast %s", + "Recv mtrace packet from %s on %s: not link-local multicast %s", from_str, ifp->name, inet_ntoa(ip_hdr->ip_dst)); return -1; } @@ -866,8 +849,7 @@ int igmp_mtrace_recv_response(struct igmp_sock *igmp, struct ip *ip_hdr, if (igmp_msg_len < (int)sizeof(struct igmp_mtrace)) { if (PIM_DEBUG_MTRACE) zlog_warn( - "Recv mtrace packet from %s on %s: too short," - " len=%d, min=%zu", + "Recv mtrace packet from %s on %s: too short, len=%d, min=%zu", from_str, ifp->name, igmp_msg_len, sizeof(struct igmp_mtrace)); return -1; @@ -884,8 +866,7 @@ int igmp_mtrace_recv_response(struct igmp_sock *igmp, struct ip *ip_hdr, if (recv_checksum != checksum) { if (PIM_DEBUG_MTRACE) zlog_warn( - "Recv mtrace response from %s on %s: checksum" - " mismatch: received=%x computed=%x", + "Recv mtrace response from %s on %s: checksum mismatch: received=%x computed=%x", from_str, ifp->name, recv_checksum, checksum); return -1; } diff --git a/pimd/pim_mlag.c b/pimd/pim_mlag.c index 305dd5cf2c..2dfc0af1de 100644 --- a/pimd/pim_mlag.c +++ b/pimd/pim_mlag.c @@ -1082,6 +1082,14 @@ void pim_instance_mlag_terminate(struct pim_instance *pim) pim->inst_mlag_intf_cnt = 0; } +void pim_mlag_terminate(void) +{ + stream_free(router->mlag_stream); + router->mlag_stream = NULL; + stream_fifo_free(router->mlag_fifo); + router->mlag_fifo = NULL; +} + void pim_mlag_init(void) { pim_mlag_param_reset(); diff --git a/pimd/pim_mlag.h b/pimd/pim_mlag.h index eb316695f7..b044c31c44 100644 --- a/pimd/pim_mlag.h +++ b/pimd/pim_mlag.h @@ -28,6 +28,7 @@ #include "pim_iface.h" extern void pim_mlag_init(void); +extern void pim_mlag_terminate(void); extern void pim_instance_mlag_init(struct pim_instance *pim); extern void pim_instance_mlag_terminate(struct pim_instance *pim); extern void pim_if_configure_mlag_dualactive(struct pim_interface *pim_ifp); diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 1611eac95d..93fe787a93 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -141,6 +141,9 @@ void pim_rp_free(struct pim_instance *pim) { if (pim->rp_list) list_delete(&pim->rp_list); + if (pim->rp_table) + route_table_finish(pim->rp_table); + pim->rp_table = NULL; } /* diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 010ec7d745..f971520c86 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -78,8 +78,7 @@ bool pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop, pim_addr_dump("<nexthop?>", &nexthop->mrib_nexthop_addr, nexthop_str, sizeof(nexthop_str)); zlog_debug( - "%s: Using last lookup for %s at %lld, %" PRId64 - " addr %s", + "%s: Using last lookup for %s at %lld, %" PRId64" addr %s", __func__, addr_str, nexthop->last_lookup_time, pim->last_route_change_time, nexthop_str); } diff --git a/pimd/pimd.c b/pimd/pimd.c index 5ccbac32f2..6c354a3cc8 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -42,6 +42,7 @@ #include "pim_vxlan.h" #include "pim_zlookup.h" #include "pim_zebra.h" +#include "pim_mlag.h" const char *const PIM_ALL_SYSTEMS = MCAST_ALL_SYSTEMS; const char *const PIM_ALL_ROUTERS = MCAST_ALL_ROUTERS; @@ -109,6 +110,7 @@ void pim_router_init(void) void pim_router_terminate(void) { + pim_mlag_terminate(); XFREE(MTYPE_ROUTER, router); } diff --git a/pimd/subdir.am b/pimd/subdir.am index 121abea598..8540651544 100644 --- a/pimd/subdir.am +++ b/pimd/subdir.am @@ -127,6 +127,12 @@ clippy_scan += \ pimd/pim_cmd.c \ # end +nodist_pimd_pimd_SOURCES = \ + yang/frr-igmp.yang.c \ + yang/frr-pim.yang.c \ + yang/frr-pim-rp.yang.c \ + # end + pimd_pimd_LDADD = pimd/libpim.a lib/libfrr.la $(LIBCAP) pimd_pimd_SOURCES = pimd/pim_main.c diff --git a/python/makefile.py b/python/makefile.py index 948d3f7391..fe20945ccc 100644 --- a/python/makefile.py +++ b/python/makefile.py @@ -73,11 +73,18 @@ while lines: out_lines.append(line) continue - m = make_rule_re.match(line) + full_line = line + full_lines = lines[:] + while full_line.endswith('\\'): + full_line = full_line[:-1] + full_lines.pop(0) + + m = make_rule_re.match(full_line) if m is None: out_lines.append(line) continue + line, lines = full_line, full_lines + target, dep = m.group(1), m.group(2) if target.endswith('.lo') or target.endswith('.o'): diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 177f53db45..6ea657401f 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -118,8 +118,7 @@ void rip_interface_multicast_set(int sock, struct connected *connected) if (setsockopt_ipv4_multicast_if(sock, addr, connected->ifp->ifindex) < 0) { zlog_warn( - "Can't setsockopt IP_MULTICAST_IF on fd %d to " - "ifindex %d for interface %s", + "Can't setsockopt IP_MULTICAST_IF on fd %d to ifindex %d for interface %s", sock, connected->ifp->ifindex, connected->ifp->name); } diff --git a/ripd/ripd.c b/ripd/ripd.c index fc53796bd2..ecadf8fb71 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -742,8 +742,7 @@ static void rip_packet_dump(struct rip_packet *packet, int size, ntohs(md5->family), ntohs(md5->type)); zlog_debug( - " RIP-2 packet len %d Key ID %d" - " Auth Data len %d", + " RIP-2 packet len %d Key ID %d Auth Data len %d", ntohs(md5->packet_len), md5->keyid, md5->auth_len); zlog_debug(" Sequence Number %ld", @@ -757,8 +756,7 @@ static void rip_packet_dump(struct rip_packet *packet, int size, ntohs(rte->family), ntohs(rte->tag)); zlog_debug( - " MD5: %02X%02X%02X%02X%02X%02X%02X%02X" - "%02X%02X%02X%02X%02X%02X%02X%02X", + " MD5: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13], @@ -904,8 +902,7 @@ static int rip_auth_md5(struct rip_packet *packet, struct sockaddr_in *from, || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE))) { if (IS_RIP_DEBUG_EVENT) zlog_debug( - "RIPv2 MD5 authentication, strange authentication " - "length field %d", + "RIPv2 MD5 authentication, strange authentication length field %d", md5->auth_len); return 0; } @@ -916,8 +913,7 @@ static int rip_auth_md5(struct rip_packet *packet, struct sockaddr_in *from, if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE)) { if (IS_RIP_DEBUG_EVENT) zlog_debug( - "RIPv2 MD5 authentication, packet length field %d " - "greater than received length %d!", + "RIPv2 MD5 authentication, packet length field %d greater than received length %d!", md5->packet_len, length); return 0; } @@ -1645,8 +1641,7 @@ void rip_redistribute_delete(struct rip *rip, int type, int sub_type, if (IS_RIP_DEBUG_EVENT) zlog_debug( - "Poison %s/%d on the interface %s with an " - "infinity metric [delete]", + "Poison %s/%d on the interface %s with an infinity metric [delete]", inet_ntoa(p->prefix), p->prefixlen, ifindex2ifname( @@ -1814,8 +1809,7 @@ static int rip_read(struct thread *t) if (ifc == NULL) { zlog_info( - "rip_read: cannot find connected address for packet from %s " - "port %d on interface %s (VRF %s)", + "rip_read: cannot find connected address for packet from %s port %d on interface %s (VRF %s)", inet_ntoa(from.sin_addr), ntohs(from.sin_port), ifp->name, rip->vrf_name); return -1; @@ -1937,8 +1931,7 @@ static int rip_read(struct thread *t) if (packet->command != RIP_REQUEST) { if (IS_RIP_DEBUG_PACKET) zlog_debug( - "RIPv1" - " dropped because authentication enabled"); + "RIPv1 dropped because authentication enabled"); ripd_notif_send_auth_type_failure(ifp->name); rip_peer_bad_packet(rip, &from); return -1; @@ -1961,8 +1954,7 @@ static int rip_read(struct thread *t) if (packet->rte->family != htons(RIP_FAMILY_AUTH)) { if (IS_RIP_DEBUG_PACKET) zlog_debug( - "RIPv2" - " dropped because authentication enabled"); + "RIPv2 dropped because authentication enabled"); ripd_notif_send_auth_type_failure(ifp->name); rip_peer_bad_packet(rip, &from); return -1; diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 625adcaa3c..bf6c6ff27b 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -1047,8 +1047,7 @@ void ripng_redistribute_delete(struct ripng *ripng, int type, int sub_type, if (IS_RIPNG_DEBUG_EVENT) zlog_debug( - "Poisone %s/%d on the interface %s with an " - "infinity metric [delete]", + "Poisone %s/%d on the interface %s with an infinity metric [delete]", inet6_ntoa(p->prefix), p->prefixlen, ifindex2ifname( diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c index 48220d1c9b..1d2b87b9ba 100644 --- a/sharpd/sharp_vty.c +++ b/sharpd/sharp_vty.c @@ -278,7 +278,8 @@ DEFPY (install_routes, if (backup) { /* Set flag and index in primary nexthop */ SET_FLAG(sg.r.nhop.flags, NEXTHOP_FLAG_HAS_BACKUP); - sg.r.nhop.backup_idx = 0; + sg.r.nhop.backup_num = 1; + sg.r.nhop.backup_idx[0] = 0; if (backup_nexthop4.s_addr != INADDR_ANY) { sg.r.backup_nhop.gate.ipv4 = backup_nexthop4; diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index 7ab2d6ec22..74e44014a9 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -155,6 +155,8 @@ int sharp_install_lsps_helper(bool install_p, const struct prefix *p, return -1; i++; + if (i >= MULTIPATH_NUM) + break; } } @@ -188,6 +190,8 @@ int sharp_install_lsps_helper(bool install_p, const struct prefix *p, return -1; i++; + if (i >= MULTIPATH_NUM) + break; } if (i > 0) diff --git a/staticd/static_main.c b/staticd/static_main.c index 3c5922b85a..0b5063a083 100644 --- a/staticd/static_main.c +++ b/staticd/static_main.c @@ -31,12 +31,14 @@ #include "vrf.h" #include "nexthop.h" #include "filter.h" +#include "routing_nb.h" #include "static_vrf.h" #include "static_vty.h" #include "static_routes.h" #include "static_zebra.h" #include "static_debug.h" +#include "static_nb.h" char backup_config_file[256]; @@ -63,10 +65,12 @@ struct option longopts[] = { { 0 } }; /* Master of threads. */ struct thread_master *master; +static struct frr_daemon_info staticd_di; /* SIGHUP handler. */ static void sighup(void) { zlog_info("SIGHUP received"); + vty_read_config(NULL, staticd_di.config_file, config_default); } /* SIGINT / SIGTERM handler. */ @@ -108,7 +112,10 @@ struct quagga_signal_t static_signals[] = { static const struct frr_yang_module_info *const staticd_yang_modules[] = { &frr_filter_info, + &frr_interface_info, &frr_vrf_info, + &frr_routing_info, + &frr_staticd_info, }; #define STATIC_VTY_PORT 2616 @@ -155,6 +162,9 @@ int main(int argc, char **argv, char **envp) static_zebra_init(); static_vty_init(); + hook_register(routing_conf_event, + routing_control_plane_protocols_name_validate); + snprintf(backup_config_file, sizeof(backup_config_file), "%s/zebra.conf", frr_sysconfdir); staticd_di.backup_config_file = backup_config_file; diff --git a/staticd/static_memory.c b/staticd/static_memory.c index 77ca4a3439..122cc9fce1 100644 --- a/staticd/static_memory.c +++ b/staticd/static_memory.c @@ -25,4 +25,4 @@ DEFINE_MGROUP(STATIC, "staticd") -DEFINE_MTYPE(STATIC, STATIC_ROUTE, "Static Route"); +DEFINE_MTYPE(STATIC, STATIC_NEXTHOP, "Static Nexthop"); diff --git a/staticd/static_memory.h b/staticd/static_memory.h index 77a0db3b12..e9cc7ba469 100644 --- a/staticd/static_memory.h +++ b/staticd/static_memory.h @@ -23,6 +23,7 @@ DECLARE_MGROUP(STATIC) -DECLARE_MTYPE(STATIC_ROUTE); +DECLARE_MTYPE(STATIC_NEXTHOP); +DECLARE_MTYPE(STATIC_PATH); #endif diff --git a/staticd/static_nb.c b/staticd/static_nb.c new file mode 100644 index 0000000000..419a6a5366 --- /dev/null +++ b/staticd/static_nb.c @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2018 Vmware + * Vishal Dhingra + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "northbound.h" +#include "libfrr.h" +#include "static_nb.h" + + +/* clang-format off */ + +const struct frr_yang_module_info frr_staticd_info = { + .name = "frr-staticd", + .nodes = { + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list", + .cbs = { + .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_create, + .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list", + .cbs = { + .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_create, + .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/tag", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_tag_modify, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/table-id", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_table_id_modify, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop", + .cbs = { + .apply_finish = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_apply_finish, + .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_create, + .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_destroy, + .pre_validate = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_pre_validate, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bh-type", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_modify, + .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/onlink", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_onlink_modify, + .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_onlink_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry", + .cbs = { + .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create, + .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_destroy, + + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/label", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_modify, + .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/ttl", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_modify, + .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/traffic-class", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_modify, + .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list", + .cbs = { + .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_create, + .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list", + .cbs = { + .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_create, + .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/tag", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_tag_modify, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/table-id", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_table_id_modify, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop", + .cbs = { + .apply_finish = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_apply_finish, + .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_create, + .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_destroy, + .pre_validate = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_pre_validate, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/bh-type", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_bh_type_modify, + .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_bh_type_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/onlink", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_onlink_modify, + .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_onlink_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry", + .cbs = { + .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create, + .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/label", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_modify, + .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/ttl", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_modify, + .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/traffic-class", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_modify, + .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_destroy, + } + }, + { + .xpath = NULL, + }, + } +}; diff --git a/staticd/static_nb.h b/staticd/static_nb.h new file mode 100644 index 0000000000..e46c156265 --- /dev/null +++ b/staticd/static_nb.h @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2018 Vmware + * Vishal Dhingra + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef _FRR_STATIC_NB_H_ +#define _FRR_STATIC_NB_H_ + +extern const struct frr_yang_module_info frr_staticd_info; + +/* Mandatory callbacks. */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_create( + struct nb_cb_create_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_create( + struct nb_cb_create_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_tag_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_table_id_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_create( + struct nb_cb_create_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_onlink_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_onlink_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create( + struct nb_cb_create_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_create( + struct nb_cb_create_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_create( + struct nb_cb_create_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_tag_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_table_id_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_create( + struct nb_cb_create_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_bh_type_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_bh_type_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_onlink_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_onlink_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create( + struct nb_cb_create_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_destroy( + struct nb_cb_destroy_args *args); + +/* Optional 'apply_finish' callbacks. */ + +void routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_apply_finish( + struct nb_cb_apply_finish_args *args); +void routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_apply_finish( + struct nb_cb_apply_finish_args *args); + +/* Optional 'pre_validate' callbacks. */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_pre_validate( + struct nb_cb_pre_validate_args *args); + +/* + * Callback registered with routing_nb lib to validate only + * one instance of staticd is allowed + */ +int routing_control_plane_protocols_name_validate( + struct nb_cb_create_args *args); + +/* xpath macros */ +/* route-list */ +#define FRR_STATIC_ROUTE_INFO_KEY_XPATH \ + "/frr-routing:routing/control-plane-protocols/" \ + "control-plane-protocol[type='%s'][name='%s'][vrf='%s']/" \ + "frr-staticd:staticd/route-list[prefix='%s'][afi-safi='%s']/" \ + "path-list[distance='%u']" + + +#define FRR_STATIC_ROUTE_PATH_TAG_XPATH "/tag" + +#define FRR_STATIC_ROUTE_PATH_TABLEID_XPATH "/table-id" + +/* route-list/frr-nexthops */ +#define FRR_STATIC_ROUTE_NH_KEY_XPATH \ + "/frr-nexthops/" \ + "nexthop[nh-type='%s'][vrf='%s'][gateway='%s'][interface='%s']" + +#define FRR_STATIC_ROUTE_NH_ONLINK_XPATH "/onlink" + +#define FRR_STATIC_ROUTE_NH_BH_XPATH "/bh-type" + +#define FRR_STATIC_ROUTE_NH_LABEL_XPATH "/mpls-label-stack" + +#define FRR_STATIC_ROUTE_NHLB_KEY_XPATH "/entry[id='%u']/label" + +/* route-list/srclist */ +#define FRR_S_ROUTE_SRC_INFO_KEY_XPATH \ + "/frr-routing:routing/control-plane-protocols/" \ + "control-plane-protocol[type='%s'][name='%s'][vrf='%s']/" \ + "frr-staticd:staticd/route-list[prefix='%s'][afi-safi='%s']/" \ + "src-list[src-prefix='%s']/path-list[distance='%u']" + +/* route-list/frr-nexthops */ +#define FRR_DEL_S_ROUTE_NH_KEY_XPATH \ + FRR_STATIC_ROUTE_INFO_KEY_XPATH \ + FRR_STATIC_ROUTE_NH_KEY_XPATH + +/* route-list/src/src-list/frr-nexthops*/ +#define FRR_DEL_S_ROUTE_SRC_NH_KEY_XPATH \ + FRR_S_ROUTE_SRC_INFO_KEY_XPATH \ + FRR_STATIC_ROUTE_NH_KEY_XPATH + +#endif diff --git a/staticd/static_nb_config.c b/staticd/static_nb_config.c new file mode 100644 index 0000000000..40c4d85fb6 --- /dev/null +++ b/staticd/static_nb_config.c @@ -0,0 +1,1241 @@ +/* + * Copyright (C) 2018 Vmware + * Vishal Dhingra + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "northbound.h" +#include "libfrr.h" +#include "log.h" +#include "lib_errors.h" +#include "prefix.h" +#include "table.h" +#include "vrf.h" +#include "nexthop.h" +#include "srcdest_table.h" + +#include "static_vrf.h" +#include "static_routes.h" +#include "static_nb.h" + + +static int static_path_list_create(struct nb_cb_create_args *args) +{ + struct route_node *rn; + struct static_path *pn; + uint8_t distance; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_ABORT: + case NB_EV_PREPARE: + break; + case NB_EV_APPLY: + rn = nb_running_get_entry(args->dnode, NULL, true); + distance = yang_dnode_get_uint8(args->dnode, "./distance"); + pn = static_add_path(rn, distance); + nb_running_set_entry(args->dnode, pn); + } + + return NB_OK; +} + +static void static_path_list_destroy(struct nb_cb_destroy_args *args, + const struct lyd_node *rn_dnode, + struct stable_info *info) +{ + struct route_node *rn; + struct static_path *pn; + + pn = nb_running_unset_entry(args->dnode); + rn = nb_running_get_entry(rn_dnode, NULL, true); + static_del_path(rn, pn, info->safi, info->svrf); +} + +static void static_path_list_tag_modify(struct nb_cb_modify_args *args, + const struct lyd_node *rn_dnode, + struct stable_info *info) +{ + struct static_path *pn; + struct route_node *rn; + route_tag_t tag; + + tag = yang_dnode_get_uint32(args->dnode, NULL); + pn = nb_running_get_entry(args->dnode, NULL, true); + pn->tag = tag; + rn = nb_running_get_entry(rn_dnode, NULL, true); + + static_install_path(rn, pn, info->safi, info->svrf); +} + +static int static_path_list_tableid_modify(struct nb_cb_modify_args *args, + const struct lyd_node *rn_dnode, + struct stable_info *info) +{ + struct static_path *pn; + struct route_node *rn; + uint32_t table_id; + const struct lyd_node *vrf_dnode; + const char *vrf; + + switch (args->event) { + case NB_EV_VALIDATE: + vrf_dnode = yang_dnode_get_parent(args->dnode, + "control-plane-protocol"); + vrf = yang_dnode_get_string(vrf_dnode, "./vrf"); + table_id = yang_dnode_get_uint32(args->dnode, NULL); + if (table_id && (strcmp(vrf, vrf_get_default_name()) != 0) + && !vrf_is_backend_netns()) { + snprintf(args->errmsg, args->errmsg_len, + "%% table param only available when running on netns-based vrfs"); + return NB_ERR_VALIDATION; + } + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + table_id = yang_dnode_get_uint32(args->dnode, NULL); + pn = nb_running_get_entry(args->dnode, NULL, true); + pn->table_id = table_id; + rn = nb_running_get_entry(rn_dnode, NULL, true); + static_install_path(rn, pn, info->safi, info->svrf); + break; + } + + return NB_OK; +} + +static bool static_nexthop_create(struct nb_cb_create_args *args, + const struct lyd_node *rn_dnode, + struct stable_info *info) +{ + struct route_node *rn; + struct static_path *pn; + struct ipaddr ipaddr; + struct static_nexthop *nh; + int nh_type; + const char *ifname; + const char *nh_vrf; + + switch (args->event) { + case NB_EV_VALIDATE: + ifname = yang_dnode_get_string(args->dnode, "./interface"); + if (ifname != NULL) { + if (strcasecmp(ifname, "Null0") == 0 + || strcasecmp(ifname, "reject") == 0 + || strcasecmp(ifname, "blackhole") == 0) { + snprintf(args->errmsg, args->errmsg_len, + "%s: Nexthop interface name can not be from reserved keywords(Null0, reject, blackhole)", + ifname); + return NB_ERR_VALIDATION; + } + } + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + yang_dnode_get_ip(&ipaddr, args->dnode, "./gateway"); + nh_type = yang_dnode_get_enum(args->dnode, "./nh-type"); + ifname = yang_dnode_get_string(args->dnode, "./interface"); + nh_vrf = yang_dnode_get_string(args->dnode, "./vrf"); + pn = nb_running_get_entry(args->dnode, NULL, true); + rn = nb_running_get_entry(rn_dnode, NULL, true); + + if (!static_add_nexthop_validate(info->svrf, nh_type, &ipaddr)) + flog_warn( + EC_LIB_NB_CB_CONFIG_VALIDATE, + "Warning!! Local connected address is configured as Gateway IP((%s))", + yang_dnode_get_string(args->dnode, + "./gateway")); + nh = static_add_nexthop(rn, pn, info->safi, info->svrf, nh_type, + &ipaddr, ifname, nh_vrf); + if (!nh) { + char buf[SRCDEST2STR_BUFFER]; + + flog_warn( + EC_LIB_NB_CB_CONFIG_APPLY, + "%s : nh [%d:%s:%s:%s] nexthop creation failed", + srcdest_rnode2str(rn, buf, sizeof(buf)), + nh_type, ifname, + yang_dnode_get_string(args->dnode, "./gateway"), + nh_vrf); + return NB_ERR; + } + nb_running_set_entry(args->dnode, nh); + break; + } + + return NB_OK; +} + +static bool static_nexthop_destroy(struct nb_cb_destroy_args *args, + const struct lyd_node *rn_dnode, + struct stable_info *info) +{ + struct route_node *rn; + struct static_path *pn; + const struct lyd_node *pn_dnode; + struct static_nexthop *nh; + int ret; + + nh = nb_running_unset_entry(args->dnode); + pn_dnode = yang_dnode_get_parent(args->dnode, "path-list"); + pn = nb_running_get_entry(pn_dnode, NULL, true); + rn = nb_running_get_entry(rn_dnode, NULL, true); + + ret = static_delete_nexthop(rn, pn, info->safi, info->svrf, nh); + if (!ret) { + char buf[SRCDEST2STR_BUFFER]; + + flog_warn(EC_LIB_NB_CB_CONFIG_APPLY, + "%s : nh [%d:%s:%s:%s] nexthop destroy failed", + srcdest_rnode2str(rn, buf, sizeof(buf)), + yang_dnode_get_enum(args->dnode, "./nh-type"), + yang_dnode_get_string(args->dnode, "./interface"), + yang_dnode_get_string(args->dnode, "./gateway"), + yang_dnode_get_string(args->dnode, "./vrf")); + return NB_ERR; + } + + return NB_OK; +} + +static int nexthop_mpls_label_stack_entry_create(struct nb_cb_create_args *args) +{ + struct static_nexthop *nh; + uint32_t pos; + uint8_t index; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + nh = nb_running_get_entry(args->dnode, NULL, true); + pos = yang_get_list_pos(args->dnode); + if (!pos) { + flog_warn(EC_LIB_NB_CB_CONFIG_APPLY, + "libyang returns invalid label position"); + return NB_ERR; + } + /* Mapping to array = list-index -1 */ + index = pos - 1; + nh->snh_label.label[index] = 0; + nh->snh_label.num_labels++; + break; + } + + return NB_OK; +} + +static int +nexthop_mpls_label_stack_entry_destroy(struct nb_cb_destroy_args *args) +{ + struct static_nexthop *nh; + uint32_t pos; + uint8_t index; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + nh = nb_running_get_entry(args->dnode, NULL, true); + pos = yang_get_list_pos(args->dnode); + if (!pos) { + flog_warn(EC_LIB_NB_CB_CONFIG_APPLY, + "libyang returns invalid label position"); + return NB_ERR; + } + index = pos - 1; + nh->snh_label.label[index] = 0; + nh->snh_label.num_labels--; + break; + } + + return NB_OK; +} + +static int static_nexthop_mpls_label_modify(struct nb_cb_modify_args *args) +{ + struct static_nexthop *nh; + uint32_t pos; + uint8_t index; + + nh = nb_running_get_entry(args->dnode, NULL, true); + pos = yang_get_list_pos(args->dnode->parent); + if (!pos) { + flog_warn(EC_LIB_NB_CB_CONFIG_APPLY, + "libyang returns invalid label position"); + return NB_ERR; + } + /* Mapping to array = list-index -1 */ + index = pos - 1; + nh->snh_label.label[index] = yang_dnode_get_uint32(args->dnode, NULL); + + return NB_OK; +} + +static int static_nexthop_onlink_modify(struct nb_cb_modify_args *args) +{ + struct static_nexthop *nh; + + nh = nb_running_get_entry(args->dnode, NULL, true); + nh->onlink = yang_dnode_get_bool(args->dnode, NULL); + + return NB_OK; +} + +static int static_nexthop_bh_type_modify(struct nb_cb_modify_args *args) +{ + struct static_nexthop *nh; + + nh = nb_running_get_entry(args->dnode, NULL, true); + nh->bh_type = yang_dnode_get_enum(args->dnode, NULL); + + return NB_OK; +} + + +void routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_apply_finish( + struct nb_cb_apply_finish_args *args) +{ + struct static_nexthop *nh; + struct static_path *pn; + struct route_node *rn; + const struct lyd_node *pn_dnode; + const struct lyd_node *rn_dnode; + const char *ifname; + const char *nh_vrf; + struct stable_info *info; + int nh_type; + + nh_type = yang_dnode_get_enum(args->dnode, "./nh-type"); + ifname = yang_dnode_get_string(args->dnode, "./interface"); + nh_vrf = yang_dnode_get_string(args->dnode, "./vrf"); + + nh = nb_running_get_entry(args->dnode, NULL, true); + + pn_dnode = yang_dnode_get_parent(args->dnode, "path-list"); + pn = nb_running_get_entry(pn_dnode, NULL, true); + + rn_dnode = yang_dnode_get_parent(pn_dnode, "route-list"); + rn = nb_running_get_entry(rn_dnode, NULL, true); + info = route_table_get_info(rn->table); + + static_install_nexthop(rn, pn, nh, info->safi, info->svrf, ifname, + nh_type, nh_vrf); +} + + +void routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_apply_finish( + struct nb_cb_apply_finish_args *args) +{ + struct static_nexthop *nh; + struct static_path *pn; + struct route_node *rn; + struct route_node *src_rn; + const struct lyd_node *pn_dnode; + const struct lyd_node *rn_dnode; + const struct lyd_node *src_dnode; + const char *ifname; + const char *nh_vrf; + struct stable_info *info; + int nh_type; + + nh_type = yang_dnode_get_enum(args->dnode, "./nh-type"); + ifname = yang_dnode_get_string(args->dnode, "./interface"); + nh_vrf = yang_dnode_get_string(args->dnode, "./vrf"); + + nh = nb_running_get_entry(args->dnode, NULL, true); + + pn_dnode = yang_dnode_get_parent(args->dnode, "path-list"); + pn = nb_running_get_entry(pn_dnode, NULL, true); + + src_dnode = yang_dnode_get_parent(pn_dnode, "src-list"); + src_rn = nb_running_get_entry(src_dnode, NULL, true); + + rn_dnode = yang_dnode_get_parent(src_dnode, "route-list"); + rn = nb_running_get_entry(rn_dnode, NULL, true); + info = route_table_get_info(rn->table); + + static_install_nexthop(src_rn, pn, nh, info->safi, info->svrf, ifname, + nh_type, nh_vrf); +} +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_pre_validate( + struct nb_cb_pre_validate_args *args) +{ + const struct lyd_node *mls_dnode; + uint32_t count; + + mls_dnode = yang_dnode_get(args->dnode, "./mpls-label-stack"); + count = yang_get_list_elements_count(yang_dnode_get_child(mls_dnode)); + + if (count > MPLS_MAX_LABELS) { + snprintf(args->errmsg, args->errmsg_len, + "Too many labels, Enter %d or fewer", + MPLS_MAX_LABELS); + return NB_ERR_VALIDATION; + } + return NB_OK; +} + +int routing_control_plane_protocols_name_validate( + struct nb_cb_create_args *args) +{ + const char *name; + + name = yang_dnode_get_string(args->dnode, "./name"); + if (!strmatch(name, "staticd")) { + snprintf(args->errmsg, args->errmsg_len, + "static routing supports only one instance with name staticd"); + return NB_ERR_VALIDATION; + } + return NB_OK; +} +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_create( + struct nb_cb_create_args *args) +{ + struct vrf *vrf; + struct static_vrf *s_vrf; + struct route_node *rn; + const struct lyd_node *vrf_dnode; + struct prefix prefix; + const char *afi_safi; + afi_t prefix_afi; + afi_t afi; + safi_t safi; + + switch (args->event) { + case NB_EV_VALIDATE: + yang_dnode_get_prefix(&prefix, args->dnode, "./prefix"); + afi_safi = yang_dnode_get_string(args->dnode, "./afi-safi"); + yang_afi_safi_identity2value(afi_safi, &afi, &safi); + prefix_afi = family2afi(prefix.family); + if (afi != prefix_afi) { + flog_warn( + EC_LIB_NB_CB_CONFIG_VALIDATE, + "route node %s creation failed", + yang_dnode_get_string(args->dnode, "./prefix")); + return NB_ERR_VALIDATION; + } + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrf_dnode = yang_dnode_get_parent(args->dnode, + "control-plane-protocol"); + vrf = nb_running_get_entry(vrf_dnode, NULL, true); + s_vrf = vrf->info; + + yang_dnode_get_prefix(&prefix, args->dnode, "./prefix"); + afi_safi = yang_dnode_get_string(args->dnode, "./afi-safi"); + yang_afi_safi_identity2value(afi_safi, &afi, &safi); + + rn = static_add_route(afi, safi, &prefix, NULL, s_vrf); + if (!rn) { + flog_warn( + EC_LIB_NB_CB_CONFIG_APPLY, + "route node %s creation failed", + yang_dnode_get_string(args->dnode, "./prefix")); + return NB_ERR; + } + nb_running_set_entry(args->dnode, rn); + break; + } + return NB_OK; +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_destroy( + struct nb_cb_destroy_args *args) +{ + struct route_node *rn; + struct stable_info *info; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + rn = nb_running_unset_entry(args->dnode); + info = route_table_get_info(rn->table); + static_del_route(rn, info->safi, info->svrf); + break; + } + return NB_OK; +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_create( + struct nb_cb_create_args *args) +{ + return static_path_list_create(args); +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_destroy( + struct nb_cb_destroy_args *args) +{ + const struct lyd_node *rn_dnode; + struct route_node *rn; + struct stable_info *info; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + rn_dnode = yang_dnode_get_parent(args->dnode, "route-list"); + rn = nb_running_get_entry(rn_dnode, NULL, true); + info = route_table_get_info(rn->table); + static_path_list_destroy(args, rn_dnode, info); + break; + } + return NB_OK; +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/tag + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_tag_modify( + struct nb_cb_modify_args *args) +{ + struct stable_info *info; + struct route_node *rn; + const struct lyd_node *rn_dnode; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_ABORT: + case NB_EV_PREPARE: + break; + case NB_EV_APPLY: + rn_dnode = yang_dnode_get_parent(args->dnode, "route-list"); + rn = nb_running_get_entry(rn_dnode, NULL, true); + info = route_table_get_info(rn->table); + static_path_list_tag_modify(args, rn_dnode, info); + break; + } + + return NB_OK; +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/table-id + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_table_id_modify( + struct nb_cb_modify_args *args) +{ + struct route_node *rn; + const struct lyd_node *rn_dnode; + struct stable_info *info; + + switch (args->event) { + case NB_EV_VALIDATE: + if (static_path_list_tableid_modify(args, NULL, NULL) != NB_OK) + return NB_ERR_VALIDATION; + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + rn_dnode = yang_dnode_get_parent(args->dnode, "route-list"); + rn = nb_running_get_entry(rn_dnode, NULL, true); + info = route_table_get_info(rn->table); + + if (static_path_list_tableid_modify(args, rn_dnode, info) + != NB_OK) + return NB_ERR_VALIDATION; + break; + } + return NB_OK; +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_create( + struct nb_cb_create_args *args) +{ + struct route_node *rn; + const struct lyd_node *rn_dnode; + struct stable_info *info; + + switch (args->event) { + case NB_EV_VALIDATE: + rn_dnode = yang_dnode_get_parent(args->dnode, "route-list"); + if (static_nexthop_create(args, rn_dnode, NULL) != NB_OK) + return NB_ERR_VALIDATION; + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + rn_dnode = yang_dnode_get_parent(args->dnode, "route-list"); + rn = nb_running_get_entry(rn_dnode, NULL, true); + info = route_table_get_info(rn->table); + + if (static_nexthop_create(args, rn_dnode, info) != NB_OK) + return NB_ERR_VALIDATION; + break; + } + return NB_OK; +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_destroy( + struct nb_cb_destroy_args *args) +{ + struct route_node *rn; + const struct lyd_node *rn_dnode; + struct stable_info *info; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + rn_dnode = yang_dnode_get_parent(args->dnode, "route-list"); + rn = nb_running_get_entry(rn_dnode, NULL, true); + info = route_table_get_info(rn->table); + + if (static_nexthop_destroy(args, rn_dnode, info) != NB_OK) + return NB_ERR; + break; + } + return NB_OK; +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bh-type + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_modify( + struct nb_cb_modify_args *args) +{ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + if (static_nexthop_bh_type_modify(args) != NB_OK) + return NB_ERR; + break; + } + return NB_OK; +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_destroy( + struct nb_cb_destroy_args *args) +{ + /* blackhole type has a boolean type with default value, + * so no need to do any operations in destroy callback + */ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + case NB_EV_APPLY: + break; + } + return NB_OK; +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/onlink + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_onlink_modify( + struct nb_cb_modify_args *args) +{ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + if (static_nexthop_onlink_modify(args) != NB_OK) + return NB_ERR; + + break; + } + return NB_OK; +} +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_onlink_destroy( + struct nb_cb_destroy_args *args) +{ + /* onlink has a boolean type with default value, + * so no need to do any operations in destroy callback + */ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + case NB_EV_APPLY: + break; + } + return NB_OK; +} +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create( + struct nb_cb_create_args *args) +{ + return nexthop_mpls_label_stack_entry_create(args); +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_destroy( + struct nb_cb_destroy_args *args) +{ + return nexthop_mpls_label_stack_entry_destroy(args); +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/label + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_modify( + struct nb_cb_modify_args *args) +{ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + if (static_nexthop_mpls_label_modify(args) != NB_OK) + return NB_ERR; + break; + } + return NB_OK; +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_destroy( + struct nb_cb_destroy_args *args) +{ + /* + * No operation is required in this call back. + * nexthop_mpls_label_stack_entry_destroy() will take care + * to reset the label vaue. + */ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + case NB_EV_APPLY: + break; + } + return NB_OK; +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/ttl + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_modify( + struct nb_cb_modify_args *args) +{ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + case NB_EV_APPLY: + break; + } + + return NB_OK; +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_destroy( + struct nb_cb_destroy_args *args) +{ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + case NB_EV_APPLY: + break; + } + + return NB_OK; +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/traffic-class + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_modify( + struct nb_cb_modify_args *args) +{ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + case NB_EV_APPLY: + break; + } + + return NB_OK; +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_destroy( + struct nb_cb_destroy_args *args) +{ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + case NB_EV_APPLY: + break; + } + + return NB_OK; +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_create( + struct nb_cb_create_args *args) +{ + struct static_vrf *s_vrf; + struct route_node *rn; + struct route_node *src_rn; + struct prefix_ipv6 src_prefix = {}; + struct stable_info *info; + afi_t afi; + safi_t safi = SAFI_UNICAST; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + rn = nb_running_get_entry(args->dnode, NULL, true); + info = route_table_get_info(rn->table); + s_vrf = info->svrf; + yang_dnode_get_ipv6p(&src_prefix, args->dnode, "./src-prefix"); + afi = family2afi(src_prefix.family); + src_rn = + static_add_route(afi, safi, &rn->p, &src_prefix, s_vrf); + if (!src_rn) { + flog_warn(EC_LIB_NB_CB_CONFIG_APPLY, + "src rn %s creation failed", + yang_dnode_get_string(args->dnode, + "./src-prefix")); + return NB_ERR; + } + nb_running_set_entry(args->dnode, src_rn); + break; + } + return NB_OK; +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_destroy( + struct nb_cb_destroy_args *args) +{ + struct route_node *src_rn; + struct route_node *rn; + struct stable_info *info; + const struct lyd_node *rn_dnode; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + src_rn = nb_running_unset_entry(args->dnode); + rn_dnode = yang_dnode_get_parent(args->dnode, "route-list"); + rn = nb_running_get_entry(rn_dnode, NULL, true); + info = route_table_get_info(rn->table); + static_del_route(src_rn, info->safi, info->svrf); + break; + } + + return NB_OK; +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_create( + struct nb_cb_create_args *args) +{ + return static_path_list_create(args); +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_destroy( + struct nb_cb_destroy_args *args) +{ + struct route_node *rn; + const struct lyd_node *rn_dnode; + const struct lyd_node *srn_dnode; + struct stable_info *info; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + srn_dnode = yang_dnode_get_parent(args->dnode, "src-list"); + rn_dnode = yang_dnode_get_parent(srn_dnode, "route-list"); + rn = nb_running_get_entry(rn_dnode, NULL, true); + info = route_table_get_info(rn->table); + static_path_list_destroy(args, srn_dnode, info); + break; + } + return NB_OK; +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/tag + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_tag_modify( + struct nb_cb_modify_args *args) +{ + struct stable_info *info; + struct route_node *rn; + const struct lyd_node *srn_dnode; + const struct lyd_node *rn_dnode; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_ABORT: + case NB_EV_PREPARE: + break; + case NB_EV_APPLY: + srn_dnode = yang_dnode_get_parent(args->dnode, "src-list"); + rn_dnode = yang_dnode_get_parent(srn_dnode, "route-list"); + rn = nb_running_get_entry(rn_dnode, NULL, true); + info = route_table_get_info(rn->table); + static_path_list_tag_modify(args, srn_dnode, info); + break; + } + return NB_OK; +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/table-id + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_table_id_modify( + struct nb_cb_modify_args *args) +{ + struct route_node *rn; + const struct lyd_node *rn_dnode; + const struct lyd_node *src_dnode; + struct stable_info *info; + + switch (args->event) { + case NB_EV_VALIDATE: + if (static_path_list_tableid_modify(args, NULL, NULL) != NB_OK) + return NB_ERR_VALIDATION; + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + src_dnode = yang_dnode_get_parent(args->dnode, "src-list"); + rn_dnode = yang_dnode_get_parent(src_dnode, "route-list"); + rn = nb_running_get_entry(rn_dnode, NULL, true); + info = route_table_get_info(rn->table); + + if (static_path_list_tableid_modify(args, src_dnode, info) + != NB_OK) + return NB_ERR_VALIDATION; + + break; + } + return NB_OK; +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_create( + struct nb_cb_create_args *args) +{ + struct route_node *rn; + const struct lyd_node *rn_dnode; + const struct lyd_node *src_dnode; + struct stable_info *info; + + switch (args->event) { + case NB_EV_VALIDATE: + rn_dnode = yang_dnode_get_parent(args->dnode, "route-list"); + if (static_nexthop_create(args, rn_dnode, NULL) != NB_OK) + return NB_ERR_VALIDATION; + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + src_dnode = yang_dnode_get_parent(args->dnode, "src-list"); + rn_dnode = yang_dnode_get_parent(src_dnode, "route-list"); + rn = nb_running_get_entry(rn_dnode, NULL, true); + info = route_table_get_info(rn->table); + + if (static_nexthop_create(args, src_dnode, info) != NB_OK) + return NB_ERR_VALIDATION; + + break; + } + return NB_OK; +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_destroy( + struct nb_cb_destroy_args *args) +{ + struct route_node *rn; + const struct lyd_node *rn_dnode; + const struct lyd_node *src_dnode; + struct stable_info *info; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + src_dnode = yang_dnode_get_parent(args->dnode, "src-list"); + rn_dnode = yang_dnode_get_parent(src_dnode, "route-list"); + rn = nb_running_get_entry(rn_dnode, NULL, true); + info = route_table_get_info(rn->table); + + if (static_nexthop_destroy(args, rn_dnode, info) != NB_OK) + return NB_ERR; + break; + } + return NB_OK; +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/bh-type + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_bh_type_modify( + struct nb_cb_modify_args *args) +{ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + if (static_nexthop_bh_type_modify(args) != NB_OK) + return NB_ERR; + break; + } + return NB_OK; +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_bh_type_destroy( + struct nb_cb_destroy_args *args) +{ + /* blackhole type has a boolean type with default value, + * so no need to do any operations in destroy callback + */ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + case NB_EV_APPLY: + break; + } + + return NB_OK; +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/onlink + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_onlink_modify( + struct nb_cb_modify_args *args) +{ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + if (static_nexthop_onlink_modify(args) != NB_OK) + return NB_ERR; + + break; + } + return NB_OK; +} + + +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_onlink_destroy( + struct nb_cb_destroy_args *args) +{ + /* onlink has a boolean type with default value, + * so no need to do any operations in destroy callback + */ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + case NB_EV_APPLY: + break; + } + return NB_OK; +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create( + struct nb_cb_create_args *args) +{ + return nexthop_mpls_label_stack_entry_create(args); +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_destroy( + struct nb_cb_destroy_args *args) +{ + return nexthop_mpls_label_stack_entry_destroy(args); +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/label + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_modify( + struct nb_cb_modify_args *args) +{ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + if (static_nexthop_mpls_label_modify(args) != NB_OK) + return NB_ERR; + break; + } + return NB_OK; +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_destroy( + struct nb_cb_destroy_args *args) +{ + /* + * No operation is required in this call back. + * nexthop_mpls_label_stack_entry_destroy() will take care + * to reset the label vaue. + */ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + case NB_EV_APPLY: + break; + } + return NB_OK; +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/ttl + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_modify( + struct nb_cb_modify_args *args) +{ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + case NB_EV_APPLY: + break; + } + + return NB_OK; +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_destroy( + struct nb_cb_destroy_args *args) +{ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + case NB_EV_APPLY: + break; + } + + return NB_OK; +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/traffic-class + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_modify( + struct nb_cb_modify_args *args) +{ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + case NB_EV_APPLY: + break; + } + + return NB_OK; +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_destroy( + struct nb_cb_destroy_args *args) +{ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + case NB_EV_APPLY: + break; + } + + return NB_OK; +} diff --git a/staticd/static_nht.c b/staticd/static_nht.c index 1a2ddd7f05..feb6e0f993 100644 --- a/staticd/static_nht.c +++ b/staticd/static_nht.c @@ -30,33 +30,33 @@ #include "static_zebra.h" #include "static_nht.h" -static void static_nht_update_rn(struct route_node *rn, - struct prefix *nhp, uint32_t nh_num, - vrf_id_t nh_vrf_id, struct vrf *vrf, - safi_t safi) +static void static_nht_update_path(struct route_node *rn, + struct static_path *pn, struct prefix *nhp, + uint32_t nh_num, vrf_id_t nh_vrf_id, + struct vrf *vrf, safi_t safi) { - struct static_route *si; + struct static_nexthop *nh; - for (si = rn->info; si; si = si->next) { - if (si->nh_vrf_id != nh_vrf_id) + frr_each(static_nexthop_list, &pn->nexthop_list, nh) { + if (nh->nh_vrf_id != nh_vrf_id) continue; - if (si->type != STATIC_IPV4_GATEWAY - && si->type != STATIC_IPV4_GATEWAY_IFNAME - && si->type != STATIC_IPV6_GATEWAY - && si->type != STATIC_IPV6_GATEWAY_IFNAME) + if (nh->type != STATIC_IPV4_GATEWAY + && nh->type != STATIC_IPV4_GATEWAY_IFNAME + && nh->type != STATIC_IPV6_GATEWAY + && nh->type != STATIC_IPV6_GATEWAY_IFNAME) continue; if (nhp->family == AF_INET - && nhp->u.prefix4.s_addr == si->addr.ipv4.s_addr) - si->nh_valid = !!nh_num; + && nhp->u.prefix4.s_addr == nh->addr.ipv4.s_addr) + nh->nh_valid = !!nh_num; if (nhp->family == AF_INET6 - && memcmp(&nhp->u.prefix6, &si->addr.ipv6, 16) == 0) - si->nh_valid = !!nh_num; + && memcmp(&nhp->u.prefix6, &nh->addr.ipv6, 16) == 0) + nh->nh_valid = !!nh_num; - if (si->state == STATIC_START) - static_zebra_route_add(rn, si, vrf->vrf_id, safi, true); + if (nh->state == STATIC_START) + static_zebra_route_add(rn, pn, safi, true); } } @@ -67,6 +67,8 @@ static void static_nht_update_safi(struct prefix *sp, struct prefix *nhp, struct route_table *stable; struct static_vrf *svrf; struct route_node *rn; + struct static_path *pn; + struct static_route_info *si; svrf = vrf->info; if (!svrf) @@ -78,17 +80,26 @@ static void static_nht_update_safi(struct prefix *sp, struct prefix *nhp, if (sp) { rn = srcdest_rnode_lookup(stable, sp, NULL); - if (rn) { - static_nht_update_rn(rn, nhp, nh_num, nh_vrf_id, - vrf, safi); + if (rn && rn->info) { + si = static_route_info_from_rnode(rn); + frr_each(static_path_list, &si->path_list, pn) { + static_nht_update_path(rn, pn, nhp, nh_num, + nh_vrf_id, vrf, safi); + } route_unlock_node(rn); } return; } - for (rn = route_top(stable); rn; rn = route_next(rn)) - static_nht_update_rn(rn, nhp, nh_num, nh_vrf_id, vrf, safi); - + for (rn = route_top(stable); rn; rn = route_next(rn)) { + si = static_route_info_from_rnode(rn); + if (!si) + continue; + frr_each(static_path_list, &si->path_list, pn) { + static_nht_update_path(rn, pn, nhp, nh_num, nh_vrf_id, + vrf, safi); + } + } } void static_nht_update(struct prefix *sp, struct prefix *nhp, @@ -111,8 +122,10 @@ static void static_nht_reset_start_safi(struct prefix *nhp, afi_t afi, { struct static_vrf *svrf; struct route_table *stable; - struct static_route *si; + struct static_nexthop *nh; + struct static_path *pn; struct route_node *rn; + struct static_route_info *si; svrf = vrf->info; if (!svrf) @@ -123,25 +136,33 @@ static void static_nht_reset_start_safi(struct prefix *nhp, afi_t afi, return; for (rn = route_top(stable); rn; rn = route_next(rn)) { - for (si = rn->info; si; si = si->next) { - if (si->nh_vrf_id != nh_vrf_id) - continue; - - if (nhp->family == AF_INET - && nhp->u.prefix4.s_addr != si->addr.ipv4.s_addr) - continue; - - if (nhp->family == AF_INET6 - && memcmp(&nhp->u.prefix6, &si->addr.ipv6, 16) != 0) - continue; - - /* - * We've been told that a nexthop we depend - * on has changed in some manner, so reset - * the state machine to allow us to start - * over. - */ - si->state = STATIC_START; + si = static_route_info_from_rnode(rn); + if (!si) + continue; + frr_each(static_path_list, &si->path_list, pn) { + frr_each(static_nexthop_list, &pn->nexthop_list, nh) { + if (nh->nh_vrf_id != nh_vrf_id) + continue; + + if (nhp->family == AF_INET + && nhp->u.prefix4.s_addr + != nh->addr.ipv4.s_addr) + continue; + + if (nhp->family == AF_INET6 + && memcmp(&nhp->u.prefix6, &nh->addr.ipv6, + 16) + != 0) + continue; + + /* + * We've been told that a nexthop we + * depend on has changed in some manner, + * so reset the state machine to allow + * us to start over. + */ + nh->state = STATIC_START; + } } } } @@ -164,8 +185,10 @@ static void static_nht_mark_state_safi(struct prefix *sp, afi_t afi, { struct static_vrf *svrf; struct route_table *stable; - struct static_route *si; struct route_node *rn; + struct static_nexthop *nh; + struct static_path *pn; + struct static_route_info *si; svrf = vrf->info; if (!svrf) @@ -178,9 +201,14 @@ static void static_nht_mark_state_safi(struct prefix *sp, afi_t afi, rn = srcdest_rnode_lookup(stable, sp, NULL); if (!rn) return; - - for (si = rn->info; si; si = si->next) - si->state = state; + si = rn->info; + if (si) { + frr_each(static_path_list, &si->path_list, pn) { + frr_each(static_nexthop_list, &pn->nexthop_list, nh) { + nh->state = state; + } + } + } route_unlock_node(rn); } diff --git a/staticd/static_routes.c b/staticd/static_routes.c index e8d6a4289b..3836109e36 100644 --- a/staticd/static_routes.c +++ b/staticd/static_routes.c @@ -32,267 +32,366 @@ #include "static_memory.h" #include "static_zebra.h" -/* Install static route into rib. */ -static void static_install_route(struct route_node *rn, - struct static_route *si_changed, safi_t safi) -{ - struct static_route *si; +DEFINE_MTYPE_STATIC(STATIC, STATIC_ROUTE, "Static Route Info"); +DEFINE_MTYPE(STATIC, STATIC_PATH, "Static Path"); - for (si = rn->info; si; si = si->next) - static_zebra_nht_register(rn, si, true); +/* Install static path into rib. */ +void static_install_path(struct route_node *rn, struct static_path *pn, + safi_t safi, struct static_vrf *svrf) +{ + struct static_nexthop *nh; - si = rn->info; - if (si) - static_zebra_route_add(rn, si_changed, si->vrf_id, safi, true); + frr_each(static_nexthop_list, &pn->nexthop_list, nh) + static_zebra_nht_register(rn, nh, true); + if (static_nexthop_list_count(&pn->nexthop_list) && svrf && svrf->vrf) + static_zebra_route_add(rn, pn, safi, true); } -/* Uninstall static route from RIB. */ -static void static_uninstall_route(vrf_id_t vrf_id, safi_t safi, - struct route_node *rn, - struct static_route *si_changed) +/* Uninstall static path from RIB. */ +static void static_uninstall_path(struct route_node *rn, struct static_path *pn, + safi_t safi, struct static_vrf *svrf) { - - if (rn->info) - static_zebra_route_add(rn, si_changed, vrf_id, safi, true); + if (static_nexthop_list_count(&pn->nexthop_list)) + static_zebra_route_add(rn, pn, safi, true); else - static_zebra_route_add(rn, si_changed, vrf_id, safi, false); + static_zebra_route_add(rn, pn, safi, false); } -int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p, - struct prefix_ipv6 *src_p, union g_addr *gate, - const char *ifname, enum static_blackhole_type bh_type, - route_tag_t tag, uint8_t distance, struct static_vrf *svrf, - struct static_vrf *nh_svrf, - struct static_nh_label *snh_label, uint32_t table_id, - bool onlink) +struct route_node *static_add_route(afi_t afi, safi_t safi, struct prefix *p, + struct prefix_ipv6 *src_p, + struct static_vrf *svrf) { struct route_node *rn; - struct static_route *si; - struct static_route *pp; - struct static_route *cp; - struct static_route *update = NULL; + struct static_route_info *si; struct route_table *stable = svrf->stable[afi][safi]; - struct interface *ifp; if (!stable) - return -1; - - if (!gate && (type == STATIC_IPV4_GATEWAY - || type == STATIC_IPV4_GATEWAY_IFNAME - || type == STATIC_IPV6_GATEWAY - || type == STATIC_IPV6_GATEWAY_IFNAME)) - return -1; - - if (!ifname - && (type == STATIC_IFNAME || type == STATIC_IPV4_GATEWAY_IFNAME - || type == STATIC_IPV6_GATEWAY_IFNAME)) - return -1; + return NULL; /* Lookup static route prefix. */ rn = srcdest_rnode_get(stable, p, src_p); - /* Do nothing if there is a same static route. */ - for (si = rn->info; si; si = si->next) { - if (type == si->type - && (!gate - || ((afi == AFI_IP - && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4)) - || (afi == AFI_IP6 - && IPV6_ADDR_SAME(gate, &si->addr.ipv6)))) - && (!strcmp(ifname ? ifname : "", si->ifname)) - && nh_svrf->vrf->vrf_id == si->nh_vrf_id) { - if ((distance == si->distance) && (tag == si->tag) - && (table_id == si->table_id) - && !memcmp(&si->snh_label, snh_label, - sizeof(struct static_nh_label)) - && si->bh_type == bh_type && si->onlink == onlink) { - route_unlock_node(rn); - return 0; - } - update = si; + si = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(struct static_route_info)); + static_route_info_init(si); + + rn->info = si; + + /* Mark as having FRR configuration */ + vrf_set_user_cfged(svrf->vrf); + + return rn; +} + +/* To delete the srcnodes */ +static void static_del_src_route(struct route_node *rn, safi_t safi, + struct static_vrf *svrf) +{ + struct static_path *pn; + struct static_route_info *si; + + si = rn->info; + + frr_each_safe(static_path_list, &si->path_list, pn) { + static_del_path(rn, pn, safi, svrf); + } + + XFREE(MTYPE_STATIC_ROUTE, rn->info); + route_unlock_node(rn); + /* If no other FRR config for this VRF, mark accordingly. */ + if (!static_vrf_has_config(svrf)) + vrf_reset_user_cfged(svrf->vrf); +} + +void static_del_route(struct route_node *rn, safi_t safi, + struct static_vrf *svrf) +{ + struct static_path *pn; + struct static_route_info *si; + struct route_table *src_table; + struct route_node *src_node; + + si = rn->info; + + frr_each_safe(static_path_list, &si->path_list, pn) { + static_del_path(rn, pn, safi, svrf); + } + + /* clean up for dst table */ + src_table = srcdest_srcnode_table(rn); + if (src_table) { + /* This means the route_node is part of the top hierarchy + * and refers to a destination prefix. + */ + for (src_node = route_top(src_table); src_node; + src_node = route_next(src_node)) { + static_del_src_route(src_node, safi, svrf); } } + XFREE(MTYPE_STATIC_ROUTE, rn->info); + route_unlock_node(rn); + /* If no other FRR config for this VRF, mark accordingly. */ + if (!static_vrf_has_config(svrf)) + vrf_reset_user_cfged(svrf->vrf); +} + +bool static_add_nexthop_validate(struct static_vrf *svrf, static_types type, + struct ipaddr *ipaddr) +{ + switch (type) { + case STATIC_IPV4_GATEWAY: + case STATIC_IPV4_GATEWAY_IFNAME: + if (if_lookup_exact_address(&ipaddr->ipaddr_v4, AF_INET, + svrf->vrf->vrf_id)) + return false; + break; + case STATIC_IPV6_GATEWAY: + case STATIC_IPV6_GATEWAY_IFNAME: + if (if_lookup_exact_address(&ipaddr->ipaddr_v6, AF_INET6, + svrf->vrf->vrf_id)) + return false; + break; + default: + break; + } - /* Distance or tag or label changed, delete existing first. */ - if (update) - static_delete_route(afi, safi, type, p, src_p, gate, ifname, - update->tag, update->distance, svrf, - &update->snh_label, table_id); + return true; +} + +struct static_path *static_add_path(struct route_node *rn, uint8_t distance) +{ + struct static_path *pn; + struct static_route_info *si; + + route_lock_node(rn); /* Make new static route structure. */ - si = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(struct static_route)); - - si->type = type; - si->distance = distance; - si->bh_type = bh_type; - si->tag = tag; - si->vrf_id = svrf->vrf->vrf_id; - si->nh_vrf_id = nh_svrf->vrf->vrf_id; - strlcpy(si->nh_vrfname, nh_svrf->vrf->name, sizeof(si->nh_vrfname)); - si->table_id = table_id; - si->onlink = onlink; + pn = XCALLOC(MTYPE_STATIC_PATH, sizeof(struct static_path)); + + pn->distance = distance; + static_nexthop_list_init(&(pn->nexthop_list)); + + si = rn->info; + static_path_list_add_head(&(si->path_list), pn); + + return pn; +} + +void static_del_path(struct route_node *rn, struct static_path *pn, safi_t safi, + struct static_vrf *svrf) +{ + struct static_route_info *si; + struct static_nexthop *nh; + + si = rn->info; + + static_path_list_del(&si->path_list, pn); + + frr_each_safe(static_nexthop_list, &pn->nexthop_list, nh) { + static_delete_nexthop(rn, pn, safi, svrf, nh); + } + + route_unlock_node(rn); + + XFREE(MTYPE_STATIC_PATH, pn); +} + +struct static_nexthop * +static_add_nexthop(struct route_node *rn, struct static_path *pn, safi_t safi, + struct static_vrf *svrf, static_types type, + struct ipaddr *ipaddr, const char *ifname, + const char *nh_vrf) +{ + struct static_nexthop *nh; + struct static_vrf *nh_svrf; + struct interface *ifp; + struct static_nexthop *cp; + + route_lock_node(rn); + + nh_svrf = static_vty_get_unknown_vrf(nh_vrf); + + if (!nh_svrf) + return NULL; + + /* Make new static route structure. */ + nh = XCALLOC(MTYPE_STATIC_NEXTHOP, sizeof(struct static_nexthop)); + + nh->type = type; + + nh->nh_vrf_id = nh_svrf->vrf->vrf_id; + strlcpy(nh->nh_vrfname, nh_svrf->vrf->name, sizeof(nh->nh_vrfname)); if (ifname) - strlcpy(si->ifname, ifname, sizeof(si->ifname)); - si->ifindex = IFINDEX_INTERNAL; + strlcpy(nh->ifname, ifname, sizeof(nh->ifname)); + nh->ifindex = IFINDEX_INTERNAL; switch (type) { case STATIC_IPV4_GATEWAY: case STATIC_IPV4_GATEWAY_IFNAME: - si->addr.ipv4 = gate->ipv4; + nh->addr.ipv4 = ipaddr->ipaddr_v4; break; case STATIC_IPV6_GATEWAY: case STATIC_IPV6_GATEWAY_IFNAME: - si->addr.ipv6 = gate->ipv6; + nh->addr.ipv6 = ipaddr->ipaddr_v6; break; - case STATIC_IFNAME: + default: break; } - - /* Save labels, if any. */ - memcpy(&si->snh_label, snh_label, sizeof(struct static_nh_label)); - /* * Add new static route information to the tree with sort by - * distance value and gateway address. + * gateway address. */ - for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) { - if (si->distance < cp->distance) - break; - if (si->distance > cp->distance) - continue; - if (si->type == STATIC_IPV4_GATEWAY + frr_each(static_nexthop_list, &pn->nexthop_list, cp) { + if (nh->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY) { - if (ntohl(si->addr.ipv4.s_addr) + if (ntohl(nh->addr.ipv4.s_addr) < ntohl(cp->addr.ipv4.s_addr)) break; - if (ntohl(si->addr.ipv4.s_addr) + if (ntohl(nh->addr.ipv4.s_addr) > ntohl(cp->addr.ipv4.s_addr)) continue; } } + static_nexthop_list_add_after(&(pn->nexthop_list), cp, nh); - /* Make linked list. */ - if (pp) - pp->next = si; - else - rn->info = si; - if (cp) - cp->prev = si; - si->prev = pp; - si->next = cp; + if (nh_svrf->vrf->vrf_id == VRF_UNKNOWN) + return nh; /* check whether interface exists in system & install if it does */ - switch (si->type) { + switch (nh->type) { case STATIC_IPV4_GATEWAY: case STATIC_IPV6_GATEWAY: - static_zebra_nht_register(rn, si, true); break; case STATIC_IPV4_GATEWAY_IFNAME: case STATIC_IPV6_GATEWAY_IFNAME: - ifp = if_lookup_by_name(ifname, nh_svrf->vrf->vrf_id); + ifp = if_lookup_by_name(ifname, nh_svrf->vrf->vrf_id); if (ifp && ifp->ifindex != IFINDEX_INTERNAL) - si->ifindex = ifp->ifindex; + nh->ifindex = ifp->ifindex; else - zlog_warn("Static Route using %s interface not installed because the interface does not exist in specified vrf", - ifname); + zlog_warn( + "Static Route using %s interface not installed because the interface does not exist in specified vrf", + ifname); - static_zebra_nht_register(rn, si, true); break; case STATIC_BLACKHOLE: - static_install_route(rn, si, safi); break; case STATIC_IFNAME: ifp = if_lookup_by_name(ifname, nh_svrf->vrf->vrf_id); if (ifp && ifp->ifindex != IFINDEX_INTERNAL) { - si->ifindex = ifp->ifindex; - static_install_route(rn, si, safi); + nh->ifindex = ifp->ifindex; } else - zlog_warn("Static Route using %s interface not installed because the interface does not exist in specified vrf", - ifname); - + zlog_warn( + "Static Route using %s interface not installed because the interface does not exist in specified vrf", + ifname); break; } - return 1; + return nh; } -int static_delete_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p, - struct prefix_ipv6 *src_p, union g_addr *gate, - const char *ifname, route_tag_t tag, uint8_t distance, - struct static_vrf *svrf, - struct static_nh_label *snh_label, - uint32_t table_id) +void static_install_nexthop(struct route_node *rn, struct static_path *pn, + struct static_nexthop *nh, safi_t safi, + struct static_vrf *svrf, const char *ifname, + static_types type, const char *nh_vrf) { - struct route_node *rn; - struct static_route *si; - struct route_table *stable; + struct static_vrf *nh_svrf; + struct interface *ifp; - /* Lookup table. */ - stable = static_vrf_static_table(afi, safi, svrf); - if (!stable) - return -1; + nh_svrf = static_vty_get_unknown_vrf(nh_vrf); - /* Lookup static route prefix. */ - rn = srcdest_rnode_lookup(stable, p, src_p); - if (!rn) - return 0; - - /* Find same static route is the tree */ - for (si = rn->info; si; si = si->next) - if (type == si->type - && (!gate - || ((afi == AFI_IP - && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4)) - || (afi == AFI_IP6 - && IPV6_ADDR_SAME(gate, &si->addr.ipv6)))) - && (!strcmp(ifname ? ifname : "", si->ifname)) - && (!tag || (tag == si->tag)) - && (table_id == si->table_id) - && (!snh_label->num_labels - || !memcmp(&si->snh_label, snh_label, - sizeof(struct static_nh_label)))) - break; - - /* Can't find static route. */ - if (!si) { - route_unlock_node(rn); - return 0; + if (!nh_svrf) + return; + + if (nh_svrf->vrf->vrf_id == VRF_UNKNOWN) + return; + + /* check whether interface exists in system & install if it does */ + switch (nh->type) { + case STATIC_IPV4_GATEWAY: + case STATIC_IPV6_GATEWAY: + if (!static_zebra_nh_update(rn, nh)) + static_zebra_nht_register(rn, nh, true); + break; + case STATIC_IPV4_GATEWAY_IFNAME: + case STATIC_IPV6_GATEWAY_IFNAME: + if (!static_zebra_nh_update(rn, nh)) + static_zebra_nht_register(rn, nh, true); + break; + case STATIC_BLACKHOLE: + static_install_path(rn, pn, safi, svrf); + break; + case STATIC_IFNAME: + ifp = if_lookup_by_name(ifname, nh_svrf->vrf->vrf_id); + if (ifp && ifp->ifindex != IFINDEX_INTERNAL) + static_install_path(rn, pn, safi, svrf); + + break; } +} - static_zebra_nht_register(rn, si, false); +int static_delete_nexthop(struct route_node *rn, struct static_path *pn, + safi_t safi, struct static_vrf *svrf, + struct static_nexthop *nh) +{ + struct static_vrf *nh_svrf; - /* Unlink static route from linked list. */ - if (si->prev) - si->prev->next = si->next; - else - rn->info = si->next; - if (si->next) - si->next->prev = si->prev; + nh_svrf = static_vrf_lookup_by_name(nh->nh_vrfname); + + static_nexthop_list_del(&(pn->nexthop_list), nh); + if (nh_svrf->vrf->vrf_id == VRF_UNKNOWN) + goto EXIT; + + static_zebra_nht_register(rn, nh, false); /* * If we have other si nodes then route replace * else delete the route */ - static_uninstall_route(si->vrf_id, safi, rn, si); - route_unlock_node(rn); - - /* Free static route configuration. */ - XFREE(MTYPE_STATIC_ROUTE, si); + static_uninstall_path(rn, pn, safi, svrf); +EXIT: route_unlock_node(rn); + /* Free static route configuration. */ + XFREE(MTYPE_STATIC_NEXTHOP, nh); return 1; } +static void static_ifindex_update_nh(struct interface *ifp, bool up, + struct route_node *rn, + struct static_path *pn, + struct static_nexthop *nh, + struct static_vrf *svrf, safi_t safi) +{ + if (!nh->ifname[0]) + return; + if (up) { + if (strcmp(nh->ifname, ifp->name)) + return; + if (nh->nh_vrf_id != ifp->vrf_id) + return; + nh->ifindex = ifp->ifindex; + } else { + if (nh->ifindex != ifp->ifindex) + return; + if (nh->nh_vrf_id != ifp->vrf_id) + return; + nh->ifindex = IFINDEX_INTERNAL; + } + + static_install_path(rn, pn, safi, svrf); +} + static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi, safi_t safi) { struct route_table *stable; struct route_node *rn; - struct static_route *si; + struct static_nexthop *nh; + struct static_path *pn; struct vrf *vrf; + struct static_route_info *si; RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { struct static_vrf *svrf; @@ -302,26 +401,17 @@ static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi, stable = static_vrf_static_table(afi, safi, svrf); if (!stable) continue; - for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) { - for (si = rn->info; si; si = si->next) { - if (!si->ifname[0]) - continue; - if (up) { - if (strcmp(si->ifname, ifp->name)) - continue; - if (si->nh_vrf_id != ifp->vrf_id) - continue; - si->ifindex = ifp->ifindex; - } else { - if (si->ifindex != ifp->ifindex) - continue; - if (si->nh_vrf_id != ifp->vrf_id) - continue; - si->ifindex = IFINDEX_INTERNAL; + si = static_route_info_from_rnode(rn); + if (!si) + continue; + frr_each(static_path_list, &si->path_list, pn) { + frr_each(static_nexthop_list, + &pn->nexthop_list, nh) { + static_ifindex_update_nh(ifp, up, rn, + pn, nh, svrf, + safi); } - - static_install_route(rn, si, safi); } } } @@ -343,26 +433,34 @@ static void static_fixup_vrf(struct static_vrf *svrf, struct route_table *stable, afi_t afi, safi_t safi) { struct route_node *rn; - struct static_route *si; + struct static_nexthop *nh; struct interface *ifp; + struct static_path *pn; + struct static_route_info *si; for (rn = route_top(stable); rn; rn = route_next(rn)) { - for (si = rn->info; si; si = si->next) { - if (strcmp(svrf->vrf->name, si->nh_vrfname) != 0) - continue; - - si->nh_vrf_id = svrf->vrf->vrf_id; - si->nh_registered = false; - if (si->ifindex) { - ifp = if_lookup_by_name(si->ifname, - si->nh_vrf_id); - if (ifp) - si->ifindex = ifp->ifindex; - else + si = static_route_info_from_rnode(rn); + if (!si) + continue; + frr_each(static_path_list, &si->path_list, pn) { + frr_each(static_nexthop_list, &pn->nexthop_list, nh) { + if (strcmp(svrf->vrf->name, nh->nh_vrfname) + != 0) continue; - } - static_install_route(rn, si, safi); + nh->nh_vrf_id = svrf->vrf->vrf_id; + nh->nh_registered = false; + if (nh->ifindex) { + ifp = if_lookup_by_name(nh->ifname, + nh->nh_vrf_id); + if (ifp) + nh->ifindex = ifp->ifindex; + else + continue; + } + + static_install_path(rn, pn, safi, svrf); + } } } } @@ -377,26 +475,31 @@ static void static_fixup_vrf(struct static_vrf *svrf, * safi -> the safi in question */ static void static_enable_vrf(struct static_vrf *svrf, - struct route_table *stable, - afi_t afi, safi_t safi) + struct route_table *stable, afi_t afi, + safi_t safi) { struct route_node *rn; - struct static_route *si; + struct static_nexthop *nh; struct interface *ifp; - struct vrf *vrf = svrf->vrf; + struct static_path *pn; + struct static_route_info *si; for (rn = route_top(stable); rn; rn = route_next(rn)) { - for (si = rn->info; si; si = si->next) { - si->vrf_id = vrf->vrf_id; - if (si->ifindex) { - ifp = if_lookup_by_name(si->ifname, - si->nh_vrf_id); - if (ifp) - si->ifindex = ifp->ifindex; - else - continue; + si = static_route_info_from_rnode(rn); + if (!si) + continue; + frr_each(static_path_list, &si->path_list, pn) { + frr_each(static_nexthop_list, &pn->nexthop_list, nh) { + if (nh->ifindex) { + ifp = if_lookup_by_name(nh->ifname, + nh->nh_vrf_id); + if (ifp) + nh->ifindex = ifp->ifindex; + else + continue; + } + static_install_path(rn, pn, safi, svrf); } - static_install_route(rn, si, safi); } } } @@ -452,14 +555,22 @@ static void static_cleanup_vrf(struct static_vrf *svrf, afi_t afi, safi_t safi) { struct route_node *rn; - struct static_route *si; + struct static_nexthop *nh; + struct static_path *pn; + struct static_route_info *si; for (rn = route_top(stable); rn; rn = route_next(rn)) { - for (si = rn->info; si; si = si->next) { - if (strcmp(svrf->vrf->name, si->nh_vrfname) != 0) - continue; + si = static_route_info_from_rnode(rn); + if (!si) + continue; + frr_each(static_path_list, &si->path_list, pn) { + frr_each(static_nexthop_list, &pn->nexthop_list, nh) { + if (strcmp(svrf->vrf->name, nh->nh_vrfname) + != 0) + continue; - static_uninstall_route(si->vrf_id, safi, rn, si); + static_uninstall_path(rn, pn, safi, svrf); + } } } } @@ -476,11 +587,23 @@ static void static_disable_vrf(struct route_table *stable, afi_t afi, safi_t safi) { struct route_node *rn; - struct static_route *si; + struct static_nexthop *nh; + struct static_path *pn; + struct stable_info *info; + struct static_route_info *si; + + info = route_table_get_info(stable); - for (rn = route_top(stable); rn; rn = route_next(rn)) - for (si = rn->info; si; si = si->next) - static_uninstall_route(si->vrf_id, safi, rn, si); + for (rn = route_top(stable); rn; rn = route_next(rn)) { + si = static_route_info_from_rnode(rn); + if (!si) + continue; + frr_each(static_path_list, &si->path_list, pn) { + frr_each(static_nexthop_list, &pn->nexthop_list, nh) { + static_uninstall_path(rn, pn, safi, info->svrf); + } + } + } } /* @@ -535,17 +658,27 @@ static void static_fixup_intf_nh(struct route_table *stable, afi_t afi, safi_t safi) { struct route_node *rn; - struct static_route *si; + struct stable_info *info; + struct static_nexthop *nh; + struct static_path *pn; + struct static_route_info *si; + + info = route_table_get_info(stable); for (rn = route_top(stable); rn; rn = route_next(rn)) { - for (si = rn->info; si; si = si->next) { - if (si->nh_vrf_id != ifp->vrf_id) - continue; + si = static_route_info_from_rnode(rn); + if (!si) + continue; + frr_each(static_path_list, &si->path_list, pn) { + frr_each(static_nexthop_list, &pn->nexthop_list, nh) { + if (nh->nh_vrf_id != ifp->vrf_id) + continue; - if (si->ifindex != ifp->ifindex) - continue; + if (nh->ifindex != ifp->ifindex) + continue; - static_install_route(rn, si, safi); + static_install_path(rn, pn, safi, info->svrf); + } } } } @@ -589,3 +722,40 @@ void static_ifindex_update(struct interface *ifp, bool up) static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_UNICAST); static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_MULTICAST); } + +void static_get_nh_type(static_types stype, char *type, size_t size) +{ + switch (stype) { + case STATIC_IFNAME: + strlcpy(type, "ifindex", size); + break; + case STATIC_IPV4_GATEWAY: + strlcpy(type, "ip4", size); + break; + case STATIC_IPV4_GATEWAY_IFNAME: + strlcpy(type, "ip4-ifindex", size); + break; + case STATIC_BLACKHOLE: + strlcpy(type, "blackhole", size); + break; + case STATIC_IPV6_GATEWAY: + strlcpy(type, "ip6", size); + break; + case STATIC_IPV6_GATEWAY_IFNAME: + strlcpy(type, "ip6-ifindex", size); + break; + }; +} + +struct stable_info *static_get_stable_info(struct route_node *rn) +{ + struct route_table *table; + + table = srcdest_rnode_table(rn); + return table->info; +} + +void static_route_info_init(struct static_route_info *si) +{ + static_path_list_init(&(si->path_list)); +} diff --git a/staticd/static_routes.h b/staticd/static_routes.h index 6414947b16..89ef544023 100644 --- a/staticd/static_routes.h +++ b/staticd/static_routes.h @@ -21,6 +21,7 @@ #define __STATIC_ROUTES_H__ #include "lib/mpls.h" +#include "table.h" /* Static route label information */ struct static_nh_label { @@ -35,13 +36,17 @@ enum static_blackhole_type { STATIC_BLACKHOLE_REJECT }; +/* + * The order for below macros should be in sync with + * yang model typedef nexthop-type + */ typedef enum { - STATIC_IFNAME, + STATIC_IFNAME = 1, STATIC_IPV4_GATEWAY, STATIC_IPV4_GATEWAY_IFNAME, - STATIC_BLACKHOLE, STATIC_IPV6_GATEWAY, STATIC_IPV6_GATEWAY_IFNAME, + STATIC_BLACKHOLE, } static_types; /* @@ -64,14 +69,37 @@ enum static_install_states { STATIC_NOT_INSTALLED, }; +PREDECL_DLIST(static_path_list); +PREDECL_DLIST(static_nexthop_list); + +/* Static route information */ +struct static_route_info { + /* path list */ + struct static_path_list_head path_list; +}; + +/* Static path information */ +struct static_path { + /* Linkage for static path lists */ + struct static_path_list_item list; + /* Administrative distance. */ + uint8_t distance; + /* Tag */ + route_tag_t tag; + /* Table-id */ + uint32_t table_id; + /* Nexthop list */ + struct static_nexthop_list_head nexthop_list; +}; + +DECLARE_DLIST(static_path_list, struct static_path, list); + /* Static route information. */ -struct static_route { +struct static_nexthop { /* For linked list. */ - struct static_route *prev; - struct static_route *next; + struct static_nexthop_list_item list; /* VRF identifier. */ - vrf_id_t vrf_id; vrf_id_t nh_vrf_id; char nh_vrfname[VRF_NAMSIZ + 1]; @@ -81,12 +109,6 @@ struct static_route { */ enum static_install_states state; - /* Administrative distance. */ - uint8_t distance; - - /* Tag */ - route_tag_t tag; - /* Flag for this static route's type. */ static_types type; @@ -104,8 +126,6 @@ struct static_route { /* Label information */ struct static_nh_label snh_label; - uint32_t table_id; - /* * Whether to pretend the nexthop is directly attached to the specified * link. Only meaningful when both a gateway address and interface name @@ -114,32 +134,64 @@ struct static_route { bool onlink; }; +DECLARE_DLIST(static_nexthop_list, struct static_nexthop, list); + + +/* + * rib_dest_from_rnode + */ +static inline struct static_route_info * +static_route_info_from_rnode(struct route_node *rn) +{ + return (struct static_route_info *)(rn->info); +} + extern bool mpls_enabled; extern struct zebra_privs_t static_privs; void static_fixup_vrf_ids(struct static_vrf *svrf); -extern int static_add_route(afi_t afi, safi_t safi, uint8_t type, - struct prefix *p, struct prefix_ipv6 *src_p, - union g_addr *gate, const char *ifname, - enum static_blackhole_type bh_type, route_tag_t tag, - uint8_t distance, struct static_vrf *svrf, - struct static_vrf *nh_svrf, - struct static_nh_label *snh_label, - uint32_t table_id, bool onlink); - -extern int static_delete_route(afi_t afi, safi_t safi, uint8_t type, - struct prefix *p, struct prefix_ipv6 *src_p, - union g_addr *gate, const char *ifname, - route_tag_t tag, uint8_t distance, - struct static_vrf *svrf, - struct static_nh_label *snh_label, - uint32_t table_id); +extern struct static_nexthop * +static_add_nexthop(struct route_node *rn, struct static_path *pn, safi_t safi, + struct static_vrf *svrf, static_types type, + struct ipaddr *ipaddr, const char *ifname, + const char *nh_vrf); +extern void static_install_nexthop(struct route_node *rn, + struct static_path *pn, + struct static_nexthop *nh, safi_t safi, + struct static_vrf *svrf, const char *ifname, + static_types type, const char *nh_vrf); + +extern int static_delete_nexthop(struct route_node *rn, struct static_path *pn, + safi_t safi, struct static_vrf *svrf, + struct static_nexthop *nh); extern void static_cleanup_vrf_ids(struct static_vrf *disable_svrf); extern void static_install_intf_nh(struct interface *ifp); extern void static_ifindex_update(struct interface *ifp, bool up); + +extern void static_install_path(struct route_node *rn, struct static_path *pn, + safi_t safi, struct static_vrf *svrf); + +extern struct route_node *static_add_route(afi_t afi, safi_t safi, + struct prefix *p, + struct prefix_ipv6 *src_p, + struct static_vrf *svrf); +extern void static_del_route(struct route_node *rn, safi_t safi, + struct static_vrf *svrf); + +extern struct static_path *static_add_path(struct route_node *rn, + uint8_t distance); +extern void static_del_path(struct route_node *rn, struct static_path *pn, + safi_t safi, struct static_vrf *svrf); + +extern void static_get_nh_type(static_types stype, char *type, size_t size); +extern bool static_add_nexthop_validate(struct static_vrf *svrf, + static_types type, + struct ipaddr *ipaddr); +extern struct stable_info *static_get_stable_info(struct route_node *rn); +extern void static_route_info_init(struct static_route_info *si); #endif diff --git a/staticd/static_vrf.c b/staticd/static_vrf.c index 6c065932a1..39b86787ff 100644 --- a/staticd/static_vrf.c +++ b/staticd/static_vrf.c @@ -30,26 +30,39 @@ #include "static_zebra.h" #include "static_vty.h" +DEFINE_MTYPE_STATIC(STATIC, STATIC_RTABLE_INFO, "Static Route Table Info"); + static void zebra_stable_node_cleanup(struct route_table *table, struct route_node *node) { - struct static_route *si, *next; - - if (node->info) - for (si = node->info; si; si = next) { - next = si->next; - XFREE(MTYPE_STATIC_ROUTE, si); + struct static_nexthop *nh; + struct static_path *pn; + struct static_route_info *si; + + si = node->info; + + if (si) { + frr_each_safe(static_path_list, &si->path_list, pn) { + frr_each_safe(static_nexthop_list, &pn->nexthop_list, + nh) { + static_nexthop_list_del(&pn->nexthop_list, nh); + XFREE(MTYPE_STATIC_NEXTHOP, nh); + } + static_path_list_del(&si->path_list, pn); + XFREE(MTYPE_STATIC_PATH, pn); } + } } static struct static_vrf *static_vrf_alloc(void) { struct route_table *table; struct static_vrf *svrf; + struct stable_info *info; safi_t safi; afi_t afi; - svrf = XCALLOC(MTYPE_TMP, sizeof(struct static_vrf)); + svrf = XCALLOC(MTYPE_STATIC_RTABLE_INFO, sizeof(struct static_vrf)); for (afi = AFI_IP; afi <= AFI_IP6; afi++) { for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) { @@ -57,6 +70,14 @@ static struct static_vrf *static_vrf_alloc(void) table = srcdest_table_init(); else table = route_table_init(); + + info = XCALLOC(MTYPE_STATIC_RTABLE_INFO, + sizeof(struct stable_info)); + info->svrf = svrf; + info->afi = afi; + info->safi = safi; + route_table_set_info(table, info); + table->cleanup = zebra_stable_node_cleanup; svrf->stable[afi][safi] = table; } @@ -81,12 +102,6 @@ static int static_vrf_enable(struct vrf *vrf) static_fixup_vrf_ids(vrf->info); - /* - * We may have static routes that are now possible to - * insert into the appropriate tables - */ - static_config_install_delayed_routes(vrf->info); - return 0; } @@ -102,16 +117,19 @@ static int static_vrf_delete(struct vrf *vrf) struct static_vrf *svrf; safi_t safi; afi_t afi; + void *info; svrf = vrf->info; for (afi = AFI_IP; afi <= AFI_IP6; afi++) { for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) { table = svrf->stable[afi][safi]; + info = route_table_get_info(table); route_table_finish(table); + XFREE(MTYPE_STATIC_RTABLE_INFO, info); svrf->stable[afi][safi] = NULL; } } - XFREE(MTYPE_TMP, svrf); + XFREE(MTYPE_STATIC_RTABLE_INFO, svrf); return 0; } @@ -210,3 +228,25 @@ void static_vrf_terminate(void) { vrf_terminate(); } + +struct static_vrf *static_vty_get_unknown_vrf(const char *vrf_name) +{ + struct static_vrf *svrf; + struct vrf *vrf; + + svrf = static_vrf_lookup_by_name(vrf_name); + + if (svrf) + return svrf; + + vrf = vrf_get(VRF_UNKNOWN, vrf_name); + if (!vrf) + return NULL; + svrf = vrf->info; + if (!svrf) + return NULL; + /* Mark as having FRR configuration */ + vrf_set_user_cfged(vrf); + + return svrf; +} diff --git a/staticd/static_vrf.h b/staticd/static_vrf.h index 6951e56712..12ad1b255a 100644 --- a/staticd/static_vrf.h +++ b/staticd/static_vrf.h @@ -26,6 +26,14 @@ struct static_vrf { struct route_table *stable[AFI_MAX][SAFI_MAX]; }; +struct stable_info { + struct static_vrf *svrf; + afi_t afi; + safi_t safi; +}; + +#define GET_STABLE_VRF_ID(info) info->svrf->vrf->vrf_id + struct static_vrf *static_vrf_lookup_by_name(const char *vrf_name); struct static_vrf *static_vrf_lookup_by_id(vrf_id_t vrf_id); @@ -36,4 +44,6 @@ void static_vrf_init(void); struct route_table *static_vrf_static_table(afi_t afi, safi_t safi, struct static_vrf *svrf); extern void static_vrf_terminate(void); + +struct static_vrf *static_vty_get_unknown_vrf(const char *vrf_name); #endif diff --git a/staticd/static_vty.c b/staticd/static_vty.c index 75bce82eef..63b425771a 100644 --- a/staticd/static_vty.c +++ b/staticd/static_vty.c @@ -27,6 +27,10 @@ #include "table.h" #include "srcdest_table.h" #include "mpls.h" +#include "northbound.h" +#include "libfrr.h" +#include "routing_nb.h" +#include "northbound_cli.h" #include "static_vrf.h" #include "static_memory.h" @@ -36,251 +40,43 @@ #ifndef VTYSH_EXTRACT_PL #include "staticd/static_vty_clippy.c" #endif +#include "static_nb.h" #define STATICD_STR "Static route daemon\n" -static struct static_vrf *static_vty_get_unknown_vrf(struct vty *vty, - const char *vrf_name) +static int static_route_leak(struct vty *vty, const char *svrf, + const char *nh_svrf, afi_t afi, safi_t safi, + const char *negate, const char *dest_str, + const char *mask_str, const char *src_str, + const char *gate_str, const char *ifname, + const char *flag_str, const char *tag_str, + const char *distance_str, const char *label_str, + const char *table_str, bool onlink) { - struct static_vrf *svrf; - struct vrf *vrf; - - svrf = static_vrf_lookup_by_name(vrf_name); - - if (svrf) - return svrf; - - vrf = vrf_get(VRF_UNKNOWN, vrf_name); - if (!vrf) { - vty_out(vty, "%% Could not create vrf %s\n", vrf_name); - return NULL; - } - svrf = vrf->info; - if (!svrf) { - vty_out(vty, "%% Could not create vrf-info %s\n", - vrf_name); - return NULL; - } - /* Mark as having FRR configuration */ - vrf_set_user_cfged(vrf); - - return svrf; -} - -struct static_hold_route { - char *vrf_name; - char *nhvrf_name; - afi_t afi; - safi_t safi; - char *dest_str; - char *mask_str; - char *src_str; - char *gate_str; - char *ifname; - char *flag_str; - char *tag_str; - char *distance_str; - char *label_str; - char *table_str; - bool onlink; - - /* processed & masked destination, used for config display */ - struct prefix dest; -}; - -static struct list *static_list; - -static int static_list_compare_helper(const char *s1, const char *s2) -{ - /* extra (!s1 && !s2) to keep SA happy */ - if (s1 == s2 || (!s1 && !s2)) - return 0; - - if (!s1 && s2) - return -1; - - if (s1 && !s2) - return 1; - - return strcmp(s1, s2); -} - -static void static_list_delete(struct static_hold_route *shr) -{ - XFREE(MTYPE_STATIC_ROUTE, shr->vrf_name); - XFREE(MTYPE_STATIC_ROUTE, shr->nhvrf_name); - XFREE(MTYPE_STATIC_ROUTE, shr->dest_str); - XFREE(MTYPE_STATIC_ROUTE, shr->mask_str); - XFREE(MTYPE_STATIC_ROUTE, shr->src_str); - XFREE(MTYPE_STATIC_ROUTE, shr->gate_str); - XFREE(MTYPE_STATIC_ROUTE, shr->ifname); - XFREE(MTYPE_STATIC_ROUTE, shr->flag_str); - XFREE(MTYPE_STATIC_ROUTE, shr->tag_str); - XFREE(MTYPE_STATIC_ROUTE, shr->distance_str); - XFREE(MTYPE_STATIC_ROUTE, shr->label_str); - XFREE(MTYPE_STATIC_ROUTE, shr->table_str); - - XFREE(MTYPE_STATIC_ROUTE, shr); -} - -static int static_list_compare(void *arg1, void *arg2) -{ - struct static_hold_route *shr1 = arg1; - struct static_hold_route *shr2 = arg2; int ret; - - ret = strcmp(shr1->vrf_name, shr2->vrf_name); - if (ret) - return ret; - - ret = strcmp(shr1->nhvrf_name, shr2->nhvrf_name); - if (ret) - return ret; - - ret = shr1->afi - shr2->afi; - if (ret) - return ret; - - ret = shr1->safi - shr2->safi; - if (ret) - return ret; - - ret = prefix_cmp(&shr1->dest, &shr2->dest); - if (ret) - return ret; - - ret = static_list_compare_helper(shr1->src_str, shr2->src_str); - if (ret) - return ret; - - ret = static_list_compare_helper(shr1->gate_str, shr2->gate_str); - if (ret) - return ret; - - ret = static_list_compare_helper(shr1->ifname, shr2->ifname); - if (ret) - return ret; - - ret = static_list_compare_helper(shr1->flag_str, shr2->flag_str); - if (ret) - return ret; - - ret = static_list_compare_helper(shr1->tag_str, shr2->tag_str); - if (ret) - return ret; - - ret = static_list_compare_helper(shr1->distance_str, - shr2->distance_str); - if (ret) - return ret; - - ret = static_list_compare_helper(shr1->table_str, - shr2->table_str); - if (ret) - return ret; - - return static_list_compare_helper(shr1->label_str, shr2->label_str); -} - - -/* General function for static route. */ -static int zebra_static_route_holdem( - struct static_vrf *svrf, struct static_vrf *nh_svrf, afi_t afi, - safi_t safi, const char *negate, struct prefix *dest, - const char *dest_str, const char *mask_str, const char *src_str, - const char *gate_str, const char *ifname, const char *flag_str, - const char *tag_str, const char *distance_str, const char *label_str, - const char *table_str, bool onlink) -{ - struct static_hold_route *shr, *lookup; - struct listnode *node; - - zlog_warn("Static Route to %s not installed currently because dependent config not fully available", - dest_str); - - shr = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(*shr)); - shr->vrf_name = XSTRDUP(MTYPE_STATIC_ROUTE, svrf->vrf->name); - shr->nhvrf_name = XSTRDUP(MTYPE_STATIC_ROUTE, nh_svrf->vrf->name); - shr->afi = afi; - shr->safi = safi; - shr->onlink = onlink; - if (dest) - prefix_copy(&shr->dest, dest); - if (dest_str) - shr->dest_str = XSTRDUP(MTYPE_STATIC_ROUTE, dest_str); - if (mask_str) - shr->mask_str = XSTRDUP(MTYPE_STATIC_ROUTE, mask_str); - if (src_str) - shr->src_str = XSTRDUP(MTYPE_STATIC_ROUTE, src_str); - if (gate_str) - shr->gate_str = XSTRDUP(MTYPE_STATIC_ROUTE, gate_str); - if (ifname) - shr->ifname = XSTRDUP(MTYPE_STATIC_ROUTE, ifname); - if (flag_str) - shr->flag_str = XSTRDUP(MTYPE_STATIC_ROUTE, flag_str); - if (tag_str) - shr->tag_str = XSTRDUP(MTYPE_STATIC_ROUTE, tag_str); - if (distance_str) - shr->distance_str = XSTRDUP(MTYPE_STATIC_ROUTE, distance_str); - if (label_str) - shr->label_str = XSTRDUP(MTYPE_STATIC_ROUTE, label_str); - if (table_str) - shr->table_str = XSTRDUP(MTYPE_STATIC_ROUTE, table_str); - - for (ALL_LIST_ELEMENTS_RO(static_list, node, lookup)) { - if (static_list_compare(shr, lookup) == 0) - break; - } - - if (lookup) { - if (negate) { - listnode_delete(static_list, lookup); - static_list_delete(shr); - static_list_delete(lookup); - - return CMD_SUCCESS; - } - - /* - * If a person enters the same line again - * we need to silently accept it - */ - goto shr_cleanup; - } - - if (!negate) { - listnode_add_sort(static_list, shr); - return CMD_SUCCESS; - } - - shr_cleanup: - XFREE(MTYPE_STATIC_ROUTE, shr->nhvrf_name); - XFREE(MTYPE_STATIC_ROUTE, shr->vrf_name); - XFREE(MTYPE_STATIC_ROUTE, shr); - - return CMD_SUCCESS; -} - -static int static_route_leak( - struct vty *vty, struct static_vrf *svrf, struct static_vrf *nh_svrf, - afi_t afi, safi_t safi, const char *negate, const char *dest_str, - const char *mask_str, const char *src_str, const char *gate_str, - const char *ifname, const char *flag_str, const char *tag_str, - const char *distance_str, const char *label_str, const char *table_str, - bool onlink) -{ - int ret; - uint8_t distance; struct prefix p, src; - struct prefix_ipv6 *src_p = NULL; - union g_addr gate; - union g_addr *gatep = NULL; struct in_addr mask; - enum static_blackhole_type bh_type = 0; - route_tag_t tag = 0; uint8_t type; - struct static_nh_label snh_label; + const char *bh_type; + char xpath_prefix[XPATH_MAXLEN]; + char xpath_nexthop[XPATH_MAXLEN]; + char xpath_mpls[XPATH_MAXLEN]; + char xpath_label[XPATH_MAXLEN]; + char ab_xpath[XPATH_MAXLEN]; + char buf_prefix[PREFIX_STRLEN]; + char buf_src_prefix[PREFIX_STRLEN]; + char buf_nh_type[PREFIX_STRLEN]; + char buf_tag[PREFIX_STRLEN]; + char buf_tableid[PREFIX_STRLEN]; + uint8_t label_stack_id = 0; + const char *buf_gate_str; + uint8_t distance = ZEBRA_STATIC_DISTANCE_DEFAULT; + route_tag_t tag = 0; uint32_t table_id = 0; + const struct lyd_node *dnode; + + memset(buf_src_prefix, 0, PREFIX_STRLEN); + memset(buf_nh_type, 0, PREFIX_STRLEN); ret = str2prefix(dest_str, &p); if (ret <= 0) { @@ -322,7 +118,6 @@ static int static_route_leak( __func__, src_str); return CMD_WARNING_CONFIG_FAILED; } - src_p = (struct prefix_ipv6 *)&src; } break; default: @@ -332,29 +127,29 @@ static int static_route_leak( /* Apply mask for given prefix. */ apply_mask(&p); - if (svrf->vrf->vrf_id == VRF_UNKNOWN - || nh_svrf->vrf->vrf_id == VRF_UNKNOWN) { - vrf_set_user_cfged(svrf->vrf); - return zebra_static_route_holdem( - svrf, nh_svrf, afi, safi, negate, &p, dest_str, - mask_str, src_str, gate_str, ifname, flag_str, tag_str, - distance_str, label_str, table_str, onlink); - } + prefix2str(&p, buf_prefix, sizeof(buf_prefix)); - if (table_str) { - /* table configured. check consistent with vrf config - */ - if (svrf->vrf->data.l.table_id != RT_TABLE_MAIN) { - if (vty) - vty_out(vty, - "%% Table %s overlaps vrf table %u\n", - table_str, svrf->vrf->data.l.table_id); - else - zlog_warn("%s: Table %s overlaps vrf table %u", - __func__, table_str, - svrf->vrf->data.l.table_id); - return CMD_WARNING_CONFIG_FAILED; - } + if (src_str) + prefix2str(&src, buf_src_prefix, sizeof(buf_src_prefix)); + if (gate_str) + buf_gate_str = gate_str; + else + buf_gate_str = ""; + + if (gate_str == NULL && ifname == NULL) + type = STATIC_BLACKHOLE; + else if (gate_str && ifname) { + if (afi == AFI_IP) + type = STATIC_IPV4_GATEWAY_IFNAME; + else + type = STATIC_IPV6_GATEWAY_IFNAME; + } else if (ifname) + type = STATIC_IFNAME; + else { + if (afi == AFI_IP) + type = STATIC_IPV4_GATEWAY; + else + type = STATIC_IPV6_GATEWAY; } /* Administrative distance. */ @@ -367,169 +162,160 @@ static int static_route_leak( if (tag_str) tag = strtoul(tag_str, NULL, 10); - /* Labels */ - memset(&snh_label, 0, sizeof(struct static_nh_label)); - if (label_str) { - if (!mpls_enabled) { - if (vty) - vty_out(vty, - "%% MPLS not turned on in kernel, ignoring command\n"); - else - zlog_warn( - "%s: MPLS not turned on in kernel ignoring static route to %s", - __func__, dest_str); - return CMD_WARNING_CONFIG_FAILED; - } - int rc = mpls_str2label(label_str, &snh_label.num_labels, - snh_label.label); - if (rc < 0) { - switch (rc) { - case -1: - if (vty) - vty_out(vty, "%% Malformed label(s)\n"); - else - zlog_warn( - "%s: Malformed labels specified for route %s", - __func__, dest_str); - break; - case -2: - if (vty) - vty_out(vty, - "%% Cannot use reserved label(s) (%d-%d)\n", - MPLS_LABEL_RESERVED_MIN, - MPLS_LABEL_RESERVED_MAX); - else - zlog_warn( - "%s: Cannot use reserved labels (%d-%d) for %s", - __func__, - MPLS_LABEL_RESERVED_MIN, - MPLS_LABEL_RESERVED_MAX, - dest_str); - break; - case -3: - if (vty) - vty_out(vty, - "%% Too many labels. Enter %d or fewer\n", - MPLS_MAX_LABELS); - else - zlog_warn( - "%s: Too many labels, Enter %d or fewer for %s", - __func__, MPLS_MAX_LABELS, - dest_str); - break; - } - return CMD_WARNING_CONFIG_FAILED; - } - } - /* TableID */ if (table_str) table_id = atol(table_str); - /* Null0 static route. */ - if (ifname != NULL) { - if (strcasecmp(ifname, "Null0") == 0 - || strcasecmp(ifname, "reject") == 0 - || strcasecmp(ifname, "blackhole") == 0) { - if (vty) - vty_out(vty, - "%% Nexthop interface name can not be from reserved keywords (Null0, reject, blackhole)\n"); - else - zlog_warn( - "%s: %s: Nexthop interface name can not be from reserved keywords (Null0, reject, blackhole)", - __func__, dest_str); - return CMD_WARNING_CONFIG_FAILED; - } - } - - /* Route flags */ - if (flag_str) { - switch (flag_str[0]) { - case 'r': - bh_type = STATIC_BLACKHOLE_REJECT; - break; - case 'b': - bh_type = STATIC_BLACKHOLE_DROP; - break; - case 'N': - bh_type = STATIC_BLACKHOLE_NULL; - break; - default: - if (vty) - vty_out(vty, "%% Malformed flag %s \n", - flag_str); - else - zlog_warn("%s: Malformed flag %s for %s", - __func__, flag_str, dest_str); - return CMD_WARNING_CONFIG_FAILED; + static_get_nh_type(type, buf_nh_type, PREFIX_STRLEN); + if (!negate) { + /* route + path procesing */ + if (src_str) + snprintf(xpath_prefix, sizeof(xpath_prefix), + FRR_S_ROUTE_SRC_INFO_KEY_XPATH, + "frr-staticd:staticd", "staticd", svrf, + buf_prefix, + yang_afi_safi_value2identity(afi, safi), + buf_src_prefix, distance); + else + snprintf(xpath_prefix, sizeof(xpath_prefix), + FRR_STATIC_ROUTE_INFO_KEY_XPATH, + "frr-staticd:staticd", "staticd", svrf, + buf_prefix, + yang_afi_safi_value2identity(afi, safi), + distance); + + nb_cli_enqueue_change(vty, xpath_prefix, NB_OP_CREATE, NULL); + + /* Tag processing */ + snprintf(buf_tag, sizeof(buf_tag), "%u", tag); + strlcpy(ab_xpath, xpath_prefix, sizeof(ab_xpath)); + strlcat(ab_xpath, FRR_STATIC_ROUTE_PATH_TAG_XPATH, + sizeof(ab_xpath)); + nb_cli_enqueue_change(vty, ab_xpath, NB_OP_MODIFY, buf_tag); + + /* Table-Id processing */ + snprintf(buf_tableid, sizeof(buf_tableid), "%u", table_id); + strlcpy(ab_xpath, xpath_prefix, sizeof(ab_xpath)); + strlcat(ab_xpath, FRR_STATIC_ROUTE_PATH_TABLEID_XPATH, + sizeof(ab_xpath)); + nb_cli_enqueue_change(vty, ab_xpath, NB_OP_MODIFY, buf_tableid); + /* nexthop processing */ + + snprintf(ab_xpath, sizeof(ab_xpath), + FRR_STATIC_ROUTE_NH_KEY_XPATH, buf_nh_type, nh_svrf, + buf_gate_str, ifname); + strlcpy(xpath_nexthop, xpath_prefix, sizeof(xpath_nexthop)); + strlcat(xpath_nexthop, ab_xpath, sizeof(xpath_nexthop)); + nb_cli_enqueue_change(vty, xpath_nexthop, NB_OP_CREATE, NULL); + + if (type == STATIC_BLACKHOLE) { + strlcpy(ab_xpath, xpath_nexthop, sizeof(ab_xpath)); + strlcat(ab_xpath, FRR_STATIC_ROUTE_NH_BH_XPATH, + sizeof(ab_xpath)); + + /* Route flags */ + if (flag_str) { + switch (flag_str[0]) { + case 'r': + bh_type = "reject"; + break; + case 'b': + bh_type = "unspec"; + break; + case 'N': + bh_type = "null"; + break; + default: + bh_type = NULL; + break; + } + nb_cli_enqueue_change(vty, ab_xpath, + NB_OP_MODIFY, bh_type); + } else { + nb_cli_enqueue_change(vty, ab_xpath, + NB_OP_MODIFY, "null"); + } } - } - - if (gate_str) { - if (inet_pton(afi2family(afi), gate_str, &gate) != 1) { - if (vty) - vty_out(vty, - "%% Malformed nexthop address %s\n", - gate_str); + if (type == STATIC_IPV4_GATEWAY_IFNAME + || type == STATIC_IPV6_GATEWAY_IFNAME) { + strlcpy(ab_xpath, xpath_nexthop, sizeof(ab_xpath)); + strlcat(ab_xpath, FRR_STATIC_ROUTE_NH_ONLINK_XPATH, + sizeof(ab_xpath)); + + if (onlink) + nb_cli_enqueue_change(vty, ab_xpath, + NB_OP_MODIFY, "true"); else - zlog_warn( - "%s: Malformed nexthop address %s for %s", - __func__, gate_str, dest_str); - return CMD_WARNING_CONFIG_FAILED; + nb_cli_enqueue_change(vty, ab_xpath, + NB_OP_MODIFY, "false"); } - gatep = &gate; - - if (afi == AFI_IP && !negate) { - if (if_lookup_exact_address(&gatep->ipv4, AF_INET, - svrf->vrf->vrf_id)) - if (vty) - vty_out(vty, - "%% Warning!! Local connected address is configured as Gateway IP(%s)\n", - gate_str); - } else if (afi == AFI_IP6 && !negate) { - if (if_lookup_exact_address(&gatep->ipv6, AF_INET6, - svrf->vrf->vrf_id)) - if (vty) - vty_out(vty, - "%% Warning!! Local connected address is configured as Gateway IPv6(%s)\n", - gate_str); + if (label_str) { + /* copy of label string (start) */ + char *ostr; + /* pointer to next segment */ + char *nump; + + strlcpy(xpath_mpls, xpath_nexthop, sizeof(xpath_mpls)); + strlcat(xpath_mpls, FRR_STATIC_ROUTE_NH_LABEL_XPATH, + sizeof(xpath_mpls)); + + nb_cli_enqueue_change(vty, xpath_mpls, NB_OP_DESTROY, + NULL); + + ostr = XSTRDUP(MTYPE_TMP, label_str); + while ((nump = strsep(&ostr, "/")) != NULL) { + snprintf(ab_xpath, sizeof(ab_xpath), + FRR_STATIC_ROUTE_NHLB_KEY_XPATH, + label_stack_id); + strlcpy(xpath_label, xpath_mpls, + sizeof(xpath_label)); + strlcat(xpath_label, ab_xpath, + sizeof(xpath_label)); + nb_cli_enqueue_change(vty, xpath_label, + NB_OP_MODIFY, nump); + label_stack_id++; + } + XFREE(MTYPE_TMP, ostr); + } else { + strlcpy(xpath_mpls, xpath_nexthop, sizeof(xpath_mpls)); + strlcat(xpath_mpls, FRR_STATIC_ROUTE_NH_LABEL_XPATH, + sizeof(xpath_mpls)); + nb_cli_enqueue_change(vty, xpath_mpls, NB_OP_DESTROY, + NULL); } - - } - - if (gate_str == NULL && ifname == NULL) - type = STATIC_BLACKHOLE; - else if (gate_str && ifname) { - if (afi == AFI_IP) - type = STATIC_IPV4_GATEWAY_IFNAME; - else - type = STATIC_IPV6_GATEWAY_IFNAME; - } else if (ifname) - type = STATIC_IFNAME; - else { - if (afi == AFI_IP) - type = STATIC_IPV4_GATEWAY; - else - type = STATIC_IPV6_GATEWAY; - } - - if (!negate) { - static_add_route(afi, safi, type, &p, src_p, gatep, ifname, - bh_type, tag, distance, svrf, nh_svrf, - &snh_label, table_id, onlink); - /* Mark as having FRR configuration */ - vrf_set_user_cfged(svrf->vrf); + ret = nb_cli_apply_changes(vty, xpath_prefix); } else { - static_delete_route(afi, safi, type, &p, src_p, gatep, ifname, - tag, distance, svrf, &snh_label, table_id); - /* If no other FRR config for this VRF, mark accordingly. */ - if (!static_vrf_has_config(svrf)) - vrf_reset_user_cfged(svrf->vrf); + if (src_str) + snprintf(ab_xpath, sizeof(ab_xpath), + FRR_DEL_S_ROUTE_SRC_NH_KEY_XPATH, + "frr-staticd:staticd", "staticd", svrf, + buf_prefix, + yang_afi_safi_value2identity(afi, safi), + buf_src_prefix, distance, buf_nh_type, nh_svrf, + buf_gate_str, ifname); + else + snprintf(ab_xpath, sizeof(ab_xpath), + FRR_DEL_S_ROUTE_NH_KEY_XPATH, + "frr-staticd:staticd", "staticd", svrf, + buf_prefix, + yang_afi_safi_value2identity(afi, safi), + distance, buf_nh_type, nh_svrf, buf_gate_str, + ifname); + + dnode = yang_dnode_get(vty->candidate_config->dnode, ab_xpath); + if (!dnode) + return ret; + + dnode = yang_get_subtree_with_no_sibling(dnode); + assert(dnode); + yang_dnode_get_path(dnode, ab_xpath, XPATH_MAXLEN); + + nb_cli_enqueue_change(vty, ab_xpath, NB_OP_DESTROY, NULL); + ret = nb_cli_apply_changes(vty, ab_xpath); } - return CMD_SUCCESS; + return ret; } - static int static_route(struct vty *vty, afi_t afi, safi_t safi, const char *negate, const char *dest_str, const char *mask_str, const char *src_str, @@ -538,77 +324,28 @@ static int static_route(struct vty *vty, afi_t afi, safi_t safi, const char *distance_str, const char *vrf_name, const char *label_str, const char *table_str) { - struct static_vrf *svrf; - - /* VRF id */ - svrf = static_vrf_lookup_by_name(vrf_name); - - /* When trying to delete, the VRF must exist. */ - if (negate && !svrf) { - vty_out(vty, "%% vrf %s is not defined\n", vrf_name); - return CMD_WARNING_CONFIG_FAILED; - } + if (!vrf_name) + vrf_name = VRF_DEFAULT_NAME; - /* When trying to create, create the VRF if it doesn't exist. - * Note: The VRF isn't active until we hear about it from the kernel. - */ - if (!svrf) { - svrf = static_vty_get_unknown_vrf(vty, vrf_name); - if (!svrf) - return CMD_WARNING_CONFIG_FAILED; - } - return static_route_leak(vty, svrf, svrf, afi, safi, negate, dest_str, - mask_str, src_str, gate_str, ifname, flag_str, - tag_str, distance_str, label_str, table_str, - false); -} - -void static_config_install_delayed_routes(struct static_vrf *svrf) -{ - struct listnode *node, *nnode; - struct static_hold_route *shr; - struct static_vrf *osvrf, *nh_svrf; - int installed; - - for (ALL_LIST_ELEMENTS(static_list, node, nnode, shr)) { - osvrf = static_vrf_lookup_by_name(shr->vrf_name); - nh_svrf = static_vrf_lookup_by_name(shr->nhvrf_name); - - if (osvrf != svrf && nh_svrf != svrf) - continue; - - if (osvrf->vrf->vrf_id == VRF_UNKNOWN - || nh_svrf->vrf->vrf_id == VRF_UNKNOWN) - continue; - - installed = static_route_leak( - NULL, osvrf, nh_svrf, shr->afi, shr->safi, NULL, - shr->dest_str, shr->mask_str, shr->src_str, - shr->gate_str, shr->ifname, shr->flag_str, shr->tag_str, - shr->distance_str, shr->label_str, shr->table_str, - shr->onlink); - - if (installed != CMD_SUCCESS) - zlog_debug( - "%s: Attempt to install %s as a route and it was rejected", - __func__, shr->dest_str); - listnode_delete(static_list, shr); - static_list_delete(shr); - } + return static_route_leak(vty, vrf_name, vrf_name, afi, safi, negate, + dest_str, mask_str, src_str, gate_str, ifname, + flag_str, tag_str, distance_str, label_str, + table_str, false); } /* Write static route configuration. */ int static_config(struct vty *vty, struct static_vrf *svrf, afi_t afi, safi_t safi, const char *cmd) { - struct static_hold_route *shr; - struct listnode *node; char spacing[100]; struct route_node *rn; - struct static_route *si; + struct static_nexthop *nh; + struct static_path *pn; struct route_table *stable; + struct static_route_info *si; char buf[SRCDEST2STR_BUFFER]; int write = 0; + struct stable_info *info; stable = svrf->stable[afi][safi]; if (stable == NULL) @@ -617,120 +354,99 @@ int static_config(struct vty *vty, struct static_vrf *svrf, afi_t afi, snprintf(spacing, sizeof(spacing), "%s%s", (svrf->vrf->vrf_id == VRF_DEFAULT) ? "" : " ", cmd); - /* - * Static routes for vrfs not fully inited - */ - for (ALL_LIST_ELEMENTS_RO(static_list, node, shr)) { - if (shr->afi != afi || shr->safi != safi) + for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) { + si = static_route_info_from_rnode(rn); + if (!si) continue; - - if (strcmp(svrf->vrf->name, shr->vrf_name) != 0) - continue; - - char dest_str[PREFIX_STRLEN]; - - prefix2str(&shr->dest, dest_str, sizeof(dest_str)); - - vty_out(vty, "%s ", spacing); - if (shr->dest_str) - vty_out(vty, "%s ", dest_str); - if (shr->src_str) - vty_out(vty, "from %s ", shr->src_str); - if (shr->gate_str) - vty_out(vty, "%s ", shr->gate_str); - if (shr->ifname) - vty_out(vty, "%s ", shr->ifname); - if (shr->flag_str) - vty_out(vty, "%s ", shr->flag_str); - if (shr->tag_str) - vty_out(vty, "tag %s ", shr->tag_str); - if (shr->distance_str) - vty_out(vty, "%s ", shr->distance_str); - if (shr->label_str) - vty_out(vty, "label %s ", shr->label_str); - if (shr->table_str) - vty_out(vty, "table %s", shr->table_str); - if (strcmp(shr->vrf_name, shr->nhvrf_name) != 0) - vty_out(vty, "nexthop-vrf %s ", shr->nhvrf_name); - if (shr->onlink) - vty_out(vty, "onlink"); - vty_out(vty, "\n"); - } - - for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) - for (si = rn->info; si; si = si->next) { - vty_out(vty, "%s %s", spacing, - srcdest_rnode2str(rn, buf, sizeof(buf))); - - switch (si->type) { - case STATIC_IPV4_GATEWAY: - vty_out(vty, " %s", inet_ntoa(si->addr.ipv4)); - break; - case STATIC_IPV6_GATEWAY: - vty_out(vty, " %s", - inet_ntop(AF_INET6, &si->addr.ipv6, buf, - sizeof(buf))); - break; - case STATIC_IFNAME: - vty_out(vty, " %s", si->ifname); - break; - case STATIC_BLACKHOLE: - switch (si->bh_type) { - case STATIC_BLACKHOLE_DROP: - vty_out(vty, " blackhole"); + info = static_get_stable_info(rn); + frr_each(static_path_list, &si->path_list, pn) { + frr_each(static_nexthop_list, &pn->nexthop_list, nh) { + vty_out(vty, "%s %s", spacing, + srcdest_rnode2str(rn, buf, + sizeof(buf))); + + switch (nh->type) { + case STATIC_IPV4_GATEWAY: + vty_out(vty, " %s", + inet_ntoa(nh->addr.ipv4)); break; - case STATIC_BLACKHOLE_NULL: - vty_out(vty, " Null0"); + case STATIC_IPV6_GATEWAY: + vty_out(vty, " %s", + inet_ntop(AF_INET6, + &nh->addr.ipv6, buf, + sizeof(buf))); break; - case STATIC_BLACKHOLE_REJECT: - vty_out(vty, " reject"); + case STATIC_IFNAME: + vty_out(vty, " %s", nh->ifname); + break; + case STATIC_BLACKHOLE: + switch (nh->bh_type) { + case STATIC_BLACKHOLE_DROP: + vty_out(vty, " blackhole"); + break; + case STATIC_BLACKHOLE_NULL: + vty_out(vty, " Null0"); + break; + case STATIC_BLACKHOLE_REJECT: + vty_out(vty, " reject"); + break; + } + break; + case STATIC_IPV4_GATEWAY_IFNAME: + vty_out(vty, " %s %s", + inet_ntop(AF_INET, + &nh->addr.ipv4, buf, + sizeof(buf)), + nh->ifname); + break; + case STATIC_IPV6_GATEWAY_IFNAME: + vty_out(vty, " %s %s", + inet_ntop(AF_INET6, + &nh->addr.ipv6, buf, + sizeof(buf)), + nh->ifname); break; } - break; - case STATIC_IPV4_GATEWAY_IFNAME: - vty_out(vty, " %s %s", - inet_ntop(AF_INET, &si->addr.ipv4, buf, - sizeof(buf)), - si->ifname); - break; - case STATIC_IPV6_GATEWAY_IFNAME: - vty_out(vty, " %s %s", - inet_ntop(AF_INET6, &si->addr.ipv6, buf, - sizeof(buf)), - si->ifname); - break; - } - if (si->tag) - vty_out(vty, " tag %" ROUTE_TAG_PRI, si->tag); - - if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT) - vty_out(vty, " %d", si->distance); - - /* Label information */ - if (si->snh_label.num_labels) - vty_out(vty, " label %s", - mpls_label2str(si->snh_label.num_labels, - si->snh_label.label, buf, - sizeof(buf), 0)); - - if (si->nh_vrf_id != si->vrf_id) - vty_out(vty, " nexthop-vrf %s", si->nh_vrfname); - - /* - * table ID from VRF overrides configured - */ - if (si->table_id && - svrf->vrf->data.l.table_id == RT_TABLE_MAIN) - vty_out(vty, " table %u", si->table_id); - - if (si->onlink) - vty_out(vty, " onlink"); - - vty_out(vty, "\n"); - - write = 1; + if (pn->tag) + vty_out(vty, " tag %" ROUTE_TAG_PRI, + pn->tag); + + if (pn->distance + != ZEBRA_STATIC_DISTANCE_DEFAULT) + vty_out(vty, " %u", pn->distance); + + /* Label information */ + if (nh->snh_label.num_labels) + vty_out(vty, " label %s", + mpls_label2str( + nh->snh_label + .num_labels, + nh->snh_label.label, + buf, sizeof(buf), 0)); + + if (nh->nh_vrf_id != GET_STABLE_VRF_ID(info)) + vty_out(vty, " nexthop-vrf %s", + nh->nh_vrfname); + + /* + * table ID from VRF overrides + * configured + */ + if (pn->table_id + && svrf->vrf->data.l.table_id + == RT_TABLE_MAIN) + vty_out(vty, " table %u", pn->table_id); + + if (nh->onlink) + vty_out(vty, " onlink"); + + vty_out(vty, "\n"); + + write = 1; + } } + } return write; } @@ -815,23 +531,24 @@ DEFPY(ip_route_blackhole_vrf, "Table to configure\n" "The table number to configure\n") { - VTY_DECLVAR_CONTEXT(vrf, vrf); - struct static_vrf *svrf = vrf->info; + const struct lyd_node *vrf_dnode; + const char *vrfname; - if (table_str && !vrf_is_backend_netns()) { - vty_out(vty, - "%% table param only available when running on netns-based vrfs\n"); + vrf_dnode = + yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH); + if (!vrf_dnode) { + vty_out(vty, "%% Failed to get vrf dnode in candidate db\n"); return CMD_WARNING_CONFIG_FAILED; } - + vrfname = yang_dnode_get_string(vrf_dnode, "./name"); /* * Coverity is complaining that prefix could * be dereferenced, but we know that prefix will * valid. Add an assert to make it happy */ assert(prefix); - return static_route_leak(vty, svrf, svrf, AFI_IP, SAFI_UNICAST, no, - prefix, mask_str, NULL, NULL, NULL, flag, + return static_route_leak(vty, vrfname, vrfname, AFI_IP, SAFI_UNICAST, + no, prefix, mask_str, NULL, NULL, NULL, flag, tag_str, distance_str, label, table_str, false); } @@ -869,38 +586,22 @@ DEFPY(ip_route_address_interface, VRF_CMD_HELP_STR "Treat the nexthop as directly attached to the interface\n") { - struct static_vrf *svrf; - struct static_vrf *nh_svrf; + const char *nh_vrf; const char *flag = NULL; if (ifname && !strncasecmp(ifname, "Null0", 5)) { flag = "Null0"; ifname = NULL; } - - svrf = static_vty_get_unknown_vrf(vty, vrf); - if (!svrf) { - vty_out(vty, "%% vrf %s is not defined\n", vrf); - return CMD_WARNING_CONFIG_FAILED; - } - - if (table_str && vrf && !vrf_is_backend_netns()) { - vty_out(vty, - "%% table param only available when running on netns-based vrfs\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!vrf) + vrf = VRF_DEFAULT_NAME; if (nexthop_vrf) - nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf); + nh_vrf = nexthop_vrf; else - nh_svrf = svrf; + nh_vrf = vrf; - if (!nh_svrf) { - vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf); - return CMD_WARNING_CONFIG_FAILED; - } - - return static_route_leak(vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no, + return static_route_leak(vty, vrf, nh_vrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str, NULL, gate_str, ifname, flag, tag_str, distance_str, label, table_str, !!onlink); @@ -937,33 +638,29 @@ DEFPY(ip_route_address_interface_vrf, VRF_CMD_HELP_STR "Treat the nexthop as directly attached to the interface\n") { - VTY_DECLVAR_CONTEXT(vrf, vrf); + const char *nh_vrf; const char *flag = NULL; - struct static_vrf *svrf = vrf->info; - struct static_vrf *nh_svrf; + const struct lyd_node *vrf_dnode; + const char *vrfname; - if (table_str && !vrf_is_backend_netns()) { - vty_out(vty, - "%% table param only available when running on netns-based vrfs\n"); + vrf_dnode = + yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH); + if (!vrf_dnode) { + vty_out(vty, "%% Failed to get vrf dnode in candidate db\n"); return CMD_WARNING_CONFIG_FAILED; } + vrfname = yang_dnode_get_string(vrf_dnode, "./name"); if (ifname && !strncasecmp(ifname, "Null0", 5)) { flag = "Null0"; ifname = NULL; } - if (nexthop_vrf) - nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf); + nh_vrf = nexthop_vrf; else - nh_svrf = svrf; - - if (!nh_svrf) { - vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf); - return CMD_WARNING_CONFIG_FAILED; - } + nh_vrf = vrfname; - return static_route_leak(vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no, + return static_route_leak(vty, vrfname, nh_vrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str, NULL, gate_str, ifname, flag, tag_str, distance_str, label, table_str, !!onlink); @@ -999,41 +696,26 @@ DEFPY(ip_route, "The table number to configure\n" VRF_CMD_HELP_STR) { - struct static_vrf *svrf; - struct static_vrf *nh_svrf; + const char *nh_vrf; const char *flag = NULL; - if (table_str && vrf && !vrf_is_backend_netns()) { - vty_out(vty, - "%% table param only available when running on netns-based vrfs\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (ifname && !strncasecmp(ifname, "Null0", 5)) { flag = "Null0"; ifname = NULL; } - svrf = static_vty_get_unknown_vrf(vty, vrf); - if (!svrf) { - vty_out(vty, "%% vrf %s is not defined\n", vrf); - return CMD_WARNING_CONFIG_FAILED; - } + if (!vrf) + vrf = VRF_DEFAULT_NAME; if (nexthop_vrf) - nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf); + nh_vrf = nexthop_vrf; else - nh_svrf = svrf; + nh_vrf = vrf; - if (!nh_svrf) { - vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf); - return CMD_WARNING_CONFIG_FAILED; - } - - return static_route_leak( - vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str, - NULL, gate_str, ifname, flag, tag_str, distance_str, label, - table_str, false); + return static_route_leak(vty, vrf, nh_vrf, AFI_IP, SAFI_UNICAST, no, + prefix, mask_str, NULL, gate_str, ifname, flag, + tag_str, distance_str, label, table_str, + false); } DEFPY(ip_route_vrf, @@ -1064,36 +746,33 @@ DEFPY(ip_route_vrf, "The table number to configure\n" VRF_CMD_HELP_STR) { - VTY_DECLVAR_CONTEXT(vrf, vrf); - struct static_vrf *svrf = vrf->info; - struct static_vrf *nh_svrf; + const char *nh_vrf; const char *flag = NULL; + const struct lyd_node *vrf_dnode; + const char *vrfname; - if (table_str && !vrf_is_backend_netns()) { - vty_out(vty, - "%% table param only available when running on netns-based vrfs\n"); + vrf_dnode = + yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH); + if (!vrf_dnode) { + vty_out(vty, "%% Failed to get vrf dnode in candidate db\n"); return CMD_WARNING_CONFIG_FAILED; } + vrfname = yang_dnode_get_string(vrf_dnode, "./name"); + if (ifname && !strncasecmp(ifname, "Null0", 5)) { flag = "Null0"; ifname = NULL; } - if (nexthop_vrf) - nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf); + nh_vrf = nexthop_vrf; else - nh_svrf = svrf; - - if (!nh_svrf) { - vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf); - return CMD_WARNING_CONFIG_FAILED; - } + nh_vrf = vrfname; - return static_route_leak( - vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str, - NULL, gate_str, ifname, flag, tag_str, distance_str, label, - table_str, false); + return static_route_leak(vty, vrfname, nh_vrf, AFI_IP, SAFI_UNICAST, no, + prefix, mask_str, NULL, gate_str, ifname, flag, + tag_str, distance_str, label, table_str, + false); } DEFPY(ipv6_route_blackhole, @@ -1159,14 +838,16 @@ DEFPY(ipv6_route_blackhole_vrf, "Table to configure\n" "The table number to configure\n") { - VTY_DECLVAR_CONTEXT(vrf, vrf); - struct static_vrf *svrf = vrf->info; + const struct lyd_node *vrf_dnode; + const char *vrfname; - if (table_str && !vrf_is_backend_netns()) { - vty_out(vty, - "%% table param only available when running on netns-based vrfs\n"); + vrf_dnode = + yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH); + if (!vrf_dnode) { + vty_out(vty, "%% Failed to get vrf dnode in candidate db\n"); return CMD_WARNING_CONFIG_FAILED; } + vrfname = yang_dnode_get_string(vrf_dnode, "./name"); /* * Coverity is complaining that prefix could @@ -1174,10 +855,11 @@ DEFPY(ipv6_route_blackhole_vrf, * valid. Add an assert to make it happy */ assert(prefix); - return static_route_leak( - vty, svrf, svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL, - from_str, NULL, NULL, flag, tag_str, distance_str, label, - table_str, false); + + return static_route_leak(vty, vrfname, vrfname, AFI_IP6, SAFI_UNICAST, + no, prefix_str, NULL, from_str, NULL, NULL, + flag, tag_str, distance_str, label, table_str, + false); } DEFPY(ipv6_route_address_interface, @@ -1213,41 +895,26 @@ DEFPY(ipv6_route_address_interface, VRF_CMD_HELP_STR "Treat the nexthop as directly attached to the interface\n") { - struct static_vrf *svrf; - struct static_vrf *nh_svrf; + const char *nh_vrf; const char *flag = NULL; - if (table_str && vrf && !vrf_is_backend_netns()) { - vty_out(vty, - "%% table param only available when running on netns-based vrfs\n"); - return CMD_WARNING_CONFIG_FAILED; + if (ifname && !strncasecmp(ifname, "Null0", 5)) { + flag = "Null0"; + ifname = NULL; } - svrf = static_vty_get_unknown_vrf(vty, vrf); - if (!svrf) { - vty_out(vty, "%% vrf %s is not defined\n", vrf); - return CMD_WARNING_CONFIG_FAILED; - } + if (!vrf) + vrf = VRF_DEFAULT_NAME; if (nexthop_vrf) - nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf); + nh_vrf = nexthop_vrf; else - nh_svrf = svrf; - - if (!nh_svrf) { - vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf); - return CMD_WARNING_CONFIG_FAILED; - } + nh_vrf = vrf; - if (ifname && !strncasecmp(ifname, "Null0", 5)) { - flag = "Null0"; - ifname = NULL; - } - - return static_route_leak( - vty, svrf, nh_svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL, - from_str, gate_str, ifname, flag, tag_str, distance_str, label, - table_str, !!onlink); + return static_route_leak(vty, vrf, nh_vrf, AFI_IP6, SAFI_UNICAST, no, + prefix_str, NULL, from_str, gate_str, ifname, + flag, tag_str, distance_str, label, table_str, + !!onlink); } DEFPY(ipv6_route_address_interface_vrf, @@ -1281,36 +948,32 @@ DEFPY(ipv6_route_address_interface_vrf, VRF_CMD_HELP_STR "Treat the nexthop as directly attached to the interface\n") { - VTY_DECLVAR_CONTEXT(vrf, vrf); - struct static_vrf *svrf = vrf->info; - struct static_vrf *nh_svrf; + const char *nh_vrf; const char *flag = NULL; + const struct lyd_node *vrf_dnode; + const char *vrfname; - if (table_str && !vrf_is_backend_netns()) { - vty_out(vty, - "%% table param only available when running on netns-based vrfs\n"); + vrf_dnode = + yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH); + if (!vrf_dnode) { + vty_out(vty, "%% Failed to get vrf dnode in candidate db\n"); return CMD_WARNING_CONFIG_FAILED; } + vrfname = yang_dnode_get_string(vrf_dnode, "./name"); if (nexthop_vrf) - nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf); + nh_vrf = nexthop_vrf; else - nh_svrf = svrf; - - if (!nh_svrf) { - vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf); - return CMD_WARNING_CONFIG_FAILED; - } + nh_vrf = vrfname; if (ifname && !strncasecmp(ifname, "Null0", 5)) { flag = "Null0"; ifname = NULL; } - - return static_route_leak( - vty, svrf, nh_svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL, - from_str, gate_str, ifname, flag, tag_str, distance_str, label, - table_str, !!onlink); + return static_route_leak(vty, vrfname, nh_vrf, AFI_IP6, SAFI_UNICAST, + no, prefix_str, NULL, from_str, gate_str, + ifname, flag, tag_str, distance_str, label, + table_str, !!onlink); } DEFPY(ipv6_route, @@ -1343,41 +1006,25 @@ DEFPY(ipv6_route, "The table number to configure\n" VRF_CMD_HELP_STR) { - struct static_vrf *svrf; - struct static_vrf *nh_svrf; + const char *nh_vrf; const char *flag = NULL; - if (table_str && vrf && !vrf_is_backend_netns()) { - vty_out(vty, - "%% table param only available when running on netns-based vrfs\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - svrf = static_vty_get_unknown_vrf(vty, vrf); - if (!svrf) { - vty_out(vty, "%% vrf %s is not defined\n", vrf); - return CMD_WARNING_CONFIG_FAILED; - } + if (!vrf) + vrf = VRF_DEFAULT_NAME; if (nexthop_vrf) - nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf); + nh_vrf = nexthop_vrf; else - nh_svrf = svrf; - - if (!nh_svrf) { - vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf); - return CMD_WARNING_CONFIG_FAILED; - } + nh_vrf = vrf; if (ifname && !strncasecmp(ifname, "Null0", 5)) { flag = "Null0"; ifname = NULL; } - - return static_route_leak( - vty, svrf, nh_svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL, - from_str, gate_str, ifname, flag, tag_str, distance_str, label, - table_str, false); + return static_route_leak(vty, vrf, nh_vrf, AFI_IP6, SAFI_UNICAST, no, + prefix_str, NULL, from_str, gate_str, ifname, + flag, tag_str, distance_str, label, table_str, + false); } DEFPY(ipv6_route_vrf, @@ -1408,36 +1055,32 @@ DEFPY(ipv6_route_vrf, "The table number to configure\n" VRF_CMD_HELP_STR) { - VTY_DECLVAR_CONTEXT(vrf, vrf); - struct static_vrf *svrf = vrf->info; - struct static_vrf *nh_svrf; + const char *nh_vrf; const char *flag = NULL; + const struct lyd_node *vrf_dnode; + const char *vrfname; - if (table_str && !vrf_is_backend_netns()) { - vty_out(vty, - "%% table param only available when running on netns-based vrfs\n"); + vrf_dnode = + yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH); + if (!vrf_dnode) { + vty_out(vty, "%% Failed to get vrf dnode in candidate db\n"); return CMD_WARNING_CONFIG_FAILED; } + vrfname = yang_dnode_get_string(vrf_dnode, "./name"); if (nexthop_vrf) - nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf); + nh_vrf = nexthop_vrf; else - nh_svrf = svrf; - - if (!nh_svrf) { - vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf); - return CMD_WARNING_CONFIG_FAILED; - } + nh_vrf = vrfname; if (ifname && !strncasecmp(ifname, "Null0", 5)) { flag = "Null0"; ifname = NULL; } - - return static_route_leak( - vty, svrf, nh_svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL, - from_str, gate_str, ifname, flag, tag_str, distance_str, label, - table_str, false); + return static_route_leak(vty, vrfname, nh_vrf, AFI_IP6, SAFI_UNICAST, + no, prefix_str, NULL, from_str, gate_str, + ifname, flag, tag_str, distance_str, label, + table_str, false); } DEFPY(debug_staticd, debug_staticd_cmd, @@ -1500,8 +1143,4 @@ void static_vty_init(void) install_element(VIEW_NODE, &show_debugging_static_cmd); install_element(VIEW_NODE, &debug_staticd_cmd); install_element(CONFIG_NODE, &debug_staticd_cmd); - - static_list = list_new(); - static_list->cmp = (int (*)(void *, void *))static_list_compare; - static_list->del = (void (*)(void *))static_list_delete; } diff --git a/staticd/static_vty.h b/staticd/static_vty.h index 2f65c08b8b..7ffc8d9c98 100644 --- a/staticd/static_vty.h +++ b/staticd/static_vty.h @@ -19,8 +19,6 @@ #ifndef __STATIC_VTY_H__ #define __STATIC_VTY_H__ -void static_config_install_delayed_routes(struct static_vrf *svrf); - int static_config(struct vty *vty, struct static_vrf *svrf, afi_t afi, safi_t safi, const char *cmd); diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index c42f632ffb..d8a4b7f0cb 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -89,7 +89,6 @@ static int static_ifp_up(struct interface *ifp) struct static_vrf *svrf = static_vrf_lookup_by_id(ifp->vrf_id); static_fixup_vrf_ids(svrf); - static_config_install_delayed_routes(svrf); } /* Install any static reliant on this interface coming up */ @@ -265,8 +264,8 @@ static void static_nht_hash_free(void *data) XFREE(MTYPE_TMP, nhtd); } -void static_zebra_nht_register(struct route_node *rn, - struct static_route *si, bool reg) +void static_zebra_nht_register(struct route_node *rn, struct static_nexthop *nh, + bool reg) { struct static_nht_data *nhtd, lookup; uint32_t cmd; @@ -276,14 +275,14 @@ void static_zebra_nht_register(struct route_node *rn, cmd = (reg) ? ZEBRA_NEXTHOP_REGISTER : ZEBRA_NEXTHOP_UNREGISTER; - if (si->nh_registered && reg) + if (nh->nh_registered && reg) return; - if (!si->nh_registered && !reg) + if (!nh->nh_registered && !reg) return; memset(&p, 0, sizeof(p)); - switch (si->type) { + switch (nh->type) { case STATIC_IFNAME: case STATIC_BLACKHOLE: return; @@ -291,23 +290,23 @@ void static_zebra_nht_register(struct route_node *rn, case STATIC_IPV4_GATEWAY_IFNAME: p.family = AF_INET; p.prefixlen = IPV4_MAX_BITLEN; - p.u.prefix4 = si->addr.ipv4; + p.u.prefix4 = nh->addr.ipv4; afi = AFI_IP; break; case STATIC_IPV6_GATEWAY: case STATIC_IPV6_GATEWAY_IFNAME: p.family = AF_INET6; p.prefixlen = IPV6_MAX_BITLEN; - p.u.prefix6 = si->addr.ipv6; + p.u.prefix6 = nh->addr.ipv6; afi = AFI_IP6; break; } memset(&lookup, 0, sizeof(lookup)); lookup.nh = &p; - lookup.nh_vrf_id = si->nh_vrf_id; + lookup.nh_vrf_id = nh->nh_vrf_id; - si->nh_registered = reg; + nh->nh_registered = reg; if (reg) { nhtd = hash_get(static_nht_hash, &lookup, @@ -318,8 +317,8 @@ void static_zebra_nht_register(struct route_node *rn, zlog_debug("Registered nexthop(%pFX) for %pRN %d", &p, rn, nhtd->nh_num); if (nhtd->refcount > 1 && nhtd->nh_num) { - static_nht_update(&rn->p, nhtd->nh, nhtd->nh_num, - afi, si->nh_vrf_id); + static_nht_update(&rn->p, nhtd->nh, nhtd->nh_num, afi, + nh->nh_vrf_id); return; } } else { @@ -335,25 +334,72 @@ void static_zebra_nht_register(struct route_node *rn, static_nht_hash_free(nhtd); } - if (zclient_send_rnh(zclient, cmd, &p, false, si->nh_vrf_id) < 0) + if (zclient_send_rnh(zclient, cmd, &p, false, nh->nh_vrf_id) < 0) zlog_warn("%s: Failure to send nexthop to zebra", __func__); } +/* + * When nexthop gets updated via configuration then use the + * already registered NH and resend the route to zebra + */ +int static_zebra_nh_update(struct route_node *rn, struct static_nexthop *nh) +{ + struct static_nht_data *nhtd, lookup = {}; + struct prefix p = {}; + afi_t afi = AFI_IP; + + if (!nh->nh_registered) + return 0; + + switch (nh->type) { + case STATIC_IFNAME: + case STATIC_BLACKHOLE: + return 0; + case STATIC_IPV4_GATEWAY: + case STATIC_IPV4_GATEWAY_IFNAME: + p.family = AF_INET; + p.prefixlen = IPV4_MAX_BITLEN; + p.u.prefix4 = nh->addr.ipv4; + afi = AFI_IP; + break; + case STATIC_IPV6_GATEWAY: + case STATIC_IPV6_GATEWAY_IFNAME: + p.family = AF_INET6; + p.prefixlen = IPV6_MAX_BITLEN; + p.u.prefix6 = nh->addr.ipv6; + afi = AFI_IP6; + break; + } + + lookup.nh = &p; + lookup.nh_vrf_id = nh->nh_vrf_id; + + nhtd = hash_lookup(static_nht_hash, &lookup); + if (nhtd && nhtd->nh_num) { + nh->state = STATIC_START; + static_nht_update(&rn->p, nhtd->nh, nhtd->nh_num, afi, + nh->nh_vrf_id); + return 1; + } + return 0; +} extern void static_zebra_route_add(struct route_node *rn, - struct static_route *si_changed, - vrf_id_t vrf_id, safi_t safi, bool install) + struct static_path *pn, safi_t safi, + bool install) { - struct static_route *si = rn->info; + struct static_nexthop *nh; const struct prefix *p, *src_pp; struct zapi_nexthop *api_nh; struct zapi_route api; uint32_t nh_num = 0; + struct stable_info *info; p = src_pp = NULL; srcdest_rnode_prefixes(rn, &p, &src_pp); memset(&api, 0, sizeof(api)); - api.vrf_id = vrf_id; + info = static_get_stable_info(rn); + api.vrf_id = GET_STABLE_VRF_ID(info); api.type = ZEBRA_ROUTE_STATIC; api.safi = safi; memcpy(&api.prefix, p, sizeof(api.prefix)); @@ -365,71 +411,65 @@ extern void static_zebra_route_add(struct route_node *rn, SET_FLAG(api.flags, ZEBRA_FLAG_RR_USE_DISTANCE); SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION); SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - if (si_changed->distance) { + if (pn->distance) { SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = si_changed->distance; + api.distance = pn->distance; } - if (si_changed->tag) { + if (pn->tag) { SET_FLAG(api.message, ZAPI_MESSAGE_TAG); - api.tag = si_changed->tag; + api.tag = pn->tag; } - if (si_changed->table_id != 0) { + if (pn->table_id != 0) { SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID); - api.tableid = si_changed->table_id; + api.tableid = pn->table_id; } - for (/*loaded above*/; si; si = si->next) { + frr_each(static_nexthop_list, &pn->nexthop_list, nh) { api_nh = &api.nexthops[nh_num]; - if (si->nh_vrf_id == VRF_UNKNOWN) - continue; - - if (si->distance != si_changed->distance) - continue; - - if (si->table_id != si_changed->table_id) + if (nh->nh_vrf_id == VRF_UNKNOWN) continue; - api_nh->vrf_id = si->nh_vrf_id; - if (si->onlink) + api_nh->vrf_id = nh->nh_vrf_id; + if (nh->onlink) SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK); - si->state = STATIC_SENT_TO_ZEBRA; + nh->state = STATIC_SENT_TO_ZEBRA; - switch (si->type) { + switch (nh->type) { case STATIC_IFNAME: - if (si->ifindex == IFINDEX_INTERNAL) + if (nh->ifindex == IFINDEX_INTERNAL) continue; - api_nh->ifindex = si->ifindex; + api_nh->ifindex = nh->ifindex; api_nh->type = NEXTHOP_TYPE_IFINDEX; break; case STATIC_IPV4_GATEWAY: - if (!si->nh_valid) + if (!nh->nh_valid) continue; api_nh->type = NEXTHOP_TYPE_IPV4; - api_nh->gate = si->addr; + api_nh->gate = nh->addr; break; case STATIC_IPV4_GATEWAY_IFNAME: - if (si->ifindex == IFINDEX_INTERNAL) + if (nh->ifindex == IFINDEX_INTERNAL) continue; - api_nh->ifindex = si->ifindex; + api_nh->ifindex = nh->ifindex; api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; - api_nh->gate = si->addr; + api_nh->gate = nh->addr; break; case STATIC_IPV6_GATEWAY: - if (!si->nh_valid) + if (!nh->nh_valid) continue; api_nh->type = NEXTHOP_TYPE_IPV6; - api_nh->gate = si->addr; + api_nh->gate = nh->addr; break; case STATIC_IPV6_GATEWAY_IFNAME: - if (si->ifindex == IFINDEX_INTERNAL) + if (nh->ifindex == IFINDEX_INTERNAL) continue; api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; - api_nh->ifindex = si->ifindex; - api_nh->gate = si->addr; + api_nh->ifindex = nh->ifindex; + api_nh->gate = nh->addr; break; case STATIC_BLACKHOLE: api_nh->type = NEXTHOP_TYPE_BLACKHOLE; - switch (si->bh_type) { + switch (nh->bh_type) { case STATIC_BLACKHOLE_DROP: case STATIC_BLACKHOLE_NULL: api_nh->bh_type = BLACKHOLE_NULL; @@ -440,13 +480,13 @@ extern void static_zebra_route_add(struct route_node *rn, break; } - if (si->snh_label.num_labels) { + if (nh->snh_label.num_labels) { int i; SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL); - api_nh->label_num = si->snh_label.num_labels; + api_nh->label_num = nh->snh_label.num_labels; for (i = 0; i < api_nh->label_num; i++) - api_nh->labels[i] = si->snh_label.label[i]; + api_nh->labels[i] = nh->snh_label.label[i]; } nh_num++; } diff --git a/staticd/static_zebra.h b/staticd/static_zebra.h index 962dc3908f..9f93f3ee63 100644 --- a/staticd/static_zebra.h +++ b/staticd/static_zebra.h @@ -22,13 +22,15 @@ extern struct thread_master *master; extern void static_zebra_nht_register(struct route_node *rn, - struct static_route *si, bool reg); + struct static_nexthop *nh, bool reg); extern void static_zebra_route_add(struct route_node *rn, - struct static_route *si_changed, - vrf_id_t vrf_id, safi_t safi, bool install); + struct static_path *pn, safi_t safi, + bool install); extern void static_zebra_init(void); extern void static_zebra_vrf_register(struct vrf *vrf); extern void static_zebra_vrf_unregister(struct vrf *vrf); +extern int static_zebra_nh_update(struct route_node *rn, + struct static_nexthop *nh); #endif diff --git a/staticd/subdir.am b/staticd/subdir.am index f2b3d11f29..eba7f270bb 100644 --- a/staticd/subdir.am +++ b/staticd/subdir.am @@ -18,6 +18,8 @@ staticd_libstatic_a_SOURCES = \ staticd/static_zebra.c \ staticd/static_vrf.c \ staticd/static_vty.c \ + staticd/static_nb.c \ + staticd/static_nb_config.c \ # end noinst_HEADERS += \ @@ -28,6 +30,7 @@ noinst_HEADERS += \ staticd/static_routes.h \ staticd/static_vty.h \ staticd/static_vrf.h \ + staticd/static_nb.h \ # end clippy_scan += \ @@ -36,3 +39,7 @@ clippy_scan += \ staticd_staticd_SOURCES = staticd/static_main.c staticd_staticd_LDADD = staticd/libstatic.a lib/libfrr.la $(LIBCAP) + +nodist_staticd_staticd_SOURCES = \ + yang/frr-staticd.yang.c \ + # end diff --git a/tests/bgpd/test_aspath.c b/tests/bgpd/test_aspath.c index b94355e8b8..439891b559 100644 --- a/tests/bgpd/test_aspath.c +++ b/tests/bgpd/test_aspath.c @@ -271,57 +271,9 @@ static struct test_segment { 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, }, 502, - {"8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285", - - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285", + {"8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285", + + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285", 250, 0, NOT_ALL_PRIVATE, 4096, 4, 8466}, }, { @@ -383,15 +335,13 @@ static struct test_segment { { /* 20 */ "reconcile_confed", - "confseq(123,456,789) confset(456,124,788) seq(6435,59408,21665)" - " set(23456,23456,23456), seq(23456,23456,23456)", + "confseq(123,456,789) confset(456,124,788) seq(6435,59408,21665) set(23456,23456,23456), seq(23456,23456,23456)", {0x3, 0x3, 0x00, 0x7b, 0x01, 0xc8, 0x03, 0x15, 0x4, 0x3, 0x01, 0xc8, 0x00, 0x7c, 0x03, 0x14, 0x2, 0x3, 0x19, 0x23, 0xe8, 0x10, 0x54, 0xa1, 0x1, 0x3, 0x5b, 0xa0, 0x5b, 0xa0, 0x5b, 0xa0, 0x2, 0x3, 0x5b, 0xa0, 0x5b, 0xa0, 0x5b, 0xa0}, 40, - {"(123 456 789) [124,456,788] 6435 59408 21665" - " {23456} 23456 23456 23456", + {"(123 456 789) [124,456,788] 6435 59408 21665 {23456} 23456 23456 23456", "6435 59408 21665 {23456} 23456 23456 23456", 7, 4, NOT_ALL_PRIVATE, 23456, 1, 6435}, }, @@ -739,10 +689,8 @@ static struct tests { /* 3 */ {&test_segments[4], &test_segments[5], - {"8467 59649 {4196,48658} {17322,30745} 6435 59408 21665" - " {2457,4369,61697} 1842 41590 51793", - "8467 59649 {4196,48658} {17322,30745} 6435 59408 21665" - " {2457,4369,61697} 1842 41590 51793", + {"8467 59649 {4196,48658} {17322,30745} 6435 59408 21665 {2457,4369,61697} 1842 41590 51793", + "8467 59649 {4196,48658} {17322,30745} 6435 59408 21665 {2457,4369,61697} 1842 41590 51793", 11, 0, NOT_ALL_PRIVATE, 61697, 1, 8467}}, /* 4 */ { @@ -777,59 +725,9 @@ static struct tests { { &test_segments[14], &test_segments[11], - {"8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 2 52737 4096 8722 4 8722", - - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 2 52737 4096 8722 4 8722", + {"8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 2 52737 4096 8722 4 8722", + + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 2 52737 4096 8722 4 8722", 257, 0, NOT_ALL_PRIVATE, 4096, 1000, 8466}, }, {NULL, @@ -861,8 +759,7 @@ struct tests reconcile_tests[] = { { &test_segments[20], &test_segments[19], - {"(123 456 789) [124,456,788] 6435 59408 21665" - " {2457,4369,61697} 1842 41591 51793", + {"(123 456 789) [124,456,788] 6435 59408 21665 {2457,4369,61697} 1842 41591 51793", "6435 59408 21665 {2457,4369,61697} 1842 41591 51793", 7, 4, NOT_ALL_PRIVATE, 51793, 1, 6435}, }, diff --git a/tests/lib/test_checksum.c b/tests/lib/test_checksum.c index ddb76c8f9d..301078867a 100644 --- a/tests/lib/test_checksum.c +++ b/tests/lib/test_checksum.c @@ -489,8 +489,7 @@ int main(int argc, char **argv) in_csum_res = in_cksum_optimized(buffer, exercise); in_csum_rfc = in_cksum_rfc(buffer, exercise); if (in_csum_res != in_csum || in_csum != in_csum_rfc) - printf("verify: in_chksum failed in_csum:%x, in_csum_res:%x," - "in_csum_rfc %x, len:%d\n", + printf("verify: in_chksum failed in_csum:%x, in_csum_res:%x,in_csum_rfc %x, len:%d\n", in_csum, in_csum_res, in_csum_rfc, exercise); ospfd = ospfd_checksum(buffer, exercise + sizeof(uint16_t), diff --git a/tests/lib/test_ttable.c b/tests/lib/test_ttable.c index 674179b6ab..43b8adcb97 100644 --- a/tests/lib/test_ttable.c +++ b/tests/lib/test_ttable.c @@ -93,8 +93,7 @@ int main(int argc, char **argv) /* add bigger row */ ttable_add_row(tt, "%s|%s||%s|%s", - "nebula dusk session streets twilight " - "pioneer beats yeah", + "nebula dusk session streets twilight pioneer beats yeah", "prarie dog", "cornmeal", ":O -*_-*"); assert(tt->ncols == 5); assert(tt->nrows == 2); diff --git a/tests/topotests/Dockerfile b/tests/topotests/Dockerfile index cdd0ae2f6e..b7c6298228 100644 --- a/tests/topotests/Dockerfile +++ b/tests/topotests/Dockerfile @@ -19,6 +19,7 @@ RUN export DEBIAN_FRONTEND=noninteractive \ libjson-c-dev \ libpcre3-dev \ libpython-dev \ + libpython3-dev \ libreadline-dev \ libc-ares-dev \ libcap-dev \ @@ -26,7 +27,10 @@ RUN export DEBIAN_FRONTEND=noninteractive \ mininet \ pkg-config \ python-pip \ - python-sphinx \ + python3 \ + python3-dev \ + python3-sphinx \ + python3-pytest \ rsync \ strace \ tcpdump \ diff --git a/tests/topotests/bfd-profiles-topo1/r3/bfd-peers-initial.json b/tests/topotests/bfd-profiles-topo1/r3/bfd-peers-initial.json index abca1ed131..d2d0c601c3 100644 --- a/tests/topotests/bfd-profiles-topo1/r3/bfd-peers-initial.json +++ b/tests/topotests/bfd-profiles-topo1/r3/bfd-peers-initial.json @@ -25,14 +25,14 @@ "local": "*", "multihop": false, "peer": "*", - "receive-interval": 300, + "receive-interval": 250, "remote-detect-multiplier": 3, "remote-diagnostic": "ok", "remote-id": "*", "remote-receive-interval": 300, "remote-transmit-interval": 300, "status": "up", - "transmit-interval": 300, + "transmit-interval": 250, "uptime": "*", "vrf": "default" } diff --git a/tests/topotests/bfd-profiles-topo1/r3/bfdd.conf b/tests/topotests/bfd-profiles-topo1/r3/bfdd.conf index 74dae5a60d..08eb0468d6 100644 --- a/tests/topotests/bfd-profiles-topo1/r3/bfdd.conf +++ b/tests/topotests/bfd-profiles-topo1/r3/bfdd.conf @@ -3,9 +3,8 @@ debug bfd network debug bfd zebra ! bfd - ! profile is commented out on purpose. - !profile fasttx - ! receive-interval 250 - ! transmit-interval 250 - !! + profile fasttx + receive-interval 250 + transmit-interval 250 + ! ! diff --git a/tests/topotests/bfd-profiles-topo1/r3/bgpd.conf b/tests/topotests/bfd-profiles-topo1/r3/bgpd.conf index 9c56a349ed..c7b75d2fde 100644 --- a/tests/topotests/bfd-profiles-topo1/r3/bgpd.conf +++ b/tests/topotests/bfd-profiles-topo1/r3/bgpd.conf @@ -1,7 +1,7 @@ router bgp 100 bgp router-id 10.254.254.3 neighbor 172.16.1.2 remote-as 100 - neighbor 172.16.1.2 bfd profile fasttx + neighbor 172.16.1.2 bfd profile DOES_NOT_EXIST address-family ipv4 unicast redistribute connected exit-address-family diff --git a/tests/topotests/bfd-profiles-topo1/r3/isisd.conf b/tests/topotests/bfd-profiles-topo1/r3/isisd.conf index 5d774a356b..d27a783adf 100644 --- a/tests/topotests/bfd-profiles-topo1/r3/isisd.conf +++ b/tests/topotests/bfd-profiles-topo1/r3/isisd.conf @@ -8,6 +8,7 @@ interface r3-eth1 ipv6 router isis lan isis circuit-type level-1 isis bfd + isis bfd profile fasttx ! router isis lan net 10.0000.0000.0000.0000.0000.0000.0000.0000.0001.00 diff --git a/tests/topotests/bfd-profiles-topo1/r4/bfd-peers-initial.json b/tests/topotests/bfd-profiles-topo1/r4/bfd-peers-initial.json index c8bc4c20e9..2c2e136abf 100644 --- a/tests/topotests/bfd-profiles-topo1/r4/bfd-peers-initial.json +++ b/tests/topotests/bfd-profiles-topo1/r4/bfd-peers-initial.json @@ -11,8 +11,8 @@ "remote-detect-multiplier": 3, "remote-diagnostic": "ok", "remote-id": "*", - "remote-receive-interval": 300, - "remote-transmit-interval": 300, + "remote-receive-interval": 250, + "remote-transmit-interval": 250, "status": "up", "transmit-interval": 300, "uptime": "*", diff --git a/tests/topotests/bfd-profiles-topo1/r4/bgpd.conf b/tests/topotests/bfd-profiles-topo1/r4/bgpd.conf index 7c4b39b020..aff1016dee 100644 --- a/tests/topotests/bfd-profiles-topo1/r4/bgpd.conf +++ b/tests/topotests/bfd-profiles-topo1/r4/bgpd.conf @@ -5,7 +5,7 @@ router bgp 200 no bgp ebgp-requires-policy neighbor 2001:db8:1::2 remote-as 100 neighbor 2001:db8:1::2 ebgp-multihop 2 - neighbor 2001:db8:1::2 bfd profile fasttx + neighbor 2001:db8:1::2 bfd profile DOES_NOT_EXIST address-family ipv4 unicast redistribute connected exit-address-family diff --git a/tests/topotests/bfd-profiles-topo1/r4/isisd.conf b/tests/topotests/bfd-profiles-topo1/r4/isisd.conf index 477740087d..01e197bed5 100644 --- a/tests/topotests/bfd-profiles-topo1/r4/isisd.conf +++ b/tests/topotests/bfd-profiles-topo1/r4/isisd.conf @@ -8,6 +8,7 @@ interface r4-eth0 ipv6 router isis lan isis circuit-type level-1 isis bfd + isis bfd profile DOES_NOT_EXIST ! router isis lan net 10.0000.0000.0000.0000.0000.0000.0000.0000.0002.00 diff --git a/tests/topotests/bfd-profiles-topo1/test_bfd_profiles_topo1.py b/tests/topotests/bfd-profiles-topo1/test_bfd_profiles_topo1.py index 02385b32e5..02385b32e5 100644..100755 --- a/tests/topotests/bfd-profiles-topo1/test_bfd_profiles_topo1.py +++ b/tests/topotests/bfd-profiles-topo1/test_bfd_profiles_topo1.py diff --git a/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py b/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py index 087ba21e5e..948f641afb 100755 --- a/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py +++ b/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py @@ -63,7 +63,7 @@ from lib.common_config import ( reset_config_on_routers, ) from lib.topolog import logger -from lib.bgp import verify_bgp_convergence, create_router_bgp, clear_bgp_and_verify +from lib.bgp import verify_bgp_convergence, create_router_bgp, clear_bgp from lib.topojson import build_topo_from_json, build_config_from_json # Reading the data from JSON File for topology and configuration creation @@ -295,7 +295,7 @@ def test_modify_ecmp_max_paths(request, ecmp_num, test_type): addr_type, dut, input_dict_1, - next_hop=NEXT_HOPS[addr_type][:int(ecmp_num)], + next_hop=NEXT_HOPS[addr_type][: int(ecmp_num)], protocol=protocol, ) assert result is True, "Testcase {} : Failed \n Error: {}".format( @@ -336,8 +336,12 @@ def test_ecmp_after_clear_bgp(request, test_type): tc_name, result ) - # Clear bgp - result = clear_bgp_and_verify(tgen, topo, dut) + # Clear BGP + for addr_type in ADDR_TYPES: + clear_bgp(tgen, addr_type, dut) + + # Verify BGP convergence + result = verify_bgp_convergence(tgen, topo) assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) for addr_type in ADDR_TYPES: diff --git a/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py b/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py index 94409ff3e1..5b997fdd16 100755 --- a/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py +++ b/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py @@ -63,7 +63,7 @@ from lib.common_config import ( reset_config_on_routers, ) from lib.topolog import logger -from lib.bgp import verify_bgp_convergence, create_router_bgp, clear_bgp_and_verify +from lib.bgp import verify_bgp_convergence, create_router_bgp, clear_bgp from lib.topojson import build_topo_from_json, build_config_from_json # Reading the data from JSON File for topology and configuration creation @@ -296,7 +296,7 @@ def test_modify_ecmp_max_paths(request, ecmp_num, test_type): addr_type, dut, input_dict_1, - next_hop=NEXT_HOPS[addr_type][:int(ecmp_num)], + next_hop=NEXT_HOPS[addr_type][: int(ecmp_num)], protocol=protocol, ) assert result is True, "Testcase {} : Failed \n Error: {}".format( @@ -337,8 +337,12 @@ def test_ecmp_after_clear_bgp(request, test_type): tc_name, result ) - # Clear bgp - result = clear_bgp_and_verify(tgen, topo, dut) + # Clear BGP + for addr_type in ADDR_TYPES: + clear_bgp(tgen, addr_type, dut) + + # Verify BGP convergence + result = verify_bgp_convergence(tgen, topo) assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) for addr_type in ADDR_TYPES: diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/ce1/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_direct/ce1/bgpd.conf index c1bb7e3d15..2712e54f12 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_direct/ce1/bgpd.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/ce1/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname ce1 password zebra log stdout notifications -log monitor notifications log commands router bgp 5226 no bgp network import-check diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/ce2/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_direct/ce2/bgpd.conf index c889a4c596..69305512cb 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_direct/ce2/bgpd.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/ce2/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname ce2 password zebra log stdout notifications -log monitor notifications log commands router bgp 5226 no bgp network import-check diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/ce3/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_direct/ce3/bgpd.conf index 36dd97190e..3ad95c3612 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_direct/ce3/bgpd.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/ce3/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname ce3 password zebra log stdout notifications -log monitor notifications log commands router bgp 5226 no bgp network import-check diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/r1/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_direct/r1/bgpd.conf index 33041262f6..502c4c8b2f 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_direct/r1/bgpd.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/r1/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname r1 password zebra log stdout notifications -log monitor notifications log commands router bgp 5226 bgp router-id 1.1.1.1 diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/r2/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_direct/r2/bgpd.conf index 524051426b..95890f25b9 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_direct/r2/bgpd.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/r2/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname r2 password zebra log stdout notifications -log monitor notifications log commands router bgp 5226 bgp router-id 2.2.2.2 diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/r3/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_direct/r3/bgpd.conf index 29b9f0da6c..2f7de073c3 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_direct/r3/bgpd.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/r3/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname r3 password zebra log stdout notifications -log monitor notifications log commands router bgp 5226 bgp router-id 3.3.3.3 diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/r4/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_direct/r4/bgpd.conf index e09b505ee4..720d06dbf1 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_direct/r4/bgpd.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/r4/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname r4 password zebra log stdout notifications -log monitor notifications log commands router bgp 5226 bgp router-id 4.4.4.4 diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce1/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce1/bgpd.conf index c3309d8c75..b81cd33c4f 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce1/bgpd.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce1/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname ce1 password zebra log stdout notifications -log monitor notifications log commands log file bgpd.log diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce2/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce2/bgpd.conf index 54401bfb2f..f18e5b852e 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce2/bgpd.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce2/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname ce2 password zebra log stdout notifications -log monitor notifications log commands log file bgpd.log diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce3/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce3/bgpd.conf index f742fede1a..54a0933588 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce3/bgpd.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce3/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname ce3 password zebra log stdout notifications -log monitor notifications log commands log file bgpd.log diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce4/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce4/bgpd.conf index 91311f32c5..5289628480 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce4/bgpd.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce4/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname ce4 password zebra log stdout notifications -log monitor notifications log commands log file bgpd.log diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/bgpd.conf index a9549e8fee..5da53ae1e7 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/bgpd.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname r1 password zebra log stdout notifications -log monitor notifications log commands log file bgpd.log debugging diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r2/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r2/bgpd.conf index cda6d9429a..e4a6b8e32c 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r2/bgpd.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r2/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname r2 password zebra log stdout notifications -log monitor notifications log commands log file bgpd.log debugging diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r3/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r3/bgpd.conf index e2a8de7db7..a861469c7a 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r3/bgpd.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r3/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname r3 password zebra log stdout notifications -log monitor notifications log commands log file bgpd.log diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r4/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r4/bgpd.conf index 7b267a6ee1..480f95954e 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r4/bgpd.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r4/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname r4 password zebra log stdout notifications -log monitor notifications log commands log file bgpd.log debug diff --git a/tests/topotests/bgp_prefix_sid/r1/bgpd.conf b/tests/topotests/bgp_prefix_sid/r1/bgpd.conf index 2f8759f960..06bdc31f8c 100644 --- a/tests/topotests/bgp_prefix_sid/r1/bgpd.conf +++ b/tests/topotests/bgp_prefix_sid/r1/bgpd.conf @@ -1,5 +1,4 @@ log stdout notifications -log monitor notifications log commands ! router bgp 1 diff --git a/tests/topotests/bgp_rfapi_basic_sanity/r1/bgpd.conf b/tests/topotests/bgp_rfapi_basic_sanity/r1/bgpd.conf index b3fe5ff23d..ada354bd62 100644 --- a/tests/topotests/bgp_rfapi_basic_sanity/r1/bgpd.conf +++ b/tests/topotests/bgp_rfapi_basic_sanity/r1/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname r1 password zebra log stdout notifications -log monitor notifications log commands router bgp 5226 bgp router-id 1.1.1.1 diff --git a/tests/topotests/bgp_rfapi_basic_sanity/r2/bgpd.conf b/tests/topotests/bgp_rfapi_basic_sanity/r2/bgpd.conf index 524051426b..95890f25b9 100644 --- a/tests/topotests/bgp_rfapi_basic_sanity/r2/bgpd.conf +++ b/tests/topotests/bgp_rfapi_basic_sanity/r2/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname r2 password zebra log stdout notifications -log monitor notifications log commands router bgp 5226 bgp router-id 2.2.2.2 diff --git a/tests/topotests/bgp_rfapi_basic_sanity/r3/bgpd.conf b/tests/topotests/bgp_rfapi_basic_sanity/r3/bgpd.conf index fbb6a65d61..4932d63d4f 100644 --- a/tests/topotests/bgp_rfapi_basic_sanity/r3/bgpd.conf +++ b/tests/topotests/bgp_rfapi_basic_sanity/r3/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname r3 password zebra log stdout notifications -log monitor notifications log commands router bgp 5226 bgp router-id 3.3.3.3 diff --git a/tests/topotests/bgp_rfapi_basic_sanity/r4/bgpd.conf b/tests/topotests/bgp_rfapi_basic_sanity/r4/bgpd.conf index d61f776f3d..1a5e41aae6 100644 --- a/tests/topotests/bgp_rfapi_basic_sanity/r4/bgpd.conf +++ b/tests/topotests/bgp_rfapi_basic_sanity/r4/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname r4 password zebra log stdout notifications -log monitor notifications log commands router bgp 5226 bgp router-id 4.4.4.4 diff --git a/tests/topotests/bgp_rfapi_basic_sanity_config2/r1/bgpd.conf b/tests/topotests/bgp_rfapi_basic_sanity_config2/r1/bgpd.conf index 626d8227e7..a38afd632f 100644 --- a/tests/topotests/bgp_rfapi_basic_sanity_config2/r1/bgpd.conf +++ b/tests/topotests/bgp_rfapi_basic_sanity_config2/r1/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname r1 password zebra log stdout notifications -log monitor notifications log commands router bgp 5226 bgp router-id 1.1.1.1 diff --git a/tests/topotests/bgp_rfapi_basic_sanity_config2/r2/bgpd.conf b/tests/topotests/bgp_rfapi_basic_sanity_config2/r2/bgpd.conf index 524051426b..95890f25b9 100644 --- a/tests/topotests/bgp_rfapi_basic_sanity_config2/r2/bgpd.conf +++ b/tests/topotests/bgp_rfapi_basic_sanity_config2/r2/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname r2 password zebra log stdout notifications -log monitor notifications log commands router bgp 5226 bgp router-id 2.2.2.2 diff --git a/tests/topotests/bgp_rfapi_basic_sanity_config2/r3/bgpd.conf b/tests/topotests/bgp_rfapi_basic_sanity_config2/r3/bgpd.conf index 8c75a39efa..dbeb2c4665 100644 --- a/tests/topotests/bgp_rfapi_basic_sanity_config2/r3/bgpd.conf +++ b/tests/topotests/bgp_rfapi_basic_sanity_config2/r3/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname r3 password zebra log stdout notifications -log monitor notifications log commands router bgp 5226 bgp router-id 3.3.3.3 diff --git a/tests/topotests/bgp_rfapi_basic_sanity_config2/r4/bgpd.conf b/tests/topotests/bgp_rfapi_basic_sanity_config2/r4/bgpd.conf index 38f8758cbc..ae1787718c 100644 --- a/tests/topotests/bgp_rfapi_basic_sanity_config2/r4/bgpd.conf +++ b/tests/topotests/bgp_rfapi_basic_sanity_config2/r4/bgpd.conf @@ -3,7 +3,6 @@ frr defaults traditional hostname r4 password zebra log stdout notifications -log monitor notifications log commands router bgp 5226 bgp router-id 4.4.4.4 diff --git a/tests/topotests/evpn_type5_test_topo1/__init__.py b/tests/topotests/evpn_type5_test_topo1/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/evpn_type5_test_topo1/__init__.py diff --git a/tests/topotests/evpn_type5_test_topo1/evpn_type5_chaos_topo1.json b/tests/topotests/evpn_type5_test_topo1/evpn_type5_chaos_topo1.json new file mode 100644 index 0000000000..14842da326 --- /dev/null +++ b/tests/topotests/evpn_type5_test_topo1/evpn_type5_chaos_topo1.json @@ -0,0 +1,887 @@ +{ + "address_types": ["ipv4","ipv6"], + "ipv4base": "10.0.0.0", + "ipv4mask": 30, + "ipv6base": "fd00::", + "ipv6mask": 64, + "link_ip_start": { + "ipv4": "10.0.0.0", + "v4mask": 30, + "ipv6": "fd00::", + "v6mask": 64 + }, + "lo_prefix": { + "ipv4": "1.0.", + "v4mask": 32, + "ipv6": "2001:db8:f::", + "v6mask": 128 + }, + "routers": { + "r1": { + "links": { + "e1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"} + }, + "vrfs":[ + { + "name": "RED", + "id": "1" + } + ], + "bgp": + [ + { + "local_as": "1", + "vrf": "RED", + "address_family": { + "ipv4": { + "unicast": { + "redistribute": [ + {"redist_type": "static"} + ], + "neighbor": { + "e1": { + "dest_link": { + "r1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "redistribute": [ + {"redist_type": "static"} + ], + "neighbor": { + "e1": { + "dest_link": { + "r1": {} + } + } + } + } + } + } + } + ], + "static_routes":[ + { + "network":"10.1.1.1/32", + "next_hop":"Null0", + "vrf": "RED" + }, + { + "network":"10::1/128", + "next_hop":"Null0", + "vrf": "RED" + } + ] + }, + "r2": { + "links": { + "e1-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"}, + "e1-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"} + }, + "vrfs":[ + { + "name": "BLUE", + "id": "1" + }, + { + "name": "GREEN", + "id": "2" + } + ], + "bgp": + [ + { + "local_as": "2", + "vrf": "BLUE", + "address_family": { + "ipv4": { + "unicast": { + "redistribute": [ + {"redist_type": "static"} + ], + "neighbor": { + "e1": { + "dest_link": { + "r2-link1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "redistribute": [ + {"redist_type": "static"} + ], + "neighbor": { + "e1": { + "dest_link": { + "r2-link1": {} + } + } + } + } + } + } + }, + { + "local_as": "2", + "vrf": "GREEN", + "address_family": { + "ipv4": { + "unicast": { + "redistribute": [ + {"redist_type": "static"} + ], + "neighbor": { + "e1": { + "dest_link": { + "r2-link2": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "redistribute": [ + {"redist_type": "static"} + ], + "neighbor": { + "e1": { + "dest_link": { + "r2-link2": {} + } + } + } + } + } + } + } + ], + "static_routes":[ + { + "network":"20.1.1.1/32", + "next_hop":"Null0", + "vrf": "BLUE" + }, + { + "network":"20::1/128", + "next_hop":"Null0", + "vrf": "BLUE" + }, + { + "network":"30.1.1.1/32", + "next_hop":"Null0", + "vrf": "GREEN" + }, + { + "network":"30::1/128", + "next_hop":"Null0", + "vrf": "GREEN" + } + ] + }, + "e1": { + "links": { + "r1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"}, + "r2-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"}, + "r2-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"}, + "d1-link1": {"ipv4": "auto", "ipv6": "auto"}, + "d2-link1": {"ipv4": "auto", "ipv6": "auto"} + }, + "vrfs":[ + { + "name": "RED", + "id": "1", + "vni": 75100 + }, + { + "name": "BLUE", + "id": "2", + "vni": 75200 + }, + { + "name": "GREEN", + "id": "3", + "vni": 75300 + } + ], + "bgp": + [ + { + "local_as": "100", + "vrf": "RED", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "e1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "e1": {} + } + } + } + } + }, + "l2vpn": { + "evpn": { + "advertise": { + "ipv4": { + "unicast": {} + }, + "ipv6": { + "unicast": {} + } + } + } + } + } + }, + { + "local_as": "100", + "vrf": "BLUE", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "e1-link1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "e1-link1": {} + } + } + } + } + }, + "l2vpn": { + "evpn": { + "advertise": { + "ipv4": { + "unicast": {} + }, + "ipv6": { + "unicast": {} + } + } + } + } + } + }, + { + "local_as": "100", + "vrf": "GREEN", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "e1-link2": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "e1-link2": {} + } + } + } + } + }, + "l2vpn": { + "evpn": { + "advertise": { + "ipv4": { + "unicast": {} + }, + "ipv6": { + "unicast": {} + } + } + } + } + } + }, + { + "local_as": "100", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "d1": { + "dest_link": { + "e1-link1": { + "deactivate": "ipv4" + } + } + }, + "d2": { + "dest_link": { + "e1-link1": { + "deactivate": "ipv4" + } + } + } + } + } + }, + "l2vpn": { + "evpn": { + "neighbor": { + "d1": { + "ipv4":{ + "e1-link1": "activate" + } + }, + "d2": { + "ipv4":{ + "e1-link1": "activate" + } + } + }, + "advertise-all-vni": true + } + } + } + } + ] + }, + "d1": { + "links": { + "e1-link1": {"ipv4": "auto", "ipv6": "auto"}, + "r3": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"}, + "r4-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"}, + "r4-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"} + }, + "vrfs":[ + { + "name": "RED", + "id": "1", + "vni": 75100 + }, + { + "name": "BLUE", + "id": "2", + "vni": 75200 + }, + { + "name": "GREEN", + "id": "3", + "vni": 75300 + } + ], + "bgp": + [ + { + "local_as": "100", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "e1": { + "dest_link": { + "d1-link1": { + "deactivate": "ipv4" + } + } + } + } + } + }, + "l2vpn": { + "evpn": { + "neighbor": { + "e1": { + "ipv4":{ + "d1-link1": "activate" + } + } + }, + "advertise-all-vni": true + } + } + } + }, + { + "local_as": "100", + "vrf": "RED", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "d1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "d1": {} + } + } + } + } + }, + "l2vpn": { + "evpn": { + "advertise": { + "ipv4": { + "unicast": {} + }, + "ipv6": { + "unicast": {} + } + } + } + } + } + }, + { + "local_as": "100", + "vrf": "BLUE", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "d1-link1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "d1-link1": {} + } + } + } + } + }, + "l2vpn": { + "evpn": { + "advertise": { + "ipv4": { + "unicast": {} + }, + "ipv6": { + "unicast": {} + } + } + } + } + } + }, + { + "local_as": "100", + "vrf": "GREEN", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "d1-link2": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "d1-link2": {} + } + } + } + } + }, + "l2vpn": { + "evpn": { + "advertise": { + "ipv4": { + "unicast": {} + }, + "ipv6": { + "unicast": {} + } + } + } + } + } + } + ] + }, + "d2": { + "links": { + "e1-link1": {"ipv4": "auto", "ipv6": "auto"}, + "r3": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"}, + "r4-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"}, + "r4-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"} + }, + "vrfs":[ + { + "name": "RED", + "id": "1", + "vni": 75100 + }, + { + "name": "BLUE", + "id": "2", + "vni": 75200 + }, + { + "name": "GREEN", + "id": "3", + "vni": 75300 + } + ], + "bgp": + [ + { + "local_as": "200", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "e1": { + "dest_link": { + "d2-link1": { + "deactivate": "ipv4" + } + } + } + } + } + }, + "l2vpn": { + "evpn": { + "neighbor": { + "e1": { + "ipv4":{ + "d2-link1": "activate" + } + } + }, + "advertise-all-vni": true + } + } + } + }, + { + "local_as": "200", + "vrf": "RED", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "d2": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "d2": {} + } + } + } + } + }, + "l2vpn": { + "evpn": { + "advertise": { + "ipv4": { + "unicast": {} + }, + "ipv6": { + "unicast": {} + } + } + } + } + } + }, + { + "local_as": "200", + "vrf": "BLUE", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "d2-link1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "d2-link1": {} + } + } + } + } + }, + "l2vpn": { + "evpn": { + "advertise": { + "ipv4": { + "unicast": {} + }, + "ipv6": { + "unicast": {} + } + } + } + } + } + }, + { + "local_as": "200", + "vrf": "GREEN", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "d2-link2": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "d2-link2": {} + } + } + } + } + }, + "l2vpn": { + "evpn": { + "advertise": { + "ipv4": { + "unicast": {} + }, + "ipv6": { + "unicast": {} + } + } + } + } + } + } + ] + }, + "r3": { + "links": { + "d1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"}, + "d2": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"} + }, + "vrfs":[ + { + "name": "RED", + "id": "1" + } + ], + "bgp": + [ + { + "local_as": "3", + "vrf": "RED", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "d1": { + "dest_link": { + "r3": {} + } + }, + "d2": { + "dest_link": { + "r3": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "d1": { + "dest_link": { + "r3": {} + } + }, + "d2": { + "dest_link": { + "r3": {} + } + } + } + } + } + } + } + ] + }, + "r4": { + "links": { + "d1-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"}, + "d1-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"}, + "d2-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"}, + "d2-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"} + }, + "vrfs":[ + { + "name": "BLUE", + "id": "1" + }, + { + "name": "GREEN", + "id": "2" + } + ], + "bgp": + [ + { + "local_as": "4", + "vrf": "BLUE", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "d1": { + "dest_link": { + "r4-link1": {} + } + }, + "d2": { + "dest_link": { + "r4-link1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "d1": { + "dest_link": { + "r4-link1": {} + } + }, + "d2": { + "dest_link": { + "r4-link1": {} + } + } + } + } + } + } + }, + { + "local_as": "4", + "vrf": "GREEN", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "d1": { + "dest_link": { + "r4-link2": {} + } + }, + "d2": { + "dest_link": { + "r4-link2": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "d1": { + "dest_link": { + "r4-link2": {} + } + }, + "d2": { + "dest_link": { + "r4-link2": {} + } + } + } + } + } + } + } + ] + } + } +} diff --git a/tests/topotests/evpn_type5_test_topo1/evpn_type5_topo1.json b/tests/topotests/evpn_type5_test_topo1/evpn_type5_topo1.json new file mode 100644 index 0000000000..14842da326 --- /dev/null +++ b/tests/topotests/evpn_type5_test_topo1/evpn_type5_topo1.json @@ -0,0 +1,887 @@ +{ + "address_types": ["ipv4","ipv6"], + "ipv4base": "10.0.0.0", + "ipv4mask": 30, + "ipv6base": "fd00::", + "ipv6mask": 64, + "link_ip_start": { + "ipv4": "10.0.0.0", + "v4mask": 30, + "ipv6": "fd00::", + "v6mask": 64 + }, + "lo_prefix": { + "ipv4": "1.0.", + "v4mask": 32, + "ipv6": "2001:db8:f::", + "v6mask": 128 + }, + "routers": { + "r1": { + "links": { + "e1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"} + }, + "vrfs":[ + { + "name": "RED", + "id": "1" + } + ], + "bgp": + [ + { + "local_as": "1", + "vrf": "RED", + "address_family": { + "ipv4": { + "unicast": { + "redistribute": [ + {"redist_type": "static"} + ], + "neighbor": { + "e1": { + "dest_link": { + "r1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "redistribute": [ + {"redist_type": "static"} + ], + "neighbor": { + "e1": { + "dest_link": { + "r1": {} + } + } + } + } + } + } + } + ], + "static_routes":[ + { + "network":"10.1.1.1/32", + "next_hop":"Null0", + "vrf": "RED" + }, + { + "network":"10::1/128", + "next_hop":"Null0", + "vrf": "RED" + } + ] + }, + "r2": { + "links": { + "e1-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"}, + "e1-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"} + }, + "vrfs":[ + { + "name": "BLUE", + "id": "1" + }, + { + "name": "GREEN", + "id": "2" + } + ], + "bgp": + [ + { + "local_as": "2", + "vrf": "BLUE", + "address_family": { + "ipv4": { + "unicast": { + "redistribute": [ + {"redist_type": "static"} + ], + "neighbor": { + "e1": { + "dest_link": { + "r2-link1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "redistribute": [ + {"redist_type": "static"} + ], + "neighbor": { + "e1": { + "dest_link": { + "r2-link1": {} + } + } + } + } + } + } + }, + { + "local_as": "2", + "vrf": "GREEN", + "address_family": { + "ipv4": { + "unicast": { + "redistribute": [ + {"redist_type": "static"} + ], + "neighbor": { + "e1": { + "dest_link": { + "r2-link2": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "redistribute": [ + {"redist_type": "static"} + ], + "neighbor": { + "e1": { + "dest_link": { + "r2-link2": {} + } + } + } + } + } + } + } + ], + "static_routes":[ + { + "network":"20.1.1.1/32", + "next_hop":"Null0", + "vrf": "BLUE" + }, + { + "network":"20::1/128", + "next_hop":"Null0", + "vrf": "BLUE" + }, + { + "network":"30.1.1.1/32", + "next_hop":"Null0", + "vrf": "GREEN" + }, + { + "network":"30::1/128", + "next_hop":"Null0", + "vrf": "GREEN" + } + ] + }, + "e1": { + "links": { + "r1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"}, + "r2-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"}, + "r2-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"}, + "d1-link1": {"ipv4": "auto", "ipv6": "auto"}, + "d2-link1": {"ipv4": "auto", "ipv6": "auto"} + }, + "vrfs":[ + { + "name": "RED", + "id": "1", + "vni": 75100 + }, + { + "name": "BLUE", + "id": "2", + "vni": 75200 + }, + { + "name": "GREEN", + "id": "3", + "vni": 75300 + } + ], + "bgp": + [ + { + "local_as": "100", + "vrf": "RED", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "e1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "e1": {} + } + } + } + } + }, + "l2vpn": { + "evpn": { + "advertise": { + "ipv4": { + "unicast": {} + }, + "ipv6": { + "unicast": {} + } + } + } + } + } + }, + { + "local_as": "100", + "vrf": "BLUE", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "e1-link1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "e1-link1": {} + } + } + } + } + }, + "l2vpn": { + "evpn": { + "advertise": { + "ipv4": { + "unicast": {} + }, + "ipv6": { + "unicast": {} + } + } + } + } + } + }, + { + "local_as": "100", + "vrf": "GREEN", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "e1-link2": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "e1-link2": {} + } + } + } + } + }, + "l2vpn": { + "evpn": { + "advertise": { + "ipv4": { + "unicast": {} + }, + "ipv6": { + "unicast": {} + } + } + } + } + } + }, + { + "local_as": "100", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "d1": { + "dest_link": { + "e1-link1": { + "deactivate": "ipv4" + } + } + }, + "d2": { + "dest_link": { + "e1-link1": { + "deactivate": "ipv4" + } + } + } + } + } + }, + "l2vpn": { + "evpn": { + "neighbor": { + "d1": { + "ipv4":{ + "e1-link1": "activate" + } + }, + "d2": { + "ipv4":{ + "e1-link1": "activate" + } + } + }, + "advertise-all-vni": true + } + } + } + } + ] + }, + "d1": { + "links": { + "e1-link1": {"ipv4": "auto", "ipv6": "auto"}, + "r3": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"}, + "r4-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"}, + "r4-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"} + }, + "vrfs":[ + { + "name": "RED", + "id": "1", + "vni": 75100 + }, + { + "name": "BLUE", + "id": "2", + "vni": 75200 + }, + { + "name": "GREEN", + "id": "3", + "vni": 75300 + } + ], + "bgp": + [ + { + "local_as": "100", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "e1": { + "dest_link": { + "d1-link1": { + "deactivate": "ipv4" + } + } + } + } + } + }, + "l2vpn": { + "evpn": { + "neighbor": { + "e1": { + "ipv4":{ + "d1-link1": "activate" + } + } + }, + "advertise-all-vni": true + } + } + } + }, + { + "local_as": "100", + "vrf": "RED", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "d1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "d1": {} + } + } + } + } + }, + "l2vpn": { + "evpn": { + "advertise": { + "ipv4": { + "unicast": {} + }, + "ipv6": { + "unicast": {} + } + } + } + } + } + }, + { + "local_as": "100", + "vrf": "BLUE", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "d1-link1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "d1-link1": {} + } + } + } + } + }, + "l2vpn": { + "evpn": { + "advertise": { + "ipv4": { + "unicast": {} + }, + "ipv6": { + "unicast": {} + } + } + } + } + } + }, + { + "local_as": "100", + "vrf": "GREEN", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "d1-link2": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "d1-link2": {} + } + } + } + } + }, + "l2vpn": { + "evpn": { + "advertise": { + "ipv4": { + "unicast": {} + }, + "ipv6": { + "unicast": {} + } + } + } + } + } + } + ] + }, + "d2": { + "links": { + "e1-link1": {"ipv4": "auto", "ipv6": "auto"}, + "r3": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"}, + "r4-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"}, + "r4-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"} + }, + "vrfs":[ + { + "name": "RED", + "id": "1", + "vni": 75100 + }, + { + "name": "BLUE", + "id": "2", + "vni": 75200 + }, + { + "name": "GREEN", + "id": "3", + "vni": 75300 + } + ], + "bgp": + [ + { + "local_as": "200", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "e1": { + "dest_link": { + "d2-link1": { + "deactivate": "ipv4" + } + } + } + } + } + }, + "l2vpn": { + "evpn": { + "neighbor": { + "e1": { + "ipv4":{ + "d2-link1": "activate" + } + } + }, + "advertise-all-vni": true + } + } + } + }, + { + "local_as": "200", + "vrf": "RED", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "d2": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "d2": {} + } + } + } + } + }, + "l2vpn": { + "evpn": { + "advertise": { + "ipv4": { + "unicast": {} + }, + "ipv6": { + "unicast": {} + } + } + } + } + } + }, + { + "local_as": "200", + "vrf": "BLUE", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "d2-link1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "d2-link1": {} + } + } + } + } + }, + "l2vpn": { + "evpn": { + "advertise": { + "ipv4": { + "unicast": {} + }, + "ipv6": { + "unicast": {} + } + } + } + } + } + }, + { + "local_as": "200", + "vrf": "GREEN", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "d2-link2": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r4": { + "dest_link": { + "d2-link2": {} + } + } + } + } + }, + "l2vpn": { + "evpn": { + "advertise": { + "ipv4": { + "unicast": {} + }, + "ipv6": { + "unicast": {} + } + } + } + } + } + } + ] + }, + "r3": { + "links": { + "d1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"}, + "d2": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"} + }, + "vrfs":[ + { + "name": "RED", + "id": "1" + } + ], + "bgp": + [ + { + "local_as": "3", + "vrf": "RED", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "d1": { + "dest_link": { + "r3": {} + } + }, + "d2": { + "dest_link": { + "r3": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "d1": { + "dest_link": { + "r3": {} + } + }, + "d2": { + "dest_link": { + "r3": {} + } + } + } + } + } + } + } + ] + }, + "r4": { + "links": { + "d1-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"}, + "d1-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"}, + "d2-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"}, + "d2-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"} + }, + "vrfs":[ + { + "name": "BLUE", + "id": "1" + }, + { + "name": "GREEN", + "id": "2" + } + ], + "bgp": + [ + { + "local_as": "4", + "vrf": "BLUE", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "d1": { + "dest_link": { + "r4-link1": {} + } + }, + "d2": { + "dest_link": { + "r4-link1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "d1": { + "dest_link": { + "r4-link1": {} + } + }, + "d2": { + "dest_link": { + "r4-link1": {} + } + } + } + } + } + } + }, + { + "local_as": "4", + "vrf": "GREEN", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "d1": { + "dest_link": { + "r4-link2": {} + } + }, + "d2": { + "dest_link": { + "r4-link2": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "d1": { + "dest_link": { + "r4-link2": {} + } + }, + "d2": { + "dest_link": { + "r4-link2": {} + } + } + } + } + } + } + } + ] + } + } +} diff --git a/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_chaos_topo1.py b/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_chaos_topo1.py new file mode 100755 index 0000000000..e160264cad --- /dev/null +++ b/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_chaos_topo1.py @@ -0,0 +1,1048 @@ +#!/usr/bin/env python + +# +# Copyright (c) 2020 by VMware, Inc. ("VMware") +# Used Copyright (c) 2018 by Network Device Education Foundation, +# Inc. ("NetDEF") in this file. +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +""" +Following tests are covered to test EVPN-Type5 functionality: + +1. In absence of an overlay index all IP-Prefixes(RT-5) + are advertised with default values for below parameters: + --> Ethernet Tag ID = GW IP address = ESI=0 +2. EVPN CLI output and JSON format validation. +3. RT verification(auto) +""" + +import os +import re +import sys +import json +import time +import pytest +import platform +from copy import deepcopy +from time import sleep + + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) +sys.path.append(os.path.join(CWD, "../lib/")) + +# Required to instantiate the topology builder class. + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib.topotest import version_cmp +from lib.topogen import Topogen, get_topogen +from mininet.topo import Topo + +from lib.common_config import ( + start_topology, + write_test_header, + check_address_types, + write_test_footer, + reset_config_on_routers, + verify_rib, + step, + start_router_daemons, + kill_router_daemons, + create_static_routes, + create_vrf_cfg, + create_route_maps, + create_interface_in_kernel, + check_router_status, + configure_vxlan, + configure_brctl, + apply_raw_config, + verify_vrf_vni, + verify_cli_json +) + +from lib.topolog import logger +from lib.bgp import ( + verify_bgp_convergence, + create_router_bgp, + clear_bgp, + verify_best_path_as_per_bgp_attribute, + verify_attributes_for_evpn_routes, + verify_evpn_routes +) +from lib.topojson import build_topo_from_json, build_config_from_json + +# Reading the data from JSON File for topology creation +jsonFile = "{}/evpn_type5_chaos_topo1.json".format(CWD) +try: + with open(jsonFile, "r") as topoJson: + topo = json.load(topoJson) +except IOError: + assert False, "Could not read file {}".format(jsonFile) + +# Reading the data from JSON File for topology creation +# Global variables +TCPDUMP_FILE = "evpn_log.txt" +LOGDIR = "/tmp/topotests/" +NETWORK1_1 = {"ipv4": "10.1.1.1/32", "ipv6": "10::1/128"} +NETWORK1_2 = {"ipv4": "40.1.1.1/32", "ipv6": "40::1/128"} +NETWORK1_3 = {"ipv4": "40.1.1.2/32", "ipv6": "40::2/128"} +NETWORK1_4 = {"ipv4": "40.1.1.3/32", "ipv6": "40::3/128"} +NETWORK2_1 = {"ipv4": "20.1.1.1/32", "ipv6": "20::1/128"} +NETWORK3_1 = {"ipv4": "30.1.1.1/32", "ipv6": "30::1/128"} +NETWORK4_1 = {"ipv4": "100.1.1.1/32 ", "ipv6": "100::100/128"} +NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"} +VNI_1 = 75100 +VNI_2 = 75200 +VNI_3 = 75300 +MAC_1 = "00:80:48:ba:d1:00" +MAC_2 = "00:80:48:ba:d1:01" +MAC_3 = "00:80:48:ba:d1:02" +BRCTL_1 = "br100" +BRCTL_2 = "br200" +BRCTL_3 = "br300" +VXLAN_1 = "vxlan75100" +VXLAN_2 = "vxlan75200" +VXLAN_3 = "vxlan75300" +BRIDGE_INTF1 = "120.0.0.1" +BRIDGE_INTF2 = "120.0.0.2" +BRIDGE_INTF3 = "120.0.0.3" +MULTICAST_MAC1 = "01:00:5e:00:52:02" + +VXLAN = { + "vxlan_name": [VXLAN_1, VXLAN_2, VXLAN_3], + "vxlan_id": [75100, 75200, 75300], + "dstport": 4789, + "local_addr": {"e1": BRIDGE_INTF1, "d1": BRIDGE_INTF2, "d2": BRIDGE_INTF3}, + "learning": "no", +} +BRCTL = { + "brctl_name": [BRCTL_1, BRCTL_2, BRCTL_3], + "addvxlan": [VXLAN_1, VXLAN_2, VXLAN_3], + "vrf": ["RED", "BLUE", "GREEN"], + "stp": [0, 0, 0], +} + + +class CreateTopo(Topo): + """ + Test BasicTopo - topology 1 + + * `Topo`: Topology object + """ + + def build(self, *_args, **_opts): + """Build function""" + tgen = get_topogen(self) + + # Building topology from json file + build_topo_from_json(tgen, topo) + + +def setup_module(mod): + """ + Sets up the pytest environment + + * `mod`: module name + """ + + global topo + testsuite_run_time = time.asctime(time.localtime(time.time())) + logger.info("Testsuite start time: {}".format(testsuite_run_time)) + logger.info("=" * 40) + + logger.info("Running setup_module to create topology") + + # This function initiates the topology build with Topogen... + tgen = Topogen(CreateTopo, mod.__name__) + # ... and here it calls Mininet initialization functions. + + # Starting topology, create tmp files which are loaded to routers + # to start deamons and then start routers + start_topology(tgen) + + # Creating configuration from JSON + build_config_from_json(tgen, topo) + + if version_cmp(platform.release(), '4.19') < 0: + error_msg = ('EVPN tests will not run (have kernel "{}", ' + 'but it requires >= 4.19)'.format(platform.release())) + pytest.skip(error_msg) + + global BGP_CONVERGENCE + global ADDR_TYPES + ADDR_TYPES = check_address_types() + + BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) + assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error: {}".format( + BGP_CONVERGENCE + ) + + logger.info("Pre-requisite config for testsuite") + prerequisite_config_for_test_suite(tgen) + + logger.info("Running setup_module() done") + + +def teardown_module(): + """Teardown the pytest environment""" + + logger.info("Running teardown_module to delete topology") + + tgen = get_topogen() + + # Stop toplogy and Remove tmp files + tgen.stop_topology() + + logger.info( + "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) + ) + logger.info("=" * 40) + + +##################################################### +# +# Testcases +# +##################################################### + + +def prerequisite_config_for_test_suite(tgen): + """ + API to do prerequisite config for testsuite + + parameters: + ----------- + * `tgen`: topogen object + """ + + step("Configure vxlan, bridge interface") + for dut in ["e1", "d1", "d2"]: + step("[DUT: ]Configure vxlan") + vxlan_input = { + dut: { + "vxlan": [ + { + "vxlan_name": VXLAN["vxlan_name"], + "vxlan_id": VXLAN["vxlan_id"], + "dstport": VXLAN["dstport"], + "local_addr": VXLAN["local_addr"][dut], + "learning": VXLAN["learning"], + } + ] + } + } + + result = configure_vxlan(tgen, vxlan_input) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step("Configure bridge interface") + brctl_input = { + dut: { + "brctl": [ + { + "brctl_name": BRCTL["brctl_name"], + "addvxlan": BRCTL["addvxlan"], + "vrf": BRCTL["vrf"], + "stp": BRCTL["stp"], + } + ] + } + } + result = configure_brctl(tgen, topo, brctl_input) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step("Configure default routes") + add_default_routes(tgen) + + +def add_default_routes(tgen): + """ + API to do prerequisite config for testsuite + + parameters: + ----------- + * `tgen`: topogen object + """ + + step("Add default routes..") + + default_routes = { + "e1": { + "static_routes": [ + { + "network": "{}/32".format(VXLAN["local_addr"]["d1"]), + "next_hop": topo["routers"]["d1"]["links"]["e1-link1"][ + "ipv4" + ].split("/")[0], + }, + { + "network": "{}/32".format(VXLAN["local_addr"]["d2"]), + "next_hop": topo["routers"]["d2"]["links"]["e1-link1"][ + "ipv4" + ].split("/")[0], + }, + ] + }, + "d1": { + "static_routes": [ + { + "network": "{}/32".format(VXLAN["local_addr"]["e1"]), + "next_hop": topo["routers"]["e1"]["links"]["d1-link1"][ + "ipv4" + ].split("/")[0], + }, + { + "network": "{}/32".format(VXLAN["local_addr"]["d2"]), + "next_hop": topo["routers"]["e1"]["links"]["d1-link1"][ + "ipv4" + ].split("/")[0], + }, + ] + }, + "d2": { + "static_routes": [ + { + "network": "{}/32".format(VXLAN["local_addr"]["d1"]), + "next_hop": topo["routers"]["e1"]["links"]["d2-link1"][ + "ipv4" + ].split("/")[0], + }, + { + "network": "{}/32".format(VXLAN["local_addr"]["e1"]), + "next_hop": topo["routers"]["e1"]["links"]["d2-link1"][ + "ipv4" + ].split("/")[0], + }, + ] + }, + } + + result = create_static_routes(tgen, default_routes) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + +def test_verify_overlay_index_p1(request): + """ + In absence of an overlay index all IP-Prefixes(RT-5) + are advertised with default values for below parameters: + --> Ethernet Tag ID = GW IP address = ESI=0 + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + check_router_status(tgen) + reset_config_on_routers(tgen) + add_default_routes(tgen) + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + step("Following steps are taken care in base config:") + step( + "Configure BGP neighborship for both address families" + "(IPv4 & IPv6) between Edge-1 and VFN routers(R1 and R2)" + ) + step( + "Advertise prefixes from VNF routers R1 and R2 in associated " + "VRFs for both address-family." + ) + step("Advertise VRF routes as in EVPN address family from Edge-1 " "router.") + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "r1": { + "static_routes": [ + { + "network": NETWORK1_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + } + ] + }, + "r2": { + "static_routes": [ + { + "network": NETWORK2_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE", + }, + { + "network": NETWORK3_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "GREEN", + } + ] + } + } + + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Verify: Prefixes are received in all VRFs on Edge-1 router.") + + for addr_type in ADDR_TYPES: + input_routes = {key: topo["routers"][key] for key in ["r1"]} + result = verify_rib(tgen, addr_type, "e1", input_routes) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + input_routes = {key: topo["routers"][key] for key in ["r2"]} + result = verify_rib(tgen, addr_type, "e1", input_routes) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Verify that EVPN routes, received on DCG-1 and DCG-2 do not " + "carry any overlay index and these indexes are set to default " + "value=0. " + ) + + for addr_type in ADDR_TYPES: + input_routes = {key: topo["routers"][key] for key in ["r1"]} + + result = verify_attributes_for_evpn_routes( + tgen, topo, "d1", input_routes, ethTag=0 + ) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + result = verify_attributes_for_evpn_routes( + tgen, topo, "d2", input_routes, ethTag=0 + ) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_evpn_cli_json_available_p1(request): + """ + EVPN CLI output and JSON format validation. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + check_router_status(tgen) + reset_config_on_routers(tgen) + add_default_routes(tgen) + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + step("Need to verify below CLIs and associated JSON format " "outputs:") + + input_dict = { + "e1": { + "cli": [ + "show evpn vni detail", + "show bgp l2vpn evpn all overlay", + "show bgp l2vpn evpn vni" + ] + } + } + + result = verify_cli_json(tgen, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + write_test_footer(tc_name) + + +def test_RT_verification_auto_p0(request): + """ + RT verification(auto) + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + check_router_status(tgen) + reset_config_on_routers(tgen) + add_default_routes(tgen) + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + step( + "Advertise overlapping prefixes from VNFs R1 and R2 in all VRFs " + "RED, GREEN and BLUE 100.1.1.1/32 and 100::100/128" + ) + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "r1": { + "static_routes": [ + { + "network": NETWORK4_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + } + ] + }, + "r2": { + "static_routes": [ + { + "network": NETWORK4_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE", + }, + { + "network": NETWORK4_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "GREEN", + } + ] + } + } + + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Verify that Edge-1 receives same prefixes in all 3 VRFs via " + "corresponding next-hop in associated VRF sh bgp vrf all" + ) + + for addr_type in ADDR_TYPES: + input_routes = { + "r1": { + "static_routes": [ + { + "network": NETWORK4_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + } + ] + }, + "r2": { + "static_routes": [ + { + "network": NETWORK4_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE", + }, + { + "network": NETWORK4_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "GREEN", + }, + ] + }, + } + + result = verify_rib(tgen, addr_type, "e1", input_routes) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Configure 4-byte local AS number on Edge-1 and establish EVPN " + "neighborship with DCG-1 & DCG-2." + ) + + topo_local = deepcopy(topo) + + step("Delete BGP config for vrf RED.") + + input_dict_vni = { + "e1": { + "vrfs": [ + {"name": "RED", "no_vni": VNI_1}, + {"name": "BLUE", "no_vni": VNI_2}, + {"name": "GREEN", "no_vni": VNI_3}, + ] + } + } + result = create_vrf_cfg(tgen, topo, input_dict=input_dict_vni) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + input_dict_2 = {} + for dut in ["e1"]: + temp = {dut: {"bgp": []}} + input_dict_2.update(temp) + + INDEX = [0, 1, 2, 3] + VRFS = ["RED", "BLUE", "GREEN", None] + AS_NUM = [100, 100, 100, 100] + + for index, vrf, as_num in zip(INDEX, VRFS, AS_NUM): + topo_local["routers"][dut]["bgp"][index]["local_as"] = 4294967293 + if vrf: + temp[dut]["bgp"].append( + {"local_as": as_num, "vrf": vrf, "delete": True} + ) + else: + temp[dut]["bgp"].append({"local_as": as_num, "delete": True}) + + result = create_router_bgp(tgen, topo, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + result = create_router_bgp(tgen, topo_local["routers"]) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + input_dict_vni = { + "e1": { + "vrfs": [ + {"name": "RED", "vni": VNI_1}, + {"name": "BLUE", "vni": VNI_2}, + {"name": "GREEN", "vni": VNI_3}, + ] + } + } + result = create_vrf_cfg(tgen, topo, input_dict=input_dict_vni) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that all overlapping prefixes across different VRFs are " + "advertised in EVPN with unique RD value(auto derived)." + ) + step( + "Verify that FRR uses only the lower 2 bytes of ASN+VNI for auto " + "derived RT value." + ) + + for addr_type in ADDR_TYPES: + input_routes_1 = { + "r1": {"static_routes": [{"network": NETWORK4_1[addr_type], "vrf": "RED"}]} + } + input_routes_2 = { + "r2": {"static_routes": [{"network": NETWORK4_1[addr_type], "vrf": "BLUE"}]} + } + input_routes_3 = { + "r2": { + "static_routes": [{"network": NETWORK4_1[addr_type], "vrf": "GREEN"}] + } + } + + result = verify_attributes_for_evpn_routes( + tgen, topo, "e1", input_routes_1, rd="auto", rd_peer="e1" + ) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + result = verify_attributes_for_evpn_routes( + tgen, topo, "e1", input_routes_1, rt="auto", rt_peer="e1" + ) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + result = verify_attributes_for_evpn_routes( + tgen, topo, "e1", input_routes_2, rd="auto", rd_peer="e1" + ) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + result = verify_attributes_for_evpn_routes( + tgen, topo, "e1", input_routes_2, rt="auto", rt_peer="e1" + ) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + result = verify_attributes_for_evpn_routes( + tgen, topo, "e1", input_routes_3, rd="auto", rd_peer="e1" + ) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + result = verify_attributes_for_evpn_routes( + tgen, topo, "e1", input_routes_3, rt="auto", rt_peer="e1" + ) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Verify that DCG-1(iBGP peer) automatically imports the prefixes" + " from EVPN address-family to respective VRFs." + ) + step( + "Verify if DCG-2(eBGP peer) automatically imports the prefixes " + "from EVPN address-family to respective VRFs or not." + ) + + for addr_type in ADDR_TYPES: + input_routes = { + "r1": { + "static_routes": [ + { + "network": NETWORK4_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + } + ] + }, + "r2": { + "static_routes": [ + { + "network": NETWORK4_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE", + }, + { + "network": NETWORK4_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "GREEN", + }, + ] + }, + } + + result = verify_rib(tgen, addr_type, "d1", input_routes) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, "d2", input_routes) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Change the VNI number for all 3 VRFs on Edge-1 as:" + "RED : 75400, GREEN: 75500, BLUE: 75600" + ) + + input_dict_vni = { + "e1": { + "vrfs": [ + {"name": "RED", "no_vni": VNI_1}, + {"name": "BLUE", "no_vni": VNI_2}, + {"name": "GREEN", "no_vni": VNI_3}, + ] + } + } + result = create_vrf_cfg(tgen, topo, input_dict=input_dict_vni) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + input_dict_vni = { + "e1": { + "vrfs": [ + {"name": "RED", "vni": 75400}, + {"name": "BLUE", "vni": 75500}, + {"name": "GREEN", "vni": 75600}, + ] + } + } + result = create_vrf_cfg(tgen, topo, input_dict=input_dict_vni) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step("Delete configured vxlan") + dut = "e1" + vxlan_input = { + dut: { + "vxlan": [ + { + "vxlan_name": VXLAN["vxlan_name"], + "vxlan_id": VXLAN["vxlan_id"], + "dstport": VXLAN["dstport"], + "local_addr": VXLAN["local_addr"][dut], + "learning": VXLAN["learning"], + "delete": True, + } + ] + } + } + + result = configure_vxlan(tgen, vxlan_input) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step("Configured vxlan") + VXLAN["vxlan_id"] = [75400, 75500, 75600] + vxlan_input = { + dut: { + "vxlan": [ + { + "vxlan_name": VXLAN["vxlan_name"], + "vxlan_id": VXLAN["vxlan_id"], + "dstport": VXLAN["dstport"], + "local_addr": VXLAN["local_addr"][dut], + "learning": VXLAN["learning"], + } + ] + } + } + + result = configure_vxlan(tgen, vxlan_input) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step("Configure bridge interface") + brctl_input = { + dut: { + "brctl": [ + { + "brctl_name": BRCTL["brctl_name"], + "addvxlan": BRCTL["addvxlan"], + "vrf": BRCTL["vrf"], + "stp": BRCTL["stp"], + } + ] + } + } + result = configure_brctl(tgen, topo, brctl_input) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step( + "Verify on Edge-1 that auto derived RT value has changed for " + "each VRF based on VNI number.." + ) + + input_dict = { + "e1": { + "vrfs": [ + {"RED": {"vni": 75400}}, + {"BLUE": {"vni": 75500}}, + {"GREEN": {"vni": 75600}}, + ] + } + } + + result = verify_vrf_vni(tgen, input_dict) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step( + "Verify on Edge-1 that auto derived RT value has changed for " + "each VRF based on VNI number." + ) + + for addr_type in ADDR_TYPES: + input_routes = { + "r1": {"static_routes": [{"network": NETWORK4_1[addr_type], "vrf": "RED"}]} + } + + result = verify_attributes_for_evpn_routes( + tgen, topo, "e1", input_routes, rt="auto", rt_peer="e1" + ) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Verify on DCG-2 that prefixes are not imported from EVPN " + "address-family to VRFs as RT values are different on sending(" + "edge-1) and receiving(DCG-2) end." + ) + + for addr_type in ADDR_TYPES: + input_routes = { + "r1": {"static_routes": [{"network": NETWORK4_1[addr_type], "vrf": "RED"}]} + } + + result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False) + assert result is not True, "Testcase {} :Failed \n " + "Routes are still present: {}".format(tc_name, result) + logger.info("Expected Behavior: {}".format(result)) + + step( + "Revert back to original VNI number for all 3 VRFs on Edge-1 " + "as: RED : 75100, GREEN: 75200, BLUE: 75300" + ) + + input_dict_vni = { + "e1": { + "vrfs": [ + {"name": "RED", "no_vni": 75400}, + {"name": "BLUE", "no_vni": 75500}, + {"name": "GREEN", "no_vni": 75600}, + ] + } + } + result = create_vrf_cfg(tgen, topo, input_dict=input_dict_vni) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + input_dict_vni = { + "e1": { + "vrfs": [ + {"name": "RED", "vni": VNI_1}, + {"name": "BLUE", "vni": VNI_2}, + {"name": "GREEN", "vni": VNI_3}, + ] + } + } + result = create_vrf_cfg(tgen, topo, input_dict=input_dict_vni) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step("Delete configured vxlan") + dut = "e1" + vxlan_input = { + dut: { + "vxlan": [ + { + "vxlan_name": VXLAN["vxlan_name"], + "vxlan_id": VXLAN["vxlan_id"], + "dstport": VXLAN["dstport"], + "local_addr": VXLAN["local_addr"][dut], + "learning": VXLAN["learning"], + "delete": True, + } + ] + } + } + result = configure_vxlan(tgen, vxlan_input) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step("Configured vxlan") + VXLAN["vxlan_id"] = [75100, 75200, 75300] + vxlan_input = { + dut: { + "vxlan": [ + { + "vxlan_name": VXLAN["vxlan_name"], + "vxlan_id": VXLAN["vxlan_id"], + "dstport": VXLAN["dstport"], + "local_addr": VXLAN["local_addr"][dut], + "learning": VXLAN["learning"], + } + ] + } + } + result = configure_vxlan(tgen, vxlan_input) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step("Configure bridge interface") + brctl_input = { + dut: { + "brctl": [ + { + "brctl_name": BRCTL["brctl_name"], + "addvxlan": BRCTL["addvxlan"], + "vrf": BRCTL["vrf"], + "stp": BRCTL["stp"], + } + ] + } + } + result = configure_brctl(tgen, topo, brctl_input) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step( + "Verify on Edge-1 that auto derived RT value has changed for " + "each VRF based on VNI number." + ) + step( + "Verify that DCG-1(iBGP peer) automatically imports the prefixes" + " from EVPN address-family to respective VRFs." + ) + + for addr_type in ADDR_TYPES: + input_routes = { + "r1": {"static_routes": [{"network": NETWORK4_1[addr_type], "vrf": "RED"}]} + } + + result = verify_attributes_for_evpn_routes( + tgen, topo, "e1", input_routes, rt="auto", rt_peer="e1" + ) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, "d1", input_routes) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step("Test with smaller VNI numbers (1-75000)") + + input_dict_vni = {"e1": {"vrfs": [{"name": "RED", "no_vni": VNI_1}]}} + result = create_vrf_cfg(tgen, topo, input_dict=input_dict_vni) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + input_dict_vni = {"e1": {"vrfs": [{"name": "RED", "vni": 111}]}} + result = create_vrf_cfg(tgen, topo, input_dict=input_dict_vni) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that DCG-2 receives EVPN prefixes along with auto " + "derived RT values(based on smaller VNI numbers)" + ) + + for addr_type in ADDR_TYPES: + input_routes_1 = { + "r1": {"static_routes": [{"network": NETWORK4_1[addr_type], "vrf": "RED"}]} + } + + result = verify_attributes_for_evpn_routes( + tgen, topo, "d2", input_routes_1, rt="auto", rt_peer="e1", expected=False + ) + assert result is not True, "Testcase {} :Failed \n " + "Malfaromed Auto-RT value accepted: {}".format(tc_name, result) + logger.info("Expected Behavior: {}".format(result)) + + step("Configure VNI number more than boundary limit (16777215)") + + input_dict_vni = {"e1": {"vrfs": [{"name": "RED", "no_vni": 111}]}} + result = create_vrf_cfg(tgen, topo, input_dict=input_dict_vni) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + input_dict_vni = {"e1": {"vrfs": [{"name": "RED", "vni": 16777215}]}} + result = create_vrf_cfg(tgen, topo, input_dict=input_dict_vni) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step("CLI error for malformed VNI.") + input_dict = { + "e1": { + "vrfs": [{"RED": {"vni": 16777215, "routerMac": "None", "state": "Down"}}] + } + } + + result = verify_vrf_vni(tgen, input_dict) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + input_routes_1 = { + "r1": {"static_routes": [{"network": NETWORK4_1[addr_type], "vrf": "RED"}]} + } + + result = verify_attributes_for_evpn_routes( + tgen, topo, "d2", input_routes_1, rt="auto", rt_peer="e1", expected=False + ) + assert result is not True, "Testcase {} :Failed \n " + "Malfaromed Auto-RT value accepted: {}".format(tc_name, result) + logger.info("Expected Behavior: {}".format(result)) + + step("Un-configure VNI number more than boundary limit (16777215)") + + input_dict_vni = {"e1": {"vrfs": [{"name": "RED", "no_vni": 16777215}]}} + result = create_vrf_cfg(tgen, topo, input_dict=input_dict_vni) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + write_test_footer(tc_name) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py b/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py new file mode 100755 index 0000000000..3cdec760f7 --- /dev/null +++ b/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py @@ -0,0 +1,2117 @@ +#!/usr/bin/env python + +# +# Copyright (c) 2020 by VMware, Inc. ("VMware") +# Used Copyright (c) 2018 by Network Device Education Foundation, +# Inc. ("NetDEF") in this file. +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +""" +Following tests are covered to test EVPN-Type5 functionality: + +1. RD verification (manual/auto). +2. RT verification(manual) +3. In an active/standby EVPN implementation, if active DCG goes down, + secondary takes over. +4. EVPN routes are advertised/withdrawn, based on VNFs + advertising/withdrawing IP prefixes. +5. Route-map operations for EVPN address family. +6. BGP attributes for EVPN address-family. +""" + +import os +import re +import sys +import json +import time +import pytest +import platform +from copy import deepcopy +from time import sleep + + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) +sys.path.append(os.path.join(CWD, "../lib/")) + +# Required to instantiate the topology builder class. + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib.topotest import version_cmp +from lib.topogen import Topogen, get_topogen +from mininet.topo import Topo + +from lib.common_config import ( + start_topology, + write_test_header, + check_address_types, + write_test_footer, + reset_config_on_routers, + verify_rib, + step, + create_route_maps, + verify_cli_json, + start_router_daemons, + kill_router_daemons, + create_static_routes, + stop_router, + start_router, + create_vrf_cfg, + check_router_status, + apply_raw_config, + configure_vxlan, + configure_brctl, + verify_vrf_vni, + create_interface_in_kernel +) + +from lib.topolog import logger +from lib.bgp import ( + verify_bgp_convergence, + create_router_bgp, + clear_bgp, + verify_best_path_as_per_bgp_attribute, + verify_attributes_for_evpn_routes, + verify_evpn_routes +) +from lib.topojson import build_topo_from_json, build_config_from_json + +# Reading the data from JSON File for topology creation +jsonFile = "{}/evpn_type5_topo1.json".format(CWD) +try: + with open(jsonFile, "r") as topoJson: + topo = json.load(topoJson) +except IOError: + assert False, "Could not read file {}".format(jsonFile) + +# Global variables +NETWORK1_1 = {"ipv4": "10.1.1.1/32", "ipv6": "10::1/128"} +NETWORK1_2 = {"ipv4": "40.1.1.1/32", "ipv6": "40::1/128"} +NETWORK1_3 = {"ipv4": "40.1.1.2/32", "ipv6": "40::2/128"} +NETWORK1_4 = {"ipv4": "40.1.1.3/32", "ipv6": "40::3/128"} +NETWORK2_1 = {"ipv4": "20.1.1.1/32", "ipv6": "20::1/128"} +NETWORK3_1 = {"ipv4": "30.1.1.1/32", "ipv6": "30::1/128"} +NETWORK4_1 = {"ipv4": "100.1.1.1/32 ", "ipv6": "100::100/128"} +NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"} +VNI_1 = 75100 +VNI_2 = 75200 +VNI_3 = 75300 +MAC_1 = "00:80:48:ba:d1:00" +MAC_2 = "00:80:48:ba:d1:01" +MAC_3 = "00:80:48:ba:d1:02" +BRCTL_1 = "br100" +BRCTL_2 = "br200" +BRCTL_3 = "br300" +VXLAN_1 = "vxlan75100" +VXLAN_2 = "vxlan75200" +VXLAN_3 = "vxlan75300" +BRIDGE_INTF1 = "120.0.0.1" +BRIDGE_INTF2 = "120.0.0.2" +BRIDGE_INTF3 = "120.0.0.3" + +VXLAN = { + "vxlan_name": [VXLAN_1, VXLAN_2, VXLAN_3], + "vxlan_id": [75100, 75200, 75300], + "dstport": 4789, + "local_addr": {"e1": BRIDGE_INTF1, "d1": BRIDGE_INTF2, "d2": BRIDGE_INTF3}, + "learning": "no", +} +BRCTL = { + "brctl_name": [BRCTL_1, BRCTL_2, BRCTL_3], + "addvxlan": [VXLAN_1, VXLAN_2, VXLAN_3], + "vrf": ["RED", "BLUE", "GREEN"], + "stp": [0, 0, 0], +} + + +class CreateTopo(Topo): + """ + Test BasicTopo - topology 1 + + * `Topo`: Topology object + """ + + def build(self, *_args, **_opts): + """Build function""" + tgen = get_topogen(self) + + # Building topology from json file + build_topo_from_json(tgen, topo) + + +def setup_module(mod): + """ + Sets up the pytest environment + + * `mod`: module name + """ + + global topo + testsuite_run_time = time.asctime(time.localtime(time.time())) + logger.info("Testsuite start time: {}".format(testsuite_run_time)) + logger.info("=" * 40) + + logger.info("Running setup_module to create topology") + + # This function initiates the topology build with Topogen... + tgen = Topogen(CreateTopo, mod.__name__) + # ... and here it calls Mininet initialization functions. + + # Starting topology, create tmp files which are loaded to routers + # to start deamons and then start routers + start_topology(tgen) + + # Creating configuration from JSON + build_config_from_json(tgen, topo) + + if version_cmp(platform.release(), '4.19') < 0: + error_msg = ('EVPN tests will not run (have kernel "{}", ' + 'but it requires >= 4.19)'.format(platform.release())) + pytest.skip(error_msg) + + global BGP_CONVERGENCE + global ADDR_TYPES + ADDR_TYPES = check_address_types() + + BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) + assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error: {}".format( + BGP_CONVERGENCE + ) + + logger.info("Pre-requisite config for testsuite") + prerequisite_config_for_test_suite(tgen) + + logger.info("Running setup_module() done") + + +def teardown_module(): + """Teardown the pytest environment""" + + logger.info("Running teardown_module to delete topology") + + tgen = get_topogen() + + # Stop toplogy and Remove tmp files + tgen.stop_topology() + + logger.info( + "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) + ) + logger.info("=" * 40) + + +##################################################### +# +# Testcases +# +##################################################### + + +def prerequisite_config_for_test_suite(tgen): + """ + API to do prerequisite config for testsuite + + parameters: + ----------- + * `tgen`: topogen object + """ + + step("Configure vxlan, bridge interface") + for dut in ["e1", "d1", "d2"]: + step("[DUT: ]Configure vxlan") + vxlan_input = { + dut: { + "vxlan": [ + { + "vxlan_name": VXLAN["vxlan_name"], + "vxlan_id": VXLAN["vxlan_id"], + "dstport": VXLAN["dstport"], + "local_addr": VXLAN["local_addr"][dut], + "learning": VXLAN["learning"], + } + ] + } + } + + result = configure_vxlan(tgen, vxlan_input) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step("Configure bridge interface") + brctl_input = { + dut: { + "brctl": [ + { + "brctl_name": BRCTL["brctl_name"], + "addvxlan": BRCTL["addvxlan"], + "vrf": BRCTL["vrf"], + "stp": BRCTL["stp"], + } + ] + } + } + result = configure_brctl(tgen, topo, brctl_input) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step("Configure default routes") + add_default_routes(tgen) + + +def add_default_routes(tgen): + """ + API to do prerequisite config for testsuite + + parameters: + ----------- + * `tgen`: topogen object + """ + + step("Add default routes..") + + default_routes = { + "e1": { + "static_routes": [ + { + "network": "{}/32".format(VXLAN["local_addr"]["d1"]), + "next_hop": topo["routers"]["d1"]["links"]["e1-link1"][ + "ipv4" + ].split("/")[0], + }, + { + "network": "{}/32".format(VXLAN["local_addr"]["d2"]), + "next_hop": topo["routers"]["d2"]["links"]["e1-link1"][ + "ipv4" + ].split("/")[0], + }, + ] + }, + "d1": { + "static_routes": [ + { + "network": "{}/32".format(VXLAN["local_addr"]["e1"]), + "next_hop": topo["routers"]["e1"]["links"]["d1-link1"][ + "ipv4" + ].split("/")[0], + }, + { + "network": "{}/32".format(VXLAN["local_addr"]["d2"]), + "next_hop": topo["routers"]["e1"]["links"]["d1-link1"][ + "ipv4" + ].split("/")[0], + }, + ] + }, + "d2": { + "static_routes": [ + { + "network": "{}/32".format(VXLAN["local_addr"]["d1"]), + "next_hop": topo["routers"]["e1"]["links"]["d2-link1"][ + "ipv4" + ].split("/")[0], + }, + { + "network": "{}/32".format(VXLAN["local_addr"]["e1"]), + "next_hop": topo["routers"]["e1"]["links"]["d2-link1"][ + "ipv4" + ].split("/")[0], + }, + ] + }, + } + + result = create_static_routes(tgen, default_routes) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + +def test_RD_verification_manual_and_auto_p0(request): + """ + RD verification (manual/auto). + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + check_router_status(tgen) + reset_config_on_routers(tgen) + add_default_routes(tgen) + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + step( + "Advertise prefixes from VNF routers R1 and R2 in associated " + "VRFs for both address-family." + ) + step( + "Advertise vrf RED's routes in EVPN address family from Edge-1 router" + ", without manual configuration of RD." + ) + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "r1": { + "static_routes": [ + { + "network": NETWORK1_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + } + ] + }, + "r2": { + "static_routes": [ + { + "network": NETWORK2_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE", + }, + { + "network": NETWORK3_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "GREEN", + } + ] + } + } + + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Verify on DCG-1 and DCG-2:") + step("EVPN route for 10.1.1.1/32 has auto-assigned RD value.") + + for dut in ["d1", "d2"]: + input_routes = {key: topo["routers"][key] for key in ["r1"]} + result = verify_attributes_for_evpn_routes( + tgen, topo, dut, input_routes, rd="auto", rd_peer="e1" + ) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Configure RD for vrf RED manually as 50.50.50.50:50 and " + "advertise vrf RED's routes in EVPN address family from " + "Edge-1 router." + ) + + input_dict_rd = { + "e1": { + "bgp": [ + { + "local_as": "100", + "vrf": "RED", + "address_family": {"l2vpn": {"evpn": {"rd": "50.50.50.50:50"}}}, + } + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_rd) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step("EVPN route for vrf RED has RD value as 50.50.50.50:50") + for dut in ["d1", "d2"]: + input_routes = {key: topo["routers"][key] for key in ["r1"]} + result = verify_attributes_for_evpn_routes( + tgen, topo, dut, input_routes, rd="50.50.50.50:50" + ) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Configure RD for vrf RED manually as 100.100.100.100:100 and " + "advertise vrf RED's routes in EVPN address family from Edge-1 " + "router." + ) + input_dict_rd = { + "e1": { + "bgp": [ + { + "local_as": "100", + "vrf": "RED", + "address_family": { + "l2vpn": {"evpn": {"rd": "100.100.100.100:100"}} + } + } + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_rd) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step( + "EVPN route for vrf RED is overridden with RD value as " "100.100.100.100:100." + ) + + for dut in ["d1", "d2"]: + input_routes = {key: topo["routers"][key] for key in ["r1"]} + result = verify_attributes_for_evpn_routes( + tgen, topo, dut, input_routes, rd="100.100.100.100:100" + ) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Configure RD for vrf BLUE manually same as vrf RED " + "(100.100.100.100:100) and advertise vrf RED and BLUE's routes " + "in EVPN address family from Edge-1 router." + ) + + input_dict_rd = { + "e1": { + "bgp": [ + { + "local_as": "100", + "vrf": "BLUE", + "address_family": { + "l2vpn": {"evpn": {"rd": "100.100.100.100:100"}} + }, + } + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_rd) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step( + "Delete manually configured RD and advertise vrf RED's routes " + "in EVPN address family from Edge-1 router." + ) + + input_dict_rd = { + "e1": { + "bgp": [ + { + "local_as": "100", + "vrf": "RED", + "address_family": { + "l2vpn": {"evpn": {"no rd": "100.100.100.100:100"}} + }, + } + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_rd) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step( + "Configure same RD value for vrf GREEN, as auto generated RD " + "value for vrf RED on Edge-1 router." + ) + + input_dict_rd = { + "e1": { + "bgp": [ + { + "local_as": "100", + "vrf": "GREEN", + "address_family": {"l2vpn": {"evpn": {"rd": "10.0.0.33:1"}}}, + } + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_rd) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step("Delete auto configured RD value from vrf RED in EVPN " "address family.") + + input_dict_rd = { + "e1": { + "bgp": [ + { + "local_as": "100", + "vrf": "GREEN", + "address_family": {"l2vpn": {"evpn": {"no rd": "10.0.0.33:1"}}}, + } + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_rd) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step("Configure RD value as 100.100.100:100") + + input_dict_rd = { + "e1": { + "bgp": [ + { + "local_as": "100", + "vrf": "GREEN", + "address_family": {"l2vpn": {"evpn": {"rd": "100.100.100:100"}}}, + } + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_rd) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + write_test_footer(tc_name) + + +def test_RT_verification_manual_p0(request): + """ + RT verification(manual) + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + check_router_status(tgen) + reset_config_on_routers(tgen) + add_default_routes(tgen) + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + step( + "Advertise prefixes from VNF routers R1 and R2 in associated " + "VRFs for both address-family." + ) + step("Advertise VRF routes as in EVPN address family from Edge-1 " "router.") + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "r1": { + "static_routes": [ + { + "network": NETWORK1_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + } + ] + }, + "r2": { + "static_routes": [ + { + "network": NETWORK2_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE", + }, + { + "network": NETWORK3_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "GREEN", + } + ] + } + } + + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Configure RT for vrf RED manually as export 100:100 " + "and advertise vrf RED's routes in EVPN address family" + " from Edge-1 router." + ) + + input_dict_rt = { + "e1": { + "bgp": [ + { + "local_as": "100", + "vrf": "RED", + "address_family": { + "ipv4": { + "unicast": {"neighbor": {"r1": {"dest_link": {"e1": {}}}}} + }, + "ipv6": { + "unicast": {"neighbor": {"r1": {"dest_link": {"e1": {}}}}} + }, + "l2vpn": { + "evpn": {"route-target": {"export": [{"value": "100:100"}]}} + }, + } + } + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_rt) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step( + "Verify on dcg-1 and dcg-2, EVPN route for 10.1.1.1/32" + " and 10::1/128 have RT value as 100:100." + ) + + for dut in ["d1", "d2"]: + input_routes = {key: topo["routers"][key] for key in ["r1"]} + result = verify_attributes_for_evpn_routes( + tgen, topo, dut, input_routes, rt="100:100" + ) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Configure RT for vrf RED manually as export 500:500 and" + " advertise vrf RED's routes in EVPN address family from" + " e1 router." + ) + + input_dict_rt = { + "e1": { + "bgp": [ + { + "local_as": "100", + "vrf": "RED", + "address_family": { + "l2vpn": { + "evpn": {"route-target": {"export": [{"value": "500:500"}]}} + } + }, + } + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_rt) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step( + "Verify on dcg-1 and dcg-2, EVPN route for 10.1.1.1/32" + " and 10::1/128 have RT value as 500:500." + ) + + for dut in ["d1", "d2"]: + input_routes = {key: topo["routers"][key] for key in ["r1"]} + result = verify_attributes_for_evpn_routes( + tgen, topo, dut, input_routes, rt=["100:100", "500:500"] + ) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Import RT value 100:100 and 500:500 in vrf BLUE manually on" + " peer router DCG-1 and DCG-2." + ) + + input_dict_rt = { + "d1": { + "bgp": [ + { + "local_as": "100", + "vrf": "BLUE", + "address_family": { + "l2vpn": { + "evpn": { + "route-target": { + "import": [ + {"value": "100:100"}, + {"value": "500:500"}, + ] + } + } + } + }, + } + ] + }, + "d2": { + "bgp": [ + { + "local_as": "200", + "vrf": "BLUE", + "address_family": { + "l2vpn": { + "evpn": { + "route-target": { + "import": [ + {"value": "100:100"}, + {"value": "500:500"}, + ] + } + } + } + }, + } + ] + }, + } + + result = create_router_bgp(tgen, topo, input_dict_rt) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step( + "EVPN route for 10.1.1.1/32 and 10::1 should be installed " + "in vrf BLUE on DCG-1 and DCG-2 and further advertised to " + "VNF router." + ) + + for addr_type in ADDR_TYPES: + input_routes = { + "r1": { + "static_routes": [{"network": [NETWORK1_1[addr_type]], "vrf": "BLUE"}] + } + } + result = verify_rib(tgen, addr_type, "d1", input_routes) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + result = verify_rib(tgen, addr_type, "d2", input_routes) + assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + + step( + "Delete import RT value 500:500 in vrf BLUE manually on " + "peer router DCG-1 and DCG-2." + ) + + input_dict_rt = { + "d1": { + "bgp": [ + { + "local_as": "100", + "vrf": "BLUE", + "address_family": { + "l2vpn": { + "evpn": { + "route-target": { + "import": [{"value": "500:500", "delete": True}] + } + } + } + }, + } + ] + }, + "d2": { + "bgp": [ + { + "local_as": "200", + "vrf": "BLUE", + "address_family": { + "l2vpn": { + "evpn": { + "route-target": { + "import": [{"value": "500:500", "delete": True}] + } + } + } + }, + } + ] + }, + } + + result = create_router_bgp(tgen, topo, input_dict_rt) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + for dut in ["d1", "d2"]: + input_routes = {key: topo["routers"][key] for key in ["r1"]} + result = verify_attributes_for_evpn_routes( + tgen, topo, dut, input_routes, rt=["100:100", "500:500"] + ) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step("Delete RT export value 100:100 for vrf RED on Edge-1") + + input_dict_rt = { + "e1": { + "bgp": [ + { + "local_as": "100", + "vrf": "RED", + "address_family": { + "l2vpn": { + "evpn": { + "route-target": { + "export": [{"value": "100:100", "delete": True}] + } + } + } + }, + } + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_rt) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step( + "EVPN route for 10.1.1.1/32 and 10::1 should be withdrawn " + "from vrf BLUE on DCG-1,DCG-2 and VNF router." + ) + + for addr_type in ADDR_TYPES: + input_routes = { + "r1": { + "static_routes": [{"network": [NETWORK1_1[addr_type]], "vrf": "BLUE"}] + } + } + result = verify_rib(tgen, addr_type, "d1", input_routes, expected=False) + assert result is not True, ( + "Testcase {} :Failed \n Expected Behavior: Routes are still " + "present \n Error: {}".format(tc_name, result) + ) + logger.info("Expected Behavior: {}".format(result)) + + result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False) + assert result is not True, ( + "Testcase {} :Failed \n Expected Behavior: Routes are still " + "present \n Error: {}".format(tc_name, result) + ) + logger.info("Expected Behavior: {}".format(result)) + + step( + "Configure RT value as 100:100000010000010000101010 to check " + "the boundary value." + ) + + input_dict_rt = { + "e1": { + "bgp": [ + { + "local_as": "100", + "vrf": "RED", + "address_family": { + "l2vpn": { + "evpn": { + "route-target": { + "export": [ + {"value": "100:100000010000010000101010"} + ] + } + } + } + }, + } + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_rt) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step( + "CLI error: RT value: 100:100000010000010000101010 should not " "be configured" + ) + + dut = "e1" + input_routes = {key: topo["routers"][key] for key in ["r1"]} + result = verify_attributes_for_evpn_routes( + tgen, topo, dut, input_routes, rt="100:100000010000010000101010", expected=False + ) + assert result is not True, ( + "Testcase {} :Failed \n Expected Behavior: RT value of out" + " of boundary \n Error: {}".format(tc_name, result) + ) + logger.info("Expected Behavior: {}".format(result)) + + write_test_footer(tc_name) + + +def test_active_standby_evpn_implementation_p1(request): + """ + In an active/standby EVPN implementation, if active DCG goes down, + secondary takes over. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + check_router_status(tgen) + reset_config_on_routers(tgen) + add_default_routes(tgen) + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + step( + "Taken care in base config: Configure BGP neighborship for both " + "address families(IPv4 & IPv6) between DCG-1/DCG-2 and VFN routers" + "(R3 and R4)." + ) + + step( + "BGP neighborships come up within defined VRFs. Please use below " + "command: sh bgp vrf all summary" + ) + + result = verify_bgp_convergence(tgen, topo, "d1") + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + result = verify_bgp_convergence(tgen, topo, "d2") + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step( + "Advertise prefixes from VNF routers R3 and R4 in associated " + "VRFs for both address-families." + ) + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "r3": { + "static_routes": [ + { + "network": NETWORK1_2[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + } + ] + }, + "r4": { + "static_routes": [ + { + "network": NETWORK1_3[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE", + }, + { + "network": NETWORK1_4[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "GREEN", + } + ] + } + } + + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Redistribute static in (IPv4 and IPv6) address-family " + "on Edge-1 for all VRFs." + ) + + input_dict_2 = {} + for dut in ["r3", "r4"]: + temp = {dut: {"bgp": []}} + input_dict_2.update(temp) + + if dut == "r3": + VRFS = ["RED"] + AS_NUM = [3] + if dut == "r4": + VRFS = ["BLUE", "GREEN"] + AS_NUM = [4, 4] + + for vrf, as_num in zip(VRFS, AS_NUM): + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step("Prefixes are received in respective VRFs on DCG-1/DCG-2.") + + for addr_type in ADDR_TYPES: + input_routes = { + "r3": { + "static_routes": [ + { + "network": NETWORK1_2[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + } + ] + }, + "r4": { + "static_routes": [ + { + "network": NETWORK1_3[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE", + }, + { + "network": NETWORK1_4[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "GREEN", + }, + ] + }, + } + + result = verify_rib(tgen, addr_type, "d1", input_routes) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, "d2", input_routes) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Taken care in base config: Advertise VRF routes in EVPN " + "address-family from DCG-1 and DCG-2 router." + ) + + step("Verify on Edge-1 that EVPN routes are installed via next-hop " "as DCG-2.") + + for addr_type in ADDR_TYPES: + input_routes = { + "r3": { + "static_routes": [ + { + "network": NETWORK1_2[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + } + ] + }, + "r4": { + "static_routes": [ + { + "network": NETWORK1_3[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE", + }, + { + "network": NETWORK1_4[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "GREEN", + }, + ] + }, + } + + if addr_type == "ipv4": + result = verify_rib( + tgen, addr_type, "e1", input_routes, next_hop=BRIDGE_INTF2 + ) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + else: + result = verify_rib(tgen, addr_type, "e1", input_routes) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Configure 'next-hop self' on DCG-1 for peer Edge-1 in EVPN " "address-family." + ) + + input_dict_3 = { + "d1": { + "bgp": [ + { + "local_as": "100", + "address_family": { + "l2vpn": { + "evpn": { + "neighbor": { + "e1": { + "ipv4": {"d1-link1": {"next_hop_self": True}} + } + } + } + } + }, + } + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + logger.info( + "Creating route-map so ipv6 glpbal ip wpuld be preferred " "as next-hop" + ) + + step( + "Verify on Edge-1 that EVPN routes are now preferred via " + "next-hop as DCG-1(iBGP) due to shortest AS-Path." + ) + + for addr_type in ADDR_TYPES: + + logger.info("Verifying only ipv4 routes") + if addr_type != "ipv4": + continue + + input_routes = { + "r3": { + "static_routes": [ + { + "network": NETWORK1_2[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + } + ] + }, + "r4": { + "static_routes": [ + { + "network": NETWORK1_3[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE", + }, + { + "network": NETWORK1_4[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "GREEN", + }, + ] + }, + } + + next_hop = topo["routers"]["d1"]["links"]["e1-link1"]["ipv4"].split("/")[0] + + result = verify_rib(tgen, addr_type, "e1", input_routes, next_hop=next_hop) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_evpn_routes_from_VNFs_p1(request): + """ + EVPN routes are advertised/withdrawn, based on VNFs + advertising/withdrawing IP prefixes. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + check_router_status(tgen) + reset_config_on_routers(tgen) + add_default_routes(tgen) + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + step( + "Advertise prefixes from VNF routers R1 and R2 in associated " + "VRFs for both address-family." + ) + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "r1": { + "static_routes": [ + { + "network": NETWORK1_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + } + ] + }, + "r2": { + "static_routes": [ + { + "network": NETWORK2_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE", + }, + { + "network": NETWORK3_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "GREEN", + } + ] + } + } + + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Taken care in base config: Advertise VNFs'(R1 and R2) " + "originated routes in EVPN address-family from Edge-1 to " + "DCG-1 and DCG-2 routers." + ) + step( + "Taken care in base config: Advertise IPv4 and IPv6 routes " + "from default vrf in EVPN address-family from Edge-1." + ) + + step( + "Verify on DCG-2 that VNF routes are received in respective " + "VRFs along with auto derived RD/RT values 'show bgp l2vpn evpn'" + ) + for dut in ["d1", "d2"]: + input_routes = {key: topo["routers"][key] for key in ["r1"]} + result = verify_evpn_routes(tgen, topo, dut, input_routes) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + input_routes = {key: topo["routers"][key] for key in ["r2"]} + result = verify_evpn_routes(tgen, topo, dut, input_routes) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Verify on R3 and R4 that DCG-2 further advertises all EVPN " + "routes to corresponding VRFs." + ) + for addr_type in ADDR_TYPES: + input_routes = {key: topo["routers"][key] for key in ["r1"]} + result = verify_rib(tgen, addr_type, "r3", input_routes) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + input_routes = {key: topo["routers"][key] for key in ["r2"]} + result = verify_rib(tgen, addr_type, "r4", input_routes) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Verify that DCG-2 receives EVPN routes associated to default " + "VRF and install in default IP routing table as well." + ) + for addr_type in ADDR_TYPES: + input_routes = {key: topo["routers"][key] for key in ["r1"]} + result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + input_routes = {key: topo["routers"][key] for key in ["r2"]} + result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step("Withdraw the IP prefixes from VFN(R1).") + dut = "r1" + input_dict_2 = {} + static_routes = topo["routers"][dut]["static_routes"] + for static_route in static_routes: + static_route["delete"] = True + temp = {dut: {"static_routes": [static_route]}} + input_dict_2.update(temp) + + result = create_static_routes(tgen, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Verify that DCG-2 removes EVPN routes corresponding to vrf RED and " + "send an withdraw to VNF(R3) as well." + ) + for addr_type in ADDR_TYPES: + input_routes = {key: topo["routers"][key] for key in ["r1"]} + result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False) + assert result is not True, "Testcase {} :Failed \n " + "Routes are still present: {}".format(tc_name, result) + logger.info("Expected Behavior: {}".format(result)) + + for addr_type in ADDR_TYPES: + input_routes = {key: topo["routers"][key] for key in ["r1"]} + result = verify_rib(tgen, addr_type, "r3", input_routes, expected=False) + assert result is not True, "Testcase {} :Failed \n " + "Routes are still present: {}".format(tc_name, result) + logger.info("Expected Behavior: {}".format(result)) + + step("Re-advertise IP prefixes from VFN(R1).") + step( + "Advertise prefixes from VNF routers R1 and R2 in associated " + "VRFs for both address-family." + ) + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "r1": { + "static_routes": [ + { + "network": NETWORK1_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + } + ] + }, + "r2": { + "static_routes": [ + { + "network": NETWORK2_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE", + }, + { + "network": NETWORK3_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "GREEN", + } + ] + } + } + + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Verify that DCG-2 receives EVPN routes corresponding to vrf RED " + "again and send an update to VNF(R3) as well." + ) + for addr_type in ADDR_TYPES: + input_routes = {key: topo["routers"][key] for key in ["r1"]} + result = verify_rib(tgen, addr_type, "d2", input_routes) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + input_routes = {key: topo["routers"][key] for key in ["r1"]} + result = verify_rib(tgen, addr_type, "r3", input_routes) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step("Delete vrf BLUE from router Edge-1") + input_dict_3 = {"e1": {"vrfs": [{"name": "BLUE", "id": "2", "delete": True}]}} + + result = create_vrf_cfg(tgen, input_dict_3) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that DCG-2 removes EVPN routes corresponding to " + "vrf BLUE and send an withdraw to VNF(R4) as well." + ) + for addr_type in ADDR_TYPES: + input_routes = { + "r2": {"static_routes": [{"network": NETWORK2_1[addr_type], "vrf": "BLUE"}]} + } + + result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False) + assert result is not True, "Testcase {} :Failed \n " + "Routes are still present: {}".format(tc_name, result) + logger.info("Expected Behavior: {}".format(result)) + + result = verify_rib(tgen, addr_type, "r4", input_routes, expected=False) + assert result is not True, "Testcase {} :Failed \n " + "Routes are still present: {}".format(tc_name, result) + logger.info("Expected Behavior: {}".format(result)) + + step("Add vrf BLUE on router Edge-1 again.") + interface = topo["routers"]["e1"]["links"]["r2-link1"]["interface"] + input_dict_3 = { + "e1": { + "links": { + "r2-link1": { + "interface": interface, + "ipv4": "auto", + "ipv6": "auto", + "vrf": "BLUE", + } + }, + "vrfs": [{"name": "BLUE", "id": "2"}], + } + } + result = create_vrf_cfg(tgen, input_dict_3) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + logger.info( + "After deleting VRFs ipv6 addresses wil be deleted " + "from kernel Adding back ipv6 addresses" + ) + dut = "e1" + vrfs = ["BLUE"] + + for vrf in vrfs: + for c_link, c_data in topo["routers"][dut]["links"].items(): + if "vrf" in c_data: + if c_data["vrf"] != vrf: + continue + + intf_name = c_data["interface"] + intf_ipv6 = c_data["ipv6"] + + create_interface_in_kernel( + tgen, dut, intf_name, intf_ipv6, vrf, create=False + ) + + logger.info("Wait for 60 sec.") + sleep(60) + + step( + "Verify that DCG-2 receives EVPN routes corresponding to " + "vrf BLUE again and send an update to VNF(R4) as well." + ) + for addr_type in ADDR_TYPES: + input_routes = { + "r2": {"static_routes": [{"network": NETWORK2_1[addr_type], "vrf": "BLUE"}]} + } + + result = verify_rib(tgen, addr_type, "d2", input_routes) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, "r4", input_routes) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step("Withdraw IPv6 address-family in EVPN advertisements for " "VRF GREEN") + addr_type = "ipv6" + input_dict_4 = { + "e1": { + "bgp": [ + { + "local_as": "100", + "vrf": "GREEN", + "address_family": { + "l2vpn": { + "evpn": { + "advertise": {addr_type: {"unicast": {"delete": True}}} + } + } + }, + } + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_4) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that EVPN routes (IPv6)associated with vrf GREEN are " + "withdrawn from DCG-2 and VNF R4." + ) + input_routes = { + "r2": {"static_routes": [{"network": NETWORK3_1[addr_type], "vrf": "GREEN"}]} + } + + result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False) + assert result is not True, "Testcase {} :Failed \n " + "Routes are still present: {}".format(tc_name, result) + logger.info("Expected Behavior: {}".format(result)) + + result = verify_rib(tgen, addr_type, "r4", input_routes, expected=False) + assert result is not True, "Testcase {} :Failed \n " + "Routes are still present: {}".format(tc_name, result) + logger.info("Expected Behavior: {}".format(result)) + + step("Advertise IPv6 address-family in EVPN advertisements " "for VRF GREEN.") + addr_type = "ipv6" + input_dict_4 = { + "e1": { + "bgp": [ + { + "local_as": "100", + "vrf": "GREEN", + "address_family": { + "l2vpn": {"evpn": {"advertise": {addr_type: {"unicast": {}}}}} + }, + } + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_4) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + input_routes = { + "r2": { + "static_routes": [{"network": NETWORK3_1[addr_type], "vrf": "GREEN"}] + } + } + + result = verify_rib(tgen, addr_type, "d2", input_routes) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, "r4", input_routes) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +@pytest.mark.parametrize( + "attribute", [{"route-type": "prefix"}, {"vni": VNI_1}, {"rt": "300:300"}] +) +def test_route_map_operations_for_evpn_address_family_p1(request, attribute): + """ + Route-map operations for EVPN address family. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + check_router_status(tgen) + reset_config_on_routers(tgen) + add_default_routes(tgen) + + step( + "Advertise prefixes from VNF routers R1 and R2 in associated " + "VRFs for both address-family." + ) + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "r1": { + "static_routes": [ + { + "network": NETWORK1_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + } + ] + }, + "r2": { + "static_routes": [ + { + "network": NETWORK2_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE", + }, + { + "network": NETWORK3_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "GREEN", + } + ] + } + } + + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + step( + "Advertise VRF routes in EVPN address family from Edge-1 router." + " Configure a route-map on e1 to filter EVPN routes based on" + " below keywords: route-type: prefix" + ) + + for key, value in attribute.items(): + if key == "rt": + logger.info("Creating extcommunity using raw_config") + raw_config = { + "d2": { + "raw_config": [ + "bgp extcommunity-list standard ECOMM300 permit {} {}".format( + key, value + ) + ] + } + } + result = apply_raw_config(tgen, raw_config) + assert result is True, "Testcase {} : Failed Error: {}".format( + tc_name, result + ) + + input_dict_1 = { + "e1": { + "route_maps": { + "rmap_route_type": [ + {"action": "permit", "set": {"extcommunity": {key: value}}} + ] + } + }, + "d2": { + "route_maps": { + "rmap_route_type": [ + {"action": "permit", "match": {"extcommunity": "ECOMM300"}} + ] + } + }, + } + + else: + input_dict_1 = { + "e1": { + "route_maps": { + "rmap_route_type": [ + {"action": "permit", "match": {"evpn": {key: value}}} + ] + } + }, + "d2": { + "route_maps": { + "rmap_route_type": [ + {"action": "permit", "match": {"evpn": {key: value}}} + ] + } + }, + } + result = create_route_maps(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + input_dict_2 = { + "e1": { + "bgp": [ + { + "local_as": "100", + "address_family": { + "l2vpn": { + "evpn": { + "neighbor": { + "d2": { + "ipv4": { + "e1-link1": { + "route_maps": [ + { + "name": "rmap_route_type", + "direction": "out", + } + ] + } + } + } + } + } + } + }, + } + ] + }, + "d2": { + "bgp": [ + { + "local_as": "200", + "address_family": { + "l2vpn": { + "evpn": { + "neighbor": { + "e1": { + "ipv4": { + "d2-link1": { + "route_maps": [ + { + "name": "rmap_route_type", + "direction": "in", + } + ] + } + } + } + } + } + } + }, + } + ] + }, + } + + result = create_router_bgp(tgen, topo, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step( + "Verify on router DCG-2 that EVPN routes corresponding to all " + "VRFs are received. As all EVPN routes are type-5 only." + ) + + input_routes = {key: topo["routers"][key] for key in ["r1"]} + result = verify_evpn_routes(tgen, topo, "d2", input_routes) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + input_routes = {key: topo["routers"][key] for key in ["r2"]} + result = verify_evpn_routes(tgen, topo, "d2", input_routes) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + write_test_footer(tc_name) + + +@pytest.mark.parametrize("attribute", ["locPrf", "weight", "path"]) +def test_bgp_attributes_for_evpn_address_family_p1(request, attribute): + """ + BGP attributes for EVPN address-family. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + check_router_status(tgen) + reset_config_on_routers(tgen) + add_default_routes(tgen) + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + step( + "Advertise prefixes from VNF routers R1 and R2 in associated " + "VRFs for both address-family." + ) + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "r1": { + "static_routes": [ + { + "network": NETWORK1_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + } + ] + }, + "r2": { + "static_routes": [ + { + "network": NETWORK2_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE", + }, + { + "network": NETWORK3_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "GREEN", + } + ] + } + } + + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + topo_local = deepcopy(topo) + + logger.info("Modifying topology b/w e1 and d1 from iBGP to eBGP") + step("Delete BGP config for vrf RED.") + + if attribute == "locPrf": + input_dict_vni = { + "d1": { + "vrfs": [ + {"name": "RED", "no_vni": VNI_1}, + {"name": "BLUE", "no_vni": VNI_2}, + {"name": "GREEN", "no_vni": VNI_3}, + ] + } + } + result = create_vrf_cfg(tgen, topo, input_dict=input_dict_vni) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + input_dict_2 = {} + for dut in ["d1"]: + temp = {dut: {"bgp": []}} + input_dict_2.update(temp) + + INDEX = [0, 1, 2, 3] + VRFS = ["RED", "BLUE", "GREEN", None] + AS_NUM = [100, 100, 100, 100] + + for index, vrf, as_num in zip(INDEX, VRFS, AS_NUM): + topo_local["routers"][dut]["bgp"][index]["local_as"] = 200 + if vrf: + temp[dut]["bgp"].append( + {"local_as": as_num, "vrf": vrf, "delete": True} + ) + else: + temp[dut]["bgp"].append({"local_as": as_num, "delete": True}) + + result = create_router_bgp(tgen, topo, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + result = create_router_bgp(tgen, topo_local["routers"]) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step("Advertise VRF routes in EVPN address-family from DCG-1 " "and DCG-2 routers.") + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "r3": { + "static_routes": [ + { + "network": NETWORK1_2[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + } + ] + }, + "r4": { + "static_routes": [ + { + "network": NETWORK1_3[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE", + }, + { + "network": NETWORK1_4[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "GREEN", + }, + ] + }, + } + + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Redistribute static in (IPv4 and IPv6) address-family " + "on Edge-1 for all VRFs." + ) + + input_dict_2 = {} + for dut in ["r3", "r4"]: + temp = {dut: {"bgp": []}} + input_dict_2.update(temp) + + if dut == "r3": + VRFS = ["RED"] + AS_NUM = [3] + if dut == "r4": + VRFS = ["BLUE", "GREEN"] + AS_NUM = [4, 4] + + for vrf, as_num in zip(VRFS, AS_NUM): + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step( + "Verify on router Edge-1 that EVPN routes corresponding to " + "all VRFs are received from both routers DCG-1 and DCG-2" + ) + + for addr_type in ADDR_TYPES: + input_routes = { + "r3": { + "static_routes": [ + { + "network": NETWORK1_2[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + } + ] + }, + "r4": { + "static_routes": [ + { + "network": NETWORK1_3[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE", + }, + { + "network": NETWORK1_4[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "GREEN", + }, + ] + }, + } + + result = verify_rib(tgen, addr_type, "e1", input_routes) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Configure a route-map on Edge-1 to modify below BGP attributes " + "for EVPN address-family:" + ) + + if attribute == "path": + input_dict_1 = { + "e1": { + "route_maps": { + "rmap_d1".format(addr_type): [ + { + "action": "permit", + "set": { + attribute: { + "as_num": "123 231 321", + "as_action": "prepend", + } + }, + } + ], + "rmap_d2".format(addr_type): [ + { + "action": "permit", + "set": { + attribute: {"as_num": "121", "as_action": "prepend"} + }, + } + ], + } + } + } + else: + input_dict_1 = { + "e1": { + "route_maps": { + "rmap_d1".format(addr_type): [ + {"action": "permit", "set": {attribute: 120}} + ], + "rmap_d2".format(addr_type): [ + {"action": "permit", "set": {attribute: 150}} + ], + } + } + } + result = create_route_maps(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + input_dict_2 = { + "e1": { + "bgp": [ + { + "local_as": "100", + "address_family": { + "l2vpn": { + "evpn": { + "neighbor": { + "d1": { + "ipv4": { + "e1-link1": { + "route_maps": [ + { + "name": "rmap_d1", + "direction": "in", + } + ] + } + } + }, + "d2": { + "ipv4": { + "e1-link1": { + "route_maps": [ + { + "name": "rmap_d2", + "direction": "in", + } + ] + } + } + }, + } + } + } + }, + } + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_2) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step( + "Verify on router Edge-1 that EVPN routes are preferred via" + " DCG-1 or DCG-2 based on best path selection criteria " + "(according to the configured BGP attribute values in route-map)." + ) + + for addr_type in ADDR_TYPES: + input_routes = { + "r3": { + "static_routes": [ + { + "network": NETWORK1_2[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + } + ] + }, + "r4": { + "static_routes": [ + { + "network": NETWORK1_3[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE", + }, + { + "network": NETWORK1_4[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "GREEN", + }, + ] + }, + } + + result = verify_best_path_as_per_bgp_attribute( + tgen, addr_type, "e1", input_routes, attribute + ) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py index 44b7335058..7b1eead944 100644 --- a/tests/topotests/lib/bgp.py +++ b/tests/topotests/lib/bgp.py @@ -27,6 +27,8 @@ import sys from lib import topotest from lib.topolog import logger +from lib.topogen import TopoRouter, get_topogen + # Import common_config to use commomnly used APIs from lib.common_config import ( create_common_configuration, @@ -44,7 +46,6 @@ from lib.common_config import ( LOGDIR = "/tmp/topotests/" TMPDIR = None - def create_router_bgp(tgen, topo, input_dict=None, build=False, load_config=True): """ API to configure bgp on router @@ -167,6 +168,7 @@ def create_router_bgp(tgen, topo, input_dict=None, build=False, load_config=True ipv4_data = bgp_addr_data.setdefault("ipv4", {}) ipv6_data = bgp_addr_data.setdefault("ipv6", {}) + l2vpn_data = bgp_addr_data.setdefault("l2vpn", {}) neigh_unicast = ( True @@ -175,6 +177,8 @@ def create_router_bgp(tgen, topo, input_dict=None, build=False, load_config=True else False ) + l2vpn_evpn = True if l2vpn_data.setdefault("evpn", {}) else False + if neigh_unicast: data_all_bgp = __create_bgp_unicast_neighbor( tgen, @@ -185,6 +189,11 @@ def create_router_bgp(tgen, topo, input_dict=None, build=False, load_config=True config_data=data_all_bgp, ) + if l2vpn_evpn: + data_all_bgp = __create_l2vpn_evpn_address_family( + tgen, topo, bgp_data, router, config_data=data_all_bgp + ) + try: result = create_common_configuration( tgen, router, data_all_bgp, "bgp", build, load_config @@ -468,6 +477,166 @@ def __create_bgp_unicast_neighbor( return config_data +def __create_l2vpn_evpn_address_family( + tgen, topo, input_dict, router, config_data=None +): + """ + Helper API to create configuration for l2vpn evpn address-family + + Parameters + ---------- + * `tgen` : Topogen object + * `topo` : json file data + * `input_dict` : Input dict data, required when configuring + from testcase + * `router` : router id to be configured. + * `build` : Only for initial setup phase this is set as True. + """ + + result = False + + logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) + + bgp_data = input_dict["address_family"] + + for family_type, family_dict in bgp_data.iteritems(): + if family_type != "l2vpn": + continue + + family_data = family_dict["evpn"] + if family_data: + config_data.append("address-family l2vpn evpn") + + advertise_data = family_data.setdefault("advertise", {}) + neighbor_data = family_data.setdefault("neighbor", {}) + advertise_all_vni_data = family_data.setdefault("advertise-all-vni", None) + rd_data = family_data.setdefault("rd", None) + no_rd_data = family_data.setdefault("no rd", False) + route_target_data = family_data.setdefault("route-target", {}) + + if advertise_data: + for address_type, unicast_type in advertise_data.items(): + + if isinstance(unicast_type, dict): + for key, value in unicast_type.items(): + cmd = "advertise {} {}".format(address_type, key) + + if value: + route_map = value.setdefault("route-map", {}) + advertise_del_action = value.setdefault("delete", None) + + if route_map: + cmd = "{} route-map {}".format(cmd, route_map) + + if advertise_del_action: + cmd = "no {}".format(cmd) + + config_data.append(cmd) + + if neighbor_data: + for neighbor, neighbor_data in neighbor_data.items(): + ipv4_neighbor = neighbor_data.setdefault("ipv4", {}) + ipv6_neighbor = neighbor_data.setdefault("ipv6", {}) + + if ipv4_neighbor: + for neighbor_name, action in ipv4_neighbor.items(): + neighbor_ip = topo[neighbor]["links"][neighbor_name][ + "ipv4" + ].split("/")[0] + + if isinstance(action, dict): + next_hop_self = action.setdefault("next_hop_self", None) + route_maps = action.setdefault("route_maps", {}) + + if next_hop_self is not None: + if next_hop_self is True: + config_data.append( + "neighbor {} " + "next-hop-self".format(neighbor_ip) + ) + elif next_hop_self is False: + config_data.append( + "no neighbor {} " + "next-hop-self".format(neighbor_ip) + ) + + if route_maps: + for route_map in route_maps: + name = route_map.setdefault("name", {}) + direction = route_map.setdefault("direction", "in") + del_action = route_map.setdefault("delete", False) + + if not name: + logger.info( + "Router %s: 'name' " + "not present in " + "input_dict for BGP " + "neighbor route name", + router, + ) + else: + cmd = "neighbor {} route-map {} " "{}".format( + neighbor_ip, name, direction + ) + + if del_action: + cmd = "no {}".format(cmd) + + config_data.append(cmd) + + else: + if action == "activate": + cmd = "neighbor {} activate".format(neighbor_ip) + elif action == "deactivate": + cmd = "no neighbor {} activate".format(neighbor_ip) + + config_data.append(cmd) + + if ipv6_neighbor: + for neighbor_name, action in ipv4_neighbor.items(): + neighbor_ip = topo[neighbor]["links"][neighbor_name][ + "ipv6" + ].split("/")[0] + if action == "activate": + cmd = "neighbor {} activate".format(neighbor_ip) + elif action == "deactivate": + cmd = "no neighbor {} activate".format(neighbor_ip) + + config_data.append(cmd) + + if advertise_all_vni_data == True: + cmd = "advertise-all-vni" + config_data.append(cmd) + elif advertise_all_vni_data == False: + cmd = "no advertise-all-vni" + config_data.append(cmd) + + if rd_data: + cmd = "rd {}".format(rd_data) + config_data.append(cmd) + + if no_rd_data: + cmd = "no rd {}".format(no_rd_data) + config_data.append(cmd) + + if route_target_data: + for rt_type, rt_dict in route_target_data.items(): + for _rt_dict in rt_dict: + rt_value = _rt_dict.setdefault("value", None) + del_rt = _rt_dict.setdefault("delete", None) + + if rt_value: + cmd = "route-target {} {}".format(rt_type, rt_value) + if del_rt: + cmd = "no {}".format(cmd) + + config_data.append(cmd) + + logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) + + return config_data + + def __create_bgp_neighbor(topo, input_dict, router, addr_type, add_neigh=True): """ Helper API to create neighbor specific configuration @@ -490,7 +659,7 @@ def __create_bgp_neighbor(topo, input_dict, router, addr_type, add_neigh=True): for dest_link, peer in peer_dict["dest_link"].iteritems(): nh_details = topo[name] - if "vrfs" in topo[router]: + if "vrfs" in topo[router] or type(nh_details["bgp"]) is list: remote_as = nh_details["bgp"][0]["local_as"] else: remote_as = nh_details["bgp"]["local_as"] @@ -882,25 +1051,22 @@ def verify_router_id(tgen, topo, input_dict): return True -@retry(attempts=44, wait=3, return_is_str=True) +@retry(attempts=50, wait=3, return_is_str=True) def verify_bgp_convergence(tgen, topo, dut=None): """ API will verify if BGP is converged with in the given time frame. Running "show bgp summary json" command and verify bgp neighbor state is established, - Parameters ---------- * `tgen`: topogen object * `topo`: input json file data * `dut`: device under test - Usage ----- # To veriry is BGP is converged for all the routers used in topology results = verify_bgp_convergence(tgen, topo, dut="r1") - Returns ------- errormsg(str) or True @@ -1052,11 +1218,13 @@ def verify_bgp_convergence(tgen, topo, dut=None): if nh_state == "Established": no_of_peer += 1 - if no_of_peer == total_peer: - logger.info("[DUT: %s] VRF: %s, BGP is Converged", router, vrf) - else: - errormsg = "[DUT: %s] VRF: %s, BGP is not converged" % (router, vrf) - return errormsg + if no_of_peer == total_peer: + logger.info("[DUT: %s] VRF: %s, BGP is Converged for %s address-family", + router, vrf, addr_type) + else: + errormsg = ("[DUT: %s] VRF: %s, BGP is not converged for %s address-family" % + (router, vrf, addr_type)) + return errormsg logger.debug("Exiting API: verify_bgp_convergence()") return True @@ -1326,7 +1494,7 @@ def verify_as_numbers(tgen, topo, input_dict): return True -@retry(attempts=44, wait=3, return_is_str=True) +@retry(attempts=50, wait=3, return_is_str=True) def verify_bgp_convergence_from_running_config(tgen, dut=None): """ API to verify BGP convergence b/w loopback and physical interface. @@ -1470,7 +1638,7 @@ def clear_bgp_and_verify(tgen, topo, router): sleeptime = 3 # Verifying BGP convergence before bgp clear command - for retry in range(44): + for retry in range(50): # Waiting for BGP to converge logger.info( "Waiting for %s sec for BGP to converge on router" " %s...", @@ -1552,7 +1720,7 @@ def clear_bgp_and_verify(tgen, topo, router): peer_uptime_after_clear_bgp = {} # Verifying BGP convergence after bgp clear command - for retry in range(44): + for retry in range(50): # Waiting for BGP to converge logger.info( @@ -3462,3 +3630,552 @@ def verify_gr_address_family(tgen, topo, addr_type, addr_family, dut): return errormsg logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) + + +@retry(attempts=5, wait=2, return_is_str=True, initial_wait=2) +def verify_attributes_for_evpn_routes( + tgen, + topo, + dut, + input_dict, + rd=None, + rt=None, + ethTag=None, + ipLen=None, + rd_peer=None, + rt_peer=None, +): + """ + API to verify rd and rt value using "sh bgp l2vpn evpn 10.1.1.1" + command. + + Parameters + ---------- + * `tgen`: topogen object + * `topo` : json file data + * `dut` : device under test + * `input_dict`: having details like - for which route, rd value + needs to be verified + * `rd` : route distinguisher + * `rt` : route target + * `ethTag` : Ethernet Tag + * `ipLen` : IP prefix length + * `rd_peer` : Peer name from which RD will be auto-generated + * `rt_peer` : Peer name from which RT will be auto-generated + + Usage + ----- + input_dict_1 = { + "r1": { + "static_routes": [{ + "network": [NETWORK1_1[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED" + }] + } + } + + result = verify_attributes_for_evpn_routes(tgen, topo, + input_dict, rd = "10.0.0.33:1") + + Returns + ------- + errormsg(str) or True + """ + + logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) + for router in input_dict.keys(): + rnode = tgen.routers()[dut] + + if "static_routes" in input_dict[router]: + for static_route in input_dict[router]["static_routes"]: + network = static_route["network"] + + if "vrf" in static_route: + vrf = static_route["vrf"] + + if type(network) is not list: + network = [network] + + for route in network: + route = route.split("/")[0] + _addr_type = validate_ip_address(route) + if "v4" in _addr_type: + input_afi = "v4" + elif "v6" in _addr_type: + input_afi = "v6" + + cmd = "show bgp l2vpn evpn {} json".format(route) + evpn_rd_value_json = run_frr_cmd(rnode, cmd, isjson=True) + if not bool(evpn_rd_value_json): + errormsg = "No output for '{}' cli".format(cmd) + return errormsg + + if rd is not None and rd != "auto": + logger.info( + "[DUT: %s]: Verifying rd value for " "evpn route %s:", + dut, + route, + ) + + if rd in evpn_rd_value_json: + rd_value_json = evpn_rd_value_json[rd] + if rd_value_json["rd"] != rd: + errormsg = ( + "[DUT: %s] Failed: Verifying" + " RD value for EVPN route: %s" + "[FAILED]!!, EXPECTED : %s " + " FOUND : %s" + % (dut, route, rd, rd_value_json["rd"]) + ) + return errormsg + + else: + logger.info( + "[DUT %s]: Verifying RD value for" + " EVPN route: %s [PASSED]|| " + "Found Exprected: %s", + dut, + route, + rd, + ) + return True + + else: + errormsg = ( + "[DUT: %s] RD : %s is not present" + " in cli json output" % (dut, rd) + ) + return errormsg + + if rd == "auto": + logger.info( + "[DUT: %s]: Verifying auto-rd value for " "evpn route %s:", + dut, + route, + ) + + if rd_peer: + index = 1 + vni_dict = {} + + rnode = tgen.routers()[rd_peer] + vrfs = topo["routers"][rd_peer]["vrfs"] + for vrf_dict in vrfs: + vni_dict[vrf_dict["name"]] = index + index += 1 + + show_bgp_json = run_frr_cmd( + rnode, "show bgp vrf all summary json", isjson=True + ) + + # Verifying output dictionary show_bgp_json is empty + if not bool(show_bgp_json): + errormsg = "BGP is not running" + return errormsg + + show_bgp_json_vrf = show_bgp_json[vrf] + for afi, afi_data in show_bgp_json_vrf.items(): + if input_afi not in afi: + continue + router_id = afi_data["routerId"] + + rd = "{}:{}".format(router_id, vni_dict[vrf]) + if rd in evpn_rd_value_json: + rd_value_json = evpn_rd_value_json[rd] + if rd_value_json["rd"] != rd: + errormsg = ( + "[DUT: %s] Failed: Verifying" + " RD value for EVPN route: %s" + "[FAILED]!!, EXPECTED : %s " + " FOUND : %s" + % (dut, route, rd, rd_value_json["rd"]) + ) + return errormsg + + else: + logger.info( + "[DUT %s]: Verifying RD value for" + " EVPN route: %s [PASSED]|| " + "Found Exprected: %s", + dut, + route, + rd, + ) + return True + + else: + errormsg = ( + "[DUT: %s] RD : %s is not present" + " in cli json output" % (dut, rd) + ) + return errormsg + + if rt == "auto": + logger.info( + "[DUT: %s]: Verifying auto-rt value for " "evpn route %s:", + dut, + route, + ) + + if rt_peer: + vni_dict = {} + + rnode = tgen.routers()[rt_peer] + show_bgp_json = run_frr_cmd( + rnode, "show bgp vrf all summary json", isjson=True + ) + + # Verifying output dictionary show_bgp_json is empty + if not bool(show_bgp_json): + errormsg = "BGP is not running" + return errormsg + + show_bgp_json_vrf = show_bgp_json[vrf] + for afi, afi_data in show_bgp_json_vrf.items(): + if input_afi not in afi: + continue + as_num = afi_data["as"] + + show_vrf_vni_json = run_frr_cmd( + rnode, "show vrf vni json", isjson=True + ) + + vrfs = show_vrf_vni_json["vrfs"] + for vrf_dict in vrfs: + if vrf_dict["vrf"] == vrf: + vni_dict[vrf_dict["vrf"]] = str(vrf_dict["vni"]) + + # If AS is 4 byte, FRR uses only the lower 2 bytes of ASN+VNI + # for auto derived RT value. + if as_num > 65535: + as_bin = bin(as_num) + as_bin = as_bin[-16:] + as_num = int(as_bin, 2) + + rt = "{}:{}".format(str(as_num), vni_dict[vrf]) + for _rd, route_data in evpn_rd_value_json.items(): + if route_data["ip"] == route: + for rt_data in route_data["paths"]: + if vni_dict[vrf] == rt_data["VNI"]: + rt_string = rt_data["extendedCommunity"][ + "string" + ] + rt_input = "RT:{}".format(rt) + if rt_input not in rt_string: + errormsg = ( + "[DUT: %s] Failed:" + " Verifying RT " + "value for EVPN " + " route: %s" + "[FAILED]!!," + " EXPECTED : %s " + " FOUND : %s" + % (dut, route, rt_input, rt_string) + ) + return errormsg + + else: + logger.info( + "[DUT %s]: Verifying " + "RT value for EVPN " + "route: %s [PASSED]||" + "Found Exprected: %s", + dut, + route, + rt_input, + ) + return True + + else: + errormsg = ( + "[DUT: %s] Route : %s is not" + " present in cli json output" % (dut, route) + ) + return errormsg + + if rt is not None and rt != "auto": + logger.info( + "[DUT: %s]: Verifying rt value for " "evpn route %s:", + dut, + route, + ) + + if type(rt) is not list: + rt = [rt] + + for _rt in rt: + for _rd, route_data in evpn_rd_value_json.items(): + if route_data["ip"] == route: + for rt_data in route_data["paths"]: + rt_string = rt_data["extendedCommunity"][ + "string" + ] + rt_input = "RT:{}".format(_rt) + if rt_input not in rt_string: + errormsg = ( + "[DUT: %s] Failed: " + "Verifying RT value " + "for EVPN route: %s" + "[FAILED]!!," + " EXPECTED : %s " + " FOUND : %s" + % (dut, route, rt_input, rt_string) + ) + return errormsg + + else: + logger.info( + "[DUT %s]: Verifying RT" + " value for EVPN route:" + " %s [PASSED]|| " + "Found Exprected: %s", + dut, + route, + rt_input, + ) + return True + + else: + errormsg = ( + "[DUT: %s] Route : %s is not" + " present in cli json output" % (dut, route) + ) + return errormsg + + if ethTag is not None: + logger.info( + "[DUT: %s]: Verifying ethTag value for " "evpn route :", dut + ) + + for _rd, route_data in evpn_rd_value_json.items(): + if route_data["ip"] == route: + if route_data["ethTag"] != ethTag: + errormsg = ( + "[DUT: %s] RD: %s, Failed: " + "Verifying ethTag value " + "for EVPN route: %s" + "[FAILED]!!," + " EXPECTED : %s " + " FOUND : %s" + % ( + dut, + _rd, + route, + ethTag, + route_data["ethTag"], + ) + ) + return errormsg + + else: + logger.info( + "[DUT %s]: RD: %s, Verifying " + "ethTag value for EVPN route:" + " %s [PASSED]|| " + "Found Exprected: %s", + dut, + _rd, + route, + ethTag, + ) + return True + + else: + errormsg = ( + "[DUT: %s] RD: %s, Route : %s " + "is not present in cli json " + "output" % (dut, _rd, route) + ) + return errormsg + + if ipLen is not None: + logger.info( + "[DUT: %s]: Verifying ipLen value for " "evpn route :", dut + ) + + for _rd, route_data in evpn_rd_value_json.items(): + if route_data["ip"] == route: + if route_data["ipLen"] != int(ipLen): + errormsg = ( + "[DUT: %s] RD: %s, Failed: " + "Verifying ipLen value " + "for EVPN route: %s" + "[FAILED]!!," + " EXPECTED : %s " + " FOUND : %s" + % (dut, _rd, route, ipLen, route_data["ipLen"]) + ) + return errormsg + + else: + logger.info( + "[DUT %s]: RD: %s, Verifying " + "ipLen value for EVPN route:" + " %s [PASSED]|| " + "Found Exprected: %s", + dut, + _rd, + route, + ipLen, + ) + return True + + else: + errormsg = ( + "[DUT: %s] RD: %s, Route : %s " + "is not present in cli json " + "output " % (dut, route) + ) + return errormsg + + logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) + return False + + +@retry(attempts=5, wait=2, return_is_str=True, initial_wait=2) +def verify_evpn_routes( + tgen, topo, dut, input_dict, routeType=5, EthTag=0, next_hop=None +): + """ + API to verify evpn routes using "sh bgp l2vpn evpn" + command. + + Parameters + ---------- + * `tgen`: topogen object + * `topo` : json file data + * `dut` : device under test + * `input_dict`: having details like - for which route, rd value + needs to be verified + * `route_type` : Route type 5 is supported as of now + * `EthTag` : Ethernet tag, by-default is 0 + * `next_hop` : Prefered nexthop for the evpn routes + + Usage + ----- + input_dict_1 = { + "r1": { + "static_routes": [{ + "network": [NETWORK1_1[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED" + }] + } + } + result = verify_evpn_routes(tgen, topo, input_dict) + + Returns + ------- + errormsg(str) or True + """ + + logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) + + for router in input_dict.keys(): + rnode = tgen.routers()[dut] + + logger.info("[DUT: %s]: Verifying evpn routes: ", dut) + + if "static_routes" in input_dict[router]: + for static_route in input_dict[router]["static_routes"]: + network = static_route["network"] + + if type(network) is not list: + network = [network] + + missing_routes = {} + for route in network: + rd_keys = 0 + ip_len = route.split("/")[1] + route = route.split("/")[0] + + prefix = "[{}]:[{}]:[{}]:[{}]".format( + routeType, EthTag, ip_len, route + ) + + cmd = "show bgp l2vpn evpn route json" + evpn_value_json = run_frr_cmd(rnode, cmd, isjson=True) + + if not bool(evpn_value_json): + errormsg = "No output for '{}' cli".format(cmd) + return errormsg + + if evpn_value_json["numPrefix"] == 0: + errormsg = "[DUT: %s]: No EVPN prefixes exist" % (dut) + return errormsg + + for key, route_data_json in evpn_value_json.items(): + if isinstance(route_data_json, dict): + rd_keys += 1 + if prefix not in route_data_json: + missing_routes[key] = prefix + + if rd_keys == len(missing_routes.keys()): + errormsg = ( + "[DUT: %s]: " + "Missing EVPN routes: " + "%s [FAILED]!!" % (dut, list(set(missing_routes.values()))) + ) + return errormsg + + for key, route_data_json in evpn_value_json.items(): + if isinstance(route_data_json, dict): + if prefix not in route_data_json: + continue + + for paths in route_data_json[prefix]["paths"]: + for path in paths: + if path["routeType"] != routeType: + errormsg = ( + "[DUT: %s]: " + "Verifying routeType " + "for EVPN route: %s " + "[FAILED]!! " + "Expected: %s, " + "Found: %s" + % ( + dut, + prefix, + routeType, + path["routeType"], + ) + ) + return errormsg + + elif next_hop: + for nh_dict in path["nexthops"]: + if nh_dict["ip"] != next_hop: + errormsg = ( + "[DUT: %s]: " + "Verifying " + "nexthop for " + "EVPN route: %s" + "[FAILED]!! " + "Expected: %s," + " Found: %s" + % ( + dut, + prefix, + next_hop, + nh_dict["ip"], + ) + ) + return errormsg + + else: + logger.info( + "[DUT %s]: Verifying " + "EVPN route : %s, " + "routeType: %s is " + "installed " + "[PASSED]|| ", + dut, + prefix, + routeType, + ) + return True + + logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) + + return False diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py index fb82b50628..156a5f7ea4 100644 --- a/tests/topotests/lib/common_config.py +++ b/tests/topotests/lib/common_config.py @@ -690,6 +690,12 @@ def start_topology(tgen): router_list = tgen.routers() for rname in ROUTER_LIST: router = router_list[rname] + + # It will help in debugging the failures, will give more details on which + # specific kernel version tests are failing + linux_ver = router.run("uname -a") + logger.info("Logging platform related details: \n %s \n", linux_ver) + try: os.chdir(TMPDIR) @@ -927,6 +933,16 @@ def create_vrf_cfg(tgen, topo, input_dict=None, build=False): ) rnode.run(cmd) + if vni: + config_data.append("vrf {}".format(vrf["name"])) + cmd = "vni {}".format(vni) + config_data.append(cmd) + + if del_vni: + config_data.append("vrf {}".format(vrf["name"])) + cmd = "no vni {}".format(del_vni) + config_data.append(cmd) + result = create_common_configuration( tgen, c_router, config_data, "vrf", build=build ) @@ -978,6 +994,34 @@ def create_interface_in_kernel( rnode.run(cmd) +def shutdown_bringup_interface_in_kernel(tgen, dut, intf_name, ifaceaction=False): + """ + Cretae interfaces in kernel for ipv4/ipv6 + Config is done in Linux Kernel: + + Parameters + ---------- + * `tgen` : Topogen object + * `dut` : Device for which interfaces to be added + * `intf_name` : interface name + * `ifaceaction` : False to shutdown and True to bringup the + ineterface + """ + + rnode = tgen.routers()[dut] + + cmd = "ip link set dev" + if ifaceaction: + action = "up" + cmd = "{} {} {}".format(cmd, intf_name, action) + else: + action = "down" + cmd = "{} {} {}".format(cmd, intf_name, action) + + logger.info("[DUT: %s]: Running command: %s", dut, cmd) + rnode.run(cmd) + + def validate_ip_address(ip_address): """ Validates the type of ip address @@ -1036,7 +1080,7 @@ def check_address_types(addr_type=None): return addr_types if addr_type not in addr_types: - logger.error( + logger.debug( "{} not in supported/configured address types {}".format( addr_type, addr_types ) @@ -1726,6 +1770,7 @@ def create_route_maps(tgen, input_dict, build=False): set_action = set_data.setdefault("set_action", None) nexthop = set_data.setdefault("nexthop", None) origin = set_data.setdefault("origin", None) + ext_comm_list = set_data.setdefault("extcommunity", {}) # Local Preference if local_preference: @@ -1790,6 +1835,19 @@ def create_route_maps(tgen, input_dict, build=False): logger.error("In large_comm_list 'id' not" " provided") return False + if ext_comm_list: + rt = ext_comm_list.setdefault("rt", None) + del_comm = ext_comm_list.setdefault("delete", None) + if rt: + cmd = "set extcommunity rt {}".format(rt) + if del_comm: + cmd = "{} delete".format(cmd) + + rmap_data.append(cmd) + else: + logger.debug("In ext_comm_list 'rt' not" " provided") + return False + # Weight if weight: rmap_data.append("set weight {}".format(weight)) @@ -2145,6 +2203,243 @@ def addKernelRoute( return True +def configure_vxlan(tgen, input_dict): + """ + Add and configure vxlan + + * `tgen`: tgen onject + * `input_dict` : data for vxlan config + + Usage: + ------ + input_dict= { + "dcg2":{ + "vxlan":[{ + "vxlan_name": "vxlan75100", + "vxlan_id": "75100", + "dstport": 4789, + "local_addr": "120.0.0.1", + "learning": "no", + "delete": True + }] + } + } + + configure_vxlan(tgen, input_dict) + + Returns: + ------- + True or errormsg + + """ + + logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) + + router_list = tgen.routers() + for dut in input_dict.keys(): + rnode = tgen.routers()[dut] + + if "vxlan" in input_dict[dut]: + for vxlan_dict in input_dict[dut]["vxlan"]: + cmd = "ip link " + + del_vxlan = vxlan_dict.setdefault("delete", None) + vxlan_names = vxlan_dict.setdefault("vxlan_name", []) + vxlan_ids = vxlan_dict.setdefault("vxlan_id", []) + dstport = vxlan_dict.setdefault("dstport", None) + local_addr = vxlan_dict.setdefault("local_addr", None) + learning = vxlan_dict.setdefault("learning", None) + + config_data = [] + if vxlan_names and vxlan_ids: + for vxlan_name, vxlan_id in zip(vxlan_names, vxlan_ids): + cmd = "ip link" + + if del_vxlan: + cmd = "{} del {} type vxlan id {}".format( + cmd, vxlan_name, vxlan_id + ) + else: + cmd = "{} add {} type vxlan id {}".format( + cmd, vxlan_name, vxlan_id + ) + + if dstport: + cmd = "{} dstport {}".format(cmd, dstport) + + if local_addr: + ip_cmd = "ip addr add {} dev {}".format( + local_addr, vxlan_name + ) + if del_vxlan: + ip_cmd = "ip addr del {} dev {}".format( + local_addr, vxlan_name + ) + + config_data.append(ip_cmd) + + cmd = "{} local {}".format(cmd, local_addr) + + if learning == "no": + cmd = "{} {} learning".format(cmd, learning) + + elif learning == "yes": + cmd = "{} learning".format(cmd) + + config_data.append(cmd) + + try: + for _cmd in config_data: + logger.info("[DUT: %s]: Running command: %s", dut, _cmd) + rnode.run(_cmd) + + except InvalidCLIError: + # Traceback + errormsg = traceback.format_exc() + logger.error(errormsg) + return errormsg + + logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) + + return True + + +def configure_brctl(tgen, topo, input_dict): + """ + Add and configure brctl + + * `tgen`: tgen onject + * `input_dict` : data for brctl config + + Usage: + ------ + input_dict= { + dut:{ + "brctl": [{ + "brctl_name": "br100", + "addvxlan": "vxlan75100", + "vrf": "RED", + "stp": "off" + }] + } + } + + configure_brctl(tgen, topo, input_dict) + + Returns: + ------- + True or errormsg + + """ + + logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) + + router_list = tgen.routers() + for dut in input_dict.keys(): + rnode = tgen.routers()[dut] + + if "brctl" in input_dict[dut]: + for brctl_dict in input_dict[dut]["brctl"]: + + brctl_names = brctl_dict.setdefault("brctl_name", []) + addvxlans = brctl_dict.setdefault("addvxlan", []) + stp_values = brctl_dict.setdefault("stp", []) + vrfs = brctl_dict.setdefault("vrf", []) + + ip_cmd = "ip link set" + for brctl_name, vxlan, vrf, stp in zip( + brctl_names, addvxlans, vrfs, stp_values + ): + + ip_cmd_list = [] + cmd = "ip link add name {} type bridge stp_state {}".format(brctl_name, stp) + + logger.info("[DUT: %s]: Running command: %s", dut, cmd) + rnode.run(cmd) + + ip_cmd_list.append("{} up dev {}".format(ip_cmd, brctl_name)) + + if vxlan: + cmd = "{} dev {} master {}".format(ip_cmd, vxlan, brctl_name) + + logger.info("[DUT: %s]: Running command: %s", dut, cmd) + rnode.run(cmd) + + ip_cmd_list.append("{} up dev {}".format(ip_cmd, vxlan)) + + if vrf: + ip_cmd_list.append( + "{} dev {} master {}".format(ip_cmd, brctl_name, vrf) + ) + + for intf_name, data in topo["routers"][dut]["links"].items(): + if "vrf" not in data: + continue + + if data["vrf"] == vrf: + ip_cmd_list.append( + "{} up dev {}".format(ip_cmd, data["interface"]) + ) + + try: + for _ip_cmd in ip_cmd_list: + logger.info("[DUT: %s]: Running command: %s", dut, _ip_cmd) + rnode.run(_ip_cmd) + + except InvalidCLIError: + # Traceback + errormsg = traceback.format_exc() + logger.error(errormsg) + return errormsg + + logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) + return True + + +def configure_interface_mac(tgen, input_dict): + """ + Add and configure brctl + + * `tgen`: tgen onject + * `input_dict` : data for mac config + + input_mac= { + "edge1":{ + "br75100": "00:80:48:BA:d1:00, + "br75200": "00:80:48:BA:d1:00 + } + } + + configure_interface_mac(tgen, input_mac) + + Returns: + ------- + True or errormsg + + """ + + router_list = tgen.routers() + for dut in input_dict.keys(): + rnode = tgen.routers()[dut] + + for intf, mac in input_dict[dut].items(): + cmd = "ifconfig {} hw ether {}".format(intf, mac) + logger.info("[DUT: %s]: Running command: %s", dut, cmd) + + try: + result = rnode.run(cmd) + if len(result) != 0: + return result + + except InvalidCLIError: + # Traceback + errormsg = traceback.format_exc() + logger.error(errormsg) + return errormsg + + return True + + ############################################# # Verification APIs ############################################# @@ -2869,3 +3164,283 @@ def verify_create_community_list(tgen, input_dict): logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) return True + + +def verify_cli_json(tgen, input_dict): + """ + API to verify if JSON is available for clis + command. + + Parameters + ---------- + * `tgen`: topogen object + * `input_dict`: CLIs for which JSON needs to be verified + Usage + ----- + input_dict = { + "edge1":{ + "cli": ["show evpn vni detail", show evpn rmac vni all] + } + } + + result = verify_cli_json(tgen, input_dict) + + Returns + ------- + errormsg(str) or True + """ + + logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) + for dut in input_dict.keys(): + rnode = tgen.routers()[dut] + + for cli in input_dict[dut]["cli"]: + logger.info( + "[DUT: %s]: Verifying JSON is available for " "CLI %s :", dut, cli + ) + + test_cli = "{} json".format(cli) + ret_json = rnode.vtysh_cmd(test_cli, isjson=True) + if not bool(ret_json): + errormsg = "CLI: %s, JSON format is not available" % (cli) + return errormsg + elif "unknown" in ret_json or "Unknown" in ret_json: + errormsg = "CLI: %s, JSON format is not available" % (cli) + return errormsg + else: + logger.info( + "CLI : %s JSON format is available: " "\n %s", cli, ret_json + ) + + logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) + + return True + + +@retry(attempts=2, wait=4, return_is_str=True, initial_wait=2) +def verify_evpn_vni(tgen, input_dict): + """ + API to verify evpn vni details using "show evpn vni detail json" + command. + + Parameters + ---------- + * `tgen`: topogen object + * `input_dict`: having details like - for which router, evpn details + needs to be verified + Usage + ----- + input_dict = { + "edge1":{ + "vni": [ + { + "75100":{ + "vrf": "RED", + "vxlanIntf": "vxlan75100", + "localVtepIp": "120.1.1.1", + "sviIntf": "br100" + } + } + ] + } + } + + result = verify_evpn_vni(tgen, input_dict) + + Returns + ------- + errormsg(str) or True + """ + + logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) + for dut in input_dict.keys(): + rnode = tgen.routers()[dut] + + logger.info("[DUT: %s]: Verifying evpn vni details :", dut) + + cmd = "show evpn vni detail json" + evpn_all_vni_json = run_frr_cmd(rnode, cmd, isjson=True) + if not bool(evpn_all_vni_json): + errormsg = "No output for '{}' cli".format(cmd) + return errormsg + + if "vni" in input_dict[dut]: + for vni_dict in input_dict[dut]["vni"]: + found = False + vni = vni_dict["name"] + for evpn_vni_json in evpn_all_vni_json: + if "vni" in evpn_vni_json: + if evpn_vni_json["vni"] != int(vni): + continue + + for attribute in vni_dict.keys(): + if vni_dict[attribute] != evpn_vni_json[attribute]: + errormsg = ( + "[DUT: %s] Verifying " + "%s for VNI: %s [FAILED]||" + ", EXPECTED : %s " + " FOUND : %s" + % ( + dut, + attribute, + vni, + vni_dict[attribute], + evpn_vni_json[attribute], + ) + ) + return errormsg + + else: + found = True + logger.info( + "[DUT: %s] Verifying" + " %s for VNI: %s , " + "Found Expected : %s ", + dut, + attribute, + vni, + evpn_vni_json[attribute], + ) + + if evpn_vni_json["state"] != "Up": + errormsg = ( + "[DUT: %s] Failed: Verifying" + " State for VNI: %s is not Up" % (dut, vni) + ) + return errormsg + + else: + errormsg = ( + "[DUT: %s] Failed:" + " VNI: %s is not present in JSON" % (dut, vni) + ) + return errormsg + + if found: + logger.info( + "[DUT %s]: Verifying VNI : %s " + "details and state is Up [PASSED]!!", + dut, + vni, + ) + return True + + else: + errormsg = ( + "[DUT: %s] Failed:" " vni details are not present in input data" % (dut) + ) + return errormsg + + logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) + return False + + +@retry(attempts=2, wait=4, return_is_str=True, initial_wait=2) +def verify_vrf_vni(tgen, input_dict): + """ + API to verify vrf vni details using "show vrf vni json" + command. + + Parameters + ---------- + * `tgen`: topogen object + * `input_dict`: having details like - for which router, evpn details + needs to be verified + Usage + ----- + input_dict = { + "edge1":{ + "vrfs": [ + { + "RED":{ + "vni": 75000, + "vxlanIntf": "vxlan75100", + "sviIntf": "br100", + "routerMac": "00:80:48:ba:d1:00", + "state": "Up" + } + } + ] + } + } + + result = verify_vrf_vni(tgen, input_dict) + + Returns + ------- + errormsg(str) or True + """ + + logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) + for dut in input_dict.keys(): + rnode = tgen.routers()[dut] + + logger.info("[DUT: %s]: Verifying vrf vni details :", dut) + + cmd = "show vrf vni json" + vrf_all_vni_json = run_frr_cmd(rnode, cmd, isjson=True) + if not bool(vrf_all_vni_json): + errormsg = "No output for '{}' cli".format(cmd) + return errormsg + + if "vrfs" in input_dict[dut]: + for vrfs in input_dict[dut]["vrfs"]: + for vrf, vrf_dict in vrfs.items(): + found = False + for vrf_vni_json in vrf_all_vni_json["vrfs"]: + if "vrf" in vrf_vni_json: + if vrf_vni_json["vrf"] != vrf: + continue + + for attribute in vrf_dict.keys(): + if vrf_dict[attribute] == vrf_vni_json[attribute]: + found = True + logger.info( + "[DUT %s]: VRF: %s, " + "verifying %s " + ", Found Expected: %s " + "[PASSED]!!", + dut, + vrf, + attribute, + vrf_vni_json[attribute], + ) + else: + errormsg = ( + "[DUT: %s] VRF: %s, " + "verifying %s [FAILED!!] " + ", EXPECTED : %s " + ", FOUND : %s" + % ( + dut, + vrf, + attribute, + vrf_dict[attribute], + vrf_vni_json[attribute], + ) + ) + return errormsg + + else: + errormsg = "[DUT: %s] VRF: %s " "is not present in JSON" % ( + dut, + vrf, + ) + return errormsg + + if found: + logger.info( + "[DUT %s] Verifying VRF: %s " " details [PASSED]!!", + dut, + vrf, + ) + return True + + else: + errormsg = ( + "[DUT: %s] Failed:" " vrf details are not present in input data" % (dut) + ) + return errormsg + + logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) + return False diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py index bffb8208e7..b5fa2ea59b 100644 --- a/tests/topotests/lib/topotest.py +++ b/tests/topotests/lib/topotest.py @@ -35,6 +35,7 @@ import tempfile import platform import difflib import time +import signal from lib.topolog import logger from copy import deepcopy @@ -51,6 +52,35 @@ from mininet.log import setLogLevel, info from mininet.cli import CLI from mininet.link import Intf +def gdb_core(obj, daemon, corefiles): + gdbcmds = ''' + info threads + bt full + disassemble + up + disassemble + up + disassemble + up + disassemble + up + disassemble + up + disassemble + ''' + gdbcmds = [['-ex', i.strip()] for i in gdbcmds.strip().split('\n')] + gdbcmds = [item for sl in gdbcmds for item in sl] + + daemon_path = os.path.join(obj.daemondir, daemon) + backtrace = subprocess.check_output( + ['gdb', daemon_path, corefiles[0], '--batch'] + gdbcmds + ) + sys.stderr.write( + "\n%s: %s crashed. Core file found - Backtrace follows:\n" + % (obj.name, daemon) + ) + sys.stderr.write("%s" % backtrace) + return backtrace class json_cmp_result(object): "json_cmp result class for better assertion messages" @@ -422,6 +452,10 @@ def pid_exists(pid): if pid <= 0: return False try: + os.waitpid(pid, os.WNOHANG) + except: + pass + try: os.kill(pid, 0) except OSError as err: if err.errno == errno.ESRCH: @@ -992,8 +1026,8 @@ class Router(Node): os.system("chmod -R go+rw /tmp/topotests") # Return count of running daemons - def countDaemons(self): - numRunning = 0 + def listDaemons(self): + ret = [] rundaemons = self.cmd("ls -1 /var/run/%s/*.pid" % self.routertype) errors = "" if re.search(r"No such file or directory", rundaemons): @@ -1002,12 +1036,11 @@ class Router(Node): for d in StringIO.StringIO(rundaemons): daemonpid = self.cmd("cat %s" % d.rstrip()).rstrip() if daemonpid.isdigit() and pid_exists(int(daemonpid)): - numRunning += 1 - return numRunning + ret.append(os.path.basename(d.rstrip().rsplit(".", 1)[0])) + return ret def stopRouter(self, wait=True, assertOnError=True, minErrorVersion="5.1"): # Stop Running FRR Daemons - numRunning = 0 rundaemons = self.cmd("ls -1 /var/run/%s/*.pid" % self.routertype) errors = "" if re.search(r"No such file or directory", rundaemons): @@ -1016,24 +1049,36 @@ class Router(Node): for d in StringIO.StringIO(rundaemons): daemonpid = self.cmd("cat %s" % d.rstrip()).rstrip() if daemonpid.isdigit() and pid_exists(int(daemonpid)): + daemonname = os.path.basename(d.rstrip().rsplit(".", 1)[0]) logger.info( "{}: stopping {}".format( - self.name, os.path.basename(d.rstrip().rsplit(".", 1)[0]) + self.name, daemonname ) ) - self.cmd("kill -TERM %s" % daemonpid) - self.waitOutput() - if pid_exists(int(daemonpid)): - numRunning += 1 - - if wait and numRunning > 0: - counter = 5 - while counter > 0 and numRunning > 0: - sleep(2, "{}: waiting for daemons stopping".format(self.name)) - numRunning = self.countDaemons() + try: + os.kill(int(daemonpid), signal.SIGTERM) + except OSError as err: + if err.errno == errno.ESRCH: + logger.error("{}: {} left a dead pidfile (pid={})".format(self.name, daemonname, daemonpid)) + else: + logger.info("{}: {} could not kill pid {}: {}".format(self.name, daemonname, daemonpid, str(err))) + + if not wait: + return errors + + running = self.listDaemons() + + if running: + sleep(0.1, "{}: waiting for daemons stopping: {}".format(self.name, ', '.join(running))) + running = self.listDaemons() + + counter = 20 + while counter > 0 and running: + sleep(0.5, "{}: waiting for daemons stopping: {}".format(self.name, ', '.join(running))) + running = self.listDaemons() counter -= 1 - if wait and numRunning > 0: + if running: # 2nd round of kill if daemons didn't exit for d in StringIO.StringIO(rundaemons): daemonpid = self.cmd("cat %s" % d.rstrip()).rstrip() @@ -1048,13 +1093,15 @@ class Router(Node): self.waitOutput() self.cmd("rm -- {}".format(d.rstrip())) - if wait: - errors = self.checkRouterCores(reportOnce=True) - if self.checkRouterVersion("<", minErrorVersion): - # ignore errors in old versions - errors = "" - if assertOnError and len(errors) > 0: - assert "Errors found - details follow:" == 0, errors + if not wait: + return errors + + errors = self.checkRouterCores(reportOnce=True) + if self.checkRouterVersion("<", minErrorVersion): + # ignore errors in old versions + errors = "" + if assertOnError and len(errors) > 0: + assert "Errors found - details follow:" == 0, errors return errors def removeIPs(self): @@ -1348,20 +1395,7 @@ class Router(Node): "{}/{}/{}_core*.dmp".format(self.logdir, self.name, daemon) ) if len(corefiles) > 0: - daemon_path = os.path.join(self.daemondir, daemon) - backtrace = subprocess.check_output( - [ - "gdb {} {} --batch -ex bt 2> /dev/null".format( - daemon_path, corefiles[0] - ) - ], - shell=True, - ) - sys.stderr.write( - "\n%s: %s crashed. Core file found - Backtrace follows:\n" - % (self.name, daemon) - ) - sys.stderr.write("%s" % backtrace) + backtrace = gdb_core(self, daemon, corefiles) traces = ( traces + "\n%s: %s crashed. Core file found - Backtrace follows:\n%s" @@ -1431,20 +1465,7 @@ class Router(Node): "{}/{}/{}_core*.dmp".format(self.logdir, self.name, daemon) ) if len(corefiles) > 0: - daemon_path = os.path.join(self.daemondir, daemon) - backtrace = subprocess.check_output( - [ - "gdb {} {} --batch -ex bt 2> /dev/null".format( - daemon_path, corefiles[0] - ) - ], - shell=True, - ) - sys.stderr.write( - "\n%s: %s crashed. Core file found - Backtrace follows:\n" - % (self.name, daemon) - ) - sys.stderr.write("%s\n" % backtrace) + gdb_core(self, daemon, corefiles) else: # No core found - If we find matching logfile in /tmp, then print last 20 lines from it. if os.path.isfile( diff --git a/tests/topotests/pbr-topo1/r1/pbr-map.json b/tests/topotests/pbr-topo1/r1/pbr-map.json index f0738dc540..bfa0ecb849 100644 --- a/tests/topotests/pbr-topo1/r1/pbr-map.json +++ b/tests/topotests/pbr-topo1/r1/pbr-map.json @@ -62,6 +62,32 @@ }, "matchDst":"dead:beef::\/64", "matchMark":314159 + }, + { + "sequenceNumber":15, + "vrfUnchanged":false, + "installed":true, + "installedReason":"Valid", + "nexthopGroup":{ + "name":"ASAKUSA15", + "installed":true, + "installedInternally":1 + }, + "matchDst":"dead:beef::/64", + "matchDscp":10 + }, + { + "sequenceNumber":20, + "vrfUnchanged":false, + "installed":true, + "installedReason":"Valid", + "nexthopGroup":{ + "name":"ASAKUSA20", + "installed":true, + "installedInternally":1 + }, + "matchDst":"dead:beef::/64", + "matchEcn":1 } ] }, diff --git a/tests/topotests/pbr-topo1/r1/pbrd.conf b/tests/topotests/pbr-topo1/r1/pbrd.conf index 298cba2860..45cb7656ab 100644 --- a/tests/topotests/pbr-topo1/r1/pbrd.conf +++ b/tests/topotests/pbr-topo1/r1/pbrd.conf @@ -73,6 +73,16 @@ pbr-map ASAKUSA seq 10 match mark 314159 set nexthop c0ff:ee::1 ! +pbr-map ASAKUSA seq 15 + match dst-ip dead:beef::/64 + match dscp af11 + set nexthop c0ff:ee::1 +! +pbr-map ASAKUSA seq 20 + match dst-ip dead:beef::/64 + match ecn 1 + set nexthop c0ff:ee::1 +! # Interface policies int r1-eth1 pbr-policy EVA diff --git a/tools/etc/frr/daemons b/tools/etc/frr/daemons index 8bec3c5bb6..0221b0c19e 100644 --- a/tools/etc/frr/daemons +++ b/tools/etc/frr/daemons @@ -72,6 +72,11 @@ vrrpd_options=" -A 127.0.0.1" # The list of daemons to watch is automatically generated by the init script. #watchfrr_options="" +# To make watchfrr create/join the specified netns, use the following option: +#watchfrr_options="--netns" +# This only has an effect in /etc/frr/<somename>/daemons, and you need to +# start FRR with "/usr/lib/frr/frrinit.sh start <somename>". + # for debugging purposes, you can specify a "wrap" command to start instead # of starting the daemon directly, e.g. to use valgrind on ospfd: # ospfd_wrap="/usr/bin/valgrind" diff --git a/tools/frr-reload.py b/tools/frr-reload.py index 9e86cf2156..05410e3c25 100755 --- a/tools/frr-reload.py +++ b/tools/frr-reload.py @@ -63,14 +63,17 @@ class VtyshException(Exception): pass class Vtysh(object): - def __init__(self, bindir=None, confdir=None, sockdir=None): + def __init__(self, bindir=None, confdir=None, sockdir=None, pathspace=None): self.bindir = bindir self.confdir = confdir + self.pathspace = pathspace self.common_args = [os.path.join(bindir or '', 'vtysh')] if confdir: self.common_args.extend(['--config_dir', confdir]) if sockdir: self.common_args.extend(['--vty_socket', sockdir]) + if pathspace: + self.common_args.extend(['-N', pathspace]) def _call(self, args, stdin=None, stdout=None, stderr=None): kwargs = {} @@ -729,6 +732,36 @@ def line_exist(lines, target_ctx_keys, target_line, exact_match=True): return True return False +def check_for_exit_vrf(lines_to_add, lines_to_del): + + # exit-vrf is a bit tricky. If the new config is missing it but we + # have configs under a vrf, we need to add it at the end to do the + # right context changes. If exit-vrf exists in both the running and + # new config, we cannot delete it or it will break context changes. + add_exit_vrf = False + index = 0 + + for (ctx_keys, line) in lines_to_add: + if add_exit_vrf == True: + if ctx_keys[0] != prior_ctx_key: + insert_key=(prior_ctx_key), + lines_to_add.insert(index, ((insert_key, "exit-vrf"))) + add_exit_vrf = False + + if ctx_keys[0].startswith('vrf') and line: + if line is not "exit-vrf": + add_exit_vrf = True + prior_ctx_key = (ctx_keys[0]) + else: + add_exit_vrf = False + index+=1 + + for (ctx_keys, line) in lines_to_del: + if line == "exit-vrf": + if (line_exist(lines_to_add, ctx_keys, line)): + lines_to_del.remove((ctx_keys, line)) + + return (lines_to_add, lines_to_del) def ignore_delete_re_add_lines(lines_to_add, lines_to_del): @@ -1156,6 +1189,7 @@ def compare_context_objects(newconf, running): for line in newconf_ctx.lines: lines_to_add.append((newconf_ctx_keys, line)) + (lines_to_add, lines_to_del) = check_for_exit_vrf(lines_to_add, lines_to_del) (lines_to_add, lines_to_del) = ignore_delete_re_add_lines(lines_to_add, lines_to_del) (lines_to_add, lines_to_del) = ignore_unconfigurable_lines(lines_to_add, lines_to_del) @@ -1171,6 +1205,7 @@ if __name__ == '__main__': group.add_argument('--test', action='store_true', help='Show the deltas', default=False) parser.add_argument('--debug', action='store_true', help='Enable debugs', default=False) parser.add_argument('--stdout', action='store_true', help='Log to STDOUT', default=False) + parser.add_argument('--pathspace', '-N', metavar='NAME', help='Reload specified path/namespace', default=None) parser.add_argument('filename', help='Location of new frr config file') parser.add_argument('--overwrite', action='store_true', help='Overwrite frr.conf with running config output', default=False) parser.add_argument('--bindir', help='path to the vtysh executable', default='/usr/bin') @@ -1246,10 +1281,13 @@ if __name__ == '__main__': log.error(msg) sys.exit(1) - vtysh = Vtysh(args.bindir, args.confdir, args.vty_socket) + vtysh = Vtysh(args.bindir, args.confdir, args.vty_socket, args.pathspace) # Verify that 'service integrated-vtysh-config' is configured - vtysh_filename = args.confdir + '/vtysh.conf' + if args.pathspace: + vtysh_filename = args.confdir + '/' + args.pathspace + '/vtysh.conf' + else: + vtysh_filename = args.confdir + '/vtysh.conf' service_integrated_vtysh_config = True if os.path.isfile(vtysh_filename): diff --git a/tools/frr.in b/tools/frr.in index 40862aa4c9..b860797d5b 100755 --- a/tools/frr.in +++ b/tools/frr.in @@ -77,7 +77,7 @@ vtysh_b () { # Rember, that all variables have been incremented by 1 in convert_daemon_prios() if [ "$vtysh_enable" = 2 -a -f $C_PATH/frr.conf ]; then - $VTYSH -b -n + $VTYSH -b fi } diff --git a/tools/frr@.service b/tools/frr@.service new file mode 100644 index 0000000000..0fa41c74a3 --- /dev/null +++ b/tools/frr@.service @@ -0,0 +1,25 @@ +[Unit] +Description=FRRouting +Documentation=https://frrouting.readthedocs.io/en/latest/setup.html +Wants=network.target +After=network-pre.target systemd-sysctl.service +Before=network.target +OnFailure=heartbeat-failed@%n.service + +[Service] +Nice=-5 +Type=forking +NotifyAccess=all +StartLimitInterval=3m +StartLimitBurst=3 +TimeoutSec=2m +WatchdogSec=60s +RestartSec=5 +Restart=on-abnormal +LimitNOFILE=1024 +ExecStart=/usr/lib/frr/frrinit.sh start %I +ExecStop=/usr/lib/frr/frrinit.sh stop %I +ExecReload=/usr/lib/frr/frrinit.sh reload %I + +[Install] +WantedBy=multi-user.target diff --git a/tools/frrcommon.sh.in b/tools/frrcommon.sh.in index 2955f74ce3..9a144b2b06 100644 --- a/tools/frrcommon.sh.in +++ b/tools/frrcommon.sh.in @@ -16,10 +16,14 @@ # # This script should be installed in @CFG_SBIN@/frrcommon.sh +# FRR_PATHSPACE is passed in from watchfrr +suffix="${FRR_PATHSPACE:+/${FRR_PATHSPACE}}" +nsopt="${FRR_PATHSPACE:+-N ${FRR_PATHSPACE}}" + PATH=/bin:/usr/bin:/sbin:/usr/sbin D_PATH="@CFG_SBIN@" # /usr/lib/frr -C_PATH="@CFG_SYSCONF@" # /etc/frr -V_PATH="@CFG_STATE@" # /var/run/frr +C_PATH="@CFG_SYSCONF@${suffix}" # /etc/frr +V_PATH="@CFG_STATE@${suffix}" # /var/run/frr VTYSH="@vtysh_bin@" # /usr/bin/vtysh FRR_USER="@enable_user@" # frr FRR_GROUP="@enable_group@" # frr @@ -61,9 +65,9 @@ vtysh_b () { [ "$1" = "watchfrr" ] && return 0 [ -r "$C_PATH/frr.conf" ] || return 0 if [ -n "$1" ]; then - "$VTYSH" -b -n -d "$1" + "$VTYSH" `echo $nsopt` -b -d "$1" else - "$VTYSH" -b -n + "$VTYSH" `echo $nsopt` -b fi } @@ -156,7 +160,7 @@ daemon_start() { instopt="${inst:+-n $inst}" eval args="\$${daemon}_options" - if eval "$all_wrap $wrap $bin -d $frr_global_options $instopt $args"; then + if eval "$all_wrap $wrap $bin $nsopt -d $frr_global_options $instopt $args"; then log_success_msg "Started $dmninst" vtysh_b "$daemon" else @@ -292,9 +296,11 @@ load_old_config() { } . "$C_PATH/daemons" -load_old_config "$C_PATH/daemons.conf" -load_old_config "/etc/default/frr" -load_old_config "/etc/sysconfig/frr" +if [ -z "$FRR_PATHSPACE" ]; then + load_old_config "$C_PATH/daemons.conf" + load_old_config "/etc/default/frr" + load_old_config "/etc/sysconfig/frr" +fi if { declare -p watchfrr_options 2>/dev/null || true; } | grep -q '^declare \-a'; then log_warning_msg "watchfrr_options contains a bash array value." \ diff --git a/tools/frrinit.sh.in b/tools/frrinit.sh.in index 423d6b9b1d..539ab7d816 100644 --- a/tools/frrinit.sh.in +++ b/tools/frrinit.sh.in @@ -30,6 +30,9 @@ else } fi +# "/usr/lib/frr/frrinit.sh start somenamespace" +FRR_PATHSPACE="$2" + self="`dirname $0`" if [ -r "$self/frrcommon.sh" ]; then . "$self/frrcommon.sh" @@ -105,7 +108,7 @@ reload) NEW_CONFIG_FILE="${2:-$C_PATH/frr.conf}" [ ! -r $NEW_CONFIG_FILE ] && log_failure_msg "Unable to read new configuration file $NEW_CONFIG_FILE" && exit 1 - "$RELOAD_SCRIPT" --reload "$NEW_CONFIG_FILE" + "$RELOAD_SCRIPT" --reload "$NEW_CONFIG_FILE" `echo $nsopt` exit $? ;; diff --git a/tools/gcc-plugins/README.md b/tools/gcc-plugins/README.md index 94a9635e76..ab31d0e636 100644 --- a/tools/gcc-plugins/README.md +++ b/tools/gcc-plugins/README.md @@ -20,11 +20,14 @@ Can be found at [https://deb.nox.tf/devel/]. GCC requirements ---------------- -To use this plugin, you need a **patched 9.3.0** version of GCC using the -[gcc-retain-typeinfo.patch] provided in this repo. Without this patch, GCC -strips type information too early during compilation, leaving to the plugin -being unable to perform more meaningful type checks. (Specifically, all -`typedef` types will be "cooked down" to their final type.) +To use this plugin, you need a **patched 9.3.0** or a **patched 10.1.0** +version of GCC using the [gcc-retain-typeinfo.patch] provided in this repo. + +Without this patch, GCC strips type information too early during compilation, +leaving to the plugin being unable to perform more meaningful type checks. +(Specifically, all `typedef` casts will be "cooked down" to their final type.) +If the patch is missing, `format-test.c` will show 4 false negative/positive +warnings marked with `(need retain-typeinfo patch)`. (@eqvinox has discussed this one-line diff with some GCC people on their IRC channel around mid 2019, the consensus was that the line is an "early @@ -32,7 +35,7 @@ optimization" and removing it should not be harmful. However, doing so is likely to break GCC's unit tests since warnings would print different types.) Other versions of gcc are not supported. gcc 8 previously did work but isn't -actively tested/maintained. gcc 10 is not supported yet but may work. +actively tested/maintained. Usage diff --git a/tools/gcc-plugins/debian/changelog b/tools/gcc-plugins/debian/changelog index 62bbbcd46f..a772803b1c 100644 --- a/tools/gcc-plugins/debian/changelog +++ b/tools/gcc-plugins/debian/changelog @@ -1,3 +1,9 @@ +gcc-frr-plugin (9.3.0d15+equi1) unstable; urgency=medium + + * update & rebuild for gcc 9.3.0-15+equi1 + + -- David Lamparter <equinox-debian@diac24.net> Tue, 14 Jul 2020 19:49:24 +0200 + gcc-frr-plugin (9.3.0d8+equi2) unstable; urgency=medium * package created (+equi1 used during development, never released.) diff --git a/tools/gcc-plugins/debian/control b/tools/gcc-plugins/debian/control index 6a9b886bef..b9b5134b46 100644 --- a/tools/gcc-plugins/debian/control +++ b/tools/gcc-plugins/debian/control @@ -3,7 +3,7 @@ Section: devel Priority: optional Maintainer: David Lamparter <equinox-debian@diac24.net> Build-Depends: - gcc-9-plugin-dev (=9.3.0-8+equi1), + gcc-9-plugin-dev (=9.3.0-15+equi1), debhelper (>= 12) Standards-Version: 4.4.1 Homepage: https://www.frrouting.org/ @@ -13,7 +13,7 @@ Vcs-Git: https://github.com/FRRouting/frr.git Package: gcc-9-frr-plugin Architecture: linux-any Depends: - gcc-9 (=9.3.0-8+equi1), + gcc-9 (=9.3.0-15+equi1), ${misc:Depends}, ${shlibs:Depends} Description: GCC plugin for FRRouting diff --git a/tools/gcc-plugins/debian/source/format b/tools/gcc-plugins/debian/source/format index af745b310b..89ae9db8f8 100644 --- a/tools/gcc-plugins/debian/source/format +++ b/tools/gcc-plugins/debian/source/format @@ -1 +1 @@ -3.0 (git) +3.0 (native) diff --git a/tools/gcc-plugins/format-test.c b/tools/gcc-plugins/format-test.c index b031ca5ece..fb7e41c7be 100644 --- a/tools/gcc-plugins/format-test.c +++ b/tools/gcc-plugins/format-test.c @@ -82,6 +82,12 @@ int test(unsigned long long ay) testfn("%Ld", v_pid_t); // WARN testfn("%Ld", v_uint64_t); // NOWARN + /* retain-typeinfo patch */ + testfn("%zu", (size_t)v_pid_t); // NOWARN (need retain-typeinfo patch) + testfn("%lu", (size_t)v_pid_t); // WARN (need retain-typeinfo patch) + testfn("%Lu", (uint64_t)v_pid_t); // NOWARN (need retain-typeinfo patch) + testfn("%lu", (uint64_t)v_pid_t); // WARN (need retain-typeinfo patch) + testfn("%pI4", &v_long); // WARN in_addr_t v_in_addr_t; diff --git a/tools/gcc-plugins/format-test.py b/tools/gcc-plugins/format-test.py index cc6ca6100e..df2437d5bc 100644 --- a/tools/gcc-plugins/format-test.py +++ b/tools/gcc-plugins/format-test.py @@ -10,6 +10,10 @@ for k in list(os.environ.keys()): if k.startswith('LC_'): os.environ.pop(k) +if len(sys.argv) < 2: + sys.stderr.write('start as format-test.py gcc-123.45 [-options ...]\n') + sys.exit(1) + c_re = re.compile(r'//\s+(NO)?WARN') expect = {} lines = {} @@ -25,9 +29,9 @@ with open('format-test.c', 'r') as fd: else: expect[lno] = 'nowarn' -cmd = shlex.split('gcc -Wall -Wextra -Wno-unused -fplugin=./frr-format.so -fno-diagnostics-show-caret -c -o format-test.o format-test.c') +cmd = shlex.split('-Wall -Wextra -Wno-unused -fplugin=./frr-format.so -fno-diagnostics-show-caret -c -o format-test.o format-test.c') -gcc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) +gcc = subprocess.Popen(sys.argv[1:] + cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) sout, serr = gcc.communicate() gcc.wait() diff --git a/tools/gcc-plugins/frr-format.c b/tools/gcc-plugins/frr-format.c index 174f403d48..be56517171 100644 --- a/tools/gcc-plugins/frr-format.c +++ b/tools/gcc-plugins/frr-format.c @@ -268,8 +268,7 @@ check_format_string (tree fntype, unsigned HOST_WIDE_INT format_num, /* We expect a string object type as the format arg. */ if (is_char_ref) { - error ("format argument should be a %qs reference but" - " a string was found", format_name (expected_format_type)); + error ("format argument should be a %qs reference but a string was found", format_name (expected_format_type)); *no_add_attrs = true; return false; } @@ -360,7 +359,7 @@ decode_format_attr (tree args, function_format_info *info, int validated_p) if (info->first_arg_num != 0 && info->first_arg_num <= info->format_num) { gcc_assert (!validated_p); - error ("format string argument follows the args to be formatted"); + error ("format string argument follows the arguments to be formatted"); return false; } @@ -490,10 +489,10 @@ static const format_flag_pair printf_flag_pairs[] = #define ETAB_SZ 128 static kernel_ext_fmt ext_p[ETAB_SZ] = { - { NULL } + { } }; static kernel_ext_fmt ext_d[ETAB_SZ] = { - { NULL } + { } }; static const format_char_info print_char_table[] = @@ -741,8 +740,8 @@ check_function_format (tree attrs, int nargs, tree *argarray, break; } if (args != 0) - warning (OPT_Wsuggest_attribute_format, "function %qD " - "might be a candidate for %qs frr_format attribute", + warning (OPT_Wsuggest_attribute_format, + "function %qD might be a candidate for %qs %<frr_format%> attribute", current_function_decl, format_types[info.format_type].name); } @@ -924,7 +923,7 @@ avoid_dollar_number (const char *format) format++; if (*format == '$') { - warning (OPT_Wformat_, "$ operand number used after format without operand number"); + warning (OPT_Wformat_, "%<$%> operand number used after format without operand number"); return true; } return false; @@ -955,7 +954,7 @@ finish_dollar_format_checking (format_check_results *res, int pointer_gap_ok) found_pointer_gap = true; else warning_at (res->format_string_loc, OPT_Wformat_, - "format argument %d unused before used argument %d in $-style format", + "format argument %d unused before used argument %d in %<$%>-style format", i + 1, dollar_max_arg_used); } } @@ -1099,7 +1098,7 @@ check_format_info (function_format_info *info, tree params, } if (res.number_dollar_extra_args > 0 && res.number_non_literal == 0 && res.number_other == 0) - warning_at (loc, OPT_Wformat_extra_args, "unused arguments in $-style format"); + warning_at (loc, OPT_Wformat_extra_args, "unused arguments in %<$%>-style format"); if (res.number_empty > 0 && res.number_non_literal == 0 && res.number_other == 0) warning_at (loc, OPT_Wformat_zero_length, "zero-length %s format string", @@ -1534,8 +1533,7 @@ flag_chars_t::validate (const format_kind_info *fki, : s->long_name); if (ADJ_STD (t->std) > C_STD_VER) warning_at (format_string_loc, OPT_Wformat_, - "%s does not support %s with" - " the %<%%%c%> %s format", + "%s does not support %s with the %<%%%c%> %s format", C_STD_NAME (t->std), _(long_name), format_char, fki->name); } @@ -2040,8 +2038,7 @@ argument_parser::find_format_char_info (char format_char) format_warning_at_char (format_string_loc, format_string_cst, format_chars - orig_format_chars, OPT_Wformat_, - "unknown conversion type character" - " %qc in format", + "unknown conversion type character %qc in format", format_char); return NULL; } @@ -2128,8 +2125,7 @@ argument_parser::give_y2k_warnings (const format_char_info *fci, y2k_level = 2; if (y2k_level == 3) warning_at (format_string_loc, OPT_Wformat_y2k, - "%<%%%c%> yields only last 2 digits of " - "year in some locales", format_char); + "%<%%%c%> yields only last 2 digits of year in some locales", format_char); else if (y2k_level == 2) warning_at (format_string_loc, OPT_Wformat_y2k, "%<%%%c%> yields only last 2 digits of year", @@ -2188,9 +2184,7 @@ argument_parser::handle_conversions (const format_char_info *fci, format_warning_at_char (format_string_loc, format_string_cst, format_chars - orig_format_chars, OPT_Wformat_, - "use of %qs length modifier with %qc type" - " character has either no effect" - " or undefined behavior", + "use of %qs length modifier with %qc type character has either no effect or undefined behavior", len_modifier.chars, format_char); /* Heuristic: skip one argument when an invalid length/type combination is encountered. */ @@ -2249,12 +2243,10 @@ check_argument_type (const format_char_info *fci, { if (suppressed) warning_at (format_string_loc, OPT_Wformat_, - "operand number specified with " - "suppressed assignment"); + "operand number specified with suppressed assignment"); else warning_at (format_string_loc, OPT_Wformat_, - "operand number specified for format " - "taking no argument"); + "operand number specified for format taking no argument"); } } else @@ -2576,8 +2568,7 @@ check_format_info_main (format_check_results *res, format_warning_at_char (format_string_loc, format_string_cst, format_chars - orig_format_chars, OPT_Wformat_, - "%qc directive redundant after prior " - "occurence of the same", format_char); + "%qc directive redundant after prior occurence of the same", format_char); else if (!color_begin) format_warning_at_char (format_string_loc, format_string_cst, format_chars - orig_format_chars, @@ -2594,8 +2585,7 @@ check_format_info_main (format_check_results *res, format_warning_at_char (format_string_loc, format_string_cst, format_chars - orig_format_chars, OPT_Wformat_, - "%qc conversion used within a quoted " - "sequence", + "%qc conversion used within a quoted sequence", format_char); } @@ -2821,16 +2811,14 @@ check_format_types (const substring_loc &fmt_loc, && i == 0 && cur_param != 0 && integer_zerop (cur_param)) - warning (OPT_Wformat_, "writing through null pointer " - "(argument %d)", arg_num); + warning (OPT_Wformat_, "writing through null pointer (argument %d)", arg_num); /* Check for reading through a NULL pointer. */ if (types->reading_from_flag && i == 0 && cur_param != 0 && integer_zerop (cur_param)) - warning (OPT_Wformat_, "reading through null pointer " - "(argument %d)", arg_num); + warning (OPT_Wformat_, "reading through null pointer (argument %d)", arg_num); if (cur_param != 0 && TREE_CODE (cur_param) == ADDR_EXPR) cur_param = TREE_OPERAND (cur_param, 0); @@ -2849,8 +2837,7 @@ check_format_types (const substring_loc &fmt_loc, && (CONSTANT_CLASS_P (cur_param) || (DECL_P (cur_param) && TREE_READONLY (cur_param)))))) - warning (OPT_Wformat_, "writing into constant object " - "(argument %d)", arg_num); + warning (OPT_Wformat_, "writing into constant object (argument %d)", arg_num); /* If there are extra type qualifiers beyond the first indirection, then this makes the types technically @@ -2861,8 +2848,7 @@ check_format_types (const substring_loc &fmt_loc, || TYPE_VOLATILE (cur_type) || TYPE_ATOMIC (cur_type) || TYPE_RESTRICT (cur_type))) - warning (OPT_Wformat_, "extra type qualifiers in format " - "argument (argument %d)", + warning (OPT_Wformat_, "extra type qualifiers in format argument (argument %d)", arg_num); } @@ -3095,8 +3081,7 @@ check_kef_type (const substring_loc &fmt_loc, || TYPE_VOLATILE (cur_type) || TYPE_ATOMIC (cur_type) || TYPE_RESTRICT (cur_type))) - warning (OPT_Wformat_, "extra type qualifiers in format " - "argument (argument %d)", + warning (OPT_Wformat_, "extra type qualifiers in format argument (argument %d)", arg_num); } @@ -3541,17 +3526,24 @@ print_type (c_pretty_printer *cpp, tree t, bool *quoted) /* C-specific implementation of range_label::get_text () vfunc for range_label_for_type_mismatch. */ +#if BUILDING_GCC_VERSION >= 10000 +#define label_borrow(text) label_text::borrow(text) +#define label_take(text) label_text::take(text) +#else +#define label_borrow(text) label_text((char *)text, false) +#define label_take(text) label_text(text, true) +#endif label_text frr_range_label_for_type_mismatch::get_text (unsigned /*range_idx*/) const { if (m_labelled_type == NULL_TREE) - return label_text (NULL, false); + return label_borrow("(null tree)"); c_pretty_printer cpp; bool quoted = false; print_type (&cpp, m_labelled_type, "ed); - return label_text (xstrdup (pp_formatted_text (&cpp)), true); + return label_take(xstrdup (pp_formatted_text (&cpp))); } #define range_label_for_type_mismatch frr_range_label_for_type_mismatch @@ -3583,7 +3575,7 @@ class range_label_for_format_type_mismatch char *result = concat (text.m_buffer, p, NULL); text.maybe_free (); - return label_text (result, true); + return label_take(result); } private: @@ -3695,8 +3687,7 @@ format_type_warning (const substring_loc &whole_fmt_loc, format_warning_at_substring (fmt_loc, &fmt_label, param_loc, ¶m_label, corrected_substring, OPT_Wformat_, - "%s %<%s%.*s%> expects argument of type %<%s%s%>, " - "but argument %d has type %qT%s", + "%s %<%s%.*s%> expects argument of type %<%s%s%>, but argument %d has type %qT%s", gettext (kind_descriptions[kind]), (kind == CF_KIND_FORMAT ? "%" : ""), format_length, format_start, @@ -3716,8 +3707,7 @@ format_type_warning (const substring_loc &whole_fmt_loc, format_warning_at_substring (fmt_loc, &fmt_label, param_loc, ¶m_label, corrected_substring, OPT_Wformat_, - "%s %<%s%.*s%> expects argument of type %<%T%s%>, " - "but argument %d has type %qT%s", + "%s %<%s%.*s%> expects argument of type %<%T%s%>, but argument %d has type %qT%s", gettext (kind_descriptions[kind]), (kind == CF_KIND_FORMAT ? "%" : ""), format_length, format_start, @@ -3875,7 +3865,7 @@ handle_frr_format_attribute (tree *node, tree ARG_UNUSED (name), tree args, if (arg_num != info.first_arg_num) { if (!(flags & (int) ATTR_FLAG_BUILT_IN)) - error ("args to be formatted is not %<...%>"); + error ("arguments to be formatted is not %<...%>"); *no_add_attrs = true; return NULL_TREE; } @@ -4149,7 +4139,7 @@ setup_type (const char *name, tree *dst) tmp = identifier_global_value (*dst); if (tmp && TREE_CODE (tmp) != TYPE_DECL) { - warning (0, "%<%s%> is not defined as a type", name); + warning (0, "%qs is not defined as a type", name); *dst = NULL; return; } @@ -4316,7 +4306,7 @@ handle_pragma_printfrr_ext (cpp_reader *dummy) if (0) { warning_at (loc, OPT_Wformat_, - "%<#pragma FRR printfrr_ext%>: duplicate printf format suffix \"%s\"", s); + "%<#pragma FRR printfrr_ext%>: duplicate printf format suffix %qs", s); warning_at (etab->origin_loc, OPT_Wformat_, "%<#pragma FRR printfrr_ext%>: previous definition was here"); return; @@ -4328,9 +4318,9 @@ handle_pragma_printfrr_ext (cpp_reader *dummy) if (!strncmp(s + 2, etab->suffix, MIN(strlen(s + 2), strlen(etab->suffix)))) { warning_at (loc, OPT_Wformat_, - "%<#pragma FRR printfrr_ext%>: overlapping printf format suffix \"%s\"", s); + "%<#pragma FRR printfrr_ext%>: overlapping printf format suffix %qs", s); warning_at (etab->origin_loc, OPT_Wformat_, - "%<#pragma FRR printfrr_ext%>: previous definition for \"%%%c%s\" was here", s[1], etab->suffix); + "%<#pragma FRR printfrr_ext%>: previous definition for %<%%%c%s%> was here", s[1], etab->suffix); return; } } @@ -4388,7 +4378,7 @@ handle_pragma_printfrr_ext (cpp_reader *dummy) { switch (ttype) { case CPP_NAME: - error_at (loc, "%<#pragma FRR printfrr_ext%>: unexpected identifier. Note the only supported qualifier is \"const\"."); + error_at (loc, "%<#pragma FRR printfrr_ext%>: unexpected identifier. Note the only supported qualifier is %<const%>"); goto out_drop; case CPP_MULT: diff --git a/tools/gcc-plugins/gcc-common.h b/tools/gcc-plugins/gcc-common.h index 6b6c17231a..ec45de1a53 100644 --- a/tools/gcc-plugins/gcc-common.h +++ b/tools/gcc-plugins/gcc-common.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* FRR: imported from Linux kernel on 2019-07-29 */ +/* FRR: imported from Linux kernel on 2020-07-14 */ #ifndef GCC_COMMON_H_INCLUDED #define GCC_COMMON_H_INCLUDED @@ -38,7 +38,9 @@ #include "ggc.h" #include "timevar.h" +#if BUILDING_GCC_VERSION < 10000 #include "params.h" +#endif #if BUILDING_GCC_VERSION <= 4009 #include "pointer-set.h" @@ -852,6 +854,7 @@ static inline gimple gimple_build_assign_with_ops(enum tree_code subcode, tree l return gimple_build_assign(lhs, subcode, op1, op2 PASS_MEM_STAT); } +#if BUILDING_GCC_VERSION < 10000 template <> template <> inline bool is_a_helper<const ggoto *>::test(const_gimple gs) @@ -865,6 +868,7 @@ inline bool is_a_helper<const greturn *>::test(const_gimple gs) { return gs->code == GIMPLE_RETURN; } +#endif static inline gasm *as_a_gasm(gimple stmt) { diff --git a/tools/start-stop-daemon.c b/tools/start-stop-daemon.c index 7ad2a84500..0e4cf271f3 100644 --- a/tools/start-stop-daemon.c +++ b/tools/start-stop-daemon.c @@ -410,8 +410,7 @@ static void parse_schedule_item(const char *string, struct schedule_item *item) item->type = sched_signal; } else { badusage( - "invalid schedule item (must be [-]<signal-name>, " - "-<signal-number>, <timeout> or `forever'"); + "invalid schedule item (must be [-]<signal-name>, -<signal-number>, <timeout> or `forever'"); } } @@ -436,8 +435,7 @@ static void parse_schedule(const char *schedule_str) parse_schedule_item(schedule_str, &schedule[1]); if (schedule[1].type != sched_timeout) { badusage( - "--retry takes timeout, or schedule list" - " of at least two items"); + "--retry takes timeout, or schedule list of at least two items"); } schedule[2].type = sched_signal; schedule[2].value = SIGKILL; @@ -451,8 +449,7 @@ static void parse_schedule(const char *schedule_str) : (ptrdiff_t)strlen(schedule_str); if (str_len >= (ptrdiff_t)sizeof(item_buf)) badusage( - "invalid schedule item: far too long" - " (you must delimit items with slashes)"); + "invalid schedule item: far too long (you must delimit items with slashes)"); memcpy(item_buf, schedule_str, str_len); item_buf[str_len] = 0; schedule_str = slash ? slash + 1 : NULL; @@ -461,8 +458,7 @@ static void parse_schedule(const char *schedule_str) if (schedule[count].type == sched_forever) { if (repeatat >= 0) badusage( - "invalid schedule: `forever'" - " appears more than once"); + "invalid schedule: `forever' appears more than once"); repeatat = count; continue; } @@ -574,8 +570,7 @@ static void parse_options(int argc, char *const *argv) if (signal_str != NULL) { if (parse_signal(signal_str, &signal_nr) != 0) badusage( - "signal value must be numeric or name" - " of signal (KILL, INTR, ...)"); + "signal value must be numeric or name of signal (KILL, INTR, ...)"); } if (schedule_str != NULL) { diff --git a/tools/stringmangle.py b/tools/stringmangle.py new file mode 100644 index 0000000000..a2eb37336a --- /dev/null +++ b/tools/stringmangle.py @@ -0,0 +1,59 @@ +# 2020 by David Lamparter, placed in the public domain. + +import sys +import os +import re +import argparse + +wrap_res = [ + (re.compile(r'(?<!\\n)"\s*\n\s*"', re.M), r''), +] +pri_res = [ + (re.compile(r'(PRI[udx][0-9]+)\s*\n\s*"', re.M), r'\1"'), + (re.compile(r'"\s*PRI([udx])32\s*"'), r'\1'), + (re.compile(r'"\s*PRI([udx])32'), r'\1"'), + (re.compile(r'"\s*PRI([udx])16\s*"'), r'h\1'), + (re.compile(r'"\s*PRI([udx])16'), r'h\1"'), + (re.compile(r'"\s*PRI([udx])8\s*"'), r'hh\1'), + (re.compile(r'"\s*PRI([udx])8'), r'hh\1"'), +] + +def main(): + argp = argparse.ArgumentParser(description = 'C string mangler') + argp.add_argument('--unwrap', action = 'store_const', const = True) + argp.add_argument('--pri8-16-32', action = 'store_const', const = True) + argp.add_argument('files', type = str, nargs = '+') + args = argp.parse_args() + + regexes = [] + if args.unwrap: + regexes.extend(wrap_res) + if args.pri8_16_32: + regexes.extend(pri_res) + if len(regexes) == 0: + sys.stderr.write('no action selected to execute\n') + sys.exit(1) + + l = 0 + + for fn in args.files: + sys.stderr.write(fn + '\033[K\r') + with open(fn, 'r') as ifd: + data = ifd.read() + + newdata = data + n = 0 + for regex, repl in regexes: + newdata, m = regex.subn(repl, newdata) + n += m + + if n > 0: + sys.stderr.write('changed: %s\n' % fn) + with open(fn + '.new', 'w') as ofd: + ofd.write(newdata) + os.rename(fn + '.new', fn) + l += 1 + + sys.stderr.write('%d files changed.\n' % (l)) + +main() diff --git a/tools/subdir.am b/tools/subdir.am index 723a87d100..e159d82d4c 100644 --- a/tools/subdir.am +++ b/tools/subdir.am @@ -48,6 +48,7 @@ EXTRA_DIST += \ tools/frr-reload \ tools/frr-reload.py \ tools/frr.service \ + tools/frr@.service \ tools/generate_support_bundle.py \ tools/multiple-bgpd.sh \ tools/rrcheck.pl \ diff --git a/vrrpd/vrrp.c b/vrrpd/vrrp.c index 3ef9fd90aa..d3f9b0c730 100644 --- a/vrrpd/vrrp.c +++ b/vrrpd/vrrp.c @@ -867,8 +867,7 @@ static int vrrp_recv_advertisement(struct vrrp_router *r, struct ipaddr *src, if (pkt->hdr.vrid != r->vr->vrid) { DEBUGD(&vrrp_dbg_proto, VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM - "Datagram invalid: Advertisement contains VRID %" PRIu8 - " which does not match our instance", + "Datagram invalid: Advertisement contains VRID %hhu which does not match our instance", r->vr->vrid, family2str(r->family), pkt->hdr.vrid); return -1; } @@ -888,8 +887,7 @@ static int vrrp_recv_advertisement(struct vrrp_router *r, struct ipaddr *src, if (r->vr->version == 2 && !adveq) { DEBUGD(&vrrp_dbg_proto, VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM - "Datagram invalid: Received advertisement with advertisement interval %" PRIu8 - " unequal to our configured value %u", + "Datagram invalid: Received advertisement with advertisement interval %hhu unequal to our configured value %u", r->vr->vrid, family2str(r->family), pkt->hdr.v2.adver_int, MAX(r->vr->advertisement_interval / 100, 1)); @@ -901,8 +899,7 @@ static int vrrp_recv_advertisement(struct vrrp_router *r, struct ipaddr *src, if (pkt->hdr.naddr != r->addrs->count) DEBUGD(&vrrp_dbg_proto, VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM - "Datagram has %" PRIu8 - " addresses, but this VRRP instance has %u", + "Datagram has %hhu addresses, but this VRRP instance has %u", r->vr->vrid, family2str(r->family), pkt->hdr.naddr, r->addrs->count); @@ -926,8 +923,7 @@ static int vrrp_recv_advertisement(struct vrrp_router *r, struct ipaddr *src, && addrcmp > 0)) { zlog_info( VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM - "Received advertisement from %s w/ priority %" PRIu8 - "; switching to Backup", + "Received advertisement from %s w/ priority %hhu; switching to Backup", r->vr->vrid, family2str(r->family), sipstr, pkt->hdr.priority); THREAD_OFF(r->t_adver_timer); @@ -946,8 +942,7 @@ static int vrrp_recv_advertisement(struct vrrp_router *r, struct ipaddr *src, /* Discard advertisement */ DEBUGD(&vrrp_dbg_proto, VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM - "Discarding advertisement from %s (%" PRIu8 - " <= %" PRIu8 " & %s <= %s)", + "Discarding advertisement from %s (%hhu <= %hhu & %s <= %s)", r->vr->vrid, family2str(r->family), sipstr, pkt->hdr.priority, r->priority, sipstr, dipstr); } @@ -975,8 +970,7 @@ static int vrrp_recv_advertisement(struct vrrp_router *r, struct ipaddr *src, /* Discard advertisement */ DEBUGD(&vrrp_dbg_proto, VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM - "Discarding advertisement from %s (%" PRIu8 - " < %" PRIu8 " & preempt = true)", + "Discarding advertisement from %s (%hhu < %hhu & preempt = true)", r->vr->vrid, family2str(r->family), sipstr, pkt->hdr.priority, r->priority); } @@ -2353,11 +2347,11 @@ int vrrp_config_write_global(struct vty *vty) /* FIXME: needs to be udpated for full YANG conversion. */ if (vd.priority != VRRP_DEFAULT_PRIORITY && ++writes) - vty_out(vty, "vrrp default priority %" PRIu8 "\n", vd.priority); + vty_out(vty, "vrrp default priority %hhu\n", vd.priority); if (vd.advertisement_interval != VRRP_DEFAULT_ADVINT && ++writes) vty_out(vty, - "vrrp default advertisement-interval %" PRIu16 "\n", + "vrrp default advertisement-interval %u\n", vd.advertisement_interval * CS2MS); if (vd.preempt_mode != VRRP_DEFAULT_PREEMPT && ++writes) @@ -2380,7 +2374,7 @@ static unsigned int vrrp_hash_key(const void *arg) const struct vrrp_vrouter *vr = arg; char key[IFNAMSIZ + 64]; - snprintf(key, sizeof(key), "%s@%" PRIu8, vr->ifp->name, vr->vrid); + snprintf(key, sizeof(key), "%s@%u", vr->ifp->name, vr->vrid); return string_hash_make(key); } diff --git a/vrrpd/vrrp_northbound.c b/vrrpd/vrrp_northbound.c index c11e0352de..e9cd714a95 100644 --- a/vrrpd/vrrp_northbound.c +++ b/vrrpd/vrrp_northbound.c @@ -103,7 +103,7 @@ lib_interface_vrrp_vrrp_group_get_keys(struct nb_cb_get_keys_args *args) const struct vrrp_vrouter *vr = args->list_entry; args->keys->num = 1; - snprintf(args->keys->key[0], sizeof(args->keys->key[0]), "%" PRIu32, + snprintf(args->keys->key[0], sizeof(args->keys->key[0]), "%u", vr->vrid); return NB_OK; diff --git a/vrrpd/vrrp_packet.c b/vrrpd/vrrp_packet.c index e4fee2d792..3cb13bd71b 100644 --- a/vrrpd/vrrp_packet.c +++ b/vrrpd/vrrp_packet.c @@ -222,13 +222,12 @@ ssize_t vrrp_pkt_parse_datagram(int family, int version, struct msghdr *m, /* IP total length check */ VRRP_PKT_VCHECK( ntohs(ip->ip_len) == read, - "IPv4 packet length field does not match # received bytes; %" PRIu16 - "!= %zu", + "IPv4 packet length field does not match # received bytes; %hu!= %zu", ntohs(ip->ip_len), read); /* TTL check */ VRRP_PKT_VCHECK(ip->ip_ttl == 255, - "IPv4 TTL is %" PRIu8 "; should be 255", + "IPv4 TTL is %hhu; should be 255", ip->ip_ttl); *pkt = (struct vrrp_pkt *)(buf + (ip->ip_hl << 2)); @@ -256,7 +255,7 @@ ssize_t vrrp_pkt_parse_datagram(int family, int version, struct msghdr *m, uint8_t *hoplimit = CMSG_DATA(c); VRRP_PKT_VCHECK(*hoplimit == 255, - "IPv6 Hop Limit is %" PRIu8 "; should be 255", + "IPv6 Hop Limit is %hhu; should be 255", *hoplimit); *pkt = (struct vrrp_pkt *)buf; @@ -293,11 +292,11 @@ ssize_t vrrp_pkt_parse_datagram(int family, int version, struct msghdr *m, uint16_t chksum = vrrp_pkt_checksum(*pkt, pktsize, src); VRRP_PKT_VCHECK((*pkt)->hdr.chksum == chksum, - "Bad VRRP checksum %" PRIx16 "; should be %" PRIx16 "", + "Bad VRRP checksum %hx; should be %hx", (*pkt)->hdr.chksum, chksum); /* Type check */ - VRRP_PKT_VCHECK(((*pkt)->hdr.vertype & 0x0F) == 1, "Bad type %" PRIu8, + VRRP_PKT_VCHECK(((*pkt)->hdr.vertype & 0x0F) == 1, "Bad type %u", (*pkt)->hdr.vertype & 0x0f); /* Exact size check */ @@ -309,7 +308,7 @@ ssize_t vrrp_pkt_parse_datagram(int family, int version, struct msghdr *m, /* auth type check */ if (version == 2) VRRP_PKT_VCHECK((*pkt)->hdr.v2.auth_type == 0, - "Bad authentication type %" PRIu8, + "Bad authentication type %hhu", (*pkt)->hdr.v2.auth_type); /* Addresses check */ @@ -318,7 +317,7 @@ ssize_t vrrp_pkt_parse_datagram(int family, int version, struct msghdr *m, for (uint8_t i = 0; i < (*pkt)->hdr.naddr; i++) { VRRP_PKT_VCHECK(inet_ntop(family, p, vbuf, sizeof(vbuf)), - "Bad IP address, #%" PRIu8, i); + "Bad IP address, #%hhu", i); p += addrsz; } diff --git a/vrrpd/vrrp_vty.c b/vrrpd/vrrp_vty.c index b6388cc5ba..dc7f023e8f 100644 --- a/vrrpd/vrrp_vty.c +++ b/vrrpd/vrrp_vty.c @@ -470,8 +470,8 @@ static void vrrp_show(struct vty *vty, struct vrrp_vrouter *vr) struct ttable *tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]); - ttable_add_row(tt, "%s|%" PRIu32, "Virtual Router ID", vr->vrid); - ttable_add_row(tt, "%s|%" PRIu8, "Protocol Version", vr->version); + ttable_add_row(tt, "%s|%u", "Virtual Router ID", vr->vrid); + ttable_add_row(tt, "%s|%hhu", "Protocol Version", vr->version); ttable_add_row(tt, "%s|%s", "Autoconfigured", vr->autoconf ? "Yes" : "No"); ttable_add_row(tt, "%s|%s", "Shutdown", vr->shutdown ? "Yes" : "No"); @@ -492,10 +492,10 @@ static void vrrp_show(struct vty *vty, struct vrrp_vrouter *vr) ttable_add_row(tt, "%s|%s", "Virtual MAC (v6)", ethstr6); ttable_add_row(tt, "%s|%s", "Status (v4)", stastr4); ttable_add_row(tt, "%s|%s", "Status (v6)", stastr6); - ttable_add_row(tt, "%s|%" PRIu8, "Priority", vr->priority); - ttable_add_row(tt, "%s|%" PRIu8, "Effective Priority (v4)", + ttable_add_row(tt, "%s|%hhu", "Priority", vr->priority); + ttable_add_row(tt, "%s|%hhu", "Effective Priority (v4)", vr->v4->priority); - ttable_add_row(tt, "%s|%" PRIu8, "Effective Priority (v6)", + ttable_add_row(tt, "%s|%hhu", "Effective Priority (v6)", vr->v6->priority); ttable_add_row(tt, "%s|%s", "Preempt Mode", vr->preempt_mode ? "Yes" : "No"); @@ -509,21 +509,21 @@ static void vrrp_show(struct vty *vty, struct vrrp_vrouter *vr) ttable_add_row(tt, "%s|%d ms", "Master Advertisement Interval (v6)", vr->v6->master_adver_interval * CS2MS); - ttable_add_row(tt, "%s|%" PRIu32, "Advertisements Tx (v4)", + ttable_add_row(tt, "%s|%u", "Advertisements Tx (v4)", vr->v4->stats.adver_tx_cnt); - ttable_add_row(tt, "%s|%" PRIu32, "Advertisements Tx (v6)", + ttable_add_row(tt, "%s|%u", "Advertisements Tx (v6)", vr->v6->stats.adver_tx_cnt); - ttable_add_row(tt, "%s|%" PRIu32, "Advertisements Rx (v4)", + ttable_add_row(tt, "%s|%u", "Advertisements Rx (v4)", vr->v4->stats.adver_rx_cnt); - ttable_add_row(tt, "%s|%" PRIu32, "Advertisements Rx (v6)", + ttable_add_row(tt, "%s|%u", "Advertisements Rx (v6)", vr->v6->stats.adver_rx_cnt); - ttable_add_row(tt, "%s|%" PRIu32, "Gratuitous ARP Tx (v4)", + ttable_add_row(tt, "%s|%u", "Gratuitous ARP Tx (v4)", vr->v4->stats.garp_tx_cnt); - ttable_add_row(tt, "%s|%" PRIu32, "Neigh. Adverts Tx (v6)", + ttable_add_row(tt, "%s|%u", "Neigh. Adverts Tx (v6)", vr->v6->stats.una_tx_cnt); - ttable_add_row(tt, "%s|%" PRIu32, "State transitions (v4)", + ttable_add_row(tt, "%s|%u", "State transitions (v4)", vr->v4->stats.trans_cnt); - ttable_add_row(tt, "%s|%" PRIu32, "State transitions (v6)", + ttable_add_row(tt, "%s|%u", "State transitions (v6)", vr->v6->stats.trans_cnt); ttable_add_row(tt, "%s|%d ms", "Skew Time (v4)", vr->v4->skew_time * CS2MS); @@ -653,7 +653,7 @@ DEFPY(vrrp_vrid_show_summary, continue; ttable_add_row( - tt, "%s|%" PRIu8 "|%" PRIu8 "|%d|%d|%s|%s", + tt, "%s|%u|%hhu|%d|%d|%s|%s", vr->ifp->name, vr->vrid, vr->priority, vr->v4->addrs->count, vr->v6->addrs->count, vr->v4->fsm.state == VRRP_STATE_MASTER ? "Master" diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in index 794e1f4c73..346061d7ca 100755 --- a/vtysh/extract.pl.in +++ b/vtysh/extract.pl.in @@ -40,7 +40,7 @@ sub scan_file { $cppadd = $fabricd ? "-DFABRICD=1" : ""; - open (FH, "@CPP@ -DHAVE_CONFIG_H -DVTYSH_EXTRACT_PL -Ivtysh/@top_builddir@ -Ivtysh/@top_srcdir@ -Ivtysh/@top_srcdir@/lib -Ivtysh/@top_builddir@/lib -Ivtysh/@top_srcdir@/bgpd -Ivtysh/@top_srcdir@/bgpd/rfapi @LUA_INCLUDE@ @CPPFLAGS@ $cppadd $file |"); + open (FH, "@CPP@ -P -DHAVE_CONFIG_H -DVTYSH_EXTRACT_PL -Ivtysh/@top_builddir@ -Ivtysh/@top_srcdir@ -Ivtysh/@top_srcdir@/lib -Ivtysh/@top_builddir@/lib -Ivtysh/@top_srcdir@/bgpd -Ivtysh/@top_srcdir@/bgpd/rfapi @LUA_INCLUDE@ @CPPFLAGS@ $cppadd $file |"); local $/; undef $/; $line = <FH>; if (!close (FH)) { @@ -48,7 +48,7 @@ sub scan_file { } # ?: makes a group non-capturing - @defun = ($line =~ /((?:DEFUN|DEFUN_HIDDEN|ALIAS|ALIAS_HIDDEN)\s*\(.+?\));?\s?\s?\n/sg); + @defun = ($line =~ /((?:DEFUN|DEFUN_HIDDEN|ALIAS|ALIAS_HIDDEN|DEFPY|DEFPY_HIDDEN)\s*\(.+?\));?\s?\s?\n/sg); @install = ($line =~ /install_element\s*\(\s*[0-9A-Z_]+,\s*&[^;]*;\s*\n/sg); # DEFUN process diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 9e5885c7b6..d3fc8bc338 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -3073,9 +3073,7 @@ DEFUN (vtysh_write_memory, * ourselves */ if (!used_watchfrr) { - printf("\nWarning: attempting direct configuration write without " - "watchfrr.\nFile permissions and ownership may be " - "incorrect, or write may fail.\n\n"); + printf("\nWarning: attempting direct configuration write without watchfrr.\nFile permissions and ownership may be incorrect, or write may fail.\n\n"); ret = vtysh_write_config_integrated(); } return ret; diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c index 25d1bf7db0..1ca219a26c 100644 --- a/vtysh/vtysh_main.c +++ b/vtysh/vtysh_main.c @@ -421,14 +421,12 @@ int main(int argc, char **argv, char **env) if (markfile + writeconfig + dryrun + boot_flag > 1) { fprintf(stderr, - "Invalid combination of arguments. Please specify at " - "most one of:\n\t-b, -C, -m, -w\n"); + "Invalid combination of arguments. Please specify at most one of:\n\t-b, -C, -m, -w\n"); return 1; } if (inputfile && (writeconfig || boot_flag)) { fprintf(stderr, - "WARNING: Combinining the -f option with -b or -w is " - "NOT SUPPORTED since its\nresults are inconsistent!\n"); + "WARNING: Combinining the -f option with -b or -w is NOT SUPPORTED since its\nresults are inconsistent!\n"); } snprintf(vtysh_config, sizeof(vtysh_config), "%s%s%s", sysconfdir, diff --git a/watchfrr/watchfrr.c b/watchfrr/watchfrr.c index 2db612adca..d1003ad5fa 100644 --- a/watchfrr/watchfrr.c +++ b/watchfrr/watchfrr.c @@ -29,6 +29,7 @@ #include "lib_errors.h" #include "zlog_targets.h" #include "network.h" +#include "printfrr.h" #include <getopt.h> #include <sys/un.h> @@ -174,6 +175,7 @@ struct daemon { #define OPTION_MINRESTART 2000 #define OPTION_MAXRESTART 2001 #define OPTION_DRY 2002 +#define OPTION_NETNS 2003 static const struct option longopts[] = { {"daemon", no_argument, NULL, 'd'}, @@ -190,6 +192,9 @@ static const struct option longopts[] = { {"max-restart-interval", required_argument, NULL, OPTION_MAXRESTART}, {"pid-file", required_argument, NULL, 'p'}, {"blank-string", required_argument, NULL, 'b'}, +#ifdef GNU_LINUX + {"netns", optional_argument, NULL, OPTION_NETNS}, +#endif {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'v'}, {NULL, 0, NULL, 0}}; @@ -244,7 +249,12 @@ Otherwise, the interval is doubled (but capped at the -M value).\n\n", -d, --daemon Run in daemon mode. In this mode, error messages are sent\n\ to syslog instead of stdout.\n\ -S, --statedir Set the vty socket directory (default is %s)\n\ --l, --loglevel Set the logging level (default is %d).\n\ +-N, --pathspace Insert prefix into config & socket paths\n" +#ifdef GNU_LINUX +" --netns Create and/or use Linux network namespace. If no name is\n" +" given, uses the value from `-N`.\n" +#endif +"-l, --loglevel Set the logging level (default is %d).\n\ The value should range from %d (LOG_EMERG) to %d (LOG_DEBUG),\n\ but it can be set higher than %d if extra-verbose debugging\n\ messages are desired.\n\ @@ -346,8 +356,7 @@ static int restart_kill(struct thread *t_kill) time_elapsed(&delay, &restart->time); zlog_warn( - "Warning: %s %s child process %d still running after " - "%ld seconds, sending signal %d", + "Warning: %s %s child process %d still running after %ld seconds, sending signal %d", restart->what, restart->name, (int)restart->pid, (long)delay.tv_sec, (restart->kills ? SIGKILL : SIGTERM)); kill(-restart->pid, (restart->kills ? SIGKILL : SIGTERM)); @@ -476,8 +485,7 @@ static int run_job(struct restart_info *restart, const char *cmdtype, if (gs.loglevel > LOG_DEBUG + 1) zlog_debug( - "postponing %s %s: " - "elapsed time %ld < retry interval %ld", + "postponing %s %s: elapsed time %ld < retry interval %ld", cmdtype, restart->name, (long)delay.tv_sec, restart->interval); return -1; @@ -646,8 +654,7 @@ static int handle_read(struct thread *t_read) if ((rc != sizeof(resp)) || memcmp(buf, resp, sizeof(resp))) { char why[100 + sizeof(buf)]; snprintf(why, sizeof(why), - "read returned bad echo response of %d bytes " - "(expecting %u): %.*s", + "read returned bad echo response of %d bytes (expecting %u): %.*s", (int)rc, (unsigned int)sizeof(resp), (int)rc, buf); daemon_down(dmn, why); return 0; @@ -659,14 +666,12 @@ static int handle_read(struct thread *t_read) if (delay.tv_sec < gs.timeout) { dmn->state = DAEMON_UP; zlog_warn( - "%s state -> up : echo response received after %ld.%06ld " - "seconds", + "%s state -> up : echo response received after %ld.%06ld seconds", dmn->name, (long)delay.tv_sec, (long)delay.tv_usec); } else zlog_warn( - "%s: slow echo response finally received after %ld.%06ld " - "seconds", + "%s: slow echo response finally received after %ld.%06ld seconds", dmn->name, (long)delay.tv_sec, (long)delay.tv_usec); } else if (gs.loglevel > LOG_DEBUG + 1) @@ -698,20 +703,18 @@ static void daemon_send_ready(int exitcode) zlog_notice("all daemons up, doing startup-complete notify"); else if (gs.numdown < gs.numdaemons) flog_err(EC_WATCHFRR_CONNECTION, - "startup did not complete within timeout" - " (%d/%d daemons running)", + "startup did not complete within timeout (%d/%d daemons running)", gs.numdaemons - gs.numdown, gs.numdaemons); else { flog_err(EC_WATCHFRR_CONNECTION, - "all configured daemons failed to start" - " -- exiting watchfrr"); + "all configured daemons failed to start -- exiting watchfrr"); exit(exitcode); } frr_detach(); - snprintf(started, sizeof(started), "%s%s", frr_vtydir, + snprintf(started, sizeof(started), "%s/%s", frr_vtydir, "watchfrr.started"); fp = fopen(started, "w"); if (fp) @@ -948,8 +951,7 @@ static void try_restart(struct daemon *dmn) 1); else zlog_debug( - "%s: postponing restart attempt because master %s daemon " - "not up [%s], or phased restart in progress", + "%s: postponing restart attempt because master %s daemon not up [%s], or phased restart in progress", dmn->name, gs.special->name, state_str[gs.special->state]); return; @@ -958,8 +960,7 @@ static void try_restart(struct daemon *dmn) if ((gs.phase != PHASE_NONE) || gs.numpids) { if (gs.loglevel > LOG_DEBUG + 1) zlog_debug( - "postponing phased global restart: restart already in " - "progress [%s], or outstanding child processes [%d]", + "postponing phased global restart: restart already in progress [%s], or outstanding child processes [%d]", phase_str[gs.phase], gs.numpids); return; } @@ -970,8 +971,7 @@ static void try_restart(struct daemon *dmn) < gs.special->restart.interval) { if (gs.loglevel > LOG_DEBUG + 1) zlog_debug( - "postponing phased global restart: " - "elapsed time %ld < retry interval %ld", + "postponing phased global restart: elapsed time %ld < retry interval %ld", (long)delay.tv_sec, gs.special->restart.interval); return; @@ -987,8 +987,7 @@ static int wakeup_unresponsive(struct thread *t_wakeup) dmn->t_wakeup = NULL; if (dmn->state != DAEMON_UNRESPONSIVE) flog_err(EC_WATCHFRR_CONNECTION, - "%s: no longer unresponsive (now %s), " - "wakeup should have been cancelled!", + "%s: no longer unresponsive (now %s), wakeup should have been cancelled!", dmn->name, state_str[dmn->state]); else { SET_WAKEUP_UNRESPONSIVE(dmn); @@ -1006,8 +1005,7 @@ static int wakeup_no_answer(struct thread *t_wakeup) if (dmn->ignore_timeout) return 0; flog_err(EC_WATCHFRR_CONNECTION, - "%s state -> unresponsive : no response yet to ping " - "sent %ld seconds ago", + "%s state -> unresponsive : no response yet to ping sent %ld seconds ago", dmn->name, gs.timeout); SET_WAKEUP_UNRESPONSIVE(dmn); try_restart(dmn); @@ -1066,8 +1064,7 @@ void watchfrr_status(struct vty *vty) else if (dmn->state == DAEMON_DOWN && time_elapsed(&delay, &dmn->restart.time)->tv_sec < dmn->restart.interval) - vty_out(vty, " restarting in %jd seconds" - " (%jds backoff interval)\n", + vty_out(vty, " restarting in %jd seconds (%jds backoff interval)\n", (intmax_t)dmn->restart.interval - (intmax_t)delay.tv_sec, (intmax_t)dmn->restart.interval); @@ -1115,6 +1112,148 @@ static int startup_timeout(struct thread *t_wakeup) return 0; } +#ifdef GNU_LINUX + +#include <sys/mount.h> +#include <sched.h> + +#define NETNS_RUN_DIR "/var/run/netns" + +static void netns_create(int dirfd, const char *nsname) +{ + /* make /var/run/netns shared between mount namespaces + * just like iproute2 sets it up + */ + if (mount("", NETNS_RUN_DIR, "none", MS_SHARED | MS_REC, NULL)) { + if (errno != EINVAL) { + perror("mount"); + exit(1); + } + + if (mount(NETNS_RUN_DIR, NETNS_RUN_DIR, "none", + MS_BIND | MS_REC, NULL)) { + perror("mount"); + exit(1); + } + + if (mount("", NETNS_RUN_DIR, "none", MS_SHARED | MS_REC, + NULL)) { + perror("mount"); + exit(1); + } + } + + /* need an empty file to mount on top of */ + int nsfd = openat(dirfd, nsname, O_CREAT | O_RDONLY | O_EXCL, 0); + + if (nsfd < 0) { + fprintf(stderr, "failed to create \"%s/%s\": %s\n", + NETNS_RUN_DIR, nsname, strerror(errno)); + exit(1); + } + close(nsfd); + + if (unshare(CLONE_NEWNET)) { + perror("unshare"); + unlinkat(dirfd, nsname, 0); + exit(1); + } + + char *dstpath = asprintfrr(MTYPE_TMP, "%s/%s", NETNS_RUN_DIR, nsname); + + /* bind-mount so the namespace has a name and is persistent */ + if (mount("/proc/self/ns/net", dstpath, "none", MS_BIND, NULL) < 0) { + fprintf(stderr, "failed to bind-mount netns to \"%s\": %s\n", + dstpath, strerror(errno)); + unlinkat(dirfd, nsname, 0); + exit(1); + } + + XFREE(MTYPE_TMP, dstpath); +} + +static void netns_setup(const char *nsname) +{ + int dirfd, nsfd; + + dirfd = open(NETNS_RUN_DIR, O_DIRECTORY | O_RDONLY); + if (dirfd < 0) { + if (errno == ENOTDIR) { + fprintf(stderr, "error: \"%s\" is not a directory!\n", + NETNS_RUN_DIR); + exit(1); + } else if (errno == ENOENT) { + if (mkdir(NETNS_RUN_DIR, 0755)) { + fprintf(stderr, "error: \"%s\": mkdir: %s\n", + NETNS_RUN_DIR, strerror(errno)); + exit(1); + } + dirfd = open(NETNS_RUN_DIR, O_DIRECTORY | O_RDONLY); + if (dirfd < 0) { + fprintf(stderr, "error: \"%s\": opendir: %s\n", + NETNS_RUN_DIR, strerror(errno)); + exit(1); + } + } else { + fprintf(stderr, "error: \"%s\": %s\n", + NETNS_RUN_DIR, strerror(errno)); + exit(1); + } + } + + nsfd = openat(dirfd, nsname, O_RDONLY); + if (nsfd < 0 && errno != ENOENT) { + fprintf(stderr, "error: \"%s/%s\": %s\n", + NETNS_RUN_DIR, nsname, strerror(errno)); + exit(1); + } + if (nsfd < 0) + netns_create(dirfd, nsname); + else { + if (setns(nsfd, CLONE_NEWNET)) { + perror("setns"); + exit(1); + } + close(nsfd); + } + close(dirfd); + + /* make sure loopback is up... weird things happen otherwise. + * ioctl is perfectly fine for this, don't need netlink... + */ + int sockfd; + struct ifreq ifr = { }; + + strlcpy(ifr.ifr_name, "lo", sizeof(ifr.ifr_name)); + + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) { + perror("socket"); + exit(1); + } + if (ioctl(sockfd, SIOCGIFFLAGS, &ifr)) { + perror("ioctl(SIOCGIFFLAGS, \"lo\")"); + exit(1); + } + if (!(ifr.ifr_flags & IFF_UP)) { + ifr.ifr_flags |= IFF_UP; + if (ioctl(sockfd, SIOCSIFFLAGS, &ifr)) { + perror("ioctl(SIOCSIFFLAGS, \"lo\")"); + exit(1); + } + } + close(sockfd); +} + +#else /* !GNU_LINUX */ + +static void netns_setup(const char *nsname) +{ + fprintf(stderr, "network namespaces are only available on Linux\n"); + exit(1); +} +#endif + static void watchfrr_init(int argc, char **argv) { const char *special = "zebra"; @@ -1204,11 +1343,13 @@ int main(int argc, char **argv) { int opt; const char *blankstr = NULL; + const char *netns = NULL; + bool netns_en = false; frr_preinit(&watchfrr_di, argc, argv); progname = watchfrr_di.progname; - frr_opt_add("b:dk:l:i:p:r:S:s:t:T:" DEPRECATED_OPTIONS, longopts, ""); + frr_opt_add("b:di:k:l:N:p:r:S:s:t:T:" DEPRECATED_OPTIONS, longopts, ""); gs.restart.name = "all"; while ((opt = frr_getopt(argc, argv, NULL)) != EOF) { @@ -1273,6 +1414,16 @@ int main(int argc, char **argv) frr_help_exit(1); } } break; + case OPTION_NETNS: + netns_en = true; + if (strchr(optarg, '/')) { + fprintf(stderr, + "invalid network namespace name \"%s\" (may not contain slashes)\n", + optarg); + frr_help_exit(1); + } + netns = optarg; + break; case 'i': { char garbage[3]; int period; @@ -1364,6 +1515,17 @@ int main(int argc, char **argv) gs.restart.interval = gs.min_restart_interval; + /* env variable for the processes that we start */ + if (watchfrr_di.pathspace) + setenv("FRR_PATHSPACE", watchfrr_di.pathspace, 1); + else + unsetenv("FRR_PATHSPACE"); + + if (netns_en && !netns) + netns = watchfrr_di.pathspace; + if (netns_en && netns && netns[0]) + netns_setup(netns); + master = frr_init(); watchfrr_error_init(); watchfrr_init(argc, argv); diff --git a/yang/frr-filter.yang b/yang/frr-filter.yang index 78db201ea1..c9e09bef4b 100644 --- a/yang/frr-filter.yang +++ b/yang/frr-filter.yang @@ -49,28 +49,6 @@ module frr-filter { /* * Types. */ - typedef access-list-standard { - description "Standard IPv4 access list (any, host or a prefix)"; - type uint16 { - range "1..99 | 1300..1999"; - } - } - - typedef access-list-extended { - description - "Extended IPv4 access list (source / destination any, hosts or prefixes)"; - type uint16 { - range "100..199 | 2000..2699"; - } - } - - typedef access-list-legacy { - description "Standard/Extended IPv4 access list"; - type uint16 { - range "1..199 | 1300..2699"; - } - } - typedef access-list-name { description "Access list name formatting"; type string { @@ -103,79 +81,6 @@ module frr-filter { * Configuration data. */ container lib { - list access-list-legacy { - description "Access list legacy instance"; - - key "number"; - - leaf number { - description "Access list sequence value"; - type access-list-legacy; - } - - leaf remark { - description "Access list remark"; - type string; - } - - list entry { - description "Access list legacy entry"; - - key "sequence"; - - leaf sequence { - description "Access list sequence value"; - type access-list-sequence; - } - - leaf action { - description "Access list action on match"; - type access-list-action; - mandatory true; - } - - choice value { - description - "Standard access list: value to match. - Extended access list: source value to match."; - mandatory true; - - leaf host { - description "Host to match"; - type inet:ipv4-address; - } - leaf network { - description "Network to match"; - type inet:ipv4-prefix; - } - leaf any { - description "Match any"; - type empty; - } - } - - choice extended-value { - when "../number >= 100 and ../number <= 199 or - ../number >= 2000 and ../number <= 2699"; - description "Destination value to match"; - mandatory true; - - leaf destination-host { - description "Host to match"; - type inet:ipv4-address; - } - leaf destination-network { - description "Network to match"; - type inet:ipv4-prefix; - } - leaf destination-any { - description "Match any"; - type empty; - } - } - } - } - list access-list { description "Access list instance"; @@ -232,15 +137,66 @@ module frr-filter { case ipv4-prefix { when "../type = 'ipv4'"; - leaf ipv4-prefix { - description "Configure IPv4 prefix to match"; - type inet:ipv4-prefix; - } + choice style { + description "Access list entry style selection: zebra or cisco."; + mandatory true; + + case zebra { + leaf ipv4-prefix { + description "Configure IPv4 prefix to match"; + type inet:ipv4-prefix; + } + + leaf ipv4-exact-match { + description "Exact match of prefix"; + type boolean; + default false; + } + } + case cisco { + leaf host { + description "Host to match"; + type inet:ipv4-address; + } + leaf network { + description "Network to match"; + type inet:ipv4-prefix; + } + leaf source-any { + /* + * Was `any`, however it conflicts with `any` leaf + * outside this choice. + */ + description "Match any"; + type empty; + } + } - leaf ipv4-exact-match { - description "Exact match of prefix"; - type boolean; - default false; + choice extended-value { + /* + * Legacy note: before using the new access-list format the + * cisco styled list only accepted identifiers using numbers + * and they had the following restriction: + * + * when "../number >= 100 and ../number <= 199 or + * ../number >= 2000 and ../number <= 2699"; + */ + description "Destination value to match"; + mandatory true; + + leaf destination-host { + description "Host to match"; + type inet:ipv4-address; + } + leaf destination-network { + description "Network to match"; + type inet:ipv4-prefix; + } + leaf destination-any { + description "Match any"; + type empty; + } + } } } case ipv6-prefix { diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang index befdc3467d..1bb693a1ef 100644 --- a/yang/frr-isisd.yang +++ b/yang/frr-isisd.yang @@ -361,11 +361,18 @@ module frr-isisd { "IS-type of this circuit."; } - leaf bfd-monitoring { - type boolean; - default "false"; - description - "Monitor IS-IS peers on this circuit."; + container bfd-monitoring { + leaf enabled { + type boolean; + default "false"; + description + "Monitor IS-IS peers on this circuit."; + } + leaf profile { + type string; + description + "Let BFD use a pre-configured profile."; + } } container csnp-interval { diff --git a/yang/frr-nexthop.yang b/yang/frr-nexthop.yang index 779c56df7f..c918a7cbfd 100644 --- a/yang/frr-nexthop.yang +++ b/yang/frr-nexthop.yang @@ -156,7 +156,7 @@ module frr-nexthop { } leaf vrf { - type frr-vrf:vrf-ref; + type string; description "The nexthop vrf name, if different from the route."; } @@ -167,7 +167,7 @@ module frr-nexthop { } leaf interface { - type frr-interface:interface-ref; + type string; description "The nexthop egress interface."; } @@ -236,7 +236,8 @@ module frr-nexthop { grouping nexthop-grouping { list nexthop { - key "nh-type gateway interface"; + key "nh-type vrf gateway interface"; + min-elements 1; description "A list of nexthop objects."; uses frr-nexthop-attributes; diff --git a/yang/frr-route-map.yang b/yang/frr-route-map.yang index f35a2976d1..734b984d7d 100644 --- a/yang/frr-route-map.yang +++ b/yang/frr-route-map.yang @@ -239,20 +239,6 @@ module frr-route-map { type string; } } - case access-list-num { - when "./condition = 'ipv4-address-list' or - ./condition = 'ipv4-next-hop-list'"; - leaf access-list-num { - type filter:access-list-standard; - } - } - case access-list-num-extended { - when "./condition = 'ipv4-address-list' or - ./condition = 'ipv4-next-hop-list'"; - leaf access-list-num-extended { - type filter:access-list-extended; - } - } case list-name { when "./condition = 'ipv4-address-list' or ./condition = 'ipv4-prefix-list' or diff --git a/yang/frr-routing.yang b/yang/frr-routing.yang index 5a06e597e5..d22e12074f 100644 --- a/yang/frr-routing.yang +++ b/yang/frr-routing.yang @@ -72,6 +72,35 @@ module frr-routing { "This identity represents an IPv6 address family."; } + identity afi-safi-type { + description + "Base identity type (AFI,SAFI) tuples for RIB"; + } + + identity ipv4-unicast { + base afi-safi-type; + description + "This identity represents the IPv4 unicast address family."; + } + + identity ipv6-unicast { + base afi-safi-type; + description + "This identity represents the IPv6 unicast address family."; + } + + identity ipv4-multicast { + base afi-safi-type; + description + "This identity represents the IPv4 multicast address family."; + } + + identity ipv6-multicast { + base afi-safi-type; + description + "This identity represents the IPv6 multicast address family."; + } + identity control-plane-protocol { description "Base identity from which control-plane protocol identities are @@ -150,7 +179,7 @@ module frr-routing { instance."; } leaf vrf { - type frr-vrf:vrf-ref; + type string; description "vrf for control-plane protocol"; } diff --git a/yang/frr-staticd.yang b/yang/frr-staticd.yang index f59158a0fd..281b4903c0 100644 --- a/yang/frr-staticd.yang +++ b/yang/frr-staticd.yang @@ -1,11 +1,10 @@ module frr-staticd { - yang-version "1.1"; + yang-version 1.1; namespace "http://frrouting.org/yang/staticd"; - prefix frr-staticd; import frr-routing { - prefix "frr-rt"; + prefix frr-rt; } import frr-nexthop { @@ -18,11 +17,9 @@ module frr-staticd { organization "FRRouting"; - contact "FRR Users List: <mailto:frog@lists.frrouting.org> FRR Development List: <mailto:dev@lists.frrouting.org>"; - description "This module defines a model for managing FRR staticd information. This YANG module augments the ietf-routing with additional @@ -58,52 +55,77 @@ module frr-staticd { "Initial revision."; } - identity static { + identity staticd { base frr-rt:routing-protocol; description - "'Static' routing pseudo-protocol."; + "'Staticd' routing pseudo-protocol."; + } + + grouping staticd-prefix-attributes { + list path-list { + key "distance"; + leaf distance { + type frr-rt:administrative-distance; + description + "Admin distance associated with this route."; + } + + leaf tag { + type uint32; + default "0"; + description + "Route tag"; + } + + leaf table-id { + type uint32; + default "0"; + description + "Table-id"; + } + + uses frr-nexthop:frr-nexthop; + } } - augment "/frr-rt:routing/frr-rt:control-plane-protocols/" - + "frr-rt:control-plane-protocol" { + augment "/frr-rt:routing/frr-rt:control-plane-protocols/frr-rt:control-plane-protocol" { container staticd { - when "../frr-rt:type = 'frr-staticd:static'" { + when "../frr-rt:type = 'frr-staticd:staticd'" { description - "This container is only valid for the 'static' routing + "This container is only valid for the 'staticd' routing protocol."; } description - "Support for a 'static' pseudo-protocol instance - consists of a list of routes."; - - list prefix-list { - key "destination-prefix"; + "Support for a 'staticd' pseudo-protocol instance + consists of a list of routes."; + list route-list { + key "prefix afi-safi"; description - "List of static IP routes."; - - leaf destination-prefix { - type inet:ip-address; + "List of staticd IP routes."; + leaf prefix { + type inet:ip-prefix; description - "IP destination prefix."; + "IP prefix."; } - - leaf distance { - type frr-rt:administrative-distance; + leaf afi-safi { + type identityref { + base frr-rt:afi-safi-type; + } description - "Admin distance associated with this route."; + "AFI-SAFI type."; } - leaf tag { - type uint32 { - range "1..4294967295"; + uses staticd-prefix-attributes; + + list src-list { + key "src-prefix"; + leaf src-prefix { + type inet:ipv6-prefix; + description + "IPv6 source prefix"; } - description - "Route tag"; - } - container frr-staticd-next-hop { - description - "Augment static route configuration 'nexthop-list'."; - uses frr-nexthop:frr-nexthop; + + uses staticd-prefix-attributes; } } } diff --git a/yang/frr-zebra.yang b/yang/frr-zebra.yang index 159dd8f791..7762c75d68 100644 --- a/yang/frr-zebra.yang +++ b/yang/frr-zebra.yang @@ -77,35 +77,6 @@ module frr-zebra { "Initial revision."; } - identity afi-safi-type { - description - "Base identity type (AFI,SAFI) tuples for RIB"; - } - - identity ipv4-unicast { - base afi-safi-type; - description - "This identity represents the IPv4 unicast address family."; - } - - identity ipv6-unicast { - base afi-safi-type; - description - "This identity represents the IPv6 unicast address family."; - } - - identity ipv4-multicast { - base afi-safi-type; - description - "This identity represents the IPv4 multicast address family."; - } - - identity ipv6-multicast { - base afi-safi-type; - description - "This identity represents the IPv6 multicast address family."; - } - typedef unix-timestamp { type uint32; units "seconds"; @@ -634,7 +605,7 @@ module frr-zebra { key "afi-safi-name table-id"; leaf afi-safi-name { type identityref { - base afi-safi-type; + base frr-rt:afi-safi-type; } description "AFI, SAFI name."; @@ -677,6 +648,23 @@ module frr-zebra { } } + grouping vrf-vni-mapping { + description + "EVPN L3-VNI mapping corresponding to a VRF."; + leaf l3vni-id { + type vni-id-type; + description + "EVPN L3-VNI id to map to the VRF."; + } + + leaf prefix-only { + type boolean; + default "false"; + description + "EVPN asymmetric mode advertise prefix routes only."; + } + } + // End of zebra container /* * RPCs @@ -2070,7 +2058,11 @@ module frr-zebra { description "Extends VRF model with Zebra-related parameters."; container zebra { + description + "Zebra's vrf specific configuration and operational model."; uses ribs; + + uses vrf-vni-mapping; } } @@ -2173,26 +2165,6 @@ module frr-zebra { description "Limit on the number of updates queued to the dataplane subsystem."; } - list vrf-vni-mapping { - key "vrf-id"; - description - "EVPN VNI mapping corresponding to a VRF."; - leaf vrf-id { - type uint32; - description - "The identifier for a VRF."; - } - leaf vni-id { - type vni-id-type; - description - "The VNI id to map to the VRF."; - } - leaf prefix-only { - type empty; - description - "Prefix routes only."; - } - } /* * Debug options */ diff --git a/yang/subdir.am b/yang/subdir.am index 6caf9fc5f3..6aae0e4701 100644 --- a/yang/subdir.am +++ b/yang/subdir.am @@ -29,10 +29,7 @@ dist_yangmodels_DATA += yang/frr-vrf.yang dist_yangmodels_DATA += yang/frr-route-types.yang dist_yangmodels_DATA += yang/frr-routing.yang dist_yangmodels_DATA += yang/ietf/ietf-routing-types.yang -dist_yangmodels_DATA += yang/frr-igmp.yang dist_yangmodels_DATA += yang/ietf/ietf-interfaces.yang -dist_yangmodels_DATA += yang/frr-pim.yang -dist_yangmodels_DATA += yang/frr-pim-rp.yang if BFDD dist_yangmodels_DATA += yang/frr-bfdd.yang @@ -65,3 +62,9 @@ endif if ZEBRA dist_yangmodels_DATA += yang/frr-zebra.yang endif + +if PIMD +dist_yangmodels_DATA += yang/frr-igmp.yang +dist_yangmodels_DATA += yang/frr-pim.yang +dist_yangmodels_DATA += yang/frr-pim-rp.yang +endif diff --git a/zebra/connected.c b/zebra/connected.c index a982ac9b46..3b9ebe14a4 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -312,13 +312,11 @@ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr, if (IPV4_ADDR_SAME(addr, dest)) flog_warn( EC_ZEBRA_IFACE_SAME_LOCAL_AS_PEER, - "warning: interface %s has same local and peer " - "address %s, routing protocols may malfunction", + "warning: interface %s has same local and peer address %s, routing protocols may malfunction", ifp->name, inet_ntoa(*addr)); } else { zlog_debug( - "warning: %s called for interface %s " - "with peer flag set, but no peer address supplied", + "warning: %s called for interface %s with peer flag set, but no peer address supplied", __func__, ifp->name); UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER); } @@ -328,8 +326,7 @@ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr, if (!dest && (prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp)) zlog_debug( - "warning: PtP interface %s with addr %s/%d needs a " - "peer address", + "warning: PtP interface %s with addr %s/%d needs a peer address", ifp->name, inet_ntoa(*addr), prefixlen); /* Label of this address. */ diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index a29a810902..a15f932451 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -513,8 +513,7 @@ static int netlink_extract_vxlan_info(struct rtattr *link_data, if (!attr[IFLA_VXLAN_LINK]) { if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("IFLA_VXLAN_LINK missing " - "from VXLAN IF message"); + zlog_debug("IFLA_VXLAN_LINK missing from VXLAN IF message"); } else { ifindex_link = *(ifindex_t *)RTA_DATA(attr[IFLA_VXLAN_LINK]); @@ -1307,8 +1306,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) /* Add interface notification from kernel */ if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( - "RTM_NEWLINK ADD for %s(%u) vrf_id %u type %d " - "sl_type %d master %u flags 0x%x", + "RTM_NEWLINK ADD for %s(%u) vrf_id %u type %d sl_type %d master %u flags 0x%x", name, ifi->ifi_index, vrf_id, zif_type, zif_slave_type, bridge_ifindex, ifi->ifi_flags); @@ -1364,8 +1362,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) /* VRF change for an interface. */ if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( - "RTM_NEWLINK vrf-change for %s(%u) " - "vrf_id %u -> %u flags 0x%x", + "RTM_NEWLINK vrf-change for %s(%u) vrf_id %u -> %u flags 0x%x", name, ifp->ifindex, ifp->vrf_id, vrf_id, ifi->ifi_flags); @@ -1376,8 +1373,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) /* Interface update. */ if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( - "RTM_NEWLINK update for %s(%u) " - "sl_type %d master %u flags 0x%x", + "RTM_NEWLINK update for %s(%u) sl_type %d master %u flags 0x%x", name, ifp->ifindex, zif_slave_type, bridge_ifindex, ifi->ifi_flags); diff --git a/zebra/interface.c b/zebra/interface.c index 982a63a022..53ae1d2089 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -385,8 +385,7 @@ int if_subnet_delete(struct interface *ifp, struct connected *ifc) rn = route_node_lookup(zebra_if->ipv4_subnets, &cp); if (!(rn && rn->info)) { flog_warn(EC_ZEBRA_REMOVE_ADDR_UNKNOWN_SUBNET, - "Trying to remove an address from an unknown subnet." - " (please report this bug)"); + "Trying to remove an address from an unknown subnet. (please report this bug)"); return -1; } route_unlock_node(rn); @@ -400,8 +399,7 @@ int if_subnet_delete(struct interface *ifp, struct connected *ifc) if (!listnode_lookup(addr_list, ifc)) { flog_warn( EC_ZEBRA_REMOVE_UNREGISTERED_ADDR, - "Trying to remove an address from a subnet where it is not" - " currently registered. (please report this bug)"); + "Trying to remove an address from a subnet where it is not currently registered. (please report this bug)"); return -1; } @@ -618,8 +616,7 @@ void if_add_update(struct interface *ifp) if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) { if (IS_ZEBRA_DEBUG_KERNEL) { zlog_debug( - "interface %s vrf %s(%u) index %d is shutdown. " - "Won't wake it up.", + "interface %s vrf %s(%u) index %d is shutdown. Won't wake it up.", ifp->name, VRF_LOGNAME(zvrf->vrf), ifp->vrf_id, ifp->ifindex); } @@ -1625,14 +1622,12 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) #ifdef HAVE_PROC_NET_DEV /* Statistics print out using proc file system. */ vty_out(vty, - " %lu input packets (%lu multicast), %lu bytes, " - "%lu dropped\n", + " %lu input packets (%lu multicast), %lu bytes, %lu dropped\n", ifp->stats.rx_packets, ifp->stats.rx_multicast, ifp->stats.rx_bytes, ifp->stats.rx_dropped); vty_out(vty, - " %lu input errors, %lu length, %lu overrun," - " %lu CRC, %lu frame\n", + " %lu input errors, %lu length, %lu overrun, %lu CRC, %lu frame\n", ifp->stats.rx_errors, ifp->stats.rx_length_errors, ifp->stats.rx_over_errors, ifp->stats.rx_crc_errors, ifp->stats.rx_frame_errors); @@ -1645,8 +1640,7 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) ifp->stats.tx_dropped); vty_out(vty, - " %lu output errors, %lu aborted, %lu carrier," - " %lu fifo, %lu heartbeat\n", + " %lu output errors, %lu aborted, %lu carrier, %lu fifo, %lu heartbeat\n", ifp->stats.tx_errors, ifp->stats.tx_aborted_errors, ifp->stats.tx_carrier_errors, ifp->stats.tx_fifo_errors, ifp->stats.tx_heartbeat_errors); @@ -1658,8 +1652,7 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) #ifdef HAVE_NET_RT_IFLIST /* Statistics print out using sysctl (). */ vty_out(vty, - " input packets %llu, bytes %llu, dropped %llu," - " multicast packets %llu\n", + " input packets %llu, bytes %llu, dropped %llu, multicast packets %llu\n", (unsigned long long)ifp->stats.ifi_ipackets, (unsigned long long)ifp->stats.ifi_ibytes, (unsigned long long)ifp->stats.ifi_iqdrops, @@ -1669,8 +1662,7 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) (unsigned long long)ifp->stats.ifi_ierrors); vty_out(vty, - " output packets %llu, bytes %llu," - " multicast packets %llu\n", + " output packets %llu, bytes %llu, multicast packets %llu\n", (unsigned long long)ifp->stats.ifi_opackets, (unsigned long long)ifp->stats.ifi_obytes, (unsigned long long)ifp->stats.ifi_omcasts); diff --git a/zebra/ipforward_solaris.c b/zebra/ipforward_solaris.c index 1a45328248..3d6a29bec6 100644 --- a/zebra/ipforward_solaris.c +++ b/zebra/ipforward_solaris.c @@ -72,8 +72,7 @@ static int solaris_nd(const int cmd, const char *parameter, const int value) snprintf(nd_buf, ND_BUFFER_SIZE, "%s", parameter); else { flog_err_sys(EC_LIB_SYSTEM_CALL, - "internal error - inappropriate command given to " - "solaris_nd()%s:%d", + "internal error - inappropriate command given to solaris_nd()%s:%d", __FILE__, __LINE__); return -1; } diff --git a/zebra/irdp_interface.c b/zebra/irdp_interface.c index 87a1f5fdc7..2ab5fd3a4c 100644 --- a/zebra/irdp_interface.c +++ b/zebra/irdp_interface.c @@ -224,8 +224,7 @@ static void irdp_if_start(struct interface *ifp, int multicast, } if ((irdp_sock < 0) && ((irdp_sock = irdp_sock_init()) < 0)) { flog_warn(EC_ZEBRA_IRDP_CANNOT_ACTIVATE_IFACE, - "IRDP: Cannot activate interface %s (cannot create " - "IRDP socket)", + "IRDP: Cannot activate interface %s (cannot create IRDP socket)", ifp->name); return; } @@ -503,8 +502,7 @@ DEFUN (ip_irdp_minadvertinterval, return CMD_SUCCESS; } else { vty_out(vty, - "%% MinAdvertInterval must be less than or equal to " - "MaxAdvertInterval\n"); + "%% MinAdvertInterval must be less than or equal to MaxAdvertInterval\n"); return CMD_WARNING_CONFIG_FAILED; } } @@ -528,8 +526,7 @@ DEFUN (ip_irdp_maxadvertinterval, return CMD_SUCCESS; } else { vty_out(vty, - "%% MaxAdvertInterval must be greater than or equal to " - "MinAdvertInterval\n"); + "%% MaxAdvertInterval must be greater than or equal to MinAdvertInterval\n"); return CMD_WARNING_CONFIG_FAILED; } } diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 950690b943..873d221149 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -712,8 +712,7 @@ int ifm_read(struct if_msghdr *ifm) { if (ifp->ifindex != ifm->ifm_index) { zlog_debug( - "%s: index mismatch, ifname %s, ifp index %d, " - "ifm index %d", + "%s: index mismatch, ifname %s, ifp index %d, ifm index %d", __func__, ifp->name, ifp->ifindex, ifm->ifm_index); return -1; @@ -833,9 +832,7 @@ static void ifam_read_mesg(struct ifa_msghdr *ifm, union sockunion *addr, ? ip_masklen(mask->sin.sin_addr) : ip6_masklen(mask->sin6.sin6_addr); zlog_debug( - "%s: ifindex %d, ifname %s, ifam_addrs {%s}, " - "ifam_flags 0x%x, addr %s/%d broad %s dst %s " - "gateway %s", + "%s: ifindex %d, ifname %s, ifam_addrs {%s}, ifam_flags 0x%x, addr %s/%d broad %s dst %s gateway %s", __func__, ifm->ifam_index, (ifnlen ? ifname : "(nil)"), rtatostr(ifm->ifam_addrs, fbuf, sizeof(fbuf)), @@ -978,8 +975,7 @@ static int rtm_read_mesg(struct rt_msghdr *rtm, union sockunion *dest, /* rt_msghdr version check. */ if (rtm->rtm_version != RTM_VERSION) flog_warn(EC_ZEBRA_RTM_VERSION_MISMATCH, - "Routing message version different %d should be %d." - "This may cause problem\n", + "Routing message version different %d should be %d.This may cause problem\n", rtm->rtm_version, RTM_VERSION); /* Be sure structure is cleared */ diff --git a/zebra/main.c b/zebra/main.c index 71c7ebb62f..9c5a1ef9b6 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -35,6 +35,7 @@ #include "vrf.h" #include "libfrr.h" #include "routemap.h" +#include "routing_nb.h" #include "zebra/zebra_router.h" #include "zebra/zebra_errors.h" @@ -258,14 +259,14 @@ static const struct frr_yang_module_info *const zebra_yang_modules[] = { &frr_route_map_info, &frr_zebra_info, &frr_vrf_info, + &frr_routing_info, }; FRR_DAEMON_INFO( zebra, ZEBRA, .vty_port = ZEBRA_VTY_PORT, .flags = FRR_NO_ZCLIENT, .proghelp = - "Daemon which manages kernel routing table management " - "and\nredistribution between different routing protocols.", + "Daemon which manages kernel routing table management and\nredistribution between different routing protocols.", .signals = zebra_signals, .n_signals = array_size(zebra_signals), @@ -415,12 +416,12 @@ int main(int argc, char **argv) rib_init(); zebra_if_init(); zebra_debug_init(); - router_id_cmd_init(); /* * Initialize NS( and implicitly the VRF module), and make kernel * routing socket. */ zebra_ns_init((const char *)vrf_default_name_configured); + router_id_cmd_init(); zebra_vty_init(); access_list_init(); prefix_list_init(); diff --git a/zebra/rib.h b/zebra/rib.h index ec992974fa..6ec9241b73 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -144,6 +144,10 @@ struct route_entry { #define ROUTE_ENTRY_INSTALLED 0x10 /* Route has Failed installation into the Data Plane in some manner */ #define ROUTE_ENTRY_FAILED 0x20 +/* Route has a 'fib' set of nexthops, probably because the installed set + * differs from the rib/normal set of nexthops. + */ +#define ROUTE_ENTRY_USE_FIB_NHG 0x40 /* Sequence value incremented for each dataplane operation */ uint32_t dplane_sequence; @@ -526,26 +530,28 @@ DECLARE_HOOK(rib_update, (struct route_node * rn, const char *reason), (rn, reason)) /* - * Access active nexthop-group, either RIB or FIB version + * Access installed/fib nexthops, which may be a subset of the + * rib nexthops. */ static inline struct nexthop_group *rib_get_fib_nhg(struct route_entry *re) { - if (re->fib_ng.nexthop) + /* If the fib set is a subset of the active rib set, + * use the dedicated fib list. + */ + if (CHECK_FLAG(re->status, ROUTE_ENTRY_USE_FIB_NHG)) return &(re->fib_ng); else return &(re->nhe->nhg); } /* - * Access active nexthop-group, either RIB or FIB version + * Access backup nexthop-group that represents the installed backup nexthops; + * any installed backup will be on the fib list. */ static inline struct nexthop_group *rib_get_fib_backup_nhg( struct route_entry *re) { - if (re->fib_backup_ng.nexthop) - return &(re->fib_backup_ng); - else - return zebra_nhg_get_backup_nhg(re->nhe); + return &(re->fib_backup_ng); } extern void zebra_vty_init(void); diff --git a/zebra/router-id.c b/zebra/router-id.c index 710f2f6c27..ba9e721614 100644 --- a/zebra/router-id.c +++ b/zebra/router-id.c @@ -69,11 +69,10 @@ static int router_id_bad_address(struct connected *ifc) return 0; } -void router_id_get(struct prefix *p, vrf_id_t vrf_id) +void router_id_get(struct prefix *p, struct zebra_vrf *zvrf) { struct listnode *node; struct connected *c; - struct zebra_vrf *zvrf = vrf_info_get(vrf_id); p->u.prefix4.s_addr = INADDR_ANY; p->family = AF_INET; @@ -92,27 +91,18 @@ void router_id_get(struct prefix *p, vrf_id_t vrf_id) } } -static void router_id_set(struct prefix *p, vrf_id_t vrf_id) +static void router_id_set(struct prefix *p, struct zebra_vrf *zvrf) { struct prefix p2; struct listnode *node; struct zserv *client; - struct zebra_vrf *zvrf; - - if (p->u.prefix4.s_addr == 0) /* unset */ - { - zvrf = vrf_info_lookup(vrf_id); - if (!zvrf) - return; - } else /* set */ - zvrf = vrf_info_get(vrf_id); zvrf->rid_user_assigned.u.prefix4.s_addr = p->u.prefix4.s_addr; - router_id_get(&p2, vrf_id); + router_id_get(&p2, zvrf); for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) - zsend_router_id_update(client, &p2, vrf_id); + zsend_router_id_update(client, &p2, zvrf->vrf->vrf_id); } void router_id_add_address(struct connected *ifc) @@ -127,7 +117,7 @@ void router_id_add_address(struct connected *ifc) if (router_id_bad_address(ifc)) return; - router_id_get(&before, zvrf_id(zvrf)); + router_id_get(&before, zvrf); if (if_is_loopback(ifc->ifp)) l = zvrf->rid_lo_sorted_list; @@ -137,7 +127,7 @@ void router_id_add_address(struct connected *ifc) if (!router_id_find_node(l, ifc)) listnode_add_sort(l, ifc); - router_id_get(&after, zvrf_id(zvrf)); + router_id_get(&after, zvrf); if (prefix_same(&before, &after)) return; @@ -159,7 +149,7 @@ void router_id_del_address(struct connected *ifc) if (router_id_bad_address(ifc)) return; - router_id_get(&before, zvrf_id(zvrf)); + router_id_get(&before, zvrf); if (if_is_loopback(ifc->ifp)) l = zvrf->rid_lo_sorted_list; @@ -169,7 +159,7 @@ void router_id_del_address(struct connected *ifc) if ((c = router_id_find_node(l, ifc))) listnode_delete(l, c); - router_id_get(&after, zvrf_id(zvrf)); + router_id_get(&after, zvrf); if (prefix_same(&before, &after)) return; @@ -178,38 +168,30 @@ void router_id_del_address(struct connected *ifc) zsend_router_id_update(client, &after, zvrf_id(zvrf)); } -void router_id_write(struct vty *vty) +void router_id_write(struct vty *vty, struct zebra_vrf *zvrf) { - struct vrf *vrf; - struct zebra_vrf *zvrf; + char space[2]; + + memset(space, 0, sizeof(space)); + + if (zvrf_id(zvrf) != VRF_DEFAULT) + snprintf(space, sizeof(space), "%s", " "); - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - if ((zvrf = vrf->info) != NULL) - if (zvrf->rid_user_assigned.u.prefix4.s_addr - != INADDR_ANY) { - if (zvrf_id(zvrf) == VRF_DEFAULT) - vty_out(vty, "router-id %s\n", - inet_ntoa( - zvrf->rid_user_assigned - .u.prefix4)); - else - vty_out(vty, "router-id %s vrf %s\n", - inet_ntoa( - zvrf->rid_user_assigned - .u.prefix4), - zvrf_name(zvrf)); - } + if (zvrf->rid_user_assigned.u.prefix4.s_addr != INADDR_ANY) { + vty_out(vty, "%srouter-id %s\n", space, + inet_ntoa(zvrf->rid_user_assigned.u.prefix4)); + } } DEFUN (router_id, router_id_cmd, - "router-id A.B.C.D [vrf NAME]", + "router-id A.B.C.D vrf NAME", "Manually set the router-id\n" - "IP address to use for router-id\n" - VRF_CMD_HELP_STR) + "IP address to use for router-id\n" VRF_CMD_HELP_STR) { int idx_ipv4 = 1; int idx_name = 3; + struct zebra_vrf *zvrf; struct prefix rid; vrf_id_t vrf_id = VRF_DEFAULT; @@ -224,23 +206,45 @@ DEFUN (router_id, if (argc > 2) VRF_GET_ID(vrf_id, argv[idx_name]->arg, false); - router_id_set(&rid, vrf_id); + zvrf = vrf_info_lookup(vrf_id); + router_id_set(&rid, zvrf); + + return CMD_SUCCESS; +} + +DEFUN (router_id_in_vrf, + router_id_in_vrf_cmd, + "router-id A.B.C.D", + "Manuall set the router-id\n" + "IP address to use for router-id\n") +{ + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); + int idx_ipv4 = 1; + struct prefix rid; + + rid.u.prefix4.s_addr = inet_addr(argv[idx_ipv4]->arg); + if (!rid.u.prefix4.s_addr) + return CMD_WARNING_CONFIG_FAILED; + + rid.prefixlen = 32; + rid.family = AF_INET; + + router_id_set(&rid, zvrf); return CMD_SUCCESS; } DEFUN (no_router_id, no_router_id_cmd, - "no router-id [A.B.C.D [vrf NAME]]", + "no router-id [A.B.C.D vrf NAME]", NO_STR "Remove the manually configured router-id\n" - "IP address to use for router-id\n" - VRF_CMD_HELP_STR) + "IP address to use for router-id\n" VRF_CMD_HELP_STR) { int idx_name = 4; - struct prefix rid; vrf_id_t vrf_id = VRF_DEFAULT; + struct zebra_vrf *zvrf; rid.u.prefix4.s_addr = 0; rid.prefixlen = 0; @@ -249,7 +253,28 @@ DEFUN (no_router_id, if (argc > 3) VRF_GET_ID(vrf_id, argv[idx_name]->arg, false); - router_id_set(&rid, vrf_id); + zvrf = vrf_info_get(vrf_id); + router_id_set(&rid, zvrf); + + return CMD_SUCCESS; +} + +DEFUN (no_router_id_in_vrf, + no_router_id_in_vrf_cmd, + "no router-id [A.B.C.D]", + NO_STR + "Remove the manually configured router-id\n" + "IP address to use for router-id\n") +{ + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); + + struct prefix rid; + + rid.u.prefix4.s_addr = 0; + rid.prefixlen = 0; + rid.family = AF_INET; + + router_id_set(&rid, zvrf); return CMD_SUCCESS; } @@ -298,6 +323,10 @@ void router_id_cmd_init(void) { install_element(CONFIG_NODE, &router_id_cmd); install_element(CONFIG_NODE, &no_router_id_cmd); + install_element(CONFIG_NODE, &router_id_in_vrf_cmd); + install_element(VRF_NODE, &router_id_in_vrf_cmd); + install_element(CONFIG_NODE, &no_router_id_in_vrf_cmd); + install_element(VRF_NODE, &no_router_id_in_vrf_cmd); install_element(VIEW_NODE, &show_router_id_cmd); } diff --git a/zebra/router-id.h b/zebra/router-id.h index f7d16853f1..c69c321fda 100644 --- a/zebra/router-id.h +++ b/zebra/router-id.h @@ -34,12 +34,12 @@ extern "C" { #endif -extern void router_id_add_address(struct connected *); -extern void router_id_del_address(struct connected *); -extern void router_id_init(struct zebra_vrf *); +extern void router_id_add_address(struct connected *c); +extern void router_id_del_address(struct connected *c); +extern void router_id_init(struct zebra_vrf *zvrf); extern void router_id_cmd_init(void); -extern void router_id_write(struct vty *); -extern void router_id_get(struct prefix *, vrf_id_t); +extern void router_id_write(struct vty *vty, struct zebra_vrf *zvrf); +extern void router_id_get(struct prefix *p, struct zebra_vrf *zvrf); #ifdef __cplusplus } diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 40a7eeba8e..07e8e37b82 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -2686,7 +2686,7 @@ static ssize_t netlink_neigh_update_msg_encode( if (datalen < sizeof(*req)) return 0; - memset(req, 0, datalen); + memset(req, 0, sizeof(*req)); op = dplane_ctx_get_op(ctx); @@ -2703,7 +2703,7 @@ static ssize_t netlink_neigh_update_msg_encode( req->ndm.ndm_flags = flags; req->ndm.ndm_ifindex = dplane_ctx_get_ifindex(ctx); - if (!nl_attr_put(&req->n, sizeof(req), NDA_PROTOCOL, &protocol, + if (!nl_attr_put(&req->n, datalen, NDA_PROTOCOL, &protocol, sizeof(protocol))) return 0; diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index 64fd7fa491..2eadaf48f4 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -50,8 +50,7 @@ static int kernel_rtm_add_labels(struct mpls_label_stack *nh_label, { if (nh_label->num_labels > 1) { flog_warn(EC_ZEBRA_MAX_LABELS_PUSH, - "%s: can't push %u labels at " - "once (maximum is 1)", + "%s: can't push %u labels at once (maximum is 1)", __func__, nh_label->num_labels); return -1; } diff --git a/zebra/rtadv.c b/zebra/rtadv.c index fa0a682d07..13b7c150a3 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -2282,13 +2282,11 @@ static int nd_dump_vty(struct vty *vty, struct interface *ifp) interval = rtadv->MaxRtrAdvInterval; if (interval % 1000) vty_out(vty, - " ND router advertisements are sent every " - "%d milliseconds\n", + " ND router advertisements are sent every %d milliseconds\n", interval); else vty_out(vty, - " ND router advertisements are sent every " - "%d seconds\n", + " ND router advertisements are sent every %d seconds\n", interval / 1000); if (!rtadv->UseFastRexmit) vty_out(vty, @@ -2302,8 +2300,7 @@ static int nd_dump_vty(struct vty *vty, struct interface *ifp) vty_out(vty, " ND router advertisements lifetime tracks ra-interval\n"); vty_out(vty, - " ND router advertisement default router preference is " - "%s\n", + " ND router advertisement default router preference is %s\n", rtadv_pref_strs[rtadv->DefaultPreference]); if (rtadv->AdvManagedFlag) vty_out(vty, diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c index 28529cc138..0a1fb82d95 100644 --- a/zebra/rtread_getmsg.c +++ b/zebra/rtread_getmsg.c @@ -230,8 +230,7 @@ void route_read(struct zebra_ns *zns) if (msgdata.len % sizeof(mib2_ipRouteEntry_t) != 0) { zlog_debug( - "getmsg(data) returned " - "msgdata.len = %d (%% sizeof(mib2_ipRouteEntry_t) != 0)", + "getmsg(data) returned msgdata.len = %d (%% sizeof(mib2_ipRouteEntry_t) != 0)", msgdata.len); goto exit; } diff --git a/zebra/rule_netlink.c b/zebra/rule_netlink.c index b7be398506..648e9eabe1 100644 --- a/zebra/rule_netlink.c +++ b/zebra/rule_netlink.c @@ -58,10 +58,12 @@ * Returns -1 on failure, 0 when the msg doesn't fit entirely in the buffer * or the number of bytes written to buf. */ -static ssize_t netlink_rule_msg_encode( - int cmd, const struct zebra_dplane_ctx *ctx, uint32_t filter_bm, - uint32_t priority, uint32_t table, const struct prefix *src_ip, - const struct prefix *dst_ip, uint32_t fwmark, void *buf, size_t buflen) +static ssize_t +netlink_rule_msg_encode(int cmd, const struct zebra_dplane_ctx *ctx, + uint32_t filter_bm, uint32_t priority, uint32_t table, + const struct prefix *src_ip, + const struct prefix *dst_ip, uint32_t fwmark, + uint8_t dsfield, void *buf, size_t buflen) { uint8_t protocol = RTPROT_ZEBRA; int family; @@ -122,6 +124,10 @@ static ssize_t netlink_rule_msg_encode( return 0; } + /* dsfield, if specified */ + if (filter_bm & PBR_FILTER_DSFIELD) + req->frh.tos = dsfield; + /* Route table to use to forward, if filter criteria matches. */ if (table < 256) req->frh.table = table; @@ -145,16 +151,15 @@ static ssize_t netlink_rule_msg_encode( /* Install or uninstall specified rule for a specific interface. * Form netlink message and ship it. */ -static int -netlink_rule_update_internal(int cmd, const struct zebra_dplane_ctx *ctx, - uint32_t filter_bm, uint32_t priority, - uint32_t table, const struct prefix *src_ip, - const struct prefix *dst_ip, uint32_t fwmark) +static int netlink_rule_update_internal( + int cmd, const struct zebra_dplane_ctx *ctx, uint32_t filter_bm, + uint32_t priority, uint32_t table, const struct prefix *src_ip, + const struct prefix *dst_ip, uint32_t fwmark, uint8_t dsfield) { char buf[NL_PKT_BUF_SIZE]; netlink_rule_msg_encode(cmd, ctx, filter_bm, priority, table, src_ip, - dst_ip, fwmark, buf, sizeof(buf)); + dst_ip, fwmark, dsfield, buf, sizeof(buf)); return netlink_talk_info(netlink_talk_filter, (void *)&buf, dplane_ctx_get_ns(ctx), 0); } @@ -188,7 +193,8 @@ enum zebra_dplane_result kernel_pbr_rule_update(struct zebra_dplane_ctx *ctx) dplane_ctx_rule_get_priority(ctx), dplane_ctx_rule_get_table(ctx), dplane_ctx_rule_get_src_ip(ctx), dplane_ctx_rule_get_dst_ip(ctx), - dplane_ctx_rule_get_fwmark(ctx)); + dplane_ctx_rule_get_fwmark(ctx), + dplane_ctx_rule_get_dsfield(ctx)); /** * Delete the old one. @@ -203,7 +209,8 @@ enum zebra_dplane_result kernel_pbr_rule_update(struct zebra_dplane_ctx *ctx) dplane_ctx_rule_get_old_table(ctx), dplane_ctx_rule_get_old_src_ip(ctx), dplane_ctx_rule_get_old_dst_ip(ctx), - dplane_ctx_rule_get_old_fwmark(ctx)); + dplane_ctx_rule_get_old_fwmark(ctx), + dplane_ctx_rule_get_old_dsfield(ctx)); return (ret == 0 ? ZEBRA_DPLANE_REQUEST_SUCCESS @@ -247,7 +254,16 @@ int netlink_rule_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) } frh = NLMSG_DATA(h); + if (frh->family != AF_INET && frh->family != AF_INET6) { + if (frh->family == RTNL_FAMILY_IPMR + || frh->family == RTNL_FAMILY_IP6MR) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "Received rule netlink that we are ignoring for family %u, rule change: %u", + frh->family, h->nlmsg_type); + return 0; + } flog_warn( EC_ZEBRA_NETLINK_INVALID_AF, "Invalid address family: %u received from kernel rule change: %u", diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index dc7c595d26..33972681f8 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1416,6 +1416,7 @@ static struct nexthop *nexthop_from_zapi(struct route_entry *re, struct nexthop *nexthop = NULL; struct ipaddr vtep_ip; struct interface *ifp; + int i; char nhbuf[INET6_ADDRSTRLEN] = ""; switch (api_nh->type) { @@ -1521,17 +1522,36 @@ static struct nexthop *nexthop_from_zapi(struct route_entry *re, nexthop->weight = api_nh->weight; if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) { - if (api_nh->backup_idx < api->backup_nexthop_num) { - /* Capture backup info */ - SET_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP); - nexthop->backup_idx = api_nh->backup_idx; - } else { - /* Warn about invalid backup index */ + /* Validate count */ + if (api_nh->backup_num > NEXTHOP_MAX_BACKUPS) { if (IS_ZEBRA_DEBUG_RECV || IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%s: invalid backup nh idx %d", - __func__, api_nh->backup_idx); + zlog_debug("%s: invalid backup nh count %d", + __func__, api_nh->backup_num); + nexthop_free(nexthop); + nexthop = NULL; + goto done; + } + + /* Copy backup info */ + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP); + nexthop->backup_num = api_nh->backup_num; + + for (i = 0; i < api_nh->backup_num; i++) { + /* Validate backup index */ + if (api_nh->backup_idx[i] < api->backup_nexthop_num) { + nexthop->backup_idx[i] = api_nh->backup_idx[i]; + } else { + if (IS_ZEBRA_DEBUG_RECV || IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s: invalid backup nh idx %d", + __func__, + api_nh->backup_idx[i]); + nexthop_free(nexthop); + nexthop = NULL; + goto done; + } } } + done: return nexthop; } @@ -1703,7 +1723,7 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) __func__, nhbuf); } UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP); - nexthop->backup_idx = 0; + nexthop->backup_num = 0; } /* MPLS labels for BGP-LU or Segment Routing */ @@ -1879,7 +1899,7 @@ static void zread_router_id_add(ZAPI_HANDLER_ARGS) /* Router-id information is needed. */ vrf_bitmap_set(client->ridinfo, zvrf_id(zvrf)); - router_id_get(&p, zvrf_id(zvrf)); + router_id_get(&p, zvrf); zsend_router_id_update(client, &p, zvrf_id(zvrf)); } @@ -1981,6 +2001,56 @@ static void zread_vrf_unregister(ZAPI_HANDLER_ARGS) } /* + * Validate incoming zapi mpls lsp / labels message + */ +static int zapi_labels_validate(const struct zapi_labels *zl) +{ + int ret = -1; + int i, j, idx; + uint32_t bits[8]; + uint32_t ival; + const struct zapi_nexthop *znh; + + /* Validate backup info: no duplicates for a single primary */ + if (zl->backup_nexthop_num == 0) { + ret = 0; + goto done; + } + + for (j = 0; j < zl->nexthop_num; j++) { + znh = &zl->nexthops[j]; + + memset(bits, 0, sizeof(bits)); + + for (i = 0; i < znh->backup_num; i++) { + idx = znh->backup_idx[i] / 32; + + ival = 1 << znh->backup_idx[i] % 32; + + /* Check whether value is already used */ + if (ival & bits[idx]) { + /* Fail */ + + if (IS_ZEBRA_DEBUG_RECV) + zlog_debug("%s: invalid zapi mpls message: duplicate backup nexthop index %d", + __func__, + znh->backup_idx[i]); + goto done; + } + + /* Mark index value */ + bits[idx] |= ival; + } + } + + ret = 0; + +done: + + return ret; +} + +/* * Handle request to create an MPLS LSP. * * A single message can fully specify an LSP with multiple nexthops. @@ -2006,6 +2076,10 @@ static void zread_mpls_labels_add(ZAPI_HANDLER_ARGS) if (!mpls_enabled) return; + /* Validate; will debug on failure */ + if (zapi_labels_validate(&zl) < 0) + return; + ret = mpls_zapi_labels_process(true, zvrf, &zl); if (ret < 0) { if (IS_ZEBRA_DEBUG_RECV) @@ -2087,6 +2161,10 @@ static void zread_mpls_labels_replace(ZAPI_HANDLER_ARGS) if (!mpls_enabled) return; + /* Validate; will debug on failure */ + if (zapi_labels_validate(&zl) < 0) + return; + /* This removes everything, then re-adds from the client's * zapi message. Since the LSP will be processed later, on this * this same pthread, all of the changes will 'appear' at once. @@ -2526,6 +2604,7 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS) STREAM_GET(&zpr.rule.filter.dst_ip.u.prefix, s, prefix_blen(&zpr.rule.filter.dst_ip)); STREAM_GETW(s, zpr.rule.filter.dst_port); + STREAM_GETC(s, zpr.rule.filter.dsfield); STREAM_GETL(s, zpr.rule.filter.fwmark); STREAM_GETL(s, zpr.rule.action.table); STREAM_GETL(s, zpr.rule.ifindex); @@ -2556,14 +2635,16 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS) if (zpr.rule.filter.dst_port) zpr.rule.filter.filter_bm |= PBR_FILTER_DST_PORT; + if (zpr.rule.filter.dsfield) + zpr.rule.filter.filter_bm |= PBR_FILTER_DSFIELD; + if (zpr.rule.filter.fwmark) zpr.rule.filter.filter_bm |= PBR_FILTER_FWMARK; if (!(zpr.rule.filter.src_ip.family == AF_INET || zpr.rule.filter.src_ip.family == AF_INET6)) { zlog_warn( - "Unsupported PBR source IP family: %s (%" PRIu8 - ")", + "Unsupported PBR source IP family: %s (%hhu)", family2str(zpr.rule.filter.src_ip.family), zpr.rule.filter.src_ip.family); return; @@ -2571,8 +2652,7 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS) if (!(zpr.rule.filter.dst_ip.family == AF_INET || zpr.rule.filter.dst_ip.family == AF_INET6)) { zlog_warn( - "Unsupported PBR destination IP family: %s (%" PRIu8 - ")", + "Unsupported PBR destination IP family: %s (%hhu)", family2str(zpr.rule.filter.dst_ip.family), zpr.rule.filter.dst_ip.family); return; @@ -2667,16 +2747,14 @@ static inline void zread_ipset_entry(ZAPI_HANDLER_ARGS) if (!(zpi.dst.family == AF_INET || zpi.dst.family == AF_INET6)) { zlog_warn( - "Unsupported PBR destination IP family: %s (%" PRIu8 - ")", + "Unsupported PBR destination IP family: %s (%hhu)", family2str(zpi.dst.family), zpi.dst.family); goto stream_failure; } if (!(zpi.src.family == AF_INET || zpi.src.family == AF_INET6)) { zlog_warn( - "Unsupported PBR source IP family: %s (%" PRIu8 - ")", + "Unsupported PBR source IP family: %s (%hhu)", family2str(zpi.src.family), zpi.src.family); goto stream_failure; } diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index e34b6f23ff..0cc7139d6b 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -204,6 +204,7 @@ struct dplane_ctx_rule { /* Filter criteria */ uint32_t filter_bm; uint32_t fwmark; + uint8_t dsfield; struct prefix src_ip; struct prefix dst_ip; }; @@ -1676,6 +1677,20 @@ uint32_t dplane_ctx_rule_get_old_fwmark(const struct zebra_dplane_ctx *ctx) return ctx->u.rule.old.fwmark; } +uint8_t dplane_ctx_rule_get_dsfield(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.rule.new.dsfield; +} + +uint8_t dplane_ctx_rule_get_old_dsfield(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.rule.old.dsfield; +} + const struct prefix * dplane_ctx_rule_get_src_ip(const struct zebra_dplane_ctx *ctx) { @@ -2001,10 +2016,19 @@ int dplane_ctx_lsp_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, break; } - /* Need to copy flags too */ + /* Need to copy flags and backup info too */ new_nhlfe->flags = nhlfe->flags; new_nhlfe->nexthop->flags = nhlfe->nexthop->flags; + if (CHECK_FLAG(new_nhlfe->nexthop->flags, + NEXTHOP_FLAG_HAS_BACKUP)) { + new_nhlfe->nexthop->backup_num = + nhlfe->nexthop->backup_num; + memcpy(new_nhlfe->nexthop->backup_idx, + nhlfe->nexthop->backup_idx, + new_nhlfe->nexthop->backup_num); + } + if (nhlfe == lsp->best_nhlfe) ctx->u.lsp.best_nhlfe = new_nhlfe; } @@ -2104,8 +2128,15 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx, if (re) { nhg = rib_get_fib_nhg(re); - copy_nexthops(&(ctx->u.pw.nhg.nexthop), - nhg->nexthop, NULL); + if (nhg && nhg->nexthop) + copy_nexthops(&(ctx->u.pw.nhg.nexthop), + nhg->nexthop, NULL); + + /* Include any installed backup nexthops */ + nhg = rib_get_fib_backup_nhg(re); + if (nhg && nhg->nexthop) + copy_nexthops(&(ctx->u.pw.nhg.nexthop), + nhg->nexthop, NULL); } route_unlock_node(rn); } @@ -2129,6 +2160,7 @@ static void dplane_ctx_rule_init_single(struct dplane_ctx_rule *dplane_rule, dplane_rule->filter_bm = rule->rule.filter.filter_bm; dplane_rule->fwmark = rule->rule.filter.fwmark; + dplane_rule->dsfield = rule->rule.filter.dsfield; prefix_copy(&(dplane_rule->dst_ip), &rule->rule.filter.dst_ip); prefix_copy(&(dplane_rule->src_ip), &rule->rule.filter.src_ip); } @@ -2461,6 +2493,7 @@ dplane_route_notif_update(struct route_node *rn, enum zebra_dplane_result ret = ZEBRA_DPLANE_REQUEST_FAILURE; struct zebra_dplane_ctx *new_ctx = NULL; struct nexthop *nexthop; + struct nexthop_group *nhg; if (rn == NULL || re == NULL) goto done; @@ -2482,8 +2515,17 @@ dplane_route_notif_update(struct route_node *rn, nexthops_free(new_ctx->u.rinfo.zd_ng.nexthop); new_ctx->u.rinfo.zd_ng.nexthop = NULL; - copy_nexthops(&(new_ctx->u.rinfo.zd_ng.nexthop), - (rib_get_fib_nhg(re))->nexthop, NULL); + nhg = rib_get_fib_nhg(re); + if (nhg && nhg->nexthop) + copy_nexthops(&(new_ctx->u.rinfo.zd_ng.nexthop), + nhg->nexthop, NULL); + + /* Check for installed backup nexthops also */ + nhg = rib_get_fib_backup_nhg(re); + if (nhg && nhg->nexthop) { + copy_nexthops(&(new_ctx->u.rinfo.zd_ng.nexthop), + nhg->nexthop, NULL); + } for (ALL_NEXTHOPS(new_ctx->u.rinfo.zd_ng, nexthop)) UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); @@ -2583,6 +2625,8 @@ dplane_lsp_notif_update(zebra_lsp_t *lsp, enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE; int ret = EINVAL; struct zebra_dplane_ctx *ctx = NULL; + struct nhlfe_list_head *head; + zebra_nhlfe_t *nhlfe, *new_nhlfe; /* Obtain context block */ ctx = dplane_ctx_alloc(); @@ -2591,10 +2635,27 @@ dplane_lsp_notif_update(zebra_lsp_t *lsp, goto done; } + /* Copy info from zebra LSP */ ret = dplane_ctx_lsp_init(ctx, op, lsp); if (ret != AOK) goto done; + /* Add any installed backup nhlfes */ + head = &(ctx->u.lsp.backup_nhlfe_list); + frr_each(nhlfe_list, head, nhlfe) { + + if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED) && + CHECK_FLAG(nhlfe->nexthop->flags, NEXTHOP_FLAG_FIB)) { + new_nhlfe = zebra_mpls_lsp_add_nh(&(ctx->u.lsp), + nhlfe->type, + nhlfe->nexthop); + + /* Need to copy flags too */ + new_nhlfe->flags = nhlfe->flags; + new_nhlfe->nexthop->flags = nhlfe->nexthop->flags; + } + } + /* Capture info about the source of the notification */ dplane_ctx_set_notif_provider( ctx, @@ -3261,8 +3322,7 @@ int dplane_show_provs_helper(struct vty *vty, bool detailed) out_max = atomic_load_explicit(&prov->dp_out_max, memory_order_relaxed); - vty_out(vty, "%s (%u): in: %"PRIu64", q_max: %"PRIu64", " - "out: %"PRIu64", q_max: %"PRIu64"\n", + vty_out(vty, "%s (%u): in: %"PRIu64", q_max: %"PRIu64", out: %"PRIu64", q_max: %"PRIu64"\n", prov->dp_name, prov->dp_id, in, in_max, out, out_max); DPLANE_LOCK(); @@ -4003,19 +4063,19 @@ bool dplane_is_in_shutdown(void) */ void zebra_dplane_pre_finish(void) { - struct zebra_dplane_provider *dp; + struct zebra_dplane_provider *prov; if (IS_ZEBRA_DEBUG_DPLANE) - zlog_debug("Zebra dataplane pre-fini called"); + zlog_debug("Zebra dataplane pre-finish called"); zdplane_info.dg_is_shutdown = true; /* Notify provider(s) of pending shutdown. */ - TAILQ_FOREACH(dp, &zdplane_info.dg_providers_q, dp_prov_link) { - if (dp->dp_fini == NULL) + TAILQ_FOREACH(prov, &zdplane_info.dg_providers_q, dp_prov_link) { + if (prov->dp_fini == NULL) continue; - dp->dp_fini(dp, true); + prov->dp_fini(prov, true /* early */); } } @@ -4337,7 +4397,10 @@ void zebra_dplane_shutdown(void) zdplane_info.dg_pthread = NULL; zdplane_info.dg_master = NULL; - /* Notify provider(s) of final shutdown. */ + /* Notify provider(s) of final shutdown. + * Note that this call is in the main pthread, so providers must + * be prepared for that. + */ TAILQ_FOREACH(dp, &zdplane_info.dg_providers_q, dp_prov_link) { if (dp->dp_fini == NULL) continue; diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 8e873886df..0fa21f620d 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -412,6 +412,8 @@ uint32_t dplane_ctx_rule_get_filter_bm(const struct zebra_dplane_ctx *ctx); uint32_t dplane_ctx_rule_get_old_filter_bm(const struct zebra_dplane_ctx *ctx); uint32_t dplane_ctx_rule_get_fwmark(const struct zebra_dplane_ctx *ctx); uint32_t dplane_ctx_rule_get_old_fwmark(const struct zebra_dplane_ctx *ctx); +uint8_t dplane_ctx_rule_get_dsfield(const struct zebra_dplane_ctx *ctx); +uint8_t dplane_ctx_rule_get_old_dsfield(const struct zebra_dplane_ctx *ctx); const struct prefix * dplane_ctx_rule_get_src_ip(const struct zebra_dplane_ctx *ctx); const struct prefix * diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c index 47b4965396..f84c8c1fcc 100644 --- a/zebra/zebra_fpm.c +++ b/zebra/zebra_fpm.c @@ -1908,8 +1908,7 @@ static inline void zfpm_init_message_format(const char *format) return; } flog_warn(EC_ZEBRA_PROTOBUF_NOT_AVAILABLE, - "FPM protobuf message format is deprecated and scheduled to be removed. " - "Please convert to using netlink format or contact dev@lists.frrouting.org with your use case."); + "FPM protobuf message format is deprecated and scheduled to be removed. Please convert to using netlink format or contact dev@lists.frrouting.org with your use case."); zfpm_g->message_format = ZFPM_MSG_FORMAT_PROTOBUF; return; } diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index e741268ebb..f905036323 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -120,7 +120,8 @@ static int mpls_lsp_uninstall_all(struct hash *lsp_table, zebra_lsp_t *lsp, enum lsp_types_t type); static int mpls_static_lsp_uninstall_all(struct zebra_vrf *zvrf, mpls_label_t in_label); -static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty); +static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty, + const char *indent); static void lsp_print(struct vty *vty, zebra_lsp_t *lsp); static void *slsp_alloc(void *p); static int snhlfe_match(zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype, @@ -232,8 +233,7 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label, if (IS_ZEBRA_DEBUG_MPLS) { nhlfe2str(nhlfe, buf, BUFSIZ); zlog_debug( - "LSP in-label %u type %d nexthop %s " - "out-label changed", + "LSP in-label %u type %d nexthop %s out-label changed", lsp->ile.in_label, lsp_type, buf); } @@ -254,8 +254,7 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label, if (IS_ZEBRA_DEBUG_MPLS) { nhlfe2str(nhlfe, buf, BUFSIZ); zlog_debug( - "Add LSP in-label %u type %d nexthop %s " - "out-label %u", + "Add LSP in-label %u type %d nexthop %s out-label %u", lsp->ile.in_label, lsp_type, buf, nexthop->nh_label->label[0]); } @@ -928,8 +927,7 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data) if (newbest) nhlfe2str(newbest, buf2, sizeof(buf2)); zlog_debug( - "Process LSP in-label %u oldbest %s newbest %s " - "flags 0x%x ecmp# %d", + "Process LSP in-label %u oldbest %s newbest %s flags 0x%x ecmp# %d", lsp->ile.in_label, oldbest ? buf : "NULL", newbest ? buf2 : "NULL", lsp->flags, lsp->num_ecmp); } @@ -1506,7 +1504,9 @@ static json_object *nhlfe_json(zebra_nhlfe_t *nhlfe) { char buf[BUFSIZ]; json_object *json_nhlfe = NULL; + json_object *json_backups = NULL; struct nexthop *nexthop = nhlfe->nexthop; + int i; json_nhlfe = json_object_new_object(); json_object_string_add(json_nhlfe, "type", nhlfe_type2str(nhlfe->type)); @@ -1537,13 +1537,27 @@ static json_object *nhlfe_json(zebra_nhlfe_t *nhlfe) default: break; } + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) { + json_backups = json_object_new_array(); + for (i = 0; i < nexthop->backup_num; i++) { + json_object_array_add( + json_backups, + json_object_new_int(nexthop->backup_idx[i])); + } + + json_object_object_add(json_nhlfe, "backupIndex", + json_backups); + } + return json_nhlfe; } /* * Print the NHLFE for a LSP forwarding entry. */ -static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty) +static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty, + const char *indent) { struct nexthop *nexthop; char buf[MPLS_LABEL_STRLEN]; @@ -1558,6 +1572,10 @@ static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty) nexthop->nh_label->label, buf, sizeof(buf), 0), nhlfe->distance); + + if (indent) + vty_out(vty, "%s", indent); + switch (nexthop->type) { case NEXTHOP_TYPE_IPV4: case NEXTHOP_TYPE_IPV4_IFINDEX: @@ -1595,31 +1613,34 @@ static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty) static void lsp_print(struct vty *vty, zebra_lsp_t *lsp) { zebra_nhlfe_t *nhlfe, *backup; - int i; + int i, j; vty_out(vty, "Local label: %u%s\n", lsp->ile.in_label, CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED) ? " (installed)" : ""); frr_each(nhlfe_list, &lsp->nhlfe_list, nhlfe) { - nhlfe_print(nhlfe, vty); + nhlfe_print(nhlfe, vty, NULL); + + if (nhlfe->nexthop == NULL || + !CHECK_FLAG(nhlfe->nexthop->flags, + NEXTHOP_FLAG_HAS_BACKUP)) + continue; - if (nhlfe->nexthop && - CHECK_FLAG(nhlfe->nexthop->flags, - NEXTHOP_FLAG_HAS_BACKUP)) { - /* Find backup in backup list */ + /* Backup nhlfes: find backups in backup list */ + for (j = 0; j < nhlfe->nexthop->backup_num; j++) { i = 0; backup = NULL; frr_each(nhlfe_list, &lsp->backup_nhlfe_list, backup) { - if (i == nhlfe->nexthop->backup_idx) + if (i == nhlfe->nexthop->backup_idx[j]) break; i++; } if (backup) { vty_out(vty, " [backup %d]", i); - nhlfe_print(backup, vty); + nhlfe_print(backup, vty, " "); } } } @@ -1643,6 +1664,19 @@ static json_object *lsp_json(zebra_lsp_t *lsp) json_object_array_add(json_nhlfe_list, nhlfe_json(nhlfe)); json_object_object_add(json, "nexthops", json_nhlfe_list); + json_nhlfe_list = NULL; + + + frr_each(nhlfe_list, &lsp->backup_nhlfe_list, nhlfe) { + if (json_nhlfe_list == NULL) + json_nhlfe_list = json_object_new_array(); + + json_object_array_add(json_nhlfe_list, nhlfe_json(nhlfe)); + } + + if (json_nhlfe_list) + json_object_object_add(json, "backupNexthops", json_nhlfe_list); + return json; } @@ -2112,6 +2146,7 @@ static int update_nhlfes_from_ctx(struct nhlfe_list_head *nhlfe_head, __func__, buf); SET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED); + SET_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED); } else { if (is_debug) @@ -2119,6 +2154,7 @@ static int update_nhlfes_from_ctx(struct nhlfe_list_head *nhlfe_head, __func__, buf); UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED); + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED); } if (CHECK_FLAG(ctx_nhlfe->nexthop->flags, @@ -2140,6 +2176,7 @@ static int update_nhlfes_from_ctx(struct nhlfe_list_head *nhlfe_head, zlog_debug("%s: no match for lsp nhlfe %s", __func__, buf); UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED); + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED); UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); } @@ -3335,7 +3372,14 @@ static int lsp_znh_install(zebra_lsp_t *lsp, enum lsp_types_t type, /* Update backup info if present */ if (CHECK_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) { - nhlfe->nexthop->backup_idx = znh->backup_idx; + if (znh->backup_num > NEXTHOP_MAX_BACKUPS) { + nhlfe_del(nhlfe); + return -1; + } + + nhlfe->nexthop->backup_num = znh->backup_num; + memcpy(nhlfe->nexthop->backup_idx, znh->backup_idx, + znh->backup_num); SET_FLAG(nhlfe->nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP); } @@ -3408,7 +3452,7 @@ int mpls_lsp_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type, return 0; if (IS_ZEBRA_DEBUG_MPLS) { - nhlfe2str(nhlfe, buf, BUFSIZ); + nhlfe2str(nhlfe, buf, sizeof(buf)); zlog_debug("Del LSP in-label %u type %d nexthop %s flags 0x%x", in_label, type, buf, nhlfe->flags); } @@ -3639,10 +3683,9 @@ int zebra_mpls_static_lsp_add(struct zebra_vrf *zvrf, mpls_label_t in_label, return 0; if (IS_ZEBRA_DEBUG_MPLS) { - snhlfe2str(snhlfe, buf, BUFSIZ); + snhlfe2str(snhlfe, buf, sizeof(buf)); zlog_debug( - "Upd static LSP in-label %u nexthop %s " - "out-label %u (old %u)", + "Upd static LSP in-label %u nexthop %s out-label %u (old %u)", in_label, buf, out_label, snhlfe->out_label); } snhlfe->out_label = out_label; @@ -3653,7 +3696,7 @@ int zebra_mpls_static_lsp_add(struct zebra_vrf *zvrf, mpls_label_t in_label, return -1; if (IS_ZEBRA_DEBUG_MPLS) { - snhlfe2str(snhlfe, buf, BUFSIZ); + snhlfe2str(snhlfe, buf, sizeof(buf)); zlog_debug( "Add static LSP in-label %u nexthop %s out-label %u", in_label, buf, out_label); @@ -3798,7 +3841,8 @@ void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf, for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp)) json_object_object_add( - json, label2str(lsp->ile.in_label, buf, BUFSIZ), + json, label2str(lsp->ile.in_label, buf, + sizeof(buf)), lsp_json(lsp)); vty_out(vty, "%s\n", json_object_to_json_string_ext( @@ -3853,7 +3897,7 @@ void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf, out_label_str = mpls_label2str( nexthop->nh_label->num_labels, &nexthop->nh_label->label[0], - buf, BUFSIZ, 1); + buf, sizeof(buf), 1); else out_label_str = "-"; diff --git a/zebra/zebra_mpls_openbsd.c b/zebra/zebra_mpls_openbsd.c index c8a3cbbbce..b767929dc0 100644 --- a/zebra/zebra_mpls_openbsd.c +++ b/zebra/zebra_mpls_openbsd.c @@ -276,8 +276,7 @@ static int kernel_lsp_cmd(struct zebra_dplane_ctx *ctx) && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)))) { if (nhlfe->nexthop->nh_label->num_labels > 1) { flog_warn(EC_ZEBRA_MAX_LABELS_PUSH, - "%s: can't push %u labels at once " - "(maximum is 1)", + "%s: can't push %u labels at once (maximum is 1)", __func__, nhlfe->nexthop->nh_label->num_labels); continue; diff --git a/zebra/zebra_nb.c b/zebra/zebra_nb.c index 53fe8e8e3f..a25d08f267 100644 --- a/zebra/zebra_nb.c +++ b/zebra/zebra_nb.c @@ -22,40 +22,6 @@ #include "libfrr.h" #include "zebra_nb.h" -const char *zebra_afi_safi_value2identity(afi_t afi, safi_t safi) -{ - if (afi == AFI_IP && safi == SAFI_UNICAST) - return "ipv4-unicast"; - if (afi == AFI_IP6 && safi == SAFI_UNICAST) - return "ipv6-unicast"; - if (afi == AFI_IP && safi == SAFI_MULTICAST) - return "ipv4-multicast"; - if (afi == AFI_IP6 && safi == SAFI_MULTICAST) - return "ipv6-multicast"; - - return " "; -} - -void zebra_afi_safi_identity2value(const char *key, afi_t *afi, safi_t *safi) -{ - if (strmatch(key, "frr-zebra:ipv4-unicast")) { - *afi = AFI_IP; - *safi = SAFI_UNICAST; - } else if (strmatch(key, "frr-zebra:ipv6-unicast")) { - *afi = AFI_IP6; - *safi = SAFI_UNICAST; - } else if (strmatch(key, "frr-zebra:ipv4-multicast")) { - *afi = AFI_IP; - *safi = SAFI_MULTICAST; - } else if (strmatch(key, "frr-zebra:ipv6-multicast")) { - *afi = AFI_IP6; - *safi = SAFI_MULTICAST; - } else { - *afi = AFI_UNSPEC; - *safi = SAFI_UNSPEC; - } -} - /* clang-format off */ const struct frr_yang_module_info frr_zebra_info = { .name = "frr-zebra", @@ -126,27 +92,6 @@ const struct frr_yang_module_info frr_zebra_info = { } }, { - .xpath = "/frr-zebra:zebra/vrf-vni-mapping", - .cbs = { - .create = zebra_vrf_vni_mapping_create, - .destroy = zebra_vrf_vni_mapping_destroy, - } - }, - { - .xpath = "/frr-zebra:zebra/vrf-vni-mapping/vni-id", - .cbs = { - .modify = zebra_vrf_vni_mapping_vni_id_modify, - .destroy = zebra_vrf_vni_mapping_vni_id_destroy, - } - }, - { - .xpath = "/frr-zebra:zebra/vrf-vni-mapping/prefix-only", - .cbs = { - .create = zebra_vrf_vni_mapping_prefix_only_create, - .destroy = zebra_vrf_vni_mapping_prefix_only_destroy, - } - }, - { .xpath = "/frr-zebra:zebra/debugs/debug-events", .cbs = { .modify = zebra_debugs_debug_events_modify, @@ -670,6 +615,19 @@ const struct frr_yang_module_info frr_zebra_info = { } }, { + .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/l3vni-id", + .cbs = { + .modify = lib_vrf_zebra_l3vni_id_modify, + .destroy = lib_vrf_zebra_l3vni_id_destroy, + } + }, + { + .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/prefix-only", + .cbs = { + .modify = lib_vrf_zebra_prefix_only_modify, + } + }, + { .xpath = "/frr-route-map:lib/route-map/entry/match-condition/frr-zebra:ipv4-prefix-length", .cbs = { .modify = lib_route_map_entry_match_condition_ipv4_prefix_length_modify, diff --git a/zebra/zebra_nb.h b/zebra/zebra_nb.h index a9e7fd5fb0..80aeb02d2d 100644 --- a/zebra/zebra_nb.h +++ b/zebra/zebra_nb.h @@ -26,10 +26,6 @@ extern "C" { extern const struct frr_yang_module_info frr_zebra_info; -/* helper functions */ -const char *zebra_afi_safi_value2identity(afi_t afi, safi_t safi); -void zebra_afi_safi_identity2value(const char *key, afi_t *afi, safi_t *safi); - /* prototypes */ int get_route_information_rpc(struct nb_cb_rpc_args *args); int get_v6_mroute_info_rpc(struct nb_cb_rpc_args *args); @@ -61,12 +57,6 @@ int zebra_import_kernel_table_route_map_destroy( int zebra_allow_external_route_update_create(struct nb_cb_create_args *args); int zebra_allow_external_route_update_destroy(struct nb_cb_destroy_args *args); int zebra_dplane_queue_limit_modify(struct nb_cb_modify_args *args); -int zebra_vrf_vni_mapping_create(struct nb_cb_create_args *args); -int zebra_vrf_vni_mapping_destroy(struct nb_cb_destroy_args *args); -int zebra_vrf_vni_mapping_vni_id_modify(struct nb_cb_modify_args *args); -int zebra_vrf_vni_mapping_vni_id_destroy(struct nb_cb_destroy_args *args); -int zebra_vrf_vni_mapping_prefix_only_create(struct nb_cb_create_args *args); -int zebra_vrf_vni_mapping_prefix_only_destroy(struct nb_cb_destroy_args *args); int zebra_debugs_debug_events_modify(struct nb_cb_modify_args *args); int zebra_debugs_debug_events_destroy(struct nb_cb_destroy_args *args); int zebra_debugs_debug_zapi_send_modify(struct nb_cb_modify_args *args); @@ -320,6 +310,9 @@ lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_fib_get_elem( struct yang_data * lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_weight_get_elem( struct nb_cb_get_elem_args *args); +int lib_vrf_zebra_l3vni_id_modify(struct nb_cb_modify_args *args); +int lib_vrf_zebra_l3vni_id_destroy(struct nb_cb_destroy_args *args); +int lib_vrf_zebra_prefix_only_modify(struct nb_cb_modify_args *args); #ifdef __cplusplus } diff --git a/zebra/zebra_nb_config.c b/zebra/zebra_nb_config.c index 948ef51320..e4501273bd 100644 --- a/zebra/zebra_nb_config.c +++ b/zebra/zebra_nb_config.c @@ -31,6 +31,8 @@ #include "zebra/connected.h" #include "zebra/zebra_router.h" #include "zebra/debug.h" +#include "zebra/zebra_vxlan_private.h" +#include "zebra/zebra_vxlan.h" /* * XPath: /frr-zebra:zebra/mcast-rpf-lookup @@ -273,99 +275,6 @@ int zebra_dplane_queue_limit_modify(struct nb_cb_modify_args *args) } /* - * XPath: /frr-zebra:zebra/vrf-vni-mapping - */ -int zebra_vrf_vni_mapping_create(struct nb_cb_create_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; -} - -int zebra_vrf_vni_mapping_destroy(struct nb_cb_destroy_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; -} - -/* - * XPath: /frr-zebra:zebra/vrf-vni-mapping/vni-id - */ -int zebra_vrf_vni_mapping_vni_id_modify(struct nb_cb_modify_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; -} - -int zebra_vrf_vni_mapping_vni_id_destroy(struct nb_cb_destroy_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; -} - -/* - * XPath: /frr-zebra:zebra/vrf-vni-mapping/prefix-only - */ -int zebra_vrf_vni_mapping_prefix_only_create(struct nb_cb_create_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; -} - -int zebra_vrf_vni_mapping_prefix_only_destroy(struct nb_cb_destroy_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ - break; - } - - return NB_OK; -} - -/* * XPath: /frr-zebra:zebra/debugs/debug-events */ int zebra_debugs_debug_events_modify(struct nb_cb_modify_args *args) @@ -1242,7 +1151,7 @@ int lib_vrf_zebra_ribs_rib_create(struct nb_cb_create_args *args) table_id = zvrf->table_id; afi_safi_name = yang_dnode_get_string(args->dnode, "./afi-safi-name"); - zebra_afi_safi_identity2value(afi_safi_name, &afi, &safi); + yang_afi_safi_identity2value(afi_safi_name, &afi, &safi); zrt = zebra_router_find_zrt(zvrf, table_id, afi, safi); @@ -1277,6 +1186,150 @@ int lib_vrf_zebra_ribs_rib_destroy(struct nb_cb_destroy_args *args) return NB_OK; } +/* + * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/l3vni-id + */ +int lib_vrf_zebra_l3vni_id_modify(struct nb_cb_modify_args *args) +{ + struct vrf *vrf; + struct zebra_vrf *zvrf; + vni_t vni = 0; + zebra_l3vni_t *zl3vni = NULL; + struct zebra_vrf *zvrf_evpn = NULL; + char err[ERR_STR_SZ]; + bool pfx_only = false; + const struct lyd_node *pn_dnode; + const char *vrfname; + + switch (args->event) { + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_VALIDATE: + zvrf_evpn = zebra_vrf_get_evpn(); + if (!zvrf_evpn) + return NB_ERR_VALIDATION; + + vni = yang_dnode_get_uint32(args->dnode, NULL); + /* Get vrf info from parent node, reject configuration + * if zebra vrf already mapped to different vni id. + */ + pn_dnode = yang_dnode_get_parent(args->dnode, "vrf"); + if (pn_dnode) { + vrfname = yang_dnode_get_string(pn_dnode, "./name"); + vrf = vrf_lookup_by_name(vrfname); + zvrf = zebra_vrf_lookup_by_id(vrf->vrf_id); + if (zvrf->l3vni && zvrf->l3vni != vni) { + zlog_debug( + "vni %u cannot be configured as vni %u is already configured under the vrf", + vni, zvrf->l3vni); + return NB_ERR_VALIDATION; + } + } + + /* Check if this VNI is already present in the system */ + zl3vni = zl3vni_lookup(vni); + if (zl3vni) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "VNI %u is already configured as L3-VNI", + vni); + return NB_ERR_VALIDATION; + } + + break; + case NB_EV_APPLY: + + vrf = nb_running_get_entry(args->dnode, NULL, true); + zvrf = zebra_vrf_lookup_by_id(vrf->vrf_id); + vni = yang_dnode_get_uint32(args->dnode, NULL); + /* Note: This covers lib_vrf_zebra_prefix_only_modify() config + * along with l3vni config + */ + pfx_only = yang_dnode_get_bool(args->dnode, "../prefix-only"); + + if (zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ, + pfx_only ? 1 : 0, 1) + != 0) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "vrf vni %u mapping failed with error: %s", + vni, err); + return NB_ERR; + } + + /* Mark as having FRR configuration */ + vrf_set_user_cfged(vrf); + + break; + } + + return NB_OK; +} + +int lib_vrf_zebra_l3vni_id_destroy(struct nb_cb_destroy_args *args) +{ + struct vrf *vrf; + struct zebra_vrf *zvrf; + vni_t vni = 0; + char err[ERR_STR_SZ]; + uint8_t filter = 0; + + switch (args->event) { + case NB_EV_PREPARE: + case NB_EV_ABORT: + case NB_EV_VALIDATE: + break; + case NB_EV_APPLY: + vrf = nb_running_get_entry(args->dnode, NULL, true); + zvrf = zebra_vrf_lookup_by_id(vrf->vrf_id); + vni = yang_dnode_get_uint32(args->dnode, NULL); + + if (!zl3vni_lookup(vni)) + return NB_OK; + + if (zvrf->l3vni != vni) + return NB_ERR; + + if (is_l3vni_for_prefix_routes_only(zvrf->l3vni)) + filter = 1; + + if (zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ, + filter, 0) + != 0) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "vrf vni %u unmapping failed with error: %s", + vni, err); + return NB_ERR; + } + + /* If no other FRR config for this VRF, mark accordingly. */ + if (!zebra_vrf_has_config(zvrf)) + vrf_reset_user_cfged(vrf); + + break; + } + + return NB_OK; +} + +/* + * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/prefix-only + */ +int lib_vrf_zebra_prefix_only_modify(struct nb_cb_modify_args *args) +{ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + case NB_EV_APPLY: + /* TODO: implement me. */ + break; + } + + return NB_OK; +} /* * XPath: diff --git a/zebra/zebra_nb_state.c b/zebra/zebra_nb_state.c index 4bca3b36d6..19ad3769eb 100644 --- a/zebra/zebra_nb_state.c +++ b/zebra/zebra_nb_state.c @@ -185,10 +185,9 @@ int lib_vrf_zebra_ribs_rib_get_keys(struct nb_cb_get_keys_args *args) args->keys->num = 2; - snprintfrr(args->keys->key[0], sizeof(args->keys->key[0]), "%s:%s", - "frr-zebra", - zebra_afi_safi_value2identity(zrt->afi, zrt->safi)); - snprintfrr(args->keys->key[1], sizeof(args->keys->key[1]), "%" PRIu32, + snprintfrr(args->keys->key[0], sizeof(args->keys->key[0]), "%s", + yang_afi_safi_value2identity(zrt->afi, zrt->safi)); + snprintfrr(args->keys->key[1], sizeof(args->keys->key[1]), "%u", zrt->tableid); return NB_OK; @@ -205,7 +204,7 @@ lib_vrf_zebra_ribs_rib_lookup_entry(struct nb_cb_lookup_entry_args *args) zvrf = zebra_vrf_lookup_by_id(vrf->vrf_id); - zebra_afi_safi_identity2value(args->keys->key[0], &afi, &safi); + yang_afi_safi_identity2value(args->keys->key[0], &afi, &safi); table_id = yang_str2uint32(args->keys->key[1]); /* table_id 0 assume vrf's table_id. */ if (!table_id) @@ -526,54 +525,57 @@ int lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_get_keys( { struct nexthop *nexthop = (struct nexthop *)args->list_entry; - args->keys->num = 3; + args->keys->num = 4; strlcpy(args->keys->key[0], yang_nexthop_type2str(nexthop->type), sizeof(args->keys->key[0])); + snprintfrr(args->keys->key[1], sizeof(args->keys->key[1]), "%" PRIu32, + nexthop->vrf_id); + switch (nexthop->type) { case NEXTHOP_TYPE_IPV4: case NEXTHOP_TYPE_IPV4_IFINDEX: - snprintfrr(args->keys->key[1], sizeof(args->keys->key[1]), + snprintfrr(args->keys->key[2], sizeof(args->keys->key[2]), "%pI4", &nexthop->gate.ipv4); if (nexthop->ifindex) - strlcpy(args->keys->key[2], + strlcpy(args->keys->key[3], ifindex2ifname(nexthop->ifindex, nexthop->vrf_id), - sizeof(args->keys->key[2])); + sizeof(args->keys->key[3])); else /* no ifindex */ - strlcpy(args->keys->key[2], " ", - sizeof(args->keys->key[2])); + strlcpy(args->keys->key[3], " ", + sizeof(args->keys->key[3])); break; case NEXTHOP_TYPE_IPV6: case NEXTHOP_TYPE_IPV6_IFINDEX: - snprintfrr(args->keys->key[1], sizeof(args->keys->key[1]), + snprintfrr(args->keys->key[2], sizeof(args->keys->key[2]), "%pI6", &nexthop->gate.ipv6); if (nexthop->ifindex) - strlcpy(args->keys->key[2], + strlcpy(args->keys->key[3], ifindex2ifname(nexthop->ifindex, nexthop->vrf_id), - sizeof(args->keys->key[2])); + sizeof(args->keys->key[3])); else /* no ifindex */ - strlcpy(args->keys->key[2], " ", - sizeof(args->keys->key[2])); + strlcpy(args->keys->key[3], " ", + sizeof(args->keys->key[3])); break; case NEXTHOP_TYPE_IFINDEX: - strlcpy(args->keys->key[1], "", sizeof(args->keys->key[1])); - strlcpy(args->keys->key[2], + strlcpy(args->keys->key[2], "", sizeof(args->keys->key[2])); + strlcpy(args->keys->key[3], ifindex2ifname(nexthop->ifindex, nexthop->vrf_id), - sizeof(args->keys->key[2])); + sizeof(args->keys->key[3])); break; case NEXTHOP_TYPE_BLACKHOLE: /* Gateway IP */ - strlcpy(args->keys->key[1], "", sizeof(args->keys->key[1])); - strlcpy(args->keys->key[2], " ", sizeof(args->keys->key[2])); + strlcpy(args->keys->key[2], "", sizeof(args->keys->key[2])); + strlcpy(args->keys->key[3], " ", sizeof(args->keys->key[3])); break; default: break; diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c index 72e4fd0055..995fa6fb5a 100644 --- a/zebra/zebra_netns_notify.c +++ b/zebra/zebra_netns_notify.c @@ -185,7 +185,7 @@ static bool zebra_ns_notify_is_default_netns(const char *name) { struct stat default_netns_stat; struct stat st; - char netnspath[64]; + char netnspath[PATH_MAX]; if (zebra_ns_notify_self_identify(&default_netns_stat)) return false; @@ -230,14 +230,12 @@ static int zebra_ns_ready_read(struct thread *t) /* check default name is not already set */ if (strmatch(VRF_DEFAULT_NAME, basename(netnspath))) { - zlog_warn("NS notify : NS %s is already default VRF." - "Cancel VRF Creation", basename(netnspath)); + zlog_warn("NS notify : NS %s is already default VRF.Cancel VRF Creation", basename(netnspath)); return zebra_ns_continue_read(zns_info, 1); } if (zebra_ns_notify_is_default_netns(basename(netnspath))) { zlog_warn( - "NS notify : NS %s is default VRF." - " Updating VRF Name", basename(netnspath)); + "NS notify : NS %s is default VRF. Updating VRF Name", basename(netnspath)); vrf_set_default_name(basename(netnspath), false); return zebra_ns_continue_read(zns_info, 1); } @@ -333,14 +331,12 @@ void zebra_ns_notify_parse(void) } /* check default name is not already set */ if (strmatch(VRF_DEFAULT_NAME, basename(dent->d_name))) { - zlog_warn("NS notify : NS %s is already default VRF." - "Cancel VRF Creation", dent->d_name); + zlog_warn("NS notify : NS %s is already default VRF.Cancel VRF Creation", dent->d_name); continue; } if (zebra_ns_notify_is_default_netns(dent->d_name)) { zlog_warn( - "NS notify : NS %s is default VRF." - " Updating VRF Name", dent->d_name); + "NS notify : NS %s is default VRF. Updating VRF Name", dent->d_name); vrf_set_default_name(dent->d_name, false); continue; } diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 9bfd7aacb7..c058090844 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -1951,8 +1951,11 @@ static int nexthop_active(afi_t afi, struct route_entry *re, goto done_with_match; } - /* Examine installed nexthops */ - nhg = &match->nhe->nhg; + /* Examine installed nexthops; note that there + * may not be any installed primary nexthops if + * only backups are installed. + */ + nhg = rib_get_fib_nhg(match); for (ALL_NEXTHOPS_PTR(nhg, newhop)) { if (!nexthop_valid_resolve(nexthop, newhop)) continue; @@ -1973,8 +1976,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re, * dedicated fib list. */ nhg = rib_get_fib_backup_nhg(match); - if (nhg == NULL || - nhg == zebra_nhg_get_backup_nhg(match->nhe)) + if (nhg == NULL || nhg->nexthop == NULL) goto done_with_match; for (ALL_NEXTHOPS_PTR(nhg, newhop)) { diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c index c5a7795273..1bc8d893bc 100644 --- a/zebra/zebra_pbr.c +++ b/zebra/zebra_pbr.c @@ -336,14 +336,20 @@ bool zebra_pbr_ipset_entry_hash_equal(const void *arg1, const void *arg2) return true; } -void zebra_pbr_iptable_free(void *arg) +/* this function gives option to flush plugin memory contexts + * with all parameter. set it to true to flush all + * set it to false to flush only passed arg argument + */ +static void _zebra_pbr_iptable_free_all(void *arg, bool all) { struct zebra_pbr_iptable *iptable; struct listnode *node, *nnode; char *name; iptable = (struct zebra_pbr_iptable *)arg; - hook_call(zebra_pbr_iptable_update, 0, iptable); + + if (all) + hook_call(zebra_pbr_iptable_update, 0, iptable); if (iptable->interface_name_list) { for (ALL_LIST_ELEMENTS(iptable->interface_name_list, node, @@ -356,6 +362,11 @@ void zebra_pbr_iptable_free(void *arg) XFREE(MTYPE_TMP, iptable); } +void zebra_pbr_iptable_free(void *arg) +{ + _zebra_pbr_iptable_free_all(arg, false); +} + uint32_t zebra_pbr_iptable_hash_key(const void *arg) { const struct zebra_pbr_iptable *iptable = arg; @@ -529,7 +540,7 @@ static void zebra_pbr_cleanup_iptable(struct hash_bucket *b, void *data) if (iptable->sock == *sock) { if (hash_release(zrouter.iptable_hash, iptable)) - zebra_pbr_iptable_free(iptable); + _zebra_pbr_iptable_free_all(iptable, true); else hook_call(zebra_pbr_iptable_update, 0, iptable); } diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h index 4bc0f40037..dd2d7a190d 100644 --- a/zebra/zebra_pbr.h +++ b/zebra/zebra_pbr.h @@ -54,6 +54,8 @@ struct zebra_pbr_rule { (r->rule.filter.filter_bm & PBR_FILTER_SRC_PORT) #define IS_RULE_FILTERING_ON_DST_PORT(r) \ (r->rule.filter.filter_bm & PBR_FILTER_DST_PORT) +#define IS_RULE_FILTERING_ON_DSFIELD(r) \ + (r->rule.filter.filter_bm & PBR_FILTER_DSFIELD) #define IS_RULE_FILTERING_ON_FWMARK(r) \ (r->rule.filter.filter_bm & PBR_FILTER_FWMARK) diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index 88ea2b87b1..9a3b567b5a 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -434,8 +434,7 @@ static void if_bfd_session_update(struct interface *ifp, struct prefix *dp, if (ifp) { zlog_debug( - "MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d on %s" - " %s event", + "MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d on %s %s event", inet_ntop(dp->family, &dp->u.prefix, buf[0], INET6_ADDRSTRLEN), dp->prefixlen, ifp->name, @@ -444,8 +443,7 @@ static void if_bfd_session_update(struct interface *ifp, struct prefix *dp, struct vrf *vrf = vrf_lookup_by_id(vrf_id); zlog_debug( - "MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d " - "with src %s/%d and vrf %s(%u) %s event", + "MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d with src %s/%d and vrf %s(%u) %s event", inet_ntop(dp->family, &dp->u.prefix, buf[0], INET6_ADDRSTRLEN), dp->prefixlen, @@ -502,8 +500,7 @@ static int zebra_ptm_handle_bfd_msg(void *arg, void *in_ctxt, if (IS_ZEBRA_DEBUG_EVENT) zlog_debug( - "%s: Recv Port [%s] bfd status [%s] vrf [%s]" - " peer [%s] local [%s]", + "%s: Recv Port [%s] bfd status [%s] vrf [%s] peer [%s] local [%s]", __func__, ifp ? ifp->name : "N/A", bfdst_str, vrf_str, dest_str, src_str); diff --git a/zebra/zebra_pw.c b/zebra/zebra_pw.c index 2328ab650a..cdcca1e930 100644 --- a/zebra/zebra_pw.c +++ b/zebra/zebra_pw.c @@ -215,8 +215,7 @@ void zebra_pw_install_failure(struct zebra_pw *pw, int pwstatus) { if (IS_ZEBRA_DEBUG_PW) zlog_debug( - "%u: failed installing pseudowire %s, " - "scheduling retry in %u seconds", + "%u: failed installing pseudowire %s, scheduling retry in %u seconds", pw->vrf_id, pw->ifname, PW_INSTALL_RETRY_INTERVAL); /* schedule to retry later */ @@ -518,6 +517,7 @@ static void vty_show_mpls_pseudowire_detail(struct vty *vty) struct zebra_pw *pw; struct route_entry *re; struct nexthop *nexthop; + struct nexthop_group *nhg; zvrf = vrf_info_lookup(VRF_DEFAULT); if (!zvrf) @@ -545,22 +545,41 @@ static void vty_show_mpls_pseudowire_detail(struct vty *vty) vty_out(vty, " VC-ID: %u\n", pw->data.ldp.pwid); vty_out(vty, " Status: %s \n", (zebra_pw_enabled(pw) && pw->status == PW_FORWARDING) - ? "Up" - : "Down"); + ? "Up" + : "Down"); re = rib_match(family2afi(pw->af), SAFI_UNICAST, pw->vrf_id, &pw->nexthop, NULL); - if (re) { - for (ALL_NEXTHOPS_PTR(rib_get_fib_nhg(re), nexthop)) { - snprintfrr(buf_nh, sizeof(buf_nh), "%pNHv", - nexthop); - vty_out(vty, " Next Hop: %s\n", buf_nh); - if (nexthop->nh_label) - vty_out(vty, " Next Hop label: %u\n", - nexthop->nh_label->label[0]); - else - vty_out(vty, " Next Hop label: %s\n", - "-"); - } + if (re == NULL) + continue; + + nhg = rib_get_fib_nhg(re); + for (ALL_NEXTHOPS_PTR(nhg, nexthop)) { + snprintfrr(buf_nh, sizeof(buf_nh), "%pNHv", + nexthop); + vty_out(vty, " Next Hop: %s\n", buf_nh); + if (nexthop->nh_label) + vty_out(vty, " Next Hop label: %u\n", + nexthop->nh_label->label[0]); + else + vty_out(vty, " Next Hop label: %s\n", + "-"); + } + + /* Include any installed backups */ + nhg = rib_get_fib_backup_nhg(re); + if (nhg == NULL) + continue; + + for (ALL_NEXTHOPS_PTR(nhg, nexthop)) { + snprintfrr(buf_nh, sizeof(buf_nh), "%pNHv", + nexthop); + vty_out(vty, " Next Hop: %s\n", buf_nh); + if (nexthop->nh_label) + vty_out(vty, " Next Hop label: %u\n", + nexthop->nh_label->label[0]); + else + vty_out(vty, " Next Hop label: %s\n", + "-"); } } } @@ -569,6 +588,7 @@ static void vty_show_mpls_pseudowire(struct zebra_pw *pw, json_object *json_pws) { struct route_entry *re; struct nexthop *nexthop; + struct nexthop_group *nhg; char buf_nbr[INET6_ADDRSTRLEN]; char buf_nh[100]; json_object *json_pw = NULL; @@ -603,23 +623,48 @@ static void vty_show_mpls_pseudowire(struct zebra_pw *pw, json_object *json_pws) : "Down"); re = rib_match(family2afi(pw->af), SAFI_UNICAST, pw->vrf_id, &pw->nexthop, NULL); - if (re) { - for (ALL_NEXTHOPS_PTR(rib_get_fib_nhg(re), nexthop)) { - json_nexthop = json_object_new_object(); - snprintfrr(buf_nh, sizeof(buf_nh), "%pNHv", nexthop); - json_object_string_add(json_nexthop, "nexthop", buf_nh); - if (nexthop->nh_label) - json_object_int_add( - json_nexthop, "nhLabel", - nexthop->nh_label->label[0]); - else - json_object_string_add(json_nexthop, "nhLabel", - "-"); + if (re == NULL) + goto done; + + nhg = rib_get_fib_nhg(re); + for (ALL_NEXTHOPS_PTR(nhg, nexthop)) { + json_nexthop = json_object_new_object(); + snprintfrr(buf_nh, sizeof(buf_nh), "%pNHv", nexthop); + json_object_string_add(json_nexthop, "nexthop", buf_nh); + if (nexthop->nh_label) + json_object_int_add( + json_nexthop, "nhLabel", + nexthop->nh_label->label[0]); + else + json_object_string_add(json_nexthop, "nhLabel", + "-"); - json_object_array_add(json_nexthops, json_nexthop); - } - json_object_object_add(json_pw, "nexthops", json_nexthops); + json_object_array_add(json_nexthops, json_nexthop); + } + + /* Include installed backup nexthops also */ + nhg = rib_get_fib_backup_nhg(re); + if (nhg == NULL) + goto done; + + for (ALL_NEXTHOPS_PTR(nhg, nexthop)) { + json_nexthop = json_object_new_object(); + snprintfrr(buf_nh, sizeof(buf_nh), "%pNHv", nexthop); + json_object_string_add(json_nexthop, "nexthop", buf_nh); + if (nexthop->nh_label) + json_object_int_add( + json_nexthop, "nhLabel", + nexthop->nh_label->label[0]); + else + json_object_string_add(json_nexthop, "nhLabel", + "-"); + + json_object_array_add(json_nexthops, json_nexthop); } + +done: + + json_object_object_add(json_pw, "nexthops", json_nexthops); json_object_array_add(json_pws, json_pw); } @@ -680,8 +725,7 @@ static int zebra_pw_config(struct vty *vty) pw->local_label, pw->remote_label); else vty_out(vty, - " ! Incomplete config, specify the static " - "MPLS labels\n"); + " ! Incomplete config, specify the static MPLS labels\n"); if (pw->af != AF_UNSPEC) { char buf[INET6_ADDRSTRLEN]; @@ -689,8 +733,7 @@ static int zebra_pw_config(struct vty *vty) vty_out(vty, " neighbor %s\n", buf); } else vty_out(vty, - " ! Incomplete config, specify a neighbor " - "address\n"); + " ! Incomplete config, specify a neighbor address\n"); if (!(pw->flags & F_PSEUDOWIRE_CWORD)) vty_out(vty, " control-word exclude\n"); diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 67b3812ed3..ee9d5d76e0 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -472,6 +472,7 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re, SET_FLAG(old->status, ROUTE_ENTRY_QUEUED); /* Free old FIB nexthop group */ + UNSET_FLAG(old->status, ROUTE_ENTRY_USE_FIB_NHG); if (old->fib_ng.nexthop) { nexthops_free(old->fib_ng.nexthop); old->fib_ng.nexthop = NULL; @@ -574,6 +575,7 @@ static void rib_uninstall(struct route_node *rn, struct route_entry *re) nexthops_free(re->fib_ng.nexthop); re->fib_ng.nexthop = NULL; } + UNSET_FLAG(re->status, ROUTE_ENTRY_USE_FIB_NHG); for (ALL_NEXTHOPS(re->nhe->nhg, nexthop)) UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); @@ -1081,8 +1083,7 @@ static void rib_process(struct route_node *rn) if (re != old_selected) { if (IS_ZEBRA_DEBUG_RIB) zlog_debug( - "%s: %s(%u):%s: imported via import-table but denied " - "by the ip protocol table route-map", + "%s: %s(%u):%s: imported via import-table but denied by the ip protocol table route-map", __func__, VRF_LOGNAME(vrf), vrf_id, buf); @@ -1376,7 +1377,7 @@ static bool rib_update_nhg_from_ctx(struct nexthop_group *re_nhg, continue; /* Check for a FIB nexthop corresponding to the RIB nexthop */ - if (nexthop_same(ctx_nexthop, nexthop) == false) { + if (!nexthop_same(ctx_nexthop, nexthop)) { /* If the FIB doesn't know about the nexthop, * it's not installed */ @@ -1491,7 +1492,7 @@ static bool rib_update_re_from_ctx(struct route_entry *re, VRF_LOGNAME(vrf), re->vrf_id, dest_str); goto check_backups; - } else if (re->fib_ng.nexthop) { + } else if (CHECK_FLAG(re->status, ROUTE_ENTRY_USE_FIB_NHG)) { /* * Free stale fib list and move on to check the rib nhg. */ @@ -1502,6 +1503,8 @@ static bool rib_update_re_from_ctx(struct route_entry *re, nexthops_free(re->fib_ng.nexthop); re->fib_ng.nexthop = NULL; + UNSET_FLAG(re->status, ROUTE_ENTRY_USE_FIB_NHG); + /* Note that the installed nexthops have changed */ changed_p = true; } else { @@ -1547,20 +1550,15 @@ no_nexthops: */ if (IS_ZEBRA_DEBUG_RIB) zlog_debug( - "%s(%u):%s update_from_ctx(): changed %s, adding new fib nhg", + "%s(%u):%s update_from_ctx(): changed %s, adding new fib nhg%s", VRF_LOGNAME(vrf), re->vrf_id, dest_str, - (changed_p ? "true" : "false")); + (changed_p ? "true" : "false"), + ctxnhg->nexthop != NULL ? "" : " (empty)"); + /* Set the flag about the dedicated fib list */ + SET_FLAG(re->status, ROUTE_ENTRY_USE_FIB_NHG); if (ctxnhg->nexthop) copy_nexthops(&(re->fib_ng.nexthop), ctxnhg->nexthop, NULL); - else { - /* Bit of a special case when the fib has _no_ installed - * nexthops. - */ - nexthop = nexthop_new(); - nexthop->type = NEXTHOP_TYPE_IPV4; - _nexthop_add(&(re->fib_ng.nexthop), nexthop); - } check_backups: @@ -1612,7 +1610,7 @@ check_backups: } /* - * If a FIB backup nexthop set exists: attach a copy + * If a FIB backup nexthop set exists, attach a copy * to the route if any backup is installed */ if (ctxnhg && ctxnhg->nexthop) { @@ -1937,7 +1935,7 @@ static int rib_count_installed_nh(struct route_entry *re) /* The meaningful flag depends on where the installed * nexthops reside. */ - if (nhg == &(re->fib_backup_ng)) { + if (nhg == &(re->fib_ng)) { if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) count++; } else { @@ -1946,9 +1944,12 @@ static int rib_count_installed_nh(struct route_entry *re) } } - for (ALL_NEXTHOPS_PTR(rib_get_fib_backup_nhg(re), nexthop)) { - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) - count++; + nhg = rib_get_fib_backup_nhg(re); + if (nhg) { + for (ALL_NEXTHOPS_PTR(nhg, nexthop)) { + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) + count++; + } } return count; @@ -2630,6 +2631,8 @@ static void _route_entry_dump_nh(const struct route_entry *re, char nhname[PREFIX_STRLEN]; char backup_str[50]; char wgt_str[50]; + char temp_str[10]; + int i; struct interface *ifp; struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id); @@ -2655,8 +2658,12 @@ static void _route_entry_dump_nh(const struct route_entry *re, backup_str[0] = '\0'; if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) { - snprintf(backup_str, sizeof(backup_str), "backup %d,", - (int)nexthop->backup_idx); + snprintf(backup_str, sizeof(backup_str), "backup "); + for (i = 0; i < nexthop->backup_num; i++) { + snprintf(temp_str, sizeof(temp_str), "%d, ", + nexthop->backup_idx[i]); + strlcat(backup_str, temp_str, sizeof(backup_str)); + } } wgt_str[0] = '\0'; @@ -3149,8 +3156,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, if (nh) rnode_debug( rn, vrf_id, - "via %s ifindex %d type %d " - "doesn't exist in rib", + "via %s ifindex %d type %d doesn't exist in rib", inet_ntop(afi2family(afi), &nh->gate, buf2, sizeof(buf2)), diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index d1a5cf2a9d..b151e90a92 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -1040,22 +1040,10 @@ static bool compare_valid_nexthops(struct route_entry *r1, * backups will be in the 'fib' list. */ nhg1 = rib_get_fib_backup_nhg(r1); - if (nhg1 == zebra_nhg_get_backup_nhg(r1->nhe)) - nhg1 = NULL; - nhg2 = rib_get_fib_backup_nhg(r2); - if (nhg2 == zebra_nhg_get_backup_nhg(r2->nhe)) - nhg2 = NULL; - - if (nhg1) - nh1 = nhg1->nexthop; - else - nh1 = NULL; - if (nhg2) - nh2 = nhg2->nexthop; - else - nh2 = NULL; + nh1 = nhg1->nexthop; + nh2 = nhg2->nexthop; while (1) { /* Find each backup list's next valid nexthop */ @@ -1180,15 +1168,15 @@ static int send_client(struct rnh *rnh, struct zserv *client, } nhg = rib_get_fib_backup_nhg(re); - if (nhg == zebra_nhg_get_backup_nhg(re->nhe)) - nhg = NULL; - if (nhg) { for (ALL_NEXTHOPS_PTR(nhg, nh)) if (rnh_nexthop_valid(re, nh)) { zapi_nexthop_from_nexthop(&znh, nh); - zapi_nexthop_encode(s, &znh, - 0 /* flags */); + ret = zapi_nexthop_encode( + s, &znh, 0 /* flags */); + if (ret < 0) + goto failure; + num++; } } diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index ee1e251a69..d102b02a21 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -544,6 +544,7 @@ static int vrf_config_write(struct vty *vty) zebra_routemap_config_write_protocol(vty, zvrf); + router_id_write(vty, zvrf); if (zvrf_id(zvrf) != VRF_DEFAULT) vty_endframe(vty, " exit-vrf\n!\n"); diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 1da2660509..2ca57f1c56 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -55,6 +55,7 @@ #include "zebra/zebra_nhg.h" #include "zebra/interface.h" #include "northbound_cli.h" +#include "zebra/zebra_nb.h" extern int allow_delete; @@ -71,6 +72,12 @@ static void vty_show_ip_route_summary(struct vty *vty, static void vty_show_ip_route_summary_prefix(struct vty *vty, struct route_table *table, bool use_json); +/* Helper api to format a nexthop in the 'detailed' output path. */ +static void show_nexthop_detail_helper(struct vty *vty, + const struct route_entry *re, + const struct nexthop *nexthop, + bool is_backup); + DEFUN (ip_multicast_mode, ip_multicast_mode_cmd, @@ -166,11 +173,24 @@ DEFUN (show_ip_rpf_addr, } static char re_status_output_char(const struct route_entry *re, - const struct nexthop *nhop) + const struct nexthop *nhop, + bool is_fib) { if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) { - if (!CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_DUPLICATE) && - !CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_RECURSIVE)) + bool star_p = false; + + if (nhop && + !CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_DUPLICATE) && + !CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_RECURSIVE)) { + /* More-specific test for 'fib' output */ + if (is_fib) { + star_p = !!CHECK_FLAG(nhop->flags, + NEXTHOP_FLAG_FIB); + } else + star_p = true; + } + + if (star_p) return '*'; else return ' '; @@ -190,19 +210,51 @@ static char re_status_output_char(const struct route_entry *re, } /* - * TODO -- Show backup nexthop info + * Show backup nexthop info, in the 'detailed' output path */ static void show_nh_backup_helper(struct vty *vty, - const struct nhg_hash_entry *nhe, + const struct route_entry *re, const struct nexthop *nexthop) { + const struct nexthop *start, *backup, *temp; + int i, idx; + /* Double-check that there _is_ a backup */ - if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) + if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP) || + re->nhe->backup_info == NULL || re->nhe->backup_info->nhe == NULL || + re->nhe->backup_info->nhe->nhg.nexthop == NULL) return; - /* Locate the backup nexthop */ + /* Locate the backup nexthop(s) */ + start = re->nhe->backup_info->nhe->nhg.nexthop; + for (i = 0; i < nexthop->backup_num; i++) { + /* Format the backup(s) (indented) */ + backup = start; + for (idx = 0; idx < nexthop->backup_idx[i]; idx++) { + backup = backup->next; + if (backup == NULL) + break; + } + + /* It's possible for backups to be recursive too, + * so walk the recursive resolution list if present. + */ + temp = backup; + while (backup) { + vty_out(vty, " "); + show_nexthop_detail_helper(vty, re, backup, + true /*backup*/); + vty_out(vty, "\n"); - /* Format the backup (indented) */ + if (backup->resolved && temp == backup) + backup = backup->resolved; + else + backup = nexthop_next(backup); + + if (backup == temp->next) + break; + } + } } @@ -212,14 +264,20 @@ static void show_nh_backup_helper(struct vty *vty, */ static void show_nexthop_detail_helper(struct vty *vty, const struct route_entry *re, - const struct nexthop *nexthop) + const struct nexthop *nexthop, + bool is_backup) { char addrstr[32]; char buf[MPLS_LABEL_STRLEN]; + int i; - vty_out(vty, " %c%s", - re_status_output_char(re, nexthop), - nexthop->rparent ? " " : ""); + if (is_backup) + vty_out(vty, " b%s", + nexthop->rparent ? " " : ""); + else + vty_out(vty, " %c%s", + re_status_output_char(re, nexthop, false), + nexthop->rparent ? " " : ""); switch (nexthop->type) { case NEXTHOP_TYPE_IPV4: @@ -333,6 +391,13 @@ static void show_nexthop_detail_helper(struct vty *vty, if (nexthop->weight) vty_out(vty, ", weight %u", nexthop->weight); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) { + vty_out(vty, ", backup %d", nexthop->backup_idx[0]); + + for (i = 1; i < nexthop->backup_num; i++) + vty_out(vty, ",%d", nexthop->backup_idx[i]); + } } /* New RIB. Detailed information for IPv4 route. */ @@ -403,12 +468,13 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn, for (ALL_NEXTHOPS(re->nhe->nhg, nexthop)) { /* Use helper to format each nexthop */ - show_nexthop_detail_helper(vty, re, nexthop); + show_nexthop_detail_helper(vty, re, nexthop, + false /*not backup*/); vty_out(vty, "\n"); - /* Include backup info, if present */ + /* Include backup(s), if present */ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) - show_nh_backup_helper(vty, re->nhe, nexthop); + show_nh_backup_helper(vty, re, nexthop); } vty_out(vty, "\n"); } @@ -422,6 +488,7 @@ static void show_route_nexthop_helper(struct vty *vty, const struct nexthop *nexthop) { char buf[MPLS_LABEL_STRLEN]; + int i; switch (nexthop->type) { case NEXTHOP_TYPE_IPV4: @@ -519,8 +586,12 @@ static void show_route_nexthop_helper(struct vty *vty, if (nexthop->weight) vty_out(vty, ", weight %u", nexthop->weight); - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) - vty_out(vty, ", backup %d", nexthop->backup_idx); + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) { + vty_out(vty, ", backup %d", nexthop->backup_idx[0]); + + for (i = 1; i < nexthop->backup_num; i++) + vty_out(vty, ",%d", nexthop->backup_idx[i]); + } } /* @@ -534,6 +605,8 @@ static void show_nexthop_json_helper(json_object *json_nexthop, char buf[SRCDEST2STR_BUFFER]; struct vrf *vrf = NULL; json_object *json_labels = NULL; + json_object *json_backups = NULL; + int i; json_object_int_add(json_nexthop, "flags", nexthop->flags); @@ -645,9 +718,17 @@ static void show_nexthop_json_helper(json_object *json_nexthop, json_object_boolean_true_add(json_nexthop, "recursive"); - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) - json_object_int_add(json_nexthop, "backupIndex", - nexthop->backup_idx); + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) { + json_backups = json_object_new_array(); + for (i = 0; i < nexthop->backup_num; i++) { + json_object_array_add( + json_backups, + json_object_new_int(nexthop->backup_idx[i])); + } + + json_object_object_add(json_nexthop, "backupIndex", + json_backups); + } switch (nexthop->type) { case NEXTHOP_TYPE_IPV4: @@ -705,18 +786,19 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, struct route_entry *re, json_object *json, bool is_fib) { - struct nexthop *nexthop; + const struct nexthop *nexthop; int len = 0; char buf[SRCDEST2STR_BUFFER]; json_object *json_nexthops = NULL; json_object *json_nexthop = NULL; json_object *json_route = NULL; time_t uptime; - struct vrf *vrf = NULL; - rib_dest_t *dest = rib_dest_from_rnode(rn); - struct nexthop_group *nhg; + const struct vrf *vrf = NULL; + const rib_dest_t *dest = rib_dest_from_rnode(rn); + const struct nexthop_group *nhg; char up_str[MONOTIME_STRLEN]; - bool first_p; + bool first_p = true; + bool nhg_from_backup = false; uptime = monotime(NULL); uptime -= re->uptime; @@ -791,9 +873,11 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, for (ALL_NEXTHOPS_PTR(nhg, nexthop)) { json_nexthop = json_object_new_object(); + show_nexthop_json_helper(json_nexthop, + nexthop, re); - show_nexthop_json_helper(json_nexthop, nexthop, re); - json_object_array_add(json_nexthops, json_nexthop); + json_object_array_add(json_nexthops, + json_nexthop); } json_object_object_add(json_route, "nexthops", json_nexthops); @@ -804,7 +888,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, else nhg = zebra_nhg_get_backup_nhg(re->nhe); - if (nhg) { + if (nhg && nhg->nexthop) { json_nexthops = json_object_new_array(); for (ALL_NEXTHOPS_PTR(nhg, nexthop)) { @@ -824,42 +908,62 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, return; } + /* Prefix information, and first nexthop. If we're showing 'fib', + * and there are no installed primary nexthops, see if there are any + * backup nexthops and start with those. + */ + if (is_fib && nhg->nexthop == NULL) { + nhg = rib_get_fib_backup_nhg(re); + nhg_from_backup = true; + } + + len = vty_out(vty, "%c", zebra_route_char(re->type)); + if (re->instance) + len += vty_out(vty, "[%d]", re->instance); + if (nhg_from_backup && nhg->nexthop) { + len += vty_out( + vty, "%cb%c %s", + CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED) ? '>' : ' ', + re_status_output_char(re, nhg->nexthop, is_fib), + srcdest_rnode2str(rn, buf, sizeof(buf))); + } else { + len += vty_out( + vty, "%c%c %s", + CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED) ? '>' : ' ', + re_status_output_char(re, nhg->nexthop, is_fib), + srcdest_rnode2str(rn, buf, sizeof(buf))); + } + + /* Distance and metric display. */ + if (((re->type == ZEBRA_ROUTE_CONNECT) && + (re->distance || re->metric)) || + (re->type != ZEBRA_ROUTE_CONNECT)) + len += vty_out(vty, " [%u/%u]", re->distance, + re->metric); + /* Nexthop information. */ - first_p = true; for (ALL_NEXTHOPS_PTR(nhg, nexthop)) { if (first_p) { first_p = false; - - /* Prefix information. */ - len = vty_out(vty, "%c", zebra_route_char(re->type)); - if (re->instance) - len += vty_out(vty, "[%d]", re->instance); - len += vty_out( - vty, "%c%c %s", - CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED) - ? '>' - : ' ', - re_status_output_char(re, nexthop), - srcdest_rnode2str(rn, buf, sizeof(buf))); - - /* Distance and metric display. */ - if (((re->type == ZEBRA_ROUTE_CONNECT) && - (re->distance || re->metric)) || - (re->type != ZEBRA_ROUTE_CONNECT)) - len += vty_out(vty, " [%u/%u]", re->distance, - re->metric); + } else if (nhg_from_backup) { + vty_out(vty, " b%c%*c", + re_status_output_char(re, nexthop, is_fib), + len - 3 + (2 * nexthop_level(nexthop)), ' '); } else { vty_out(vty, " %c%*c", - re_status_output_char(re, nexthop), + re_status_output_char(re, nexthop, is_fib), len - 3 + (2 * nexthop_level(nexthop)), ' '); } show_route_nexthop_helper(vty, re, nexthop); - vty_out(vty, ", %s\n", up_str); } - /* Check for backup info if present */ + /* If we only had backup nexthops, we're done */ + if (nhg_from_backup) + return; + + /* Check for backup nexthop info if present */ if (is_fib) nhg = rib_get_fib_backup_nhg(re); else @@ -1206,7 +1310,7 @@ static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe) if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) vty_out(vty, " [backup %d]", - nexthop->backup_idx); + nexthop->backup_idx[0]); vty_out(vty, "\n"); continue; @@ -1214,22 +1318,13 @@ static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe) /* TODO -- print more useful backup info */ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) { - struct nexthop *backup; int i; - i = 0; - for (ALL_NEXTHOPS(nhe->backup_info->nhe->nhg, backup)) { - if (i == nexthop->backup_idx) - break; - i++; - } + vty_out(vty, "[backup"); + for (i = 0; i < nexthop->backup_num; i++) + vty_out(vty, " %d", nexthop->backup_idx[i]); - /* TODO */ - if (backup) - vty_out(vty, " [backup %d]", - nexthop->backup_idx); - else - vty_out(vty, " [backup INVALID]"); + vty_out(vty, "]"); } vty_out(vty, "\n"); @@ -2304,12 +2399,9 @@ DEFUN (vrf_vni_mapping, "VNI-ID\n" "prefix-routes-only\n") { - int ret = 0; int filter = 0; ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); - vni_t vni = strtoul(argv[1]->arg, NULL, 10); - char err[ERR_STR_SZ]; assert(vrf); assert(zvrf); @@ -2317,14 +2409,15 @@ DEFUN (vrf_vni_mapping, if (argc == 3) filter = 1; - /* Mark as having FRR configuration */ - vrf_set_user_cfged(vrf); - ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ, - filter, 1); - if (ret != 0) { - vty_out(vty, "%s\n", err); - return CMD_WARNING; - } + nb_cli_enqueue_change(vty, "./frr-zebra:zebra", NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./frr-zebra:zebra/l3vni-id", NB_OP_MODIFY, + argv[1]->arg); + + if (filter) + nb_cli_enqueue_change(vty, "./frr-zebra:zebra/prefix-only", + NB_OP_MODIFY, "true"); + + nb_cli_apply_changes(vty, NULL); return CMD_SUCCESS; } @@ -2337,12 +2430,10 @@ DEFUN (no_vrf_vni_mapping, "VNI-ID\n" "prefix-routes-only\n") { - int ret = 0; int filter = 0; - char err[ERR_STR_SZ]; - vni_t vni = strtoul(argv[2]->arg, NULL, 10); ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); + vni_t vni = strtoul(argv[1]->arg, NULL, 10); assert(vrf); assert(zvrf); @@ -2350,16 +2441,22 @@ DEFUN (no_vrf_vni_mapping, if (argc == 4) filter = 1; - ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, - ERR_STR_SZ, filter, 0); - if (ret != 0) { - vty_out(vty, "%s\n", err); + if (zvrf->l3vni != vni) { + vty_out(vty, "VNI %d doesn't exist in VRF: %s \n", vni, + zvrf->vrf->name); return CMD_WARNING; } - /* If no other FRR config for this VRF, mark accordingly. */ - if (!zebra_vrf_has_config(zvrf)) - vrf_reset_user_cfged(vrf); + nb_cli_enqueue_change(vty, "./frr-zebra:zebra/l3vni-id", NB_OP_DESTROY, + argv[2]->arg); + + if (filter) + nb_cli_enqueue_change(vty, "./frr-zebra:zebra/prefix-only", + NB_OP_DESTROY, "true"); + + nb_cli_enqueue_change(vty, "./frr-zebra:zebra", NB_OP_DESTROY, NULL); + + nb_cli_apply_changes(vty, NULL); return CMD_SUCCESS; } @@ -3236,8 +3333,7 @@ DEFUN (show_zebra, RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { struct zebra_vrf *zvrf = vrf->info; - vty_out(vty, "%-25s %10" PRIu64 " %10" PRIu64 " %10" PRIu64 - " %10" PRIu64 " %10" PRIu64 "\n", + vty_out(vty, "%-25s %10" PRIu64 " %10" PRIu64 " %10" PRIu64" %10" PRIu64 " %10" PRIu64 "\n", vrf->name, zvrf->installs, zvrf->removals, zvrf->neigh_updates, zvrf->lsp_installs, zvrf->lsp_removals); @@ -3469,9 +3565,6 @@ static int config_write_table(struct vty *vty) /* IPForwarding configuration write function. */ static int config_write_forwarding(struct vty *vty) { - /* FIXME: Find better place for that. */ - router_id_write(vty); - if (!ipforward()) vty_out(vty, "no ip forwarding\n"); if (!ipforward_ipv6()) diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 998c035656..1bb673c940 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -142,7 +142,6 @@ static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac); static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac); /* l3-vni related APIs*/ -static zebra_l3vni_t *zl3vni_lookup(vni_t vni); static void *zl3vni_alloc(void *p); static zebra_l3vni_t *zl3vni_add(vni_t vni, vrf_id_t vrf_id); static int zl3vni_del(zebra_l3vni_t *zl3vni); @@ -1938,8 +1937,7 @@ static void zvni_print(zebra_vni_t *zvni, void **ctxt) " Number of MACs (local and remote) known for this VNI: %u\n", num_macs); vty_out(vty, - " Number of ARPs (IPv4 and IPv6, local and remote) " - "known for this VNI: %u\n", + " Number of ARPs (IPv4 and IPv6, local and remote) known for this VNI: %u\n", num_neigh); vty_out(vty, " Advertise-gw-macip: %s\n", zvni->advertise_gw_macip ? "Yes" : "No"); @@ -4274,8 +4272,7 @@ static int zvni_build_hash_table_ns(struct ns *ns, if (zvrf->zns->ns_id != vxl->link_nsid) { if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( - "Intf %s(%u) VNI %u, link not in same " - "namespace than BGP EVPN core instance ", + "Intf %s(%u) VNI %u, link not in same namespace than BGP EVPN core instance ", ifp->name, ifp->ifindex, vni); continue; } @@ -5112,7 +5109,7 @@ static void *zl3vni_alloc(void *p) /* * Look up L3 VNI hash entry. */ -static zebra_l3vni_t *zl3vni_lookup(vni_t vni) +zebra_l3vni_t *zl3vni_lookup(vni_t vni) { zebra_l3vni_t tmp_l3vni; zebra_l3vni_t *zl3vni = NULL; @@ -5218,8 +5215,7 @@ static int zl3vni_map_to_vxlan_if_ns(struct ns *ns, if (zvrf->zns->ns_id != vxl->link_nsid) { if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( - "Intf %s(%u) VNI %u, link not in same " - "namespace than BGP EVPN core instance ", + "Intf %s(%u) VNI %u, link not in same namespace than BGP EVPN core instance ", ifp->name, ifp->ifindex, vxl->vni); continue; } @@ -8285,8 +8281,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp, && mac->fwd_info.local.vid == vid) { if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( - " Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, " - "entry exists and has not changed ", + " Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, entry exists and has not changed ", sticky ? "sticky " : "", prefix_mac2str(macaddr, buf, sizeof(buf)), @@ -8434,8 +8429,7 @@ void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS) if (!zvni) { if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( - "Failed to locate VNI hash upon remote VTEP DEL, " - "VNI %u", + "Failed to locate VNI hash upon remote VTEP DEL, VNI %u", vni); continue; } @@ -9480,8 +9474,15 @@ int zebra_vxlan_vrf_disable(struct zebra_vrf *zvrf) if (!zl3vni) return 0; - zl3vni->vrf_id = VRF_UNKNOWN; zebra_vxlan_process_l3vni_oper_down(zl3vni); + + /* delete and uninstall all rmacs */ + hash_iterate(zl3vni->rmac_table, zl3vni_del_rmac_hash_entry, zl3vni); + /* delete and uninstall all next-hops */ + hash_iterate(zl3vni->nh_table, zl3vni_del_nh_hash_entry, zl3vni); + + zl3vni->vrf_id = VRF_UNKNOWN; + return 0; } diff --git a/zebra/zebra_vxlan_private.h b/zebra/zebra_vxlan_private.h index d2b02df2ad..e4b06054b2 100644 --- a/zebra/zebra_vxlan_private.h +++ b/zebra/zebra_vxlan_private.h @@ -476,6 +476,7 @@ extern zebra_l3vni_t *zl3vni_from_vrf(vrf_id_t vrf_id); extern struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni); extern struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni); extern struct interface *zl3vni_map_to_mac_vlan_if(zebra_l3vni_t *zl3vni); +extern zebra_l3vni_t *zl3vni_lookup(vni_t vni); DECLARE_HOOK(zebra_rmac_update, (zebra_mac_t *rmac, zebra_l3vni_t *zl3vni, bool delete, const char *reason), (rmac, zl3vni, delete, reason)) |
