Merge pull request #8237 from pguibert6WIND/nhrp_use_zebra_2

Nhrp use zebra 2
This commit is contained in:
Mark Stapp 2021-05-05 07:57:04 -04:00 committed by GitHub
commit 3d4b999fab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 788 additions and 227 deletions

16
include/linux/if_packet.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef __LINUX_IF_PACKET_H
#define __LINUX_IF_PACKET_H
#include <linux/types.h>
struct sockaddr_ll {
unsigned short sll_family;
__be16 sll_protocol;
int sll_ifindex;
unsigned short sll_hatype;
unsigned char sll_pkttype;
unsigned char sll_halen;
unsigned char sll_addr[8];
};
#endif

71
include/linux/if_tunnel.h Normal file
View File

@ -0,0 +1,71 @@
#ifndef _IF_TUNNEL_H_
#define _IF_TUNNEL_H_
#include <linux/types.h>
#include <linux/if.h>
#include <linux/ip.h>
#include <linux/in6.h>
#include <asm/byteorder.h>
#define SIOCGETTUNNEL (SIOCDEVPRIVATE + 0)
#define SIOCADDTUNNEL (SIOCDEVPRIVATE + 1)
#define SIOCDELTUNNEL (SIOCDEVPRIVATE + 2)
#define SIOCCHGTUNNEL (SIOCDEVPRIVATE + 3)
#define SIOCGETPRL (SIOCDEVPRIVATE + 4)
#define SIOCADDPRL (SIOCDEVPRIVATE + 5)
#define SIOCDELPRL (SIOCDEVPRIVATE + 6)
#define SIOCCHGPRL (SIOCDEVPRIVATE + 7)
#define GRE_CSUM __cpu_to_be16(0x8000)
#define GRE_ROUTING __cpu_to_be16(0x4000)
#define GRE_KEY __cpu_to_be16(0x2000)
#define GRE_SEQ __cpu_to_be16(0x1000)
#define GRE_STRICT __cpu_to_be16(0x0800)
#define GRE_REC __cpu_to_be16(0x0700)
#define GRE_FLAGS __cpu_to_be16(0x00F8)
#define GRE_VERSION __cpu_to_be16(0x0007)
struct ip_tunnel_parm {
char name[IFNAMSIZ];
int link;
__be16 i_flags;
__be16 o_flags;
__be32 i_key;
__be32 o_key;
struct iphdr iph;
};
/* SIT-mode i_flags */
#define SIT_ISATAP 0x0001
struct ip_tunnel_prl {
__be32 addr;
__u16 flags;
__u16 __reserved;
__u32 datalen;
__u32 __reserved2;
/* data follows */
};
/* PRL flags */
#define PRL_DEFAULT 0x0001
enum {
IFLA_GRE_UNSPEC,
IFLA_GRE_LINK,
IFLA_GRE_IFLAGS,
IFLA_GRE_OFLAGS,
IFLA_GRE_IKEY,
IFLA_GRE_OKEY,
IFLA_GRE_LOCAL,
IFLA_GRE_REMOTE,
IFLA_GRE_TTL,
IFLA_GRE_TOS,
IFLA_GRE_PMTUDISC,
__IFLA_GRE_MAX,
};
#define IFLA_GRE_MAX (__IFLA_GRE_MAX - 1)
#endif /* _IF_TUNNEL_H_ */

View File

@ -461,7 +461,10 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_NHRP_NEIGH_UNREGISTER),
DESC_ENTRY(ZEBRA_NEIGH_IP_ADD),
DESC_ENTRY(ZEBRA_NEIGH_IP_DEL),
DESC_ENTRY(ZEBRA_CONFIGURE_ARP)};
DESC_ENTRY(ZEBRA_CONFIGURE_ARP),
DESC_ENTRY(ZEBRA_GRE_GET),
DESC_ENTRY(ZEBRA_GRE_UPDATE),
DESC_ENTRY(ZEBRA_GRE_SOURCE_SET)};
#undef DESC_ENTRY
static const struct zebra_desc_table unknown = {0, "unknown", '?'};

View File

@ -3931,6 +3931,11 @@ static int zclient_read(struct thread *thread)
(*zclient->neighbor_get)(command, zclient, length,
vrf_id);
break;
case ZEBRA_GRE_UPDATE:
if (zclient->gre_update)
(*zclient->gre_update)(command, zclient,
length, vrf_id);
break;
default:
break;
}
@ -4252,3 +4257,23 @@ int zclient_neigh_ip_decode(struct stream *s, struct zapi_neigh_ip *api)
stream_failure:
return -1;
}
int zclient_send_zebra_gre_request(struct zclient *client,
struct interface *ifp)
{
struct stream *s;
if (!client || client->sock < 0) {
zlog_err("%s : zclient not ready", __func__);
return -1;
}
s = client->obuf;
stream_reset(s);
zclient_create_header(s,
ZEBRA_GRE_GET,
ifp->vrf_id);
stream_putl(s, ifp->ifindex);
stream_putw_at(s, 0, stream_get_endp(s));
zclient_send_message(client);
return 0;
}

View File

