[Devel] [PATCH v2 RH9 3/3] vzeth: bits and pieces of our interface

Pavel Tikhomirov ptikhomirov at virtuozzo.com
Wed Oct 27 17:45:28 MSK 2021


From: Konstantin Khorenko <khorenko at virtuozzo.com>

Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
Signed-off-by: Konstantin Khlebnikov <khlebnikov at openvz.org>
Signed-off-by: Stanislav Kinsbursky <skinsbursky at parallels.com>
Signed-off-by: Andrew Vagin <avagin at openvz.org>
Signed-off-by: Vladimir Davydov <vdavydov at parallels.com>
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>

vz9 changes:
- remove excess vzctl_veth.h
- remove excess include of br_private.h
- put everything under CONFIG_VE

v2: cleanup vzethdev_filter

https://jira.sw.ru/browse/PSBM-135200
(cherry picked from vz8 commit c4c1af66f15295e64ba722219bfb7838a46ec510)
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
 drivers/net/veth.c              | 85 ++++++++++++++++++++++++++++++++-
 include/linux/netdev_features.h |  2 +
 include/uapi/linux/veth.h       |  3 ++
 3 files changed, 89 insertions(+), 1 deletion(-)

diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index bdb7ce3cb054..1ccd8e7ed0f1 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -294,6 +294,34 @@ static int veth_forward_skb(struct net_device *dev, struct sk_buff *skb,
 		netif_rx(skb);
 }
 
+#ifdef CONFIG_VE
+static int vzethdev_filter(struct sk_buff *skb, struct net_device *dev, struct net_device *rcv)
+{
+	struct ethhdr *eh;
+
+	if (!(dev->ve_features & NETIF_F_FIXED_ADDR))
+		return 1;
+
+	/* Filtering */
+	eh = (struct ethhdr *)skb->data;
+	if (ve_is_super(dev_net(dev)->owner_ve)) {
+		/* from VE0 to VEX */
+		if (ve_is_super(dev_net(rcv)->owner_ve))
+			return 1;
+		if (is_multicast_ether_addr(eh->h_dest))
+			return 1;
+		if (!ether_addr_equal(eh->h_dest, rcv->dev_addr))
+			return 0;
+	} else {
+		/* from VEX to VE0 */
+		if (!ether_addr_equal(eh->h_source, dev->dev_addr))
+			return 0;
+	}
+
+	return 1;
+}
+#endif
+
 /* return true if the specified skb has chances of GRO aggregation
  * Don't strive for accuracy, but try to avoid GRO overhead in the most
  * common scenarios.
@@ -329,6 +357,13 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
 		goto drop;
 	}
 
+#ifdef CONFIG_VE
+	if (dev->ve_features & NETIF_F_VENET && !vzethdev_filter(skb, dev, rcv)) {
+		kfree_skb(skb);
+		goto drop;
+	}
+#endif
+
 	rcv_priv = netdev_priv(rcv);
 	rxq = skb_get_queue_mapping(skb);
 	if (rxq < rcv->real_num_rx_queues) {
@@ -1364,6 +1399,46 @@ static int veth_xdp(struct net_device *dev, struct netdev_bpf *xdp)
 	}
 }
 
+#ifdef CONFIG_VE
+static int veth_mac_addr(struct net_device *dev, void *p)
+{
+	if (dev->ve_features & NETIF_F_VENET &&
+	    dev->ve_features & NETIF_F_FIXED_ADDR)
+		return -EPERM;
+	return eth_mac_addr(dev, p);
+}
+
+static int vzethdev_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	switch (cmd) {
+	case SIOCSVENET:
+	{
+		struct veth_priv *priv = netdev_priv(dev);
+		struct net_device *rcv;
+
+		rcu_read_lock();
+		rcv = rcu_dereference(priv->peer);
+		if (rcv)
+			rcv->ve_features |= NETIF_F_VENET;
+		dev->ve_features |= NETIF_F_VENET;
+		rcu_read_unlock();
+
+		return 0;
+	}
+	case SIOCSFIXEDADDR:
+		if (ifr->ifr_ifru.ifru_flags)
+			dev->ve_features |= NETIF_F_FIXED_ADDR;
+		else
+			dev->ve_features &= ~NETIF_F_FIXED_ADDR;
+		return 0;
+	}
+	return -ENOTTY;
+}
+#endif
+
 static const struct net_device_ops veth_netdev_ops = {
 	.ndo_init            = veth_dev_init,
 	.ndo_open            = veth_open,
@@ -1371,7 +1446,6 @@ static const struct net_device_ops veth_netdev_ops = {
 	.ndo_start_xmit      = veth_xmit,
 	.ndo_get_stats64     = veth_get_stats64,
 	.ndo_set_rx_mode     = veth_set_multicast_list,
-	.ndo_set_mac_address = eth_mac_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= veth_poll_controller,
 #endif
@@ -1383,6 +1457,12 @@ static const struct net_device_ops veth_netdev_ops = {
 	.ndo_bpf		= veth_xdp,
 	.ndo_xdp_xmit		= veth_ndo_xdp_xmit,
 	.ndo_get_peer_dev	= veth_peer_dev,
+#ifdef CONFIG_VE
+	.ndo_set_mac_address	= veth_mac_addr,
+	.ndo_do_ioctl		= vzethdev_net_ioctl,
+#else
+	.ndo_set_mac_address	= eth_mac_addr,
+#endif
 };
 
 #define VETH_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HW_CSUM | \
@@ -1404,6 +1484,9 @@ static void veth_setup(struct net_device *dev)
 	dev->ethtool_ops = &veth_ethtool_ops;
 	dev->features |= NETIF_F_LLTX;
 	dev->features |= VETH_FEATURES;
+#ifdef CONFIG_VE
+	dev->ve_features = NETIF_F_VIRTUAL;
+#endif
 	dev->vlan_features = dev->features &
 			     ~(NETIF_F_HW_VLAN_CTAG_TX |
 			       NETIF_F_HW_VLAN_STAG_TX |
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index 9945162fa074..22789112fa5b 100644
--- a/include/linux/netdev_features.h
+++ b/include/linux/netdev_features.h
@@ -172,10 +172,12 @@ enum {
 enum {
 	NETIF_F_VIRTUAL_BIT,	/* Device is venet device */
 	NETIF_F_VENET_BIT,	/* Device is venet device */
+	NETIF_F_FIXED_ADDR_BIT,	/* Device has fixed mac */
 };
 
 #define NETIF_F_VIRTUAL		__NETIF_F(VIRTUAL)
 #define NETIF_F_VENET		__NETIF_F(VENET)
+#define NETIF_F_FIXED_ADDR	__NETIF_F(FIXED_ADDR)
 #endif
 
 /* Finds the next feature with the highest number of the range of start till 0.
diff --git a/include/uapi/linux/veth.h b/include/uapi/linux/veth.h
index 52b58e587e23..ccc020590969 100644
--- a/include/uapi/linux/veth.h
+++ b/include/uapi/linux/veth.h
@@ -10,4 +10,7 @@ enum {
 #define VETH_INFO_MAX	(__VETH_INFO_MAX - 1)
 };
 
+#define SIOCSVENET	(SIOCDEVPRIVATE + 0xf)
+#define SIOCSFIXEDADDR	(SIOCDEVPRIVATE + 0xe)
+
 #endif
-- 
2.31.1



More information about the Devel mailing list