Merge pull request #14948 from lucize/frrup

frr: update to latest and backports
This commit is contained in:
Rosen Penev 2021-02-28 11:33:46 -08:00 committed by GitHub
commit 7b89bbe3ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 2838 additions and 5 deletions

View File

@ -8,15 +8,15 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=frr
PKG_VERSION:=7.5
PKG_RELEASE:=4
PKG_SOURCE_DATE:=2021-02-05
PKG_RELEASE:=5
PKG_SOURCE_DATE:=2021-02-26
PKG_SOURCE:=$(PKG_NAME)-$(PKG_SOURCE_DATE).tar.gz
PKG_SOURCE_VERSION:=20b35e4c3386de798f3b0cb9f2a7e6b04d995485
PKG_SOURCE_VERSION:=13a8efb4b6e3c92e8b9361c9cb1e78a86b0194cf
PKG_SOURCE_URL:=https://codeload.github.com/FRRouting/frr/tar.gz/$(PKG_SOURCE_VERSION)?
PKG_HASH:=f3b4a4ce43ad60fcf4b908dc4467cbc9dae277b5829489b3d221913e043dd250
PKG_HASH:=6e313edff69cd12444b53dbc5593892b280280b7735e620c00189a669f80bdcc
PKG_MAINTAINER:=Lucian Cristian <lucian.cristian@gmail.com>
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_SOURCE_VERSION)

View File

@ -0,0 +1,385 @@
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,

View File

@ -0,0 +1,48 @@
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,

View File

@ -0,0 +1,226 @@
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);

View File

@ -0,0 +1,383 @@
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. */
@@ -839,14 +890,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)
@@ -864,6 +912,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
@@ -523,7 +523,11 @@ extern struct ospf *ospf_lookup_by_inst_
const char *name);
extern struct ospf *ospf_lookup_by_vrf_id(vrf_id_t vrf_id);
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 *,
@@ -548,6 +552,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);

View File

@ -0,0 +1,105 @@
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
@@ -1932,35 +1932,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
@@ -567,8 +567,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);

View File

@ -0,0 +1,797 @@
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;
}
@@ -3324,11 +3330,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)
@@ -4014,11 +4020,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)
@@ -4407,11 +4413,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)
@@ -4619,11 +4625,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();
@@ -4759,11 +4765,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)
@@ -5168,11 +5174,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,
@@ -5341,11 +5347,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)
@@ -5536,11 +5542,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)
@@ -5668,11 +5674,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,
@@ -6418,10 +6424,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,
@@ -6482,15 +6489,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);
}
@@ -6576,13 +6580,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));
@@ -8033,7 +8036,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
@@ -8158,7 +8161,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;
@@ -468,36 +470,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
@@ -507,6 +507,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;
@@ -516,9 +517,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");

View File