@ -232,6 +232,9 @@ typedef enum {
ZEBRA_NEIGH_IP_ADD,
ZEBRA_NEIGH_IP_DEL,
ZEBRA_CONFIGURE_ARP,
ZEBRA_GRE_GET,
ZEBRA_GRE_UPDATE,
ZEBRA_GRE_SOURCE_SET,
} zebra_message_types_t;
enum zebra_error_types {
@ -393,6 +396,7 @@ struct zclient {
void (*neighbor_added)(ZAPI_CALLBACK_ARGS);
void (*neighbor_removed)(ZAPI_CALLBACK_ARGS);
void (*neighbor_get)(ZAPI_CALLBACK_ARGS);
void (*gre_update)(ZAPI_CALLBACK_ARGS);
};
/* Zebra API message flag. */
@ -1228,6 +1232,8 @@ struct zapi_client_close_info {
extern int zapi_client_close_notify_decode(struct stream *s,
struct zapi_client_close_info *info);
extern int zclient_send_zebra_gre_request(struct zclient *client,
struct interface *ifp);
#ifdef __cplusplus
}
#endif

View File

@ -7,30 +7,12 @@
* (at your option) any later version.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <asm/types.h>
#include <arpa/inet.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/ip.h>
#include <linux/if_arp.h>
#include <linux/if_tunnel.h>
#include <linux/limits.h>
#include "zebra.h"
#include <linux/if_packet.h>
#include "nhrp_protocol.h"
#include "os.h"
#include "netlink.h"
#ifndef HAVE_STRLCPY
size_t strlcpy(char *__restrict dest,

View File

@ -7,21 +7,16 @@
* (at your option) any later version.
*/
#include <stdint.h>
#include <zebra.h>
#include <vrf.h>
#include <if.h>
union sockunion;
struct interface;
extern int netlink_nflog_group;
extern int netlink_mcast_nflog_group;
extern int netlink_req_fd;
void netlink_init(void);
int netlink_configure_arp(unsigned int ifindex, int pf);
void netlink_update_binding(struct interface *ifp, union sockunion *proto,
union sockunion *nbma);
void netlink_set_nflog_group(int nlgroup);
void netlink_gre_get_info(unsigned int ifindex, uint32_t *gre_key,
unsigned int *link_index, struct in_addr *saddr);
void netlink_gre_set_link(unsigned int ifindex, unsigned int link_index);

View File

@ -25,7 +25,6 @@
#include "netlink.h"
#include "znl.h"
int netlink_req_fd = -1;
int netlink_nflog_group;
static int netlink_log_fd = -1;
static struct thread *netlink_log_thread;
@ -203,10 +202,3 @@ void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS)
nhrp_cache_set_used(c, state == ZEBRA_NEIGH_STATE_REACHABLE);
}
}
void netlink_init(void)
{
netlink_req_fd = znl_open(NETLINK_ROUTE, 0);
if (netlink_req_fd < 0)
return;
}

View File

