diff -uprN aa/include/linux/ve.h bb/include/linux/ve.h --- aa/include/linux/ve.h 2007-09-13 17:43:16.000000000 +0400 +++ bb/include/linux/ve.h 2007-09-13 17:59:08.000000000 +0400 @@ -51,6 +51,7 @@ struct nsproxy; #if defined(CONFIG_VE) && defined(CONFIG_NET) struct ve_ipip_tunnels; +struct ve_sit_tunnels; #endif /* CONFIG_VE && CONFIG_NET */ #if defined(CONFIG_VE) && defined(CONFIG_INET) @@ -198,6 +199,7 @@ struct ve_struct { struct net_device *_loopback_dev; struct net_device_stats *_loopback_stats; struct ve_ipip_tunnels *_ve_ipip_tunnels; + struct ve_sit_tunnels *_ve_sit_tunnels; #ifdef CONFIG_INET struct ipv4_devconf *_ipv4_devconf; struct ipv4_devconf *_ipv4_devconf_dflt; diff -uprN aa/include/net/ipip.h bb/include/net/ipip.h --- aa/include/net/ipip.h 2007-09-13 17:43:38.000000000 +0400 +++ bb/include/net/ipip.h 2007-09-13 18:29:01.000000000 +0400 @@ -49,6 +49,7 @@ extern int sit_init(void); extern void sit_cleanup(void); #define HASH_SIZE_IPIP 16 +#define HASH_SIZE_SIT 16 #if defined(CONFIG_VE) struct ve_ipip_tunnels { @@ -60,6 +61,16 @@ struct ve_ipip_tunnels { struct ip_tunnel **tunnels[4]; rwlock_t ipip_lock; }; + +struct ve_sit_tunnels { + struct net_device *ipip6_fb_tunnel_dev; + struct ip_tunnel *tunnels_r_l[HASH_SIZE_SIT]; + struct ip_tunnel *tunnels_r[HASH_SIZE_SIT]; + struct ip_tunnel *tunnels_l[HASH_SIZE_SIT]; + struct ip_tunnel *tunnels_wc[1]; + struct ip_tunnel **tunnels[4]; + rwlock_t ipip6_lock; +}; #endif /* CONFIG_VE */ #endif diff -uprN aa/net/ipv6/sit.c bb/net/ipv6/sit.c --- aa/net/ipv6/sit.c 2007-09-13 17:45:09.000000000 +0400 +++ bb/net/ipv6/sit.c 2007-09-13 19:59:36.000000000 +0400 @@ -52,6 +52,7 @@ #include #include #include +#include /* This version of net/ipv6/sit.c is cloned of net/ipv4/ip_gre.c @@ -59,13 +60,23 @@ For comments look at net/ipv4/ip_gre.c --ANK */ -#define HASH_SIZE 16 +#define HASH_SIZE HASH_SIZE_SIT #define HASH(addr) ((addr^(addr>>4))&0xF) static int ipip6_fb_tunnel_init(struct net_device *dev); static int ipip6_tunnel_init(struct net_device *dev); static void ipip6_tunnel_setup(struct net_device *dev); +#if defined(CONFIG_VE) +#define ipip6_fb_tunnel_dev \ + (get_exec_env()->_ve_sit_tunnels->ipip6_fb_tunnel_dev) +#define tunnels_r_l (get_exec_env()->_ve_sit_tunnels->tunnels_r_l) +#define tunnels_r (get_exec_env()->_ve_sit_tunnels->tunnels_r) +#define tunnels_l (get_exec_env()->_ve_sit_tunnels->tunnels_l) +#define tunnels_wc (get_exec_env()->_ve_sit_tunnels->tunnels_wc) +#define tunnels (get_exec_env()->_ve_sit_tunnels->tunnels) +#define ipip6_lock (get_exec_env()->_ve_sit_tunnels->ipip6_lock) +#else static struct net_device *ipip6_fb_tunnel_dev; static struct ip_tunnel *tunnels_r_l[HASH_SIZE]; @@ -75,6 +86,7 @@ static struct ip_tunnel *tunnels_wc[1]; static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunnels_r_l }; static DEFINE_RWLOCK(ipip6_lock); +#endif /* CONFIG_VE */ static struct ip_tunnel * ipip6_tunnel_lookup(u32 remote, u32 local) { @@ -618,7 +630,11 @@ ipip6_tunnel_ioctl (struct net_device *d case SIOCADDTUNNEL: case SIOCCHGTUNNEL: err = -EPERM; - if (!capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN) +#if defined(CONFIG_VE) + && !capable(CAP_VE_NET_ADMIN) +#endif /* CONFIG_VE */ + ) goto done; err = -EFAULT; @@ -671,7 +687,11 @@ ipip6_tunnel_ioctl (struct net_device *d case SIOCDELTUNNEL: err = -EPERM; - if (!capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN) +#if defined(CONFIG_VE) + && !capable(CAP_VE_NET_ADMIN) +#endif /* CONFIG_VE */ + ) goto done; if (dev == ipip6_fb_tunnel_dev) { @@ -726,6 +746,9 @@ static void ipip6_tunnel_setup(struct ne dev->flags = IFF_NOARP; dev->iflink = 0; dev->addr_len = 4; +#if defined(CONFIG_VE) + dev->features = NETIF_F_VIRTUAL; +#endif /* CONFIG_VE */ } static int ipip6_tunnel_init(struct net_device *dev) @@ -772,7 +795,7 @@ static int ipip6_tunnel_init(struct net_ return 0; } -static int __init ipip6_fb_tunnel_init(struct net_device *dev) +static int ipip6_fb_tunnel_init(struct net_device *dev) { struct ip_tunnel *tunnel = netdev_priv(dev); struct iphdr *iph = &tunnel->parms.iph; @@ -795,7 +818,7 @@ static struct net_protocol sit_protocol .err_handler = ipip6_err, }; -static void __exit sit_destroy_tunnels(void) +static void sit_destroy_tunnels(void) { int prio; @@ -809,14 +832,93 @@ static void __exit sit_destroy_tunnels(v } } +#if defined(CONFIG_VE) +static int sit_ve_start(void *data) +{ + struct ve_struct *env; + int err; + + env = (struct ve_struct *)data; + if (!ve_is_super(env)) + __module_get(THIS_MODULE); + + env->_ve_sit_tunnels = + kmalloc(sizeof(struct ve_sit_tunnels), GFP_KERNEL); + if (!env->_ve_sit_tunnels) { + err = -ENOMEM; + goto out; + } + memset(env->_ve_sit_tunnels, 0, sizeof(struct ve_sit_tunnels)); + tunnels[0] = tunnels_wc; + tunnels[1] = tunnels_l; + tunnels[2] = tunnels_r; + tunnels[3] = tunnels_r_l; + rwlock_init(&ipip6_lock); + + if (ve_is_super(env)) + return 0; + + ipip6_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0", + ipip6_tunnel_setup); + if (!ipip6_fb_tunnel_dev) { + err = -ENOMEM; + goto free_tunnel; + } + ipip6_fb_tunnel_dev->init = ipip6_fb_tunnel_init; + if ((err = register_netdev(ipip6_fb_tunnel_dev))) + goto free_netdev; + return 0; + + free_netdev: + free_netdev(ipip6_fb_tunnel_dev); + free_tunnel: + kfree(env->_ve_sit_tunnels); + env->_ve_sit_tunnels = NULL; + if (!ve_is_super(env)) + module_put(THIS_MODULE); + out: + return err; +} + +static void sit_ve_stop(void *data) +{ + struct ve_struct *env; + + env = (struct ve_struct *)data; + if (env->_ve_sit_tunnels == NULL) + return; + if (!ve_is_super(env)) { + rtnl_lock(); + sit_destroy_tunnels(); + unregister_netdevice(ipip6_fb_tunnel_dev); + rtnl_unlock(); + } + kfree(env->_ve_sit_tunnels); + env->_ve_sit_tunnels = NULL; + if (!ve_is_super(env)) + module_put(THIS_MODULE); +} + +static struct ve_hook sit_ve_hook = { + .init = sit_ve_start, + .fini = sit_ve_stop, + .owner = THIS_MODULE, + .priority = HOOK_PRIO_NET_POST, +}; +#endif /* CONFIG_VE */ + void __exit sit_cleanup(void) { + ve_hook_unregister(&sit_ve_hook); inet_del_protocol(&sit_protocol, IPPROTO_IPV6); rtnl_lock(); sit_destroy_tunnels(); unregister_netdevice(ipip6_fb_tunnel_dev); rtnl_unlock(); +#if defined(CONFIG_VE) + sit_ve_stop(get_exec_env()); +#endif /* CONFIG_VE */ } int __init sit_init(void) @@ -830,23 +932,34 @@ int __init sit_init(void) return -EAGAIN; } +#if defined(CONFIG_VE) + err = sit_ve_start(get_exec_env()); + if (err) + goto err1; +#endif /* CONFIG_VE */ ipip6_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0", ipip6_tunnel_setup); if (!ipip6_fb_tunnel_dev) { err = -ENOMEM; - goto err1; + goto err2; } ipip6_fb_tunnel_dev->init = ipip6_fb_tunnel_init; if ((err = register_netdev(ipip6_fb_tunnel_dev))) - goto err2; + goto err3; + + ve_hook_register(VE_SS_CHAIN, &sit_ve_hook); out: return err; - err2: + err3: free_netdev(ipip6_fb_tunnel_dev); + err2: +#if defined(CONFIG_VE) + sit_ve_stop(get_exec_env()); err1: +#endif /* CONFIG_VE */ inet_del_protocol(&sit_protocol, IPPROTO_IPV6); goto out; }