summaryrefslogtreecommitdiffstats
path: root/nhrpd/nhrp_interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'nhrpd/nhrp_interface.c')
-rw-r--r--nhrpd/nhrp_interface.c92
1 files changed, 74 insertions, 18 deletions
diff --git a/nhrpd/nhrp_interface.c b/nhrpd/nhrp_interface.c
index 402ffe9a2..12c86c387 100644
--- a/nhrpd/nhrp_interface.c
+++ b/nhrpd/nhrp_interface.c
@@ -20,8 +20,47 @@
#include "nhrpd.h"
#include "os.h"
#include "netlink.h"
+#include "hash.h"
DEFINE_MTYPE_STATIC(NHRPD, NHRP_IF, "NHRP interface");
+DEFINE_MTYPE_STATIC(NHRPD, NHRP_IF_GRE, "NHRP GRE interface");
+
+struct hash *nhrp_gre_list;
+
+static unsigned int nhrp_gre_info_key(const void *data)
+{
+ const struct nhrp_gre_info *r = data;
+
+ return r->ifindex;
+}
+
+static bool nhrp_gre_info_cmp(const void *data, const void *key)
+{
+ const struct nhrp_gre_info *a = data, *b = key;
+
+ if (a->ifindex == b->ifindex)
+ return true;
+ return false;
+}
+
+static void *nhrp_interface_gre_alloc(void *data)
+{
+ struct nhrp_gre_info *a;
+ struct nhrp_gre_info *b = data;
+
+ a = XMALLOC(MTYPE_NHRP_IF_GRE, sizeof(struct nhrp_gre_info));
+ memcpy(a, b, sizeof(struct nhrp_gre_info));
+ return a;
+}
+
+struct nhrp_gre_info *nhrp_gre_info_alloc(struct nhrp_gre_info *p)
+{
+ struct nhrp_gre_info *a;
+
+ a = (struct nhrp_gre_info *)hash_get(nhrp_gre_list, p,
+ nhrp_interface_gre_alloc);
+ return a;
+}
static void nhrp_interface_update_cache_config(struct interface *ifp,
bool available,
@@ -74,6 +113,9 @@ void nhrp_interface_init(void)
{
hook_register_prio(if_add, 0, nhrp_if_new_hook);
hook_register_prio(if_del, 0, nhrp_if_delete_hook);
+
+ nhrp_gre_list = hash_create(nhrp_gre_info_key, nhrp_gre_info_cmp,
+ "NHRP GRE list Hash");
}
void nhrp_interface_update_mtu(struct interface *ifp, afi_t afi)
@@ -102,14 +144,16 @@ static void nhrp_interface_update_source(struct interface *ifp)
{
struct nhrp_interface *nifp = ifp->info;
- if (!nifp->source || !nifp->nbmaifp
- || (ifindex_t)nifp->linkidx == nifp->nbmaifp->ifindex)
+ if (!nifp->source || !nifp->nbmaifp ||
+ ((ifindex_t)nifp->link_idx == nifp->nbmaifp->ifindex &&
+ (nifp->link_vrf_id == nifp->nbmaifp->vrf_id)))
return;
- nifp->linkidx = nifp->nbmaifp->ifindex;
- debugf(NHRP_DEBUG_IF, "%s: bound device index changed to %d", ifp->name,
- nifp->linkidx);
- netlink_gre_set_link(ifp->ifindex, nifp->linkidx);
+ nifp->link_idx = nifp->nbmaifp->ifindex;
+ nifp->link_vrf_id = nifp->nbmaifp->vrf_id;
+ debugf(NHRP_DEBUG_IF, "%s: bound device index changed to %d, vr %u",
+ ifp->name, nifp->link_idx, nifp->link_vrf_id);
+ nhrp_send_zebra_gre_source_set(ifp, nifp->link_idx, nifp->link_vrf_id);
}
static void nhrp_interface_interface_notifier(struct notifier_block *n,
@@ -136,7 +180,8 @@ static void nhrp_interface_interface_notifier(struct notifier_block *n,
}
}
-static void nhrp_interface_update_nbma(struct interface *ifp)
+void nhrp_interface_update_nbma(struct interface *ifp,
+ struct nhrp_gre_info *gre_info)
{
struct nhrp_interface *nifp = ifp->info, *nbmanifp = NULL;
struct interface *nbmaifp = NULL;
@@ -145,21 +190,32 @@ static void nhrp_interface_update_nbma(struct interface *ifp)
sockunion_family(&nbma) = AF_UNSPEC;
if (nifp->source)
- nbmaifp = if_lookup_by_name(nifp->source, VRF_DEFAULT);
+ nbmaifp = if_lookup_by_name(nifp->source, nifp->link_vrf_id);
switch (ifp->ll_type) {
case ZEBRA_LLT_IPGRE: {
struct in_addr saddr = {0};
- netlink_gre_get_info(ifp->ifindex, &nifp->grekey,
- &nifp->linkidx, &saddr);
+
+ if (!gre_info) {
+ nhrp_send_zebra_gre_request(ifp);
+ return;
+ }
+ nifp->i_grekey = gre_info->ikey;
+ nifp->o_grekey = gre_info->okey;
+ nifp->link_idx = gre_info->ifindex_link;
+ nifp->link_vrf_id = gre_info->vrfid_link;
+ saddr.s_addr = gre_info->vtep_ip.s_addr;
+
debugf(NHRP_DEBUG_IF, "%s: GRE: %x %x %x", ifp->name,
- nifp->grekey, nifp->linkidx, saddr.s_addr);
- if (saddr.s_addr != INADDR_ANY)
- sockunion_set(&nbma, AF_INET, (uint8_t *)&saddr.s_addr,
+ nifp->i_grekey, nifp->link_idx, saddr.s_addr);
+ if (saddr.s_addr)
+ sockunion_set(&nbma, AF_INET,
+ (uint8_t *)&saddr.s_addr,
sizeof(saddr.s_addr));
- else if (!nbmaifp && nifp->linkidx != IFINDEX_INTERNAL)
+ else if (!nbmaifp && nifp->link_idx != IFINDEX_INTERNAL)
nbmaifp =
- if_lookup_by_index(nifp->linkidx, VRF_DEFAULT);
+ if_lookup_by_index(nifp->link_idx,
+ nifp->link_vrf_id);
} break;
default:
break;
@@ -322,7 +378,7 @@ int nhrp_ifp_create(struct interface *ifp)
ifp->name, ifp->ifindex, ifp->ll_type,
if_link_type_str(ifp->ll_type));
- nhrp_interface_update_nbma(ifp);
+ nhrp_interface_update_nbma(ifp, NULL);
return 0;
}
@@ -402,7 +458,7 @@ static void nhrp_interface_update_cache_config(struct interface *ifp, bool avail
int nhrp_ifp_up(struct interface *ifp)
{
debugf(NHRP_DEBUG_IF, "if-up: %s", ifp->name);
- nhrp_interface_update_nbma(ifp);
+ nhrp_interface_update_nbma(ifp, NULL);
return 0;
}
@@ -493,5 +549,5 @@ void nhrp_interface_set_source(struct interface *ifp, const char *ifname)
free(nifp->source);
nifp->source = ifname ? strdup(ifname) : NULL;
- nhrp_interface_update_nbma(ifp);
+ nhrp_interface_update_nbma(ifp, NULL);
}