@ -1,152 +0,0 @@
/* NHRP netlink/GRE tunnel configuration code
* Copyright (c) 2014-2016 Timo Teräs
*
* 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 <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/in.h>
#include <linux/if.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/if_tunnel.h>
#include "debug.h"
#include "netlink.h"
#include "znl.h"
static int __netlink_gre_get_data(struct zbuf *zb, struct zbuf *data,
int ifindex)
{
struct nlmsghdr *n;
struct ifinfomsg *ifi;
struct zbuf payload, rtapayload;
struct rtattr *rta;
debugf(NHRP_DEBUG_KERNEL, "netlink-link-gre: get-info %u", ifindex);
n = znl_nlmsg_push(zb, RTM_GETLINK, NLM_F_REQUEST);
ifi = znl_push(zb, sizeof(*ifi));
*ifi = (struct ifinfomsg){
.ifi_index = ifindex,
};
znl_nlmsg_complete(zb, n);
if (zbuf_send(zb, netlink_req_fd) < 0
|| zbuf_recv(zb, netlink_req_fd) < 0)
return -1;
n = znl_nlmsg_pull(zb, &payload);
if (!n)
return -1;
if (n->nlmsg_type != RTM_NEWLINK)
return -1;
ifi = znl_pull(&payload, sizeof(struct ifinfomsg));
if (!ifi)
return -1;
debugf(NHRP_DEBUG_KERNEL,
"netlink-link-gre: ifindex %u, receive msg_type %u, msg_flags %u",
ifi->ifi_index, n->nlmsg_type, n->nlmsg_flags);
if (ifi->ifi_index != ifindex)
return -1;
while ((rta = znl_rta_pull(&payload, &rtapayload)) != NULL)
if (rta->rta_type == IFLA_LINKINFO)
break;
if (!rta)
return -1;
payload = rtapayload;
while ((rta = znl_rta_pull(&payload, &rtapayload)) != NULL)
if (rta->rta_type == IFLA_INFO_DATA)
break;
if (!rta)
return -1;
*data = rtapayload;
return 0;
}
void netlink_gre_get_info(unsigned int ifindex, uint32_t *gre_key,
unsigned int *link_index, struct in_addr *saddr)
{
struct zbuf *zb = zbuf_alloc(8192), data, rtapl;
struct rtattr *rta;
*link_index = 0;
*gre_key = 0;
saddr->s_addr = 0;
if (__netlink_gre_get_data(zb, &data, ifindex) < 0)
goto err;
while ((rta = znl_rta_pull(&data, &rtapl)) != NULL) {
switch (rta->rta_type) {
case IFLA_GRE_LINK:
*link_index = zbuf_get32(&rtapl);
break;
case IFLA_GRE_IKEY:
case IFLA_GRE_OKEY:
*gre_key = zbuf_get32(&rtapl);
break;
case IFLA_GRE_LOCAL:
saddr->s_addr = zbuf_get32(&rtapl);
break;
}
}
err:
zbuf_free(zb);
}
void netlink_gre_set_link(unsigned int ifindex, unsigned int link_index)
{
struct nlmsghdr *n;
struct ifinfomsg *ifi;
struct rtattr *rta_info, *rta_data, *rta;
struct zbuf *zr = zbuf_alloc(8192), data, rtapl;
struct zbuf *zb = zbuf_alloc(8192);
size_t len;
if (__netlink_gre_get_data(zr, &data, ifindex) < 0)
goto err;
n = znl_nlmsg_push(zb, RTM_NEWLINK, NLM_F_REQUEST);
ifi = znl_push(zb, sizeof(*ifi));
*ifi = (struct ifinfomsg){
.ifi_index = ifindex,
};
rta_info = znl_rta_nested_push(zb, IFLA_LINKINFO);
znl_rta_push(zb, IFLA_INFO_KIND, "gre", 3);
rta_data = znl_rta_nested_push(zb, IFLA_INFO_DATA);
znl_rta_push_u32(zb, IFLA_GRE_LINK, link_index);
while ((rta = znl_rta_pull(&data, &rtapl)) != NULL) {
if (rta->rta_type == IFLA_GRE_LINK)
continue;
len = zbuf_used(&rtapl);
znl_rta_push(zb, rta->rta_type, zbuf_pulln(&rtapl, len), len);
}
znl_rta_nested_complete(zb, rta_data);
znl_rta_nested_complete(zb, rta_info);
znl_nlmsg_complete(zb, n);
zbuf_send(zb, netlink_req_fd);
zbuf_recv(zb, netlink_req_fd);
err:
zbuf_free(zb);
zbuf_free(zr);
}

View File

@ -19,14 +19,52 @@
#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 void nhrp_interface_update_cache_config(struct interface *ifp,
bool available,
uint8_t family);
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 int nhrp_if_new_hook(struct interface *ifp)
{
struct nhrp_interface *nifp;
@ -74,6 +112,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 +143,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 +179,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 +189,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 +377,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 +457,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 +548,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);
}

View File

@ -26,7 +26,6 @@
#include "filter.h"
#include "nhrpd.h"
#include "netlink.h"
#include "nhrp_errors.h"
DEFINE_MGROUP(NHRPD, "NHRP");
@ -154,7 +153,6 @@ int main(int argc, char **argv)
assert(nhrpd_privs.change);
nhrpd_privs.change(ZPRIVS_RAISE);
netlink_init();
evmgr_init();
nhrp_vc_init();
nhrp_packet_init();

View File

@ -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,33 @@ 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_putl(s, 0); /* mtu provisioning */
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 +457,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 +474,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__);
}

View File

@ -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);

View File

@ -13,7 +13,6 @@ nhrpd_nhrpd_LDADD = lib/libfrr.la lib/libfrrcares.la $(LIBCAP)
nhrpd_nhrpd_SOURCES = \
nhrpd/linux.c \
nhrpd/netlink_arp.c \
nhrpd/netlink_gre.c \
nhrpd/nhrp_cache.c \
nhrpd/nhrp_errors.c \
nhrpd/nhrp_event.c \

View File

