diff options
| -rw-r--r-- | .git-blame-ignore-revs | 1 | ||||
| -rw-r--r-- | bgpd/bgp_bmp.c | 19 | ||||
| -rw-r--r-- | bgpd/bgp_fsm.c | 6 | ||||
| -rw-r--r-- | bgpd/bgp_nexthop.c | 12 | ||||
| -rw-r--r-- | bgpd/bgp_nexthop.h | 3 | ||||
| -rw-r--r-- | bgpd/bgp_nht.c | 142 | ||||
| -rw-r--r-- | bgpd/bgp_nht.h | 4 | ||||
| -rw-r--r-- | bgpd/bgp_trace.h | 106 | ||||
| -rw-r--r-- | bgpd/bgp_zebra.c | 4 | ||||
| -rw-r--r-- | bgpd/bgpd.h | 2 | ||||
| -rw-r--r-- | lib/clippy.c | 4 | ||||
| -rw-r--r-- | lib/defun_lex.l | 4 | ||||
| -rw-r--r-- | lib/northbound_cli.c | 12 | ||||
| -rw-r--r-- | lib/thread.c | 48 | ||||
| -rw-r--r-- | ospf6d/ospf6_intra.c | 7 | ||||
| -rw-r--r-- | staticd/static_nb_config.c | 14 | ||||
| -rw-r--r-- | staticd/static_routes.c | 54 | ||||
| -rw-r--r-- | staticd/static_routes.h | 2 | ||||
| -rw-r--r-- | staticd/static_vrf.c | 22 | ||||
| -rw-r--r-- | staticd/static_vrf.h | 1 | ||||
| -rw-r--r-- | tests/topotests/lib/common_config.py | 3 | ||||
| -rwxr-xr-x | tools/frr-reload.py | 10 | ||||
| -rw-r--r-- | zebra/rt_netlink.c | 4 |
23 files changed, 375 insertions, 109 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/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_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_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_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 8d03079fd7..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; } 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/lib/clippy.c b/lib/clippy.c index 15cd9d7a4b..c655619b71 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])); + char *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/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/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) 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/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 a1ef2f5f28..ce35bdc0fe 100644 --- a/tests/topotests/lib/common_config.py +++ b/tests/topotests/lib/common_config.py @@ -4119,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/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; |
