From: kernelcoder2 on
Hi,

I need to port some code from linux kernel 2.6.18 to kernel 2.6.29.
One of the file where changes are involved is <net/ipv6/ip6_tunnel.c>,
where a new structure struct ip6_tnl_net was added into kernel2.6.29
that didn't exist in 2.6.18 as follows:

struct ip6_tnl_net {
/* the IPv6 tunnel fallback device */
struct net_device *fb_tnl_dev;
/* lists for storing tunnels in use */
struct ip6_tnl *tnls_r_l[HASH_SIZE];
struct ip6_tnl *tnls_wc[1];
struct ip6_tnl **tnls[2];
};

All those fields in struct ip6_tnl_net were in global namespace in
2.6.18, but wrapped in this struct for some reason (what benefit does
this gain?)

2.6.18 code in function ip6_tunnel_init() works fine as follows. After
being ported to kernel 2.6.29 as shown below, after kernel/module
build, install, reboot hangs. I inserted some printk message as shown,
only 111111 to 44444 were displayed, which indicates that
"register_netdev(ip6n->fb_tnl_dev)" failed.

Any inputs? Thanks.


====================Kernel 2.6.18 code, works fine====================
static int __init ip6_tunnel_init(void)
{
int err;
struct ip6_tnl *tun0;

if (xfrm6_tunnel_register(&ip6ip6_handler)) {
printk(KERN_ERR "ip6ip6 init: can't register tunnel\n");
return -EAGAIN;
}
ip6ip6_fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0",
ip6ip6_tnl_dev_setup);

if (!ip6ip6_fb_tnl_dev) {
err = -ENOMEM;
goto fail;
}
ip6ip6_fb_tnl_dev->init = ip6ip6_fb_tnl_dev_init;

if ((err = register_netdev(ip6ip6_fb_tnl_dev))) {
free_netdev(ip6ip6_fb_tnl_dev);
goto fail;
}
tun0 = ip6ip6_fb_tnl_dev->priv;
tun0->parms.flags |= (IP6_TNL_F_CAP_XMIT | IP6_TNL_F_CAP_RCV);
return 0;
fail:
xfrm6_tunnel_deregister(&ip6ip6_handler);
return err;
}


=================modified Kernel 2.6.29 code, buggy==============
static int __init ip6_tunnel_init(void)
{
int err;
struct ip6_tnl_net *ip6n; /*added due to kernel struct change*/
struct ip6_tnl *tun0; /*added 06082010*/


if (xfrm6_tunnel_register(&ip4ip6_handler, AF_INET)) {
printk(KERN_ERR "ip6_tunnel init: can't register ip4ip6\n");
err = -EAGAIN;
goto out;
}

if (xfrm6_tunnel_register(&ip6ip6_handler, AF_INET6)) {
printk(KERN_ERR "ip6_tunnel init: can't register ip6ip6\n");
err = -EAGAIN;
goto unreg_ip4ip6;
}

err = register_pernet_gen_device(&ip6_tnl_net_id, &ip6_tnl_net_ops);
if (err < 0)
goto err_pernet;
printk(KERN_ERR "=========1111111111111111111========\n");

//alloc_netdev() and init the device, added
err = -ENOMEM;
ip6n = kzalloc(sizeof(struct ip6_tnl_net), GFP_KERNEL);
if (ip6n == NULL)
goto out;

ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0",
ip6_tnl_dev_setup);
printk(KERN_ERR "=======222222222222222222=========\n");
if (!ip6n->fb_tnl_dev) {
err = -ENOMEM;
goto out;
}
printk(KERN_ERR "=========3333333333333333333========\n");


ip6n->fb_tnl_dev->init = ip6_fb_tnl_dev_init2;
//ip6_fb_tnl_dev_init(ip6n->fb_tnl_dev);
printk(KERN_ERR "=========4444444444444444444========\n");

err = register_netdev(ip6n->fb_tnl_dev);
if (err<0) {
free_netdev(ip6n->fb_tnl_dev);
goto err_pernet;
}
printk(KERN_ERR "=========555555555555555555========\n");

// tun0 = ip6ip6_fb_tnl_dev->priv; /*added per patch*/
tun0 = netdev_priv(ip6n->fb_tnl_dev); /*modified */
printk(KERN_ERR "=========666666666666666666========\n");
tun0->parms.flags |= (IP6_TNL_F_CAP_XMIT | IP6_TNL_F_CAP_RCV);
printk(KERN_ERR "=========777777777777777777========\n");
return 0;

err_pernet:
xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6);
printk(KERN_ERR "========err pernet=========\n");
unreg_ip4ip6:
xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET);
printk(KERN_ERR "========err unreg_ip4ip6=========\n");
out:
printk(KERN_ERR "========err out==================\n");
return err;
}