@ -178,7 +178,7 @@ DEFPY (debug_zebra_mpls,
return CMD_SUCCESS;
}
DEFUN (debug_zebra_vxlan,
DEFPY (debug_zebra_vxlan,
debug_zebra_vxlan_cmd,
"debug zebra vxlan",
DEBUG_STR

View File

@ -29,10 +29,13 @@
* Reference - https://sourceware.org/ml/libc-alpha/2013-01/msg00599.html
*/
#define _LINUX_IN6_H
#define _LINUX_IF_H
#define _LINUX_IP_H
#include <netinet/if_ether.h>
#include <linux/if_bridge.h>
#include <linux/if_link.h>
#include <linux/if_tunnel.h>
#include <net/if_arp.h>
#include <linux/sockios.h>
#include <linux/ethtool.h>
@ -70,6 +73,7 @@
#include "zebra/zebra_errors.h"
#include "zebra/zebra_vxlan.h"
#include "zebra/zebra_evpn_mh.h"
#include "zebra/zebra_l2.h"
extern struct zebra_privs_t zserv_privs;
@ -289,6 +293,8 @@ static void netlink_determine_zebra_iftype(const char *kind,
*zif_type = ZEBRA_IF_BOND;
else if (strcmp(kind, "bond_slave") == 0)
*zif_type = ZEBRA_IF_BOND_SLAVE;
else if (strcmp(kind, "gre") == 0)
*zif_type = ZEBRA_IF_GRE;
}
#define parse_rtattr_nested(tb, max, rta) \
@ -458,6 +464,80 @@ uint32_t kernel_get_speed(struct interface *ifp, int *error)
return get_iflink_speed(ifp, error);
}
static ssize_t
netlink_gre_set_msg_encoder(struct zebra_dplane_ctx *ctx, void *buf,
size_t buflen)
{
struct {
struct nlmsghdr n;
struct ifinfomsg ifi;
char buf[];
} *req = buf;
uint32_t link_idx;
unsigned int mtu;
struct rtattr *rta_info, *rta_data;
const struct zebra_l2info_gre *gre_info;
if (buflen < sizeof(*req))
return 0;
memset(req, 0, sizeof(*req));
req->n.nlmsg_type = RTM_NEWLINK;
req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
req->n.nlmsg_flags = NLM_F_REQUEST;
req->ifi.ifi_index = dplane_ctx_get_ifindex(ctx);
gre_info = dplane_ctx_gre_get_info(ctx);
if (!gre_info)
return 0;
req->ifi.ifi_change = 0xFFFFFFFF;
link_idx = dplane_ctx_gre_get_link_ifindex(ctx);
mtu = dplane_ctx_gre_get_mtu(ctx);
if (mtu && !nl_attr_put32(&req->n, buflen, IFLA_MTU, mtu))
return 0;
rta_info = nl_attr_nest(&req->n, buflen, IFLA_LINKINFO);
if (!rta_info)
return 0;
if (!nl_attr_put(&req->n, buflen, IFLA_INFO_KIND, "gre", 3))
return 0;
rta_data = nl_attr_nest(&req->n, buflen, IFLA_INFO_DATA);
if (!rta_data)
return 0;
if (!nl_attr_put32(&req->n, buflen, IFLA_GRE_LINK, link_idx))
return 0;
if (gre_info->vtep_ip.s_addr &&
!nl_attr_put32(&req->n, buflen, IFLA_GRE_LOCAL,
gre_info->vtep_ip.s_addr))
return 0;
if (gre_info->vtep_ip_remote.s_addr &&
!nl_attr_put32(&req->n, buflen, IFLA_GRE_REMOTE,
gre_info->vtep_ip_remote.s_addr))
return 0;
if (gre_info->ikey &&
!nl_attr_put32(&req->n, buflen, IFLA_GRE_IKEY,
gre_info->ikey))
return 0;
if (gre_info->okey &&
!nl_attr_put32(&req->n, buflen, IFLA_GRE_IKEY,
gre_info->okey))
return 0;
nl_attr_nest_end(&req->n, rta_data);
nl_attr_nest_end(&req->n, rta_info);
return NLMSG_ALIGN(req->n.nlmsg_len);
}
static int netlink_extract_bridge_info(struct rtattr *link_data,
struct zebra_l2info_bridge *bridge_info)
{
@ -492,6 +572,47 @@ static int netlink_extract_vlan_info(struct rtattr *link_data,
return 0;
}
static int netlink_extract_gre_info(struct rtattr *link_data,
struct zebra_l2info_gre *gre_info)
{
struct rtattr *attr[IFLA_GRE_MAX + 1];
memset(gre_info, 0, sizeof(*gre_info));
memset(attr, 0, sizeof(attr));
parse_rtattr_nested(attr, IFLA_GRE_MAX, link_data);
if (!attr[IFLA_GRE_LOCAL]) {
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
"IFLA_GRE_LOCAL missing from GRE IF message");
} else
gre_info->vtep_ip =
*(struct in_addr *)RTA_DATA(attr[IFLA_GRE_LOCAL]);
if (!attr[IFLA_GRE_REMOTE]) {
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
"IFLA_GRE_REMOTE missing from GRE IF message");
} else
gre_info->vtep_ip_remote =
*(struct in_addr *)RTA_DATA(attr[IFLA_GRE_REMOTE]);
if (!attr[IFLA_GRE_LINK]) {
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("IFLA_GRE_LINK missing from GRE IF message");
} else {
gre_info->ifindex_link =
*(ifindex_t *)RTA_DATA(attr[IFLA_GRE_LINK]);
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("IFLA_GRE_LINK obtained is %u",
gre_info->ifindex_link);
}
if (attr[IFLA_GRE_IKEY])
gre_info->ikey = *(uint32_t *)RTA_DATA(attr[IFLA_GRE_IKEY]);
if (attr[IFLA_GRE_OKEY])
gre_info->okey = *(uint32_t *)RTA_DATA(attr[IFLA_GRE_OKEY]);
return 0;
}
static int netlink_extract_vxlan_info(struct rtattr *link_data,
struct zebra_l2info_vxlan *vxl_info)
{
@ -572,6 +693,16 @@ static void netlink_interface_update_l2info(struct interface *ifp,
vxlan_info.ifindex_link)
zebra_if_update_link(ifp, vxlan_info.ifindex_link,
link_nsid);
} else if (IS_ZEBRA_IF_GRE(ifp)) {
struct zebra_l2info_gre gre_info;
netlink_extract_gre_info(link_data, &gre_info);
gre_info.link_nsid = link_nsid;
zebra_l2_greif_add_update(ifp, &gre_info, add);
if (link_nsid != NS_UNKNOWN &&
gre_info.ifindex_link)
zebra_if_update_link(ifp, gre_info.ifindex_link,
link_nsid);
}
}
@ -934,6 +1065,20 @@ static int netlink_request_intf_addr(struct nlsock *netlink_cmd, int family,
return netlink_request(netlink_cmd, &req);
}
enum netlink_msg_status
netlink_put_gre_set_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx)
{
enum dplane_op_e op;
enum netlink_msg_status ret;
op = dplane_ctx_get_op(ctx);
assert(op == DPLANE_OP_GRE_SET);
ret = netlink_batch_add_msg(bth, ctx, netlink_gre_set_msg_encoder, false);
return ret;
}
/* Interface lookup by netlink socket. */
int interface_lookup_netlink(struct zebra_ns *zns)
{

View File

@ -32,6 +32,9 @@ extern int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id,
extern int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup);
extern int interface_lookup_netlink(struct zebra_ns *zns);
extern enum netlink_msg_status
netlink_put_gre_set_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx);
extern enum netlink_msg_status
netlink_put_address_update_msg(struct nl_batch *bth,
struct zebra_dplane_ctx *ctx);

