[Devel] [PATCH RHEL7 COMMIT] ve/veth: add ability to enable vz-specific features

Konstantin Khorenko khorenko at virtuozzo.com
Mon Jun 8 09:24:22 PDT 2015


The commit is pushed to "branch-rh7-3.10.0-123.1.2-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-123.1.2.vz7.5.11
------>
commit d6d2385a872895a5ebc325ef745533d6b561eb5c
Author: Andrew Vagin <avagin at openvz.org>
Date:   Mon Jun 8 20:24:22 2015 +0400

    ve/veth: add ability to enable vz-specific features
    
    For example, vzethdev filters packages by MAC addresses.
    
    https://jira.sw.ru/browse/PSBM-32276
    
    Signed-off-by: Andrew Vagin <avagin at openvz.org>
    Reviewed-by: Kirill Tkhai <ktkhai at odin.com>
    
    ===========================================================
    VZ veth features description:
    
    1) vzctl creates a pair of veth interfaces CT 0 <-> CT N
    
    2) vzctl in CT0 calls ioctl SIOCSVENET (in include/uapi/linux/veth.h) on one of veth interfaces,
       it will enable Virtuozzo features for veth pair.
       This ioctl automatically enables skb marks saving on going out of a net namespace, which can be used
       for CT traffic accounting on CT0.
    
       Notes:
       a) no need to call this ioctl for 2 interfaces
       b) CT owner cannot call this ioctl because it's guarded by capable(CAP_NET_ADMIN), available on CT0 only
       c) it's impossible to disable VZ features on veth pair once enabled
    
    3) after veth pair is created, MAC change functionality is enabled both from CT0 and from inside a CT
    
    4) vzctl can set appropriate MAC addresses for both veth interfaces
    
    5) vzctl can call SIOCSFIXEDADDR ioctl (in include/uapi/linux/veth.h) on veth interface with ifr_ifru.ifru_flags set to 1,
       which disables ability to change MAC addresses on both ends.
       The possibility to change MAC can be re-enabled by calling SIOCSFIXEDADDR ioctl with ifr_ifru.ifru_flags set to 0.
    
       Note: MAC change prevention will work _only_ after ioctl SIOCSVENET is called on a veth interface.
    
    =========================================================
    Here is an example how to call ioctl-s from Andrey Vagin.
    
    #include <string.h>
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <linux/if.h>
    #include <sys/ioctl.h>
    
    #ifndef SIOCSFIXEDADDR
    #define SIOCSVENET      (SIOCDEVPRIVATE + 0xf)
    #define SIOCSFIXEDADDR  (SIOCDEVPRIVATE + 0xe)
    #endif
    
    int main(int argc, char **argv)
    {
    	struct ifreq req;
    	int sk;
    
    	sk = socket(AF_UNIX, SOCK_DGRAM, 0);
    	strcpy(req.ifr_ifrn.ifrn_name, argv[1]);
    	req.ifr_ifru.ifru_flags = 1;
    
    	if (ioctl(sk, SIOCSVENET, &req)) {
    		printf("SIOCSVENET: %m");
    		return 1;
    	}
    	if (ioctl(sk, SIOCSFIXEDADDR, &req)) {
    		printf("SIOCSFIXEDADDR: %m");
    		return 1;
    	}
    	return 0;
    }
---
 drivers/net/veth.c        | 24 ++++++++++++++++++++++++
 include/uapi/linux/veth.h |  2 ++
 2 files changed, 26 insertions(+)

diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 04d8d7e..7f64043 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -244,6 +244,29 @@ static void veth_dev_free(struct net_device *dev)
 	free_netdev(dev);
 }
 
+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->features |= NETIF_F_VENET;
+		dev->features |= NETIF_F_VENET;
+		rcu_read_unlock();
+
+		return 0;
+	}
+	return -ENOTTY;
+}
+
 static const struct net_device_ops veth_netdev_ops = {
 	.ndo_init            = veth_dev_init,
 	.ndo_open            = veth_open,
@@ -252,6 +275,7 @@ static const struct net_device_ops veth_netdev_ops = {
 	.ndo_change_mtu      = veth_change_mtu,
 	.ndo_get_stats64     = veth_get_stats64,
 	.ndo_set_mac_address = eth_mac_addr,
+	.ndo_do_ioctl        = vzethdev_net_ioctl,
 };
 
 #define VETH_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_TSO |    \
diff --git a/include/uapi/linux/veth.h b/include/uapi/linux/veth.h
index 6f893ae..27e7795 100644
--- a/include/uapi/linux/veth.h
+++ b/include/uapi/linux/veth.h
@@ -18,4 +18,6 @@ enum {
 #define VETH_INFO_MAX	(__VETH_INFO_MAX - 1)
 };
 
+#define SIOCSVENET	(SIOCDEVPRIVATE + 0xf)
+
 #endif



More information about the Devel mailing list