include $(TOPDIR)/rules.mk
PKG_NAME:=frr
-PKG_VERSION:=7.5.1
-PKG_RELEASE:=2
-PKG_SOURCE_DATE:=2021-08-26
+PKG_VERSION:=8.1.0
+PKG_RELEASE:=1
+PKG_SOURCE_DATE:=2021-11-12
PKG_SOURCE:=$(PKG_NAME)-$(PKG_SOURCE_DATE).tar.gz
-PKG_SOURCE_VERSION:=4cc14d346bdedc81a52b2981f9f568176513dc3e
+PKG_SOURCE_VERSION:=c18235d5b1e33fad9d3181aa29fefa48b8c6ff3f
PKG_SOURCE_URL:=https://codeload.github.com/FRRouting/frr/tar.gz/$(PKG_SOURCE_VERSION)?
-PKG_HASH:=dd0ec4616b85f5142c9e4ecc4a17b944000a3219bedf9d091484503e8c91e0e7
+PKG_HASH:=95922586d6c39565b3eec362563e031fd4cb2b6d6c0012256e345b364de1ae82
PKG_MAINTAINER:=Lucian Cristian <lucian.cristian@gmail.com>
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_SOURCE_VERSION)
nhrpd \
ospfd \
ospf6d \
+ pathd \
pbrd \
pimd \
ripd \
PKG_INSTALL:=1
PKG_BUILD_DEPENDS:=frr/host
-HOST_BUILD_DEPENDS:=python3/host
+HOST_BUILD_DEPENDS:=python3/host elfutils/host
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/host-build.mk
TITLE:= $(1) routing engine
DEPENDS+=frr-libfrr $(2)
endef
+# if [ "$(1)" == "bfdd" ]; then \
+# export HAVE_BFDD == 1 ; fi
define Package/frr-$(1)/install
$(INSTALL_DIR) $$(1)/usr/sbin
$(SED) 's/$$$$(MAKE) $$$$(AM_MAKEFLAGS) install-am/# $$$$(MAKE) $$$$(AM_MAKEFLAGS) install-am/' $(HOST_BUILD_DIR)/Makefile.in
endef
-#HOST_CPPFLAGS += -I$(STAGING_DIR_HOST)/include/libelf
+HOST_CPPFLAGS += -I$(STAGING_DIR_HOST)/include/libelf
HOST_CONFIGURE_ARGS+= \
--enable-clippy-only
--prefix=/usr \
--enable-shared \
--disable-static \
- --disable-pathd \
--enable-user=network \
--enable-group=network \
--disable-ospfclient \
$(INSTALL_CONF) ./files/{frr.conf,daemons} $(1)/etc/frr/
endef
+
define Package/frr-pythontools/install
$(INSTALL_DIR) $(1)/usr/lib/frr $(1)/usr/sbin $(1)/etc/frr
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/*.py $(1)/usr/lib/frr/
$(eval $(call BuildDaemon,nhrpd,+libcares))
$(eval $(call BuildDaemon,ospfd,))
$(eval $(call BuildDaemon,ospf6d,@IPV6))
+$(eval $(call BuildDaemon,pathd,))
$(eval $(call BuildDaemon,pbrd,))
$(eval $(call BuildDaemon,pimd,))
$(eval $(call BuildDaemon,ripd,))
eigrpd=no
babeld=no
sharpd=no
+pathd=no
pbrd=no
bfdd=no
fabricd=no
# - keep zebra first
# - watchfrr does NOT belong in this list
-DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pimd ldpd nhrpd eigrpd sharpd pbrd staticd bfdd fabricd vrrpd"
+DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pathd pimd ldpd nhrpd eigrpd sharpd pbrd staticd bfdd fabricd vrrpd"
RELOAD_SCRIPT="$D_PATH/frr-reload.py"
#
+++ /dev/null
-From fef2ed139d140f551cdfcbb21c5a023dea2e02cb Mon Sep 17 00:00:00 2001
-From: Philippe Guibert <philippe.guibert@6wind.com>
-Date: Thu, 26 Mar 2020 17:33:53 +0100
-Subject: [PATCH] nhrpd: cache config may disappear if iface not present at
- startup
-
-When interface not present at config time, store separately the list of
-config parameters. Then, when interface is ready and an address has been configured, the nbma setting is done. Reversely, when interface disappears,
-there is no need to keep the maps present, then keep only the configuration.
-
-Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
----
- nhrpd/nhrp_cache.c | 86 ++++++++++++++++++++++++++++++++++++++++++
- nhrpd/nhrp_interface.c | 63 ++++++++++++++++++++++++++++++-
- nhrpd/nhrp_vty.c | 49 ++++++++++++++++--------
- nhrpd/nhrpd.h | 14 +++++++
- 4 files changed, 195 insertions(+), 17 deletions(-)
-
---- a/nhrpd/nhrp_cache.c
-+++ b/nhrpd/nhrp_cache.c
-@@ -16,6 +16,7 @@
- #include "netlink.h"
-
- DEFINE_MTYPE_STATIC(NHRPD, NHRP_CACHE, "NHRP cache entry")
-+DEFINE_MTYPE_STATIC(NHRPD, NHRP_CACHE_CONFIG, "NHRP cache config entry")
-
- unsigned long nhrp_cache_counts[NHRP_CACHE_NUM_TYPES];
-
-@@ -77,6 +78,68 @@ static void nhrp_cache_free(struct nhrp_
- XFREE(MTYPE_NHRP_CACHE, c);
- }
-
-+static unsigned int nhrp_cache_config_protocol_key(const void *peer_data)
-+{
-+ const struct nhrp_cache_config *p = peer_data;
-+ return sockunion_hash(&p->remote_addr);
-+}
-+
-+static bool nhrp_cache_config_protocol_cmp(const void *cache_data,
-+ const void *key_data)
-+{
-+ const struct nhrp_cache_config *a = cache_data;
-+ const struct nhrp_cache_config *b = key_data;
-+
-+ if (!sockunion_same(&a->remote_addr, &b->remote_addr))
-+ return false;
-+ if (a->ifp != b->ifp)
-+ return false;
-+ return true;
-+}
-+
-+static void *nhrp_cache_config_alloc(void *data)
-+{
-+ struct nhrp_cache_config *p, *key = data;
-+
-+ p = XCALLOC(MTYPE_NHRP_CACHE_CONFIG, sizeof(struct nhrp_cache_config));
-+
-+ *p = (struct nhrp_cache_config){
-+ .remote_addr = key->remote_addr,
-+ .ifp = key->ifp,
-+ };
-+ return p;
-+}
-+
-+void nhrp_cache_config_free(struct nhrp_cache_config *c)
-+{
-+ struct nhrp_interface *nifp = c->ifp->info;
-+
-+ hash_release(nifp->cache_config_hash, c);
-+ XFREE(MTYPE_NHRP_CACHE_CONFIG, c);
-+}
-+
-+struct nhrp_cache_config *nhrp_cache_config_get(struct interface *ifp,
-+ union sockunion *remote_addr,
-+ int create)
-+{
-+ struct nhrp_interface *nifp = ifp->info;
-+ struct nhrp_cache_config key;
-+
-+ if (!nifp->cache_config_hash) {
-+ nifp->cache_config_hash =
-+ hash_create(nhrp_cache_config_protocol_key,
-+ nhrp_cache_config_protocol_cmp,
-+ "NHRP Config Cache");
-+ if (!nifp->cache_config_hash)
-+ return NULL;
-+ }
-+ key.remote_addr = *remote_addr;
-+ key.ifp = ifp;
-+
-+ return hash_get(nifp->cache_config_hash, &key,
-+ create ? nhrp_cache_config_alloc : NULL);
-+}
-+
- struct nhrp_cache *nhrp_cache_get(struct interface *ifp,
- union sockunion *remote_addr, int create)
- {
-@@ -423,12 +486,23 @@ struct nhrp_cache_iterator_ctx {
- void *ctx;
- };
-
-+struct nhrp_cache_config_iterator_ctx {
-+ void (*cb)(struct nhrp_cache_config *, void *);
-+ void *ctx;
-+};
-+
- static void nhrp_cache_iterator(struct hash_bucket *b, void *ctx)
- {
- struct nhrp_cache_iterator_ctx *ic = ctx;
- ic->cb(b->data, ic->ctx);
- }
-
-+static void nhrp_cache_config_iterator(struct hash_bucket *b, void *ctx)
-+{
-+ struct nhrp_cache_config_iterator_ctx *ic = ctx;
-+ ic->cb(b->data, ic->ctx);
-+}
-+
- void nhrp_cache_foreach(struct interface *ifp,
- void (*cb)(struct nhrp_cache *, void *), void *ctx)
- {
-@@ -441,6 +515,18 @@ void nhrp_cache_foreach(struct interface
- hash_iterate(nifp->cache_hash, nhrp_cache_iterator, &ic);
- }
-
-+void nhrp_cache_config_foreach(struct interface *ifp,
-+ void (*cb)(struct nhrp_cache_config *, void *), void *ctx)
-+{
-+ struct nhrp_interface *nifp = ifp->info;
-+ struct nhrp_cache_config_iterator_ctx ic = {
-+ .cb = cb, .ctx = ctx,
-+ };
-+
-+ if (nifp->cache_config_hash)
-+ hash_iterate(nifp->cache_config_hash, nhrp_cache_config_iterator, &ic);
-+}
-+
- void nhrp_cache_notify_add(struct nhrp_cache *c, struct notifier_block *n,
- notifier_fn_t fn)
- {
---- a/nhrpd/nhrp_interface.c
-+++ b/nhrpd/nhrp_interface.c
-@@ -23,6 +23,10 @@
-
- DEFINE_MTYPE_STATIC(NHRPD, NHRP_IF, "NHRP interface")
-
-+static void nhrp_interface_update_cache_config(struct interface *ifp,
-+ bool available,
-+ uint8_t family);
-+
- static int nhrp_if_new_hook(struct interface *ifp)
- {
- struct nhrp_interface *nifp;
-@@ -311,11 +315,68 @@ int nhrp_ifp_destroy(struct interface *i
- {
- debugf(NHRP_DEBUG_IF, "if-delete: %s", ifp->name);
-
-+ nhrp_interface_update_cache_config(ifp, false, AF_INET);
-+ nhrp_interface_update_cache_config(ifp, false, AF_INET6);
- nhrp_interface_update(ifp);
-
- return 0;
- }
-
-+struct map_ctx {
-+ int family;
-+ bool enabled;
-+};
-+
-+static void interface_config_update_nhrp_map(struct nhrp_cache_config *cc, void *data)
-+{
-+ struct map_ctx *ctx = data;
-+ struct interface *ifp = cc->ifp;
-+ struct nhrp_cache *c;
-+ union sockunion nbma_addr;
-+
-+ if (sockunion_family(&cc->remote_addr) != ctx->family)
-+ return;
-+
-+ /* gre layer not ready */
-+ if (ifp->vrf_id == VRF_UNKNOWN)
-+ return;
-+
-+ c = nhrp_cache_get(ifp, &cc->remote_addr, ctx->enabled ? 1 : 0);
-+ if (!c && !ctx->enabled)
-+ return;
-+ /* suppress */
-+ if (!ctx->enabled) {
-+ if (c && c->map) {
-+ nhrp_cache_update_binding(c, c->cur.type, -1,
-+ nhrp_peer_get(ifp, &nbma_addr), 0, NULL);
-+ }
-+ return;
-+ }
-+ /* create */
-+ c->map = 1;
-+ if (cc->type == NHRP_CACHE_LOCAL)
-+ nhrp_cache_update_binding(c, NHRP_CACHE_LOCAL, 0, NULL, 0,
-+ NULL);
-+ else {
-+ nhrp_cache_update_binding(c, NHRP_CACHE_STATIC, 0,
-+ nhrp_peer_get(ifp, &cc->nbma), 0,
-+ NULL);
-+ }
-+}
-+
-+static void nhrp_interface_update_cache_config(struct interface *ifp, bool available, uint8_t family)
-+{
-+ struct map_ctx mapctx;
-+
-+ mapctx = (struct map_ctx){
-+ .family = family,
-+ .enabled = available
-+ };
-+ nhrp_cache_config_foreach(ifp, interface_config_update_nhrp_map,
-+ &mapctx);
-+
-+}
-+
- int nhrp_ifp_up(struct interface *ifp)
- {
- debugf(NHRP_DEBUG_IF, "if-up: %s", ifp->name);
-@@ -346,7 +407,7 @@ int nhrp_interface_address_add(ZAPI_CALL
-
- nhrp_interface_update_address(
- ifc->ifp, family2afi(PREFIX_FAMILY(ifc->address)), 0);
--
-+ nhrp_interface_update_cache_config(ifc->ifp, true, PREFIX_FAMILY(ifc->address));
- return 0;
- }
-
---- a/nhrpd/nhrp_vty.c
-+++ b/nhrpd/nhrp_vty.c
-@@ -494,28 +494,42 @@ DEFUN(if_nhrp_map, if_nhrp_map_cmd,
- VTY_DECLVAR_CONTEXT(interface, ifp);
- afi_t afi = cmd_to_afi(argv[0]);
- union sockunion proto_addr, nbma_addr;
-+ struct nhrp_cache_config *cc;
- struct nhrp_cache *c;
-+ enum nhrp_cache_type type;
-
- if (str2sockunion(argv[3]->arg, &proto_addr) < 0
- || afi2family(afi) != sockunion_family(&proto_addr))
- return nhrp_vty_return(vty, NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH);
-
-+ if (strmatch(argv[4]->text, "local"))
-+ type = NHRP_CACHE_LOCAL;
-+ else {
-+ if (str2sockunion(argv[4]->arg, &nbma_addr) < 0)
-+ return nhrp_vty_return(vty, NHRP_ERR_FAIL);
-+ type = NHRP_CACHE_STATIC;
-+ }
-+ cc = nhrp_cache_config_get(ifp, &proto_addr, 1);
-+ if (!cc)
-+ return nhrp_vty_return(vty, NHRP_ERR_FAIL);
-+ cc->nbma = nbma_addr;
-+ cc->type = type;
-+ /* gre layer not ready */
-+ if (ifp->ifindex == IFINDEX_INTERNAL)
-+ return CMD_SUCCESS;
-+
- c = nhrp_cache_get(ifp, &proto_addr, 1);
- if (!c)
- return nhrp_vty_return(vty, NHRP_ERR_FAIL);
-
- c->map = 1;
-- if (strmatch(argv[4]->text, "local")) {
-+ if (type == NHRP_CACHE_LOCAL)
- nhrp_cache_update_binding(c, NHRP_CACHE_LOCAL, 0, NULL, 0,
- NULL);
-- } else {
-- if (str2sockunion(argv[4]->arg, &nbma_addr) < 0)
-- return nhrp_vty_return(vty, NHRP_ERR_FAIL);
-+ else
- nhrp_cache_update_binding(c, NHRP_CACHE_STATIC, 0,
- nhrp_peer_get(ifp, &nbma_addr), 0,
- NULL);
-- }
--
- return CMD_SUCCESS;
- }
-
-@@ -533,15 +547,22 @@ DEFUN(if_no_nhrp_map, if_no_nhrp_map_cmd
- VTY_DECLVAR_CONTEXT(interface, ifp);
- afi_t afi = cmd_to_afi(argv[1]);
- union sockunion proto_addr, nbma_addr;
-+ struct nhrp_cache_config *cc;
- struct nhrp_cache *c;
-
- if (str2sockunion(argv[4]->arg, &proto_addr) < 0
- || afi2family(afi) != sockunion_family(&proto_addr))
- return nhrp_vty_return(vty, NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH);
-
-+ cc = nhrp_cache_config_get(ifp, &proto_addr, 0);
-+ if (!cc)
-+ return nhrp_vty_return(vty, NHRP_ERR_FAIL);
-+ nhrp_cache_config_free(cc);
-+
- c = nhrp_cache_get(ifp, &proto_addr, 0);
-+ /* silently return */
- if (!c || !c->map)
-- return nhrp_vty_return(vty, NHRP_ERR_ENTRY_NOT_FOUND);
-+ return CMD_SUCCESS;
-
- nhrp_cache_update_binding(c, c->cur.type, -1,
- nhrp_peer_get(ifp, &nbma_addr), 0, NULL);
-@@ -997,23 +1018,19 @@ struct write_map_ctx {
- const char *aficmd;
- };
-
--static void interface_config_write_nhrp_map(struct nhrp_cache *c, void *data)
-+static void interface_config_write_nhrp_map(struct nhrp_cache_config *c, void *data)
- {
- struct write_map_ctx *ctx = data;
- struct vty *vty = ctx->vty;
- char buf[2][SU_ADDRSTRLEN];
-
-- if (!c->map)
-- return;
- if (sockunion_family(&c->remote_addr) != ctx->family)
- return;
-
- vty_out(vty, " %s nhrp map %s %s\n", ctx->aficmd,
- sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0])),
-- c->cur.type == NHRP_CACHE_LOCAL
-- ? "local"
-- : sockunion2str(&c->cur.peer->vc->remote.nbma, buf[1],
-- sizeof(buf[1])));
-+ c->type == NHRP_CACHE_LOCAL
-+ ? "local" : sockunion2str(&c->nbma, buf[1], sizeof(buf[1])));
- }
-
- static int interface_config_write(struct vty *vty)
-@@ -1076,8 +1093,8 @@ static int interface_config_write(struct
- .family = afi2family(afi),
- .aficmd = aficmd,
- };
-- nhrp_cache_foreach(ifp, interface_config_write_nhrp_map,
-- &mapctx);
-+ nhrp_cache_config_foreach(ifp, interface_config_write_nhrp_map,
-+ &mapctx);
-
- list_for_each_entry(nhs, &ad->nhslist_head,
- nhslist_entry)
---- a/nhrpd/nhrpd.h
-+++ b/nhrpd/nhrpd.h
-@@ -197,6 +197,13 @@ enum nhrp_cache_type {
- extern const char *const nhrp_cache_type_str[];
- extern unsigned long nhrp_cache_counts[NHRP_CACHE_NUM_TYPES];
-
-+struct nhrp_cache_config {
-+ struct interface *ifp;
-+ union sockunion remote_addr;
-+ enum nhrp_cache_type type;
-+ union sockunion nbma;
-+};
-+
- struct nhrp_cache {
- struct interface *ifp;
- union sockunion remote_addr;
-@@ -280,6 +287,7 @@ struct nhrp_interface {
- uint32_t grekey;
-
- struct hash *peer_hash;
-+ struct hash *cache_config_hash;
- struct hash *cache_hash;
-
- struct notifier_list notifier_list;
-@@ -358,10 +366,16 @@ void nhrp_shortcut_foreach(afi_t afi,
- void nhrp_shortcut_purge(struct nhrp_shortcut *s, int force);
- void nhrp_shortcut_prefix_change(const struct prefix *p, int deleted);
-
-+void nhrp_cache_config_free(struct nhrp_cache_config *c);
-+struct nhrp_cache_config *nhrp_cache_config_get(struct interface *ifp,
-+ union sockunion *remote_addr,
-+ int create);
- struct nhrp_cache *nhrp_cache_get(struct interface *ifp,
- union sockunion *remote_addr, int create);
- void nhrp_cache_foreach(struct interface *ifp,
- void (*cb)(struct nhrp_cache *, void *), void *ctx);
-+void nhrp_cache_config_foreach(struct interface *ifp,
-+ void (*cb)(struct nhrp_cache_config *, void *), void *ctx);
- void nhrp_cache_set_used(struct nhrp_cache *, int);
- int nhrp_cache_update_binding(struct nhrp_cache *, enum nhrp_cache_type type,
- int holding_time, struct nhrp_peer *p,
+++ /dev/null
-From e5773617afba7408c76ec2683814ce076c72c79d Mon Sep 17 00:00:00 2001
-From: Mark Stapp <mjs@voltanet.io>
-Date: Tue, 8 Dec 2020 09:10:10 -0500
-Subject: [PATCH] nhrpd: fix SA warning in nhrp_interface
-
-Clear SA warning from recent nhrp cache code changes.
-
-Signed-off-by: Mark Stapp <mjs@voltanet.io>
----
- nhrpd/nhrp_interface.c | 14 ++++++++++----
- 1 file changed, 10 insertions(+), 4 deletions(-)
-
---- a/nhrpd/nhrp_interface.c
-+++ b/nhrpd/nhrp_interface.c
-@@ -327,7 +327,8 @@ struct map_ctx {
- bool enabled;
- };
-
--static void interface_config_update_nhrp_map(struct nhrp_cache_config *cc, void *data)
-+static void interface_config_update_nhrp_map(struct nhrp_cache_config *cc,
-+ void *data)
- {
- struct map_ctx *ctx = data;
- struct interface *ifp = cc->ifp;
-@@ -344,15 +345,20 @@ static void interface_config_update_nhrp
- c = nhrp_cache_get(ifp, &cc->remote_addr, ctx->enabled ? 1 : 0);
- if (!c && !ctx->enabled)
- return;
-+
- /* suppress */
- if (!ctx->enabled) {
- if (c && c->map) {
-- nhrp_cache_update_binding(c, c->cur.type, -1,
-- nhrp_peer_get(ifp, &nbma_addr), 0, NULL);
-+ nhrp_cache_update_binding(
-+ c, c->cur.type, -1,
-+ nhrp_peer_get(ifp, &nbma_addr), 0, NULL);
- }
- return;
- }
-- /* create */
-+
-+ /* Newly created */
-+ assert(c != NULL);
-+
- c->map = 1;
- if (cc->type == NHRP_CACHE_LOCAL)
- nhrp_cache_update_binding(c, NHRP_CACHE_LOCAL, 0, NULL, 0,
+++ /dev/null
-From ee72f0a0eb93038ef6dfd01fed9f32e24c5de2a1 Mon Sep 17 00:00:00 2001
-From: Reuben Dowle <reuben.dowle@4rf.com>
-Date: Mon, 7 Dec 2020 16:35:13 +1300
-Subject: [PATCH] nhrpd: Cleanup resources when interface is deleted
-
-Currently when an interface is deleted from configuration, associated
-resources are not freed. This causes memory leaks and crashes.
-
-To reproduce this issue:
-* Connect to a DMVPN hub
-* Outside of frr, delete the underlying GRE interface
-* Use 'no interface xxx' to delete the interface containing nhrp configurations
-
-Signed-off-by: Reuben Dowle <reuben.dowle@4rf.com>
----
- nhrpd/nhrp_cache.c | 42 ++++++++++++++++++++++++++++++++++++++++--
- nhrpd/nhrp_interface.c | 15 +++++++++++++++
- nhrpd/nhrp_nhs.c | 18 ++++++++++++++++++
- nhrpd/nhrp_peer.c | 27 +++++++++++++++++++++++++++
- nhrpd/nhrpd.h | 3 +++
- 5 files changed, 103 insertions(+), 2 deletions(-)
- mode change 100644 => 100755 nhrpd/nhrp_cache.c
- mode change 100644 => 100755 nhrpd/nhrp_interface.c
- mode change 100644 => 100755 nhrpd/nhrpd.h
-
---- a/nhrpd/nhrp_cache.c
-+++ b/nhrpd/nhrp_cache.c
-@@ -69,12 +69,13 @@ static void nhrp_cache_free(struct nhrp_
- {
- struct nhrp_interface *nifp = c->ifp->info;
-
-- zassert(c->cur.type == NHRP_CACHE_INVALID && c->cur.peer == NULL);
-- zassert(c->new.type == NHRP_CACHE_INVALID && c->new.peer == NULL);
-+ debugf(NHRP_DEBUG_COMMON, "Deleting cache entry");
- nhrp_cache_counts[c->cur.type]--;
- notifier_call(&c->notifier_list, NOTIFY_CACHE_DELETE);
- zassert(!notifier_active(&c->notifier_list));
- hash_release(nifp->cache_hash, c);
-+ THREAD_OFF(c->t_timeout);
-+ THREAD_OFF(c->t_auth);
- XFREE(MTYPE_NHRP_CACHE, c);
- }
-
-@@ -140,6 +141,41 @@ struct nhrp_cache_config *nhrp_cache_con
- create ? nhrp_cache_config_alloc : NULL);
- }
-
-+static void do_nhrp_cache_free(struct hash_bucket *hb,
-+ void *arg __attribute__((__unused__)))
-+{
-+ struct nhrp_cache *c = hb->data;
-+
-+ nhrp_cache_free(c);
-+}
-+
-+static void do_nhrp_cache_config_free(struct hash_bucket *hb,
-+ void *arg __attribute__((__unused__)))
-+{
-+ struct nhrp_cache_config *cc = hb->data;
-+
-+ nhrp_cache_config_free(cc);
-+}
-+
-+void nhrp_cache_interface_del(struct interface *ifp)
-+{
-+ struct nhrp_interface *nifp = ifp->info;
-+
-+ debugf(NHRP_DEBUG_COMMON, "Cleaning up undeleted cache entries (%lu)",
-+ nifp->cache_hash ? nifp->cache_hash->count : 0);
-+
-+ if (nifp->cache_hash) {
-+ hash_iterate(nifp->cache_hash, do_nhrp_cache_free, NULL);
-+ hash_free(nifp->cache_hash);
-+ }
-+
-+ if (nifp->cache_config_hash) {
-+ hash_iterate(nifp->cache_config_hash, do_nhrp_cache_config_free,
-+ NULL);
-+ hash_free(nifp->cache_config_hash);
-+ }
-+}
-+
- struct nhrp_cache *nhrp_cache_get(struct interface *ifp,
- union sockunion *remote_addr, int create)
- {
-@@ -164,6 +200,7 @@ struct nhrp_cache *nhrp_cache_get(struct
- static int nhrp_cache_do_free(struct thread *t)
- {
- struct nhrp_cache *c = THREAD_ARG(t);
-+
- c->t_timeout = NULL;
- nhrp_cache_free(c);
- return 0;
-@@ -172,6 +209,7 @@ static int nhrp_cache_do_free(struct thr
- static int nhrp_cache_do_timeout(struct thread *t)
- {
- struct nhrp_cache *c = THREAD_ARG(t);
-+
- c->t_timeout = NULL;
- if (c->cur.type != NHRP_CACHE_INVALID)
- nhrp_cache_update_binding(c, c->cur.type, -1, NULL, 0, NULL);
---- a/nhrpd/nhrp_interface.c
-+++ b/nhrpd/nhrp_interface.c
-@@ -49,6 +49,21 @@ static int nhrp_if_new_hook(struct inter
-
- static int nhrp_if_delete_hook(struct interface *ifp)
- {
-+ struct nhrp_interface *nifp = ifp->info;
-+
-+ debugf(NHRP_DEBUG_IF, "Deleted interface (%s)", ifp->name);
-+
-+ nhrp_cache_interface_del(ifp);
-+ nhrp_nhs_interface_del(ifp);
-+ nhrp_peer_interface_del(ifp);
-+
-+ if (nifp->ipsec_profile)
-+ free(nifp->ipsec_profile);
-+ if (nifp->ipsec_fallback_profile)
-+ free(nifp->ipsec_fallback_profile);
-+ if (nifp->source)
-+ free(nifp->source);
-+
- XFREE(MTYPE_NHRP_IF, ifp->info);
- return 0;
- }
---- a/nhrpd/nhrp_nhs.c
-+++ b/nhrpd/nhrp_nhs.c
-@@ -378,6 +378,24 @@ int nhrp_nhs_free(struct nhrp_nhs *nhs)
- return 0;
- }
-
-+void nhrp_nhs_interface_del(struct interface *ifp)
-+{
-+ struct nhrp_interface *nifp = ifp->info;
-+ struct nhrp_nhs *nhs, *tmp;
-+ afi_t afi;
-+
-+ for (afi = 0; afi < AFI_MAX; afi++) {
-+ debugf(NHRP_DEBUG_COMMON, "Cleaning up nhs entries (%d)",
-+ !list_empty(&nifp->afi[afi].nhslist_head));
-+
-+ list_for_each_entry_safe(nhs, tmp, &nifp->afi[afi].nhslist_head,
-+ nhslist_entry)
-+ {
-+ nhrp_nhs_free(nhs);
-+ }
-+ }
-+}
-+
- void nhrp_nhs_terminate(void)
- {
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
---- a/nhrpd/nhrp_peer.c
-+++ b/nhrpd/nhrp_peer.c
-@@ -38,11 +38,17 @@ static void nhrp_packet_debug(struct zbu
-
- static void nhrp_peer_check_delete(struct nhrp_peer *p)
- {
-+ char buf[2][256];
- struct nhrp_interface *nifp = p->ifp->info;
-
- if (p->ref || notifier_active(&p->notifier_list))
- return;
-
-+ debugf(NHRP_DEBUG_COMMON, "Deleting peer ref:%d remote:%s local:%s",
-+ p->ref,
-+ sockunion2str(&p->vc->remote.nbma, buf[0], sizeof(buf[0])),
-+ sockunion2str(&p->vc->local.nbma, buf[1], sizeof(buf[1])));
-+
- THREAD_OFF(p->t_fallback);
- hash_release(nifp->peer_hash, p);
- nhrp_interface_notify_del(p->ifp, &p->ifp_notifier);
-@@ -185,6 +191,27 @@ static void *nhrp_peer_create(void *data
- return p;
- }
-
-+static void do_peer_hash_free(struct hash_bucket *hb,
-+ void *arg __attribute__((__unused__)))
-+{
-+ struct nhrp_peer *p = hb->data;
-+ nhrp_peer_check_delete(p);
-+}
-+
-+void nhrp_peer_interface_del(struct interface *ifp)
-+{
-+ struct nhrp_interface *nifp = ifp->info;
-+
-+ debugf(NHRP_DEBUG_COMMON, "Cleaning up undeleted peer entries (%lu)",
-+ nifp->peer_hash ? nifp->peer_hash->count : 0);
-+
-+ if (nifp->peer_hash) {
-+ hash_iterate(nifp->peer_hash, do_peer_hash_free, NULL);
-+ assert(nifp->peer_hash->count == 0);
-+ hash_free(nifp->peer_hash);
-+ }
-+}
-+
- struct nhrp_peer *nhrp_peer_get(struct interface *ifp,
- const union sockunion *remote_nbma)
- {
---- a/nhrpd/nhrpd.h
-+++ b/nhrpd/nhrpd.h
-@@ -343,6 +343,7 @@ void nhrp_nhs_foreach(struct interface *
- void (*cb)(struct nhrp_nhs *, struct nhrp_registration *,
- void *),
- void *ctx);
-+void nhrp_nhs_interface_del(struct interface *ifp);
-
- void nhrp_route_update_nhrp(const struct prefix *p, struct interface *ifp);
- void nhrp_route_announce(int add, enum nhrp_cache_type type,
-@@ -366,6 +367,7 @@ void nhrp_shortcut_foreach(afi_t afi,
- void nhrp_shortcut_purge(struct nhrp_shortcut *s, int force);
- void nhrp_shortcut_prefix_change(const struct prefix *p, int deleted);
-
-+void nhrp_cache_interface_del(struct interface *ifp);
- void nhrp_cache_config_free(struct nhrp_cache_config *c);
- struct nhrp_cache_config *nhrp_cache_config_get(struct interface *ifp,
- union sockunion *remote_addr,
-@@ -446,6 +448,7 @@ struct nhrp_reqid *nhrp_reqid_lookup(str
-
- int nhrp_packet_init(void);
-
-+void nhrp_peer_interface_del(struct interface *ifp);
- struct nhrp_peer *nhrp_peer_get(struct interface *ifp,
- const union sockunion *remote_nbma);
- struct nhrp_peer *nhrp_peer_ref(struct nhrp_peer *p);
+++ /dev/null
-From f91ce319d3cdb465df54ff4e091dbd4aed85b24c Mon Sep 17 00:00:00 2001
-From: Mobashshera Rasool <mrasool@vmware.com>
-Date: Wed, 23 Dec 2020 13:20:22 +0000
-Subject: [PATCH] ospfd: Clear ip ospf process and clear ip ospf neighbor
-
-Implement the below 2 CLIs to clear the current data in the process
-and neighbor data structure.
-1. clear ip ospf process
-2. clear ip ospf neighbor
-
-Signed-off-by: Mobashshera Rasool <mrasool@vmware.com>
----
- doc/user/ospfd.rst | 17 ++++++++
- ospfd/ospf_ase.c | 1 +
- ospfd/ospf_lsa.c | 13 +++++-
- ospfd/ospf_vty.c | 72 +++++++++++++++++++++++++++++++--
- ospfd/ospfd.c | 99 ++++++++++++++++++++++++++++++++++++----------
- ospfd/ospfd.h | 5 +++
- 6 files changed, 182 insertions(+), 25 deletions(-)
-
---- a/doc/user/ospfd.rst
-+++ b/doc/user/ospfd.rst
-@@ -322,6 +322,23 @@ To start OSPF process you have to specif
-
- This feature is enabled by default.
-
-+.. index:: clear ip ospf [(1-65535)] process
-+.. clicmd:: clear ip ospf [(1-65535)] process
-+
-+ This command can be used to clear the ospf process data structures. This
-+ will clear the ospf neighborship as well and it will get re-established.
-+ This will clear the LSDB too. This will be helpful when there is a change
-+ in router-id and if user wants the router-id change to take effect, user can
-+ use this cli instead of restarting the ospfd daemon.
-+
-+.. index:: clear ip ospf [(1-65535)] neighbor
-+.. clicmd:: clear ip ospf [(1-65535)] neighbor
-+
-+ This command can be used to clear the ospf neighbor data structures. This
-+ will clear the ospf neighborship and it will get re-established. This
-+ command can be used when the neighbor state get stuck at some state and
-+ this can be used to recover it from that state.
-+
- .. _ospf-area:
-
- Areas
---- a/ospfd/ospf_ase.c
-+++ b/ospfd/ospf_ase.c
-@@ -753,6 +753,7 @@ void ospf_ase_unregister_external_lsa(st
- lst = rn->info;
- listnode_delete(lst, lsa);
- ospf_lsa_unlock(&lsa); /* external_lsas list */
-+
- route_unlock_node(rn);
- }
- }
---- a/ospfd/ospf_lsa.c
-+++ b/ospfd/ospf_lsa.c
-@@ -2735,7 +2735,7 @@ int ospf_check_nbr_status(struct ospf *o
- static int ospf_maxage_lsa_remover(struct thread *thread)
- {
- struct ospf *ospf = THREAD_ARG(thread);
-- struct ospf_lsa *lsa;
-+ struct ospf_lsa *lsa, *old;
- struct route_node *rn;
- int reschedule = 0;
-
-@@ -2797,6 +2797,17 @@ static int ospf_maxage_lsa_remover(struc
-
- /* Remove from lsdb. */
- if (lsa->lsdb) {
-+ old = ospf_lsdb_lookup(lsa->lsdb, lsa);
-+ /* The max age LSA here must be the same
-+ * as the LSA in LSDB
-+ */
-+ if (old != lsa) {
-+ flog_err(EC_OSPF_LSA_MISSING,
-+ "%s: LSA[Type%d:%s]: LSA not in LSDB",
-+ __func__, lsa->data->type,
-+ inet_ntoa(lsa->data->id));
-+ continue;
-+ }
- ospf_discard_from_db(ospf, lsa->lsdb, lsa);
- ospf_lsdb_delete(lsa->lsdb, lsa);
- } else {
---- a/ospfd/ospf_vty.c
-+++ b/ospfd/ospf_vty.c
-@@ -276,7 +276,7 @@ DEFPY (ospf_router_id,
- for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area))
- if (area->full_nbrs) {
- vty_out(vty,
-- "For this router-id change to take effect, save config and restart ospfd\n");
-+ "For this router-id change to take effect, use “clear ip ospf process” command\n");
- return CMD_SUCCESS;
- }
-
-@@ -309,7 +309,7 @@ DEFUN_HIDDEN (ospf_router_id_old,
- for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area))
- if (area->full_nbrs) {
- vty_out(vty,
-- "For this router-id change to take effect, save config and restart ospfd\n");
-+ "For this router-id change to take effect, use “clear ip ospf process” command\n");
- return CMD_SUCCESS;
- }
-
-@@ -342,7 +342,7 @@ DEFPY (no_ospf_router_id,
- for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area))
- if (area->full_nbrs) {
- vty_out(vty,
-- "For this router-id change to take effect, save config and restart ospfd\n");
-+ "For this router-id change to take effect, use “clear ip ospf process” command\n");
- return CMD_SUCCESS;
- }
-
-@@ -9769,6 +9769,70 @@ DEFUN (show_ip_ospf_vrfs,
-
- return CMD_SUCCESS;
- }
-+DEFPY (clear_ip_ospf_neighbor,
-+ clear_ip_ospf_neighbor_cmd,
-+ "clear ip ospf [(1-65535)]$instance neighbor [A.B.C.D$nbr_id]",
-+ CLEAR_STR
-+ IP_STR
-+ "OSPF information\n"
-+ "Instance ID\n"
-+ "Reset OSPF Neighbor\n"
-+ "Neighbor ID\n")
-+{
-+ struct listnode *node;
-+ struct ospf *ospf = NULL;
-+
-+ /* If user does not specify the arguments,
-+ * instance = 0 and nbr_id = 0.0.0.0
-+ */
-+ if (instance != 0) {
-+ /* This means clear only the particular ospf process */
-+ ospf = ospf_lookup_instance(instance);
-+ if (ospf == NULL)
-+ return CMD_NOT_MY_INSTANCE;
-+ }
-+
-+ /* Clear all the ospf processes */
-+ for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) {
-+ if (!ospf->oi_running)
-+ continue;
-+
-+ ospf_neighbor_reset(ospf, nbr_id, nbr_id_str);
-+ }
-+
-+ return CMD_SUCCESS;
-+}
-+
-+DEFPY (clear_ip_ospf_process,
-+ clear_ip_ospf_process_cmd,
-+ "clear ip ospf [(1-65535)]$instance process",
-+ CLEAR_STR
-+ IP_STR
-+ "OSPF information\n"
-+ "Instance ID\n"
-+ "Reset OSPF Process\n")
-+{
-+ struct listnode *node;
-+ struct ospf *ospf = NULL;
-+
-+ /* Check if instance is not passed as an argument */
-+ if (instance != 0) {
-+ /* This means clear only the particular ospf process */
-+ ospf = ospf_lookup_instance(instance);
-+ if (ospf == NULL)
-+ return CMD_NOT_MY_INSTANCE;
-+ }
-+
-+ /* Clear all the ospf processes */
-+ for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) {
-+ if (!ospf->oi_running)
-+ continue;
-+
-+ ospf_process_reset(ospf);
-+ }
-+
-+ return CMD_SUCCESS;
-+}
-
- static const char *const ospf_abr_type_str[] = {
- "unknown", "standard", "ibm", "cisco", "shortcut"
-@@ -10806,6 +10870,8 @@ DEFUN (clear_ip_ospf_interface,
- void ospf_vty_clear_init(void)
- {
- install_element(ENABLE_NODE, &clear_ip_ospf_interface_cmd);
-+ install_element(ENABLE_NODE, &clear_ip_ospf_process_cmd);
-+ install_element(ENABLE_NODE, &clear_ip_ospf_neighbor_cmd);
- }
-
-
---- a/ospfd/ospfd.c
-+++ b/ospfd/ospfd.c
-@@ -84,13 +84,15 @@ static void ospf_finish_final(struct osp
-
- #define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1
-
--void ospf_router_id_update(struct ospf *ospf)
-+void ospf_process_refresh_data(struct ospf *ospf, bool reset)
- {
- struct vrf *vrf = vrf_lookup_by_id(ospf->vrf_id);
- struct in_addr router_id, router_id_old;
- struct ospf_interface *oi;
- struct interface *ifp;
-- struct listnode *node;
-+ struct listnode *node, *nnode;
-+ struct ospf_area *area;
-+ bool rid_change = false;
-
- if (!ospf->oi_running) {
- if (IS_DEBUG_OSPF_EVENT)
-@@ -123,8 +125,8 @@ void ospf_router_id_update(struct ospf *
- zlog_debug("Router-ID[OLD:%s]: Update to %s",
- inet_ntoa(ospf->router_id), inet_ntoa(router_id));
-
-- if (!IPV4_ADDR_SAME(&router_id_old, &router_id)) {
--
-+ rid_change = !(IPV4_ADDR_SAME(&router_id_old, &router_id));
-+ if (rid_change || (reset)) {
- for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
- /* Some nbrs are identified by router_id, these needs
- * to be rebuilt. Possible optimization would be to do
-@@ -146,16 +148,8 @@ void ospf_router_id_update(struct ospf *
- ospf_if_up(oi);
- }
-
-- /* Flush (inline) all external LSAs based on the OSPF_LSA_SELF
-- * flag */
-- if (ospf->lsdb) {
-- struct route_node *rn;
-- struct ospf_lsa *lsa;
--
-- LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa)
-- if (IS_LSA_SELF(lsa))
-- ospf_lsa_flush_schedule(ospf, lsa);
-- }
-+ /* Flush (inline) all the self originated LSAs */
-+ ospf_flush_self_originated_lsas_now(ospf);
-
- ospf->router_id = router_id;
- if (IS_DEBUG_OSPF_EVENT)
-@@ -180,24 +174,81 @@ void ospf_router_id_update(struct ospf *
- LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa) {
- /* AdvRouter and Router ID is the same. */
- if (IPV4_ADDR_SAME(&lsa->data->adv_router,
-- &ospf->router_id)) {
-+ &ospf->router_id) && rid_change) {
- SET_FLAG(lsa->flags,
- OSPF_LSA_SELF_CHECKED);
- SET_FLAG(lsa->flags, OSPF_LSA_SELF);
- ospf_lsa_flush_schedule(ospf, lsa);
- }
-+ /* The above flush will send immediately
-+ * So discard the LSA to originate new
-+ */
-+ ospf_discard_from_db(ospf, ospf->lsdb, lsa);
- }
-+
-+ LSDB_LOOP (OPAQUE_AS_LSDB(ospf), rn, lsa)
-+ ospf_discard_from_db(ospf, ospf->lsdb, lsa);
-+
-+ ospf_lsdb_delete_all(ospf->lsdb);
- }
-
-+ /* Delete the LSDB */
-+ for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
-+ ospf_area_lsdb_discard_delete(area);
-+
- /* update router-lsa's for each area */
- ospf_router_lsa_update(ospf);
-
- /* update ospf_interface's */
-- FOR_ALL_INTERFACES (vrf, ifp)
-- ospf_if_update(ospf, ifp);
-+ FOR_ALL_INTERFACES (vrf, ifp) {
-+ if (reset)
-+ ospf_if_reset(ifp);
-+ else
-+ ospf_if_update(ospf, ifp);
-+ }
-
- ospf_external_lsa_rid_change(ospf);
- }
-+
-+ ospf->inst_shutdown = 0;
-+}
-+
-+void ospf_router_id_update(struct ospf *ospf)
-+{
-+ ospf_process_refresh_data(ospf, false);
-+}
-+
-+void ospf_process_reset(struct ospf *ospf)
-+{
-+ ospf_process_refresh_data(ospf, true);
-+}
-+
-+void ospf_neighbor_reset(struct ospf *ospf, struct in_addr nbr_id,
-+ const char *nbr_str)
-+{
-+ struct route_node *rn;
-+ struct ospf_neighbor *nbr;
-+ struct ospf_interface *oi;
-+ struct listnode *node;
-+
-+ /* Clear only a particular nbr with nbr router id as nbr_id */
-+ if (nbr_str != NULL) {
-+ for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
-+ nbr = ospf_nbr_lookup_by_routerid(oi->nbrs, &nbr_id);
-+ if (nbr)
-+ OSPF_NSM_EVENT_EXECUTE(nbr, NSM_KillNbr);
-+ }
-+ return;
-+ }
-+
-+ /* send Neighbor event KillNbr to all associated neighbors. */
-+ for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
-+ for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
-+ nbr = rn->info;
-+ if (nbr && (nbr != oi->nbr_self))
-+ OSPF_NSM_EVENT_EXECUTE(nbr, NSM_KillNbr);
-+ }
-+ }
- }
-
- /* For OSPF area sort by area id. */
-@@ -826,14 +877,11 @@ static struct ospf_area *ospf_area_new(s
- return new;
- }
-
--static void ospf_area_free(struct ospf_area *area)
-+void ospf_area_lsdb_discard_delete(struct ospf_area *area)
- {
- struct route_node *rn;
- struct ospf_lsa *lsa;
-
-- ospf_opaque_type10_lsa_term(area);
--
-- /* Free LSDBs. */
- LSDB_LOOP (ROUTER_LSDB(area), rn, lsa)
- ospf_discard_from_db(area->ospf, area->lsdb, lsa);
- LSDB_LOOP (NETWORK_LSDB(area), rn, lsa)
-@@ -851,6 +899,15 @@ static void ospf_area_free(struct ospf_a
- ospf_discard_from_db(area->ospf, area->lsdb, lsa);
-
- ospf_lsdb_delete_all(area->lsdb);
-+}
-+
-+static void ospf_area_free(struct ospf_area *area)
-+{
-+ ospf_opaque_type10_lsa_term(area);
-+
-+ /* Free LSDBs. */
-+ ospf_area_lsdb_discard_delete(area);
-+
- ospf_lsdb_free(area->lsdb);
-
- ospf_lsa_unlock(&area->router_lsa_self);
---- a/ospfd/ospfd.h
-+++ b/ospfd/ospfd.h
-@@ -519,7 +519,11 @@ extern struct ospf *ospf_lookup_by_inst_
- extern struct ospf *ospf_lookup_by_vrf_id(vrf_id_t vrf_id);
- extern uint32_t ospf_count_area_params(struct ospf *ospf);
- extern void ospf_finish(struct ospf *);
-+extern void ospf_process_refresh_data(struct ospf *ospf, bool reset);
- extern void ospf_router_id_update(struct ospf *ospf);
-+extern void ospf_process_reset(struct ospf *ospf);
-+extern void ospf_neighbor_reset(struct ospf *ospf, struct in_addr nbr_id,
-+ const char *nbr_str);
- extern int ospf_network_set(struct ospf *, struct prefix_ipv4 *, struct in_addr,
- int);
- extern int ospf_network_unset(struct ospf *, struct prefix_ipv4 *,
-@@ -544,6 +548,7 @@ extern int ospf_area_shortcut_set(struct
- extern int ospf_area_shortcut_unset(struct ospf *, struct ospf_area *);
- extern int ospf_timers_refresh_set(struct ospf *, int);
- extern int ospf_timers_refresh_unset(struct ospf *);
-+void ospf_area_lsdb_discard_delete(struct ospf_area *area);
- extern int ospf_nbr_nbma_set(struct ospf *, struct in_addr);
- extern int ospf_nbr_nbma_unset(struct ospf *, struct in_addr);
- extern int ospf_nbr_nbma_priority_set(struct ospf *, struct in_addr, uint8_t);
+++ /dev/null
-From 153bdb3d03542530ed1deccbefc716cb4b699a67 Mon Sep 17 00:00:00 2001
-From: Donald Sharp <sharpd@nvidia.com>
-Date: Thu, 28 Jan 2021 14:56:11 -0500
-Subject: [PATCH] ospfd: ospf_nbr_nbma_lookup_next always returns NULL
-
-The calling function of ospf_nbr_nbma_lookup_next calls
-this function and then immediately returns when it
-gets the NULL. Just cleanup a bit more code.
-
-Signed-off-by: Donald Sharp <sharpd@nvidia.com>
----
- ospfd/ospf_snmp.c | 23 +----------------------
- ospfd/ospfd.c | 9 ---------
- ospfd/ospfd.h | 2 --
- 3 files changed, 1 insertion(+), 33 deletions(-)
-
---- a/ospfd/ospf_snmp.c
-+++ b/ospfd/ospf_snmp.c
-@@ -1236,7 +1236,6 @@ static struct ospf_nbr_nbma *ospfHostLoo
- size_t *length,
- struct in_addr *addr, int exact)
- {
-- int len;
- struct ospf_nbr_nbma *nbr_nbma;
- struct ospf *ospf;
-
-@@ -1258,28 +1257,8 @@ static struct ospf_nbr_nbma *ospfHostLoo
- nbr_nbma = ospf_nbr_nbma_lookup(ospf, *addr);
-
- return nbr_nbma;
-- } else {
-- len = *length - v->namelen;
-- if (len > 4)
-- len = 4;
--
-- oid2in_addr(name + v->namelen, len, addr);
--
-- nbr_nbma =
-- ospf_nbr_nbma_lookup_next(ospf, addr, len == 0 ? 1 : 0);
--
-- if (nbr_nbma == NULL)
-- return NULL;
--
-- oid_copy_addr(name + v->namelen, addr, IN_ADDR_SIZE);
--
-- /* Set TOS 0. */
-- name[v->namelen + IN_ADDR_SIZE] = 0;
--
-- *length = v->namelen + IN_ADDR_SIZE + 1;
--
-- return nbr_nbma;
- }
-+
- return NULL;
- }
-
---- a/ospfd/ospfd.c
-+++ b/ospfd/ospfd.c
-@@ -1919,35 +1919,6 @@ struct ospf_nbr_nbma *ospf_nbr_nbma_look
- return NULL;
- }
-
--struct ospf_nbr_nbma *ospf_nbr_nbma_lookup_next(struct ospf *ospf,
-- struct in_addr *addr, int first)
--{
--#if 0
-- struct ospf_nbr_nbma *nbr_nbma;
-- struct listnode *node;
--#endif
--
-- if (ospf == NULL)
-- return NULL;
--
--#if 0
-- for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma))
-- {
-- if (first)
-- {
-- *addr = nbr_nbma->addr;
-- return nbr_nbma;
-- }
-- else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
-- {
-- *addr = nbr_nbma->addr;
-- return nbr_nbma;
-- }
-- }
--#endif
-- return NULL;
--}
--
- int ospf_nbr_nbma_set(struct ospf *ospf, struct in_addr nbr_addr)
- {
- struct ospf_nbr_nbma *nbr_nbma;
---- a/ospfd/ospfd.h
-+++ b/ospfd/ospfd.h
-@@ -563,8 +563,6 @@ extern void ospf_terminate(void);
- extern void ospf_nbr_nbma_if_update(struct ospf *, struct ospf_interface *);
- extern struct ospf_nbr_nbma *ospf_nbr_nbma_lookup(struct ospf *,
- struct in_addr);
--extern struct ospf_nbr_nbma *ospf_nbr_nbma_lookup_next(struct ospf *,
-- struct in_addr *, int);
- extern int ospf_oi_count(struct interface *);
-
- extern struct ospf_area *ospf_area_get(struct ospf *, struct in_addr);
+++ /dev/null
-From 409f98ab443682ec360e3e76954f1c8985b3371d Mon Sep 17 00:00:00 2001
-From: Igor Ryzhov <iryzhov@nfware.com>
-Date: Thu, 28 Jan 2021 02:41:07 +0300
-Subject: [PATCH 1/2] ospfd: don't rely on instance existence in vty
-
-Store instance index at startup and use it when processing vty commands.
-The instance itself may be created and deleted by the user in runtime
-using `[no] router ospf X` command.
-
-Fixes #7908
-
-Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
----
- ospfd/ospf_dump.c | 70 ++++++---------
- ospfd/ospf_main.c | 20 +----
- ospfd/ospf_vty.c | 220 +++++++++++++++++++++++-----------------------
- ospfd/ospfd.c | 26 +++---
- ospfd/ospfd.h | 3 +-
- 5 files changed, 154 insertions(+), 185 deletions(-)
-
---- a/ospfd/ospf_dump.c
-+++ b/ospfd/ospf_dump.c
-@@ -607,7 +607,7 @@ DEFUN (debug_ospf_packet,
-
- if (inst) // user passed instance ID
- {
-- if (!ospf_lookup_instance(strtoul(argv[2]->arg, NULL, 10)))
-+ if (inst != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
- }
-
-@@ -683,7 +683,7 @@ DEFUN (no_debug_ospf_packet,
-
- if (inst) // user passed instance ID
- {
-- if (!ospf_lookup_instance(strtoul(argv[3]->arg, NULL, 10)))
-+ if (inst != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
- }
-
-@@ -754,7 +754,7 @@ DEFUN (debug_ospf_ism,
-
- if (inst) // user passed instance ID
- {
-- if (!ospf_lookup_instance(strtoul(argv[2]->arg, NULL, 10)))
-+ if (inst != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
- }
-
-@@ -805,7 +805,7 @@ DEFUN (no_debug_ospf_ism,
-
- if (inst) // user passed instance ID
- {
-- if (!ospf_lookup_instance(strtoul(argv[3]->arg, NULL, 10)))
-+ if (inst != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
- }
-
-@@ -900,8 +900,8 @@ DEFUN (debug_ospf_instance_nsm,
- unsigned short instance = 0;
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
-- if (!ospf_lookup_instance(instance))
-- return CMD_SUCCESS;
-+ if (instance != ospf_instance)
-+ return CMD_NOT_MY_INSTANCE;
-
- return debug_ospf_nsm_common(vty, 4, argc, argv);
- }
-@@ -972,7 +972,7 @@ DEFUN (no_debug_ospf_instance_nsm,
- unsigned short instance = 0;
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
-- if (!ospf_lookup_instance(instance))
-+ if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-
- return no_debug_ospf_nsm_common(vty, 5, argc, argv);
-@@ -1046,7 +1046,7 @@ DEFUN (debug_ospf_instance_lsa,
- unsigned short instance = 0;
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
-- if (!ospf_lookup_instance(instance))
-+ if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-
- return debug_ospf_lsa_common(vty, 4, argc, argv);
-@@ -1122,7 +1122,7 @@ DEFUN (no_debug_ospf_instance_lsa,
- unsigned short instance = 0;
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
-- if (!ospf_lookup_instance(instance))
-+ if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-
- return no_debug_ospf_lsa_common(vty, 5, argc, argv);
-@@ -1184,7 +1184,7 @@ DEFUN (debug_ospf_instance_zebra,
- unsigned short instance = 0;
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
-- if (!ospf_lookup_instance(instance))
-+ if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-
- return debug_ospf_zebra_common(vty, 4, argc, argv);
-@@ -1248,8 +1248,8 @@ DEFUN (no_debug_ospf_instance_zebra,
- unsigned short instance = 0;
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
-- if (!ospf_lookup_instance(instance))
-- return CMD_SUCCESS;
-+ if (instance != ospf_instance)
-+ return CMD_NOT_MY_INSTANCE;
-
- return no_debug_ospf_zebra_common(vty, 5, argc, argv);
- }
-@@ -1294,8 +1294,8 @@ DEFUN (debug_ospf_instance_event,
- unsigned short instance = 0;
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
-- if (!ospf_lookup_instance(instance))
-- return CMD_SUCCESS;
-+ if (instance != ospf_instance)
-+ return CMD_NOT_MY_INSTANCE;
-
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_ON(event, EVENT);
-@@ -1316,8 +1316,8 @@ DEFUN (no_debug_ospf_instance_event,
- unsigned short instance = 0;
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
-- if (!ospf_lookup_instance(instance))
-- return CMD_SUCCESS;
-+ if (instance != ospf_instance)
-+ return CMD_NOT_MY_INSTANCE;
-
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_OFF(event, EVENT);
-@@ -1364,8 +1364,8 @@ DEFUN (debug_ospf_instance_nssa,
- unsigned short instance = 0;
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
-- if (!ospf_lookup_instance(instance))
-- return CMD_SUCCESS;
-+ if (instance != ospf_instance)
-+ return CMD_NOT_MY_INSTANCE;
-
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_ON(nssa, NSSA);
-@@ -1386,8 +1386,8 @@ DEFUN (no_debug_ospf_instance_nssa,
- unsigned short instance = 0;
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
-- if (!ospf_lookup_instance(instance))
-- return CMD_SUCCESS;
-+ if (instance != ospf_instance)
-+ return CMD_NOT_MY_INSTANCE;
-
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_OFF(nssa, NSSA);
-@@ -1536,12 +1536,12 @@ DEFUN (no_debug_ospf,
- return CMD_SUCCESS;
- }
-
--static int show_debugging_ospf_common(struct vty *vty, struct ospf *ospf)
-+static int show_debugging_ospf_common(struct vty *vty)
- {
- int i;
-
-- if (ospf->instance)
-- vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance);
-+ if (ospf_instance)
-+ vty_out(vty, "\nOSPF Instance: %d\n\n", ospf_instance);
-
- vty_out(vty, "OSPF debugging status:\n");
-
-@@ -1645,13 +1645,7 @@ DEFUN_NOSH (show_debugging_ospf,
- DEBUG_STR
- OSPF_STR)
- {
-- struct ospf *ospf = NULL;
--
-- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
-- if (ospf == NULL)
-- return CMD_SUCCESS;
--
-- return show_debugging_ospf_common(vty, ospf);
-+ return show_debugging_ospf_common(vty);
- }
-
- DEFUN_NOSH (show_debugging_ospf_instance,
-@@ -1663,14 +1657,13 @@ DEFUN_NOSH (show_debugging_ospf_instance
- "Instance ID\n")
- {
- int idx_number = 3;
-- struct ospf *ospf;
- unsigned short instance = 0;
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
-- if ((ospf = ospf_lookup_instance(instance)) == NULL)
-- return CMD_SUCCESS;
-+ if (instance != ospf_instance)
-+ return CMD_NOT_MY_INSTANCE;
-
-- return show_debugging_ospf_common(vty, ospf);
-+ return show_debugging_ospf_common(vty);
- }
-
- static int config_write_debug(struct vty *vty);
-@@ -1693,16 +1686,11 @@ static int config_write_debug(struct vty
- "", " send", " recv", "",
- " detail", " send detail", " recv detail", " detail"};
-
-- struct ospf *ospf;
- char str[16];
- memset(str, 0, 16);
-
-- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
-- if (ospf == NULL)
-- return CMD_SUCCESS;
--
-- if (ospf->instance)
-- snprintf(str, sizeof(str), " %u", ospf->instance);
-+ if (ospf_instance)
-+ snprintf(str, sizeof(str), " %u", ospf_instance);
-
- /* debug ospf ism (status|events|timers). */
- if (IS_CONF_DEBUG_OSPF(ism, ISM) == OSPF_DEBUG_ISM)
---- a/ospfd/ospf_main.c
-+++ b/ospfd/ospf_main.c
-@@ -145,9 +145,6 @@ FRR_DAEMON_INFO(ospfd, OSPF, .vty_port =
- /* OSPFd main routine. */
- int main(int argc, char **argv)
- {
-- unsigned short instance = 0;
-- bool created = false;
--
- #ifdef SUPPORT_OSPF_API
- /* OSPF apiserver is disabled by default. */
- ospf_apiserver_enable = 0;
-@@ -168,8 +165,8 @@ int main(int argc, char **argv)
-
- switch (opt) {
- case 'n':
-- ospfd_di.instance = instance = atoi(optarg);
-- if (instance < 1)
-+ ospfd_di.instance = ospf_instance = atoi(optarg);
-+ if (ospf_instance < 1)
- exit(0);
- break;
- case 0:
-@@ -207,7 +204,7 @@ int main(int argc, char **argv)
-
- /* OSPFd inits. */
- ospf_if_init();
-- ospf_zebra_init(master, instance);
-+ ospf_zebra_init(master, ospf_instance);
-
- /* OSPF vty inits. */
- ospf_vty_init();
-@@ -223,17 +220,6 @@ int main(int argc, char **argv)
- /* OSPF errors init */
- ospf_error_init();
-
-- /*
-- * Need to initialize the default ospf structure, so the interface mode
-- * commands can be duly processed if they are received before 'router
-- * ospf', when ospfd is restarted
-- */
-- if (instance && !ospf_get_instance(instance, &created)) {
-- flog_err(EC_OSPF_INIT_FAIL, "OSPF instance init failed: %s",
-- strerror(errno));
-- exit(1);
-- }
--
- frr_config_fork();
- frr_run(master);
-
---- a/ospfd/ospf_vty.c
-+++ b/ospfd/ospf_vty.c
-@@ -136,44 +136,37 @@ int ospf_oi_count(struct interface *ifp)
- all_vrf = strmatch(vrf_name, "all"); \
- }
-
--static struct ospf *ospf_cmd_lookup_ospf(struct vty *vty,
-- struct cmd_token *argv[],
-- const int argc, uint32_t enable,
-- unsigned short *instance)
-+static int ospf_router_cmd_parse(struct vty *vty, struct cmd_token *argv[],
-+ const int argc, unsigned short *instance,
-+ const char **vrf_name)
- {
-- struct ospf *ospf = NULL;
- int idx_vrf = 0, idx_inst = 0;
-- const char *vrf_name = NULL;
-- bool created = false;
-
- *instance = 0;
-- if (argv_find(argv, argc, "(1-65535)", &idx_inst))
-+ if (argv_find(argv, argc, "(1-65535)", &idx_inst)) {
-+ if (ospf_instance == 0) {
-+ vty_out(vty,
-+ "%% OSPF is not running in instance mode\n");
-+ return CMD_WARNING_CONFIG_FAILED;
-+ }
-+
- *instance = strtoul(argv[idx_inst]->arg, NULL, 10);
-+ }
-
-+ *vrf_name = NULL;
- if (argv_find(argv, argc, "vrf", &idx_vrf)) {
-- vrf_name = argv[idx_vrf + 1]->arg;
-- if (vrf_name == NULL || strmatch(vrf_name, VRF_DEFAULT_NAME))
-- vrf_name = NULL;
-- if (enable) {
-- /* Allocate VRF aware instance */
-- ospf = ospf_get(*instance, vrf_name, &created);
-- } else {
-- ospf = ospf_lookup_by_inst_name(*instance, vrf_name);
-- }
-- } else {
-- if (enable) {
-- ospf = ospf_get(*instance, NULL, &created);
-- } else {
-- ospf = ospf_lookup_instance(*instance);
-+ if (ospf_instance != 0) {
-+ vty_out(vty,
-+ "%% VRF is not supported in instance mode\n");
-+ return CMD_WARNING_CONFIG_FAILED;
- }
-- }
-
-- if (created) {
-- if (DFLT_OSPF_LOG_ADJACENCY_CHANGES)
-- SET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES);
-+ *vrf_name = argv[idx_vrf + 1]->arg;
-+ if (*vrf_name && strmatch(*vrf_name, VRF_DEFAULT_NAME))
-+ *vrf_name = NULL;
- }
-
-- return ospf;
-+ return CMD_SUCCESS;
- }
-
- static void ospf_show_vrf_name(struct ospf *ospf, struct vty *vty,
-@@ -209,28 +202,35 @@ DEFUN_NOSH (router_ospf,
- "Instance ID\n"
- VRF_CMD_HELP_STR)
- {
-- struct ospf *ospf = NULL;
-- int ret = CMD_SUCCESS;
-- unsigned short instance = 0;
-+ unsigned short instance;
-+ const char *vrf_name;
-+ bool created = false;
-+ struct ospf *ospf;
-+ int ret;
-
-- ospf = ospf_cmd_lookup_ospf(vty, argv, argc, 1, &instance);
-- if (!ospf)
-- return CMD_WARNING_CONFIG_FAILED;
-+ ret = ospf_router_cmd_parse(vty, argv, argc, &instance, &vrf_name);
-+ if (ret != CMD_SUCCESS)
-+ return ret;
-
-- /* The following logic to set the vty qobj index is in place to be able
-- to ignore the commands which dont belong to this instance. */
-- if (ospf->instance != instance) {
-+ if (instance != ospf_instance) {
- VTY_PUSH_CONTEXT_NULL(OSPF_NODE);
-- ret = CMD_NOT_MY_INSTANCE;
-- } else {
-- if (IS_DEBUG_OSPF_EVENT)
-- zlog_debug(
-- "Config command 'router ospf %d' received, vrf %s id %u oi_running %u",
-- instance, ospf->name ? ospf->name : "NIL",
-- ospf->vrf_id, ospf->oi_running);
-- VTY_PUSH_CONTEXT(OSPF_NODE, ospf);
-+ return CMD_NOT_MY_INSTANCE;
- }
-
-+ ospf = ospf_get(instance, vrf_name, &created);
-+
-+ if (created)
-+ if (DFLT_OSPF_LOG_ADJACENCY_CHANGES)
-+ SET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES);
-+
-+ if (IS_DEBUG_OSPF_EVENT)
-+ zlog_debug(
-+ "Config command 'router ospf %d' received, vrf %s id %u oi_running %u",
-+ ospf->instance, ospf->name ? ospf->name : "NIL",
-+ ospf->vrf_id, ospf->oi_running);
-+
-+ VTY_PUSH_CONTEXT(OSPF_NODE, ospf);
-+
- return ret;
- }
-
-@@ -243,19 +243,25 @@ DEFUN (no_router_ospf,
- "Instance ID\n"
- VRF_CMD_HELP_STR)
- {
-+ unsigned short instance;
-+ const char *vrf_name;
- struct ospf *ospf;
-- unsigned short instance = 0;
-+ int ret;
-
-- ospf = ospf_cmd_lookup_ospf(vty, argv, argc, 0, &instance);
-- if (ospf == NULL) {
-- if (instance)
-- return CMD_NOT_MY_INSTANCE;
-- else
-- return CMD_WARNING;
-- }
-- ospf_finish(ospf);
-+ ret = ospf_router_cmd_parse(vty, argv, argc, &instance, &vrf_name);
-+ if (ret != CMD_SUCCESS)
-+ return ret;
-
-- return CMD_SUCCESS;
-+ if (instance != ospf_instance)
-+ return CMD_NOT_MY_INSTANCE;
-+
-+ ospf = ospf_lookup(instance, vrf_name);
-+ if (ospf)
-+ ospf_finish(ospf);
-+ else
-+ ret = CMD_WARNING_CONFIG_FAILED;
-+
-+ return ret;
- }
-
-
-@@ -3326,11 +3332,11 @@ DEFUN (show_ip_ospf_instance,
- json_object *json = NULL;
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
-- ospf = ospf_lookup_instance(instance);
-- if (ospf == NULL)
-+ if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-
-- if (!ospf->oi_running)
-+ ospf = ospf_lookup_instance(instance);
-+ if (!ospf || !ospf->oi_running)
- return CMD_SUCCESS;
-
- if (uj)
-@@ -4016,11 +4022,11 @@ DEFUN (show_ip_ospf_instance_interface,
- json_object *json = NULL;
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
-- ospf = ospf_lookup_instance(instance);
-- if (ospf == NULL)
-+ if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-
-- if (!ospf->oi_running)
-+ ospf = ospf_lookup_instance(instance);
-+ if (!ospf || !ospf->oi_running)
- return CMD_SUCCESS;
-
- if (uj)
-@@ -4409,11 +4415,11 @@ DEFUN (show_ip_ospf_instance_neighbor,
- int ret = CMD_SUCCESS;
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
-- ospf = ospf_lookup_instance(instance);
-- if (ospf == NULL)
-+ if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-
-- if (!ospf->oi_running)
-+ ospf = ospf_lookup_instance(instance);
-+ if (!ospf || !ospf->oi_running)
- return CMD_SUCCESS;
-
- if (uj)
-@@ -4621,11 +4627,11 @@ DEFUN (show_ip_ospf_instance_neighbor_al
- int ret = CMD_SUCCESS;
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
-- ospf = ospf_lookup_instance(instance);
-- if (ospf == NULL)
-+ if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-
-- if (!ospf->oi_running)
-+ ospf = ospf_lookup_instance(instance);
-+ if (!ospf || !ospf->oi_running)
- return CMD_SUCCESS;
- if (uj)
- json = json_object_new_object();
-@@ -4761,11 +4767,11 @@ DEFUN (show_ip_ospf_instance_neighbor_in
- show_ip_ospf_neighbour_header(vty);
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
-- ospf = ospf_lookup_instance(instance);
-- if (ospf == NULL)
-+ if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-
-- if (!ospf->oi_running)
-+ ospf = ospf_lookup_instance(instance);
-+ if (!ospf || !ospf->oi_running)
- return CMD_SUCCESS;
-
- if (!uj)
-@@ -5170,11 +5176,11 @@ DEFPY (show_ip_ospf_instance_neighbor_id
- {
- struct ospf *ospf;
-
-- ospf = ospf_lookup_instance(instance);
-- if (ospf == NULL)
-+ if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-
-- if (!ospf->oi_running)
-+ ospf = ospf_lookup_instance(instance);
-+ if (!ospf || !ospf->oi_running)
- return CMD_SUCCESS;
-
- return show_ip_ospf_neighbor_id_common(vty, ospf, &router_id, !!json,
-@@ -5343,11 +5349,11 @@ DEFUN (show_ip_ospf_instance_neighbor_de
- int ret = CMD_SUCCESS;
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
-- ospf = ospf_lookup_instance(instance);
-- if (ospf == NULL)
-+ if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-
-- if (!ospf->oi_running)
-+ ospf = ospf_lookup_instance(instance);
-+ if (!ospf || !ospf->oi_running)
- return CMD_SUCCESS;
-
- if (uj)
-@@ -5538,11 +5544,11 @@ DEFUN (show_ip_ospf_instance_neighbor_de
- int ret = CMD_SUCCESS;
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
-- ospf = ospf_lookup_instance(instance);
-- if (ospf == NULL)
-+ if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-
-- if (!ospf->oi_running)
-+ ospf = ospf_lookup_instance(instance);
-+ if (!ospf || !ospf->oi_running)
- return CMD_SUCCESS;
-
- if (uj)
-@@ -5670,11 +5676,11 @@ DEFUN (show_ip_ospf_instance_neighbor_in
- bool uj = use_json(argc, argv);
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
-- ospf = ospf_lookup_instance(instance);
-- if (ospf == NULL)
-+ if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-
-- if (!ospf->oi_running)
-+ ospf = ospf_lookup_instance(instance);
-+ if (!ospf || !ospf->oi_running)
- return CMD_SUCCESS;
-
- return show_ip_ospf_neighbor_int_detail_common(vty, ospf, idx_ifname,
-@@ -6420,10 +6426,11 @@ DEFUN (show_ip_ospf_instance_database,
-
- if (argv_find(argv, argc, "(1-65535)", &idx)) {
- instance = strtoul(argv[idx]->arg, NULL, 10);
-- ospf = ospf_lookup_instance(instance);
-- if (ospf == NULL)
-+ if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-- if (!ospf->oi_running)
-+
-+ ospf = ospf_lookup_instance(instance);
-+ if (!ospf || !ospf->oi_running)
- return CMD_SUCCESS;
-
- return (show_ip_ospf_database_common(vty, ospf, idx ? 1 : 0,
-@@ -6484,15 +6491,12 @@ DEFUN (show_ip_ospf_instance_database_ma
- unsigned short instance = 0;
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
--
-- ospf = ospf_lookup_instance(instance);
-- if (ospf == NULL)
-+ if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-
-- if (!ospf->oi_running) {
-- vty_out(vty, "%% OSPF instance not found\n");
-+ ospf = ospf_lookup_instance(instance);
-+ if (!ospf || !ospf->oi_running)
- return CMD_SUCCESS;
-- }
-
- return show_ip_ospf_database_common(vty, ospf, 1, argc, argv, 0);
- }
-@@ -6578,13 +6582,12 @@ DEFUN (show_ip_ospf_instance_database_ty
-
- if (argv_find(argv, argc, "(1-65535)", &idx)) {
- instance = strtoul(argv[idx]->arg, NULL, 10);
-- ospf = ospf_lookup_instance(instance);
-- if (ospf == NULL)
-+ if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-- if (!ospf->oi_running) {
-- vty_out(vty, "%% OSPF instance not found\n");
-+
-+ ospf = ospf_lookup_instance(instance);
-+ if (!ospf || !ospf->oi_running)
- return CMD_SUCCESS;
-- }
-
- return (show_ip_ospf_database_type_adv_router_common(
- vty, ospf, idx ? 1 : 0, argc, argv, use_vrf));
-@@ -8035,7 +8038,7 @@ DEFUN (ip_ospf_area,
- else
- ospf = ospf_lookup_instance(instance);
-
-- if (instance && ospf == NULL) {
-+ if (instance && instance != ospf_instance) {
- /*
- * At this point we know we have received
- * an instance and there is no ospf instance
-@@ -8159,7 +8162,7 @@ DEFUN (no_ip_ospf_area,
- else
- ospf = ospf_lookup_instance(instance);
-
-- if (instance && ospf == NULL)
-+ if (instance && instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-
- argv_find(argv, argc, "area", &idx);
-@@ -9519,11 +9522,11 @@ DEFUN (show_ip_ospf_instance_border_rout
- unsigned short instance = 0;
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
-- ospf = ospf_lookup_instance(instance);
-- if (ospf == NULL)
-+ if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-
-- if (!ospf->oi_running)
-+ ospf = ospf_lookup_instance(instance);
-+ if (!ospf || !ospf->oi_running)
- return CMD_SUCCESS;
-
- return show_ip_ospf_border_routers_common(vty, ospf, 0);
-@@ -9687,11 +9690,11 @@ DEFUN (show_ip_ospf_instance_route,
- unsigned short instance = 0;
-
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
-- ospf = ospf_lookup_instance(instance);
-- if (ospf == NULL)
-+ if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-
-- if (!ospf->oi_running)
-+ ospf = ospf_lookup_instance(instance);
-+ if (!ospf || !ospf->oi_running)
- return CMD_SUCCESS;
-
- return show_ip_ospf_route_common(vty, ospf, NULL, 0);
-@@ -9787,8 +9790,7 @@ DEFPY (clear_ip_ospf_neighbor,
- */
- if (instance != 0) {
- /* This means clear only the particular ospf process */
-- ospf = ospf_lookup_instance(instance);
-- if (ospf == NULL)
-+ if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
- }
-
-@@ -9818,8 +9820,7 @@ DEFPY (clear_ip_ospf_process,
- /* Check if instance is not passed as an argument */
- if (instance != 0) {
- /* This means clear only the particular ospf process */
-- ospf = ospf_lookup_instance(instance);
-- if (ospf == NULL)
-+ if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
- }
-
-@@ -9860,7 +9861,6 @@ static int config_write_interface_one(st
- struct route_node *rn = NULL;
- struct ospf_if_params *params;
- int write = 0;
-- struct ospf *ospf = vrf->info;
-
- FOR_ALL_INTERFACES (vrf, ifp) {
-
-@@ -10039,9 +10039,9 @@ static int config_write_interface_one(st
-
- /* Area print. */
- if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) {
-- if (ospf && ospf->instance)
-+ if (ospf_instance)
- vty_out(vty, " ip ospf %d",
-- ospf->instance);
-+ ospf_instance);
- else
- vty_out(vty, " ip ospf");
-
---- a/ospfd/ospfd.c
-+++ b/ospfd/ospfd.c
-@@ -67,6 +67,8 @@ static struct ospf_master ospf_master;
- /* OSPF process wide configuration pointer to export. */
- struct ospf_master *om;
-
-+unsigned short ospf_instance;
-+
- extern struct zclient *zclient;
-
-
-@@ -438,36 +440,28 @@ static void ospf_init(struct ospf *ospf)
- ospf_router_id_update(ospf);
- }
-
--struct ospf *ospf_get(unsigned short instance, const char *name, bool *created)
-+struct ospf *ospf_lookup(unsigned short instance, const char *name)
- {
- struct ospf *ospf;
-
-- /* vrf name provided call inst and name based api
-- * in case of no name pass default ospf instance */
-- if (name)
-+ if (ospf_instance) {
-+ ospf = ospf_lookup_instance(instance);
-+ } else {
- ospf = ospf_lookup_by_inst_name(instance, name);
-- else
-- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
--
-- *created = (ospf == NULL);
-- if (ospf == NULL) {
-- ospf = ospf_new(instance, name);
-- ospf_add(ospf);
--
-- ospf_init(ospf);
- }
-
- return ospf;
- }
-
--struct ospf *ospf_get_instance(unsigned short instance, bool *created)
-+struct ospf *ospf_get(unsigned short instance, const char *name, bool *created)
- {
- struct ospf *ospf;
-
-- ospf = ospf_lookup_instance(instance);
-+ ospf = ospf_lookup(instance, name);
-+
- *created = (ospf == NULL);
- if (ospf == NULL) {
-- ospf = ospf_new(instance, NULL /* VRF_DEFAULT*/);
-+ ospf = ospf_new(instance, name);
- ospf_add(ospf);
-
- ospf_init(ospf);
---- a/ospfd/ospfd.h
-+++ b/ospfd/ospfd.h
-@@ -502,6 +502,7 @@ struct ospf_nbr_nbma {
-
- /* Extern variables. */
- extern struct ospf_master *om;
-+extern unsigned short ospf_instance;
- extern const int ospf_redistributed_proto_max;
- extern struct zclient *zclient;
- extern struct thread_master *master;
-@@ -511,9 +512,9 @@ extern struct zebra_privs_t ospfd_privs;
- /* Prototypes. */
- extern const char *ospf_redist_string(unsigned int route_type);
- extern struct ospf *ospf_lookup_instance(unsigned short);
-+extern struct ospf *ospf_lookup(unsigned short instance, const char *name);
- extern struct ospf *ospf_get(unsigned short instance, const char *name,
- bool *created);
--extern struct ospf *ospf_get_instance(unsigned short, bool *created);
- extern struct ospf *ospf_lookup_by_inst_name(unsigned short instance,
- const char *name);
- extern struct ospf *ospf_lookup_by_vrf_id(vrf_id_t vrf_id);
---- a/vtysh/vtysh.c
-+++ b/vtysh/vtysh.c
-@@ -2487,7 +2487,7 @@ static int show_per_daemon(const char *l
- int ret = CMD_SUCCESS;
-
- for (i = 0; i < array_size(vtysh_client); i++)
-- if (vtysh_client[i].fd >= 0) {
-+ if (vtysh_client[i].fd >= 0 || vtysh_client[i].next) {
- vty_out(vty, headline, vtysh_client[i].name);
- ret = vtysh_client_execute(&vtysh_client[i], line);
- vty_out(vty, "\n");
+++ /dev/null
-From 6ea5d99456b14db5e82abc2461228bb37aa7556d Mon Sep 17 00:00:00 2001
-From: Amol Lad <amol.lad@4rf.com>
-Date: Wed, 17 Feb 2021 13:47:32 +1300
-Subject: [PATCH 01/14] nhrpd: Add support for forwarding multicast packets
-
-Forwarding multicast is a pre-requisite for allowing multicast based routing
-protocols such as OSPF to work with DMVPN
-
-This code relies on externally adding iptables rule. For example:
-iptables -A OUTPUT -d 224.0.0.0/24 -o gre1 -j NFLOG --nflog-group 224
-
-Signed-off-by: Reuben Dowle <reuben.dowle@4rf.com>
----
- nhrpd/linux.c | 11 +-
- nhrpd/nhrp_interface.c | 2 +
- nhrpd/nhrp_multicast.c | 307 +++++++++++++++++++++++++++++++++++++++++
- nhrpd/nhrp_peer.c | 3 +-
- nhrpd/nhrp_vty.c | 63 +++++++++
- nhrpd/nhrpd.h | 16 +++
- nhrpd/os.h | 2 +-
- nhrpd/subdir.am | 1 +
- 8 files changed, 398 insertions(+), 7 deletions(-)
- create mode 100755 nhrpd/nhrp_multicast.c
-
---- a/nhrpd/linux.c
-+++ b/nhrpd/linux.c
-@@ -15,6 +15,7 @@
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
-+#include <errno.h>
- #include <sys/ioctl.h>
- #include <sys/socket.h>
- #include <sys/types.h>
-@@ -31,6 +32,11 @@
- #include "os.h"
- #include "netlink.h"
-
-+#ifndef HAVE_STRLCPY
-+size_t strlcpy(char *__restrict dest,
-+ const char *__restrict src, size_t destsize);
-+#endif
-+
- static int nhrp_socket_fd = -1;
-
- int os_socket(void)
-@@ -42,7 +48,7 @@ int os_socket(void)
- }
-
- int os_sendmsg(const uint8_t *buf, size_t len, int ifindex, const uint8_t *addr,
-- size_t addrlen)
-+ size_t addrlen, uint16_t protocol)
- {
- struct sockaddr_ll lladdr;
- struct iovec iov = {
-@@ -61,16 +67,16 @@ int os_sendmsg(const uint8_t *buf, size_
-
- memset(&lladdr, 0, sizeof(lladdr));
- lladdr.sll_family = AF_PACKET;
-- lladdr.sll_protocol = htons(ETH_P_NHRP);
-+ lladdr.sll_protocol = htons(protocol);
- lladdr.sll_ifindex = ifindex;
- lladdr.sll_halen = addrlen;
- memcpy(lladdr.sll_addr, addr, addrlen);
-
-- status = sendmsg(nhrp_socket_fd, &msg, 0);
-+ status = sendmsg(os_socket(), &msg, 0);
- if (status < 0)
-- return -1;
-+ return -errno;
-
-- return 0;
-+ return status;
- }
-
- int os_recvmsg(uint8_t *buf, size_t *len, int *ifindex, uint8_t *addr,
-@@ -111,7 +117,7 @@ static int linux_configure_arp(const cha
- {
- struct ifreq ifr;
-
-- strncpy(ifr.ifr_name, iface, IFNAMSIZ - 1);
-+ strlcpy(ifr.ifr_name, iface, IFNAMSIZ);
- if (ioctl(nhrp_socket_fd, SIOCGIFFLAGS, &ifr))
- return -1;
-
---- a/nhrpd/nhrp_interface.c
-+++ b/nhrpd/nhrp_interface.c
-@@ -42,6 +42,7 @@ static int nhrp_if_new_hook(struct inter
- struct nhrp_afi_data *ad = &nifp->afi[afi];
- ad->holdtime = NHRPD_DEFAULT_HOLDTIME;
- list_init(&ad->nhslist_head);
-+ list_init(&ad->mcastlist_head);
- }
-
- return 0;
-@@ -55,6 +56,7 @@ static int nhrp_if_delete_hook(struct in
-
- nhrp_cache_interface_del(ifp);
- nhrp_nhs_interface_del(ifp);
-+ nhrp_multicast_interface_del(ifp);
- nhrp_peer_interface_del(ifp);
-
- if (nifp->ipsec_profile)
---- /dev/null
-+++ b/nhrpd/nhrp_multicast.c
-@@ -0,0 +1,309 @@
-+/* NHRP Multicast Support
-+ * Copyright (c) 2020-2021 4RF Limited
-+ *
-+ * This file is free software: you may copy, redistribute and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation, either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+#ifdef HAVE_CONFIG_H
-+#include "config.h"
-+#endif
-+
-+#include <fcntl.h>
-+#include <net/if.h>
-+#include <net/ethernet.h>
-+#include <netinet/if_ether.h>
-+#include <linux/netlink.h>
-+#include <linux/neighbour.h>
-+#include <linux/netfilter/nfnetlink_log.h>
-+#include <linux/if_packet.h>
-+#include <sys/types.h>
-+#include <sys/socket.h>
-+
-+#include "thread.h"
-+#include "nhrpd.h"
-+#include "netlink.h"
-+#include "znl.h"
-+#include "os.h"
-+
-+DEFINE_MTYPE_STATIC(NHRPD, NHRP_MULTICAST, "NHRP Multicast")
-+
-+int netlink_mcast_nflog_group;
-+static int netlink_mcast_log_fd = -1;
-+static struct thread *netlink_mcast_log_thread;
-+
-+struct mcast_ctx {
-+ struct interface *ifp;
-+ struct zbuf *pkt;
-+};
-+
-+static void nhrp_multicast_send(struct nhrp_peer *p, struct zbuf *zb)
-+{
-+ char buf[2][256];
-+ size_t addrlen;
-+ int ret;
-+
-+ addrlen = sockunion_get_addrlen(&p->vc->remote.nbma);
-+ ret = os_sendmsg(zb->head, zbuf_used(zb), p->ifp->ifindex,
-+ sockunion_get_addr(&p->vc->remote.nbma), addrlen,
-+ addrlen == 4 ? ETH_P_IP : ETH_P_IPV6);
-+
-+ debugf(NHRP_DEBUG_COMMON,
-+ "Multicast Packet: %s -> %s, ret = %d, size = %zu, addrlen = %zu",
-+ sockunion2str(&p->vc->local.nbma, buf[0], sizeof(buf[0])),
-+ sockunion2str(&p->vc->remote.nbma, buf[1], sizeof(buf[1])), ret,
-+ zbuf_used(zb), addrlen);
-+}
-+
-+static void nhrp_multicast_forward_nbma(union sockunion *nbma_addr,
-+ struct interface *ifp, struct zbuf *pkt)
-+{
-+ struct nhrp_peer *p = nhrp_peer_get(ifp, nbma_addr);
-+
-+ if (p && p->online) {
-+ /* Send packet */
-+ nhrp_multicast_send(p, pkt);
-+ }
-+ nhrp_peer_unref(p);
-+}
-+
-+static void nhrp_multicast_forward_cache(struct nhrp_cache *c, void *pctx)
-+{
-+ struct mcast_ctx *ctx = (struct mcast_ctx *)pctx;
-+
-+ if (c->cur.type == NHRP_CACHE_DYNAMIC && c->cur.peer)
-+ nhrp_multicast_forward_nbma(&c->cur.peer->vc->remote.nbma,
-+ ctx->ifp, ctx->pkt);
-+}
-+
-+static void nhrp_multicast_forward(struct nhrp_multicast *mcast, void *pctx)
-+{
-+ struct mcast_ctx *ctx = (struct mcast_ctx *)pctx;
-+ struct nhrp_interface *nifp = ctx->ifp->info;
-+
-+ if (!nifp->enabled)
-+ return;
-+
-+ /* dynamic */
-+ if (sockunion_family(&mcast->nbma_addr) == AF_UNSPEC) {
-+ nhrp_cache_foreach(ctx->ifp, nhrp_multicast_forward_cache,
-+ pctx);
-+ return;
-+ }
-+
-+ /* Fixed IP Address */
-+ nhrp_multicast_forward_nbma(&mcast->nbma_addr, ctx->ifp, ctx->pkt);
-+}
-+
-+static void netlink_mcast_log_handler(struct nlmsghdr *msg, struct zbuf *zb)
-+{
-+ struct nfgenmsg *nf;
-+ struct rtattr *rta;
-+ struct zbuf rtapl;
-+ uint32_t *out_ndx = NULL;
-+ afi_t afi;
-+ struct mcast_ctx ctx;
-+
-+ nf = znl_pull(zb, sizeof(*nf));
-+ if (!nf)
-+ return;
-+
-+ ctx.pkt = NULL;
-+ while ((rta = znl_rta_pull(zb, &rtapl)) != NULL) {
-+ switch (rta->rta_type) {
-+ case NFULA_IFINDEX_OUTDEV:
-+ out_ndx = znl_pull(&rtapl, sizeof(*out_ndx));
-+ break;
-+ case NFULA_PAYLOAD:
-+ ctx.pkt = &rtapl;
-+ break;
-+ /* NFULA_HWHDR exists and is supposed to contain source
-+ * hardware address. However, for ip_gre it seems to be
-+ * the nexthop destination address if the packet matches
-+ * route.
-+ */
-+ }
-+ }
-+
-+ if (!out_ndx || !ctx.pkt)
-+ return;
-+
-+ ctx.ifp = if_lookup_by_index(htonl(*out_ndx), VRF_DEFAULT);
-+ if (!ctx.ifp)
-+ return;
-+
-+ debugf(NHRP_DEBUG_COMMON, "Received multicast packet on %s len %zu\n",
-+ ctx.ifp->name, zbuf_used(ctx.pkt));
-+
-+ for (afi = 0; afi < AFI_MAX; afi++) {
-+ nhrp_multicast_foreach(ctx.ifp, afi, nhrp_multicast_forward,
-+ (void *)&ctx);
-+ }
-+}
-+
-+static int netlink_mcast_log_recv(struct thread *t)
-+{
-+ uint8_t buf[65535]; /* Max OSPF Packet size */
-+ int fd = THREAD_FD(t);
-+ struct zbuf payload, zb;
-+ struct nlmsghdr *n;
-+
-+ netlink_mcast_log_thread = NULL;
-+
-+ zbuf_init(&zb, buf, sizeof(buf), 0);
-+ while (zbuf_recv(&zb, fd) > 0) {
-+ while ((n = znl_nlmsg_pull(&zb, &payload)) != NULL) {
-+ debugf(NHRP_DEBUG_COMMON,
-+ "Netlink-mcast-log: Received msg_type %u, msg_flags %u",
-+ n->nlmsg_type, n->nlmsg_flags);
-+ switch (n->nlmsg_type) {
-+ case (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_PACKET:
-+ netlink_mcast_log_handler(n, &payload);
-+ break;
-+ }
-+ }
-+ }
-+
-+ thread_add_read(master, netlink_mcast_log_recv, 0, netlink_mcast_log_fd,
-+ &netlink_mcast_log_thread);
-+
-+ return 0;
-+}
-+
-+static void netlink_mcast_log_register(int fd, int group)
-+{
-+ struct nlmsghdr *n;
-+ struct nfgenmsg *nf;
-+ struct nfulnl_msg_config_cmd cmd;
-+ struct zbuf *zb = zbuf_alloc(512);
-+
-+ n = znl_nlmsg_push(zb, (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG,
-+ NLM_F_REQUEST | NLM_F_ACK);
-+ nf = znl_push(zb, sizeof(*nf));
-+ *nf = (struct nfgenmsg){
-+ .nfgen_family = AF_UNSPEC,
-+ .version = NFNETLINK_V0,
-+ .res_id = htons(group),
-+ };
-+ cmd.command = NFULNL_CFG_CMD_BIND;
-+ znl_rta_push(zb, NFULA_CFG_CMD, &cmd, sizeof(cmd));
-+ znl_nlmsg_complete(zb, n);
-+
-+ zbuf_send(zb, fd);
-+ zbuf_free(zb);
-+}
-+
-+void netlink_mcast_set_nflog_group(int nlgroup)
-+{
-+ if (netlink_mcast_log_fd >= 0) {
-+ THREAD_OFF(netlink_mcast_log_thread);
-+ close(netlink_mcast_log_fd);
-+ netlink_mcast_log_fd = -1;
-+ debugf(NHRP_DEBUG_COMMON, "De-register nflog group");
-+ }
-+ netlink_mcast_nflog_group = nlgroup;
-+ if (nlgroup) {
-+ netlink_mcast_log_fd = znl_open(NETLINK_NETFILTER, 0);
-+ if (netlink_mcast_log_fd < 0)
-+ return;
-+
-+ netlink_mcast_log_register(netlink_mcast_log_fd, nlgroup);
-+ thread_add_read(master, netlink_mcast_log_recv, 0,
-+ netlink_mcast_log_fd,
-+ &netlink_mcast_log_thread);
-+ debugf(NHRP_DEBUG_COMMON, "Register nflog group: %d",
-+ netlink_mcast_nflog_group);
-+ }
-+}
-+
-+static int nhrp_multicast_free(struct interface *ifp,
-+ struct nhrp_multicast *mcast)
-+{
-+ list_del(&mcast->list_entry);
-+ XFREE(MTYPE_NHRP_MULTICAST, mcast);
-+ return 0;
-+}
-+
-+int nhrp_multicast_add(struct interface *ifp, afi_t afi,
-+ union sockunion *nbma_addr)
-+{
-+ struct nhrp_interface *nifp = ifp->info;
-+ struct nhrp_multicast *mcast;
-+ char buf[SU_ADDRSTRLEN];
-+
-+ list_for_each_entry(mcast, &nifp->afi[afi].mcastlist_head, list_entry)
-+ {
-+ if (sockunion_same(&mcast->nbma_addr, nbma_addr))
-+ return NHRP_ERR_ENTRY_EXISTS;
-+ }
-+
-+ mcast = XMALLOC(MTYPE_NHRP_MULTICAST, sizeof(struct nhrp_multicast));
-+
-+ *mcast = (struct nhrp_multicast){
-+ .afi = afi, .ifp = ifp, .nbma_addr = *nbma_addr,
-+ };
-+ list_add_tail(&mcast->list_entry, &nifp->afi[afi].mcastlist_head);
-+
-+ sockunion2str(nbma_addr, buf, sizeof(buf));
-+ debugf(NHRP_DEBUG_COMMON, "Adding multicast entry (%s)", buf);
-+
-+ return NHRP_OK;
-+}
-+
-+int nhrp_multicast_del(struct interface *ifp, afi_t afi,
-+ union sockunion *nbma_addr)
-+{
-+ struct nhrp_interface *nifp = ifp->info;
-+ struct nhrp_multicast *mcast, *tmp;
-+ char buf[SU_ADDRSTRLEN];
-+
-+ list_for_each_entry_safe(mcast, tmp, &nifp->afi[afi].mcastlist_head,
-+ list_entry)
-+ {
-+ if (!sockunion_same(&mcast->nbma_addr, nbma_addr))
-+ continue;
-+
-+ sockunion2str(nbma_addr, buf, sizeof(buf));
-+ debugf(NHRP_DEBUG_COMMON, "Deleting multicast entry (%s)", buf);
-+
-+ nhrp_multicast_free(ifp, mcast);
-+
-+ return NHRP_OK;
-+ }
-+
-+ return NHRP_ERR_ENTRY_NOT_FOUND;
-+}
-+
-+void nhrp_multicast_interface_del(struct interface *ifp)
-+{
-+ struct nhrp_interface *nifp = ifp->info;
-+ struct nhrp_multicast *mcast, *tmp;
-+ afi_t afi;
-+
-+ for (afi = 0; afi < AFI_MAX; afi++) {
-+ debugf(NHRP_DEBUG_COMMON,
-+ "Cleaning up multicast entries (%d)",
-+ !list_empty(&nifp->afi[afi].mcastlist_head));
-+
-+ list_for_each_entry_safe(
-+ mcast, tmp, &nifp->afi[afi].mcastlist_head, list_entry)
-+ {
-+ nhrp_multicast_free(ifp, mcast);
-+ }
-+ }
-+}
-+
-+void nhrp_multicast_foreach(struct interface *ifp, afi_t afi,
-+ void (*cb)(struct nhrp_multicast *, void *),
-+ void *ctx)
-+{
-+ struct nhrp_interface *nifp = ifp->info;
-+ struct nhrp_multicast *mcast;
-+
-+ list_for_each_entry(mcast, &nifp->afi[afi].mcastlist_head, list_entry)
-+ {
-+ cb(mcast, ctx);
-+ }
-+}
---- a/nhrpd/nhrp_peer.c
-+++ b/nhrpd/nhrp_peer.c
-@@ -337,7 +337,7 @@ void nhrp_peer_send(struct nhrp_peer *p,
-
- os_sendmsg(zb->head, zbuf_used(zb), p->ifp->ifindex,
- sockunion_get_addr(&p->vc->remote.nbma),
-- sockunion_get_addrlen(&p->vc->remote.nbma));
-+ sockunion_get_addrlen(&p->vc->remote.nbma), ETH_P_NHRP);
- zbuf_reset(zb);
- }
-
---- a/nhrpd/nhrp_vty.c
-+++ b/nhrpd/nhrp_vty.c
-@@ -187,6 +187,9 @@ static int nhrp_config_write(struct vty
- if (netlink_nflog_group) {
- vty_out(vty, "nhrp nflog-group %d\n", netlink_nflog_group);
- }
-+ if (netlink_mcast_nflog_group)
-+ vty_out(vty, "nhrp multicast-nflog-group %d\n",
-+ netlink_mcast_nflog_group);
-
- return 0;
- }
-@@ -257,6 +260,31 @@ DEFUN(no_nhrp_nflog_group, no_nhrp_nflog
- return CMD_SUCCESS;
- }
-
-+DEFUN(nhrp_multicast_nflog_group, nhrp_multicast_nflog_group_cmd,
-+ "nhrp multicast-nflog-group (1-65535)",
-+ NHRP_STR
-+ "Specify NFLOG group number for Multicast Packets\n"
-+ "NFLOG group number\n")
-+{
-+ uint32_t nfgroup;
-+
-+ nfgroup = strtoul(argv[2]->arg, NULL, 10);
-+ netlink_mcast_set_nflog_group(nfgroup);
-+
-+ return CMD_SUCCESS;
-+}
-+
-+DEFUN(no_nhrp_multicast_nflog_group, no_nhrp_multicast_nflog_group_cmd,
-+ "no nhrp multicast-nflog-group [(1-65535)]",
-+ NO_STR
-+ NHRP_STR
-+ "Specify NFLOG group number\n"
-+ "NFLOG group number\n")
-+{
-+ netlink_mcast_set_nflog_group(0);
-+ return CMD_SUCCESS;
-+}
-+
- DEFUN(tunnel_protection, tunnel_protection_cmd,
- "tunnel protection vici profile PROFILE [fallback-profile FALLBACK]",
- "NHRP/GRE integration\n"
-@@ -569,6 +597,53 @@ DEFUN(if_no_nhrp_map, if_no_nhrp_map_cmd
- return CMD_SUCCESS;
- }
-
-+DEFUN(if_nhrp_map_multicast, if_nhrp_map_multicast_cmd,
-+ AFI_CMD " nhrp map multicast <A.B.C.D|X:X::X:X|dynamic>",
-+ AFI_STR
-+ NHRP_STR
-+ "Multicast NBMA Configuration\n"
-+ "Use this NBMA mapping for multicasts\n"
-+ "IPv4 NBMA address\n"
-+ "IPv6 NBMA address\n"
-+ "Dynamically learn destinations from client registrations on hub\n")
-+{
-+ VTY_DECLVAR_CONTEXT(interface, ifp);
-+ afi_t afi = cmd_to_afi(argv[0]);
-+ union sockunion nbma_addr;
-+ int ret;
-+
-+ if (str2sockunion(argv[4]->arg, &nbma_addr) < 0)
-+ sockunion_family(&nbma_addr) = AF_UNSPEC;
-+
-+ ret = nhrp_multicast_add(ifp, afi, &nbma_addr);
-+
-+ return nhrp_vty_return(vty, ret);
-+}
-+
-+DEFUN(if_no_nhrp_map_multicast, if_no_nhrp_map_multicast_cmd,
-+ "no " AFI_CMD " nhrp map multicast <A.B.C.D|X:X::X:X|dynamic>",
-+ NO_STR
-+ AFI_STR
-+ NHRP_STR
-+ "Multicast NBMA Configuration\n"
-+ "Use this NBMA mapping for multicasts\n"
-+ "IPv4 NBMA address\n"
-+ "IPv6 NBMA address\n"
-+ "Dynamically learn destinations from client registrations on hub\n")
-+{
-+ VTY_DECLVAR_CONTEXT(interface, ifp);
-+ afi_t afi = cmd_to_afi(argv[1]);
-+ union sockunion nbma_addr;
-+ int ret;
-+
-+ if (str2sockunion(argv[5]->arg, &nbma_addr) < 0)
-+ sockunion_family(&nbma_addr) = AF_UNSPEC;
-+
-+ ret = nhrp_multicast_del(ifp, afi, &nbma_addr);
-+
-+ return nhrp_vty_return(vty, ret);
-+}
-+
- DEFUN(if_nhrp_nhs, if_nhrp_nhs_cmd,
- AFI_CMD " nhrp nhs <A.B.C.D|X:X::X:X|dynamic> nbma <A.B.C.D|FQDN>",
- AFI_STR
-@@ -644,8 +719,8 @@ static void show_ip_nhrp_cache(struct nh
-
- sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0]));
- if (c->cur.peer)
-- sockunion2str(&c->cur.peer->vc->remote.nbma,
-- buf[1], sizeof(buf[1]));
-+ sockunion2str(&c->cur.peer->vc->remote.nbma, buf[1],
-+ sizeof(buf[1]));
- else
- snprintf(buf[1], sizeof(buf[1]), "-");
-
-@@ -704,8 +779,8 @@ static void show_ip_nhrp_nhs(struct nhrp
- ctx->count++;
-
- if (reg && reg->peer)
-- sockunion2str(®->peer->vc->remote.nbma,
-- buf[0], sizeof(buf[0]));
-+ sockunion2str(®->peer->vc->remote.nbma, buf[0],
-+ sizeof(buf[0]));
- else
- snprintf(buf[0], sizeof(buf[0]), "-");
- sockunion2str(reg ? ®->proto_addr : &n->proto_addr, buf[1],
-@@ -1018,7 +1093,8 @@ struct write_map_ctx {
- const char *aficmd;
- };
-
--static void interface_config_write_nhrp_map(struct nhrp_cache_config *c, void *data)
-+static void interface_config_write_nhrp_map(struct nhrp_cache_config *c,
-+ void *data)
- {
- struct write_map_ctx *ctx = data;
- struct vty *vty = ctx->vty;
-@@ -1030,7 +1106,8 @@ static void interface_config_write_nhrp_
- vty_out(vty, " %s nhrp map %s %s\n", ctx->aficmd,
- sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0])),
- c->type == NHRP_CACHE_LOCAL
-- ? "local" : sockunion2str(&c->nbma, buf[1], sizeof(buf[1])));
-+ ? "local"
-+ : sockunion2str(&c->nbma, buf[1], sizeof(buf[1])));
- }
-
- static int interface_config_write(struct vty *vty)
-@@ -1040,6 +1117,7 @@ static int interface_config_write(struct
- struct interface *ifp;
- struct nhrp_interface *nifp;
- struct nhrp_nhs *nhs;
-+ struct nhrp_multicast *mcast;
- const char *aficmd;
- afi_t afi;
- char buf[SU_ADDRSTRLEN];
-@@ -1093,8 +1171,8 @@ static int interface_config_write(struct
- .family = afi2family(afi),
- .aficmd = aficmd,
- };
-- nhrp_cache_config_foreach(ifp, interface_config_write_nhrp_map,
-- &mapctx);
-+ nhrp_cache_config_foreach(
-+ ifp, interface_config_write_nhrp_map, &mapctx);
-
- list_for_each_entry(nhs, &ad->nhslist_head,
- nhslist_entry)
-@@ -1109,6 +1187,19 @@ static int interface_config_write(struct
- sizeof(buf)),
- nhs->nbma_fqdn);
- }
-+
-+ list_for_each_entry(mcast, &ad->mcastlist_head,
-+ list_entry)
-+ {
-+ vty_out(vty, " %s nhrp map multicast %s\n",
-+ aficmd,
-+ sockunion_family(&mcast->nbma_addr)
-+ == AF_UNSPEC
-+ ? "dynamic"
-+ : sockunion2str(
-+ &mcast->nbma_addr,
-+ buf, sizeof(buf)));
-+ }
- }
-
- vty_endframe(vty, "!\n");
-@@ -1142,6 +1233,8 @@ void nhrp_config_init(void)
- install_element(CONFIG_NODE, &no_nhrp_event_socket_cmd);
- install_element(CONFIG_NODE, &nhrp_nflog_group_cmd);
- install_element(CONFIG_NODE, &no_nhrp_nflog_group_cmd);
-+ install_element(CONFIG_NODE, &nhrp_multicast_nflog_group_cmd);
-+ install_element(CONFIG_NODE, &no_nhrp_multicast_nflog_group_cmd);
-
- /* interface specific commands */
- install_node(&nhrp_interface_node);
-@@ -1163,6 +1256,8 @@ void nhrp_config_init(void)
- install_element(INTERFACE_NODE, &if_no_nhrp_reg_flags_cmd);
- install_element(INTERFACE_NODE, &if_nhrp_map_cmd);
- install_element(INTERFACE_NODE, &if_no_nhrp_map_cmd);
-+ install_element(INTERFACE_NODE, &if_nhrp_map_multicast_cmd);
-+ install_element(INTERFACE_NODE, &if_no_nhrp_map_multicast_cmd);
- install_element(INTERFACE_NODE, &if_nhrp_nhs_cmd);
- install_element(INTERFACE_NODE, &if_no_nhrp_nhs_cmd);
- }
---- a/nhrpd/nhrpd.h
-+++ b/nhrpd/nhrpd.h
-@@ -259,6 +259,13 @@ struct nhrp_nhs {
- struct list_head reglist_head;
- };
-
-+struct nhrp_multicast {
-+ struct interface *ifp;
-+ struct list_head list_entry;
-+ afi_t afi;
-+ union sockunion nbma_addr; /* IP-address */
-+};
-+
- struct nhrp_registration {
- struct list_head reglist_entry;
- struct thread *t_register;
-@@ -304,6 +311,7 @@ struct nhrp_interface {
- unsigned short mtu;
- unsigned int holdtime;
- struct list_head nhslist_head;
-+ struct list_head mcastlist_head;
- } afi[AFI_MAX];
- };
-
-@@ -345,6 +353,16 @@ void nhrp_nhs_foreach(struct interface *
- void *ctx);
- void nhrp_nhs_interface_del(struct interface *ifp);
-
-+int nhrp_multicast_add(struct interface *ifp, afi_t afi,
-+ union sockunion *nbma_addr);
-+int nhrp_multicast_del(struct interface *ifp, afi_t afi,
-+ union sockunion *nbma_addr);
-+void nhrp_multicast_interface_del(struct interface *ifp);
-+void nhrp_multicast_foreach(struct interface *ifp, afi_t afi,
-+ void (*cb)(struct nhrp_multicast *, void *),
-+ void *ctx);
-+void netlink_mcast_set_nflog_group(int nlgroup);
-+
- void nhrp_route_update_nhrp(const struct prefix *p, struct interface *ifp);
- void nhrp_route_announce(int add, enum nhrp_cache_type type,
- const struct prefix *p, struct interface *ifp,
---- a/nhrpd/os.h
-+++ b/nhrpd/os.h
-@@ -1,7 +1,7 @@
-
- int os_socket(void);
- int os_sendmsg(const uint8_t *buf, size_t len, int ifindex, const uint8_t *addr,
-- size_t addrlen);
-+ size_t addrlen, uint16_t protocol);
- int os_recvmsg(uint8_t *buf, size_t *len, int *ifindex, uint8_t *addr,
- size_t *addrlen);
- int os_configure_dmvpn(unsigned int ifindex, const char *ifname, int af);
---- a/nhrpd/subdir.am
-+++ b/nhrpd/subdir.am
-@@ -21,6 +21,7 @@ nhrpd_nhrpd_SOURCES = \
- nhrpd/nhrp_nhs.c \
- nhrpd/nhrp_packet.c \
- nhrpd/nhrp_peer.c \
-+ nhrpd/nhrp_multicast.c \
- nhrpd/nhrp_route.c \
- nhrpd/nhrp_shortcut.c \
- nhrpd/nhrp_vc.c \
---- a/ospfd/ospf_interface.c
-+++ b/ospfd/ospf_interface.c
-@@ -534,6 +534,8 @@ static struct ospf_if_params *ospf_new_i
- oip->network_lsa_seqnum = htonl(OSPF_INITIAL_SEQUENCE_NUMBER);
- oip->is_v_wait_set = false;
-
-+ oip->ptp_dmvpn = 0;
-+
- return oip;
- }
-
---- a/ospfd/ospf_interface.h
-+++ b/ospfd/ospf_interface.h
-@@ -105,6 +105,9 @@ struct ospf_if_params {
-
- /* BFD configuration */
- struct bfd_info *bfd_info;
-+
-+ /* point-to-point DMVPN configuration */
-+ uint8_t ptp_dmvpn;
- };
-
- enum { MEMBER_ALLROUTERS = 0,
-@@ -167,6 +170,9 @@ struct ospf_interface {
- /* OSPF Network Type. */
- uint8_t type;
-
-+ /* point-to-point DMVPN configuration */
-+ uint8_t ptp_dmvpn;
-+
- /* State of Interface State Machine. */
- uint8_t state;
-
---- a/ospfd/ospf_lsa.c
-+++ b/ospfd/ospf_lsa.c
-@@ -469,6 +469,12 @@ static char link_info_set(struct stream
- }
-
- /* Describe Point-to-Point link (Section 12.4.1.1). */
-+
-+/* Note: If the interface is configured as point-to-point dmvpn then the other
-+ * end of link is dmvpn hub with point-to-multipoint ospf network type. The
-+ * hub then expects this router to populate the stub network and also Link Data
-+ * Field set to IP Address and not MIB-II ifIndex
-+ */
- static int lsa_link_ptop_set(struct stream **s, struct ospf_interface *oi)
- {
- int links = 0;
-@@ -482,7 +488,8 @@ static int lsa_link_ptop_set(struct stre
- if ((nbr = ospf_nbr_lookup_ptop(oi)))
- if (nbr->state == NSM_Full) {
- if (CHECK_FLAG(oi->connected->flags,
-- ZEBRA_IFA_UNNUMBERED)) {
-+ ZEBRA_IFA_UNNUMBERED)
-+ && !oi->ptp_dmvpn) {
- /* For unnumbered point-to-point networks, the
- Link Data field
- should specify the interface's MIB-II ifIndex
-@@ -500,7 +507,8 @@ static int lsa_link_ptop_set(struct stre
- }
-
- /* no need for a stub link for unnumbered interfaces */
-- if (!CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) {
-+ if (oi->ptp_dmvpn
-+ || !CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) {
- /* Regardless of the state of the neighboring router, we must
- add a Type 3 link (stub network).
- N.B. Options 1 & 2 share basically the same logic. */
---- a/ospfd/ospf_vty.c
-+++ b/ospfd/ospf_vty.c
-@@ -7562,20 +7562,21 @@ DEFUN_HIDDEN (no_ospf_hello_interval,
- return no_ip_ospf_hello_interval(self, vty, argc, argv);
- }
-
--DEFUN (ip_ospf_network,
-- ip_ospf_network_cmd,
-- "ip ospf network <broadcast|non-broadcast|point-to-multipoint|point-to-point>",
-- "IP Information\n"
-- "OSPF interface commands\n"
-- "Network type\n"
-- "Specify OSPF broadcast multi-access network\n"
-- "Specify OSPF NBMA network\n"
-- "Specify OSPF point-to-multipoint network\n"
-- "Specify OSPF point-to-point network\n")
-+DEFUN(ip_ospf_network, ip_ospf_network_cmd,
-+ "ip ospf network <broadcast|non-broadcast|point-to-multipoint|point-to-point [dmvpn]>",
-+ "IP Information\n"
-+ "OSPF interface commands\n"
-+ "Network type\n"
-+ "Specify OSPF broadcast multi-access network\n"
-+ "Specify OSPF NBMA network\n"
-+ "Specify OSPF point-to-multipoint network\n"
-+ "Specify OSPF point-to-point network\n"
-+ "Specify OSPF point-to-point DMVPN network\n")
- {
- VTY_DECLVAR_CONTEXT(interface, ifp);
- int idx = 0;
- int old_type = IF_DEF_PARAMS(ifp)->type;
-+ uint8_t old_ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn;
- struct route_node *rn;
-
- if (old_type == OSPF_IFTYPE_LOOPBACK) {
-@@ -7584,16 +7585,22 @@ DEFUN (ip_ospf_network,
- return CMD_WARNING_CONFIG_FAILED;
- }
-
-+ IF_DEF_PARAMS(ifp)->ptp_dmvpn = 0;
-+
- if (argv_find(argv, argc, "broadcast", &idx))
- IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_BROADCAST;
- else if (argv_find(argv, argc, "non-broadcast", &idx))
- IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_NBMA;
- else if (argv_find(argv, argc, "point-to-multipoint", &idx))
- IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_POINTOMULTIPOINT;
-- else if (argv_find(argv, argc, "point-to-point", &idx))
-+ else if (argv_find(argv, argc, "point-to-point", &idx)) {
- IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_POINTOPOINT;
-+ if (argv_find(argv, argc, "dmvpn", &idx))
-+ IF_DEF_PARAMS(ifp)->ptp_dmvpn = 1;
-+ }
-
-- if (IF_DEF_PARAMS(ifp)->type == old_type)
-+ if (IF_DEF_PARAMS(ifp)->type == old_type
-+ && IF_DEF_PARAMS(ifp)->ptp_dmvpn == old_ptp_dmvpn)
- return CMD_SUCCESS;
-
- SET_IF_PARAM(IF_DEF_PARAMS(ifp), type);
-@@ -7605,6 +7612,7 @@ DEFUN (ip_ospf_network,
- continue;
-
- oi->type = IF_DEF_PARAMS(ifp)->type;
-+ oi->ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn;
-
- if (oi->state > ISM_Down) {
- OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown);
-@@ -7645,6 +7653,7 @@ DEFUN (no_ip_ospf_network,
- struct route_node *rn;
-
- IF_DEF_PARAMS(ifp)->type = ospf_default_iftype(ifp);
-+ IF_DEF_PARAMS(ifp)->ptp_dmvpn = 0;
-
- if (IF_DEF_PARAMS(ifp)->type == old_type)
- return CMD_SUCCESS;
-@@ -9888,6 +9897,10 @@ static int config_write_interface_one(st
- vty_out(vty, " ip ospf network %s",
- ospf_int_type_str
- [params->type]);
-+ if (params->type
-+ == OSPF_IFTYPE_POINTOPOINT
-+ && params->ptp_dmvpn)
-+ vty_out(vty, " dmvpn");
- if (params != IF_DEF_PARAMS(ifp) && rn)
- vty_out(vty, " %s",
- inet_ntoa(
---- a/ospfd/ospfd.c
-+++ b/ospfd/ospfd.c
-@@ -1004,6 +1004,7 @@ static void add_ospf_interface(struct co
- /* If network type is specified previously,
- skip network type setting. */
- oi->type = IF_DEF_PARAMS(co->ifp)->type;
-+ oi->ptp_dmvpn = IF_DEF_PARAMS(co->ifp)->ptp_dmvpn;
-
- /* Add pseudo neighbor. */
- ospf_nbr_self_reset(oi, oi->ospf->router_id);
---- a/doc/user/nhrpd.rst
-+++ b/doc/user/nhrpd.rst
-@@ -189,6 +189,37 @@ and
- https://git.alpinelinux.org/user/tteras/strongswan/log/?h=tteras
- git repositories for the patches.
-
-+.. _multicast-functionality:
-+
-+Multicast Functionality
-+=======================
-+
-+nhrpd can be configured to forward multicast packets, allowing routing
-+protocols that use multicast (such as OSPF) to be supported in the DMVPN
-+network.
-+
-+This support requires an iptables NFLOG rule to allow nhrpd to intercept
-+multicast packets. A second iptables rule is also usually used to drop the
-+original multicast packet.
-+
-+ .. code-block:: shell
-+
-+ iptables -A OUTPUT -d 224.0.0.0/24 -o gre1 -j NFLOG --nflog-group 2
-+ iptables -A OUTPUT -d 224.0.0.0/24 -o gre1 -j DROP
-+
-+.. index:: nhrp multicast-nflog-group (1-65535)
-+.. clicmd:: nhrp multicast-nflog-group (1-65535)
-+
-+ Sets the nflog group that nhrpd will listen on for multicast packets. This
-+ value must match the nflog-group value set in the iptables rule.
-+
-+.. index:: ip nhrp map multicast A.B.C.D|X:X::X:X A.B.C.D|dynamic
-+.. clicmd:: ip nhrp map multicast A.B.C.D|X:X::X:X A.B.C.D|dynamic
-+
-+ Sends multicast packets to the specified NBMA address. If dynamic is
-+ specified then destination NBMA address (or addresses) are learnt
-+ dynamically.
-+
- .. _nhrp-events:
-
- NHRP Events
---- a/doc/user/ospfd.rst
-+++ b/doc/user/ospfd.rst
-@@ -687,8 +687,8 @@ Interfaces
- :clicmd:`ip ospf dead-interval minimal hello-multiplier (2-20)` is also
- specified for the interface.
-
--.. index:: ip ospf network (broadcast|non-broadcast|point-to-multipoint|point-to-point)
--.. clicmd:: ip ospf network (broadcast|non-broadcast|point-to-multipoint|point-to-point)
-+.. index:: ip ospf network (broadcast|non-broadcast|point-to-multipoint|point-to-point [dmvpn])
-+.. clicmd:: ip ospf network (broadcast|non-broadcast|point-to-multipoint|point-to-point [dmvpn])
-
- When configuring a point-to-point network on an interface and the interface
- has a /32 address associated with then OSPF will treat the interface
-@@ -870,6 +870,9 @@ Redistribution
- .. index:: no router zebra
- .. clicmd:: no router zebra
-
-+ When used in a DMVPN network at a spoke, this OSPF will be configured in
-+ point-to-point, but the HUB will be a point-to-multipoint. To make this
-+ topology work, specify the optional 'dmvpn' parameter at the spoke.
-
- .. _showing-ospf-information:
-
---- a/nhrpd/netlink.h
-+++ b/nhrpd/netlink.h
-@@ -13,6 +13,7 @@ union sockunion;
- struct interface;
-
- extern int netlink_nflog_group;
-+extern int netlink_mcast_nflog_group;
- extern int netlink_req_fd;
-
- void netlink_init(void);
---- a/ospfd/ospf_packet.c
-+++ b/ospfd/ospf_packet.c
-@@ -802,7 +802,13 @@ static int ospf_write(struct thread *thr
- inet_ntoa(iph.ip_dst), iph.ip_id, iph.ip_off,
- iph.ip_len, oi->ifp->name, oi->ifp->mtu);
-
-- if (ret < 0)
-+ /* sendmsg will return EPERM if firewall is blocking sending.
-+ * This is a normal situation when 'ip nhrp map multicast xxx'
-+ * is being used to send multicast packets to DMVPN peers. In
-+ * that case the original message is blocked with iptables rule
-+ * causing the EPERM result
-+ */
-+ if (ret < 0 && errno != EPERM)
- flog_err(
- EC_LIB_SOCKET,
- "*** sendmsg in ospf_write failed to %s, id %d, off %d, len %d, interface %s, mtu %u: %s",
-@@ -910,8 +916,11 @@ static void ospf_hello(struct ip *iph, s
-
- /* Compare network mask. */
- /* Checking is ignored for Point-to-Point and Virtual link. */
-+ /* Checking is also ignored for Point-to-Multipoint with /32 prefix */
- if (oi->type != OSPF_IFTYPE_POINTOPOINT
-- && oi->type != OSPF_IFTYPE_VIRTUALLINK)
-+ && oi->type != OSPF_IFTYPE_VIRTUALLINK
-+ && !(oi->type == OSPF_IFTYPE_POINTOMULTIPOINT
-+ && oi->address->prefixlen == IPV4_MAX_BITLEN))
- if (oi->address->prefixlen != p.prefixlen) {
- flog_warn(
- EC_OSPF_PACKET,
-@@ -2439,6 +2448,11 @@ static int ospf_check_network_mask(struc
- || oi->type == OSPF_IFTYPE_VIRTUALLINK)
- return 1;
-
-+ /* Ignore mask check for max prefix length (32) */
-+ if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT
-+ && oi->address->prefixlen == IPV4_MAX_BITLEN)
-+ return 1;
-+
- masklen2ip(oi->address->prefixlen, &mask);
-
- me.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
+++ /dev/null
-From 354196c027e81affb05163a6c3676eef1ba06dd9 Mon Sep 17 00:00:00 2001
-From: Zoran Pericic <zpericic@netst.org>
-Date: Sat, 25 Jan 2020 19:38:39 +0100
-Subject: [PATCH] nhrp: Make vici socket path configurable
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-nhrp: Configure vici socket path using
-
-configure --with-vici-socket=/var/run/charon.vici
-
-If not specified default to /var/run/charon.vici
-
-Signed-off-by: Zoran Peričić <zpericic@netst.org>
----
- configure.ac | 8 ++++++++
- doc/user/installation.rst | 4 ++++
- nhrpd/README.nhrpd | 3 ++-
- nhrpd/vici.c | 2 +-
- 4 files changed, 15 insertions(+), 2 deletions(-)
-
---- a/configure.ac
-+++ b/configure.ac
-@@ -139,6 +139,13 @@ AC_ARG_WITH([yangmodelsdir], [AS_HELP_ST
- ])
- AC_SUBST([yangmodelsdir])
-
-+AC_ARG_WITH([vici-socket], [AS_HELP_STRING([--with-vici-socket=PATH], [vici-socket (/var/run/charon.vici)])], [
-+ vici_socket="$withval"
-+], [
-+ vici_socket="/var/run/charon.vici"
-+])
-+AC_DEFINE_UNQUOTED([VICI_SOCKET], ["$vici_socket"], [StrongSWAN vici socket path])
-+
- AC_ARG_ENABLE(tcmalloc,
- AS_HELP_STRING([--enable-tcmalloc], [Turn on tcmalloc]),
- [case "${enableval}" in
-@@ -2480,6 +2487,7 @@ group for vty sockets : ${enable_vty_g
- config file mask : ${enable_configfile_mask}
- log file mask : ${enable_logfile_mask}
- zebra protobuf enabled : ${enable_protobuf:-no}
-+vici socket path : ${vici_socket}
-
- The above user and group must have read/write access to the state file
- directory and to the config files in the config file directory."
---- a/doc/user/installation.rst
-+++ b/doc/user/installation.rst
-@@ -383,6 +383,10 @@ options to the configuration script.
- Look for YANG modules in `dir` [`prefix`/share/yang]. Note that the FRR
- YANG modules will be installed here.
-
-+.. option:: --with-vici-socket <path>
-+
-+ Set StrongSWAN vici interface socket path [/var/run/charon.vici].
-+
- Python dependency, documentation and tests
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
---- a/nhrpd/README.nhrpd
-+++ b/nhrpd/README.nhrpd
-@@ -126,7 +126,8 @@ Integration with strongSwan
-
- Contrary to opennhrp, Quagga/NHRP has tight integration with IKE daemon.
- Currently strongSwan is supported using the VICI protocol. strongSwan
--is connected using UNIX socket (hardcoded now as /var/run/charon.vici).
-+is connected using UNIX socket (default /var/run/charon.vici use configure
-+argument --with-vici-socket= to change).
- Thus nhrpd needs to be run as user that can open that file.
-
- Currently, you will need patched strongSwan. The working tree is at:
---- a/nhrpd/vici.c
-+++ b/nhrpd/vici.c
-@@ -478,7 +478,7 @@ static int vici_reconnect(struct thread
- if (vici->fd >= 0)
- return 0;
-
-- fd = sock_open_unix("/var/run/charon.vici");
-+ fd = sock_open_unix(VICI_SOCKET);
- if (fd < 0) {
- debugf(NHRP_DEBUG_VICI,
- "%s: failure connecting VICI socket: %s", __func__,
--- a/lib/northbound.h
+++ b/lib/northbound.h
-@@ -569,11 +569,7 @@ struct frr_yang_module_info {
+@@ -592,11 +592,7 @@ struct frr_yang_module_info {
/* Priority - lower priorities are processed first. */
uint32_t priority;
--- a/lib/thread.c
+++ b/lib/thread.c
-@@ -723,13 +723,9 @@ static void thread_free(struct thread_ma
+@@ -824,13 +824,9 @@ static void thread_free(struct thread_ma
XFREE(MTYPE_THREAD, thread);
}
/*
* If timer_wait is null here, that means poll() should block
* indefinitely, unless the thread_master has overridden it by setting
-@@ -760,58 +756,15 @@ static int fd_poll(struct thread_master
+@@ -861,58 +857,15 @@ static int fd_poll(struct thread_master
rcu_assert_read_unlocked();
/* add poll pipe poker */
- /* Don't make any changes for the non-main pthreads */
- pthread_sigmask(SIG_SETMASK, NULL, &origsigs);
- }
--
++ assert(count + 1 < pfdsize);
++ pfds[count].fd = m->io_pipe[0];
++ pfds[count].events = POLLIN;
++ pfds[count].revents = 0x00;
+
-#if defined(HAVE_PPOLL)
- struct timespec ts, *tsp;
--
++ num = poll(pfds, count + 1, timeout);
+
- if (timeout >= 0) {
- ts.tv_sec = timeout / 1000;
- ts.tv_nsec = (timeout % 1000) * 1000000;
-#endif
-
-done:
-+ assert(count + 1 < pfdsize);
-+ pfds[count].fd = m->io_pipe[0];
-+ pfds[count].events = POLLIN;
-+ pfds[count].revents = 0x00;
-
+-
- if (num < 0 && errno == EINTR)
- *eintr_p = true;
-+ num = poll(pfds, count + 1, timeout);
-
+-
- if (num > 0 && m->handler.copy[count].revents != 0 && num--)
+ unsigned char trash[64];
+ if (num > 0 && pfds[count].revents != 0 && num--)
while (read(m->io_pipe[0], &trash, sizeof(trash)) > 0)
;
-@@ -1438,7 +1391,7 @@ struct thread *thread_fetch(struct threa
+@@ -1700,7 +1653,7 @@ struct thread *thread_fetch(struct threa
struct timeval zerotime = {0, 0};
struct timeval tv;
struct timeval *tw = NULL;
int num = 0;
do {
-@@ -1510,14 +1463,14 @@ struct thread *thread_fetch(struct threa
+@@ -1776,14 +1729,14 @@ struct thread *thread_fetch(struct threa
pthread_mutex_unlock(&m->mtx);
{