[Devel] [PATCH DRAFT vz10 2/5] ve/net/gre: Enable ERSPAN support in Containers under VE_FEATURE_ERSPAN
Konstantin Khorenko
khorenko at virtuozzo.com
Wed Aug 12 16:03:58 MSK 2026
Commit a6adc8063402 ("ve/net/gre: Disable ERSPAN support in ip_gre
module") compiled ERSPAN out under CONFIG_VE because it was not wired
into the per-Container GRE infrastructure. Its revert brings the code
back; this commit integrates ERSPAN into the Container framework so it
can be used inside a CT, gated by a dedicated feature bit.
ERSPAN is a Cisco-specific traffic mirroring protocol built on top of
GRE, but it is a separate device type from ip_gre/gretap and has its
own pernet id (erspan_net_id). Reusing VE_FEATURE_IPGRE would tie the
two together, so introduce a standalone VE_FEATURE_ERSPAN bit. It is
disabled by default for Containers (VE_FEATURES_DEF) and enabled for
the host (init_ve has all features set), so host behaviour is
unchanged.
Integration mirrors what is already done for ip_gre/gretap:
- erspan_setup() marks the device NETIF_F_VIRTUAL so that
register_netdevice() permits it inside a non-super VE;
- erspan_init_net() frees its net_generic slot and skips device
creation when the feature is off, so erspan_net_id is NULL for such
a CT; the lookup path is already guarded against a NULL itn in
ip_tunnel_lookup(), so the rx/error paths are safe;
- device creation and reconfiguration (erspan_newlink/changelink)
reject the operation with -EACCES when the feature is off, before
reaching ip_tunnel_newlink() which would dereference the NULL
net_generic slot.
The VE feature check is dropped from ipgre_newlink_encap_setup() and
done explicitly in each rtnl link operation via ve_feature_set(), so
the ip_gre/gretap paths keep checking VE_FEATURE_IPGRE while the erspan
paths check VE_FEATURE_ERSPAN.
https://virtuozzo.atlassian.net/browse/VSTOR-141173
Feature: net: ERSPAN support in Containers
Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
---
include/uapi/linux/vzcalluser.h | 1 +
net/ipv4/ip_gre.c | 26 +++++++++++++++++++++-----
2 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/include/uapi/linux/vzcalluser.h b/include/uapi/linux/vzcalluser.h
index 000e3ee107add..a716e0b41ef30 100644
--- a/include/uapi/linux/vzcalluser.h
+++ b/include/uapi/linux/vzcalluser.h
@@ -49,6 +49,7 @@ struct vzctl_ve_configure {
#define VE_FEATURE_NFSD (1ULL << 8)
#define VE_FEATURE_TIME (1ULL << 9)
#define VE_FEATURE_BPF (1ULL << 10)
+#define VE_FEATURE_ERSPAN (1ULL << 11)
#define VE_FEATURES_OLD (VE_FEATURE_SYSFS)
#define VE_FEATURES_DEF (VE_FEATURE_SYSFS | VE_FEATURE_DEF_PERMS)
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index d776eb8d9f76c..b4db5112c3853 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -1390,11 +1390,6 @@ ipgre_newlink_encap_setup(struct net_device *dev, struct nlattr *data[])
{
struct ip_tunnel_encap ipencap;
-#ifdef CONFIG_VE
- if (!(dev_net(dev)->owner_ve->features & VE_FEATURE_IPGRE))
- return -EACCES;
-#endif
-
if (ipgre_netlink_encap_parms(data, &ipencap)) {
struct ip_tunnel *t = netdev_priv(dev);
int err = ip_tunnel_encap_setup(t, &ipencap);
@@ -1414,6 +1409,9 @@ static int ipgre_newlink(struct net *src_net, struct net_device *dev,
__u32 fwmark = 0;
int err;
+ if (!ve_feature_set(dev_net(dev)->owner_ve, IPGRE))
+ return -EACCES;
+
err = ipgre_newlink_encap_setup(dev, data);
if (err)
return err;
@@ -1432,6 +1430,9 @@ static int erspan_newlink(struct net *src_net, struct net_device *dev,
__u32 fwmark = 0;
int err;
+ if (!ve_feature_set(dev_net(dev)->owner_ve, ERSPAN))
+ return -EACCES;
+
err = ipgre_newlink_encap_setup(dev, data);
if (err)
return err;
@@ -1451,6 +1452,9 @@ static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
__u32 fwmark = t->fwmark;
int err;
+ if (!ve_feature_set(dev_net(dev)->owner_ve, IPGRE))
+ return -EACCES;
+
err = ipgre_newlink_encap_setup(dev, data);
if (err)
return err;
@@ -1480,6 +1484,9 @@ static int erspan_changelink(struct net_device *dev, struct nlattr *tb[],
__u32 fwmark = t->fwmark;
int err;
+ if (!ve_feature_set(dev_net(dev)->owner_ve, ERSPAN))
+ return -EACCES;
+
err = ipgre_newlink_encap_setup(dev, data);
if (err)
return err;
@@ -1631,6 +1638,9 @@ static void erspan_setup(struct net_device *dev)
dev->netdev_ops = &erspan_netdev_ops;
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
+#ifdef CONFIG_VE
+ dev->ve_features = NETIF_F_VIRTUAL;
+#endif
ip_tunnel_setup(dev, erspan_net_id);
t->erspan_ver = 1;
}
@@ -1776,6 +1786,12 @@ static struct pernet_operations ipgre_tap_net_ops = {
static int __net_init erspan_init_net(struct net *net)
{
+#ifdef CONFIG_VE
+ if (!(net->owner_ve->features & VE_FEATURE_ERSPAN)) {
+ net_generic_free(net, erspan_net_id);
+ return 0;
+ }
+#endif
return ip_tunnel_init_net(net, erspan_net_id,
&erspan_link_ops, "erspan0");
}
--
2.43.0
More information about the Devel
mailing list