View File

@ -1066,8 +1066,9 @@ void if_up(struct interface *ifp)
zif->link_ifindex);
if (link_if)
zebra_vxlan_svi_up(ifp, link_if);
} else if (IS_ZEBRA_IF_MACVLAN(ifp))
} else if (IS_ZEBRA_IF_MACVLAN(ifp)) {
zebra_vxlan_macvlan_up(ifp);
}
if (zif->es_info.es)
zebra_evpn_es_if_oper_state_change(zif, true /*up*/);
@ -1108,8 +1109,9 @@ void if_down(struct interface *ifp)
zif->link_ifindex);
if (link_if)
zebra_vxlan_svi_down(ifp, link_if);
} else if (IS_ZEBRA_IF_MACVLAN(ifp))
} else if (IS_ZEBRA_IF_MACVLAN(ifp)) {
zebra_vxlan_macvlan_down(ifp);
}
if (zif->es_info.es)
zebra_evpn_es_if_oper_state_change(zif, false /*up*/);
@ -1305,6 +1307,9 @@ static const char *zebra_ziftype_2str(zebra_iftype_t zif_type)
case ZEBRA_IF_MACVLAN:
return "macvlan";
case ZEBRA_IF_GRE:
return "GRE";
default:
return "Unknown";
}
@ -1577,6 +1582,28 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
ifp->name);
}
vty_out(vty, "\n");
} else if (IS_ZEBRA_IF_GRE(ifp)) {
struct zebra_l2info_gre *gre_info;
gre_info = &zebra_if->l2info.gre;
if (gre_info->vtep_ip.s_addr != INADDR_ANY) {
vty_out(vty, " VTEP IP: %pI4", &gre_info->vtep_ip);
if (gre_info->vtep_ip_remote.s_addr != INADDR_ANY)
vty_out(vty, " , remote %pI4",
&gre_info->vtep_ip_remote);
vty_out(vty, "\n");
}
if (gre_info->ifindex_link &&
(gre_info->link_nsid != NS_UNKNOWN)) {
struct interface *ifp;
ifp = if_lookup_by_index_per_ns(
zebra_ns_lookup(gre_info->link_nsid),
gre_info->ifindex_link);
vty_out(vty, " Link Interface %s\n",
ifp == NULL ? "Unknown" :
ifp->name);
}
}
if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) {

View File

@ -263,6 +263,7 @@ typedef enum {
ZEBRA_IF_VETH, /* VETH interface*/
ZEBRA_IF_BOND, /* Bond */
ZEBRA_IF_BOND_SLAVE, /* Bond */
ZEBRA_IF_GRE, /* GRE interface */
} zebra_iftype_t;
/* Zebra "slave" interface type */
@ -442,6 +443,9 @@ DECLARE_HOOK(zebra_if_config_wr, (struct vty * vty, struct interface *ifp),
#define IS_ZEBRA_IF_BOND(ifp) \
(((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_BOND)
#define IS_ZEBRA_IF_GRE(ifp) \
(((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_GRE)
#define IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) \
(((struct zebra_if *)(ifp->info))->zif_slave_type \
== ZEBRA_IF_SLAVE_BRIDGE)

View File

@ -1360,6 +1360,9 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth,
case DPLANE_OP_IPSET_ENTRY_DELETE:
return FRR_NETLINK_ERROR;
case DPLANE_OP_GRE_SET:
return netlink_put_gre_set_msg(bth, ctx);
case DPLANE_OP_NONE:
return FRR_NETLINK_ERROR;
}

View File

@ -81,9 +81,6 @@ extern int mpls_kernel_init(void);
extern uint32_t kernel_get_speed(struct interface *ifp, int *error);
extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute);
extern int kernel_configure_if_link(struct interface *ifp,
struct interface *link_ifp, ns_id_t ns_id);
/*
* Southbound Initialization routines to get initial starting
* state.

View File

@ -394,12 +394,6 @@ enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx)
return ZEBRA_DPLANE_REQUEST_SUCCESS;
}
int kernel_configure_if_link(struct interface *ifp, struct interface *link_ifp,
ns_id_t ns_id)
{
return 0;
}
extern int kernel_interface_set_master(struct interface *master,
struct interface *slave)
{

View File

@ -3240,6 +3240,61 @@ stream_failure:
return;
}
static inline void zebra_gre_get(ZAPI_HANDLER_ARGS)
{
struct stream *s;
ifindex_t idx;
struct interface *ifp;
struct zebra_if *zebra_if = NULL;
struct zebra_l2info_gre *gre_info;
struct interface *ifp_link = NULL;
vrf_id_t vrf_id_link = VRF_UNKNOWN;
vrf_id_t vrf_id = zvrf->vrf->vrf_id;
s = msg;
STREAM_GETL(s, idx);
ifp = if_lookup_by_index(idx, vrf_id);
if (ifp)
zebra_if = ifp->info;
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, ZEBRA_GRE_UPDATE, vrf_id);
if (ifp && IS_ZEBRA_IF_GRE(ifp) && zebra_if) {
gre_info = &zebra_if->l2info.gre;
stream_putl(s, idx);
stream_putl(s, gre_info->ikey);
stream_putl(s, gre_info->ikey);
stream_putl(s, gre_info->ifindex_link);
ifp_link = if_lookup_by_index_per_ns(
zebra_ns_lookup(gre_info->link_nsid),
gre_info->ifindex_link);
if (ifp_link)
vrf_id_link = ifp_link->vrf_id;
stream_putl(s, vrf_id_link);
stream_putl(s, gre_info->vtep_ip.s_addr);
stream_putl(s, gre_info->vtep_ip_remote.s_addr);
} else {
stream_putl(s, idx);
stream_putl(s, 0);
stream_putl(s, 0);
stream_putl(s, IFINDEX_INTERNAL);
stream_putl(s, VRF_UNKNOWN);
stream_putl(s, 0);
}
/* Write packet size. */
stream_putw_at(s, 0, stream_get_endp(s));
zserv_send_message(client, s);
return;
stream_failure:
return;
}
static inline void zebra_configure_arp(ZAPI_HANDLER_ARGS)
{
struct stream *s;
@ -3373,6 +3428,57 @@ stream_failure:
return;
}
static inline void zebra_gre_source_set(ZAPI_HANDLER_ARGS)
{
struct stream *s;
ifindex_t idx, link_idx;
vrf_id_t link_vrf_id;
struct interface *ifp;
struct interface *ifp_link;
vrf_id_t vrf_id = zvrf->vrf->vrf_id;
struct zebra_if *zif, *gre_zif;
struct zebra_l2info_gre *gre_info;
unsigned int mtu;
s = msg;
STREAM_GETL(s, idx);
ifp = if_lookup_by_index(idx, vrf_id);
STREAM_GETL(s, link_idx);
STREAM_GETL(s, link_vrf_id);
STREAM_GETL(s, mtu);
ifp_link = if_lookup_by_index(link_idx, link_vrf_id);
if (!ifp_link || !ifp) {
zlog_warn("GRE (index %u, VRF %u) or GRE link interface (index %u, VRF %u) not found, when setting GRE params",
idx, vrf_id, link_idx, link_vrf_id);
return;
}
if (!IS_ZEBRA_IF_GRE(ifp))
return;
gre_zif = (struct zebra_if *)ifp->info;
zif = (struct zebra_if *)ifp_link->info;
if (!zif || !gre_zif)
return;
gre_info = &zif->l2info.gre;
if (!gre_info)
return;
if (!mtu)
mtu = ifp->mtu;
/* if gre link already set or mtu did not change, do not set it */
if (gre_zif->link && gre_zif->link == ifp_link && mtu == ifp->mtu)
return;
dplane_gre_set(ifp, ifp_link, mtu, gre_info);
stream_failure:
return;
}
static void zsend_error_msg(struct zserv *client, enum zebra_error_types error,
struct zmsghdr *bad_hdr)
{
@ -3488,6 +3594,8 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_NHRP_NEIGH_REGISTER] = zebra_neigh_register,
[ZEBRA_NHRP_NEIGH_UNREGISTER] = zebra_neigh_unregister,
[ZEBRA_CONFIGURE_ARP] = zebra_configure_arp,
[ZEBRA_GRE_GET] = zebra_gre_get,
[ZEBRA_GRE_SOURCE_SET] = zebra_gre_source_set,
};
/*

View File

@ -271,6 +271,11 @@ struct dplane_rule_info {
struct dplane_ctx_rule old;
};
struct dplane_gre_ctx {
uint32_t link_ifindex;
unsigned int mtu;
struct zebra_l2info_gre info;
};
/*
* The context block used to exchange info about route updates across
* the boundary between the zebra main context (and pthread) and the
@ -327,6 +332,7 @@ struct zebra_dplane_ctx {
struct zebra_pbr_ipset_info info;
} ipset_entry;
struct dplane_neigh_table neightable;
struct dplane_gre_ctx gre;
} u;
/* Namespace info, used especially for netlink kernel communication */
@ -469,6 +475,9 @@ static struct zebra_dplane_globals {
_Atomic uint32_t dg_neightable_in;
_Atomic uint32_t dg_neightable_errors;
_Atomic uint32_t dg_gre_set_in;
_Atomic uint32_t dg_gre_set_errors;
/* Dataplane pthread */
struct frr_pthread *dg_pthread;
@ -713,6 +722,9 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
}
list_delete(&ctx->u.iptable.interface_name_list);
}
break;
case DPLANE_OP_GRE_SET:
break;
}
}
@ -979,6 +991,10 @@ const char *dplane_op2str(enum dplane_op_e op)
case DPLANE_OP_NEIGH_TABLE_UPDATE:
ret = "NEIGH_TABLE_UPDATE";
break;
case DPLANE_OP_GRE_SET:
ret = "GRE_SET";
break;
}
return ret;
@ -1772,6 +1788,31 @@ uint32_t dplane_ctx_neigh_get_update_flags(const struct zebra_dplane_ctx *ctx)
return ctx->u.neigh.update_flags;
}
/* Accessor for GRE set */
uint32_t
dplane_ctx_gre_get_link_ifindex(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
return ctx->u.gre.link_ifindex;
}
unsigned int
dplane_ctx_gre_get_mtu(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
return ctx->u.gre.mtu;
}
const struct zebra_l2info_gre *
dplane_ctx_gre_get_info(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
return &ctx->u.gre.info;
}
/* Accessors for PBR rule information */
int dplane_ctx_rule_get_sock(const struct zebra_dplane_ctx *ctx)
{
@ -4125,6 +4166,71 @@ dplane_pbr_ipset_entry_delete(struct zebra_pbr_ipset_entry *ipset)
return ipset_entry_update_internal(DPLANE_OP_IPSET_ENTRY_DELETE, ipset);
}
/*
* Common helper api for GRE set
*/
enum zebra_dplane_result
dplane_gre_set(struct interface *ifp, struct interface *ifp_link,
unsigned int mtu, const struct zebra_l2info_gre *gre_info)
{
enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
struct zebra_dplane_ctx *ctx;
enum dplane_op_e op = DPLANE_OP_GRE_SET;
int ret;
struct zebra_ns *zns;
ctx = dplane_ctx_alloc();
if (!ifp)
return result;
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
zlog_debug("init dplane ctx %s: if %s link %s%s",
dplane_op2str(op), ifp->name,
ifp_link ? "set" : "unset", ifp_link ?
ifp_link->name : "");
}
ctx->zd_op = op;
ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
zns = zebra_ns_lookup(ifp->vrf_id);
if (!zns)
return result;
dplane_ctx_ns_init(ctx, zns, false);
dplane_ctx_set_ifname(ctx, ifp->name);
ctx->zd_vrf_id = ifp->vrf_id;
ctx->zd_ifindex = ifp->ifindex;
if (ifp_link)
ctx->u.gre.link_ifindex = ifp_link->ifindex;
else
ctx->u.gre.link_ifindex = 0;
if (gre_info)
memcpy(&ctx->u.gre.info, gre_info, sizeof(ctx->u.gre.info));
ctx->u.gre.mtu = mtu;
ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
/* Enqueue context for processing */
ret = dplane_update_enqueue(ctx);
/* Update counter */
atomic_fetch_add_explicit(&zdplane_info.dg_gre_set_in, 1,
memory_order_relaxed);
if (ret == AOK)
result = ZEBRA_DPLANE_REQUEST_QUEUED;
else {
atomic_fetch_add_explicit(
&zdplane_info.dg_gre_set_errors, 1,
memory_order_relaxed);
if (ctx)
dplane_ctx_free(&ctx);
result = ZEBRA_DPLANE_REQUEST_FAILURE;
}
return result;
}
/*
* Handler for 'show dplane'
*/
@ -4234,6 +4340,13 @@ int dplane_show_helper(struct vty *vty, bool detailed)
memory_order_relaxed);
vty_out(vty, "Neighbor Table updates: %"PRIu64"\n", incoming);
vty_out(vty, "Neighbor Table errors: %"PRIu64"\n", errs);
incoming = atomic_load_explicit(&zdplane_info.dg_gre_set_in,
memory_order_relaxed);
errs = atomic_load_explicit(&zdplane_info.dg_gre_set_errors,
memory_order_relaxed);
vty_out(vty, "GRE set updates: %"PRIu64"\n", incoming);
vty_out(vty, "GRE set errors: %"PRIu64"\n", errs);
return CMD_SUCCESS;
}
@ -4680,6 +4793,12 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
dplane_ctx_get_ifname(ctx),
family2str(dplane_ctx_neightable_get_family(ctx)));
break;
case DPLANE_OP_GRE_SET:
zlog_debug("Dplane gre set op %s, ifp %s, link %u",
dplane_op2str(dplane_ctx_get_op(ctx)),
dplane_ctx_get_ifname(ctx),
ctx->u.gre.link_ifindex);
break;
}
}
@ -4808,6 +4927,12 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
memory_order_relaxed);
break;
case DPLANE_OP_GRE_SET:
if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
atomic_fetch_add_explicit(
&zdplane_info.dg_gre_set_errors, 1,
memory_order_relaxed);
break;
/* Ignore 'notifications' - no-op */
case DPLANE_OP_SYS_ROUTE_ADD:
case DPLANE_OP_SYS_ROUTE_DELETE:

