diff options
44 files changed, 935 insertions, 357 deletions
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index c3a0fdedf0..103ac3a478 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -11,3 +11,4 @@ ac2914d3261a78cf78eec7a6e20ebbe42bb57150 ac4d0be5874fafd14212d6007fff7495edc9b152 d62a17aedeb0eebdba98238874bb13d62c48dbf9 c14777c6bfd0a446c85243d3a9835054a259c276 +996c93142d3abfab0f6d6c800474e22a8cfbdbc5 diff --git a/bfdd/dplane.c b/bfdd/dplane.c index b8f0aadd93..66b79f3b13 100644 --- a/bfdd/dplane.c +++ b/bfdd/dplane.c @@ -169,8 +169,8 @@ static void bfd_dplane_debug_message(const struct bfddp_message *msg) &msg->data.session.dst); else snprintfrr(addrs, sizeof(addrs), "src=%pI4 dst=%pI4", - &msg->data.session.src, - &msg->data.session.dst); + (struct in_addr *)&msg->data.session.src, + (struct in_addr *)&msg->data.session.dst); buf[0] = 0; if (flags & SESSION_CBIT) diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c index c93713668f..4102d102e6 100644 --- a/bgpd/bgp_bmp.c +++ b/bgpd/bgp_bmp.c @@ -49,6 +49,7 @@ #include "bgpd/bgp_fsm.h" #include "bgpd/bgp_updgrp.h" #include "bgpd/bgp_vty.h" +#include "bgpd/bgp_trace.h" static void bmp_close(struct bmp *bmp); static struct bmp_bgp *bmp_bgp_find(struct bgp *bgp); @@ -554,6 +555,8 @@ static int bmp_mirror_packet(struct peer *peer, uint8_t type, bgp_size_t size, struct bmp_targets *bt; struct bmp *bmp; + frrtrace(3, frr_bgp, bmp_mirror_packet, peer, type, packet); + gettimeofday(&tv, NULL); if (type == BGP_MSG_OPEN) { @@ -671,6 +674,8 @@ static int bmp_outgoing_packet(struct peer *peer, uint8_t type, bgp_size_t size, struct stream *packet) { if (type == BGP_MSG_OPEN) { + frrtrace(2, frr_bgp, bmp_update_saved_open, peer, packet); + struct bmp_bgp_peer *bbpeer = bmp_bgp_peer_get(peer); XFREE(MTYPE_BMP_OPEN, bbpeer->open_tx); @@ -686,6 +691,8 @@ static int bmp_peer_established(struct peer *peer) { struct bmp_bgp *bmpbgp = bmp_bgp_find(peer->bgp); + frrtrace(1, frr_bgp, bmp_peer_status_changed, peer); + if (!bmpbgp) return 0; @@ -721,6 +728,8 @@ static int bmp_peer_backward(struct peer *peer) struct bmp_bgp *bmpbgp = bmp_bgp_find(peer->bgp); struct bmp_bgp_peer *bbpeer; + frrtrace(1, frr_bgp, bmp_peer_backward_transition, peer); + if (!bmpbgp) return 0; @@ -744,6 +753,8 @@ static void bmp_eor(struct bmp *bmp, afi_t afi, safi_t safi, uint8_t flags) iana_afi_t pkt_afi; iana_safi_t pkt_safi; + frrtrace(3, frr_bgp, bmp_eor, afi, safi, flags); + s = stream_new(BGP_MAX_PACKET_SIZE); /* Make BGP update packet. */ @@ -1260,6 +1271,14 @@ static int bmp_process(struct bgp *bgp, afi_t afi, safi_t safi, struct bmp_targets *bt; struct bmp *bmp; + if (frrtrace_enabled(frr_bgp, bmp_process)) { + char pfxprint[PREFIX2STR_BUFFER]; + + prefix2str(&bn->p, pfxprint, sizeof(pfxprint)); + frrtrace(5, frr_bgp, bmp_process, peer, pfxprint, afi, safi, + withdraw); + } + if (!bmpbgp) return 0; diff --git a/bgpd/bgp_dump.c b/bgpd/bgp_dump.c index 975bba9314..944a5848ec 100644 --- a/bgpd/bgp_dump.c +++ b/bgpd/bgp_dump.c @@ -300,6 +300,13 @@ static void bgp_dump_routes_index_table(struct bgp *bgp) fflush(bgp_dump_routes.fp); } +static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi) +{ + + return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) + && CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ADDPATH_AF_TX_RCV)); +} static struct bgp_path_info * bgp_dump_route_node_record(int afi, struct bgp_dest *dest, @@ -308,16 +315,27 @@ bgp_dump_route_node_record(int afi, struct bgp_dest *dest, struct stream *obuf; size_t sizep; size_t endp; + int addpath_encoded; const struct prefix *p = bgp_dest_get_prefix(dest); obuf = bgp_dump_obuf; stream_reset(obuf); + addpath_encoded = bgp_addpath_encode_rx(path->peer, afi, SAFI_UNICAST); + /* MRT header */ - if (afi == AFI_IP) + if (afi == AFI_IP && addpath_encoded) + bgp_dump_header(obuf, MSG_TABLE_DUMP_V2, + TABLE_DUMP_V2_RIB_IPV4_UNICAST_ADDPATH, + BGP_DUMP_ROUTES); + else if (afi == AFI_IP) bgp_dump_header(obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV4_UNICAST, BGP_DUMP_ROUTES); + else if (afi == AFI_IP6 && addpath_encoded) + bgp_dump_header(obuf, MSG_TABLE_DUMP_V2, + TABLE_DUMP_V2_RIB_IPV6_UNICAST_ADDPATH, + BGP_DUMP_ROUTES); else if (afi == AFI_IP6) bgp_dump_header(obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV6_UNICAST, @@ -361,6 +379,11 @@ bgp_dump_route_node_record(int afi, struct bgp_dest *dest, /* Originated */ stream_putl(obuf, time(NULL) - (bgp_clock() - path->uptime)); + /*Path Identifier*/ + if (addpath_encoded) { + stream_putl(obuf, path->addpath_rx_id); + } + /* Dump attribute. */ /* Skip prefix & AFI/SAFI for MP_NLRI */ bgp_dump_routes_attr(obuf, path->attr, p); @@ -528,19 +551,32 @@ static void bgp_dump_packet_func(struct bgp_dump *bgp_dump, struct peer *peer, struct stream *packet) { struct stream *obuf; - + int addpath_encoded = 0; /* If dump file pointer is disabled return immediately. */ if (bgp_dump->fp == NULL) return; + if (peer->su.sa.sa_family == AF_INET) { + addpath_encoded = + bgp_addpath_encode_rx(peer, AFI_IP, SAFI_UNICAST); + } else if (peer->su.sa.sa_family == AF_INET6) { + addpath_encoded = + bgp_addpath_encode_rx(peer, AFI_IP6, SAFI_UNICAST); + } /* Make dump stream. */ obuf = bgp_dump_obuf; stream_reset(obuf); /* Dump header and common part. */ - if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)) { + if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV) && addpath_encoded) { + bgp_dump_header(obuf, MSG_PROTOCOL_BGP4MP, + BGP4MP_MESSAGE_AS4_ADDPATH, bgp_dump->type); + } else if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)) { bgp_dump_header(obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE_AS4, bgp_dump->type); + } else if (addpath_encoded) { + bgp_dump_header(obuf, MSG_PROTOCOL_BGP4MP, + BGP4MP_MESSAGE_ADDPATH, bgp_dump->type); } else { bgp_dump_header(obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE, bgp_dump->type); diff --git a/bgpd/bgp_dump.h b/bgpd/bgp_dump.h index 86c80d481c..a8cbd8ed2c 100644 --- a/bgpd/bgp_dump.h +++ b/bgpd/bgp_dump.h @@ -27,22 +27,30 @@ #define MSG_PROTOCOL_BGP4MP_ET 17 /* subtype value */ -#define BGP4MP_STATE_CHANGE 0 -#define BGP4MP_MESSAGE 1 -#define BGP4MP_ENTRY 2 -#define BGP4MP_SNAPSHOT 3 -#define BGP4MP_MESSAGE_AS4 4 -#define BGP4MP_STATE_CHANGE_AS4 5 +#define BGP4MP_STATE_CHANGE 0 +#define BGP4MP_MESSAGE 1 +#define BGP4MP_ENTRY 2 +#define BGP4MP_SNAPSHOT 3 +#define BGP4MP_MESSAGE_AS4 4 +#define BGP4MP_STATE_CHANGE_AS4 5 +#define BGP4MP_MESSAGE_ADDPATH 8 +#define BGP4MP_MESSAGE_AS4_ADDPATH 9 +#define BGP4MP_MESSAGE_LOCAL_ADDPATH 10 +#define BGP4MP_MESSAGE_AS4_LOCAL_ADDPATH 11 #define BGP_DUMP_HEADER_SIZE 12 #define BGP_DUMP_MSG_HEADER 40 -#define TABLE_DUMP_V2_PEER_INDEX_TABLE 1 -#define TABLE_DUMP_V2_RIB_IPV4_UNICAST 2 +#define TABLE_DUMP_V2_PEER_INDEX_TABLE 1 +#define TABLE_DUMP_V2_RIB_IPV4_UNICAST 2 #define TABLE_DUMP_V2_RIB_IPV4_MULTICAST 3 -#define TABLE_DUMP_V2_RIB_IPV6_UNICAST 4 +#define TABLE_DUMP_V2_RIB_IPV6_UNICAST 4 #define TABLE_DUMP_V2_RIB_IPV6_MULTICAST 5 -#define TABLE_DUMP_V2_RIB_GENERIC 6 +#define TABLE_DUMP_V2_RIB_IPV4_UNICAST_ADDPATH 8 +#define TABLE_DUMP_V2_RIB_IPV4_MULTICAST_ADDPATH 9 +#define TABLE_DUMP_V2_RIB_IPV6_UNICAST_ADDPATH 10 +#define TABLE_DUMP_V2_RIB_IPV6_MULTICAST_ADDPATH 11 +#define TABLE_DUMP_V2_RIB_GENERIC_ADDPATH 12 #define TABLE_DUMP_V2_PEER_INDEX_TABLE_IP 0 #define TABLE_DUMP_V2_PEER_INDEX_TABLE_IP6 1 diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index b69e2d71b6..30e2c3d489 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -1634,6 +1634,12 @@ static int bgp_connect_fail(struct peer *peer) return -1; } + /* + * If we are doing nht for a peer that ls v6 LL based + * massage the event system to make things happy + */ + bgp_nht_interface_events(peer); + return (bgp_stop(peer)); } diff --git a/bgpd/bgp_mplsvpn_snmp.c b/bgpd/bgp_mplsvpn_snmp.c index 055bae8432..b74cf37ac7 100644 --- a/bgpd/bgp_mplsvpn_snmp.c +++ b/bgpd/bgp_mplsvpn_snmp.c @@ -1023,14 +1023,17 @@ static struct bgp *bgpL3vpnVrfRt_lookup(struct variable *v, oid name[], *rt_type = name[namelen + vrf_name_len + sizeof(uint32_t)]; } + /* validate the RT index is in range */ + if (*rt_index > AFI_IP6) + return NULL; + if (exact) { l3vpn_bgp = bgp_lookup_by_name(vrf_name); if (l3vpn_bgp && !is_bgp_vrf_mplsvpn(l3vpn_bgp)) return NULL; if (!l3vpn_bgp) return NULL; - /* check the index and type match up */ - if ((*rt_index != AFI_IP) || (*rt_index != AFI_IP6)) + if ((*rt_index != AFI_IP) && (*rt_index != AFI_IP6)) return NULL; /* do we have RT config */ if (!(l3vpn_bgp->vpn_policy[*rt_index] @@ -1408,8 +1411,7 @@ static struct bgp_path_info *bgpL3vpnRte_lookup(struct variable *v, oid name[], break; case INETADDRESSTYPEIPV6: prefix.family = AF_INET6; - oid2in_addr(&name[i], sizeof(struct in6_addr), - &prefix.u.prefix4); /* sic */ + oid2in6_addr(&name[i], &prefix.u.prefix6); i += sizeof(struct in6_addr); break; } @@ -1431,8 +1433,7 @@ static struct bgp_path_info *bgpL3vpnRte_lookup(struct variable *v, oid name[], break; case INETADDRESSTYPEIPV6: nexthop.ipa_type = IPADDR_V6; - oid2in_addr(&name[i], sizeof(struct in6_addr), - &nexthop.ip._v4_addr); /* sic */ + oid2in6_addr(&name[i], &nexthop.ip._v6_addr); /* i += sizeof(struct in6_addr); */ break; } @@ -1458,7 +1459,7 @@ static struct bgp_path_info *bgpL3vpnRte_lookup(struct variable *v, oid name[], /* otherwise lookup the one we have */ *l3vpn_bgp = bgp_lookup_by_name(vrf_name); - if (l3vpn_bgp == NULL) + if (*l3vpn_bgp == NULL) return NULL; pi = bgp_lookup_route_next(l3vpn_bgp, dest, &prefix, policy, diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index b7f62ec0a1..46942a0bea 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -783,7 +783,9 @@ static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp, vty_out(vty, " gate %s, if %s\n", inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, sizeof(buf)), - ifindex2ifname(nexthop->ifindex, bgp->vrf_id)); + ifindex2ifname(bnc->ifindex ? bnc->ifindex + : nexthop->ifindex, + bgp->vrf_id)); break; case NEXTHOP_TYPE_IPV4: vty_out(vty, " gate %s\n", @@ -792,13 +794,17 @@ static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp, break; case NEXTHOP_TYPE_IFINDEX: vty_out(vty, " if %s\n", - ifindex2ifname(nexthop->ifindex, bgp->vrf_id)); + ifindex2ifname(bnc->ifindex ? bnc->ifindex + : nexthop->ifindex, + bgp->vrf_id)); break; case NEXTHOP_TYPE_IPV4_IFINDEX: vty_out(vty, " gate %s, if %s\n", inet_ntop(AF_INET, &nexthop->gate.ipv4, buf, sizeof(buf)), - ifindex2ifname(nexthop->ifindex, bgp->vrf_id)); + ifindex2ifname(bnc->ifindex ? bnc->ifindex + : nexthop->ifindex, + bgp->vrf_id)); break; case NEXTHOP_TYPE_BLACKHOLE: vty_out(vty, " blackhole\n"); diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h index a223ff4133..fe0a9646a0 100644 --- a/bgpd/bgp_nexthop.h +++ b/bgpd/bgp_nexthop.h @@ -41,6 +41,9 @@ PREDECL_RBTREE_UNIQ(bgp_nexthop_cache); /* BGP nexthop cache value structure. */ struct bgp_nexthop_cache { + /* The ifindex of the outgoing interface *if* it's a v6 LL */ + ifindex_t ifindex; + /* RB-tree entry. */ struct bgp_nexthop_cache_item entry; diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index bc5da0ee21..c6fa37fa8d 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -55,6 +55,7 @@ static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc, int is_bgp_static_route); static void evaluate_paths(struct bgp_nexthop_cache *bnc); static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p); +static int bgp_nht_ifp_initial(struct thread *thread); static int bgp_isvalid_nexthop(struct bgp_nexthop_cache *bnc) { @@ -129,6 +130,7 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, struct prefix p; uint32_t srte_color = 0; int is_bgp_static_route = 0; + ifindex_t ifindex = 0; if (pi) { is_bgp_static_route = ((pi->type == ZEBRA_ROUTE_BGP) @@ -155,6 +157,14 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, srte_color = pi->attr->srte_color; } else if (peer) { + /* + * Gather the ifindex for if up/down events to be + * tagged into this fun + */ + if (afi == AFI_IP6 + && IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr)) + ifindex = peer->su.sin6.sin6_scope_id; + if (!sockunion2hostprefix(&peer->su, &p)) { if (BGP_DEBUG(nht, NHT)) { zlog_debug( @@ -175,6 +185,7 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, if (!bnc) { bnc = bnc_new(tree, &p, srte_color); bnc->bgp = bgp_nexthop; + bnc->ifindex = ifindex; if (BGP_DEBUG(nht, NHT)) { char buf[PREFIX2STR_BUFFER]; @@ -430,6 +441,107 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc, evaluate_paths(bnc); } +static void bgp_nht_ifp_table_handle(struct bgp *bgp, + struct bgp_nexthop_cache_head *table, + struct interface *ifp, bool up) +{ + struct bgp_nexthop_cache *bnc; + + frr_each (bgp_nexthop_cache, table, bnc) { + if (bnc->ifindex != ifp->ifindex) + continue; + + bnc->last_update = bgp_clock(); + bnc->change_flags = 0; + + if (up) { + SET_FLAG(bnc->flags, BGP_NEXTHOP_VALID); + SET_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED); + bnc->metric = 1; + bnc->nexthop_num = 1; + } else { + UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED); + UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID); + SET_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED); + bnc->nexthop_num = 0; + bnc->metric = 0; + } + + evaluate_paths(bnc); + } +} +static void bgp_nht_ifp_handle(struct interface *ifp, bool up) +{ + struct bgp *bgp; + + bgp = bgp_lookup_by_vrf_id(ifp->vrf_id); + if (!bgp) + return; + + bgp_nht_ifp_table_handle(bgp, &bgp->nexthop_cache_table[AFI_IP6], ifp, + up); + bgp_nht_ifp_table_handle(bgp, &bgp->import_check_table[AFI_IP6], ifp, + up); +} + +void bgp_nht_ifp_up(struct interface *ifp) +{ + bgp_nht_ifp_handle(ifp, true); +} + +void bgp_nht_ifp_down(struct interface *ifp) +{ + bgp_nht_ifp_handle(ifp, false); +} + +static int bgp_nht_ifp_initial(struct thread *thread) +{ + ifindex_t ifindex = THREAD_VAL(thread); + struct interface *ifp = if_lookup_by_index_all_vrf(ifindex); + + if (!ifp) + return 0; + + if (if_is_up(ifp)) + bgp_nht_ifp_up(ifp); + else + bgp_nht_ifp_down(ifp); + + return 0; +} + +/* + * So the bnc code has the ability to handle interface up/down + * events to properly handle v6 LL peering. + * What is happening here: + * The event system for peering expects the nht code to + * report on the tracking events after we move to active + * So let's give the system a chance to report on that event + * in a manner that is expected. + */ +void bgp_nht_interface_events(struct peer *peer) +{ + struct bgp *bgp = peer->bgp; + struct bgp_nexthop_cache_head *table; + struct bgp_nexthop_cache *bnc; + struct prefix p; + + if (!IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr)) + return; + + if (!sockunion2hostprefix(&peer->su, &p)) + return; + + table = &bgp->nexthop_cache_table[AFI_IP6]; + bnc = bnc_find(table, &p, 0); + if (!bnc) + return; + + if (bnc->ifindex) + thread_add_event(bm->master, bgp_nht_ifp_initial, NULL, + bnc->ifindex, NULL); +} + void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id) { struct bgp_nexthop_cache_head *tree = NULL; @@ -661,6 +773,12 @@ static void register_zebra_rnh(struct bgp_nexthop_cache *bnc, /* Check if we have already registered */ if (bnc->flags & BGP_NEXTHOP_REGISTERED) return; + + if (bnc->ifindex) { + SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); + return; + } + if (is_bgp_import_route) sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_REGISTER); else @@ -681,6 +799,11 @@ static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc, if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED)) return; + if (bnc->ifindex) { + UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); + return; + } + if (is_bgp_import_route) sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_UNREGISTER); else @@ -843,17 +966,26 @@ static void evaluate_paths(struct bgp_nexthop_cache *bnc) if (peer) { int valid_nexthops = bgp_isvalid_nexthop(bnc); - if (valid_nexthops) - peer->last_reset = PEER_DOWN_WAITING_OPEN; - else + if (valid_nexthops) { + /* + * Peering cannot occur across a blackhole nexthop + */ + if (bnc->nexthop_num == 1 && bnc->nexthop + && bnc->nexthop->type == NEXTHOP_TYPE_BLACKHOLE) { + peer->last_reset = PEER_DOWN_WAITING_NHT; + valid_nexthops = 0; + } else + peer->last_reset = PEER_DOWN_WAITING_OPEN; + } else peer->last_reset = PEER_DOWN_WAITING_NHT; if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED)) { if (BGP_DEBUG(nht, NHT)) zlog_debug( - "%s: Updating peer (%s(%s)) status with NHT", + "%s: Updating peer (%s(%s)) status with NHT nexthops %d", __func__, peer->host, - peer->bgp->name_pretty); + peer->bgp->name_pretty, + !!valid_nexthops); bgp_fsm_nht_update(peer, !!valid_nexthops); SET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED); } diff --git a/bgpd/bgp_nht.h b/bgpd/bgp_nht.h index f374e8dfa5..a1683e1511 100644 --- a/bgpd/bgp_nht.h +++ b/bgpd/bgp_nht.h @@ -97,4 +97,8 @@ extern void bgp_l3nhg_id_free(uint32_t nhg_id); extern void bgp_l3nhg_init(void); void bgp_l3nhg_finish(void); +extern void bgp_nht_ifp_up(struct interface *ifp); +extern void bgp_nht_ifp_down(struct interface *ifp); + +extern void bgp_nht_interface_events(struct peer *peer); #endif /* _BGP_NHT_H */ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index f63a2b0247..f9e655b4e7 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -13021,51 +13021,29 @@ static void show_adj_route_header(struct vty *vty, struct bgp *bgp, } } -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, json_object *json, - uint8_t show_flags) +static void +show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table, + afi_t afi, safi_t safi, enum bgp_show_adj_route_type type, + const char *rmap_name, json_object *json, json_object *json_ar, + json_object *json_scode, json_object *json_ocode, + uint8_t show_flags, int *header1, int *header2, char *rd_str, + unsigned long *output_count, unsigned long *filtered_count) { - struct bgp_table *table; struct bgp_adj_in *ain; struct bgp_adj_out *adj; - unsigned long output_count = 0; - unsigned long filtered_count = 0; struct bgp_dest *dest; - int header1 = 1; struct bgp *bgp; - int header2 = 1; struct attr attr; int ret; struct update_subgroup *subgrp; - json_object *json_scode = NULL; - json_object *json_ocode = NULL; - json_object *json_ar = NULL; struct peer_af *paf; bool route_filtered; bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON); bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE); - - if (use_json) { - json_scode = json_object_new_object(); - json_ocode = json_object_new_object(); - json_ar = json_object_new_object(); - - json_object_string_add(json_scode, "suppressed", "s"); - json_object_string_add(json_scode, "damped", "d"); - json_object_string_add(json_scode, "history", "h"); - json_object_string_add(json_scode, "valid", "*"); - json_object_string_add(json_scode, "best", ">"); - json_object_string_add(json_scode, "multipath", "="); - json_object_string_add(json_scode, "internal", "i"); - json_object_string_add(json_scode, "ribFailure", "r"); - json_object_string_add(json_scode, "stale", "S"); - json_object_string_add(json_scode, "removed", "R"); - - json_object_string_add(json_ocode, "igp", "i"); - json_object_string_add(json_ocode, "egp", "e"); - json_object_string_add(json_ocode, "incomplete", "?"); - } + bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) + || (safi == SAFI_EVPN)) + ? true + : false; bgp = peer->bgp; @@ -13079,13 +13057,6 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, return; } - /* labeled-unicast routes live in the unicast table */ - if (safi == SAFI_LABELED_UNICAST) - table = bgp->rib[afi][SAFI_UNICAST]; - else - table = bgp->rib[afi][safi]; - - output_count = filtered_count = 0; subgrp = peer_subgroup(peer, afi, safi); if (type == bgp_show_adj_route_advertised && subgrp @@ -13129,7 +13100,7 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, vty_out(vty, "Originating default network %s\n\n", (afi == AFI_IP) ? "0.0.0.0/0" : "::/0"); } - header1 = 0; + *header1 = 0; } for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) { @@ -13139,9 +13110,23 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, if (ain->peer != peer) continue; - show_adj_route_header( - vty, bgp, table, &header1, &header2, - json, json_scode, json_ocode, wide); + show_adj_route_header(vty, bgp, table, header1, + header2, json, json_scode, + json_ocode, wide); + + if ((safi == SAFI_MPLS_VPN) + || (safi == SAFI_ENCAP) + || (safi == SAFI_EVPN)) { + if (use_json) + json_object_string_add( + json_ar, "rd", rd_str); + else if (show_rd && rd_str) { + vty_out(vty, + "Route Distinguisher: %s\n", + rd_str); + show_rd = false; + } + } attr = *ain->attr; route_filtered = false; @@ -13167,14 +13152,14 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, continue; } - if (type == bgp_show_adj_route_received && - (route_filtered || ret == RMAP_DENY)) - filtered_count++; + if (type == bgp_show_adj_route_received + && (route_filtered || ret == RMAP_DENY)) + (*filtered_count)++; route_vty_out_tmp(vty, rn_p, &attr, safi, use_json, json_ar, wide); bgp_attr_undup(&attr, ain->attr); - output_count++; + (*output_count)++; } } else if (type == bgp_show_adj_route_advertised) { RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out) @@ -13182,10 +13167,10 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, if (paf->peer != peer || !adj->attr) continue; - show_adj_route_header( - vty, bgp, table, &header1, - &header2, json, json_scode, - json_ocode, wide); + show_adj_route_header(vty, bgp, table, + header1, header2, + json, json_scode, + json_ocode, wide); const struct prefix *rn_p = bgp_dest_get_prefix(dest); @@ -13196,13 +13181,29 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, rmap_name); if (ret != RMAP_DENY) { + if ((safi == SAFI_MPLS_VPN) + || (safi == SAFI_ENCAP) + || (safi == SAFI_EVPN)) { + if (use_json) + json_object_string_add( + json_ar, + "rd", + rd_str); + else if (show_rd + && rd_str) { + vty_out(vty, + "Route Distinguisher: %s\n", + rd_str); + show_rd = false; + } + } route_vty_out_tmp( vty, rn_p, &attr, safi, use_json, json_ar, wide); - output_count++; + (*output_count)++; } else { - filtered_count++; + (*filtered_count)++; } bgp_attr_undup(&attr, adj->attr); @@ -13210,9 +13211,9 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, } else if (type == bgp_show_adj_route_bestpath) { struct bgp_path_info *pi; - show_adj_route_header(vty, bgp, table, &header1, - &header2, json, json_scode, - json_ocode, wide); + show_adj_route_header(vty, bgp, table, header1, header2, + json, json_scode, json_ocode, + wide); for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { @@ -13226,46 +13227,67 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, bgp_dest_get_prefix(dest), pi->attr, safi, use_json, json_ar, wide); - output_count++; + (*output_count)++; } } } - - if (use_json) { - json_object_object_add(json, "advertisedRoutes", json_ar); - json_object_int_add(json, "totalPrefixCounter", output_count); - json_object_int_add(json, "filteredPrefixCounter", - filtered_count); - - vty_out(vty, "%s\n", json_object_to_json_string_ext( - json, JSON_C_TO_STRING_PRETTY)); - - if (!output_count && !filtered_count) { - json_object_free(json_scode); - json_object_free(json_ocode); - } - - json_object_free(json); - } else if (output_count > 0) { - if (filtered_count > 0) - vty_out(vty, - "\nTotal number of prefixes %ld (%ld filtered)\n", - output_count, filtered_count); - else - vty_out(vty, "\nTotal number of prefixes %ld\n", - output_count); - } } 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, uint8_t show_flags) { + struct bgp *bgp; + struct bgp_table *table; json_object *json = NULL; + json_object *json_scode = NULL; + json_object *json_ocode = NULL; + json_object *json_ar = NULL; bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON); - if (use_json) + /* Init BGP headers here so they're only displayed once + * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN). + */ + int header1 = 1; + int header2 = 1; + + /* + * Initialize variables for each RD + * All prefixes under an RD is aggregated within "json_routes" + */ + char rd_str[BUFSIZ] = {0}; + json_object *json_routes = NULL; + + + /* For 2-tier tables, prefix counts need to be + * maintained across multiple runs of show_adj_route() + */ + unsigned long output_count_per_rd; + unsigned long filtered_count_per_rd; + unsigned long output_count = 0; + unsigned long filtered_count = 0; + + if (use_json) { json = json_object_new_object(); + json_ar = json_object_new_object(); + json_scode = json_object_new_object(); + json_ocode = json_object_new_object(); + + json_object_string_add(json_scode, "suppressed", "s"); + json_object_string_add(json_scode, "damped", "d"); + json_object_string_add(json_scode, "history", "h"); + json_object_string_add(json_scode, "valid", "*"); + json_object_string_add(json_scode, "best", ">"); + json_object_string_add(json_scode, "multipath", "="); + json_object_string_add(json_scode, "internal", "i"); + json_object_string_add(json_scode, "ribFailure", "r"); + json_object_string_add(json_scode, "stale", "S"); + json_object_string_add(json_scode, "removed", "R"); + + json_object_string_add(json_ocode, "igp", "i"); + json_object_string_add(json_ocode, "egp", "e"); + json_object_string_add(json_ocode, "incomplete", "?"); + } if (!peer || !peer->afc[afi][safi]) { if (use_json) { @@ -13297,7 +13319,84 @@ 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, json, show_flags); + bgp = peer->bgp; + + /* labeled-unicast routes live in the unicast table */ + if (safi == SAFI_LABELED_UNICAST) + table = bgp->rib[afi][SAFI_UNICAST]; + else + table = bgp->rib[afi][safi]; + + if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) + || (safi == SAFI_EVPN)) { + + struct bgp_dest *dest; + + for (dest = bgp_table_top(table); dest; + dest = bgp_route_next(dest)) { + table = bgp_dest_get_bgp_table_info(dest); + if (!table) + continue; + + output_count_per_rd = 0; + filtered_count_per_rd = 0; + + if (use_json) + json_routes = json_object_new_object(); + + const struct prefix_rd *prd; + prd = (const struct prefix_rd *)bgp_dest_get_prefix( + dest); + + prefix_rd2str(prd, rd_str, sizeof(rd_str)); + + show_adj_route(vty, peer, table, afi, safi, type, + rmap_name, json, json_routes, json_scode, + json_ocode, show_flags, &header1, + &header2, rd_str, &output_count_per_rd, + &filtered_count_per_rd); + + /* Don't include an empty RD in the output! */ + if (json_routes && (output_count_per_rd > 0)) + json_object_object_add(json_ar, rd_str, + json_routes); + + output_count += output_count_per_rd; + filtered_count += filtered_count_per_rd; + } + } else + show_adj_route(vty, peer, table, afi, safi, type, rmap_name, + json, json_ar, json_scode, json_ocode, + show_flags, &header1, &header2, rd_str, + &output_count, &filtered_count); + + if (use_json) { + json_object_object_add(json, "advertisedRoutes", json_ar); + json_object_int_add(json, "totalPrefixCounter", output_count); + json_object_int_add(json, "filteredPrefixCounter", + filtered_count); + + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + + if (!output_count && !filtered_count) { + json_object_free(json_scode); + json_object_free(json_ocode); + } + + if (json) + json_object_free(json); + + } else if (output_count > 0) { + if (filtered_count > 0) + vty_out(vty, + "\nTotal number of prefixes %ld (%ld filtered)\n", + output_count, filtered_count); + else + vty_out(vty, "\nTotal number of prefixes %ld\n", + output_count); + } return CMD_SUCCESS; } diff --git a/bgpd/bgp_trace.h b/bgpd/bgp_trace.h index 2566ffb928..8bc513009d 100644 --- a/bgpd/bgp_trace.h +++ b/bgpd/bgp_trace.h @@ -43,7 +43,7 @@ TRACEPOINT_EVENT_CLASS( packet_process, TP_ARGS(struct peer *, peer, bgp_size_t, size), TP_FIELDS( - ctf_string(peer, peer->host ? peer->host : "(unknown peer)") + ctf_string(peer, PEER_HOSTNAME(peer)) ) ) @@ -65,7 +65,7 @@ TRACEPOINT_EVENT( packet_read, TP_ARGS(struct peer *, peer, struct stream *, pkt), TP_FIELDS( - ctf_string(peer, peer->host ? peer->host : "(unknown peer)") + ctf_string(peer, PEER_HOSTNAME(peer)) ctf_sequence_hex(uint8_t, packet, pkt->data, size_t, STREAM_READABLE(pkt)) ) @@ -79,7 +79,7 @@ TRACEPOINT_EVENT( TP_ARGS(struct peer *, peer, char *, pfx, uint32_t, addpath_id, afi_t, afi, safi_t, safi, struct attr *, attr), TP_FIELDS( - ctf_string(peer, peer->host ? peer->host : "(unknown peer)") + ctf_string(peer, PEER_HOSTNAME(peer)) ctf_string(prefix, pfx) ctf_integer(uint32_t, addpath_id, addpath_id) ctf_integer(afi_t, afi, afi) @@ -96,7 +96,7 @@ TRACEPOINT_EVENT( TP_ARGS(struct peer *, peer, char *, pfx, afi_t, afi, safi_t, safi, const char *, result), TP_FIELDS( - ctf_string(peer, peer->host ? peer->host : "(unknown peer)") + ctf_string(peer, PEER_HOSTNAME(peer)) ctf_string(prefix, pfx) ctf_integer(afi_t, afi, afi) ctf_integer(safi_t, safi, safi) @@ -112,7 +112,7 @@ TRACEPOINT_EVENT( TP_ARGS(struct peer *, peer, char *, pfx, afi_t, afi, safi_t, safi, const char *, result), TP_FIELDS( - ctf_string(peer, peer->host ? peer->host : "(unknown peer)") + ctf_string(peer, PEER_HOSTNAME(peer)) ctf_string(prefix, pfx) ctf_integer(afi_t, afi, afi) ctf_integer(safi_t, safi, safi) @@ -122,6 +122,102 @@ TRACEPOINT_EVENT( TRACEPOINT_LOGLEVEL(frr_bgp, output_filter, TRACE_INFO) +/* BMP tracepoints */ + +/* BMP mirrors a packet to all mirror-enabled targets */ +TRACEPOINT_EVENT( + frr_bgp, + bmp_mirror_packet, + TP_ARGS(struct peer *, peer, uint8_t, type, struct stream *, pkt), + TP_FIELDS( + ctf_string(peer, PEER_HOSTNAME(peer)) + ctf_integer(uint8_t, type, type) + ctf_sequence_hex(uint8_t, packet, pkt->data, size_t, + STREAM_READABLE(pkt)) + ) +) + +TRACEPOINT_LOGLEVEL(frr_bgp, bmp_mirror_packet, TRACE_INFO) + + +/* BMP sends an EOR */ +TRACEPOINT_EVENT( + frr_bgp, + bmp_eor, + TP_ARGS(afi_t, afi, safi_t, safi, uint8_t, flags), + TP_FIELDS( + ctf_integer(afi_t, afi, afi) + ctf_integer(safi_t, safi, safi) + ctf_integer(uint8_t, flags, flags) + ) +) + +TRACEPOINT_LOGLEVEL(frr_bgp, bmp_eor, TRACE_INFO) + + +/* BMP updates its copy of the last OPEN a peer sent */ +TRACEPOINT_EVENT( + frr_bgp, + bmp_update_saved_open, + TP_ARGS(struct peer *, peer, struct stream *, pkt), + TP_FIELDS( + ctf_string(peer, PEER_HOSTNAME(peer)) + ctf_sequence_hex(uint8_t, packet, pkt->data, size_t, + STREAM_READABLE(pkt)) + ) +) + +TRACEPOINT_LOGLEVEL(frr_bgp, bmp_update_saved_open, TRACE_DEBUG) + + +/* BMP is notified of a peer status change internally */ +TRACEPOINT_EVENT( + frr_bgp, + bmp_peer_status_changed, + TP_ARGS(struct peer *, peer), + TP_FIELDS( + ctf_string(peer, PEER_HOSTNAME(peer)) + ) +) + +TRACEPOINT_LOGLEVEL(frr_bgp, bmp_peer_status_changed, TRACE_DEBUG) + + +/* + * BMP is notified that a peer has transitioned in the opposite direction of + * Established internally + */ +TRACEPOINT_EVENT( + frr_bgp, + bmp_peer_backward_transition, + TP_ARGS(struct peer *, peer), + TP_FIELDS( + ctf_string(peer, PEER_HOSTNAME(peer)) + ) +) + +TRACEPOINT_LOGLEVEL(frr_bgp, bmp_peer_backward, TRACE_DEBUG) + + +/* + * BMP is hooked for a route process + */ +TRACEPOINT_EVENT( + frr_bgp, + bmp_process, + TP_ARGS(struct peer *, peer, char *, pfx, afi_t, + afi, safi_t, safi, bool, withdraw), + TP_FIELDS( + ctf_string(peer, PEER_HOSTNAME(peer)) + ctf_string(prefix, pfx) + ctf_integer(afi_t, afi, afi) + ctf_integer(safi_t, safi, safi) + ctf_integer(bool, withdraw, withdraw) + ) +) + +TRACEPOINT_LOGLEVEL(frr_bgp, bmp_process, TRACE_DEBUG) + /* clang-format on */ #include <lttng/tracepoint-event.h> diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 627e996937..d397a5241a 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -250,6 +250,8 @@ static int bgp_ifp_up(struct interface *ifp) bgp_nbr_connected_add(bgp, nc); hook_call(bgp_vrf_status_changed, bgp, ifp); + bgp_nht_ifp_up(ifp); + return 0; } @@ -305,6 +307,8 @@ static int bgp_ifp_down(struct interface *ifp) } hook_call(bgp_vrf_status_changed, bgp, ifp); + bgp_nht_ifp_down(ifp); + return 0; } @@ -954,8 +958,11 @@ static bool bgp_table_map_apply(struct route_map *map, const struct prefix *p, zlog_debug( "Zebra rmap deny: IPv6 route %pFX nexthop %s", p, - inet_ntop(AF_INET6, nexthop, buf[1], - sizeof(buf[1]))); + nexthop ? inet_ntop(AF_INET6, nexthop, buf[1], + sizeof(buf[1])) + : inet_ntop(AF_INET, + &path->attr->nexthop, + buf[1], sizeof(buf[1]))); } } return false; diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 7a8f99163e..e79dccdab8 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -995,6 +995,8 @@ enum bgp_fsm_status { BGP_STATUS_MAX, }; +#define PEER_HOSTNAME(peer) ((peer)->host ? (peer)->host : "(unknown peer)") + /* BGP neighbor structure. */ struct peer { /* BGP structure. */ diff --git a/configure.ac b/configure.ac index 266f37a112..f3d1f38986 100755 --- a/configure.ac +++ b/configure.ac @@ -191,6 +191,11 @@ CXXFLAGS="$orig_cxxflags" AC_PROG_CC_C99 dnl NB: see C11 below +dnl Some special handling for ICC later on +if test "$CC" = "icc"; then + cc_is_icc="yes" +fi + PKG_PROG_PKG_CONFIG dnl it's 2019, sed is sed. @@ -252,7 +257,9 @@ AC_DEFUN([AC_LINK_IFELSE_FLAGS], [{ dnl ICC won't bail on unknown options without -diag-error 10006 dnl need to do this first so we get useful results for the other options -AC_C_FLAG([-diag-error 10006]) +if test "$cc_is_icc" = "yes"; then + AC_C_FLAG([-diag-error 10006]) +fi dnl AC_PROG_CC_C99 may change CC to include -std=gnu99 or something ac_cc="$CC" @@ -335,7 +342,9 @@ AC_SUBST([CXX_COMPAT_CFLAGS]) dnl ICC emits a broken warning for const char *x = a ? "b" : "c"; dnl for some reason the string consts get 'promoted' to char *, dnl triggering a const to non-const conversion warning. -AC_C_FLAG([-diag-disable 3179]) +if test "$cc_is_icc" = "yes"; then + AC_C_FLAG([-diag-disable 3179]) +fi if test "$enable_werror" = "yes" ; then WERROR="-Werror" diff --git a/doc/user/pim.rst b/doc/user/pim.rst index 05297a0609..201fe2f9ed 100644 --- a/doc/user/pim.rst +++ b/doc/user/pim.rst @@ -389,10 +389,11 @@ cause great confusion. Display IGMP interface information. -.. index:: show ip igmp join -.. clicmd:: show ip igmp join +.. index:: show ip igmp [vrf NAME] join [json] +.. clicmd:: show ip igmp [vrf NAME] join [json] - Display IGMP static join information. + Display IGMP static join information for a specific vrf. + If "vrf all" is provided, it displays information for all the vrfs present. .. index:: show ip igmp groups .. clicmd:: show ip igmp groups diff --git a/lib/clippy.c b/lib/clippy.c index 15cd9d7a4b..b52c48ec92 100644 --- a/lib/clippy.c +++ b/lib/clippy.c @@ -51,7 +51,8 @@ int main(int argc, char **argv) #if PY_VERSION_HEX >= 0x03040000 /* 3.4 */ Py_SetStandardStreamEncoding("UTF-8", NULL); #endif - Py_SetProgramName(wconv(argv[0])); + wchar_t *name = wconv(argv[0]); + Py_SetProgramName(name); PyImport_AppendInittab("_clippy", command_py_init); Py_Initialize(); @@ -93,6 +94,7 @@ int main(int argc, char **argv) for (int i = 1; i < argc; i++) free(wargv[i - 1]); #endif + free(name); free(wargv); return 0; } diff --git a/lib/defun_lex.l b/lib/defun_lex.l index bc5fbd24d9..af506f13d6 100644 --- a/lib/defun_lex.l +++ b/lib/defun_lex.l @@ -80,6 +80,8 @@ static void extendbuf(char **what, const char *arg) } #define extend(x) extendbuf(&value, x) +#ifndef __clang_analyzer__ + %} ID [A-Za-z0-9_]+ @@ -157,6 +159,8 @@ SPECIAL [(),] %% +#endif /* __clang_analyzer__ */ + static int yylex_clr(char **retbuf) { int rv = def_yylex(); diff --git a/lib/libfrr.c b/lib/libfrr.c index b83883779c..51b97369c9 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -71,6 +71,7 @@ static char vtypath_default[512]; bool debug_memstats_at_exit = false; static bool nodetach_term, nodetach_daemon; +static uint64_t startup_fds; static char comb_optstr[256]; static struct option comb_lo[64]; @@ -341,6 +342,28 @@ void frr_preinit(struct frr_daemon_info *daemon, int argc, char **argv) strlcpy(frr_protonameinst, di->logname, sizeof(frr_protonameinst)); di->cli_mode = FRR_CLI_CLASSIC; + + /* we may be starting with extra FDs open for whatever purpose, + * e.g. logging, some module, etc. Recording them here allows later + * checking whether an fd is valid for such extension purposes, + * without this we could end up e.g. logging to a BGP session fd. + */ + startup_fds = 0; + for (int i = 0; i < 64; i++) { + struct stat st; + + if (fstat(i, &st)) + continue; + if (S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode)) + continue; + + startup_fds |= UINT64_C(0x1) << (uint64_t)i; + } +} + +bool frr_is_startup_fd(int fd) +{ + return !!(startup_fds & (UINT64_C(0x1) << (uint64_t)fd)); } void frr_opt_add(const char *optstr, const struct option *longopts, diff --git a/lib/libfrr.h b/lib/libfrr.h index c446931468..825f502bdf 100644 --- a/lib/libfrr.h +++ b/lib/libfrr.h @@ -138,7 +138,8 @@ extern __attribute__((__noreturn__)) void frr_help_exit(int status); extern struct thread_master *frr_init(void); extern const char *frr_get_progname(void); extern enum frr_cli_mode frr_get_cli_mode(void); -uint32_t frr_get_fd_limit(void); +extern uint32_t frr_get_fd_limit(void); +extern bool frr_is_startup_fd(int fd); DECLARE_HOOK(frr_late_init, (struct thread_master * tm), (tm)) DECLARE_HOOK(frr_very_late_init, (struct thread_master * tm), (tm)) diff --git a/lib/link_state.c b/lib/link_state.c index 6bd7ef703c..ecf0d0698d 100644 --- a/lib/link_state.c +++ b/lib/link_state.c @@ -1246,7 +1246,7 @@ void ls_dump_ted(struct ls_ted *ted) for (ALL_LIST_ELEMENTS_RO(vertex->incoming_edges, lst_node, vertex_edge)) { zlog_debug( - " inc edge key:%lldn attr key:%pI4 loc:(%pI4) rmt:(%pI4)", + " inc edge key:%"PRIu64"n attr key:%pI4 loc:(%pI4) rmt:(%pI4)", vertex_edge->key, &vertex_edge->attributes->adv.id.ip.addr, &vertex_edge->attributes->standard.local, @@ -1255,7 +1255,7 @@ void ls_dump_ted(struct ls_ted *ted) for (ALL_LIST_ELEMENTS_RO(vertex->outgoing_edges, lst_node, vertex_edge)) { zlog_debug( - " out edge key:%lld attr key:%pI4 loc:(%pI4) rmt:(%pI4)", + " out edge key:%"PRIu64" attr key:%pI4 loc:(%pI4) rmt:(%pI4)", vertex_edge->key, &vertex_edge->attributes->adv.id.ip.addr, &vertex_edge->attributes->standard.local, @@ -1264,7 +1264,8 @@ void ls_dump_ted(struct ls_ted *ted) } frr_each(edges, &ted->edges, edge) { ls_edge2msg(&msg, edge); - zlog_debug(" Ted edge key:%lld src:%s dst:%s", edge->key, + zlog_debug(" Ted edge key:%"PRIu64" src:%s dst:%s", + edge->key, edge->source ? edge->source->node->name : "no_source", edge->destination ? edge->destination->node->name diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c index ad7dad5cb2..1416b758d8 100644 --- a/lib/northbound_cli.c +++ b/lib/northbound_cli.c @@ -600,7 +600,19 @@ void nb_cli_show_dnode_cmds(struct vty *vty, struct lyd_node *root, (*nb_node->cbs.cli_show_end)(vty, parent); } + /* + * There is a possible path in this macro that ends up + * dereferencing child->parent->parent. We just null checked + * child->parent by checking (ly_iter_next_up(child) != NULL) + * above. + * + * I am not sure whether it is possible for the other + * conditions within this macro guarding the problem + * dereference to be satisfied when child->parent == NULL. + */ +#ifndef __clang_analyzer__ LY_TREE_DFS_END(root, next, child); +#endif } } diff --git a/lib/privs.c b/lib/privs.c index 1bb5d059c8..5ca3c0d886 100644 --- a/lib/privs.c +++ b/lib/privs.c @@ -587,6 +587,8 @@ void zprivs_preinit(struct zebra_privs_t *zprivs) } } +struct zebra_privs_t *lib_privs; + void zprivs_init(struct zebra_privs_t *zprivs) { gid_t groups[NGROUPS_MAX] = {}; @@ -598,6 +600,8 @@ void zprivs_init(struct zebra_privs_t *zprivs) || zprivs->cap_num_i)) return; + lib_privs = zprivs; + if (zprivs->user) { ngroups = array_size(groups); if (getgrouplist(zprivs->user, zprivs_state.zgid, groups, @@ -701,6 +705,8 @@ void zprivs_terminate(struct zebra_privs_t *zprivs) { struct zebra_privs_refs_t *refs; + lib_privs = NULL; + if (!zprivs) { fprintf(stderr, "%s: no privs struct given, terminating", __func__); diff --git a/lib/privs.h b/lib/privs.h index 18ba8e8888..2dcdbe2e6c 100644 --- a/lib/privs.h +++ b/lib/privs.h @@ -100,6 +100,8 @@ struct zprivs_ids_t { gid_t gid_vty; /* vty gid */ }; +extern struct zebra_privs_t *lib_privs; + /* initialise zebra privileges */ extern void zprivs_preinit(struct zebra_privs_t *zprivs); extern void zprivs_init(struct zebra_privs_t *zprivs); diff --git a/lib/smux.h b/lib/smux.h index e07df2369f..11c1becd60 100644 --- a/lib/smux.h +++ b/lib/smux.h @@ -143,6 +143,7 @@ extern int smux_trap_multi_index(struct variable *vp, size_t vp_len, size_t trapobjlen, uint8_t sptrap); extern int oid_compare(const oid *, int, const oid *, int); extern void oid2in_addr(oid[], int, struct in_addr *); +extern void oid2in6_addr(oid oid[], struct in6_addr *addr); extern void oid2int(oid oid[], int *dest); extern void *oid_copy(void *, const void *, size_t); extern void oid_copy_addr(oid[], const struct in_addr *, int); diff --git a/lib/snmp.c b/lib/snmp.c index e92f622bb9..17a4ed4a1d 100644 --- a/lib/snmp.c +++ b/lib/snmp.c @@ -64,6 +64,17 @@ void oid2in_addr(oid oid[], int len, struct in_addr *addr) *pnt++ = oid[i]; } +void oid2in6_addr(oid oid[], struct in6_addr *addr) +{ + unsigned int i; + uint8_t *pnt; + + pnt = (uint8_t *)addr; + + for (i = 0; i < sizeof(struct in6_addr); i++) + *pnt++ = oid[i]; +} + void oid2int(oid oid[], int *dest) { uint8_t i; diff --git a/lib/thread.c b/lib/thread.c index e0d734a951..f7f1ed8b7e 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -58,8 +58,7 @@ static int thread_timer_cmp(const struct thread *a, const struct thread *b) return 0; } -DECLARE_HEAP(thread_timer_list, struct thread, timeritem, - thread_timer_cmp) +DECLARE_HEAP(thread_timer_list, struct thread, timeritem, thread_timer_cmp) #if defined(__APPLE__) #include <mach/mach.h> @@ -910,31 +909,33 @@ struct thread *_thread_add_read_write(const struct xref_threadsched *xref, static struct thread * _thread_add_timer_timeval(const struct xref_threadsched *xref, struct thread_master *m, int (*func)(struct thread *), - int type, void *arg, struct timeval *time_relative, + void *arg, struct timeval *time_relative, struct thread **t_ptr) { struct thread *thread; + struct timeval t; assert(m != NULL); - assert(type == THREAD_TIMER); assert(time_relative); frrtrace(9, frr_libfrr, schedule_timer, m, xref->funcname, xref->xref.file, xref->xref.line, t_ptr, 0, 0, arg, (long)time_relative->tv_sec); + /* Compute expiration/deadline time. */ + monotime(&t); + timeradd(&t, time_relative, &t); + frr_with_mutex(&m->mtx) { if (t_ptr && *t_ptr) /* thread is already scheduled; don't reschedule */ return NULL; - thread = thread_get(m, type, func, arg, xref); + thread = thread_get(m, THREAD_TIMER, func, arg, xref); frr_with_mutex(&thread->mtx) { - monotime(&thread->u.sands); - timeradd(&thread->u.sands, time_relative, - &thread->u.sands); + thread->u.sands = t; thread_timer_list_add(&m->timer, thread); if (t_ptr) { *t_ptr = thread; @@ -942,7 +943,12 @@ _thread_add_timer_timeval(const struct xref_threadsched *xref, } } - AWAKEN(m); + /* The timer list is sorted - if this new timer + * might change the time we'll wait for, give the pthread + * a chance to re-compute. + */ + if (thread_timer_list_first(&m->timer) == thread) + AWAKEN(m); } return thread; @@ -962,8 +968,7 @@ struct thread *_thread_add_timer(const struct xref_threadsched *xref, trel.tv_sec = timer; trel.tv_usec = 0; - return _thread_add_timer_timeval(xref, m, func, THREAD_TIMER, arg, - &trel, t_ptr); + return _thread_add_timer_timeval(xref, m, func, arg, &trel, t_ptr); } /* Add timer event thread with "millisecond" resolution */ @@ -980,19 +985,17 @@ struct thread *_thread_add_timer_msec(const struct xref_threadsched *xref, trel.tv_sec = timer / 1000; trel.tv_usec = 1000 * (timer % 1000); - return _thread_add_timer_timeval(xref, m, func, THREAD_TIMER, arg, - &trel, t_ptr); + return _thread_add_timer_timeval(xref, m, func, arg, &trel, t_ptr); } -/* Add timer event thread with "millisecond" resolution */ +/* Add timer event thread with "timeval" resolution */ struct thread *_thread_add_timer_tv(const struct xref_threadsched *xref, struct thread_master *m, int (*func)(struct thread *), void *arg, struct timeval *tv, struct thread **t_ptr) { - return _thread_add_timer_timeval(xref, m, func, THREAD_TIMER, arg, tv, - t_ptr); + return _thread_add_timer_timeval(xref, m, func, arg, tv, t_ptr); } /* Add simple event thread. */ @@ -1449,20 +1452,21 @@ static void thread_process_io(struct thread_master *m, unsigned int num) } /* Add all timers that have popped to the ready list. */ -static unsigned int thread_process_timers(struct thread_timer_list_head *timers, +static unsigned int thread_process_timers(struct thread_master *m, struct timeval *timenow) { struct thread *thread; unsigned int ready = 0; - while ((thread = thread_timer_list_first(timers))) { + while ((thread = thread_timer_list_first(&m->timer))) { if (timercmp(timenow, &thread->u.sands, <)) - return ready; - thread_timer_list_pop(timers); + break; + thread_timer_list_pop(&m->timer); thread->type = THREAD_READY; - thread_list_add_tail(&thread->master->ready, thread); + thread_list_add_tail(&m->ready, thread); ready++; } + return ready; } @@ -1584,7 +1588,7 @@ struct thread *thread_fetch(struct thread_master *m, struct thread *fetch) /* Post timers to ready queue. */ monotime(&now); - thread_process_timers(&m->timer, &now); + thread_process_timers(m, &now); /* Post I/O to ready queue. */ if (num > 0) @@ -73,7 +73,8 @@ enum event { #endif /* VTYSH */ }; -static void vty_event(enum event, int, struct vty *); +static void vty_event_serv(enum event event, int sock); +static void vty_event(enum event, struct vty *); /* Extern host structure from command.c */ extern struct host host; @@ -1284,6 +1285,7 @@ static int vty_execute(struct vty *vty) #define VTY_NORMAL 0 #define VTY_PRE_ESCAPE 1 #define VTY_ESCAPE 2 +#define VTY_CR 3 /* Escape character command map. */ static void vty_escape_map(unsigned char c, struct vty *vty) @@ -1325,14 +1327,13 @@ static int vty_read(struct thread *thread) int nbytes; unsigned char buf[VTY_READ_BUFSIZ]; - int vty_sock = THREAD_FD(thread); struct vty *vty = THREAD_ARG(thread); /* Read raw data from socket */ if ((nbytes = read(vty->fd, buf, VTY_READ_BUFSIZ)) <= 0) { if (nbytes < 0) { if (ERRNO_IO_RETRY(errno)) { - vty_event(VTY_READ, vty_sock, vty); + vty_event(VTY_READ, vty); return 0; } vty->monitor = 0; /* disable monitoring to avoid @@ -1423,6 +1424,17 @@ static int vty_read(struct thread *thread) continue; } + if (vty->escape == VTY_CR) { + /* if we get CR+NL, the NL results in an extra empty + * prompt line being printed without this; just drop + * the NL if it immediately follows CR. + */ + vty->escape = VTY_NORMAL; + + if (buf[i] == '\n') + continue; + } + switch (buf[i]) { case CONTROL('A'): vty_beginning_of_line(vty); @@ -1467,9 +1479,12 @@ static int vty_read(struct thread *thread) case CONTROL('Z'): vty_end_config(vty); break; - case '\n': case '\r': + vty->escape = VTY_CR; + /* fallthru */ + case '\n': vty_out(vty, "\n"); + buffer_flush_available(vty->obuf, vty->wfd); vty_execute(vty); break; case '\t': @@ -1500,8 +1515,8 @@ static int vty_read(struct thread *thread) if (vty->status == VTY_CLOSE) vty_close(vty); else { - vty_event(VTY_WRITE, vty->wfd, vty); - vty_event(VTY_READ, vty_sock, vty); + vty_event(VTY_WRITE, vty); + vty_event(VTY_READ, vty); } return 0; } @@ -1511,7 +1526,6 @@ static int vty_flush(struct thread *thread) { int erase; buffer_status_t flushrc; - int vty_sock = THREAD_FD(thread); struct vty *vty = THREAD_ARG(thread); /* Tempolary disable read thread. */ @@ -1523,20 +1537,20 @@ static int vty_flush(struct thread *thread) /* N.B. if width is 0, that means we don't know the window size. */ if ((vty->lines == 0) || (vty->width == 0) || (vty->height == 0)) - flushrc = buffer_flush_available(vty->obuf, vty_sock); + flushrc = buffer_flush_available(vty->obuf, vty->wfd); else if (vty->status == VTY_MORELINE) - flushrc = buffer_flush_window(vty->obuf, vty_sock, vty->width, + flushrc = buffer_flush_window(vty->obuf, vty->wfd, vty->width, 1, erase, 0); else flushrc = buffer_flush_window( - vty->obuf, vty_sock, vty->width, + vty->obuf, vty->wfd, vty->width, vty->lines >= 0 ? vty->lines : vty->height, erase, 0); switch (flushrc) { case BUFFER_ERROR: vty->monitor = 0; /* disable monitoring to avoid infinite recursion */ - zlog_info("buffer_flush failed on vty client fd %d, closing", - vty->fd); + zlog_info("buffer_flush failed on vty client fd %d/%d, closing", + vty->fd, vty->wfd); buffer_reset(vty->lbuf); buffer_reset(vty->obuf); vty_close(vty); @@ -1547,14 +1561,14 @@ static int vty_flush(struct thread *thread) else { vty->status = VTY_NORMAL; if (vty->lines == 0) - vty_event(VTY_READ, vty_sock, vty); + vty_event(VTY_READ, vty); } break; case BUFFER_PENDING: /* There is more data waiting to be written. */ vty->status = VTY_MORE; if (vty->lines == 0) - vty_event(VTY_WRITE, vty_sock, vty); + vty_event(VTY_WRITE, vty); break; } @@ -1657,8 +1671,8 @@ static struct vty *vty_create(int vty_sock, union sockunion *su) vty_prompt(vty); /* Add read/write thread. */ - vty_event(VTY_WRITE, vty_sock, vty); - vty_event(VTY_READ, vty_sock, vty); + vty_event(VTY_WRITE, vty); + vty_event(VTY_READ, vty); return vty; } @@ -1714,7 +1728,6 @@ void vty_stdio_resume(void) termios = stdio_orig_termios; termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); - termios.c_oflag &= ~OPOST; termios.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN); termios.c_cflag &= ~(CSIZE | PARENB); termios.c_cflag |= CS8; @@ -1725,8 +1738,8 @@ void vty_stdio_resume(void) vty_prompt(stdio_vty); /* Add read/write thread. */ - vty_event(VTY_WRITE, 1, stdio_vty); - vty_event(VTY_READ, 0, stdio_vty); + vty_event(VTY_WRITE, stdio_vty); + vty_event(VTY_READ, stdio_vty); } void vty_stdio_close(void) @@ -1775,7 +1788,7 @@ static int vty_accept(struct thread *thread) accept_sock = THREAD_FD(thread); /* We continue hearing vty socket. */ - vty_event(VTY_SERV, accept_sock, NULL); + vty_event_serv(VTY_SERV, accept_sock); memset(&su, 0, sizeof(union sockunion)); @@ -1805,7 +1818,7 @@ static int vty_accept(struct thread *thread) close(vty_sock); /* continue accepting connections */ - vty_event(VTY_SERV, accept_sock, NULL); + vty_event_serv(VTY_SERV, accept_sock); return 0; } @@ -1821,7 +1834,7 @@ static int vty_accept(struct thread *thread) close(vty_sock); /* continue accepting connections */ - vty_event(VTY_SERV, accept_sock, NULL); + vty_event_serv(VTY_SERV, accept_sock); return 0; } @@ -1894,7 +1907,7 @@ static void vty_serv_sock_addrinfo(const char *hostname, unsigned short port) continue; } - vty_event(VTY_SERV, sock, NULL); + vty_event_serv(VTY_SERV, sock); } while ((ainfo = ainfo->ai_next) != NULL); freeaddrinfo(ainfo_save); @@ -1972,7 +1985,7 @@ static void vty_serv_un(const char *path) } } - vty_event(VTYSH_SERV, sock, NULL); + vty_event_serv(VTYSH_SERV, sock); } /* #define VTYSH_DEBUG 1 */ @@ -1987,7 +2000,7 @@ static int vtysh_accept(struct thread *thread) accept_sock = THREAD_FD(thread); - vty_event(VTYSH_SERV, accept_sock, NULL); + vty_event_serv(VTYSH_SERV, accept_sock); memset(&client, 0, sizeof(struct sockaddr_un)); client_len = sizeof(struct sockaddr_un); @@ -2021,7 +2034,7 @@ static int vtysh_accept(struct thread *thread) vty->type = VTY_SHELL_SERV; vty->node = VIEW_NODE; - vty_event(VTYSH_READ, sock, vty); + vty_event(VTYSH_READ, vty); return 0; } @@ -2030,7 +2043,7 @@ static int vtysh_flush(struct vty *vty) { switch (buffer_flush_available(vty->obuf, vty->wfd)) { case BUFFER_PENDING: - vty_event(VTYSH_WRITE, vty->wfd, vty); + vty_event(VTYSH_WRITE, vty); break; case BUFFER_ERROR: vty->monitor = @@ -2063,7 +2076,7 @@ static int vtysh_read(struct thread *thread) if ((nbytes = read(sock, buf, VTY_READ_BUFSIZ)) <= 0) { if (nbytes < 0) { if (ERRNO_IO_RETRY(errno)) { - vty_event(VTYSH_READ, sock, vty); + vty_event(VTYSH_READ, vty); return 0; } vty->monitor = 0; /* disable monitoring to avoid @@ -2129,7 +2142,7 @@ static int vtysh_read(struct thread *thread) if (vty->status == VTY_CLOSE) vty_close(vty); else - vty_event(VTYSH_READ, sock, vty); + vty_event(VTYSH_READ, vty); return 0; } @@ -2636,33 +2649,44 @@ int vty_config_node_exit(struct vty *vty) /* Master of the threads. */ static struct thread_master *vty_master; -static void vty_event(enum event event, int sock, struct vty *vty) +static void vty_event_serv(enum event event, int sock) { struct thread *vty_serv_thread = NULL; switch (event) { case VTY_SERV: - vty_serv_thread = thread_add_read(vty_master, vty_accept, vty, - sock, NULL); + vty_serv_thread = thread_add_read(vty_master, vty_accept, + NULL, sock, NULL); vector_set_index(Vvty_serv_thread, sock, vty_serv_thread); break; #ifdef VTYSH case VTYSH_SERV: - vty_serv_thread = thread_add_read(vty_master, vtysh_accept, vty, - sock, NULL); + vty_serv_thread = thread_add_read(vty_master, vtysh_accept, + NULL, sock, NULL); vector_set_index(Vvty_serv_thread, sock, vty_serv_thread); break; +#endif /* VTYSH */ + default: + assert(!"vty_event_serv() called incorrectly"); + } +} + +static void vty_event(enum event event, struct vty *vty) +{ + switch (event) { +#ifdef VTYSH case VTYSH_READ: - thread_add_read(vty_master, vtysh_read, vty, sock, + thread_add_read(vty_master, vtysh_read, vty, vty->fd, &vty->t_read); break; case VTYSH_WRITE: - thread_add_write(vty_master, vtysh_write, vty, sock, + thread_add_write(vty_master, vtysh_write, vty, vty->wfd, &vty->t_write); break; #endif /* VTYSH */ case VTY_READ: - thread_add_read(vty_master, vty_read, vty, sock, &vty->t_read); + thread_add_read(vty_master, vty_read, vty, vty->fd, + &vty->t_read); /* Time out treatment. */ if (vty->v_timeout) { @@ -2672,7 +2696,7 @@ static void vty_event(enum event event, int sock, struct vty *vty) } break; case VTY_WRITE: - thread_add_write(vty_master, vty_flush, vty, sock, + thread_add_write(vty_master, vty_flush, vty, vty->wfd, &vty->t_write); break; case VTY_TIMEOUT_RESET: @@ -2681,6 +2705,8 @@ static void vty_event(enum event event, int sock, struct vty *vty) thread_add_timer(vty_master, vty_timeout, vty, vty->v_timeout, &vty->t_timeout); break; + default: + assert(!"vty_event() called incorrectly"); } } @@ -2727,7 +2753,7 @@ static int exec_timeout(struct vty *vty, const char *min_str, vty_timeout_val = timeout; vty->v_timeout = timeout; - vty_event(VTY_TIMEOUT_RESET, 0, vty); + vty_event(VTY_TIMEOUT_RESET, vty); return CMD_SUCCESS; diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 0cc3bd2cc9..621cc36a0c 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -1976,8 +1976,11 @@ DEFUN (no_ipv6_ospf6_passive, UNSET_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE); THREAD_OFF(oi->thread_send_hello); THREAD_OFF(oi->thread_sso); - thread_add_event(master, ospf6_hello_send, oi, 0, - &oi->thread_send_hello); + + /* don't send hellos over loopback interface */ + if (!if_is_loopback(oi->interface)) + thread_add_event(master, ospf6_hello_send, oi, 0, + &oi->thread_send_hello); return CMD_SUCCESS; } diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index 2abe64ac60..5394ba9786 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -989,10 +989,15 @@ static int ospf6_intra_prefix_lsa_show(struct vty *vty, struct ospf6_lsa *lsa, buf, prefix->prefix_length); json_object_string_add(json_loop, "prefix", prefix_string); + json_object_int_add(json_loop, "metric", + ntohs(prefix->prefix_metric)); json_object_array_add(json_arr, json_loop); - } else + } else { vty_out(vty, " Prefix: %s/%d\n", buf, prefix->prefix_length); + vty_out(vty, " Metric: %d\n", + ntohs(prefix->prefix_metric)); + } } if (use_json) json_object_object_add(json_obj, "prefix", json_arr); diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c index 5f9953782c..bd180a9f55 100644 --- a/ospf6d/ospf6_message.c +++ b/ospf6d/ospf6_message.c @@ -239,23 +239,30 @@ static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst, /* HelloInterval check */ if (ntohs(hello->hello_interval) != oi->hello_interval) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) - zlog_debug("HelloInterval mismatch"); + zlog_warn( + "VRF %s: I/F %s HelloInterval mismatch: (my %d, rcvd %d)", + vrf_id_to_name(oi->interface->vrf_id), + oi->interface->name, oi->hello_interval, + ntohs(hello->hello_interval)); return; } /* RouterDeadInterval check */ if (ntohs(hello->dead_interval) != oi->dead_interval) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) - zlog_debug("RouterDeadInterval mismatch"); + zlog_warn( + "VRF %s: I/F %s DeadInterval mismatch: (my %d, rcvd %d)", + vrf_id_to_name(oi->interface->vrf_id), + oi->interface->name, oi->dead_interval, + ntohs(hello->dead_interval)); return; } /* E-bit check */ if (OSPF6_OPT_ISSET(hello->options, OSPF6_OPT_E) != OSPF6_OPT_ISSET(oi->area->options, OSPF6_OPT_E)) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) - zlog_debug("E-bit mismatch"); + zlog_warn("VRF %s: IF %s E-bit mismatch", + vrf_id_to_name(oi->interface->vrf_id), + oi->interface->name); return; } @@ -385,8 +392,10 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh, memcpy(on->options, dbdesc->options, sizeof(on->options)); } else { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) - zlog_debug("Negotiation failed"); + zlog_warn( + "VRF %s: Nbr %s: Negotiation failed", + vrf_id_to_name(on->ospf6_if->interface->vrf_id), + on->name); return; } /* fall through to exchange */ @@ -599,8 +608,10 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh, memcpy(on->options, dbdesc->options, sizeof(on->options)); } else { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) - zlog_debug("Negotiation failed"); + zlog_warn( + "VRF %s: Nbr %s Negotiation failed", + vrf_id_to_name(on->ospf6_if->interface->vrf_id), + on->name); return; } break; @@ -765,8 +776,9 @@ static void ospf6_dbdesc_recv(struct in6_addr *src, struct in6_addr *dst, /* Interface MTU check */ if (!oi->mtu_ignore && ntohs(dbdesc->ifmtu) != oi->ifmtu) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) - zlog_debug("I/F MTU mismatch"); + zlog_warn("VRF %s: I/F %s MTU mismatch (my %d rcvd %d)", + vrf_id_to_name(oi->interface->vrf_id), + oi->interface->name, oi->ifmtu, ntohs(dbdesc->ifmtu)); return; } @@ -1316,34 +1328,37 @@ static int ospf6_rxpacket_examin(struct ospf6_interface *oi, /* Area-ID check */ if (oh->area_id != oi->area->area_id) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) { - if (oh->area_id == OSPF_AREA_BACKBONE) - zlog_debug( - "%s: Message may be via Virtual Link: not supported", - __func__); - else - zlog_debug( - "%s: Area-ID mismatch (my %s, rcvd %s)", - __func__, - inet_ntop(AF_INET, &oi->area->area_id, - buf[0], INET_ADDRSTRLEN), - inet_ntop(AF_INET, &oh->area_id, buf[1], - INET_ADDRSTRLEN)); - } + if (oh->area_id == OSPF_AREA_BACKBONE) + zlog_warn( + "VRF %s: I/F %s Message may be via Virtual Link: not supported", + vrf_id_to_name(oi->interface->vrf_id), + oi->interface->name); + else + zlog_warn( + "VRF %s: I/F %s Area-ID mismatch (my %s, rcvd %s)", + vrf_id_to_name(oi->interface->vrf_id), + oi->interface->name, + inet_ntop(AF_INET, &oi->area->area_id, buf[0], + INET_ADDRSTRLEN), + inet_ntop(AF_INET, &oh->area_id, buf[1], + INET_ADDRSTRLEN)); return MSG_NG; } /* Instance-ID check */ if (oh->instance_id != oi->instance_id) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) - zlog_debug("%s: Instance-ID mismatch (my %u, rcvd %u)", - __func__, oi->instance_id, oh->instance_id); + zlog_warn( + "VRF %s: I/F %s Instance-ID mismatch (my %u, rcvd %u)", + vrf_id_to_name(oi->interface->vrf_id), + oi->interface->name, oi->instance_id, oh->instance_id); return MSG_NG; } /* Router-ID check */ if (oh->router_id == oi->area->ospf6->router_id) { - zlog_warn("%s: Duplicate Router-ID (%s)", __func__, + zlog_warn("VRF %s: I/F %s Duplicate Router-ID (%s)", + vrf_id_to_name(oi->interface->vrf_id), + oi->interface->name, inet_ntop(AF_INET, &oh->router_id, buf[0], INET_ADDRSTRLEN)); return MSG_NG; diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index cb2b7c2365..5f74984c66 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -458,11 +458,11 @@ static int ospf_flood_through_interface(struct ospf_interface *oi, if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "%s:ospf_flood_through_interface(): considering int %s, INBR(%s), LSA[%s] AGE %u", - ospf_get_name(oi->ospf), IF_NAME(oi), - inbr ? - inet_ntop(AF_INET, &inbr->router_id, buf, sizeof(buf)) : - "NULL", + "%s: considering int %s (%s), INBR(%s), LSA[%s] AGE %u", + __func__, IF_NAME(oi), ospf_get_name(oi->ospf), + inbr ? inet_ntop(AF_INET, &inbr->router_id, buf, + sizeof(buf)) + : "NULL", dump_lsa_key(lsa), ntohs(lsa->data->ls_age)); if (!ospf_if_is_enable(oi)) @@ -483,8 +483,8 @@ static int ospf_flood_through_interface(struct ospf_interface *oi, onbr = rn->info; if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_flood_through_interface(): considering nbr %pI4(%s) (%s)", - &onbr->router_id, + "%s: considering nbr %pI4 via %s (%s), state: %s", + __func__, &onbr->router_id, IF_NAME(oi), ospf_get_name(oi->ospf), lookup_msg(ospf_nsm_state_msg, onbr->state, NULL)); @@ -504,7 +504,10 @@ static int ospf_flood_through_interface(struct ospf_interface *oi, if (onbr->state < NSM_Full) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "ospf_flood_through_interface(): nbr adj is not Full"); + "%s: adj to onbr %pI4 is not Full (%s)", + __func__, &onbr->router_id, + lookup_msg(ospf_nsm_state_msg, + onbr->state, NULL)); ls_req = ospf_ls_request_lookup(onbr, lsa); if (ls_req != NULL) { int ret; @@ -534,7 +537,11 @@ static int ospf_flood_through_interface(struct ospf_interface *oi, if (!CHECK_FLAG(onbr->options, OSPF_OPTION_O)) { if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) zlog_debug( - "Skip this neighbor: Not Opaque-capable."); + "%s: Skipping neighbor %s via %s -- Not Opaque-capable.", + __func__, IF_NAME(oi), + inet_ntop(AF_INET, + &onbr->router_id, buf, + sizeof(buf))); continue; } } @@ -550,7 +557,11 @@ static int ospf_flood_through_interface(struct ospf_interface *oi, &onbr->router_id)) { if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) zlog_debug( - "Skip this neighbor: inbr == onbr"); + "%s: Skipping neighbor %s via %s -- inbr == onbr.", + __func__, IF_NAME(oi), + inet_ntop(AF_INET, + &inbr->router_id, buf, + sizeof(buf))); continue; } } else { @@ -562,7 +573,11 @@ static int ospf_flood_through_interface(struct ospf_interface *oi, &onbr->router_id)) { if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) zlog_debug( - "Skip this neighbor: lsah->adv_router == onbr"); + "%s: Skipping neighbor %s via %s -- lsah->adv_router == onbr.", + __func__, IF_NAME(oi), + inet_ntop(AF_INET, + &onbr->router_id, buf, + sizeof(buf))); continue; } } @@ -591,9 +606,9 @@ static int ospf_flood_through_interface(struct ospf_interface *oi, received the LSA already. */ 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", - IF_NAME(oi)); + zlog_debug("%s: DR/BDR NOT SEND to int %s (%s)", + __func__, IF_NAME(oi), + ospf_get_name(oi->ospf)); return 1; } @@ -606,8 +621,9 @@ 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", - IF_NAME(oi)); + "%s: ISM_Backup NOT SEND to int %s (%s)", + __func__, IF_NAME(oi), + ospf_get_name(oi->ospf)); return 1; } } @@ -620,9 +636,8 @@ static int ospf_flood_through_interface(struct ospf_interface *oi, value of MaxAge). */ /* 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", - IF_NAME(oi)); + zlog_debug("%s: DR/BDR sending upd to int %s (%s)", __func__, + IF_NAME(oi), ospf_get_name(oi->ospf)); /* RFC2328 Section 13.3 On non-broadcast networks, separate Link State Update diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 5a48eebe49..6bde5467b2 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -2248,10 +2248,9 @@ void ospf_external_lsa_refresh_type(struct ospf *ospf, uint8_t type, lsa, EXTNL_LSA_AGGR)) zlog_debug( - "%s: Send Aggreate LSA (%pFX/%d)", + "%s: Send Aggreate LSA (%pFX)", __func__, - &aggr->p.prefix, - aggr->p.prefixlen); + &aggr->p); ospf_originate_summary_lsa( ospf, aggr, ei); diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index e7c076c7ca..714d6e8e1d 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -795,15 +795,26 @@ static void igmp_show_interfaces_single(struct pim_instance *pim, } } -static void igmp_show_interface_join(struct pim_instance *pim, struct vty *vty) +static void igmp_show_interface_join(struct pim_instance *pim, struct vty *vty, + bool uj) { struct interface *ifp; time_t now; + json_object *json = NULL; + json_object *json_iface = NULL; + json_object *json_grp = NULL; + json_object *json_grp_arr = NULL; now = pim_time_monotonic_sec(); - vty_out(vty, - "Interface Address Source Group Socket Uptime \n"); + if (uj) { + json = json_object_new_object(); + json_object_string_add(json, "vrf", + vrf_id_to_name(pim->vrf_id)); + } else { + vty_out(vty, + "Interface Address Source Group Socket Uptime \n"); + } FOR_ALL_INTERFACES (pim->vrf, ifp) { struct pim_interface *pim_ifp; @@ -837,12 +848,49 @@ static void igmp_show_interface_join(struct pim_instance *pim, struct vty *vty) pim_inet4_dump("<src?>", ij->source_addr, source_str, sizeof(source_str)); - vty_out(vty, "%-16s %-15s %-15s %-15s %6d %8s\n", - ifp->name, pri_addr_str, source_str, group_str, - ij->sock_fd, uptime); + if (uj) { + json_object_object_get_ex(json, ifp->name, + &json_iface); + + if (!json_iface) { + json_iface = json_object_new_object(); + json_object_string_add( + json_iface, "name", ifp->name); + json_object_object_add(json, ifp->name, + json_iface); + json_grp_arr = json_object_new_array(); + json_object_object_add(json_iface, + "groups", + json_grp_arr); + } + + json_grp = json_object_new_object(); + json_object_string_add(json_grp, "source", + source_str); + json_object_string_add(json_grp, "group", + group_str); + json_object_string_add(json_grp, "primaryAddr", + pri_addr_str); + json_object_int_add(json_grp, "sockFd", + ij->sock_fd); + json_object_string_add(json_grp, "upTime", + uptime); + json_object_array_add(json_grp_arr, json_grp); + } else { + vty_out(vty, + "%-16s %-15s %-15s %-15s %6d %8s\n", + ifp->name, pri_addr_str, source_str, + group_str, ij->sock_fd, uptime); + } } /* for (pim_ifp->igmp_join_list) */ } /* for (iflist) */ + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } static void pim_show_interfaces_single(struct pim_instance *pim, @@ -4217,32 +4265,35 @@ DEFUN (show_ip_igmp_interface_vrf_all, DEFUN (show_ip_igmp_join, show_ip_igmp_join_cmd, - "show ip igmp [vrf NAME] join", + "show ip igmp [vrf NAME] join [json]", SHOW_STR IP_STR IGMP_STR VRF_CMD_HELP_STR - "IGMP static join information\n") + "IGMP static join information\n" + JSON_STR) { int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + bool uj = use_json(argc, argv); if (!vrf) return CMD_WARNING; - igmp_show_interface_join(vrf->info, vty); + igmp_show_interface_join(vrf->info, vty, uj); return CMD_SUCCESS; } DEFUN (show_ip_igmp_join_vrf_all, show_ip_igmp_join_vrf_all_cmd, - "show ip igmp vrf all join", + "show ip igmp vrf all join [json]", SHOW_STR IP_STR IGMP_STR VRF_CMD_HELP_STR - "IGMP static join information\n") + "IGMP static join information\n" + JSON_STR) { bool uj = use_json(argc, argv); struct vrf *vrf; @@ -4258,7 +4309,7 @@ DEFUN (show_ip_igmp_join_vrf_all, first = false; } else vty_out(vty, "VRF: %s\n", vrf->name); - igmp_show_interface_join(vrf->info, vty); + igmp_show_interface_join(vrf->info, vty, uj); } if (uj) vty_out(vty, "}\n"); diff --git a/staticd/static_nb_config.c b/staticd/static_nb_config.c index bf669957bf..3f1d0aa496 100644 --- a/staticd/static_nb_config.c +++ b/staticd/static_nb_config.c @@ -140,7 +140,7 @@ static bool static_nexthop_create(struct nb_cb_create_args *args, 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)) + if (!static_add_nexthop_validate(nh_vrf, nh_type, &ipaddr)) flog_warn( EC_LIB_NB_CB_CONFIG_VALIDATE, "Warning!! Local connected address is configured as Gateway IP((%s))", @@ -148,18 +148,6 @@ static bool static_nexthop_create(struct nb_cb_create_args *args, "./gateway")); nh = static_add_nexthop(rn, pn, info->safi, info->svrf, nh_type, &ipaddr, ifname, nh_vrf, 0); - 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; } diff --git a/staticd/static_routes.c b/staticd/static_routes.c index 1c436a66b0..9f7e19660d 100644 --- a/staticd/static_routes.c +++ b/staticd/static_routes.c @@ -138,20 +138,26 @@ void static_del_route(struct route_node *rn, safi_t safi, vrf_reset_user_cfged(svrf->vrf); } -bool static_add_nexthop_validate(struct static_vrf *svrf, static_types type, +bool static_add_nexthop_validate(const char *nh_vrf_name, static_types type, struct ipaddr *ipaddr) { + struct vrf *vrf; + + vrf = vrf_lookup_by_name(nh_vrf_name); + if (!vrf) + return true; + 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)) + 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)) + vrf->vrf_id)) return false; break; default: @@ -214,10 +220,7 @@ static_add_nexthop(struct route_node *rn, struct static_path *pn, safi_t safi, route_lock_node(rn); - nh_svrf = static_vty_get_unknown_vrf(nh_vrf); - - if (!nh_svrf) - return NULL; + nh_svrf = static_vrf_lookup_by_name(nh_vrf); /* Make new static route structure. */ nh = XCALLOC(MTYPE_STATIC_NEXTHOP, sizeof(struct static_nexthop)); @@ -225,8 +228,8 @@ static_add_nexthop(struct route_node *rn, struct static_path *pn, safi_t safi, nh->type = type; nh->color = color; - nh->nh_vrf_id = nh_svrf->vrf->vrf_id; - strlcpy(nh->nh_vrfname, nh_svrf->vrf->name, sizeof(nh->nh_vrfname)); + nh->nh_vrf_id = nh_svrf ? nh_svrf->vrf->vrf_id : VRF_UNKNOWN; + strlcpy(nh->nh_vrfname, nh_vrf, sizeof(nh->nh_vrfname)); if (ifname) strlcpy(nh->ifname, ifname, sizeof(nh->ifname)); @@ -261,7 +264,7 @@ static_add_nexthop(struct route_node *rn, struct static_path *pn, safi_t safi, } static_nexthop_list_add_after(&(pn->nexthop_list), cp, nh); - if (nh_svrf->vrf->vrf_id == VRF_UNKNOWN) { + if (nh->nh_vrf_id == VRF_UNKNOWN) { zlog_warn( "Static Route to %pFX not installed currently because dependent config not fully available", &rn->p); @@ -275,7 +278,7 @@ static_add_nexthop(struct route_node *rn, struct static_path *pn, safi_t safi, 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->nh_vrf_id); if (ifp && ifp->ifindex != IFINDEX_INTERNAL) nh->ifindex = ifp->ifindex; else @@ -288,7 +291,7 @@ static_add_nexthop(struct route_node *rn, struct static_path *pn, safi_t safi, nh->bh_type = STATIC_BLACKHOLE_NULL; break; case STATIC_IFNAME: - ifp = if_lookup_by_name(ifname, nh_svrf->vrf->vrf_id); + ifp = if_lookup_by_name(ifname, nh->nh_vrf_id); if (ifp && ifp->ifindex != IFINDEX_INTERNAL) { nh->ifindex = ifp->ifindex; } else @@ -306,28 +309,15 @@ void static_install_nexthop(struct route_node *rn, struct static_path *pn, struct static_vrf *svrf, const char *ifname, static_types type, const char *nh_vrf) { - struct static_vrf *nh_svrf; struct interface *ifp; - nh_svrf = static_vty_get_unknown_vrf(nh_vrf); - - if (!nh_svrf) { - char nexthop_str[NEXTHOP_STR]; - - static_get_nh_str(nh, nexthop_str, sizeof(nexthop_str)); - DEBUGD(&static_dbg_route, - "Static Route %pFX not installed for %s vrf %s not ready", - &rn->p, nexthop_str, nh_vrf); - return; - } - - if (nh_svrf->vrf->vrf_id == VRF_UNKNOWN) { + if (nh->nh_vrf_id == VRF_UNKNOWN) { char nexthop_str[NEXTHOP_STR]; static_get_nh_str(nh, nexthop_str, sizeof(nexthop_str)); DEBUGD(&static_dbg_route, "Static Route %pFX not installed for %s vrf %s is unknown", - &rn->p, nexthop_str, nh_vrf); + &rn->p, nexthop_str, nh->nh_vrfname); return; } @@ -347,7 +337,7 @@ void static_install_nexthop(struct route_node *rn, struct static_path *pn, static_install_path(rn, pn, safi, svrf); break; case STATIC_IFNAME: - ifp = if_lookup_by_name(ifname, nh_svrf->vrf->vrf_id); + ifp = if_lookup_by_name(ifname, nh->nh_vrf_id); if (ifp && ifp->ifindex != IFINDEX_INTERNAL) static_install_path(rn, pn, safi, svrf); @@ -359,13 +349,9 @@ 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; - - 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) + if (nh->nh_vrf_id == VRF_UNKNOWN) goto EXIT; static_zebra_nht_register(rn, nh, false); @@ -523,6 +509,8 @@ static void static_enable_vrf(struct static_vrf *svrf, else continue; } + if (nh->nh_vrf_id == VRF_UNKNOWN) + continue; static_install_path(rn, pn, safi, svrf); } } diff --git a/staticd/static_routes.h b/staticd/static_routes.h index 470afb605d..0fbf0674d7 100644 --- a/staticd/static_routes.h +++ b/staticd/static_routes.h @@ -192,7 +192,7 @@ 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, +extern bool static_add_nexthop_validate(const char *nh_vrf_name, static_types type, struct ipaddr *ipaddr); extern struct stable_info *static_get_stable_info(struct route_node *rn); diff --git a/staticd/static_vrf.c b/staticd/static_vrf.c index 83894e9267..2133093bb3 100644 --- a/staticd/static_vrf.c +++ b/staticd/static_vrf.c @@ -261,25 +261,3 @@ 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 12ad1b255a..81296f2864 100644 --- a/staticd/static_vrf.h +++ b/staticd/static_vrf.h @@ -45,5 +45,4 @@ 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/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py index 3f360ef40a..ce35bdc0fe 100644 --- a/tests/topotests/lib/common_config.py +++ b/tests/topotests/lib/common_config.py @@ -677,7 +677,10 @@ def generate_support_bundle(): for rname, rnode in router_list.items(): logger.info("Generating support bundle for {}".format(rname)) rnode.run("mkdir -p /var/log/frr") - bundle_log = rnode.run("python2 /usr/lib/frr/generate_support_bundle.py") + + # Support only python3 going forward + bundle_log = rnode.run("env python3 /usr/lib/frr/generate_support_bundle.py") + logger.info(bundle_log) dst_bundle = "{}/{}/support_bundles/{}".format(TMPDIR, rname, test_name) @@ -4116,6 +4119,9 @@ def required_linux_kernel_version(required_version): 'These tests will not run on kernel "{}", ' "they require kernel >= {})".format(system_kernel, required_version) ) + + logger.info(error_msg) + return error_msg return True diff --git a/tools/frr-reload.py b/tools/frr-reload.py index dca877dbfe..b98c001e7d 100755 --- a/tools/frr-reload.py +++ b/tools/frr-reload.py @@ -629,6 +629,16 @@ end ctx_keys = [] current_context_lines = [] + elif line == "exit" and ctx_keys[0].startswith("rpki"): + self.save_contexts(ctx_keys, current_context_lines) + log.debug("LINE %-50s: exiting old context, %-50s", line, ctx_keys) + + # Start a new context + new_ctx = True + main_ctx_key = [] + ctx_keys = [] + current_context_lines = [] + elif line == "exit-vrf": self.save_contexts(ctx_keys, current_context_lines) current_context_lines.append(line) diff --git a/tools/generate_support_bundle.py b/tools/generate_support_bundle.py index ae258bddfe..38fdbd46df 100755 --- a/tools/generate_support_bundle.py +++ b/tools/generate_support_bundle.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 ######################################################## ### Python Script to generate the FRR support bundle ### @@ -7,7 +7,6 @@ import os import subprocess import datetime -TOOLS_DIR = "tools/" ETC_DIR = "/etc/frr/" LOG_DIR = "/var/log/frr/" SUCCESS = 1 @@ -15,16 +14,6 @@ FAIL = 0 inputFile = ETC_DIR + "support_bundle_commands.conf" -# Open support bundle configuration file -def openConfFile(i_file): - try: - with open(i_file) as supportBundleConfFile: - lines = filter(None, (line.rstrip() for line in supportBundleConfFile)) - return lines - except IOError: - return [] - - # Create the output file name def createOutputFile(procName): fileName = procName + "_support_bundle.log" @@ -50,9 +39,9 @@ def openOutputFile(fileName): # Close the output file for this process -def closeOutputFile(file): +def closeOutputFile(f): try: - file.close() + f.close() return SUCCESS except IOError: return FAIL @@ -67,13 +56,13 @@ def executeCommand(cmd, outputFile): try: dateTime = datetime.datetime.now() outputFile.write(">>[" + str(dateTime) + "]" + cmd + "\n") - outputFile.write(cmd_output) + outputFile.write(str(cmd_output)) outputFile.write( "########################################################\n" ) outputFile.write("\n") - except: - print("Writing to ouptut file Failed") + except Exception as e: + print("Writing to output file Failed: ", e) except subprocess.CalledProcessError as e: dateTime = datetime.datetime.now() outputFile.write(">>[" + str(dateTime) + "]" + cmd + "\n") @@ -85,10 +74,23 @@ def executeCommand(cmd, outputFile): # Process the support bundle configuration file # and call appropriate functions -def processConfFile(lines): +def processConfFile(): + + lines = list() + outputFile = None + + try: + with open(inputFile, "r") as supportBundleConfFile: + for l in supportBundleConfFile: + lines.append(l.rstrip()) + except IOError: + print("conf file {} not present".format(inputFile)) + return + for line in lines: - if line[0][0] == "#": + if len(line) == 0 or line[0] == "#": continue + cmd_line = line.split(":") if cmd_line[0] == "PROC_NAME": outputFileName = createOutputFile(cmd_line[1]) @@ -112,8 +114,4 @@ def processConfFile(lines): # Main Function -lines = openConfFile(inputFile) -if not lines: - print("File support_bundle_commands.conf not present in /etc/frr/ directory") -else: - processConfFile(lines) +processConfFile() diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 1cae0b1f9b..602805be3c 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -288,8 +288,8 @@ static inline int proto2zebra(int proto, int family, bool is_nexthop) proto = ZEBRA_ROUTE_BGP; break; case RTPROT_OSPF: - proto = (family == AFI_IP) ? ZEBRA_ROUTE_OSPF - : ZEBRA_ROUTE_OSPF6; + proto = (family == AF_INET) ? ZEBRA_ROUTE_OSPF + : ZEBRA_ROUTE_OSPF6; break; case RTPROT_ISIS: proto = ZEBRA_ROUTE_ISIS; |
