summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2021-02-17 06:53:12 -0500
committerGitHub <noreply@github.com>2021-02-17 06:53:12 -0500
commite2f17ae47ad047e66923c2ff1e84c9ba10d4ad38 (patch)
treec0d59f7da8dd36ed932e6380f78ff4ebdc575aa6
parent91b3c471f1c48818370a0f218add917f0d46aa47 (diff)
parent380341362ced8e317c18b7395acb012de1f23acd (diff)
Merge pull request #8096 from idryzhov/7.5-backports-2021-02-16
7.5 backports
-rw-r--r--bfdd/bfd.c160
-rw-r--r--bfdd/bfd_packet.c2
-rw-r--r--bfdd/ptm_adapter.c8
-rw-r--r--bgpd/bgp_bmp.c15
-rw-r--r--bgpd/bgp_bmp.h2
-rw-r--r--bgpd/bgp_packet.c1
-rw-r--r--bgpd/bgpd.h42
-rw-r--r--doc/user/bgp.rst26
-rw-r--r--docker/alpine/Dockerfile13
-rw-r--r--docker/centos-7/Dockerfile6
-rw-r--r--docker/centos-8/Dockerfile14
-rw-r--r--eigrpd/eigrp_interface.c18
-rw-r--r--eigrpd/eigrp_structs.h2
-rw-r--r--eigrpd/eigrp_topology.c1
-rw-r--r--isisd/isis_bfd.c6
-rw-r--r--lib/bfd.c22
-rw-r--r--lib/filter_cli.c24
-rw-r--r--lib/log.c3
-rw-r--r--lib/vrf.c3
-rw-r--r--ospf6d/ospf6_abr.c51
-rw-r--r--ospf6d/ospf6_asbr.c8
-rw-r--r--ospf6d/ospf6_interface.c7
-rw-r--r--ospf6d/ospf6_intra.c31
-rw-r--r--ospfd/ospf_bfd.c6
-rw-r--r--ospfd/ospf_packet.c10
-rw-r--r--pimd/pim_bfd.c6
-rw-r--r--pimd/pim_ifchannel.c33
-rw-r--r--pimd/pim_instance.c8
-rw-r--r--watchfrr/watchfrr.c5
-rw-r--r--zebra/zapi_msg.c1
-rw-r--r--zebra/zebra_nhg.c4
31 files changed, 332 insertions, 206 deletions
diff --git a/bfdd/bfd.c b/bfdd/bfd.c
index 74b41aeec9..19cdb31990 100644
--- a/bfdd/bfd.c
+++ b/bfdd/bfd.c
@@ -1633,15 +1633,54 @@ static bool bfd_id_hash_cmp(const void *n1, const void *n2)
static unsigned int bfd_key_hash_do(const void *p)
{
const struct bfd_session *bs = p;
+ struct bfd_key key = bs->key;
- return jhash(&bs->key, sizeof(bs->key), 0);
+ /*
+ * Local address and interface name are optional and
+ * can be filled any time after session creation.
+ * Hash key should not depend on these fields.
+ */
+ memset(&key.local, 0, sizeof(key.local));
+ memset(key.ifname, 0, sizeof(key.ifname));
+
+ return jhash(&key, sizeof(key), 0);
}
static bool bfd_key_hash_cmp(const void *n1, const void *n2)
{
const struct bfd_session *bs1 = n1, *bs2 = n2;
- return memcmp(&bs1->key, &bs2->key, sizeof(bs1->key)) == 0;
+ if (bs1->key.family != bs2->key.family)
+ return false;
+ if (bs1->key.mhop != bs2->key.mhop)
+ return false;
+ if (memcmp(&bs1->key.peer, &bs2->key.peer, sizeof(bs1->key.peer)))
+ return false;
+ if (memcmp(bs1->key.vrfname, bs2->key.vrfname,
+ sizeof(bs1->key.vrfname)))
+ return false;
+
+ /*
+ * Local address is optional and can be empty.
+ * If both addresses are not empty and different,
+ * then the keys are different.
+ */
+ if (memcmp(&bs1->key.local, &zero_addr, sizeof(bs1->key.local))
+ && memcmp(&bs2->key.local, &zero_addr, sizeof(bs2->key.local))
+ && memcmp(&bs1->key.local, &bs2->key.local, sizeof(bs1->key.local)))
+ return false;
+
+ /*
+ * Interface name is optional and can be empty.
+ * If both names are not empty and different,
+ * then the keys are different.
+ */
+ if (bs1->key.ifname[0] && bs2->key.ifname[0]
+ && memcmp(bs1->key.ifname, bs2->key.ifname,
+ sizeof(bs1->key.ifname)))
+ return false;
+
+ return true;
}
@@ -1659,117 +1698,13 @@ struct bfd_session *bfd_id_lookup(uint32_t id)
return hash_lookup(bfd_id_hash, &bs);
}
-struct bfd_key_walk_partial_lookup {
- struct bfd_session *given;
- struct bfd_session *result;
-};
-
-/* ignore some parameters */
-static int bfd_key_lookup_ignore_partial_walker(struct hash_bucket *b,
- void *data)
-{
- struct bfd_key_walk_partial_lookup *ctx =
- (struct bfd_key_walk_partial_lookup *)data;
- struct bfd_session *given = ctx->given;
- struct bfd_session *parsed = b->data;
-
- if (given->key.family != parsed->key.family)
- return HASHWALK_CONTINUE;
- if (given->key.mhop != parsed->key.mhop)
- return HASHWALK_CONTINUE;
- if (memcmp(&given->key.peer, &parsed->key.peer,
- sizeof(struct in6_addr)))
- return HASHWALK_CONTINUE;
- if (memcmp(given->key.vrfname, parsed->key.vrfname, MAXNAMELEN))
- return HASHWALK_CONTINUE;
- ctx->result = parsed;
- /* ignore localaddr or interface */
- return HASHWALK_ABORT;
-}
-
struct bfd_session *bfd_key_lookup(struct bfd_key key)
{
- struct bfd_session bs, *bsp;
- struct bfd_key_walk_partial_lookup ctx;
- char peer_buf[INET6_ADDRSTRLEN];
-
- bs.key = key;
- bsp = hash_lookup(bfd_key_hash, &bs);
- if (bsp)
- return bsp;
-
- inet_ntop(bs.key.family, &bs.key.peer, peer_buf,
- sizeof(peer_buf));
- /* Handle cases where local-address is optional. */
- if (memcmp(&bs.key.local, &zero_addr, sizeof(bs.key.local))) {
- memset(&bs.key.local, 0, sizeof(bs.key.local));
- bsp = hash_lookup(bfd_key_hash, &bs);
- if (bsp) {
- if (bglobal.debug_peer_event) {
- char addr_buf[INET6_ADDRSTRLEN];
- inet_ntop(bs.key.family, &key.local, addr_buf,
- sizeof(addr_buf));
- zlog_debug(
- " peer %s found, but loc-addr %s ignored",
- peer_buf, addr_buf);
- }
- return bsp;
- }
- }
-
- bs.key = key;
- /* Handle cases where ifname is optional. */
- if (bs.key.ifname[0]) {
- memset(bs.key.ifname, 0, sizeof(bs.key.ifname));
- bsp = hash_lookup(bfd_key_hash, &bs);
- if (bsp) {
- if (bglobal.debug_peer_event)
- zlog_debug(" peer %s found, but ifp %s ignored",
- peer_buf, key.ifname);
- return bsp;
- }
- }
+ struct bfd_session bs;
- /* Handle cases where local-address and ifname are optional. */
- if (bs.key.family == AF_INET) {
- memset(&bs.key.local, 0, sizeof(bs.key.local));
- bsp = hash_lookup(bfd_key_hash, &bs);
- if (bsp) {
- if (bglobal.debug_peer_event) {
- char addr_buf[INET6_ADDRSTRLEN];
- inet_ntop(bs.key.family, &bs.key.local,
- addr_buf, sizeof(addr_buf));
- zlog_debug(
- " peer %s found, but ifp %s and loc-addr %s ignored",
- peer_buf, key.ifname, addr_buf);
- }
- return bsp;
- }
- }
bs.key = key;
- /* Handle case where a context more complex ctx is present.
- * input has no iface nor local-address, but a context may
- * exist.
- *
- * Only applies to IPv4, because IPv6 requires either
- * local-address or interface.
- */
- if (!bs.key.mhop && bs.key.family == AF_INET) {
- ctx.result = NULL;
- ctx.given = &bs;
- hash_walk(bfd_key_hash, &bfd_key_lookup_ignore_partial_walker,
- &ctx);
- /* change key */
- if (ctx.result) {
- bsp = ctx.result;
- if (bglobal.debug_peer_event)
- zlog_debug(
- " peer %s found, but ifp and/or loc-addr params ignored",
- peer_buf);
- }
- }
- return bsp;
+ return hash_lookup(bfd_key_hash, &bs);
}
/*
@@ -1793,16 +1728,11 @@ struct bfd_session *bfd_id_delete(uint32_t id)
struct bfd_session *bfd_key_delete(struct bfd_key key)
{
- struct bfd_session bs, *bsp;
+ struct bfd_session bs;
bs.key = key;
- bsp = hash_lookup(bfd_key_hash, &bs);
- if (bsp == NULL && key.ifname[0]) {
- memset(bs.key.ifname, 0, sizeof(bs.key.ifname));
- bsp = hash_lookup(bfd_key_hash, &bs);
- }
- return hash_release(bfd_key_hash, bsp);
+ return hash_release(bfd_key_hash, &bs);
}
/* Iteration functions. */
diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c
index 076318e6ca..12bb52cf67 100644
--- a/bfdd/bfd_packet.c
+++ b/bfdd/bfd_packet.c
@@ -165,7 +165,7 @@ void ptm_bfd_echo_snd(struct bfd_session *bfd)
salen = sizeof(sin6);
} else {
sd = bvrf->bg_echo;
- memset(&sin6, 0, sizeof(sin6));
+ memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
memcpy(&sin.sin_addr, &bfd->key.peer, sizeof(sin.sin_addr));
sin.sin_port = htons(BFD_DEF_ECHO_PORT);
diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c
index 33f5119e4d..4816b860b2 100644
--- a/bfdd/ptm_adapter.c
+++ b/bfdd/ptm_adapter.c
@@ -681,11 +681,15 @@ static void bfdd_sessions_disable_interface(struct interface *ifp)
TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) {
bs = bso->bso_bs;
- if (strcmp(ifp->name, bs->key.ifname))
+
+ if (bs->ifp != ifp)
continue;
+
/* Skip disabled sessions. */
- if (bs->sock == -1)
+ if (bs->sock == -1) {
+ bs->ifp = NULL;
continue;
+ }
bfd_session_disable(bs);
diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c
index af88547ca9..2ce5e1c6d6 100644
--- a/bgpd/bgp_bmp.c
+++ b/bgpd/bgp_bmp.c
@@ -434,10 +434,19 @@ static struct stream *bmp_peerstate(struct peer *peer, bool down)
case PEER_DOWN_CLOSE_SESSION:
type = BMP_PEERDOWN_REMOTE_CLOSE;
break;
+ case PEER_DOWN_WAITING_NHT:
+ type = BMP_PEERDOWN_LOCAL_FSM;
+ stream_putw(s, BGP_FSM_TcpConnectionFails);
+ break;
+ /*
+ * TODO: Map remaining PEER_DOWN_* reasons to RFC event codes.
+ * TODO: Implement BMP_PEERDOWN_LOCAL_NOTIFY.
+ *
+ * See RFC7854 ss. 4.9
+ */
default:
- type = BMP_PEERDOWN_LOCAL_NOTIFY;
- stream_put(s, peer->last_reset_cause,
- peer->last_reset_cause_size);
+ type = BMP_PEERDOWN_LOCAL_FSM;
+ stream_putw(s, BMP_PEER_DOWN_NO_RELEVANT_EVENT_CODE);
break;
}
stream_putc_at(s, type_pos, type);
diff --git a/bgpd/bgp_bmp.h b/bgpd/bgp_bmp.h
index 9032da55bf..9cbb27e805 100644
--- a/bgpd/bgp_bmp.h
+++ b/bgpd/bgp_bmp.h
@@ -269,6 +269,8 @@ struct bmp_bgp_peer {
/* per struct bgp * data */
PREDECL_HASH(bmp_bgph)
+#define BMP_PEER_DOWN_NO_RELEVANT_EVENT_CODE 0x00
+
struct bmp_bgp {
struct bmp_bgph_item bbi;
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index f26c8a6a29..d4715c2433 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -1806,6 +1806,7 @@ static int bgp_notify_receive(struct peer *peer, bgp_size_t size)
bgp_notify.subcode = stream_getc(peer->curr);
bgp_notify.length = size - 2;
bgp_notify.data = NULL;
+ bgp_notify.raw_data = NULL;
/* Preserv notify code and sub code. */
peer->notify.code = bgp_notify.code;
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 2aa0690025..19aa1ce5fb 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -866,7 +866,47 @@ struct bgp_peer_gr {
bgp_peer_gr_action_ptr action_fun;
};
-/* BGP finite state machine events. */
+/*
+ * BGP FSM event codes, per RFC 4271 ss. 8.1
+ */
+enum bgp_fsm_rfc_codes {
+ BGP_FSM_ManualStart = 1,
+ BGP_FSM_ManualStop = 2,
+ BGP_FSM_AutomaticStart = 3,
+ BGP_FSM_ManualStart_with_PassiveTcpEstablishment = 4,
+ BGP_FSM_AutomaticStart_with_PassiveTcpEstablishment = 5,
+ BGP_FSM_AutomaticStart_with_DampPeerOscillations = 6,
+ BGP_FSM_AutomaticStart_with_DampPeerOscillations_and_PassiveTcpEstablishment =
+ 7,
+ BGP_FSM_AutomaticStop = 8,
+ BGP_FSM_ConnectRetryTimer_Expires = 9,
+ BGP_FSM_HoldTimer_Expires = 10,
+ BGP_FSM_KeepaliveTimer_Expires = 11,
+ BGP_FSM_DelayOpenTimer_Expires = 12,
+ BGP_FSM_IdleHoldTimer_Expires = 13,
+ BGP_FSM_TcpConnection_Valid = 14,
+ BGP_FSM_Tcp_CR_Invalid = 15,
+ BGP_FSM_Tcp_CR_Acked = 16,
+ BGP_FSM_TcpConnectionConfirmed = 17,
+ BGP_FSM_TcpConnectionFails = 18,
+ BGP_FSM_BGPOpen = 19,
+ BGP_FSM_BGPOpen_with_DelayOpenTimer_running = 20,
+ BGP_FSM_BGPHeaderErr = 21,
+ BGP_FSM_BGPOpenMsgErr = 22,
+ BGP_FSM_OpenCollisionDump = 23,
+ BGP_FSM_NotifMsgVerErr = 24,
+ BGP_FSM_NotifMsg = 25,
+ BGP_FSM_KeepAliveMsg = 26,
+ BGP_FSM_UpdateMsg = 27,
+ BGP_FSM_UpdateMsgErr = 28
+};
+
+/*
+ * BGP finite state machine events
+ *
+ * Note: these do not correspond to RFC-defined event codes. Those are
+ * defined elsewhere.
+ */
enum bgp_fsm_events {
BGP_Start = 1,
BGP_Stop,
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index ff83eb0a4c..6f3ff3a5f4 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -415,10 +415,14 @@ Require policy on EBGP
.. clicmd:: [no] bgp ebgp-requires-policy
This command requires incoming and outgoing filters to be applied
- for eBGP sessions. Without the incoming filter, no routes will be
- accepted. Without the outgoing filter, no routes will be announced.
+ for eBGP sessions as part of RFC-8212 compliance. Without the incoming
+ filter, no routes will be accepted. Without the outgoing filter, no
+ routes will be announced.
- This is enabled by default.
+ This is enabled by default for the traditional configuration and
+ turned off by default for datacenter configuration.
+
+ When you enable/disable this option you MUST clear the session.
When the incoming or outgoing filter is missing you will see
"(Policy)" sign under ``show bgp summary``:
@@ -437,6 +441,22 @@ Require policy on EBGP
192.168.0.2 4 65002 8 10 0 0 0 00:03:09 5 (Policy)
fe80:1::2222 4 65002 9 11 0 0 0 00:03:09 (Policy) (Policy)
+ Additionally a `show bgp neighbor` command would indicate in the `For address family:`
+ block that:
+
+ .. code-block:: frr
+
+ exit1# show bgp neighbor
+ ...
+ For address family: IPv4 Unicast
+ Update group 1, subgroup 1
+ Packet Queue length 0
+ Inbound soft reconfiguration allowed
+ Community attribute sent to this neighbor(all)
+ Inbound updates discarded due to missing policy
+ Outbound updates discarded due to missing policy
+ 0 accepted prefixes
+
Reject routes with AS_SET or AS_CONFED_SET types
------------------------------------------------
diff --git a/docker/alpine/Dockerfile b/docker/alpine/Dockerfile
index ed6453e2b1..126710f8c2 100644
--- a/docker/alpine/Dockerfile
+++ b/docker/alpine/Dockerfile
@@ -1,10 +1,9 @@
# This stage builds a dist tarball from the source
-FROM alpine:edge as source-builder
+FROM alpine:latest as source-builder
RUN mkdir -p /src/alpine
COPY alpine/APKBUILD.in /src/alpine
RUN source /src/alpine/APKBUILD.in \
- && echo 'http://dl-cdn.alpinelinux.org/alpine/edge/testing' >> /etc/apk/repositories \
&& apk add \
--no-cache \
--update-cache \
@@ -22,10 +21,9 @@ RUN cd /src \
&& make dist
# This stage builds an apk from the dist tarball
-FROM alpine:edge as alpine-builder
+FROM alpine:latest as alpine-builder
# Don't use nocache here so that abuild can use the cache
-RUN echo 'http://dl-cdn.alpinelinux.org/alpine/edge/testing' >> /etc/apk/repositories \
- && apk add \
+RUN apk add \
--update-cache \
abuild \
alpine-conf \
@@ -46,11 +44,10 @@ RUN cd /dist \
&& abuild -r -P /pkgs/apk
# This stage installs frr from the apk
-FROM alpine:edge
+FROM alpine:latest
RUN mkdir -p /pkgs/apk
COPY --from=alpine-builder /pkgs/apk/ /pkgs/apk/
-RUN echo 'http://dl-cdn.alpinelinux.org/alpine/edge/testing' >> /etc/apk/repositories \
- && apk add \
+RUN apk add \
--no-cache \
--update-cache \
tini \
diff --git a/docker/centos-7/Dockerfile b/docker/centos-7/Dockerfile
index cca8baa147..a92326fcf3 100644
--- a/docker/centos-7/Dockerfile
+++ b/docker/centos-7/Dockerfile
@@ -5,8 +5,8 @@ RUN yum install -y rpm-build autoconf automake libtool make \
readline-devel texinfo net-snmp-devel groff pkgconfig \
json-c-devel pam-devel bison flex pytest c-ares-devel \
python3-devel python3-sphinx systemd-devel libcap-devel \
- https://ci1.netdef.org/artifact/LIBYANG-YANGRELEASE/shared/build-10/CentOS-7-x86_64-Packages/libyang-0.16.111-0.x86_64.rpm \
- https://ci1.netdef.org/artifact/LIBYANG-YANGRELEASE/shared/build-10/CentOS-7-x86_64-Packages/libyang-devel-0.16.111-0.x86_64.rpm \
+ https://ci1.netdef.org/artifact/LIBYANG-LY1REL/shared/build-4/CentOS-7-x86_64-Packages/libyang1-1.0.184-0.x86_64.rpm \
+ https://ci1.netdef.org/artifact/LIBYANG-LY1REL/shared/build-4/CentOS-7-x86_64-Packages/libyang-devel-1.0.184-0.x86_64.rpm \
https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-110/CentOS-7-x86_64-Packages/librtr-0.7.0-1.el7.centos.x86_64.rpm \
https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-110/CentOS-7-x86_64-Packages/librtr-devel-0.7.0-1.el7.centos.x86_64.rpm
@@ -32,7 +32,7 @@ RUN echo '%_smp_mflags %( echo "-j$(/usr/bin/getconf _NPROCESSORS_ONLN)"; )' >>
# This stage installs frr from the rpm
FROM centos:centos7
RUN mkdir -p /pkgs/rpm \
- && yum install -y https://ci1.netdef.org/artifact/LIBYANG-YANGRELEASE/shared/build-10/CentOS-7-x86_64-Packages/libyang-0.16.111-0.x86_64.rpm \
+ && yum install -y https://ci1.netdef.org/artifact/LIBYANG-LY1REL/shared/build-4/CentOS-7-x86_64-Packages/libyang1-1.0.184-0.x86_64.rpm \
https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-110/CentOS-7-x86_64-Packages/librtr-0.7.0-1.el7.centos.x86_64.rpm
COPY --from=centos-7-builder /rpmbuild/RPMS/ /pkgs/rpm/
diff --git a/docker/centos-8/Dockerfile b/docker/centos-8/Dockerfile
index 6c1f873589..7ed7948927 100644
--- a/docker/centos-8/Dockerfile
+++ b/docker/centos-8/Dockerfile
@@ -1,17 +1,15 @@
# This stage builds an rpm from the source
FROM centos:centos8 as centos-8-builder
-RUN dnf install --enablerepo=PowerTools -y rpm-build git autoconf pcre-devel \
+RUN dnf install --enablerepo=powertools -y rpm-build git autoconf pcre-devel \
automake libtool make readline-devel texinfo net-snmp-devel pkgconfig \
- groff pkgconfig json-c-devel pam-devel bison flex python2-pytest \
- c-ares-devel python2-devel systemd-devel libcap-devel platform-python-devel \
- https://ci1.netdef.org/artifact/LIBYANG-YANGRELEASE/shared/build-10/CentOS-7-x86_64-Packages/libyang-0.16.111-0.x86_64.rpm \
- https://ci1.netdef.org/artifact/LIBYANG-YANGRELEASE/shared/build-10/CentOS-7-x86_64-Packages/libyang-devel-0.16.111-0.x86_64.rpm \
+ groff pkgconfig json-c-devel pam-devel bison flex python3-pytest \
+ c-ares-devel python3-devel python3-sphinx systemd-devel libcap-devel platform-python-devel \
+ https://ci1.netdef.org/artifact/LIBYANG-LY1REL/shared/build-4/CentOS-8-x86_64-Packages/libyang1-1.0.184-0.x86_64.rpm \
+ https://ci1.netdef.org/artifact/LIBYANG-LY1REL/shared/build-4/CentOS-8-x86_64-Packages/libyang-devel-1.0.184-0.x86_64.rpm \
https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-110/CentOS-7-x86_64-Packages/librtr-0.7.0-1.el7.centos.x86_64.rpm \
https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-110/CentOS-7-x86_64-Packages/librtr-devel-0.7.0-1.el7.centos.x86_64.rpm
-RUN pip2 install sphinx
-
COPY . /src
ARG PKGVER
@@ -35,7 +33,7 @@ RUN echo '%_smp_mflags %( echo "-j$(/usr/bin/getconf _NPROCESSORS_ONLN)"; )' >>
# This stage installs frr from the rpm
FROM centos:centos8
RUN mkdir -p /pkgs/rpm \
- && yum install -y https://ci1.netdef.org/artifact/LIBYANG-YANGRELEASE/shared/build-10/CentOS-7-x86_64-Packages/libyang-0.16.111-0.x86_64.rpm \
+ && yum install -y https://ci1.netdef.org/artifact/LIBYANG-LY1REL/shared/build-4/CentOS-8-x86_64-Packages/libyang1-1.0.184-0.x86_64.rpm \
https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-110/CentOS-7-x86_64-Packages/librtr-0.7.0-1.el7.centos.x86_64.rpm
COPY --from=centos-8-builder /rpmbuild/RPMS/ /pkgs/rpm/
diff --git a/eigrpd/eigrp_interface.c b/eigrpd/eigrp_interface.c
index 9ef4e86237..3a45771eaa 100644
--- a/eigrpd/eigrp_interface.c
+++ b/eigrpd/eigrp_interface.c
@@ -227,6 +227,20 @@ void eigrp_del_if_params(struct eigrp_if_params *eip)
free(eip->auth_keychain);
}
+/*
+ * Set the network byte order of the 3 bytes we send
+ * of the mtu of the link.
+ */
+static void eigrp_mtu_convert(struct eigrp_metrics *metric, uint32_t host_mtu)
+{
+ uint32_t network_mtu = htonl(host_mtu);
+ uint8_t *nm = (uint8_t *)&network_mtu;
+
+ metric->mtu[0] = nm[1];
+ metric->mtu[1] = nm[2];
+ metric->mtu[2] = nm[3];
+}
+
int eigrp_if_up(struct eigrp_interface *ei)
{
struct eigrp_prefix_entry *pe;
@@ -254,9 +268,7 @@ int eigrp_if_up(struct eigrp_interface *ei)
metric.delay = eigrp_delay_to_scaled(ei->params.delay);
metric.load = ei->params.load;
metric.reliability = ei->params.reliability;
- metric.mtu[0] = 0xDC;
- metric.mtu[1] = 0x05;
- metric.mtu[2] = 0x00;
+ eigrp_mtu_convert(&metric, ei->ifp->mtu);
metric.hop_count = 0;
metric.flags = 0;
metric.tag = 0;
diff --git a/eigrpd/eigrp_structs.h b/eigrpd/eigrp_structs.h
index 82bddaaae3..1337ec966f 100644
--- a/eigrpd/eigrp_structs.h
+++ b/eigrpd/eigrp_structs.h
@@ -60,7 +60,7 @@ struct eigrp_master {
struct eigrp_metrics {
uint32_t delay;
uint32_t bandwidth;
- unsigned char mtu[3];
+ uint8_t mtu[3];
uint8_t hop_count;
uint8_t reliability;
uint8_t load;
diff --git a/eigrpd/eigrp_topology.c b/eigrpd/eigrp_topology.c
index 7676af15f2..5247413d2f 100644
--- a/eigrpd/eigrp_topology.c
+++ b/eigrpd/eigrp_topology.c
@@ -508,6 +508,7 @@ void eigrp_topology_neighbor_down(struct eigrp *eigrp,
if (entry->adv_router != nbr)
continue;
+ memset(&msg, 0, sizeof(msg));
msg.metrics.delay = EIGRP_MAX_METRIC;
msg.packet_type = EIGRP_OPC_UPDATE;
msg.eigrp = eigrp;
diff --git a/isisd/isis_bfd.c b/isisd/isis_bfd.c
index f81dd6cf51..f6255d5a59 100644
--- a/isisd/isis_bfd.c
+++ b/isisd/isis_bfd.c
@@ -146,11 +146,11 @@ static void bfd_adj_event(struct isis_adjacency *adj, struct prefix *dst,
static int isis_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS)
{
struct interface *ifp;
- struct prefix dst_ip;
+ struct prefix dst_ip, src_ip;
int status;
- ifp = bfd_get_peer_info(zclient->ibuf, &dst_ip, NULL, &status,
- NULL, vrf_id);
+ ifp = bfd_get_peer_info(zclient->ibuf, &dst_ip, &src_ip, &status, NULL,
+ vrf_id);
if (!ifp || (dst_ip.family != AF_INET && dst_ip.family != AF_INET6))
return 0;
diff --git a/lib/bfd.c b/lib/bfd.c
index 758271b729..a309b741dd 100644
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -224,6 +224,17 @@ struct interface *bfd_get_peer_info(struct stream *s, struct prefix *dp,
int plen;
int local_remote_cbit;
+ /*
+ * If the ifindex lookup fails the
+ * rest of the data in the stream is
+ * not read. All examples of this function
+ * call immediately use the dp->family which
+ * is not good. Ensure we are not using
+ * random data
+ */
+ memset(dp, 0, sizeof(*dp));
+ memset(sp, 0, sizeof(*sp));
+
/* Get interface index. */
ifindex = stream_getl(s);
@@ -249,13 +260,12 @@ struct interface *bfd_get_peer_info(struct stream *s, struct prefix *dp,
/* Get BFD status. */
*status = stream_getl(s);
- if (sp) {
- sp->family = stream_getc(s);
+ sp->family = stream_getc(s);
+
+ plen = prefix_blen(sp);
+ stream_get(&sp->u.prefix, s, plen);
+ sp->prefixlen = stream_getc(s);
- plen = prefix_blen(sp);
- stream_get(&sp->u.prefix, s, plen);
- sp->prefixlen = stream_getc(s);
- }
local_remote_cbit = stream_getc(s);
if (remote_cbit)
*remote_cbit = local_remote_cbit;
diff --git a/lib/filter_cli.c b/lib/filter_cli.c
index 54b6cda9a5..5d66a9fc73 100644
--- a/lib/filter_cli.c
+++ b/lib/filter_cli.c
@@ -259,7 +259,7 @@ DEFPY_YANG(
/* Access-list must exist before entries. */
if (yang_dnode_exists(running_config->dnode, xpath) == false)
- return CMD_WARNING;
+ return CMD_WARNING_CONFIG_FAILED;
/* Use access-list data structure to fetch sequence. */
dnode = yang_dnode_get(running_config->dnode, xpath);
@@ -268,7 +268,7 @@ DEFPY_YANG(
mask_str ? mask_str : CISCO_HOST_WILDCARD_MASK,
NULL, NULL);
if (sseq == -1)
- return CMD_WARNING;
+ return CMD_WARNING_CONFIG_FAILED;
snprintfrr(xpath_entry, sizeof(xpath_entry),
"%s/entry[sequence='%" PRId64 "']", xpath, sseq);
@@ -436,7 +436,7 @@ DEFPY_YANG(
/* Access-list must exist before entries. */
if (yang_dnode_exists(running_config->dnode, xpath) == false)
- return CMD_WARNING;
+ return CMD_WARNING_CONFIG_FAILED;
/* Use access-list data structure to fetch sequence. */
dnode = yang_dnode_get(running_config->dnode, xpath);
@@ -469,7 +469,7 @@ DEFPY_YANG(
"0.0.0.0", CISCO_ANY_WILDCARD_MASK);
}
if (sseq == -1)
- return CMD_WARNING;
+ return CMD_WARNING_CONFIG_FAILED;
snprintfrr(xpath_entry, sizeof(xpath_entry),
"%s/entry[sequence='%" PRId64 "']", xpath, sseq);
@@ -588,7 +588,7 @@ DEFPY_YANG(
/* Access-list must exist before entries. */
if (yang_dnode_exists(running_config->dnode, xpath) == false)
- return CMD_WARNING;
+ return CMD_WARNING_CONFIG_FAILED;
/* Use access-list data structure to fetch sequence. */
dnode = yang_dnode_get(running_config->dnode, xpath);
@@ -601,7 +601,7 @@ DEFPY_YANG(
sseq = acl_zebra_get_seq(acl, action, (struct prefix *)prefix,
exact);
if (sseq == -1)
- return CMD_WARNING;
+ return CMD_WARNING_CONFIG_FAILED;
snprintfrr(xpath_entry, sizeof(xpath_entry),
"%s/entry[sequence='%" PRId64 "']", xpath, sseq);
@@ -786,7 +786,7 @@ DEFPY_YANG(
/* Access-list must exist before entries. */
if (yang_dnode_exists(running_config->dnode, xpath) == false)
- return CMD_WARNING;
+ return CMD_WARNING_CONFIG_FAILED;
/* Use access-list data structure to fetch sequence. */
dnode = yang_dnode_get(running_config->dnode, xpath);
@@ -799,7 +799,7 @@ DEFPY_YANG(
sseq = acl_zebra_get_seq(acl, action, (struct prefix *)prefix,
exact);
if (sseq == -1)
- return CMD_WARNING;
+ return CMD_WARNING_CONFIG_FAILED;
snprintfrr(xpath_entry, sizeof(xpath_entry),
"%s/entry[sequence='%" PRId64 "']", xpath, sseq);
@@ -979,7 +979,7 @@ DEFPY_YANG(
/* Access-list must exist before entries. */
if (yang_dnode_exists(running_config->dnode, xpath) == false)
- return CMD_WARNING;
+ return CMD_WARNING_CONFIG_FAILED;
/* Use access-list data structure to fetch sequence. */
dnode = yang_dnode_get(running_config->dnode, xpath);
@@ -992,7 +992,7 @@ DEFPY_YANG(
sseq = acl_zebra_get_seq(acl, action, (struct prefix *)prefix,
false);
if (sseq == -1)
- return CMD_WARNING;
+ return CMD_WARNING_CONFIG_FAILED;
snprintfrr(xpath_entry, sizeof(xpath_entry),
"%s/entry[sequence='%" PRId64 "']", xpath, sseq);
@@ -1277,7 +1277,7 @@ static int plist_remove(struct vty *vty, const char *iptype, const char *name,
/* Access-list must exist before entries. */
if (yang_dnode_exists(running_config->dnode, xpath) == false)
- return CMD_WARNING;
+ return CMD_WARNING_CONFIG_FAILED;
/* Use access-list data structure to fetch sequence. */
assert(action != NULL);
@@ -1290,7 +1290,7 @@ static int plist_remove(struct vty *vty, const char *iptype, const char *name,
pl = nb_running_get_entry(dnode, NULL, true);
pentry = prefix_list_entry_lookup(pl, p, plt, -1, le, ge);
if (pentry == NULL)
- return CMD_WARNING;
+ return CMD_WARNING_CONFIG_FAILED;
snprintfrr(xpath_entry, sizeof(xpath_entry),
"%s/entry[sequence='%" PRId64 "']", xpath, pentry->seq);
diff --git a/lib/log.c b/lib/log.c
index 4054185019..0dace07ab7 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -179,6 +179,9 @@ void zlog_backtrace_sigsafe(int priority, void *program_counter)
unw_word_t ip, off, sp;
Dl_info dlinfo;
+ memset(&uc, 0, sizeof(uc));
+ memset(&cursor, 0, sizeof(cursor));
+
unw_getcontext(&uc);
unw_init_local(&cursor, &uc);
while (unw_step(&cursor) > 0) {
diff --git a/lib/vrf.c b/lib/vrf.c
index 1a9cd7e451..87744ea954 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -1064,6 +1064,7 @@ static int lib_vrf_create(struct nb_cb_create_args *args)
vrfp = vrf_get(VRF_UNKNOWN, vrfname);
+ vrf_set_user_cfged(vrfp);
nb_running_set_entry(args->dnode, vrfp);
return NB_OK;
@@ -1089,7 +1090,7 @@ static int lib_vrf_destroy(struct nb_cb_destroy_args *args)
vrfp = nb_running_unset_entry(args->dnode);
/* Clear configured flag and invoke delete. */
- UNSET_FLAG(vrfp->status, VRF_CONFIGURED);
+ vrf_reset_user_cfged(vrfp);
vrf_delete(vrfp);
break;
}
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
index 6fe3a289ce..2ecfd892cd 100644
--- a/ospf6d/ospf6_abr.c
+++ b/ospf6d/ospf6_abr.c
@@ -793,6 +793,10 @@ void ospf6_abr_old_route_remove(struct ospf6_lsa *lsa,
struct ospf6_route *old,
struct ospf6_route_table *table)
{
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_debug("%s: route %pFX, paths %d", __func__, &old->prefix,
+ listcount(old->paths));
+
if (listcount(old->paths) > 1) {
struct listnode *anode, *anext, *nnode, *rnode, *rnext;
struct ospf6_path *o_path;
@@ -802,13 +806,15 @@ void ospf6_abr_old_route_remove(struct ospf6_lsa *lsa,
for (ALL_LIST_ELEMENTS(old->paths, anode, anext, o_path)) {
if (o_path->origin.adv_router != lsa->header->adv_router
- && o_path->origin.id != lsa->header->id)
+ || o_path->origin.id != lsa->header->id)
continue;
for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
for (ALL_LIST_ELEMENTS(old->nh_list,
rnode, rnext, rnh)) {
if (!ospf6_nexthop_is_same(rnh, nh))
continue;
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_debug("deleted nexthop");
listnode_delete(old->nh_list, rnh);
ospf6_nexthop_delete(rnh);
}
@@ -875,14 +881,16 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
bool old_entry_updated = false;
struct ospf6_path *path, *o_path, *ecmp_path;
struct listnode *anode;
+ bool add_route = false;
memset(&prefix, 0, sizeof(prefix));
if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) {
if (IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX)) {
is_debug++;
- zlog_debug("%s: Examin %s in area %s", __func__,
- lsa->name, oa->name);
+ zlog_debug("%s: LSA %s age %d in area %s", __func__,
+ lsa->name, ospf6_lsa_age_current(lsa),
+ oa->name);
}
prefix_lsa =
@@ -901,8 +909,9 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
} else if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) {
if (IS_OSPF6_DEBUG_EXAMIN(INTER_ROUTER)) {
is_debug++;
- zlog_debug("%s: Examin %s in area %s", __func__,
- lsa->name, oa->name);
+ zlog_debug("%s: LSA %s age %d in area %s", __func__,
+ lsa->name, ospf6_lsa_age_current(lsa),
+ oa->name);
}
router_lsa =
@@ -926,8 +935,12 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
/* Find existing route */
route = ospf6_route_lookup(&prefix, table);
- if (route)
+ if (route) {
ospf6_route_lock(route);
+ if (is_debug)
+ zlog_debug("%s: route %pFX, paths %d", __func__,
+ &prefix, listcount(route->paths));
+ }
while (route && ospf6_route_is_prefix(&prefix, route)) {
if (route->path.area_id == oa->area_id
&& route->path.origin.type == lsa->header->type
@@ -980,6 +993,7 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
return;
}
+
/* (2) if the LSA is self-originated, ignore */
if (lsa->header->adv_router == oa->ospf6->router_id) {
if (is_debug)
@@ -1054,8 +1068,8 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
|| !CHECK_FLAG(abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B)) {
if (is_debug)
zlog_debug(
- "%s: ABR router entry does not exist, ignore",
- __func__);
+ "%s: ABR router entry %pFX does not exist, ignore",
+ __func__, &abr_prefix);
if (old) {
if (old->type == OSPF6_DEST_TYPE_ROUTER &&
oa->intra_brouter_calc) {
@@ -1068,7 +1082,7 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
zlog_debug(
"%s: remove old entry: %s %p ",
__func__, buf, (void *)old);
- ospf6_route_remove(old, table);
+ ospf6_abr_old_route_remove(lsa, old, table);
}
}
return;
@@ -1132,7 +1146,11 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
are identical.
*/
old = ospf6_route_lookup(&prefix, table);
-
+ if (old) {
+ if (is_debug)
+ zlog_debug("%s: found old route %pFX, paths %d",
+ __func__, &prefix, listcount(old->paths));
+ }
for (old_route = old; old_route; old_route = old_route->next) {
if (!ospf6_route_is_same(old_route, route) ||
(old_route->type != route->type) ||
@@ -1216,7 +1234,7 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
"%s: Update route: %s %p old cost %u new cost %u nh %u",
__func__, buf, (void *)old_route,
old_route->path.cost, route->path.cost,
- listcount(route->nh_list));
+ listcount(old_route->nh_list));
/* For Inter-Prefix route: Update RIB/FIB,
* For Inter-Router trigger summary update
@@ -1229,10 +1247,19 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
break;
}
+ /* If the old entry is not updated and old entry not found or old entry
+ * does not match with the new entry then add the new route
+ */
if (old_entry_updated == false) {
+ if ((old == NULL) || (old->type != route->type)
+ || (old->path.type != route->path.type))
+ add_route = true;
+ }
+
+ if (add_route) {
if (is_debug) {
zlog_debug(
- "%s: Install route: %s cost %u nh %u adv_router %pI4",
+ "%s: Install new route: %s cost %u nh %u adv_router %pI4",
__func__, buf, route->path.cost,
listcount(route->nh_list),
&route->path.origin.adv_router);
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 71ca5afcd2..8fcedc8198 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -206,7 +206,7 @@ static route_tag_t ospf6_as_external_lsa_get_tag(struct ospf6_lsa *lsa)
void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
struct ospf6_route *route)
{
- struct ospf6_route *old_route;
+ struct ospf6_route *old_route, *next_route;
struct ospf6_path *ecmp_path, *o_path = NULL;
struct listnode *anode, *anext;
struct listnode *nnode, *rnode, *rnext;
@@ -217,9 +217,11 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
/* check for old entry match with new route origin,
* delete old entry.
*/
- for (old_route = old; old_route; old_route = old_route->next) {
+ for (old_route = old; old_route; old_route = next_route) {
bool route_updated = false;
+ next_route = old_route->next;
+
if (!ospf6_route_is_same(old_route, route)
|| (old_route->path.type != route->path.type))
continue;
@@ -312,6 +314,8 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
old_route->path.cost,
route->path.cost);
}
+ if (old == old_route)
+ old = next_route;
ospf6_route_remove(old_route,
ospf6->route_table);
}
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index 2191ff46db..ab6a0f9639 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -1681,8 +1681,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 d07b04d90e..51d34773d7 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -76,7 +76,8 @@ static char *ospf6_router_lsa_get_nbr_id(struct ospf6_lsa *lsa, char *buf,
*)(start
+ pos * (sizeof(struct
ospf6_router_lsdesc)));
- if ((char *)lsdesc < end) {
+ if ((char *)lsdesc + sizeof(struct ospf6_router_lsdesc)
+ <= end) {
if (buf && (buflen > INET_ADDRSTRLEN * 2)) {
inet_ntop(AF_INET,
&lsdesc->neighbor_interface_id, buf1,
@@ -84,12 +85,13 @@ static char *ospf6_router_lsa_get_nbr_id(struct ospf6_lsa *lsa, char *buf,
inet_ntop(AF_INET, &lsdesc->neighbor_router_id,
buf2, sizeof(buf2));
sprintf(buf, "%s/%s", buf2, buf1);
+
+ return buf;
}
- } else
- return NULL;
+ }
}
- return buf;
+ return NULL;
}
static int ospf6_router_lsa_show(struct vty *vty, struct ospf6_lsa *lsa)
@@ -411,14 +413,15 @@ static char *ospf6_network_lsa_get_ar_id(struct ospf6_lsa *lsa, char *buf,
if ((current + sizeof(struct ospf6_network_lsdesc)) <= end) {
lsdesc = (struct ospf6_network_lsdesc *)current;
- if (buf)
+ if (buf) {
inet_ntop(AF_INET, &lsdesc->router_id, buf,
buflen);
- } else
- return NULL;
+ return buf;
+ }
+ }
}
- return (buf);
+ return NULL;
}
static int ospf6_network_lsa_show(struct vty *vty, struct ospf6_lsa *lsa)
@@ -602,7 +605,7 @@ static char *ospf6_link_lsa_get_prefix_str(struct ospf6_lsa *lsa, char *buf,
end = (char *)lsa->header + ntohs(lsa->header->length);
current = start;
- do {
+ while (current + sizeof(struct ospf6_prefix) <= end) {
prefix = (struct ospf6_prefix *)current;
if (prefix->prefix_length == 0
|| current + OSPF6_PREFIX_SIZE(prefix) > end) {
@@ -620,7 +623,7 @@ static char *ospf6_link_lsa_get_prefix_str(struct ospf6_lsa *lsa, char *buf,
inet_ntop(AF_INET6, &in6, buf, buflen);
return (buf);
}
- } while (current <= end);
+ }
}
return NULL;
}
@@ -803,7 +806,7 @@ static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
end = (char *)lsa->header + ntohs(lsa->header->length);
current = start;
- do {
+ while (current + sizeof(struct ospf6_prefix) <= end) {
prefix = (struct ospf6_prefix *)current;
if (prefix->prefix_length == 0
|| current + OSPF6_PREFIX_SIZE(prefix) > end) {
@@ -823,9 +826,9 @@ static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
prefix->prefix_length);
return (buf);
}
- } while (current <= end);
+ }
}
- return (buf);
+ return NULL;
}
static int ospf6_intra_prefix_lsa_show(struct vty *vty, struct ospf6_lsa *lsa)
@@ -1344,6 +1347,8 @@ static void ospf6_intra_prefix_update_route_origin(struct ospf6_route *oa_route)
g_route->path.origin.id = h_path->origin.id;
g_route->path.origin.adv_router =
h_path->origin.adv_router;
+ if (nroute)
+ ospf6_route_unlock(nroute);
break;
}
}
diff --git a/ospfd/ospf_bfd.c b/ospfd/ospf_bfd.c
index d2c5090f2f..cdc1d14feb 100644
--- a/ospfd/ospf_bfd.c
+++ b/ospfd/ospf_bfd.c
@@ -205,14 +205,14 @@ static int ospf_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS)
struct ospf_neighbor *nbr = NULL;
struct route_node *node;
struct route_node *n_node;
- struct prefix p;
+ struct prefix p, src_p;
int status;
int old_status;
struct bfd_info *bfd_info;
struct timeval tv;
- ifp = bfd_get_peer_info(zclient->ibuf, &p, NULL, &status,
- NULL, vrf_id);
+ ifp = bfd_get_peer_info(zclient->ibuf, &p, &src_p, &status, NULL,
+ vrf_id);
if ((ifp == NULL) || (p.family != AF_INET))
return 0;
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index 61aae695b3..12e6ab123a 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -2981,6 +2981,16 @@ static enum ospf_read_return_enum ospf_read_helper(struct ospf *ospf)
}
}
+ if (ospf->vrf_id == VRF_DEFAULT && ospf->vrf_id != ifp->vrf_id) {
+ /*
+ * We may have a situation where l3mdev_accept == 1
+ * let's just kindly drop the packet and move on.
+ * ospf really really really does not like when
+ * we receive the same packet multiple times.
+ */
+ return OSPF_READ_CONTINUE;
+ }
+
/* Self-originated packet should be discarded silently. */
if (ospf_if_lookup_by_local_addr(ospf, NULL, iph->ip_src)) {
if (IS_DEBUG_OSPF_PACKET(0, RECV)) {
diff --git a/pimd/pim_bfd.c b/pimd/pim_bfd.c
index 146b53fa8f..a103fc5f8d 100644
--- a/pimd/pim_bfd.c
+++ b/pimd/pim_bfd.c
@@ -217,7 +217,7 @@ static int pim_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS)
{
struct interface *ifp = NULL;
struct pim_interface *pim_ifp = NULL;
- struct prefix p;
+ struct prefix p, src_p;
int status;
char msg[100];
int old_status;
@@ -227,8 +227,8 @@ static int pim_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS)
struct listnode *neigh_nextnode = NULL;
struct pim_neighbor *neigh = NULL;
- ifp = bfd_get_peer_info(zclient->ibuf, &p, NULL, &status,
- NULL, vrf_id);
+ ifp = bfd_get_peer_info(zclient->ibuf, &p, &src_p, &status, NULL,
+ vrf_id);
if ((ifp == NULL) || (p.family != AF_INET))
return 0;
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index 212c77c039..7957b0799b 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -710,6 +710,21 @@ static int on_ifjoin_prune_pending_timer(struct thread *t)
pim_jp_agg_single_upstream_send(&parent->rpf,
parent, true);
+ /*
+ * SGRpt prune pending expiry has to install
+ * SG entry with empty olist to drop the SG
+ * traffic incase no other intf exists.
+ * On that scenario, SG entry wouldn't have
+ * got installed until Prune pending timer
+ * expired. So install now.
+ */
+ pim_channel_del_oif(
+ ch->upstream->channel_oil, ifp,
+ PIM_OIF_FLAG_PROTO_STAR, __func__);
+ if (!ch->upstream->channel_oil->installed)
+ pim_upstream_mroute_add(
+ ch->upstream->channel_oil,
+ __PRETTY_FUNCTION__);
}
}
/* from here ch may have been deleted */
@@ -1057,6 +1072,24 @@ void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream,
case PIM_IFJOIN_PRUNE:
if (source_flags & PIM_ENCODE_RPT_BIT) {
THREAD_OFF(ch->t_ifjoin_prune_pending_timer);
+ /*
+ * While in Prune State, Receive SGRpt Prune.
+ * RFC 7761 Sec 4.5.3:
+ * The (S,G,rpt) downstream state machine on interface I
+ * remains in Prune state. The Expiry Timer (ET) is
+ * restarted and is then set to the maximum of its
+ * current value and the HoldTime from the triggering
+ * Join/Prune message.
+ */
+ if (ch->t_ifjoin_expiry_timer) {
+ unsigned long rem = thread_timer_remain_second(
+ ch->t_ifjoin_expiry_timer);
+
+ if (rem > holdtime)
+ return;
+ THREAD_OFF(ch->t_ifjoin_expiry_timer);
+ }
+
thread_add_timer(router->master, on_ifjoin_expiry_timer,
ch, holdtime,
&ch->t_ifjoin_expiry_timer);
diff --git a/pimd/pim_instance.c b/pimd/pim_instance.c
index b7e49078ef..019048abf1 100644
--- a/pimd/pim_instance.c
+++ b/pimd/pim_instance.c
@@ -71,6 +71,8 @@ static void pim_instance_terminate(struct pim_instance *pim)
XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist);
XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
+
+ pim->vrf = NULL;
XFREE(MTYPE_PIM_PIM_INSTANCE, pim);
}
@@ -153,10 +155,16 @@ static int pim_vrf_delete(struct vrf *vrf)
{
struct pim_instance *pim = vrf->info;
+ if (!pim)
+ return 0;
+
zlog_debug("VRF Deletion: %s(%u)", vrf->name, vrf->vrf_id);
pim_ssmpingd_destroy(pim);
pim_instance_terminate(pim);
+
+ vrf->info = NULL;
+
return 0;
}
diff --git a/watchfrr/watchfrr.c b/watchfrr/watchfrr.c
index d1003ad5fa..34ef1a45a6 100644
--- a/watchfrr/watchfrr.c
+++ b/watchfrr/watchfrr.c
@@ -1082,6 +1082,9 @@ static int valid_command(const char *cmd)
{
char *p;
+ if (cmd == NULL)
+ return 0;
+
return ((p = strchr(cmd, '%')) != NULL) && (*(p + 1) == 's')
&& !strchr(p + 1, '%');
}
@@ -1416,7 +1419,7 @@ int main(int argc, char **argv)
} break;
case OPTION_NETNS:
netns_en = true;
- if (strchr(optarg, '/')) {
+ if (optarg && strchr(optarg, '/')) {
fprintf(stderr,
"invalid network namespace name \"%s\" (may not contain slashes)\n",
optarg);
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 9a9be3ac40..b4127ae1ec 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -102,6 +102,7 @@ static void zserv_encode_vrf(struct stream *s, struct zebra_vrf *zvrf)
struct vrf_data data;
const char *netns_name = zvrf_ns_name(zvrf);
+ memset(&data, 0, sizeof(data));
data.l.table_id = zvrf->table_id;
if (netns_name)
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index 3d92124b8d..cfc31eeca6 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -1754,6 +1754,10 @@ static bool nexthop_valid_resolve(const struct nexthop *nexthop,
if (!CHECK_FLAG(resolved->flags, NEXTHOP_FLAG_ACTIVE))
return false;
+ /* Must not be duplicate */
+ if (CHECK_FLAG(resolved->flags, NEXTHOP_FLAG_DUPLICATE))
+ return false;
+
switch (nexthop->type) {
case NEXTHOP_TYPE_IPV4_IFINDEX:
case NEXTHOP_TYPE_IPV6_IFINDEX: