|
|
- 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,
|