@ -0,0 +1,793 @@
From f9ff7bf497894b74fd02d54dc0f0a39981f7cc06 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 1/6] 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 | 312 +++++++++++++++++++++++++++++++++++++++++
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, 403 insertions(+), 7 deletions(-)
create mode 100644 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>
@@ -42,7 +43,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 +62,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,
--- 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,312 @@
+/* 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")
+
+static int netlink_mcast_nflog_group;
+static int netlink_mcast_log_fd = -1;
+static struct thread *netlink_mcast_log_thread;
+static int nhrp_multicast_ip_count;
+
+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 ? 0x0800 : 0x86DD);
+
+ 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, pktpl;
+ struct interface *ifp;
+ uint32_t *out_ndx = NULL;
+ afi_t afi;
+ struct mcast_ctx ctx;
+
+ debugf(NHRP_DEBUG_COMMON,"Inside %s\n", __func__);
+
+ nf = znl_pull(zb, sizeof(*nf));
+ if (!nf)
+ return;
+
+ memset(&pktpl, 0, sizeof(pktpl));
+ 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:
+ pktpl = 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 || !zbuf_used(&pktpl))
+ return;
+
+ ifp = if_lookup_by_index(htonl(*out_ndx), VRF_DEFAULT);
+ if (!ifp)
+ return;
+
+ debugf(NHRP_DEBUG_COMMON,"Outgoing interface = %s\n", ifp->name);
+
+ ctx = (struct mcast_ctx) {
+ .ifp = ifp,
+ .pkt = &pktpl,
+ };
+
+ for (afi = 0; afi < AFI_MAX; afi++) {
+ nhrp_multicast_foreach(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);
+}
+
+static void netlink_mcast_set_nflog_group(struct interface *ifp, 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);
+ if (--nhrp_multicast_ip_count == 0)
+ netlink_mcast_set_nflog_group(ifp, 0);
+ 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);
+
+ if (netlink_mcast_log_fd == -1)
+ netlink_mcast_set_nflog_group(ifp, MCAST_NFLOG_GROUP);
+
+ nhrp_multicast_ip_count++;
+
+ sockunion2str(nbma_addr, buf, sizeof(buf));
+ debugf(NHRP_DEBUG_COMMON, "Adding multicast entry (%s) [%d]", buf, nhrp_multicast_ip_count);
+
+ 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) [%d]", buf, nhrp_multicast_ip_count);
+
+ 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, %d)", !list_empty(&nifp->afi[afi].mcastlist_head), nhrp_multicast_ip_count);
+
+ 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,8 @@ 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
@@ -569,6 +569,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
@@ -1040,6 +1087,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];
@@ -1109,6 +1157,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");
@@ -1163,6 +1224,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
@@ -24,6 +24,7 @@ DECLARE_MGROUP(NHRPD)
#define NHRP_VTY_PORT 2610
#define NHRP_DEFAULT_CONFIG "nhrpd.conf"
+#define MCAST_NFLOG_GROUP 224
extern struct thread_master *master;
@@ -259,6 +260,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 +312,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 +354,13 @@ 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 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
@@ -7560,20 +7560,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) {
@@ -7582,16 +7583,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);
@@ -7603,6 +7610,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);
@@ -7643,6 +7651,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
@@ -1017,6 +1017,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,34 @@ 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 NFLOG redirection rule to work:
+
+ .. code-block:: shell
+
+ iptables -I OUTPUT -d 224.0.0.0/24 -o gre1 -j NFLOG --nflog-group 2
+
+.. 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:

View File

@ -0,0 +1,96 @@
From bd9caa8f11d931db21f628ad61be042147861ad4 Mon Sep 17 00:00:00 2001
From: Mark Stapp <mjs@voltanet.io>
Date: Fri, 26 Feb 2021 11:16:09 -0500
Subject: [PATCH 1/3] lib: fix some misc SA warnings
- clippy.c: fix valid memleak
- defun_lex.l: suppress warnings in generated code
- northbound_cli.c: suppress warning in eldritch libyang macro
Signed-off-by: Quentin Young <qlyoung@nvidia.com>
---
lib/clippy.c | 4 +++-
lib/defun_lex.l | 4 ++++
lib/northbound_cli.c | 12 ++++++++++++
3 files changed, 19 insertions(+), 1 deletion(-)
--- a/lib/clippy.c
+++ b/lib/clippy.c
@@ -51,7 +51,8 @@ int main(int argc, char **argv)
#if PY_VERSION_HEX >= 0x03040000 /* 3.4 */
Py_SetStandardStreamEncoding("UTF-8", NULL);
#endif
- Py_SetProgramName(wconv(argv[0]));
+ wchar_t *name = wconv(argv[0]);
+ Py_SetProgramName(name);
PyImport_AppendInittab("_clippy", command_py_init);
Py_Initialize();
@@ -67,6 +68,8 @@ int main(int argc, char **argv)
fp = fopen(pyfile, "r");
if (!fp) {
fprintf(stderr, "%s: %s\n", pyfile, strerror(errno));
+
+ free(name);
return 1;
}
} else {
@@ -85,6 +88,8 @@ int main(int argc, char **argv)
if (PyRun_AnyFile(fp, pyfile)) {
if (PyErr_Occurred())
PyErr_Print();
+
+ free(name);
return 1;
}
Py_Finalize();
@@ -93,6 +98,7 @@ int main(int argc, char **argv)
for (int i = 1; i < argc; i++)
free(wargv[i - 1]);
#endif
+ free(name);
free(wargv);
return 0;
}
--- a/lib/defun_lex.l
+++ b/lib/defun_lex.l
@@ -80,6 +80,8 @@ static void extendbuf(char **what, const
}
#define extend(x) extendbuf(&value, x)
+#ifndef __clang_analyzer__
+
%}
ID [A-Za-z0-9_]+
@@ -157,6 +159,8 @@ SPECIAL [(),]
%%
+#endif /* __clang_analyzer__ */
+
static int yylex_clr(char **retbuf)
{
int rv = def_yylex();
--- a/lib/northbound_cli.c
+++ b/lib/northbound_cli.c
@@ -595,7 +595,19 @@ void nb_cli_show_dnode_cmds(struct vty *
(*nb_node->cbs.cli_show_end)(vty, parent);
}
+ /*
+ * There is a possible path in this macro that ends up
+ * dereferencing child->parent->parent. We just null checked
+ * child->parent by checking (ly_iter_next_up(child) != NULL)
+ * above.
+ *
+ * I am not sure whether it is possible for the other
+ * conditions within this macro guarding the problem
+ * dereference to be satisfied when child->parent == NULL.
+ */
+#ifndef __clang_analyzer__
LY_TREE_DFS_END(root, next, child);
+#endif
}
}

View File

@ -1,6 +1,6 @@
--- a/lib/northbound.h
+++ b/lib/northbound.h
@@ -562,11 +562,7 @@ struct frr_yang_module_info {
@@ -569,11 +569,7 @@ struct frr_yang_module_info {
/* Priority - lower priorities are processed first. */
uint32_t priority;