summaryrefslogtreecommitdiffstats
path: root/nhrpd
diff options
context:
space:
mode:
authorPhilippe Guibert <philippe.guibert@6wind.com>2019-12-20 11:10:34 +0100
committerPhilippe Guibert <philippe.guibert@6wind.com>2021-04-30 10:33:18 +0200
commit7f48cfa5e4d93bb8899e0eb815074741df3c8177 (patch)
tree04e6f009fd53b396c7ef7490a52c2934ebdcb5a3 /nhrpd
parentlib, zebra: get gre information (diff)
downloadfrr-7f48cfa5e4d93bb8899e0eb815074741df3c8177.tar.xz
frr-7f48cfa5e4d93bb8899e0eb815074741df3c8177.zip
nhrpd: redirect netlink gre with zebra
as zebra has a new api to get gre and set gre source commands, netlink gre get and netlink gre source function calls are redirected to zebra by using the zapi interface. Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Diffstat (limited to 'nhrpd')
-rw-r--r--nhrpd/nhrp_interface.c92
-rw-r--r--nhrpd/nhrp_route.c77
-rw-r--r--nhrpd/nhrpd.h33
3 files changed, 180 insertions, 22 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);
}
diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c
index 23fa0771e..1f513b7c0 100644
--- a/nhrpd/nhrp_route.c
+++ b/nhrpd/nhrp_route.c
@@ -380,6 +380,7 @@ void nhrp_zebra_init(void)
zclient->neighbor_added = nhrp_neighbor_operation;
zclient->neighbor_removed = nhrp_neighbor_operation;
zclient->neighbor_get = nhrp_neighbor_operation;
+ zclient->gre_update = nhrp_gre_update;
zclient_init(zclient, ZEBRA_ROUTE_NHRP, 0, &nhrpd_privs);
}
@@ -412,6 +413,32 @@ void nhrp_send_zebra_configure_arp(struct interface *ifp, int family)
zclient_send_message(zclient);
}
+void nhrp_send_zebra_gre_source_set(struct interface *ifp,
+ unsigned int link_idx,
+ vrf_id_t link_vrf_id)
+{
+ struct stream *s;
+
+ if (!zclient || zclient->sock < 0) {
+ zlog_err("%s : zclient not ready", __func__);
+ return;
+ }
+ if (link_idx == IFINDEX_INTERNAL || link_vrf_id == VRF_UNKNOWN) {
+ /* silently ignore */
+ return;
+ }
+ s = zclient->obuf;
+ stream_reset(s);
+ zclient_create_header(s,
+ ZEBRA_GRE_SOURCE_SET,
+ ifp->vrf_id);
+ stream_putl(s, ifp->ifindex);
+ stream_putl(s, link_idx);
+ stream_putl(s, link_vrf_id);
+ stream_putw_at(s, 0, stream_get_endp(s));
+ zclient_send_message(zclient);
+}
+
void nhrp_send_zebra_nbr(union sockunion *in,
union sockunion *out,
struct interface *ifp)
@@ -429,6 +456,11 @@ void nhrp_send_zebra_nbr(union sockunion *in,
zclient_send_message(zclient);
}
+int nhrp_send_zebra_gre_request(struct interface *ifp)
+{
+ return zclient_send_zebra_gre_request(zclient, ifp);
+}
+
void nhrp_zebra_terminate(void)
{
nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP, false);
@@ -441,3 +473,48 @@ void nhrp_zebra_terminate(void)
route_table_finish(zebra_rib[AFI_IP]);
route_table_finish(zebra_rib[AFI_IP6]);
}
+
+void nhrp_gre_update(ZAPI_CALLBACK_ARGS)
+{
+ struct stream *s;
+ struct nhrp_gre_info gre_info, *val;
+ struct interface *ifp;
+
+ /* result */
+ s = zclient->ibuf;
+ if (vrf_id != VRF_DEFAULT)
+ return;
+
+ /* read GRE information */
+ STREAM_GETL(s, gre_info.ifindex);
+ STREAM_GETL(s, gre_info.ikey);
+ STREAM_GETL(s, gre_info.okey);
+ STREAM_GETL(s, gre_info.ifindex_link);
+ STREAM_GETL(s, gre_info.vrfid_link);
+ STREAM_GETL(s, gre_info.vtep_ip.s_addr);
+ STREAM_GETL(s, gre_info.vtep_ip_remote.s_addr);
+ if (gre_info.ifindex == IFINDEX_INTERNAL)
+ val = NULL;
+ else
+ val = hash_lookup(nhrp_gre_list, &gre_info);
+ if (val) {
+ if (gre_info.vtep_ip.s_addr != val->vtep_ip.s_addr ||
+ gre_info.vrfid_link != val->vrfid_link ||
+ gre_info.ifindex_link != val->ifindex_link ||
+ gre_info.ikey != val->ikey ||
+ gre_info.okey != val->okey) {
+ /* update */
+ memcpy(val, &gre_info, sizeof(struct nhrp_gre_info));
+ }
+ } else {
+ val = nhrp_gre_info_alloc(&gre_info);
+ }
+ ifp = if_lookup_by_index(gre_info.ifindex, vrf_id);
+ debugf(NHRP_DEBUG_EVENT, "%s: gre interface %d vr %d obtained from system",
+ ifp ? ifp->name : "<none>", gre_info.ifindex, vrf_id);
+ if (ifp)
+ nhrp_interface_update_nbma(ifp, val);
+ return;
+stream_failure:
+ zlog_err("%s(): error reading response ..", __func__);
+}
diff --git a/nhrpd/nhrpd.h b/nhrpd/nhrpd.h
index 730f9b7d1..17abb0476 100644
--- a/nhrpd/nhrpd.h
+++ b/nhrpd/nhrpd.h
@@ -86,14 +86,22 @@ static inline int notifier_active(struct notifier_list *l)
return !list_empty(&l->notifier_head);
}
+extern struct hash *nhrp_gre_list;
+
void nhrp_zebra_init(void);
void nhrp_zebra_terminate(void);
void nhrp_send_zebra_configure_arp(struct interface *ifp, int family);
void nhrp_send_zebra_nbr(union sockunion *in,
union sockunion *out,
struct interface *ifp);
-void nhrp_send_zebra_configure_arp(struct interface *ifp,
- int family);
+
+void nhrp_send_zebra_gre_source_set(struct interface *ifp,
+ unsigned int link_idx,
+ vrf_id_t link_vrf_id);
+
+extern int nhrp_send_zebra_gre_request(struct interface *ifp);
+extern struct nhrp_gre_info *nhrp_gre_info_alloc(struct nhrp_gre_info *p);
+
struct zbuf;
struct nhrp_vc;
struct nhrp_cache;
@@ -300,8 +308,10 @@ struct nhrp_interface {
char *ipsec_profile, *ipsec_fallback_profile, *source;
union sockunion nbma;
union sockunion nat_nbma;
- unsigned int linkidx;
- uint32_t grekey;
+ unsigned int link_idx;
+ unsigned int link_vrf_id;
+ uint32_t i_grekey;
+ uint32_t o_grekey;
struct hash *peer_hash;
struct hash *cache_config_hash;
@@ -325,6 +335,18 @@ struct nhrp_interface {
} afi[AFI_MAX];
};
+struct nhrp_gre_info {
+ ifindex_t ifindex;
+ struct in_addr vtep_ip; /* IFLA_GRE_LOCAL */
+ struct in_addr vtep_ip_remote; /* IFLA_GRE_REMOTE */
+ uint32_t ikey;
+ uint32_t okey;
+ ifindex_t ifindex_link; /* Interface index of interface
+ * linked with GRE
+ */
+ vrf_id_t vrfid_link;
+};
+
extern struct zebra_privs_t nhrpd_privs;
int sock_open_unix(const char *path);
@@ -332,6 +354,8 @@ int sock_open_unix(const char *path);
void nhrp_interface_init(void);
void nhrp_interface_update(struct interface *ifp);
void nhrp_interface_update_mtu(struct interface *ifp, afi_t afi);
+void nhrp_interface_update_nbma(struct interface *ifp,
+ struct nhrp_gre_info *gre_info);
int nhrp_interface_add(ZAPI_CALLBACK_ARGS);
int nhrp_interface_delete(ZAPI_CALLBACK_ARGS);
@@ -340,6 +364,7 @@ int nhrp_interface_down(ZAPI_CALLBACK_ARGS);
int nhrp_interface_address_add(ZAPI_CALLBACK_ARGS);
int nhrp_interface_address_delete(ZAPI_CALLBACK_ARGS);
void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS);
+void nhrp_gre_update(ZAPI_CALLBACK_ARGS);
void nhrp_interface_notify_add(struct interface *ifp, struct notifier_block *n,
notifier_fn_t fn);