View File

@ -171,6 +171,7 @@ enum dplane_op_e {
DPLANE_OP_NEIGH_IP_DELETE,
DPLANE_OP_NEIGH_TABLE_UPDATE,
DPLANE_OP_GRE_SET,
};
/*
@ -527,6 +528,14 @@ dplane_ctx_neightable_get_mcast_probes(const struct zebra_dplane_ctx *ctx);
uint32_t
dplane_ctx_neightable_get_ucast_probes(const struct zebra_dplane_ctx *ctx);
/* Accessor for GRE set */
uint32_t
dplane_ctx_gre_get_link_ifindex(const struct zebra_dplane_ctx *ctx);
unsigned int
dplane_ctx_gre_get_mtu(const struct zebra_dplane_ctx *ctx);
const struct zebra_l2info_gre *
dplane_ctx_gre_get_info(const struct zebra_dplane_ctx *ctx);
/* Namespace info - esp. for netlink communication */
const struct zebra_dplane_info *dplane_ctx_get_ns(
const struct zebra_dplane_ctx *ctx);
@ -695,6 +704,13 @@ enum zebra_dplane_result dplane_neigh_table_update(const struct interface *ifp,
const uint32_t ucast_probes,
const uint32_t mcast_probes);
/*
* Enqueue a GRE set
*/
enum zebra_dplane_result
dplane_gre_set(struct interface *ifp, struct interface *ifp_link,
unsigned int mtu, const struct zebra_l2info_gre *gre_info);
/* Forward ref of zebra_pbr_rule */
struct zebra_pbr_rule;

