From mboxrd@z Thu Jan 1 00:00:00 1970 From: Konstantin Khorenko Date: Wed, 12 Aug 2026 15:03:58 +0200 Subject: [Devel] [PATCH DRAFT vz10 2/5] ve/net/gre: Enable ERSPAN support in Containers under VE_FEATURE_ERSPAN In-Reply-To: <20260812130401.154702-1-khorenko@virtuozzo.com> References: <20260812130401.154702-1-khorenko@virtuozzo.com> Message-ID: <20260812130401.154702-3-khorenko@virtuozzo.com> List-Id: 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 --- 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