summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.git-blame-ignore-revs1
-rw-r--r--bfdd/dplane.c4
-rw-r--r--bgpd/bgp_bmp.c19
-rw-r--r--bgpd/bgp_dump.c42
-rw-r--r--bgpd/bgp_dump.h28
-rw-r--r--bgpd/bgp_fsm.c6
-rw-r--r--bgpd/bgp_mplsvpn_snmp.c15
-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_route.c269
-rw-r--r--bgpd/bgp_trace.h106
-rw-r--r--bgpd/bgp_zebra.c11
-rw-r--r--bgpd/bgpd.h2
-rwxr-xr-xconfigure.ac13
-rw-r--r--doc/user/pim.rst7
-rw-r--r--lib/clippy.c4
-rw-r--r--lib/defun_lex.l4
-rw-r--r--lib/libfrr.c23
-rw-r--r--lib/libfrr.h3
-rw-r--r--lib/link_state.c7
-rw-r--r--lib/northbound_cli.c12
-rw-r--r--lib/privs.c6
-rw-r--r--lib/privs.h2
-rw-r--r--lib/smux.h1
-rw-r--r--lib/snmp.c11
-rw-r--r--lib/thread.c48
-rw-r--r--lib/vty.c104
-rw-r--r--ospf6d/ospf6_interface.c7
-rw-r--r--ospf6d/ospf6_intra.c7
-rw-r--r--ospf6d/ospf6_message.c75
-rw-r--r--ospfd/ospf_flood.c53
-rw-r--r--ospfd/ospf_lsa.c5
-rw-r--r--pimd/pim_cmd.c75
-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.py8
-rwxr-xr-xtools/frr-reload.py10
-rwxr-xr-xtools/generate_support_bundle.py46
-rw-r--r--zebra/rt_netlink.c4
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)
diff --git a/lib/vty.c b/lib/vty.c
index 4062b183e7..65f8d78a96 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -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;