: Make IPGRE tunnel work in net namespaces.
Subsystems (3)
cover : Make IPGRE tunnel work in net namespaces.
This one is mostly the same as the ipip one.
Hm... these sets are more likely ~8 patches each, not ~7 as I promised earlier...
PATCH 1/8 : Introduce empty ipgre_net structure and net init/exit ops.
--- net/ipv4/ip_gre.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 49 insertions(+), 0 deletions(-)
net/ipv4/ip_gre.c +49 -0
@@ -39,6 +39,8 @@#include <net/dsfield.h> #include <net/inet_ecn.h> #include <net/xfrm.h> +#include <net/net_namespace.h> +#include <net/netns/generic.h> #ifdef CONFIG_IPV6 #include <net/ipv6.h>
@@ -122,6 +124,10 @@ static void ipgre_tunnel_setup(struct net_device *dev);static int ipgre_fb_tunnel_init (struct net_device *dev); +static int ipgre_net_id; +struct ipgre_net { +}; +static struct net_device *ipgre_fb_tunnel_dev;/* Tunnel hash table */
@@ -1275,6 +1281,40 @@ static struct net_protocol ipgre_protocol = { .err_handler = ipgre_err, }; +static int ipgre_init_net (struct net *net) +{ +int err; +struct ipgre_net *ign; + + err = -ENOMEM ; + ign =kmalloc (sizeof (struct ipgre_net ),GFP_KERNEL ); +if (ign ==NULL ) + goto err_alloc; + + err =net_assign_generic (net, ipgre_net_id, ign); +if (err <0 ) + goto err_assign; + +return 0 ; + +err_assign: +kfree (ign); +err_alloc: +return err; +} + +static void ipgre_exit_net (struct net *net) +{ +struct ipgre_net *ign; + + ign =net_generic (net, ipgre_net_id); +kfree (ign); +} + +static struct pernet_operations ipgre_net_ops = { + .init = ipgre_init_net, + .exit = ipgre_exit_net, +};/* * And now the modules code and kernel interface.
@@ -1302,6 +1342,10 @@ static int __init ipgre_init(void)if ((err =register_netdev (ipgre_fb_tunnel_dev))) goto err2; + + err =register_pernet_gen_device (&ipgre_net_id, &ipgre_net_ops); +if (err <0 ) + goto err3; out:return err; err2:
@@ -1309,6 +1353,9 @@ err2: err1:inet_del_protocol (&ipgre_protocol,IPPROTO_GRE ); goto out; +err3: +unregister_netdevice (ipgre_fb_tunnel_dev); + goto err1; } static void __exit ipgre_destroy_tunnels(void)
@@ -1333,6 +1380,8 @@ static void __exit ipgre_fini(void)rtnl_lock ();ipgre_destroy_tunnels ();rtnl_unlock (); + +unregister_pernet_gen_device (ipgre_net_id, &ipgre_net_ops); }module_init (ipgre_init);
Signature · 1 line
1.5.3.4
PATCH 2/8 : Add net/gre_net argument to some functions.
In reply to Pavel EmelyanovThe fallback device and hashes are to become per-net, but many code doesn't have anything to get the struct net pointer from.
So pass the proper net there with an extra argument.
--- net/ipv4/ip_gre.c | 51 ++++++++++++++++++++++++++++++++------------------- 1 files changed, 32 insertions(+), 19 deletions(-)
net/ipv4/ip_gre.c +32 -19
@@ -162,7 +162,8 @@ static DEFINE_RWLOCK(ipgre_lock);/* Given src, dst and key, find appropriate for input tunnel. */ -static struct ip_tunnel *ipgre_tunnel_lookup (__be32 remote,__be32 local,__be32 key) +static struct ip_tunnel *ipgre_tunnel_lookup (struct net *net, +__be32 remote,__be32 local,__be32 key) {unsigned h0 =HASH (remote);unsigned h1 =HASH (key);
@@ -198,7 +199,8 @@ static struct ip_tunnel * ipgre_tunnel_lookup(__be32 remote, __be32 local, __be3return NULL ; } -static struct ip_tunnel **__ipgre_bucket (struct ip_tunnel_parm *parms) +static struct ip_tunnel **__ipgre_bucket (struct ipgre_net *ign, +struct ip_tunnel_parm *parms) {__be32 remote = parms->iph.daddr;__be32 local = parms->iph.saddr;
@@ -216,14 +218,15 @@ static struct ip_tunnel **__ipgre_bucket(struct ip_tunnel_parm *parms)return &tunnels[prio][h]; } -static inline struct ip_tunnel **ipgre_bucket (struct ip_tunnel *t) +static inline struct ip_tunnel **ipgre_bucket (struct ipgre_net *ign, +struct ip_tunnel *t) { -return __ipgre_bucket (&t->parms); +return __ipgre_bucket (ign, &t->parms); } -static void ipgre_tunnel_link (struct ip_tunnel *t) +static void ipgre_tunnel_link (struct ipgre_net *ign,struct ip_tunnel *t) { -struct ip_tunnel **tp =ipgre_bucket (t); +struct ip_tunnel **tp =ipgre_bucket (ign, t); t->next = *tp;write_lock_bh (&ipgre_lock);
@@ -231,11 +234,11 @@ static void ipgre_tunnel_link(struct ip_tunnel *t)write_unlock_bh (&ipgre_lock); } -static void ipgre_tunnel_unlink (struct ip_tunnel *t) +static void ipgre_tunnel_unlink (struct ipgre_net *ign,struct ip_tunnel *t) {struct ip_tunnel **tp; -for (tp =ipgre_bucket (t); *tp; tp = &(*tp)->next) { +for (tp =ipgre_bucket (ign, t); *tp; tp = &(*tp)->next) {if (t == *tp) {write_lock_bh (&ipgre_lock); *tp = t->next;
@@ -245,7 +248,8 @@ static void ipgre_tunnel_unlink(struct ip_tunnel *t) } } -static struct ip_tunnel *ipgre_tunnel_locate (struct ip_tunnel_parm *parms,int create) +static struct ip_tunnel *ipgre_tunnel_locate (struct net *net, +struct ip_tunnel_parm *parms,int create) {__be32 remote = parms->iph.daddr;__be32 local = parms->iph.saddr;
@@ -253,8 +257,9 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, intstruct ip_tunnel *t, **tp, *nt;struct net_device *dev;char name[IFNAMSIZ ]; +struct ipgre_net *ign =net_generic (net, ipgre_net_id); -for (tp =__ipgre_bucket (parms); (t = *tp) !=NULL ; tp = &t->next) { +for (tp =__ipgre_bucket (ign, parms); (t = *tp) !=NULL ; tp = &t->next) {if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) {if (key == t->parms.i_key)return t;
@@ -285,7 +290,7 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int goto failed_free;dev_hold (dev); -ipgre_tunnel_link (nt); +ipgre_tunnel_link (ign, nt);return nt; failed_free:
@@ -295,7 +300,10 @@ failed_free:static void ipgre_tunnel_uninit (struct net_device *dev) { -ipgre_tunnel_unlink (netdev_priv (dev)); +struct net *net =dev_net (dev); +struct ipgre_net *ign =net_generic (net, ipgre_net_id); + +ipgre_tunnel_unlink (ign,netdev_priv (dev));dev_put (dev); }
@@ -369,7 +377,9 @@ static void ipgre_err(struct sk_buff *skb, u32 info) }read_lock (&ipgre_lock); - t =ipgre_tunnel_lookup (iph->daddr, iph->saddr, (flags&GRE_KEY ) ? *(((__be32 *)p) + (grehlen>>2 ) -1 ) :0 ); + t =ipgre_tunnel_lookup (&init_net, iph->daddr, iph->saddr, + (flags&GRE_KEY ) ? + *(((__be32 *)p) + (grehlen>>2 ) -1 ) :0 );if (t ==NULL || t->parms.iph.daddr ==0 ||ipv4_is_multicast (t->parms.iph.daddr)) goto out;
@@ -602,7 +612,8 @@ static int ipgre_rcv(struct sk_buff *skb) }read_lock (&ipgre_lock); -if ((tunnel =ipgre_tunnel_lookup (iph->saddr, iph->daddr, key)) !=NULL ) { +if ((tunnel =ipgre_tunnel_lookup (&init_net, + iph->saddr, iph->daddr, key)) !=NULL ) {secpath_reset (skb); skb->protocol = *(__be16 *)(h +2 );
@@ -960,6 +971,8 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)int err =0 ;struct ip_tunnel_parm p;struct ip_tunnel *t; +struct net *net =dev_net (dev); +struct ipgre_net *ign =net_generic (net, ipgre_net_id);switch (cmd) {case SIOCGETTUNNEL :
@@ -969,7 +982,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) err = -EFAULT ;break ; } - t =ipgre_tunnel_locate (&p,0 ); + t =ipgre_tunnel_locate (net, &p,0 ); }if (t ==NULL ) t =netdev_priv (dev);
@@ -1001,7 +1014,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)if (!(p.o_flags&GRE_KEY )) p.o_key =0 ; - t =ipgre_tunnel_locate (&p, cmd ==SIOCADDTUNNEL ); + t =ipgre_tunnel_locate (net, &p, cmd ==SIOCADDTUNNEL );if (dev != ipgre_fb_tunnel_dev && cmd ==SIOCCHGTUNNEL ) {if (t !=NULL ) {
@@ -1023,14 +1036,14 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) err = -EINVAL ;break ; } -ipgre_tunnel_unlink (t); +ipgre_tunnel_unlink (ign, t); t->parms.iph.saddr = p.iph.saddr; t->parms.iph.daddr = p.iph.daddr; t->parms.i_key = p.i_key; t->parms.o_key = p.o_key;memcpy (dev->dev_addr, &p.iph.saddr,4 );memcpy (dev->broadcast, &p.iph.daddr,4 ); -ipgre_tunnel_link (t); +ipgre_tunnel_link (ign, t);netdev_state_change (dev); } }
@@ -1063,7 +1076,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)if (copy_from_user (&p, ifr->ifr_ifru.ifru_data,sizeof (p))) goto done; err = -ENOENT ; -if ((t =ipgre_tunnel_locate (&p,0 )) ==NULL ) +if ((t =ipgre_tunnel_locate (net, &p,0 )) ==NULL ) goto done; err = -EPERM ;if (t ==netdev_priv (ipgre_fb_tunnel_dev))
Signature · 1 line
1.5.3.4
PATCH 3/8 : Use proper net in hash-lookup functions.
In reply to Pavel EmelyanovThis is the part#2 of the patch #2 - get the proper net for these functions. This change in a separate patch in order not to get lost in a large previous patch.
--- net/ipv4/ip_gre.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
net/ipv4/ip_gre.c +2 -2
@@ -377,7 +377,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info) }read_lock (&ipgre_lock); - t =ipgre_tunnel_lookup (&init_net, iph->daddr, iph->saddr, + t =ipgre_tunnel_lookup (dev_net (skb->dev), iph->daddr, iph->saddr, (flags&GRE_KEY ) ? *(((__be32 *)p) + (grehlen>>2 ) -1 ) :0 ); if (t == NULL || t->parms.iph.daddr == 0 ||
@@ -612,7 +612,7 @@ static int ipgre_rcv(struct sk_buff *skb) }read_lock (&ipgre_lock); -if ((tunnel =ipgre_tunnel_lookup (&init_net, +if ((tunnel =ipgre_tunnel_lookup (dev_net (skb->dev), iph->saddr, iph->daddr, key)) !=NULL ) {secpath_reset (skb);
Signature · 1 line
1.5.3.4
PATCH 4/8 : Make the fallback tunnel device per-net.
In reply to Pavel EmelyanovEverything is prepared for this change now. Create on in init callback, use it over the code and destroy on net exit.
--- net/ipv4/ip_gre.c | 63 +++++++++++++++++++++++++++-------------------------- 1 files changed, 32 insertions(+), 31 deletions(-)
net/ipv4/ip_gre.c +32 -31
@@ -126,10 +126,9 @@ static int ipgre_fb_tunnel_init(struct net_device *dev);static int ipgre_net_id;struct ipgre_net { +struct net_device *fb_tunnel_dev; }; -static struct net_device *ipgre_fb_tunnel_dev; -/* Tunnel hash table */ /*
@@ -168,6 +167,7 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net *net,unsigned h0 =HASH (remote);unsigned h1 =HASH (key);struct ip_tunnel *t; +struct ipgre_net *ign =net_generic (net, ipgre_net_id);for (t = tunnels_r_l[h0^h1]; t; t = t->next) {if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) {
@@ -194,8 +194,8 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net *net,return t; } -if (ipgre_fb_tunnel_dev->flags&IFF_UP ) -return netdev_priv (ipgre_fb_tunnel_dev); +if (ign->fb_tunnel_dev->flags&IFF_UP ) +return netdev_priv (ign->fb_tunnel_dev);return NULL ; }
@@ -977,7 +977,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)switch (cmd) {case SIOCGETTUNNEL : t =NULL ; -if (dev == ipgre_fb_tunnel_dev) { +if (dev == ign->fb_tunnel_dev) {if (copy_from_user (&p, ifr->ifr_ifru.ifru_data,sizeof (p))) { err = -EFAULT ;break ;
@@ -1016,7 +1016,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) t =ipgre_tunnel_locate (net, &p, cmd ==SIOCADDTUNNEL ); -if (dev != ipgre_fb_tunnel_dev && cmd ==SIOCCHGTUNNEL ) { +if (dev != ign->fb_tunnel_dev && cmd ==SIOCCHGTUNNEL ) {if (t !=NULL ) {if (t->dev != dev) { err = -EEXIST ;
@@ -1071,7 +1071,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)if (!capable (CAP_NET_ADMIN )) goto done; -if (dev == ipgre_fb_tunnel_dev) { +if (dev == ign->fb_tunnel_dev) { err = -EFAULT ;if (copy_from_user (&p, ifr->ifr_ifru.ifru_data,sizeof (p))) goto done;
@@ -1079,7 +1079,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)if ((t =ipgre_tunnel_locate (net, &p,0 )) ==NULL ) goto done; err = -EPERM ; -if (t ==netdev_priv (ipgre_fb_tunnel_dev)) +if (t ==netdev_priv (ign->fb_tunnel_dev)) goto done; dev = t->dev; }
@@ -1270,7 +1270,7 @@ static int ipgre_tunnel_init(struct net_device *dev)return 0 ; } -static int __init ipgre_fb_tunnel_init (struct net_device *dev) +static int ipgre_fb_tunnel_init (struct net_device *dev) {struct ip_tunnel *tunnel =netdev_priv (dev);struct iphdr *iph = &tunnel->parms.iph;
@@ -1308,8 +1308,25 @@ static int ipgre_init_net(struct net *net)if (err <0 ) goto err_assign; + ign->fb_tunnel_dev =alloc_netdev (sizeof (struct ip_tunnel ),"gre0" , + ipgre_tunnel_setup); +if (!ign->fb_tunnel_dev) { + err = -ENOMEM ; + goto err_alloc_dev; + } + + ign->fb_tunnel_dev->init = ipgre_fb_tunnel_init; +dev_net_set (ign->fb_tunnel_dev, net); + +if ((err =register_netdev (ign->fb_tunnel_dev))) + goto err_reg_dev; +return 0 ; +err_reg_dev: +free_netdev (ign->fb_tunnel_dev); +err_alloc_dev: +/* nothing */ err_assign:kfree (ign); err_alloc:
@@ -1321,6 +1338,10 @@ static void ipgre_exit_net(struct net *net)struct ipgre_net *ign; ign =net_generic (net, ipgre_net_id); +rtnl_lock (); +if (net != &init_net) +unregister_netdevice (ign->fb_tunnel_dev); +rtnl_unlock ();kfree (ign); }
@@ -1344,31 +1365,11 @@ static int __init ipgre_init(void)return -EAGAIN ; } - ipgre_fb_tunnel_dev =alloc_netdev (sizeof (struct ip_tunnel ),"gre0" , - ipgre_tunnel_setup); -if (!ipgre_fb_tunnel_dev) { - err = -ENOMEM ; - goto err1; - } - - ipgre_fb_tunnel_dev->init = ipgre_fb_tunnel_init; - -if ((err =register_netdev (ipgre_fb_tunnel_dev))) - goto err2; - err =register_pernet_gen_device (&ipgre_net_id, &ipgre_net_ops);if (err <0 ) - goto err3; -out: +inet_del_protocol (&ipgre_protocol,IPPROTO_GRE ); +return err; -err2: -free_netdev (ipgre_fb_tunnel_dev); -err1: -inet_del_protocol (&ipgre_protocol,IPPROTO_GRE ); - goto out; -err3: -unregister_netdevice (ipgre_fb_tunnel_dev); - goto err1; } static void __exit ipgre_destroy_tunnels(void)
Signature · 1 line
1.5.3.4
PATCH 5/8 : Make tunnels hashes per-net.
In reply to Pavel EmelyanovVery similar to what was done for the IPIP code.
--- net/ipv4/ip_gre.c | 65 +++++++++++++++++++++++++--------------------------- 1 files changed, 31 insertions(+), 34 deletions(-)
net/ipv4/ip_gre.c +31 -34
@@ -124,8 +124,12 @@ static void ipgre_tunnel_setup(struct net_device *dev);static int ipgre_fb_tunnel_init (struct net_device *dev); +#define HASH_SIZE 16 +static int ipgre_net_id;struct ipgre_net { +struct ip_tunnel *tunnels[4 ][HASH_SIZE ]; +struct net_device *fb_tunnel_dev; };
@@ -147,15 +151,12 @@ struct ipgre_net {will match fallback tunnel. */ -#define HASH_SIZE 16#define HASH (addr) (((__force u32)addr^((__force u32)addr>>4))&0xF) -static struct ip_tunnel *tunnels[4 ][HASH_SIZE ]; - -#define tunnels_r_l (tunnels[3]) -#define tunnels_r (tunnels[2]) -#define tunnels_l (tunnels[1]) -#define tunnels_wc (tunnels[0]) +#define tunnels_r_l tunnels[3] +#define tunnels_r tunnels[2] +#define tunnels_l tunnels[1] +#define tunnels_wc tunnels[0]static DEFINE_RWLOCK (ipgre_lock);
@@ -169,19 +170,19 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net *net,struct ip_tunnel *t;struct ipgre_net *ign =net_generic (net, ipgre_net_id); -for (t = tunnels_r_l[h0^h1]; t; t = t->next) { +for (t = ign->tunnels_r_l[h0^h1]; t; t = t->next) {if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) {if (t->parms.i_key == key && (t->dev->flags&IFF_UP ))return t; } } -for (t = tunnels_r[h0^h1]; t; t = t->next) { +for (t = ign->tunnels_r[h0^h1]; t; t = t->next) {if (remote == t->parms.iph.daddr) {if (t->parms.i_key == key && (t->dev->flags&IFF_UP ))return t; } } -for (t = tunnels_l[h1]; t; t = t->next) { +for (t = ign->tunnels_l[h1]; t; t = t->next) {if (local == t->parms.iph.saddr || (local == t->parms.iph.daddr &&ipv4_is_multicast (local))) {
@@ -189,7 +190,7 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net *net,return t; } } -for (t = tunnels_wc[h1]; t; t = t->next) { +for (t = ign->tunnels_wc[h1]; t; t = t->next) {if (t->parms.i_key == key && (t->dev->flags&IFF_UP ))return t; }
@@ -215,7 +216,7 @@ static struct ip_tunnel **__ipgre_bucket(struct ipgre_net *ign, h ^=HASH (remote); } -return &tunnels[prio][h]; +return &ign->tunnels[prio][h]; } static inline struct ip_tunnel **ipgre_bucket(struct ipgre_net *ign,
@@ -1274,6 +1275,7 @@ static int ipgre_fb_tunnel_init(struct net_device *dev) {struct ip_tunnel *tunnel =netdev_priv (dev);struct iphdr *iph = &tunnel->parms.iph; +struct ipgre_net *ign =net_generic (dev_net (dev), ipgre_net_id); tunnel->dev = dev;strcpy (tunnel->parms.name, dev->name);
@@ -1284,7 +1286,7 @@ static int ipgre_fb_tunnel_init(struct net_device *dev) tunnel->hlen =sizeof (struct iphdr ) +4 ;dev_hold (dev); - tunnels_wc[0 ] = tunnel; + ign->tunnels_wc[0 ] = tunnel;return 0 ; }
@@ -1294,13 +1296,27 @@ static struct net_protocol ipgre_protocol = { .err_handler = ipgre_err, }; +static void ipgre_destroy_tunnels (struct ipgre_net *ign) +{ +int prio; + +for (prio =0 ; prio <4 ; prio++) { +int h; +for (h =0 ; h <HASH_SIZE ; h++) { +struct ip_tunnel *t; +while ((t = ign->tunnels[prio][h]) !=NULL ) +unregister_netdevice (t->dev); + } + } +} +static int ipgre_init_net (struct net *net) {int err;struct ipgre_net *ign; err = -ENOMEM ; - ign =kmalloc (sizeof (struct ipgre_net ),GFP_KERNEL ); + ign =kzalloc (sizeof (struct ipgre_net ),GFP_KERNEL );if (ign ==NULL ) goto err_alloc;
@@ -1339,8 +1355,7 @@ static void ipgre_exit_net(struct net *net) ign =net_generic (net, ipgre_net_id);rtnl_lock (); -if (net != &init_net) -unregister_netdevice (ign->fb_tunnel_dev); +ipgre_destroy_tunnels (ign);rtnl_unlock ();kfree (ign); }
@@ -1372,29 +1387,11 @@ static int __init ipgre_init(void)return err; } -static void __exit ipgre_destroy_tunnels(void) -{ -int prio; - -for (prio =0 ; prio <4 ; prio++) { -int h; -for (h =0 ; h <HASH_SIZE ; h++) { -struct ip_tunnel *t; -while ((t = tunnels[prio][h]) !=NULL ) -unregister_netdevice (t->dev); - } - } -} - static void __exit ipgre_fini(void) {if (inet_del_protocol (&ipgre_protocol,IPPROTO_GRE ) <0 )printk (KERN_INFO "ipgre close: can't remove protocol\n" ); -rtnl_lock (); -ipgre_destroy_tunnels (); -rtnl_unlock (); -unregister_pernet_gen_device (ipgre_net_id, &ipgre_net_ops); }
Signature · 1 line
1.5.3.4
PATCH 6/8 : Use proper net in routing calls.
In reply to Pavel EmelyanovAs for the IPIP tunnel, there are some ip_route_output_key() calls in there that require a proper net so give one to them.
And a proper net for the __get_dev_by_index hanging around.
--- net/ipv4/ip_gre.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-)
net/ipv4/ip_gre.c +6 -6
@@ -493,7 +493,7 @@ out: fl.fl4_dst = eiph->saddr; fl.fl4_tos =RT_TOS (eiph->tos); fl.proto =IPPROTO_GRE ; -if (ip_route_output_key (&init_net, &rt, &fl)) { +if (ip_route_output_key (dev_net (skb->dev), &rt, &fl)) {kfree_skb (skb2);return ; }
@@ -506,7 +506,7 @@ out: fl.fl4_dst = eiph->daddr; fl.fl4_src = eiph->saddr; fl.fl4_tos = eiph->tos; -if (ip_route_output_key (&init_net, &rt, &fl) || +if (ip_route_output_key (dev_net (skb->dev), &rt, &fl) || rt->u.dst.dev->type !=ARPHRD_IPGRE ) {ip_rt_put (rt);kfree_skb (skb2);
@@ -762,7 +762,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) .saddr = tiph->saddr, .tos = RT_TOS(tos) } }, .proto = IPPROTO_GRE }; -if (ip_route_output_key (&init_net, &rt, &fl)) { +if (ip_route_output_key (dev_net (dev), &rt, &fl)) { tunnel->stat.tx_carrier_errors++; goto tx_error; }
@@ -935,7 +935,7 @@ static void ipgre_tunnel_bind_dev(struct net_device *dev) .tos = RT_TOS(iph->tos) } }, .proto = IPPROTO_GRE };struct rtable *rt; -if (!ip_route_output_key (&init_net, &rt, &fl)) { +if (!ip_route_output_key (dev_net (dev), &rt, &fl)) { tdev = rt->u.dst.dev;ip_rt_put (rt); }
@@ -943,7 +943,7 @@ static void ipgre_tunnel_bind_dev(struct net_device *dev) }if (!tdev && tunnel->parms.link) - tdev =__dev_get_by_index (&init_net, tunnel->parms.link); + tdev =__dev_get_by_index (dev_net (dev), tunnel->parms.link);if (tdev) { hlen = tdev->hard_header_len;
@@ -1193,7 +1193,7 @@ static int ipgre_open(struct net_device *dev) .tos = RT_TOS(t->parms.iph.tos) } }, .proto = IPPROTO_GRE };struct rtable *rt; -if (ip_route_output_key (&init_net, &rt, &fl)) +if (ip_route_output_key (dev_net (dev), &rt, &fl))return -EADDRNOTAVAIL ; dev = rt->u.dst.dev;ip_rt_put (rt);
Signature · 1 line
1.5.3.4
PATCH 7/8 : Allow to create IPGRE tunnels in net namespaces.
In reply to Pavel EmelyanovI.e. set the proper net and mark as NETNS_LOCAL.
--- net/ipv4/ip_gre.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
net/ipv4/ip_gre.c +3 -0
@@ -278,6 +278,8 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct net *net,if (!dev)return NULL ; +dev_net_set (dev, net); +if (strchr (name,'%' )) {if (dev_alloc_name (dev, name) <0 ) goto failed_free;
@@ -1236,6 +1238,7 @@ static void ipgre_tunnel_setup(struct net_device *dev) dev->flags =IFF_NOARP ; dev->iflink =0 ; dev->addr_len =4 ; + dev->features |=NETIF_F_NETNS_LOCAL ; }static int ipgre_tunnel_init (struct net_device *dev)
Signature · 1 line
1.5.3.4
PATCH 8/8 : Allow for IPPROTO_GRE protocol in namespaces.
In reply to Pavel EmelyanovThis one was also disabled by default for sanity.
--- net/ipv4/ip_gre.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
net/ipv4/ip_gre.c +1 -0
@@ -1297,6 +1297,7 @@ static int ipgre_fb_tunnel_init(struct net_device *dev)static struct net_protocol ipgre_protocol = { .handler = ipgre_rcv, .err_handler = ipgre_err, + .netns_ok =1 , };static void ipgre_destroy_tunnels (struct ipgre_net *ign)
Signature · 1 line
1.5.3.4
David Miller
maintainerRe: [PATCH net-2.6.26 8/8][GRE]: Allow for IPPROTO_GRE protocol in namespaces.
From: Pavel Emelyanov <[email protected]>
Date: Tue, 15 Apr 2008 17:03:04 +0400
Quoted 3 lines
This one was also disabled by default for sanity.
Signed-off-by Pavel Emelyanov <[email protected]>
Applied and pushed to net-2.6.26
Keep up the great work Pavel.