summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.git-blame-ignore-revs1
-rw-r--r--bgpd/bgp_bmp.c19
-rw-r--r--bgpd/bgp_fsm.c6
-rw-r--r--bgpd/bgp_nexthop.c12
-rw-r--r--bgpd/bgp_nexthop.h3
-rw-r--r--bgpd/bgp_nht.c142
-rw-r--r--bgpd/bgp_nht.h4
-rw-r--r--bgpd/bgp_trace.h106
-rw-r--r--bgpd/bgp_zebra.c4
-rw-r--r--bgpd/bgpd.h2
-rw-r--r--lib/clippy.c4
-rw-r--r--lib/defun_lex.l4
-rw-r--r--lib/northbound_cli.c12
-rw-r--r--lib/thread.c48
-rw-r--r--ospf6d/ospf6_intra.c7
-rw-r--r--staticd/static_nb_config.c14
-rw-r--r--staticd/static_routes.c54
-rw-r--r--staticd/static_routes.h2
-rw-r--r--staticd/static_vrf.c22
-rw-r--r--staticd/static_vrf.h1
-rw-r--r--tests/topotests/lib/common_config.py3
-rwxr-xr-xtools/frr-reload.py10
-rw-r--r--zebra/rt_netlink.c4
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;