summaryrefslogtreecommitdiffstats
path: root/zebra
diff options
context:
space:
mode:
authorMark Stapp <mjs@voltanet.io>2021-05-05 13:57:04 +0200
committerGitHub <noreply@github.com>2021-05-05 13:57:04 +0200
commit3d4b999fab50a4f08d2c4257ec059218a90ed29f (patch)
tree135eea80ddb75fb83ff291f43b7f1a87572cf5d6 /zebra
parentMerge pull request #8564 from rameshabhinay/bgp_tcp_mss (diff)
parentnhrpd: move prototype to top of file (diff)
downloadfrr-3d4b999fab50a4f08d2c4257ec059218a90ed29f.tar.xz
frr-3d4b999fab50a4f08d2c4257ec059218a90ed29f.zip
Merge pull request #8237 from pguibert6WIND/nhrp_use_zebra_2
Nhrp use zebra 2
Diffstat (limited to 'zebra')
-rw-r--r--zebra/debug.c2
-rw-r--r--zebra/if_netlink.c145
-rw-r--r--zebra/if_netlink.h3
-rw-r--r--zebra/interface.c31
-rw-r--r--zebra/interface.h4
-rw-r--r--zebra/kernel_netlink.c3
-rw-r--r--zebra/rt.h3
-rw-r--r--zebra/rt_socket.c6
-rw-r--r--zebra/zapi_msg.c108
-rw-r--r--zebra/zebra_dplane.c125
-rw-r--r--zebra/zebra_dplane.h16
-rw-r--r--zebra/zebra_errors.h1
-rw-r--r--zebra/zebra_l2.c26
-rw-r--r--zebra/zebra_l2.h17
-rw-r--r--zebra/zebra_nhg.c1
-rw-r--r--zebra/zebra_rib.c1
16 files changed, 480 insertions, 12 deletions
diff --git a/zebra/debug.c b/zebra/debug.c
index a8ddf6ba6..88a3d9881 100644
--- a/zebra/debug.c
+++ b/zebra/debug.c
@@ -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
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index e7d8b318e..fbf64439e 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -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)
{
diff --git a/zebra/if_netlink.h b/zebra/if_netlink.h
index 0bbba81ca..4f09b10b7 100644
--- a/zebra/if_netlink.h
+++ b/zebra/if_netlink.h
@@ -33,6 +33,9 @@ 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);
diff --git a/zebra/interface.c b/zebra/interface.c
index e7357cb30..7fd967dd8 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -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)) {
diff --git a/zebra/interface.h b/zebra/interface.h
index 24bc70cb9..df4872d48 100644
--- a/zebra/interface.h
+++ b/zebra/interface.h
@@ -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)
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index adb61023c..cd22e9573 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -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;
}
diff --git a/zebra/rt.h b/zebra/rt.h
index daaa926a7..f79ddbe95 100644
--- a/zebra/rt.h
+++ b/zebra/rt.h
@@ -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.
diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c
index ada828d01..006513ac9 100644
--- a/zebra/rt_socket.c
+++ b/zebra/rt_socket.c
@@ -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)
{
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 77a9188fe..55f8edd27 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -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,
};
/*
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index c8ee8f905..a8df0c56c 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -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)
{
@@ -4126,6 +4167,71 @@ dplane_pbr_ipset_entry_delete(struct zebra_pbr_ipset_entry *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'
*/
int dplane_show_helper(struct vty *vty, bool detailed)
@@ -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:
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index 8d51d93cd..3a8536dda 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -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;
diff --git a/zebra/zebra_errors.h b/zebra/zebra_errors.h
index fc0382a6c..200a977a6 100644
--- a/zebra/zebra_errors.h
+++ b/zebra/zebra_errors.h
@@ -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);
diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c
index c3fbff272..71fac556e 100644
--- a/zebra/zebra_l2.c
+++ b/zebra/zebra_l2.c
@@ -290,6 +290,32 @@ void zebra_l2_vlanif_update(struct interface *ifp,
}
/*
+ * 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
* function. Upon update, the params of interest are the local tunnel
diff --git a/zebra/zebra_l2.h b/zebra/zebra_l2.h
index 183443028..6572f344c 100644
--- a/zebra/zebra_l2.h
+++ b/zebra/zebra_l2.h
@@ -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,
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index 47651318a..6b40eae5b 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -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;
}
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index bdacd411b..dbc5c77fd 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -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);