zebra: storage of gre information in zebra layer

zebra is able to get information about gre tunnels.
zebra_gre file is created to handle hooks, but is not yet used.
also, debug zebra gre command is done to add gre traces.
A zebra_gre file is used for complementary actions that may be needed.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
Philippe Guibert 2019-12-19 18:33:56 +01:00
parent c962ab93a8
commit 077c07cc58
7 changed files with 200 additions and 3 deletions

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

@ -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>
@ -289,6 +292,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) \
@ -492,6 +497,43 @@ 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 (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 +614,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);
}
}

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*/);
@ -1105,8 +1106,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*/);
@ -1304,6 +1306,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";
}
@ -1576,6 +1581,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

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