Compare commits
15 Commits
frr-7.4-1.
...
frr-7.5.1-
| Author | SHA1 | Date | |
|---|---|---|---|
| bbdf53f4bd | |||
| d804566770 | |||
|
|
3b172a04b7 | ||
|
|
9dbdfc757a | ||
|
|
15263f01a6 | ||
|
|
3d27b07fe4 | ||
|
|
549c517210 | ||
|
|
6295fc893e | ||
|
|
0d34206229 | ||
|
|
69f43ae016 | ||
|
|
cc5d8e11bc | ||
|
|
6eb34bb459 | ||
|
|
57c898887f | ||
|
|
fbca0aec49 | ||
|
|
3f446986bd |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,2 +1,8 @@
|
|||||||
/frr-7.1.tar.gz
|
/frr-7.1.tar.gz
|
||||||
/frr-7.2.tar.gz
|
/frr-7.2.tar.gz
|
||||||
|
/frr-7.3.tar.gz
|
||||||
|
/remove-babeld-ldpd.sh
|
||||||
|
/frr-7.3.1.tar.gz
|
||||||
|
/frr-7.4.tar.gz
|
||||||
|
/frr-7.5.tar.gz
|
||||||
|
/frr-7.5.1.tar.gz
|
||||||
|
|||||||
@@ -8,3 +8,13 @@ index 208fb11..0692adc 100755
|
|||||||
# Frr Reloader
|
# Frr Reloader
|
||||||
# Copyright (C) 2014 Cumulus Networks, Inc.
|
# Copyright (C) 2014 Cumulus Networks, Inc.
|
||||||
#
|
#
|
||||||
|
diff --git a/tools/generate_support_bundle.py b/tools/generate_support_bundle.py
|
||||||
|
index 540b7a1..0876ebb 100755
|
||||||
|
--- a/tools/generate_support_bundle.py
|
||||||
|
+++ b/tools/generate_support_bundle.py
|
||||||
|
@@ -1,4 +1,4 @@
|
||||||
|
-#!/usr/bin/python
|
||||||
|
+#!/usr/bin/python3
|
||||||
|
|
||||||
|
########################################################
|
||||||
|
### Python Script to generate the FRR support bundle ###
|
||||||
|
|||||||
@@ -3,15 +3,15 @@ index 0b7af18..0533e24 100644
|
|||||||
--- a/lib/subdir.am
|
--- a/lib/subdir.am
|
||||||
+++ b/lib/subdir.am
|
+++ b/lib/subdir.am
|
||||||
@@ -41,7 +41,6 @@ lib_libfrr_la_SOURCES = \
|
@@ -41,7 +41,6 @@ lib_libfrr_la_SOURCES = \
|
||||||
lib/linklist.c \
|
|
||||||
lib/log.c \
|
lib/log.c \
|
||||||
|
lib/log_filter.c \
|
||||||
lib/log_vty.c \
|
lib/log_vty.c \
|
||||||
- lib/md5.c \
|
- lib/md5.c \
|
||||||
lib/memory.c \
|
lib/memory.c \
|
||||||
lib/memory_vty.c \
|
|
||||||
lib/mlag.c \
|
lib/mlag.c \
|
||||||
|
lib/module.c \
|
||||||
@@ -64,7 +64,6 @@ lib_libfrr_la_SOURCES = \
|
@@ -64,7 +64,6 @@ lib_libfrr_la_SOURCES = \
|
||||||
lib/routemap.c \
|
lib/routemap_northbound.c \
|
||||||
lib/sbuf.c \
|
lib/sbuf.c \
|
||||||
lib/seqlock.c \
|
lib/seqlock.c \
|
||||||
- lib/sha256.c \
|
- lib/sha256.c \
|
||||||
@@ -24,8 +24,8 @@ index 0b7af18..0533e24 100644
|
|||||||
lib/log_vty.h \
|
lib/log_vty.h \
|
||||||
- lib/md5.h \
|
- lib/md5.h \
|
||||||
lib/memory.h \
|
lib/memory.h \
|
||||||
lib/memory_vty.h \
|
|
||||||
lib/module.h \
|
lib/module.h \
|
||||||
|
lib/monotime.h \
|
||||||
@@ -191,7 +190,6 @@ pkginclude_HEADERS += \
|
@@ -191,7 +190,6 @@ pkginclude_HEADERS += \
|
||||||
lib/routemap.h \
|
lib/routemap.h \
|
||||||
lib/sbuf.h \
|
lib/sbuf.h \
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
diff --git a/tests/lib/test_typelist.h b/tests/lib/test_typelist.h
|
|
||||||
index f20bbc52d..9039fa8a4 100644
|
|
||||||
--- a/tests/lib/test_typelist.h
|
|
||||||
+++ b/tests/lib/test_typelist.h
|
|
||||||
@@ -98,12 +98,13 @@ static void ts_hash(const char *text, const char *expect)
|
|
||||||
unsigned i = 0;
|
|
||||||
uint8_t hash[32];
|
|
||||||
char hashtext[65];
|
|
||||||
- uint32_t count;
|
|
||||||
+ uint32_t swap_count, count;
|
|
||||||
|
|
||||||
- count = htonl(list_count(&head));
|
|
||||||
+ count = list_count(&head);
|
|
||||||
+ swap_count = htonl(count);
|
|
||||||
|
|
||||||
SHA256_Init(&ctx);
|
|
||||||
- SHA256_Update(&ctx, &count, sizeof(count));
|
|
||||||
+ SHA256_Update(&ctx, &swap_count, sizeof(swap_count));
|
|
||||||
|
|
||||||
frr_each (list, &head, item) {
|
|
||||||
struct {
|
|
||||||
@@ -115,7 +115,7 @@ static void ts_hash(const char *text, const char *expect)
|
|
||||||
};
|
|
||||||
SHA256_Update(&ctx, &hashitem, sizeof(hashitem));
|
|
||||||
i++;
|
|
||||||
- assert(i < count);
|
|
||||||
+ assert(i <= count);
|
|
||||||
}
|
|
||||||
SHA256_Final(hash, &ctx);
|
|
||||||
|
|
||||||
385
046-nhrpd_cache_config_fixes.patch
Normal file
385
046-nhrpd_cache_config_fixes.patch
Normal 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,
|
||||||
48
047-nhrpd_fix_SA_warning.patch
Normal file
48
047-nhrpd_fix_SA_warning.patch
Normal 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,
|
||||||
226
048-nhrpd_cleanup_resources.patch
Normal file
226
048-nhrpd_cleanup_resources.patch
Normal 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);
|
||||||
383
049-clear_ip_ospf_process_and_neighbor.patch
Normal file
383
049-clear_ip_ospf_process_and_neighbor.patch
Normal 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);
|
||||||
105
050-ospf_nbr_nbma_lookup_next.patch
Normal file
105
050-ospf_nbr_nbma_lookup_next.patch
Normal 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);
|
||||||
797
051-ospfd_instance_fixes.patch
Normal file
797
051-ospfd_instance_fixes.patch
Normal 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");
|
||||||
964
052-nhrpd_support_for_multicast.patch
Normal file
964
052-nhrpd_support_for_multicast.patch
Normal file
@@ -0,0 +1,964 @@
|
|||||||
|
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
|
||||||
|
@@ -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,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;
|
||||||
70
053-nhrpd_replace_socket.patch
Normal file
70
053-nhrpd_replace_socket.patch
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
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/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__,
|
||||||
1
frr-tmpfiles.conf
Normal file
1
frr-tmpfiles.conf
Normal file
@@ -0,0 +1 @@
|
|||||||
|
d /run/frr 0755 frr frr -
|
||||||
81
frr.spec
81
frr.spec
@@ -1,20 +1,22 @@
|
|||||||
%global frrversion 7.2
|
%global frrversion 7.5.1
|
||||||
%global frr_libdir /usr/lib/frr
|
%global frr_libdir /usr/lib/frr
|
||||||
|
%global checkout .st.2
|
||||||
|
|
||||||
%global _hardened_build 1
|
%global _hardened_build 1
|
||||||
|
%define _legacy_common_support 1
|
||||||
|
|
||||||
Name: frr
|
Name: frr
|
||||||
Version: 7.2
|
Version: 7.5.1
|
||||||
Release: 2%{?checkout}%{?dist}
|
Release: 2%{?checkout}%{?dist}
|
||||||
Summary: Routing daemon
|
Summary: Routing daemon
|
||||||
License: GPLv2+
|
License: GPLv2+
|
||||||
URL: http://www.frrouting.org
|
URL: http://www.frrouting.org
|
||||||
Source0: https://github.com/FRRouting/frr/releases/download/%{name}-%{frrversion}/%{name}-%{frrversion}.tar.gz
|
Source0: https://github.com/FRRouting/frr/releases/download/%{name}-%{frrversion}/%{name}-%{frrversion}.tar.gz
|
||||||
|
Source1: %{name}-tmpfiles.conf
|
||||||
BuildRequires: perl-generators
|
BuildRequires: perl-generators
|
||||||
BuildRequires: systemd
|
|
||||||
BuildRequires: gcc
|
BuildRequires: gcc
|
||||||
BuildRequires: net-snmp-devel
|
BuildRequires: net-snmp-devel
|
||||||
BuildRequires: texinfo libcap-devel texi2html autoconf automake libtool patch groff
|
BuildRequires: texinfo libcap-devel autoconf automake libtool patch groff
|
||||||
BuildRequires: readline readline-devel ncurses ncurses-devel
|
BuildRequires: readline readline-devel ncurses ncurses-devel
|
||||||
BuildRequires: git pam-devel c-ares-devel
|
BuildRequires: git pam-devel c-ares-devel
|
||||||
BuildRequires: json-c-devel bison >= 2.7 flex perl-XML-LibXML
|
BuildRequires: json-c-devel bison >= 2.7 flex perl-XML-LibXML
|
||||||
@@ -33,7 +35,16 @@ Patch0001: 0001-use-python3.patch
|
|||||||
Patch0002: 0002-enable-openssl.patch
|
Patch0002: 0002-enable-openssl.patch
|
||||||
Patch0003: 0003-disable-eigrp-crypto.patch
|
Patch0003: 0003-disable-eigrp-crypto.patch
|
||||||
Patch0004: 0004-fips-mode.patch
|
Patch0004: 0004-fips-mode.patch
|
||||||
Patch0005: 0005-test-typelist-power.patch
|
|
||||||
|
Patch0060: 046-nhrpd_cache_config_fixes.patch
|
||||||
|
Patch0061: 047-nhrpd_fix_SA_warning.patch
|
||||||
|
Patch0062: 048-nhrpd_cleanup_resources.patch
|
||||||
|
Patch0063: 049-clear_ip_ospf_process_and_neighbor.patch
|
||||||
|
Patch0064: 050-ospf_nbr_nbma_lookup_next.patch
|
||||||
|
Patch0065: 051-ospfd_instance_fixes.patch
|
||||||
|
Patch0066: 052-nhrpd_support_for_multicast.patch
|
||||||
|
Patch0067: 053-nhrpd_replace_socket.patch
|
||||||
|
|
||||||
|
|
||||||
%description
|
%description
|
||||||
FRRouting is free software that manages TCP/IP based routing protocols. It takes
|
FRRouting is free software that manages TCP/IP based routing protocols. It takes
|
||||||
@@ -72,6 +83,7 @@ autoreconf -ivf
|
|||||||
--disable-babeld \
|
--disable-babeld \
|
||||||
--with-moduledir=%{_libdir}/frr/modules \
|
--with-moduledir=%{_libdir}/frr/modules \
|
||||||
--with-crypto=openssl \
|
--with-crypto=openssl \
|
||||||
|
--with-vici-socket=/run/strongswan/charon.vici \
|
||||||
--enable-fpm
|
--enable-fpm
|
||||||
|
|
||||||
%make_build MAKEINFO="makeinfo --no-split" PYTHON=%{__python3}
|
%make_build MAKEINFO="makeinfo --no-split" PYTHON=%{__python3}
|
||||||
@@ -86,12 +98,14 @@ mkdir -p %{buildroot}/etc/{frr,rc.d/init.d,sysconfig,logrotate.d,pam.d,default}
|
|||||||
%{buildroot}%{_unitdir}
|
%{buildroot}%{_unitdir}
|
||||||
|
|
||||||
mkdir -p -m 0755 %{buildroot}%{_libdir}/frr
|
mkdir -p -m 0755 %{buildroot}%{_libdir}/frr
|
||||||
|
mkdir -p %{buildroot}%{_tmpfilesdir}
|
||||||
|
|
||||||
%make_install
|
%make_install
|
||||||
|
|
||||||
# Remove this file, as it is uninstalled and causes errors when building on RH9
|
# Remove this file, as it is uninstalled and causes errors when building on RH9
|
||||||
rm -rf %{buildroot}/usr/share/info/dir
|
rm -rf %{buildroot}/usr/share/info/dir
|
||||||
|
|
||||||
|
install -p -m 644 %{SOURCE1} %{buildroot}%{_tmpfilesdir}/%{name}.conf
|
||||||
install -p -m 644 %{_builddir}/%{name}-%{frrversion}/tools/etc/frr/daemons %{buildroot}/etc/frr/daemons
|
install -p -m 644 %{_builddir}/%{name}-%{frrversion}/tools/etc/frr/daemons %{buildroot}/etc/frr/daemons
|
||||||
install -p -m 644 %{_builddir}/%{name}-%{frrversion}/tools/frr.service %{buildroot}%{_unitdir}/frr.service
|
install -p -m 644 %{_builddir}/%{name}-%{frrversion}/tools/frr.service %{buildroot}%{_unitdir}/frr.service
|
||||||
install -p -m 755 %{_builddir}/%{name}-%{frrversion}/tools/frrinit.sh %{buildroot}%{frr_libdir}/frr
|
install -p -m 755 %{_builddir}/%{name}-%{frrversion}/tools/frrinit.sh %{buildroot}%{frr_libdir}/frr
|
||||||
@@ -130,6 +144,13 @@ if [ ! -e %{_sysconfdir}/frr/frr.conf ]; then
|
|||||||
chmod 640 %{_sysconfdir}/frr/frr.conf
|
chmod 640 %{_sysconfdir}/frr/frr.conf
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
#still used by vtysh, this way no error is produced when using vtysh
|
||||||
|
if [ ! -e %{_sysconfdir}/frr/vtysh.conf ]; then
|
||||||
|
touch %{_sysconfdir}/frr/vtysh.conf
|
||||||
|
chmod 640 %{_sysconfdir}/frr/vtysh.conf
|
||||||
|
chown frr:frrvty %{_sysconfdir}/frr/vtysh.conf
|
||||||
|
fi
|
||||||
|
|
||||||
%postun
|
%postun
|
||||||
%systemd_postun_with_restart frr.service
|
%systemd_postun_with_restart frr.service
|
||||||
|
|
||||||
@@ -158,24 +179,68 @@ make check PYTHON=%{__python3}
|
|||||||
%doc ripngd/ripngd.conf.sample
|
%doc ripngd/ripngd.conf.sample
|
||||||
%doc pimd/pimd.conf.sample
|
%doc pimd/pimd.conf.sample
|
||||||
%doc doc/mpls
|
%doc doc/mpls
|
||||||
%dir %attr(755,frr,frr) %{_sysconfdir}/frr
|
%dir %attr(750,frr,frr) %{_sysconfdir}/frr
|
||||||
%dir %attr(755,frr,frr) /var/log/frr
|
%dir %attr(755,frr,frr) /var/log/frr
|
||||||
%dir %attr(755,frr,frr) /run/frr
|
%dir %attr(755,frr,frr) /run/frr
|
||||||
%{_infodir}/*info*
|
%{_infodir}/*info*
|
||||||
%{_mandir}/man*/*
|
%{_mandir}/man*/*
|
||||||
|
%dir %{frr_libdir}/
|
||||||
%{frr_libdir}/*
|
%{frr_libdir}/*
|
||||||
%{_bindir}/*
|
%{_bindir}/*
|
||||||
%dir %{_libdir}/frr
|
%dir %{_libdir}/frr
|
||||||
%{_libdir}/frr/*.so.*
|
%{_libdir}/frr/*.so.*
|
||||||
|
%dir %{_libdir}/frr/modules
|
||||||
%{_libdir}/frr/modules/*
|
%{_libdir}/frr/modules/*
|
||||||
%config(noreplace) %attr(644,root,root) /etc/logrotate.d/frr
|
%config(noreplace) %attr(644,root,root) /etc/logrotate.d/frr
|
||||||
%config(noreplace) /etc/frr/daemons
|
%config(noreplace) %attr(644,frr,frr) /etc/frr/daemons
|
||||||
%config(noreplace) /etc/pam.d/frr
|
%config(noreplace) /etc/pam.d/frr
|
||||||
%{_unitdir}/*.service
|
%{_unitdir}/*.service
|
||||||
|
%dir /usr/share/yang
|
||||||
/usr/share/yang/*.yang
|
/usr/share/yang/*.yang
|
||||||
#%%{_libdir}/frr/frr/libyang_plugins/*
|
%{_tmpfilesdir}/%{name}.conf
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Fri Apr 23 2021 Michal Ruprich <mruprich@redhat.com> - 7.5.1-2
|
||||||
|
- Fixing permissions on config files in /etc/frr
|
||||||
|
- Enabling integrated configuration option for frr
|
||||||
|
|
||||||
|
* Tue Mar 16 2021 Michal Ruprich <mruprich@redhat.com> - 7.5.1-1
|
||||||
|
- New version 7.5.1
|
||||||
|
|
||||||
|
* Fri Jan 01 2021 Michal Ruprich <mruprich@redhat.com> - 7.5-1
|
||||||
|
- New version 7.5
|
||||||
|
|
||||||
|
* Mon Sep 21 2020 Michal Ruprich <mruprich@redhat.com> - 7.4-1
|
||||||
|
- New version 7.4
|
||||||
|
|
||||||
|
* Thu Aug 27 2020 Josef Řídký <jridky@redhat.com> - 7.3.1-4
|
||||||
|
- Rebuilt for new net-snmp release
|
||||||
|
|
||||||
|
* Mon Jul 27 2020 Fedora Release Engineering <releng@fedoraproject.org> - 7.3.1-3
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
|
||||||
|
|
||||||
|
* Thu Jun 18 2020 Michal Ruprich <mruprich@redhat.com.com> - 7.3.1-1
|
||||||
|
- New version 7.3.1
|
||||||
|
- Fixes a couple of bugs(#1832259, #1835039, #1830815, #1830808, #1830806, #1830800, #1830798, #1814773)
|
||||||
|
|
||||||
|
* Tue May 19 2020 Michal Ruprich <mruprich@redhat.com.com> - 7.3-6
|
||||||
|
- Removing texi2html, it is not available in Rawhide anymore
|
||||||
|
|
||||||
|
* Mon May 18 2020 Michal Ruprich <mruprich@redhat.com.com> - 7.3-5
|
||||||
|
- Rebuild for new version of libyang
|
||||||
|
|
||||||
|
* Tue Apr 21 2020 Björn Esser <besser82@fedoraproject.org> - 7.3-4
|
||||||
|
- Rebuild (json-c)
|
||||||
|
|
||||||
|
* Mon Apr 13 2020 Björn Esser <besser82@fedoraproject.org> - 7.3-3
|
||||||
|
- Update json-c-0.14 patch with a solution from upstream
|
||||||
|
|
||||||
|
* Mon Apr 13 2020 Björn Esser <besser82@fedoraproject.org> - 7.3-2
|
||||||
|
- Add support for upcoming json-c 0.14.0
|
||||||
|
|
||||||
|
* Wed Feb 19 2020 Michal Ruprich <mruprich@redhat.com> - 7.3-1
|
||||||
|
- New version 7.3
|
||||||
|
|
||||||
* Tue Jan 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 7.2-2
|
* Tue Jan 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 7.2-2
|
||||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
|
||||||
|
|
||||||
|
|||||||
3
sources
3
sources
@@ -1 +1,2 @@
|
|||||||
SHA512 (frr-7.2.tar.gz) = a99cd23ef9499e28fdf3b2d23993e4a9bcfea3c5eb4c8ddc33ad50b0afab961733729116e01397af9e77918b8c0de5598f6c22bbab92050b548fb5c21e5d81d8
|
SHA512 (frr-7.5.1.tar.gz) = 1c27420594e52647090da3556e5c62d6f916903c4fa86e5110f1e86152f07d3ce4252bc859d36c9d218dc96a80b245c8b9eee97f370d818cb39be187b6c3546e
|
||||||
|
SHA512 (remove-babeld-ldpd.sh) = a5bf67a3722cb20d43cef1dac28f839db68df73a1b7d34d8438e4f9366da3b67d85c1f44281f93434e8dd8ebcb2d3dc258b77eaa5627475b7395d207f020839d
|
||||||
|
|||||||
Reference in New Issue
Block a user