View File

@ -134,6 +134,7 @@ enum zebra_log_refs {
EC_ZEBRA_DUPLICATE_NHG_MESSAGE,
EC_ZEBRA_VRF_MISCONFIGURED,
EC_ZEBRA_ES_CREATE,
EC_ZEBRA_GRE_SET_UPDATE,
};
void zebra_error_init(void);

View File

@ -289,6 +289,32 @@ void zebra_l2_vlanif_update(struct interface *ifp,
memcpy(&zif->l2info.vl, vlan_info, sizeof(*vlan_info));
}
/*
* Update L2 info for a GRE interface. This is called upon interface
* addition as well as update. Upon add/update, need to inform
* clients about GRE information.
*/
void zebra_l2_greif_add_update(struct interface *ifp,
struct zebra_l2info_gre *gre_info, int add)
{
struct zebra_if *zif;
struct in_addr old_vtep_ip;
zif = ifp->info;
assert(zif);
if (add) {
memcpy(&zif->l2info.gre, gre_info, sizeof(*gre_info));
return;
}
old_vtep_ip = zif->l2info.gre.vtep_ip;
if (IPV4_ADDR_SAME(&old_vtep_ip, &gre_info->vtep_ip))
return;
zif->l2info.gre.vtep_ip = gre_info->vtep_ip;
}
/*
* Update L2 info for a VxLAN interface. This is called upon interface
* addition as well as update. Upon add, need to invoke the VNI create

View File

@ -54,6 +54,18 @@ struct zebra_l2info_vlan {
vlanid_t vid; /* VLAN id */
};
/* zebra L2 interface information - GRE interface */
struct zebra_l2info_gre {
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
*/
ns_id_t link_nsid;
};
/* zebra L2 interface information - VXLAN interface */
struct zebra_l2info_vxlan {
vni_t vni; /* VNI */
@ -75,6 +87,7 @@ union zebra_l2if_info {
struct zebra_l2info_bridge br;
struct zebra_l2info_vlan vl;
struct zebra_l2info_vxlan vxl;
struct zebra_l2info_gre gre;
};
/* NOTE: These macros are to be invoked only in the "correct" context.
@ -96,11 +109,15 @@ extern void zebra_l2_bridge_add_update(struct interface *ifp,
extern void zebra_l2_bridge_del(struct interface *ifp);
extern void zebra_l2_vlanif_update(struct interface *ifp,
struct zebra_l2info_vlan *vlan_info);
extern void zebra_l2_greif_add_update(struct interface *ifp,
struct zebra_l2info_gre *vxlan_info,
int add);
extern void zebra_l2_vxlanif_add_update(struct interface *ifp,
struct zebra_l2info_vxlan *vxlan_info,
int add);
extern void zebra_l2_vxlanif_update_access_vlan(struct interface *ifp,
vlanid_t access_vlan);
extern void zebra_l2_greif_del(struct interface *ifp);
extern void zebra_l2_vxlanif_del(struct interface *ifp);
extern void zebra_l2if_update_bridge_slave(struct interface *ifp,
ifindex_t bridge_ifindex,

View File

@ -2965,6 +2965,7 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_IPSET_ENTRY_ADD:
case DPLANE_OP_IPSET_ENTRY_DELETE:
case DPLANE_OP_NEIGH_TABLE_UPDATE:
case DPLANE_OP_GRE_SET:
break;
}

View File

@ -4062,6 +4062,7 @@ static int rib_process_dplane_results(struct thread *thread)
case DPLANE_OP_NEIGH_DISCOVER:
case DPLANE_OP_BR_PORT_UPDATE:
case DPLANE_OP_NEIGH_TABLE_UPDATE:
case DPLANE_OP_GRE_SET:
case DPLANE_OP_NONE:
/* Don't expect this: just return the struct? */
dplane_ctx_fini(&ctx);