diff options
| author | Donald Sharp <sharpd@cumulusnetworks.com> | 2021-02-17 06:53:12 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-02-17 06:53:12 -0500 |
| commit | e2f17ae47ad047e66923c2ff1e84c9ba10d4ad38 (patch) | |
| tree | c0d59f7da8dd36ed932e6380f78ff4ebdc575aa6 | |
| parent | 91b3c471f1c48818370a0f218add917f0d46aa47 (diff) | |
| parent | 380341362ced8e317c18b7395acb012de1f23acd (diff) | |
Merge pull request #8096 from idryzhov/7.5-backports-2021-02-16
7.5 backports
| -rw-r--r-- | bfdd/bfd.c | 160 | ||||
| -rw-r--r-- | bfdd/bfd_packet.c | 2 | ||||
| -rw-r--r-- | bfdd/ptm_adapter.c | 8 | ||||
| -rw-r--r-- | bgpd/bgp_bmp.c | 15 | ||||
| -rw-r--r-- | bgpd/bgp_bmp.h | 2 | ||||
| -rw-r--r-- | bgpd/bgp_packet.c | 1 | ||||
| -rw-r--r-- | bgpd/bgpd.h | 42 | ||||
| -rw-r--r-- | doc/user/bgp.rst | 26 | ||||
| -rw-r--r-- | docker/alpine/Dockerfile | 13 | ||||
| -rw-r--r-- | docker/centos-7/Dockerfile | 6 | ||||
| -rw-r--r-- | docker/centos-8/Dockerfile | 14 | ||||
| -rw-r--r-- | eigrpd/eigrp_interface.c | 18 | ||||
| -rw-r--r-- | eigrpd/eigrp_structs.h | 2 | ||||
| -rw-r--r-- | eigrpd/eigrp_topology.c | 1 | ||||
| -rw-r--r-- | isisd/isis_bfd.c | 6 | ||||
| -rw-r--r-- | lib/bfd.c | 22 | ||||
| -rw-r--r-- | lib/filter_cli.c | 24 | ||||
| -rw-r--r-- | lib/log.c | 3 | ||||
| -rw-r--r-- | lib/vrf.c | 3 | ||||
| -rw-r--r-- | ospf6d/ospf6_abr.c | 51 | ||||
| -rw-r--r-- | ospf6d/ospf6_asbr.c | 8 | ||||
| -rw-r--r-- | ospf6d/ospf6_interface.c | 7 | ||||
| -rw-r--r-- | ospf6d/ospf6_intra.c | 31 | ||||
| -rw-r--r-- | ospfd/ospf_bfd.c | 6 | ||||
| -rw-r--r-- | ospfd/ospf_packet.c | 10 | ||||
| -rw-r--r-- | pimd/pim_bfd.c | 6 | ||||
| -rw-r--r-- | pimd/pim_ifchannel.c | 33 | ||||
| -rw-r--r-- | pimd/pim_instance.c | 8 | ||||
| -rw-r--r-- | watchfrr/watchfrr.c | 5 | ||||
| -rw-r--r-- | zebra/zapi_msg.c | 1 | ||||
| -rw-r--r-- | zebra/zebra_nhg.c | 4 |
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; @@ -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); @@ -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) { @@ -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: |
