diff options
author | Philippe Guibert <philippe.guibert@6wind.com> | 2019-12-20 11:10:34 +0100 |
---|---|---|
committer | Philippe Guibert <philippe.guibert@6wind.com> | 2021-04-30 10:33:18 +0200 |
commit | 7f48cfa5e4d93bb8899e0eb815074741df3c8177 (patch) | |
tree | 04e6f009fd53b396c7ef7490a52c2934ebdcb5a3 /nhrpd | |
parent | lib, zebra: get gre information (diff) | |
download | frr-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.c | 92 | ||||
-rw-r--r-- | nhrpd/nhrp_route.c | 77 | ||||
-rw-r--r-- | nhrpd/nhrpd.h | 33 |
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); |