summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfdd/bfd.c18
-rw-r--r--bfdd/bfd.h8
-rw-r--r--bfdd/bfd_packet.c415
-rw-r--r--bfdd/bfdd_cli.c11
-rw-r--r--pimd/pim6_cmd.c8
-rw-r--r--pimd/pim_cmd.c10
-rw-r--r--pimd/pim_igmp.c4
-rw-r--r--pimd/pim_instance.h2
-rw-r--r--pimd/pim_oil.h3
-rw-r--r--pimd/pim_vty.c11
-rw-r--r--tests/topotests/bfd_vrf_topo1/r1/bfdd.conf4
-rw-r--r--tests/topotests/bfd_vrf_topo1/r1/peers.json2
-rw-r--r--tests/topotests/bfd_vrf_topo1/r2/bfdd.conf8
-rw-r--r--tests/topotests/bfd_vrf_topo1/r2/peers.json2
-rw-r--r--tests/topotests/bfd_vrf_topo1/r3/bfdd.conf4
-rw-r--r--tests/topotests/bgp_conditional_advertisement/test_bgp_conditional_advertisement.py679
-rw-r--r--zebra/kernel_netlink.c50
-rw-r--r--zebra/kernel_socket.c11
-rw-r--r--zebra/main.c5
-rw-r--r--zebra/rt_netlink.c29
-rw-r--r--zebra/zebra_rib.c63
-rw-r--r--zebra/zebra_router.c2
-rw-r--r--zebra/zebra_router.h3
-rw-r--r--zebra/zebra_vty.c10
24 files changed, 1084 insertions, 278 deletions
diff --git a/bfdd/bfd.c b/bfdd/bfd.c
index d52eeeddba..483beb1b17 100644
--- a/bfdd/bfd.c
+++ b/bfdd/bfd.c
@@ -454,7 +454,17 @@ void ptm_bfd_start_xmt_timer(struct bfd_session *bfd, bool is_echo)
static void ptm_bfd_echo_xmt_TO(struct bfd_session *bfd)
{
/* Send the scheduled echo packet */
- ptm_bfd_echo_snd(bfd);
+ /* if ipv4 use the new echo implementation that causes
+ * the packet to be looped in forwarding plane of peer
+ */
+ if (CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_IPV6) == 0)
+#ifdef BFD_LINUX
+ ptm_bfd_echo_fp_snd(bfd);
+#else
+ ptm_bfd_echo_snd(bfd);
+#endif
+ else
+ ptm_bfd_echo_snd(bfd);
/* Restart the timer for next time */
ptm_bfd_start_xmt_timer(bfd, true);
@@ -558,6 +568,12 @@ void ptm_bfd_sess_dn(struct bfd_session *bfd, uint8_t diag)
state_list[bfd->ses_state].str,
get_diag_str(bfd->local_diag));
}
+
+ /* clear peer's mac address */
+ UNSET_FLAG(bfd->flags, BFD_SESS_FLAG_MAC_SET);
+ memset(bfd->peer_hw_addr, 0, sizeof(bfd->peer_hw_addr));
+ /* reset local address ,it might has been be changed after bfd is up*/
+ memset(&bfd->local_address, 0, sizeof(bfd->local_address));
}
static struct bfd_session *bfd_find_disc(struct sockaddr_any *sa,
diff --git a/bfdd/bfd.h b/bfdd/bfd.h
index 6aa9e00586..48a1e0bc31 100644
--- a/bfdd/bfd.h
+++ b/bfdd/bfd.h
@@ -168,9 +168,10 @@ enum bfd_session_flags {
* expires
*/
BFD_SESS_FLAG_SHUTDOWN = 1 << 7, /* disable BGP peer function */
- BFD_SESS_FLAG_CONFIG = 1 << 8, /* Session configured with bfd NB API */
- BFD_SESS_FLAG_CBIT = 1 << 9, /* CBIT is set */
+ BFD_SESS_FLAG_CONFIG = 1 << 8, /* Session configured with bfd NB API */
+ BFD_SESS_FLAG_CBIT = 1 << 9, /* CBIT is set */
BFD_SESS_FLAG_PASSIVE = 1 << 10, /* Passive mode */
+ BFD_SESS_FLAG_MAC_SET = 1 << 11, /* MAC of peer known */
};
/*
@@ -290,6 +291,8 @@ struct bfd_session {
struct peer_label *pl;
struct bfd_dplane_ctx *bdc;
+ struct sockaddr_any local_address;
+ uint8_t peer_hw_addr[ETH_ALEN];
struct interface *ifp;
struct vrf *vrf;
@@ -554,6 +557,7 @@ int bp_echov6_socket(const struct vrf *vrf);
void ptm_bfd_snd(struct bfd_session *bfd, int fbit);
void ptm_bfd_echo_snd(struct bfd_session *bfd);
+void ptm_bfd_echo_fp_snd(struct bfd_session *bfd);
void bfd_recv_cb(struct thread *t);
diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c
index c717a333a6..6b0afef65f 100644
--- a/bfdd/bfd_packet.c
+++ b/bfdd/bfd_packet.c
@@ -34,6 +34,8 @@
#include <netinet/udp.h>
#include "lib/sockopt.h"
+#include "lib/checksum.h"
+#include "lib/network.h"
#include "bfd.h"
@@ -55,6 +57,18 @@ int bp_udp_send(int sd, uint8_t ttl, uint8_t *data, size_t datalen,
struct sockaddr *to, socklen_t tolen);
int bp_bfd_echo_in(struct bfd_vrf_global *bvrf, int sd,
uint8_t *ttl, uint32_t *my_discr);
+#ifdef BFD_LINUX
+ssize_t bfd_recv_ipv4_fp(int sd, uint8_t *msgbuf, size_t msgbuflen,
+ uint8_t *ttl, ifindex_t *ifindex,
+ struct sockaddr_any *local, struct sockaddr_any *peer);
+void bfd_peer_mac_set(int sd, struct bfd_session *bfd,
+ struct sockaddr_any *peer, struct interface *ifp);
+int bp_udp_send_fp(int sd, uint8_t *data, size_t datalen,
+ struct bfd_session *bfd);
+ssize_t bfd_recv_fp_echo(int sd, uint8_t *msgbuf, size_t msgbuflen,
+ uint8_t *ttl, ifindex_t *ifindex,
+ struct sockaddr_any *local, struct sockaddr_any *peer);
+#endif
/* socket related prototypes */
static void bp_set_ipopts(int sd);
@@ -126,6 +140,142 @@ int _ptm_bfd_send(struct bfd_session *bs, uint16_t *port, const void *data,
return 0;
}
+#ifdef BFD_LINUX
+/*
+ * Compute the UDP checksum.
+ *
+ * Checksum is not set in the packet, just computed.
+ *
+ * pkt
+ * Packet, fully filled out except for checksum field.
+ *
+ * pktsize
+ * sizeof(*pkt)
+ *
+ * ip
+ * IP address that pkt will be transmitted from and too.
+ *
+ * Returns:
+ * Checksum in network byte order.
+ */
+static uint16_t bfd_pkt_checksum(struct udphdr *pkt, size_t pktsize,
+ struct in6_addr *ip, sa_family_t family)
+{
+ uint16_t chksum;
+
+ pkt->check = 0;
+
+ if (family == AF_INET6) {
+ struct ipv6_ph ph = {};
+
+ memcpy(&ph.src, ip, sizeof(ph.src));
+ memcpy(&ph.dst, ip, sizeof(ph.dst));
+ ph.ulpl = htons(pktsize);
+ ph.next_hdr = IPPROTO_UDP;
+ chksum = in_cksum_with_ph6(&ph, pkt, pktsize);
+ } else {
+ struct ipv4_ph ph = {};
+
+ memcpy(&ph.src, ip, sizeof(ph.src));
+ memcpy(&ph.dst, ip, sizeof(ph.dst));
+ ph.proto = IPPROTO_UDP;
+ ph.len = htons(pktsize);
+ chksum = in_cksum_with_ph4(&ph, pkt, pktsize);
+ }
+
+ return chksum;
+}
+
+/*
+ * This routine creates the entire ECHO packet so that it will be looped
+ * in the forwarding plane of the peer router instead of going up the
+ * stack in BFD to be looped. If we haven't learned the peers MAC yet
+ * no echo is sent.
+ *
+ * echo packet with src/dst IP equal to local IP
+ * dest MAC as peer's MAC
+ *
+ * currently support ipv4
+ */
+void ptm_bfd_echo_fp_snd(struct bfd_session *bfd)
+{
+ int sd;
+ struct bfd_vrf_global *bvrf = bfd_vrf_look_by_session(bfd);
+ int total_len = 0;
+ struct ethhdr *eth;
+ struct udphdr *uh;
+ struct iphdr *iph;
+ struct bfd_echo_pkt *beph;
+ static char sendbuff[100];
+
+ if (!bvrf)
+ return;
+ if (!CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_MAC_SET))
+ return;
+ if (!CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE))
+ SET_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE);
+
+ memset(sendbuff, 0, sizeof(sendbuff));
+
+ /* add eth hdr */
+ eth = (struct ethhdr *)(sendbuff);
+ memcpy(eth->h_source, bfd->ifp->hw_addr, sizeof(bfd->ifp->hw_addr));
+ memcpy(eth->h_dest, bfd->peer_hw_addr, sizeof(bfd->peer_hw_addr));
+
+ total_len += sizeof(struct ethhdr);
+
+ sd = bvrf->bg_echo;
+ eth->h_proto = htons(ETH_P_IP);
+
+ /* add ip hdr */
+ iph = (struct iphdr *)(sendbuff + sizeof(struct ethhdr));
+
+ iph->ihl = sizeof(struct ip) >> 2;
+ iph->version = IPVERSION;
+ iph->tos = IPTOS_PREC_INTERNETCONTROL;
+ iph->id = (uint16_t)frr_weak_random();
+ iph->ttl = BFD_TTL_VAL;
+ iph->protocol = IPPROTO_UDP;
+ memcpy(&iph->saddr, &bfd->local_address.sa_sin.sin_addr,
+ sizeof(bfd->local_address.sa_sin.sin_addr));
+ memcpy(&iph->daddr, &bfd->local_address.sa_sin.sin_addr,
+ sizeof(bfd->local_address.sa_sin.sin_addr));
+ total_len += sizeof(struct iphdr);
+
+ /* add udp hdr */
+ uh = (struct udphdr *)(sendbuff + sizeof(struct iphdr) +
+ sizeof(struct ethhdr));
+ uh->source = htons(BFD_DEF_ECHO_PORT);
+ uh->dest = htons(BFD_DEF_ECHO_PORT);
+
+ total_len += sizeof(struct udphdr);
+
+ /* add bfd echo */
+ beph = (struct bfd_echo_pkt *)(sendbuff + sizeof(struct udphdr) +
+ sizeof(struct iphdr) +
+ sizeof(struct ethhdr));
+
+ beph->ver = BFD_ECHO_VERSION;
+ beph->len = BFD_ECHO_PKT_LEN;
+ beph->my_discr = htonl(bfd->discrs.my_discr);
+
+ total_len += sizeof(struct bfd_echo_pkt);
+ uh->len =
+ htons(total_len - sizeof(struct iphdr) - sizeof(struct ethhdr));
+ uh->check = bfd_pkt_checksum(
+ uh, (total_len - sizeof(struct iphdr) - sizeof(struct ethhdr)),
+ (struct in6_addr *)&iph->saddr, AF_INET);
+
+ iph->tot_len = htons(total_len - sizeof(struct ethhdr));
+ iph->check = in_cksum((const void *)iph, sizeof(struct iphdr));
+
+ if (bp_udp_send_fp(sd, (uint8_t *)&sendbuff, total_len, bfd) == -1)
+ return;
+
+ bfd->stats.tx_echo_pkt++;
+}
+#endif
+
void ptm_bfd_echo_snd(struct bfd_session *bfd)
{
struct sockaddr *sa;
@@ -275,6 +425,94 @@ void ptm_bfd_snd(struct bfd_session *bfd, int fbit)
bfd->stats.tx_ctrl_pkt++;
}
+#ifdef BFD_LINUX
+/*
+ * receive the ipv4 echo packet that was loopback in the peers forwarding plane
+ */
+ssize_t bfd_recv_ipv4_fp(int sd, uint8_t *msgbuf, size_t msgbuflen,
+ uint8_t *ttl, ifindex_t *ifindex,
+ struct sockaddr_any *local, struct sockaddr_any *peer)
+{
+ ssize_t mlen;
+ struct sockaddr_ll msgaddr;
+ struct msghdr msghdr;
+ struct iovec iov[1];
+ uint16_t recv_checksum;
+ uint16_t checksum;
+ struct iphdr *ip;
+ struct udphdr *uh;
+
+ /* Prepare the recvmsg params. */
+ iov[0].iov_base = msgbuf;
+ iov[0].iov_len = msgbuflen;
+
+ memset(&msghdr, 0, sizeof(msghdr));
+ msghdr.msg_name = &msgaddr;
+ msghdr.msg_namelen = sizeof(msgaddr);
+ msghdr.msg_iov = iov;
+ msghdr.msg_iovlen = 1;
+
+ mlen = recvmsg(sd, &msghdr, MSG_DONTWAIT);
+ if (mlen == -1) {
+ if (errno != EAGAIN || errno != EWOULDBLOCK || errno != EINTR)
+ zlog_err("%s: recv failed: %s", __func__,
+ strerror(errno));
+
+ return -1;
+ }
+
+ ip = (struct iphdr *)(msgbuf + sizeof(struct ethhdr));
+
+ /* verify ip checksum */
+ recv_checksum = ip->check;
+ ip->check = 0;
+ checksum = in_cksum((const void *)ip, sizeof(struct iphdr));
+ if (recv_checksum != checksum) {
+ if (bglobal.debug_network)
+ zlog_debug(
+ "%s: invalid iphdr checksum expected 0x%x rcvd 0x%x",
+ __func__, checksum, recv_checksum);
+ return -1;
+ }
+
+ *ttl = ip->ttl;
+ if (*ttl != 254) {
+ /* Echo should be looped in peer's forwarding plane, but it also
+ * comes up to BFD so silently drop it
+ */
+ if (ip->daddr == ip->saddr)
+ return -1;
+
+ if (bglobal.debug_network)
+ zlog_debug("%s: invalid TTL: %u", __func__, *ttl);
+ return -1;
+ }
+
+ local->sa_sin.sin_family = AF_INET;
+ memcpy(&local->sa_sin.sin_addr, &ip->saddr, sizeof(ip->saddr));
+ peer->sa_sin.sin_family = AF_INET;
+ memcpy(&peer->sa_sin.sin_addr, &ip->daddr, sizeof(ip->daddr));
+
+ *ifindex = msgaddr.sll_ifindex;
+
+ /* verify udp checksum */
+ uh = (struct udphdr *)(msgbuf + sizeof(struct iphdr) +
+ sizeof(struct ethhdr));
+ recv_checksum = uh->check;
+ uh->check = 0;
+ checksum = bfd_pkt_checksum(uh, ntohs(uh->len),
+ (struct in6_addr *)&ip->saddr, AF_INET);
+ if (recv_checksum != checksum) {
+ if (bglobal.debug_network)
+ zlog_debug(
+ "%s: invalid udphdr checksum expected 0x%x rcvd 0x%x",
+ __func__, checksum, recv_checksum);
+ return -1;
+ }
+ return mlen;
+}
+#endif
+
ssize_t bfd_recv_ipv4(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
ifindex_t *ifindex, struct sockaddr_any *local,
struct sockaddr_any *peer)
@@ -649,6 +887,8 @@ void bfd_recv_cb(struct thread *t)
/*
* Multi hop: validate packet TTL.
+ * Single hop: set local address that received the packet.
+ * set peers mac address for echo packets
*/
if (is_mhop) {
if (ttl < bfd->mh_ttl) {
@@ -657,6 +897,14 @@ void bfd_recv_cb(struct thread *t)
bfd->mh_ttl, ttl);
return;
}
+ } else {
+
+ if (bfd->local_address.sa_sin.sin_family == AF_UNSPEC)
+ bfd->local_address = local;
+#ifdef BFD_LINUX
+ if (ifp)
+ bfd_peer_mac_set(sd, bfd, &peer, ifp);
+#endif
}
bfd->stats.rx_ctrl_pkt++;
@@ -756,13 +1004,30 @@ int bp_bfd_echo_in(struct bfd_vrf_global *bvrf, int sd,
ifindex_t ifindex = IFINDEX_INTERNAL;
vrf_id_t vrfid = VRF_DEFAULT;
uint8_t msgbuf[1516];
+ size_t bfd_offset = 0;
+
+ if (sd == bvrf->bg_echo) {
+#ifdef BFD_LINUX
+ rlen = bfd_recv_ipv4_fp(sd, msgbuf, sizeof(msgbuf), ttl,
+ &ifindex, &local, &peer);
- if (sd == bvrf->bg_echo)
+ /* silently drop echo packet that is looped in fastpath but
+ * still comes up to BFD
+ */
+ if (rlen == -1)
+ return -1;
+ bfd_offset = sizeof(struct udphdr) + sizeof(struct iphdr) +
+ sizeof(struct ethhdr);
+#else
rlen = bfd_recv_ipv4(sd, msgbuf, sizeof(msgbuf), ttl, &ifindex,
&local, &peer);
- else
+ bfd_offset = 0;
+#endif
+ } else {
rlen = bfd_recv_ipv6(sd, msgbuf, sizeof(msgbuf), ttl, &ifindex,
&local, &peer);
+ bfd_offset = 0;
+ }
/* Short packet, better not risk reading it. */
if (rlen < (ssize_t)sizeof(*bep)) {
@@ -771,8 +1036,8 @@ int bp_bfd_echo_in(struct bfd_vrf_global *bvrf, int sd,
return -1;
}
- /* Test for loopback. */
- if (*ttl == BFD_TTL_VAL) {
+ /* Test for loopback for ipv6, ipv4 is looped in forwarding plane */
+ if ((*ttl == BFD_TTL_VAL) && (sd == bvrf->bg_echov6)) {
bp_udp_send(sd, *ttl - 1, msgbuf, rlen,
(struct sockaddr *)&peer,
(sd == bvrf->bg_echo) ? sizeof(peer.sa_sin)
@@ -781,7 +1046,7 @@ int bp_bfd_echo_in(struct bfd_vrf_global *bvrf, int sd,
}
/* Read my discriminator from BFD Echo packet. */
- bep = (struct bfd_echo_pkt *)msgbuf;
+ bep = (struct bfd_echo_pkt *)(msgbuf + bfd_offset);
*my_discr = ntohl(bep->my_discr);
if (*my_discr == 0) {
cp_debug(false, &peer, &local, ifindex, vrfid,
@@ -792,6 +1057,56 @@ int bp_bfd_echo_in(struct bfd_vrf_global *bvrf, int sd,
return 0;
}
+#ifdef BFD_LINUX
+/*
+ * send a bfd packet with src/dst same IP so that the peer will receive
+ * the packet and forward it back to sender in the forwarding plane
+ */
+int bp_udp_send_fp(int sd, uint8_t *data, size_t datalen,
+ struct bfd_session *bfd)
+{
+ ssize_t wlen;
+ struct msghdr msg;
+ struct iovec iov[1];
+ uint8_t msgctl[255];
+ struct sockaddr_ll sadr_ll;
+
+
+ sadr_ll.sll_ifindex = bfd->ifp->ifindex;
+ sadr_ll.sll_halen = ETH_ALEN;
+ memcpy(sadr_ll.sll_addr, bfd->peer_hw_addr, sizeof(bfd->peer_hw_addr));
+ sadr_ll.sll_protocol = htons(ETH_P_IP);
+
+ /* Prepare message data. */
+ iov[0].iov_base = data;
+ iov[0].iov_len = datalen;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(msgctl, 0, sizeof(msgctl));
+ msg.msg_name = &sadr_ll;
+ msg.msg_namelen = sizeof(sadr_ll);
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+
+ /* Send echo to peer */
+ wlen = sendmsg(sd, &msg, 0);
+
+ if (wlen <= 0) {
+ if (bglobal.debug_network)
+ zlog_debug("udp-send: loopback failure: (%d) %s", errno,
+ strerror(errno));
+ return -1;
+ } else if (wlen < (ssize_t)datalen) {
+ if (bglobal.debug_network)
+ zlog_debug("udp-send: partial send: %zd expected %zu",
+ wlen, datalen);
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
int bp_udp_send(int sd, uint8_t ttl, uint8_t *data, size_t datalen,
struct sockaddr *to, socklen_t tolen)
{
@@ -1219,6 +1534,57 @@ int bp_udp6_mhop(const struct vrf *vrf)
return sd;
}
+#ifdef BFD_LINUX
+/* tcpdump -dd udp dst port 3785 */
+struct sock_filter my_filterudp[] = {
+ {0x28, 0, 0, 0x0000000c}, {0x15, 0, 8, 0x00000800},
+ {0x30, 0, 0, 0x00000017}, {0x15, 0, 6, 0x00000011},
+ {0x28, 0, 0, 0x00000014}, {0x45, 4, 0, 0x00001fff},
+ {0xb1, 0, 0, 0x0000000e}, {0x48, 0, 0, 0x00000010},
+ {0x15, 0, 1, 0x00000ec9}, {0x6, 0, 0, 0x00040000},
+ {0x6, 0, 0, 0x00000000},
+};
+
+#define MY_FILTER_LENGTH 11
+
+int bp_echo_socket(const struct vrf *vrf)
+{
+ int s;
+
+ frr_with_privs (&bglobal.bfdd_privs) {
+ s = vrf_socket(AF_PACKET, SOCK_RAW, ETH_P_IP, vrf->vrf_id,
+ vrf->name);
+ }
+
+ if (s == -1)
+ zlog_fatal("echo-socket: socket: %s", strerror(errno));
+
+ struct sock_fprog pf;
+ struct sockaddr_ll sll;
+
+ /* adjust filter for socket to only receive ECHO packets */
+ pf.filter = my_filterudp;
+ pf.len = MY_FILTER_LENGTH;
+ if (setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &pf, sizeof(pf)) ==
+ -1) {
+ zlog_warn("%s: setsockopt(SO_ATTACH_FILTER): %s", __func__,
+ strerror(errno));
+ return -1;
+ }
+
+
+ sll.sll_family = AF_PACKET;
+ sll.sll_protocol = htons(ETH_P_IP);
+ sll.sll_ifindex = 0;
+ if (bind(s, (struct sockaddr *)&sll, sizeof(sll)) < 0) {
+ zlog_warn("Failed to bind echo socket: %s",
+ safe_strerror(errno));
+ return -1;
+ }
+
+ return s;
+}
+#else
int bp_echo_socket(const struct vrf *vrf)
{
int s;
@@ -1234,6 +1600,7 @@ int bp_echo_socket(const struct vrf *vrf)
return s;
}
+#endif
int bp_echov6_socket(const struct vrf *vrf)
{
@@ -1257,3 +1624,41 @@ int bp_echov6_socket(const struct vrf *vrf)
return s;
}
+
+#ifdef BFD_LINUX
+/* get peer's mac address to be used with Echo packets when they are looped in
+ * peers forwarding plane
+ */
+void bfd_peer_mac_set(int sd, struct bfd_session *bfd,
+ struct sockaddr_any *peer, struct interface *ifp)
+{
+ struct arpreq arpreq_;
+
+ if (CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_MAC_SET))
+ return;
+
+ if (peer->sa_sin.sin_family == AF_INET) {
+ /* IPV4 */
+ struct sockaddr_in *addr =
+ (struct sockaddr_in *)&arpreq_.arp_pa;
+
+ memset(&arpreq_, 0, sizeof(struct arpreq));
+ addr->sin_family = AF_INET;
+ memcpy(&addr->sin_addr.s_addr, &peer->sa_sin.sin_addr,
+ sizeof(addr->sin_addr));
+ strlcpy(arpreq_.arp_dev, ifp->name, sizeof(arpreq_.arp_dev));
+
+ if (ioctl(sd, SIOCGARP, &arpreq_) < 0) {
+ zlog_warn("BFD: getting peer's mac failed error %s",
+ strerror(errno));
+ UNSET_FLAG(bfd->flags, BFD_SESS_FLAG_MAC_SET);
+ memset(bfd->peer_hw_addr, 0, sizeof(bfd->peer_hw_addr));
+
+ } else {
+ memcpy(bfd->peer_hw_addr, arpreq_.arp_ha.sa_data,
+ sizeof(bfd->peer_hw_addr));
+ SET_FLAG(bfd->flags, BFD_SESS_FLAG_MAC_SET);
+ }
+ }
+}
+#endif
diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c
index d4e12e4f1a..69424c45d9 100644
--- a/bfdd/bfdd_cli.c
+++ b/bfdd/bfdd_cli.c
@@ -423,12 +423,19 @@ DEFPY_YANG(
"Configure echo mode\n")
{
if (!bfd_cli_is_profile(vty) && !bfd_cli_is_single_hop(vty)) {
- vty_out(vty, "%% Echo mode is only available for single hop sessions.\n");
+ vty_out(vty,
+ "%% Echo mode is only available for single hop sessions.\n");
return CMD_WARNING_CONFIG_FAILED;
}
if (!no && !bglobal.bg_use_dplane) {
- vty_out(vty, "%% Current implementation of echo mode works only when the peer is also FRR.\n");
+#ifdef BFD_LINUX
+ vty_out(vty,
+ "%% Echo mode works correctly for IPv4, but only works when the peer is also FRR for IPv6.\n");
+#else
+ vty_out(vty,
+ "%% Current implementation of echo mode works only when the peer is also FRR.\n");
+#endif /* BFD_LINUX */
}
nb_cli_enqueue_change(vty, "./echo-mode", NB_OP_MODIFY,
diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c
index 4f0758cf6a..1a2829f962 100644
--- a/pimd/pim6_cmd.c
+++ b/pimd/pim6_cmd.c
@@ -686,9 +686,7 @@ DEFPY (ipv6_mld_group_watermark,
"Group count to generate watermark warning\n")
{
PIM_DECLVAR_CONTEXT_VRF(vrf, pim);
-
- /* TBD Depends on MLD data structure changes */
- (void)pim;
+ pim->gm_watermark_limit = limit;
return CMD_SUCCESS;
}
@@ -703,9 +701,7 @@ DEFPY (no_ipv6_mld_group_watermark,
IGNORED_IN_NO_STR)
{
PIM_DECLVAR_CONTEXT_VRF(vrf, pim);
-
- /* TBD Depends on MLD data structure changes */
- (void)pim;
+ pim->gm_watermark_limit = 0;
return CMD_SUCCESS;
}
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 817ebcc256..91cc3aa79b 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -1135,12 +1135,12 @@ static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj)
json = json_object_new_object();
json_object_int_add(json, "totalGroups", pim->igmp_group_count);
json_object_int_add(json, "watermarkLimit",
- pim->igmp_watermark_limit);
+ pim->gm_watermark_limit);
} else {
vty_out(vty, "Total IGMP groups: %u\n", pim->igmp_group_count);
vty_out(vty, "Watermark warn limit(%s): %u\n",
- pim->igmp_watermark_limit ? "Set" : "Not Set",
- pim->igmp_watermark_limit);
+ pim->gm_watermark_limit ? "Set" : "Not Set",
+ pim->gm_watermark_limit);
vty_out(vty,
"Interface Group Mode Timer Srcs V Uptime \n");
}
@@ -3334,7 +3334,7 @@ DEFPY (ip_igmp_group_watermark,
"Group count to generate watermark warning\n")
{
PIM_DECLVAR_CONTEXT_VRF(vrf, pim);
- pim->igmp_watermark_limit = limit;
+ pim->gm_watermark_limit = limit;
return CMD_SUCCESS;
}
@@ -3349,7 +3349,7 @@ DEFPY (no_ip_igmp_group_watermark,
IGNORED_IN_NO_STR)
{
PIM_DECLVAR_CONTEXT_VRF(vrf, pim);
- pim->igmp_watermark_limit = 0;
+ pim->gm_watermark_limit = 0;
return CMD_SUCCESS;
}
diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c
index 849216af62..6ffeeb9657 100644
--- a/pimd/pim_igmp.c
+++ b/pimd/pim_igmp.c
@@ -1009,8 +1009,8 @@ static void igmp_group_count_incr(struct pim_interface *pim_ifp)
uint32_t group_count = listcount(pim_ifp->gm_group_list);
++pim_ifp->pim->igmp_group_count;
- if (pim_ifp->pim->igmp_group_count
- == pim_ifp->pim->igmp_watermark_limit) {
+ if (pim_ifp->pim->igmp_group_count ==
+ pim_ifp->pim->gm_watermark_limit) {
zlog_warn(
"IGMP group count reached watermark limit: %u(vrf: %s)",
pim_ifp->pim->igmp_group_count,
diff --git a/pimd/pim_instance.h b/pimd/pim_instance.h
index 23b9df4aff..684785dd13 100644
--- a/pimd/pim_instance.h
+++ b/pimd/pim_instance.h
@@ -173,7 +173,7 @@ struct pim_instance {
struct thread *t_gm_recv;
unsigned int igmp_group_count;
- unsigned int igmp_watermark_limit;
+ unsigned int gm_watermark_limit;
unsigned int keep_alive_time;
unsigned int rp_keep_alive_time;
diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h
index d0c4921d07..5a2647b93f 100644
--- a/pimd/pim_oil.h
+++ b/pimd/pim_oil.h
@@ -187,9 +187,6 @@ extern int pim_channel_oil_compare(const struct channel_oil *c1,
DECLARE_RBTREE_UNIQ(rb_pim_oil, struct channel_oil, oil_rb,
pim_channel_oil_compare);
-
-extern struct list *pim_channel_oil_list;
-
void pim_oil_init(struct pim_instance *pim);
void pim_oil_terminate(struct pim_instance *pim);
diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c
index 4dd1398733..43d9c29278 100644
--- a/pimd/pim_vty.c
+++ b/pimd/pim_vty.c
@@ -260,9 +260,14 @@ int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty)
++writes;
}
- if (pim->igmp_watermark_limit != 0) {
- vty_out(vty, "%sip igmp watermark-warn %u\n", spaces,
- pim->igmp_watermark_limit);
+ if (pim->gm_watermark_limit != 0) {
+#if PIM_IPV == 4
+ vty_out(vty, "%s" PIM_AF_NAME " igmp watermark-warn %u\n",
+ spaces, pim->gm_watermark_limit);
+#else
+ vty_out(vty, "%s" PIM_AF_NAME " mld watermark-warn %u\n",
+ spaces, pim->gm_watermark_limit);
+#endif
++writes;
}
diff --git a/tests/topotests/bfd_vrf_topo1/r1/bfdd.conf b/tests/topotests/bfd_vrf_topo1/r1/bfdd.conf
index 8fca099686..0476df740a 100644
--- a/tests/topotests/bfd_vrf_topo1/r1/bfdd.conf
+++ b/tests/topotests/bfd_vrf_topo1/r1/bfdd.conf
@@ -5,7 +5,11 @@
!
bfd
peer 192.168.0.2 vrf r1-bfd-cust1
+ receive-interval 1000
+ transmit-interval 1000
echo-mode
+ echo transmit-interval 1000
+ echo receive-interval 1000
no shutdown
!
!
diff --git a/tests/topotests/bfd_vrf_topo1/r1/peers.json b/tests/topotests/bfd_vrf_topo1/r1/peers.json
index f49768ff75..57cea71e53 100644
--- a/tests/topotests/bfd_vrf_topo1/r1/peers.json
+++ b/tests/topotests/bfd_vrf_topo1/r1/peers.json
@@ -1,7 +1,7 @@
[
{
"remote-receive-interval": 1000,
- "remote-transmit-interval": 500,
+ "remote-transmit-interval": 1000,
"peer": "192.168.0.2",
"status": "up"
}
diff --git a/tests/topotests/bfd_vrf_topo1/r2/bfdd.conf b/tests/topotests/bfd_vrf_topo1/r2/bfdd.conf
index 4490090ec6..69edd1536b 100644
--- a/tests/topotests/bfd_vrf_topo1/r2/bfdd.conf
+++ b/tests/topotests/bfd_vrf_topo1/r2/bfdd.conf
@@ -6,12 +6,18 @@
bfd
peer 192.168.0.1 vrf r2-bfd-cust1
receive-interval 1000
- transmit-interval 500
+ transmit-interval 1000
echo-mode
+ echo transmit-interval 1000
+ echo receive-interval 1000
no shutdown
!
peer 192.168.1.1 vrf r2-bfd-cust1
+ receive-interval 1000
+ transmit-interval 1000
echo-mode
+ echo transmit-interval 1000
+ echo receive-interval 1000
no shutdown
!
!
diff --git a/tests/topotests/bfd_vrf_topo1/r2/peers.json b/tests/topotests/bfd_vrf_topo1/r2/peers.json
index 267459c7a8..0a1c34224b 100644
--- a/tests/topotests/bfd_vrf_topo1/r2/peers.json
+++ b/tests/topotests/bfd_vrf_topo1/r2/peers.json
@@ -4,7 +4,7 @@
"status": "up"
},
{
- "remote-echo-receive-interval": 100,
+ "remote-echo-receive-interval": 1000,
"peer": "192.168.1.1",
"status": "up"
},
diff --git a/tests/topotests/bfd_vrf_topo1/r3/bfdd.conf b/tests/topotests/bfd_vrf_topo1/r3/bfdd.conf
index 0333320898..00162b5247 100644
--- a/tests/topotests/bfd_vrf_topo1/r3/bfdd.conf
+++ b/tests/topotests/bfd_vrf_topo1/r3/bfdd.conf
@@ -5,7 +5,9 @@
!
bfd
peer 192.168.1.2 vrf r3-bfd-cust1
- echo-interval 100
+ receive-interval 1000
+ transmit-interval 1000
+ echo-interval 1000
echo-mode
no shutdown
!
diff --git a/tests/topotests/bgp_conditional_advertisement/test_bgp_conditional_advertisement.py b/tests/topotests/bgp_conditional_advertisement/test_bgp_conditional_advertisement.py
index 6153aee418..1097be3d70 100644
--- a/tests/topotests/bgp_conditional_advertisement/test_bgp_conditional_advertisement.py
+++ b/tests/topotests/bgp_conditional_advertisement/test_bgp_conditional_advertisement.py
@@ -197,11 +197,199 @@ def teardown_module(mod):
logger.info("=" * 40)
-def test_bgp_conditional_advertisement():
- """
- Test BGP conditional advertisement functionality.
- """
+def all_routes_advertised(router):
+ output = json.loads(router.vtysh_cmd("show ip route json"))
+ expected = {
+ "0.0.0.0/0": [{"protocol": "bgp"}],
+ "192.0.2.1/32": [{"protocol": "bgp"}],
+ "192.0.2.5/32": [{"protocol": "bgp"}],
+ "10.139.224.0/20": [{"protocol": "bgp"}],
+ "203.0.113.1/32": [{"protocol": "bgp"}],
+ }
+ return topotest.json_cmp(output, expected)
+
+
+def all_routes_withdrawn(router):
+ output = json.loads(router.vtysh_cmd("show ip route json"))
+ expected = {
+ "0.0.0.0/0": None,
+ "192.0.2.1/32": None,
+ "192.0.2.5/32": None,
+ "10.139.224.0/20": None,
+ "203.0.113.1/32": None,
+ }
+ return topotest.json_cmp(output, expected)
+
+
+# BGP conditional advertisement with route-maps
+# EXIST-MAP, ADV-MAP-1 and RMAP-1
+def exist_map_routes_present(router):
+ return all_routes_advertised(router)
+
+
+def exist_map_routes_not_present(router):
+ output = json.loads(router.vtysh_cmd("show ip route json"))
+ expected = {
+ "0.0.0.0/0": None,
+ "192.0.2.1/32": None,
+ "192.0.2.5/32": [{"protocol": "bgp"}],
+ "10.139.224.0/20": None,
+ "203.0.113.1/32": [{"protocol": "bgp"}],
+ }
+ return topotest.json_cmp(output, expected)
+
+
+def non_exist_map_routes_present(router):
+ output = json.loads(router.vtysh_cmd("show ip route json"))
+ expected = {
+ "0.0.0.0/0": [{"protocol": "bgp"}],
+ "192.0.2.1/32": None,
+ "192.0.2.5/32": [{"protocol": "bgp"}],
+ "10.139.224.0/20": None,
+ "203.0.113.1/32": [{"protocol": "bgp"}],
+ }
+ return topotest.json_cmp(output, expected)
+
+
+def non_exist_map_routes_not_present(router):
+ output = json.loads(router.vtysh_cmd("show ip route json"))
+ expected = {
+ "0.0.0.0/0": None,
+ "192.0.2.1/32": [{"protocol": "bgp"}],
+ "192.0.2.5/32": [{"protocol": "bgp"}],
+ "10.139.224.0/20": [{"protocol": "bgp"}],
+ "203.0.113.1/32": [{"protocol": "bgp"}],
+ }
+ return topotest.json_cmp(output, expected)
+
+
+def exist_map_no_condition_route_map(router):
+ return non_exist_map_routes_present(router)
+
+
+def non_exist_map_no_condition_route_map(router):
+ return all_routes_advertised(router)
+
+
+def exist_map_routes_present_rmap_filter(router):
+ output = json.loads(router.vtysh_cmd("show ip route json"))
+ expected = {
+ "0.0.0.0/0": None,
+ "192.0.2.1/32": [{"protocol": "bgp"}],
+ "192.0.2.5/32": None,
+ "10.139.224.0/20": [{"protocol": "bgp"}],
+ "203.0.113.1/32": None,
+ }
+ return topotest.json_cmp(output, expected)
+
+
+def exist_map_routes_present_no_rmap_filter(router):
+ return all_routes_advertised(router)
+
+
+def non_exist_map_routes_present_rmap_filter(router):
+ return all_routes_withdrawn(router)
+
+
+def non_exist_map_routes_present_no_rmap_filter(router):
+ return non_exist_map_routes_present(router)
+
+
+def exist_map_routes_not_present_rmap_filter(router):
+ return all_routes_withdrawn(router)
+
+
+def exist_map_routes_not_present_no_rmap_filter(router):
+ return exist_map_routes_not_present(router)
+
+
+def non_exist_map_routes_not_present_rmap_filter(router):
+ return exist_map_routes_present_rmap_filter(router)
+
+
+def non_exist_map_routes_not_present_no_rmap_filter(router):
+ return non_exist_map_routes_not_present(router)
+
+
+# BGP conditional advertisement with route-maps
+# EXIST-MAP, ADV-MAP-2 and RMAP-2
+def exist_map_routes_not_present_rmap2_filter(router):
+ return all_routes_withdrawn(router)
+
+
+def exist_map_routes_not_present_no_rmap2_filter(router):
+ output = json.loads(router.vtysh_cmd("show ip route json"))
+ expected = {
+ "0.0.0.0/0": None,
+ "192.0.2.1/32": [{"protocol": "bgp"}],
+ "192.0.2.5/32": [{"protocol": "bgp"}],
+ "10.139.224.0/20": [{"protocol": "bgp"}],
+ "203.0.113.1/32": None,
+ }
+ return topotest.json_cmp(output, expected)
+
+
+def non_exist_map_routes_not_present_rmap2_filter(router):
+ output = json.loads(router.vtysh_cmd("show ip route json"))
+ expected = {
+ "0.0.0.0/0": None,
+ "192.0.2.1/32": None,
+ "192.0.2.5/32": None,
+ "10.139.224.0/20": None,
+ "203.0.113.1/32": [{"protocol": "bgp", "metric": 911}],
+ }
+ return topotest.json_cmp(output, expected)
+
+def non_exist_map_routes_not_present_no_rmap2_filter(router):
+ return non_exist_map_routes_not_present(router)
+
+
+def exist_map_routes_present_rmap2_filter(router):
+ return non_exist_map_routes_not_present_rmap2_filter(router)
+
+
+def exist_map_routes_present_no_rmap2_filter(router):
+ return all_routes_advertised(router)
+
+
+def non_exist_map_routes_present_rmap2_filter(router):
+ return all_routes_withdrawn(router)
+
+
+def non_exist_map_routes_present_no_rmap2_filter(router):
+ output = json.loads(router.vtysh_cmd("show ip route json"))
+ expected = {
+ "0.0.0.0/0": [{"protocol": "bgp"}],
+ "192.0.2.1/32": [{"protocol": "bgp"}],
+ "192.0.2.5/32": [{"protocol": "bgp"}],
+ "10.139.224.0/20": [{"protocol": "bgp"}],
+ "203.0.113.1/32": None,
+ }
+ return topotest.json_cmp(output, expected)
+
+
+def exist_map_routes_present_rmap2_network(router):
+ return non_exist_map_routes_not_present_rmap2_filter(router)
+
+
+def exist_map_routes_present_rmap2_no_network(router):
+ return all_routes_withdrawn(router)
+
+
+def non_exist_map_routes_not_present_rmap2_network(router):
+ return non_exist_map_routes_not_present_rmap2_filter(router)
+
+
+def non_exist_map_routes_not_present_rmap2_no_network(router):
+ return all_routes_withdrawn(router)
+
+
+passed = "PASSED!!!"
+failed = "FAILED!!!"
+
+
+def test_bgp_conditional_advertisement_step1():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -210,172 +398,9 @@ def test_bgp_conditional_advertisement():
router2 = tgen.gears["r2"]
router3 = tgen.gears["r3"]
- passed = "PASSED!!!"
- failed = "FAILED!!!"
-
- def _all_routes_advertised(router):
- output = json.loads(router.vtysh_cmd("show ip route json"))
- expected = {
- "0.0.0.0/0": [{"protocol": "bgp"}],
- "192.0.2.1/32": [{"protocol": "bgp"}],
- "192.0.2.5/32": [{"protocol": "bgp"}],
- "10.139.224.0/20": [{"protocol": "bgp"}],
- "203.0.113.1/32": [{"protocol": "bgp"}],
- }
- return topotest.json_cmp(output, expected)
-
- def _all_routes_withdrawn(router):
- output = json.loads(router.vtysh_cmd("show ip route json"))
- expected = {
- "0.0.0.0/0": None,
- "192.0.2.1/32": None,
- "192.0.2.5/32": None,
- "10.139.224.0/20": None,
- "203.0.113.1/32": None,
- }
- return topotest.json_cmp(output, expected)
-
- # BGP conditional advertisement with route-maps
- # EXIST-MAP, ADV-MAP-1 and RMAP-1
- def _exist_map_routes_present(router):
- return _all_routes_advertised(router)
-
- def _exist_map_routes_not_present(router):
- output = json.loads(router.vtysh_cmd("show ip route json"))
- expected = {
- "0.0.0.0/0": None,
- "192.0.2.1/32": None,
- "192.0.2.5/32": [{"protocol": "bgp"}],
- "10.139.224.0/20": None,
- "203.0.113.1/32": [{"protocol": "bgp"}],
- }
- return topotest.json_cmp(output, expected)
-
- def _non_exist_map_routes_present(router):
- output = json.loads(router.vtysh_cmd("show ip route json"))
- expected = {
- "0.0.0.0/0": [{"protocol": "bgp"}],
- "192.0.2.1/32": None,
- "192.0.2.5/32": [{"protocol": "bgp"}],
- "10.139.224.0/20": None,
- "203.0.113.1/32": [{"protocol": "bgp"}],
- }
- return topotest.json_cmp(output, expected)
-
- def _non_exist_map_routes_not_present(router):
- output = json.loads(router.vtysh_cmd("show ip route json"))
- expected = {
- "0.0.0.0/0": None,
- "192.0.2.1/32": [{"protocol": "bgp"}],
- "192.0.2.5/32": [{"protocol": "bgp"}],
- "10.139.224.0/20": [{"protocol": "bgp"}],
- "203.0.113.1/32": [{"protocol": "bgp"}],
- }
- return topotest.json_cmp(output, expected)
-
- def _exist_map_no_condition_route_map(router):
- return _non_exist_map_routes_present(router)
-
- def _non_exist_map_no_condition_route_map(router):
- return _all_routes_advertised(router)
-
- def _exist_map_routes_present_rmap_filter(router):
- output = json.loads(router.vtysh_cmd("show ip route json"))
- expected = {
- "0.0.0.0/0": None,
- "192.0.2.1/32": [{"protocol": "bgp"}],
- "192.0.2.5/32": None,
- "10.139.224.0/20": [{"protocol": "bgp"}],
- "203.0.113.1/32": None,
- }
- return topotest.json_cmp(output, expected)
-
- def _exist_map_routes_present_no_rmap_filter(router):
- return _all_routes_advertised(router)
-
- def _non_exist_map_routes_present_rmap_filter(router):
- return _all_routes_withdrawn(router)
-
- def _non_exist_map_routes_present_no_rmap_filter(router):
- return _non_exist_map_routes_present(router)
-
- def _exist_map_routes_not_present_rmap_filter(router):
- return _all_routes_withdrawn(router)
-
- def _exist_map_routes_not_present_no_rmap_filter(router):
- return _exist_map_routes_not_present(router)
-
- def _non_exist_map_routes_not_present_rmap_filter(router):
- return _exist_map_routes_present_rmap_filter(router)
-
- def _non_exist_map_routes_not_present_no_rmap_filter(router):
- return _non_exist_map_routes_not_present(router)
-
- # BGP conditional advertisement with route-maps
- # EXIST-MAP, ADV-MAP-2 and RMAP-2
- def _exist_map_routes_not_present_rmap2_filter(router):
- return _all_routes_withdrawn(router)
-
- def _exist_map_routes_not_present_no_rmap2_filter(router):
- output = json.loads(router.vtysh_cmd("show ip route json"))
- expected = {
- "0.0.0.0/0": None,
- "192.0.2.1/32": [{"protocol": "bgp"}],
- "192.0.2.5/32": [{"protocol": "bgp"}],
- "10.139.224.0/20": [{"protocol": "bgp"}],
- "203.0.113.1/32": None,
- }
- return topotest.json_cmp(output, expected)
-
- def _non_exist_map_routes_not_present_rmap2_filter(router):
- output = json.loads(router.vtysh_cmd("show ip route json"))
- expected = {
- "0.0.0.0/0": None,
- "192.0.2.1/32": None,
- "192.0.2.5/32": None,
- "10.139.224.0/20": None,
- "203.0.113.1/32": [{"protocol": "bgp", "metric": 911}],
- }
- return topotest.json_cmp(output, expected)
-
- def _non_exist_map_routes_not_present_no_rmap2_filter(router):
- return _non_exist_map_routes_not_present(router)
-
- def _exist_map_routes_present_rmap2_filter(router):
- return _non_exist_map_routes_not_present_rmap2_filter(router)
-
- def _exist_map_routes_present_no_rmap2_filter(router):
- return _all_routes_advertised(router)
-
- def _non_exist_map_routes_present_rmap2_filter(router):
- return _all_routes_withdrawn(router)
-
- def _non_exist_map_routes_present_no_rmap2_filter(router):
- output = json.loads(router.vtysh_cmd("show ip route json"))
- expected = {
- "0.0.0.0/0": [{"protocol": "bgp"}],
- "192.0.2.1/32": [{"protocol": "bgp"}],
- "192.0.2.5/32": [{"protocol": "bgp"}],
- "10.139.224.0/20": [{"protocol": "bgp"}],
- "203.0.113.1/32": None,
- }
- return topotest.json_cmp(output, expected)
-
- def _exist_map_routes_present_rmap2_network(router):
- return _non_exist_map_routes_not_present_rmap2_filter(router)
-
- def _exist_map_routes_present_rmap2_no_network(router):
- return _all_routes_withdrawn(router)
-
- def _non_exist_map_routes_not_present_rmap2_network(router):
- return _non_exist_map_routes_not_present_rmap2_filter(router)
-
- def _non_exist_map_routes_not_present_rmap2_no_network(router):
- return _all_routes_withdrawn(router)
-
# TC11: R3 BGP convergence, without advertise-map configuration.
# All routes are advertised to R3.
- test_func = functools.partial(_all_routes_advertised, router3)
+ test_func = functools.partial(all_routes_advertised, router3)
success, result = topotest.run_and_expect(test_func, None, count=130, wait=1)
msg = 'TC11: "router3" BGP convergence - '
@@ -383,6 +408,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step2():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC21: exist-map routes present in R2's BGP table.
# advertise-map routes present in R2's BGP table are advertised to R3.
router2.vtysh_cmd(
@@ -394,7 +429,7 @@ def test_bgp_conditional_advertisement():
"""
)
- test_func = functools.partial(_exist_map_routes_present, router3)
+ test_func = functools.partial(exist_map_routes_present, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = 'TC21: exist-map routes present in "router2" BGP table - '
@@ -402,6 +437,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step3():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC22: exist-map routes not present in R2's BGP table
# advertise-map routes present in R2's BGP table are withdrawn from R3.
router1.vtysh_cmd(
@@ -413,7 +458,7 @@ def test_bgp_conditional_advertisement():
"""
)
- test_func = functools.partial(_exist_map_routes_not_present, router3)
+ test_func = functools.partial(exist_map_routes_not_present, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = 'TC22: exist-map routes not present in "router2" BGP table - '
@@ -421,6 +466,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step4():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC31: non-exist-map routes not present in R2's BGP table
# advertise-map routes present in R2's BGP table are advertised to R3.
router2.vtysh_cmd(
@@ -432,7 +487,7 @@ def test_bgp_conditional_advertisement():
"""
)
- test_func = functools.partial(_non_exist_map_routes_not_present, router3)
+ test_func = functools.partial(non_exist_map_routes_not_present, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = 'TC31: non-exist-map routes not present in "router2" BGP table - '
@@ -440,6 +495,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step5():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC32: non-exist-map routes present in R2's BGP table
# advertise-map routes present in R2's BGP table are withdrawn from R3.
router1.vtysh_cmd(
@@ -451,7 +516,7 @@ def test_bgp_conditional_advertisement():
"""
)
- test_func = functools.partial(_non_exist_map_routes_present, router3)
+ test_func = functools.partial(non_exist_map_routes_present, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = 'TC32: non-exist-map routes present in "router2" BGP table - '
@@ -459,6 +524,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step6():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC41: non-exist-map route-map configuration removed in R2.
# advertise-map routes present in R2's BGP table are advertised to R3.
router2.vtysh_cmd(
@@ -468,7 +543,7 @@ def test_bgp_conditional_advertisement():
"""
)
- test_func = functools.partial(_non_exist_map_no_condition_route_map, router3)
+ test_func = functools.partial(non_exist_map_no_condition_route_map, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = 'TC41: non-exist-map route-map removed in "router2" - '
@@ -476,6 +551,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step7():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC42: exist-map route-map configuration removed in R2
# advertise-map routes present in R2's BGP table are withdrawn from R3.
router2.vtysh_cmd(
@@ -487,7 +572,7 @@ def test_bgp_conditional_advertisement():
"""
)
- test_func = functools.partial(_exist_map_no_condition_route_map, router3)
+ test_func = functools.partial(exist_map_no_condition_route_map, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = 'TC42: exist-map route-map removed in "router2" - '
@@ -495,6 +580,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step8():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC51: exist-map routes present in R2's BGP table, with route-map filter.
# All routes are withdrawn from R3 except advertise-map routes.
router2.vtysh_cmd(
@@ -510,7 +605,7 @@ def test_bgp_conditional_advertisement():
"""
)
- test_func = functools.partial(_exist_map_routes_present_rmap_filter, router3)
+ test_func = functools.partial(exist_map_routes_present_rmap_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC51: exist-map routes present with route-map filter - "
@@ -518,6 +613,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step9():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC52: exist-map routes present in R2's BGP table, no route-map filter.
# All routes are advertised to R3 including advertise-map routes.
router2.vtysh_cmd(
@@ -529,7 +634,7 @@ def test_bgp_conditional_advertisement():
"""
)
- test_func = functools.partial(_exist_map_routes_present_no_rmap_filter, router3)
+ test_func = functools.partial(exist_map_routes_present_no_rmap_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC52: exist-map routes present, no route-map filter - "
@@ -537,6 +642,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step10():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC53: non-exist-map routes present in R2's BGP table, with route-map filter.
# All routes are withdrawn from R3 including advertise-map routes.
router2.vtysh_cmd(
@@ -549,7 +664,7 @@ def test_bgp_conditional_advertisement():
"""
)
- test_func = functools.partial(_non_exist_map_routes_present_rmap_filter, router3)
+ test_func = functools.partial(non_exist_map_routes_present_rmap_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC53: non-exist-map routes present, with route-map filter - "
@@ -557,6 +672,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step11():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC54: non-exist-map routes present in R2's BGP table, no route-map filter.
# All routes are advertised to R3 except advertise-map routes.
router2.vtysh_cmd(
@@ -568,7 +693,7 @@ def test_bgp_conditional_advertisement():
"""
)
- test_func = functools.partial(_non_exist_map_routes_present_no_rmap_filter, router3)
+ test_func = functools.partial(non_exist_map_routes_present_no_rmap_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC54: non-exist-map routes present, no route-map filter - "
@@ -576,6 +701,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step12():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC61: exist-map routes not present in R2's BGP table, with route-map filter.
# All routes are withdrawn from R3 including advertise-map routes.
router1.vtysh_cmd(
@@ -596,7 +731,7 @@ def test_bgp_conditional_advertisement():
"""
)
- test_func = functools.partial(_exist_map_routes_not_present_rmap_filter, router3)
+ test_func = functools.partial(exist_map_routes_not_present_rmap_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC61: exist-map routes not present, route-map filter - "
@@ -604,6 +739,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step13():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC62: exist-map routes not present in R2's BGP table, without route-map filter.
# All routes are advertised to R3 except advertise-map routes.
router2.vtysh_cmd(
@@ -615,7 +760,7 @@ def test_bgp_conditional_advertisement():
"""
)
- test_func = functools.partial(_exist_map_routes_not_present_no_rmap_filter, router3)
+ test_func = functools.partial(exist_map_routes_not_present_no_rmap_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC62: exist-map routes not present, no route-map filter - "
@@ -623,6 +768,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step14():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC63: non-exist-map routes not present in R2's BGP table, with route-map filter.
# All routes are withdrawn from R3 except advertise-map routes.
router2.vtysh_cmd(
@@ -635,9 +790,7 @@ def test_bgp_conditional_advertisement():
"""
)
- test_func = functools.partial(
- _non_exist_map_routes_not_present_rmap_filter, router3
- )
+ test_func = functools.partial(non_exist_map_routes_not_present_rmap_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC63: non-exist-map routes not present, route-map filter - "
@@ -645,6 +798,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step15():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC64: non-exist-map routes not present in R2's BGP table, without route-map filter.
# All routes are advertised to R3 including advertise-map routes.
router2.vtysh_cmd(
@@ -657,7 +820,7 @@ def test_bgp_conditional_advertisement():
)
test_func = functools.partial(
- _non_exist_map_routes_not_present_no_rmap_filter, router3
+ non_exist_map_routes_not_present_no_rmap_filter, router3
)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
@@ -666,6 +829,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step16():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC71: exist-map routes present in R2's BGP table, with route-map filter.
# All routes are withdrawn from R3 except advertise-map routes.
router1.vtysh_cmd(
@@ -686,7 +859,7 @@ def test_bgp_conditional_advertisement():
"""
)
- test_func = functools.partial(_exist_map_routes_present_rmap2_filter, router3)
+ test_func = functools.partial(exist_map_routes_present_rmap2_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC71: exist-map routes present, route-map filter - "
@@ -694,6 +867,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step17():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC72: exist-map routes present in R2's BGP table, without route-map filter.
# All routes are advertised to R3 including advertise-map routes.
router2.vtysh_cmd(
@@ -705,7 +888,7 @@ def test_bgp_conditional_advertisement():
"""
)
- test_func = functools.partial(_exist_map_routes_present_no_rmap2_filter, router3)
+ test_func = functools.partial(exist_map_routes_present_no_rmap2_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC72: exist-map routes present, no route-map filter - "
@@ -713,6 +896,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step18():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC73: non-exist-map routes present in R2's BGP table, with route-map filter.
# All routes are advertised to R3 including advertise-map routes.
router2.vtysh_cmd(
@@ -725,7 +918,7 @@ def test_bgp_conditional_advertisement():
"""
)
- test_func = functools.partial(_non_exist_map_routes_present_rmap2_filter, router3)
+ test_func = functools.partial(non_exist_map_routes_present_rmap2_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC73: non-exist-map routes present, route-map filter - "
@@ -733,6 +926,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step19():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC74: non-exist-map routes present in R2's BGP table, without route-map filter.
# All routes are advertised to R3 including advertise-map routes.
router2.vtysh_cmd(
@@ -744,9 +947,7 @@ def test_bgp_conditional_advertisement():
"""
)
- test_func = functools.partial(
- _non_exist_map_routes_present_no_rmap2_filter, router3
- )
+ test_func = functools.partial(non_exist_map_routes_present_no_rmap2_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC74: non-exist-map routes present, no route-map filter - "
@@ -754,6 +955,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step20():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC81: exist-map routes not present in R2's BGP table, with route-map filter.
# All routes are withdrawn from R3 including advertise-map routes.
router1.vtysh_cmd(
@@ -774,7 +985,7 @@ def test_bgp_conditional_advertisement():
"""
)
- test_func = functools.partial(_exist_map_routes_not_present_rmap2_filter, router3)
+ test_func = functools.partial(exist_map_routes_not_present_rmap2_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC81: exist-map routes not present, route-map filter - "
@@ -782,6 +993,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step21():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC82: exist-map routes not present in R2's BGP table, without route-map filter.
# All routes are advertised to R3 except advertise-map routes.
router2.vtysh_cmd(
@@ -793,9 +1014,7 @@ def test_bgp_conditional_advertisement():
"""
)
- test_func = functools.partial(
- _exist_map_routes_not_present_no_rmap2_filter, router3
- )
+ test_func = functools.partial(exist_map_routes_not_present_no_rmap2_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC82: exist-map routes not present, no route-map filter - "
@@ -803,6 +1022,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step22():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC83: non-exist-map routes not present in R2's BGP table, with route-map filter.
# All routes are advertised to R3 including advertise-map routes.
router2.vtysh_cmd(
@@ -816,7 +1045,7 @@ def test_bgp_conditional_advertisement():
)
test_func = functools.partial(
- _non_exist_map_routes_not_present_rmap2_filter, router3
+ non_exist_map_routes_not_present_rmap2_filter, router3
)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
@@ -825,6 +1054,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step23():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC84: non-exist-map routes not present in R2's BGP table, without route-map filter.
# All routes are advertised to R3 including advertise-map routes.
router2.vtysh_cmd(
@@ -837,7 +1076,7 @@ def test_bgp_conditional_advertisement():
)
test_func = functools.partial(
- _non_exist_map_routes_not_present_no_rmap2_filter, router3
+ non_exist_map_routes_not_present_no_rmap2_filter, router3
)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
@@ -846,6 +1085,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step24():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC91: exist-map routes present in R2's BGP table, with route-map filter and network.
# All routes are advertised to R3 including advertise-map routes.
router1.vtysh_cmd(
@@ -866,7 +1115,7 @@ def test_bgp_conditional_advertisement():
"""
)
- test_func = functools.partial(_exist_map_routes_present_rmap2_network, router3)
+ test_func = functools.partial(exist_map_routes_present_rmap2_network, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC91: exist-map routes present, route-map filter and network - "
@@ -874,6 +1123,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step25():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC92: exist-map routes present in R2's BGP table, with route-map filter and no network.
# All routes are advertised to R3 except advertise-map routes.
router2.vtysh_cmd(
@@ -885,7 +1144,7 @@ def test_bgp_conditional_advertisement():
"""
)
- test_func = functools.partial(_exist_map_routes_present_rmap2_no_network, router3)
+ test_func = functools.partial(exist_map_routes_present_rmap2_no_network, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC92: exist-map routes present, route-map filter and no network - "
@@ -893,6 +1152,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step26():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC93: non-exist-map routes not present in R2's BGP table, with route-map filter and network.
# All routes are advertised to R3 including advertise-map routes.
router1.vtysh_cmd(
@@ -914,7 +1183,7 @@ def test_bgp_conditional_advertisement():
)
test_func = functools.partial(
- _non_exist_map_routes_not_present_rmap2_network, router3
+ non_exist_map_routes_not_present_rmap2_network, router3
)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
@@ -923,6 +1192,16 @@ def test_bgp_conditional_advertisement():
logger.info(msg + passed)
+
+def test_bgp_conditional_advertisement_step27():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
# TC94: non-exist-map routes not present in R2's BGP table, with route-map filter and no network.
# All routes are advertised to R3 except advertise-map routes.
router2.vtysh_cmd(
@@ -935,7 +1214,7 @@ def test_bgp_conditional_advertisement():
)
test_func = functools.partial(
- _non_exist_map_routes_not_present_rmap2_no_network, router3
+ non_exist_map_routes_not_present_rmap2_no_network, router3
)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index 4bd0ac27f6..31d8294a0f 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -290,9 +290,20 @@ static int netlink_recvbuf(struct nlsock *nl, uint32_t newsize)
return 0;
}
+static const char *group2str(uint32_t group)
+{
+ switch (group) {
+ case RTNLGRP_TUNNEL:
+ return "RTNLGRP_TUNNEL";
+ default:
+ return "UNKNOWN";
+ }
+}
+
/* Make socket for Linux netlink interface. */
static int netlink_socket(struct nlsock *nl, unsigned long groups,
- unsigned long ext_groups, ns_id_t ns_id)
+ uint32_t ext_groups[], uint8_t ext_group_size,
+ ns_id_t ns_id)
{
int ret;
struct sockaddr_nl snl;
@@ -311,18 +322,30 @@ static int netlink_socket(struct nlsock *nl, unsigned long groups,
snl.nl_family = AF_NETLINK;
snl.nl_groups = groups;
+ if (ext_group_size) {
+ uint8_t i;
+
+ for (i = 0; i < ext_group_size; i++) {
#if defined SOL_NETLINK
- if (ext_groups) {
- ret = setsockopt(sock, SOL_NETLINK,
- NETLINK_ADD_MEMBERSHIP, &ext_groups,
- sizeof(ext_groups));
- if (ret < 0) {
+ ret = setsockopt(sock, SOL_NETLINK,
+ NETLINK_ADD_MEMBERSHIP,
+ &ext_groups[i],
+ sizeof(ext_groups[i]));
+ if (ret < 0) {
+ zlog_notice(
+ "can't setsockopt NETLINK_ADD_MEMBERSHIP for group %s(%u), this linux kernel does not support it: %s(%d)",
+ group2str(ext_groups[i]),
+ ext_groups[i],
+ safe_strerror(errno), errno);
+ }
+#else
zlog_notice(
- "can't setsockopt NETLINK_ADD_MEMBERSHIP: %s(%d)",
- safe_strerror(errno), errno);
+ "Unable to use NETLINK_ADD_MEMBERSHIP via SOL_NETLINK for %s(%u) since the linux kernel does not support the socket option",
+ group2str(ext_groups[i]),
+ ext_groups[i]);
+#endif
}
}
-#endif
/* Bind the socket to the netlink structure for anything. */
ret = bind(sock, (struct sockaddr *)&snl, sizeof(snl));
@@ -1734,7 +1757,8 @@ void kernel_init(struct zebra_ns *zns)
snprintf(zns->netlink.name, sizeof(zns->netlink.name),
"netlink-listen (NS %u)", zns->ns_id);
zns->netlink.sock = -1;
- if (netlink_socket(&zns->netlink, groups, ext_groups, zns->ns_id) < 0) {
+ if (netlink_socket(&zns->netlink, groups, &ext_groups, 1, zns->ns_id) <
+ 0) {
zlog_err("Failure to create %s socket",
zns->netlink.name);
exit(-1);
@@ -1745,7 +1769,7 @@ void kernel_init(struct zebra_ns *zns)
snprintf(zns->netlink_cmd.name, sizeof(zns->netlink_cmd.name),
"netlink-cmd (NS %u)", zns->ns_id);
zns->netlink_cmd.sock = -1;
- if (netlink_socket(&zns->netlink_cmd, 0, 0, zns->ns_id) < 0) {
+ if (netlink_socket(&zns->netlink_cmd, 0, 0, 0, zns->ns_id) < 0) {
zlog_err("Failure to create %s socket",
zns->netlink_cmd.name);
exit(-1);
@@ -1758,7 +1782,7 @@ void kernel_init(struct zebra_ns *zns)
sizeof(zns->netlink_dplane_out.name), "netlink-dp (NS %u)",
zns->ns_id);
zns->netlink_dplane_out.sock = -1;
- if (netlink_socket(&zns->netlink_dplane_out, 0, 0, zns->ns_id) < 0) {
+ if (netlink_socket(&zns->netlink_dplane_out, 0, 0, 0, zns->ns_id) < 0) {
zlog_err("Failure to create %s socket",
zns->netlink_dplane_out.name);
exit(-1);
@@ -1771,7 +1795,7 @@ void kernel_init(struct zebra_ns *zns)
sizeof(zns->netlink_dplane_in.name), "netlink-dp-in (NS %u)",
zns->ns_id);
zns->netlink_dplane_in.sock = -1;
- if (netlink_socket(&zns->netlink_dplane_in, dplane_groups, 0,
+ if (netlink_socket(&zns->netlink_dplane_in, dplane_groups, 0, 0,
zns->ns_id) < 0) {
zlog_err("Failure to create %s socket",
zns->netlink_dplane_in.name);
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index 57fd304ae8..2741a23242 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -1354,6 +1354,16 @@ static void kernel_read(struct thread *thread)
if (nbytes < 0) {
if (errno == ENOBUFS) {
+#ifdef __FreeBSD__
+ /*
+ * ENOBUFS indicates a temporary resource
+ * shortage and is not harmful for consistency of
+ * reading the routing socket. Ignore it.
+ */
+ thread_add_read(zrouter.master, kernel_read, NULL, sock,
+ NULL);
+ return;
+#else
flog_err(EC_ZEBRA_RECVMSG_OVERRUN,
"routing socket overrun: %s",
safe_strerror(errno));
@@ -1363,6 +1373,7 @@ static void kernel_read(struct thread *thread)
* recover zebra at this point.
*/
exit(-1);
+#endif
}
if (errno != EAGAIN && errno != EWOULDBLOCK)
flog_err_sys(EC_LIB_SOCKET, "routing socket error: %s",
diff --git a/zebra/main.c b/zebra/main.c
index e516688a19..46cf2eea7d 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -71,9 +71,6 @@ struct thread_master *master;
/* Route retain mode flag. */
int retain_mode = 0;
-/* Allow non-frr entities to delete frr routes */
-int allow_delete = 0;
-
int graceful_restart;
bool v6_rr_semantics = false;
@@ -336,7 +333,7 @@ int main(int argc, char **argv)
// batch_mode = 1;
break;
case 'a':
- allow_delete = 1;
+ zrouter.allow_delete = true;
break;
case 'e': {
unsigned long int parsed_multipath =
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 21c991c7db..ce06f1683d 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -341,6 +341,22 @@ static inline int proto2zebra(int proto, int family, bool is_nexthop)
case RTPROT_SRTE:
proto = ZEBRA_ROUTE_SRTE;
break;
+ case RTPROT_UNSPEC:
+ case RTPROT_REDIRECT:
+ case RTPROT_KERNEL:
+ case RTPROT_BOOT:
+ case RTPROT_GATED:
+ case RTPROT_RA:
+ case RTPROT_MRT:
+ case RTPROT_BIRD:
+ case RTPROT_DNROUTED:
+ case RTPROT_XORP:
+ case RTPROT_NTK:
+ case RTPROT_MROUTED:
+ case RTPROT_KEEPALIVED:
+ case RTPROT_OPENR:
+ proto = ZEBRA_ROUTE_KERNEL;
+ break;
case RTPROT_ZEBRA:
if (is_nexthop) {
proto = ZEBRA_ROUTE_NHG;
@@ -977,8 +993,19 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
if (nhe_id || ng)
rib_add_multipath(afi, SAFI_UNICAST, &p,
&src_p, re, ng, startup);
- else
+ else {
+ /*
+ * I really don't see how this is possible
+ * but since we are testing for it let's
+ * let the end user know why the route
+ * that was just received was swallowed
+ * up and forgotten
+ */
+ zlog_err(
+ "%s: %pFX multipath RTM_NEWROUTE has a invalid nexthop group from the kernel",
+ __func__, &p);
XFREE(MTYPE_RE, re);
+ }
}
} else {
if (nhe_id) {
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 63f15b0f20..adfd3174e3 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -77,9 +77,6 @@ static struct dplane_ctx_q rib_dplane_q;
DEFINE_HOOK(rib_update, (struct route_node * rn, const char *reason),
(rn, reason));
-/* Should we allow non FRR processes to delete our routes */
-extern int allow_delete;
-
/* Each route type's string and default distance value. */
static const struct {
int key;
@@ -167,6 +164,30 @@ struct wq_evpn_wrapper {
#pragma FRR printfrr_ext "%pZN" (struct route_node *)
#endif
+static const char *subqueue2str(uint8_t index)
+{
+ switch (index) {
+ case 0:
+ return "NHG Objects";
+ case 1:
+ return "EVPN/VxLan Objects";
+ case 2:
+ return "Connected Routes";
+ case 3:
+ return "Kernel Routes";
+ case 4:
+ return "Static Routes";
+ case 5:
+ return "RIP/OSPF/ISIS/EIGRP/NHRP Routes";
+ case 6:
+ return "BGP Routes";
+ case 7:
+ return "Other Routes";
+ }
+
+ return "Unknown";
+}
+
printfrr_ext_autoreg_p("ZN", printfrr_zebra_node);
static ssize_t printfrr_zebra_node(struct fbuf *buf, struct printfrr_eargs *ea,
const void *ptr)
@@ -2407,8 +2428,8 @@ static void process_subq_nhg(struct listnode *lnode)
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug(
- "NHG Context id=%u dequeued from sub-queue %u",
- ctx->id, qindex);
+ "NHG Context id=%u dequeued from sub-queue %s",
+ ctx->id, subqueue2str(qindex));
/* Process nexthop group updates coming 'up' from the OS */
@@ -2418,8 +2439,8 @@ static void process_subq_nhg(struct listnode *lnode)
nhe = w->u.nhe;
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- zlog_debug("NHG %u dequeued from sub-queue %u",
- nhe->id, qindex);
+ zlog_debug("NHG %u dequeued from sub-queue %s", nhe->id,
+ subqueue2str(qindex));
/* Process incoming nhg update, probably from a proto daemon */
newnhe = zebra_nhg_proto_add(nhe->id, nhe->type,
@@ -2465,9 +2486,9 @@ static void process_subq_route(struct listnode *lnode, uint8_t qindex)
if (dest)
re = re_list_first(&dest->routes);
- zlog_debug("%s(%u:%u):%pRN rn %p dequeued from sub-queue %u",
+ zlog_debug("%s(%u:%u):%pRN rn %p dequeued from sub-queue %s",
zvrf_name(zvrf), zvrf_id(zvrf), re ? re->table : 0,
- rnode, rnode, qindex);
+ rnode, rnode, subqueue2str(qindex));
}
if (rnode->info)
@@ -2578,8 +2599,8 @@ static int rib_meta_queue_add(struct meta_queue *mq, void *data)
RIB_ROUTE_QUEUED(qindex))) {
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
rnode_debug(rn, re->vrf_id,
- "rn %p is already queued in sub-queue %u",
- (void *)rn, qindex);
+ "rn %p is already queued in sub-queue %s",
+ (void *)rn, subqueue2str(qindex));
return -1;
}
@@ -2589,8 +2610,8 @@ static int rib_meta_queue_add(struct meta_queue *mq, void *data)
mq->size++;
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- rnode_debug(rn, re->vrf_id, "queued rn %p into sub-queue %u",
- (void *)rn, qindex);
+ rnode_debug(rn, re->vrf_id, "queued rn %p into sub-queue %s",
+ (void *)rn, subqueue2str(qindex));
return 0;
}
@@ -2615,8 +2636,8 @@ static int rib_meta_queue_nhg_ctx_add(struct meta_queue *mq, void *data)
mq->size++;
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- zlog_debug("NHG Context id=%u queued into sub-queue %u",
- ctx->id, qindex);
+ zlog_debug("NHG Context id=%u queued into sub-queue %s",
+ ctx->id, subqueue2str(qindex));
return 0;
}
@@ -2641,8 +2662,8 @@ static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data)
mq->size++;
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- zlog_debug("NHG id=%u queued into sub-queue %u",
- nhe->id, qindex);
+ zlog_debug("NHG id=%u queued into sub-queue %s", nhe->id,
+ subqueue2str(qindex));
return 0;
}
@@ -3722,8 +3743,8 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
rn, fib,
zebra_route_string(fib->type));
}
- if (allow_delete
- || CHECK_FLAG(dest->flags, RIB_ROUTE_ANY_QUEUED)) {
+ if (zrouter.allow_delete ||
+ CHECK_FLAG(dest->flags, RIB_ROUTE_ANY_QUEUED)) {
UNSET_FLAG(fib->status, ROUTE_ENTRY_INSTALLED);
/* Unset flags. */
for (rtnh = fib->nhe->nhg.nexthop; rtnh;
@@ -3768,8 +3789,8 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
if (same) {
struct nexthop *tmp_nh;
- if (fromkernel && CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE)
- && !allow_delete) {
+ if (fromkernel && CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE) &&
+ !zrouter.allow_delete) {
rib_install_kernel(rn, same, NULL);
route_unlock_node(rn);
diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c
index 9fccda9e08..f7ad30b41f 100644
--- a/zebra/zebra_router.c
+++ b/zebra/zebra_router.c
@@ -278,6 +278,8 @@ void zebra_router_init(bool asic_offload, bool notify_on_ack)
{
zrouter.sequence_num = 0;
+ zrouter.allow_delete = false;
+
zrouter.packets_to_process = ZEBRA_ZAPI_PACKETS_TO_PROCESS;
zrouter.nhg_keep = ZEBRA_DEFAULT_NHG_KEEP_TIMER;
diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h
index d51e7a2b7d..0e2725c977 100644
--- a/zebra/zebra_router.h
+++ b/zebra/zebra_router.h
@@ -229,6 +229,9 @@ struct zebra_router {
#define ZEBRA_DEFAULT_NHG_KEEP_TIMER 180
uint32_t nhg_keep;
+
+ /* Should we allow non FRR processes to delete our routes */
+ bool allow_delete;
};
#define GRACEFUL_RESTART_TIME 60
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 6ae55cdba4..e6038d0bc2 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -66,8 +66,6 @@
#include "zebra/rtadv.h"
#include "zebra/zebra_neigh.h"
-extern int allow_delete;
-
/* context to manage dumps in multiple tables or vrfs */
struct route_show_ctx {
bool multi; /* dump multiple tables or vrf */
@@ -2699,7 +2697,7 @@ DEFUN (allow_external_route_update,
"allow-external-route-update",
"Allow FRR routes to be overwritten by external processes\n")
{
- allow_delete = 1;
+ zrouter.allow_delete = true;
return CMD_SUCCESS;
}
@@ -2710,7 +2708,7 @@ DEFUN (no_allow_external_route_update,
NO_STR
"Allow FRR routes to be overwritten by external processes\n")
{
- allow_delete = 0;
+ zrouter.allow_delete = false;
return CMD_SUCCESS;
}
@@ -3911,7 +3909,7 @@ DEFPY (zebra_nexthop_group_keep,
static int config_write_protocol(struct vty *vty)
{
- if (allow_delete)
+ if (zrouter.allow_delete)
vty_out(vty, "allow-external-route-update\n");
if (zrouter.nhg_keep != ZEBRA_DEFAULT_NHG_KEEP_TIMER)
@@ -4011,6 +4009,8 @@ DEFUN (show_zebra,
ttable_add_row(table, "Kernel NHG|%s",
zrouter.supports_nhgs ? "Available" : "Unavailable");
+ ttable_add_row(table, "Allow Non FRR route deletion|%s",
+ zrouter.allow_delete ? "Yes" : "No");
ttable_add_row(table, "v4 All LinkDown Routes|%s",
zrouter.all_linkdownv4 ? "On" : "Off");
ttable_add_row(table, "v4 Default LinkDown Routes|%s",