OpenVZ Forum


Home » Mailing lists » Devel » Dynamically allocate the loopback device
Re: Dynamically allocate the loopback device [message #19765 is a reply to message #19762] Fri, 24 August 2007 13:06 Go to previous message
dev is currently offline  dev
Messages: 1693
Registered: September 2005
Location: Moscow
Senior Member

Acked-By: Kirill Korotaev <dev@sw.ru>

dlezcano@fr.ibm.com wrote:
> From: Daniel Lezcano <dlezcano@fr.ibm.com>
> 
> Doing this makes loopback.c a better example of how to do a
> simple network device, and it removes the special case
> single static allocation of a struct net_device, hopefully
> making maintenance easier.
> 
> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
> Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
> ---
>  drivers/net/loopback.c           |   63 +++++++++++++++++++++++---------------
>  include/linux/netdevice.h        |    2 +-
>  net/core/dst.c                   |    8 ++--
>  net/decnet/dn_dev.c              |    4 +-
>  net/decnet/dn_route.c            |   14 ++++----
>  net/ipv4/devinet.c               |    6 ++--
>  net/ipv4/ipconfig.c              |    6 ++--
>  net/ipv4/ipvs/ip_vs_core.c       |    2 +-
>  net/ipv4/route.c                 |   18 +++++-----
>  net/ipv4/xfrm4_policy.c          |    2 +-
>  net/ipv6/addrconf.c              |   15 +++++---
>  net/ipv6/ip6_input.c             |    2 +-
>  net/ipv6/netfilter/ip6t_REJECT.c |    2 +-
>  net/ipv6/route.c                 |   15 +++-----
>  net/ipv6/xfrm6_policy.c          |    2 +-
>  net/xfrm/xfrm_policy.c           |    4 +-
>  16 files changed, 89 insertions(+), 76 deletions(-)
> 
> diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
> index 5106c23..3642aff 100644
> --- a/drivers/net/loopback.c
> +++ b/drivers/net/loopback.c
> @@ -199,44 +199,57 @@ static const struct ethtool_ops loopback_ethtool_ops = {
>  	.get_rx_csum		= always_on,
>  };
>  
> -/*
> - * The loopback device is special. There is only one instance and
> - * it is statically allocated. Don't do this for other devices.
> - */
> -struct net_device loopback_dev = {
> -	.name	 		= "lo",
> -	.get_stats		= &get_stats,
> -	.mtu			= (16 * 1024) + 20 + 20 + 12,
> -	.hard_start_xmit	= loopback_xmit,
> -	.hard_header		= eth_header,
> -	.hard_header_cache	= eth_header_cache,
> -	.header_cache_update	= eth_header_cache_update,
> -	.hard_header_len	= ETH_HLEN,	/* 14	*/
> -	.addr_len		= ETH_ALEN,	/* 6	*/
> -	.tx_queue_len		= 0,
> -	.type			= ARPHRD_LOOPBACK,	/* 0x0001*/
> -	.rebuild_header		= eth_rebuild_header,
> -	.flags			= IFF_LOOPBACK,
> -	.features 		= NETIF_F_SG | NETIF_F_FRAGLIST
> +static void loopback_setup(struct net_device *dev)
> +{
> +	dev->get_stats		= &get_stats;
> +	dev->mtu		= (16 * 1024) + 20 + 20 + 12;
> +	dev->hard_start_xmit	= loopback_xmit;
> +	dev->hard_header	= eth_header;
> +	dev->hard_header_cache	= eth_header_cache;
> +	dev->header_cache_update = eth_header_cache_update;
> +	dev->hard_header_len	= ETH_HLEN;	/* 14	*/
> +	dev->addr_len		= ETH_ALEN;	/* 6	*/
> +	dev->tx_queue_len	= 0;
> +	dev->type		= ARPHRD_LOOPBACK;	/* 0x0001*/
> +	dev->rebuild_header	= eth_rebuild_header;
> +	dev->flags		= IFF_LOOPBACK;
> +	dev->features 		= NETIF_F_SG | NETIF_F_FRAGLIST
>  #ifdef LOOPBACK_TSO
>  				  | NETIF_F_TSO
>  #endif
>  				  | NETIF_F_NO_CSUM | NETIF_F_HIGHDMA
> -				  | NETIF_F_LLTX,
> -	.ethtool_ops		= &loopback_ethtool_ops,
> -};
> +				  | NETIF_F_LLTX;
> +	dev->ethtool_ops	= &loopback_ethtool_ops;
> +}
>  
>  /* Setup and register the loopback device. */
>  static int __init loopback_init(void)
>  {
> -	int err = register_netdev(&loopback_dev);
> +	struct net_device *dev;
> +	int err;
> +	
> +	err = -ENOMEM;
> +	dev = alloc_netdev(0, "lo", loopback_setup);
> +	if (!dev)
> +		goto out;
> +
> +	err = register_netdev(dev);
> +	if (err)
> +		goto out_free_netdev;
>  
> +	err = 0;
> +	loopback_dev = dev;
> +
> +out:
>  	if (err)
>  		panic("loopback: Failed to register netdevice: %d\n", err);
> -
>  	return err;
> +out_free_netdev:
> +	free_netdev(dev);
> +	goto out;
>  };
>  
> -module_init(loopback_init);
> +fs_initcall(loopback_init);
>  
> +struct net_device *loopback_dev;
>  EXPORT_SYMBOL(loopback_dev);
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index 8d12f02..7cd0641 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -680,7 +680,7 @@ struct packet_type {
>  #include <linux/interrupt.h>
>  #include <linux/notifier.h>
>  
> -extern struct net_device		loopback_dev;		/* The loopback */
> +extern struct net_device		*loopback_dev;		/* The loopback */
>  extern struct list_head			dev_base_head;		/* All devices */
>  extern rwlock_t				dev_base_lock;		/* Device list lock */
>  
> diff --git a/net/core/dst.c b/net/core/dst.c
> index c6a0587..ad8549e 100644
> --- a/net/core/dst.c
> +++ b/net/core/dst.c
> @@ -236,13 +236,13 @@ static inline void dst_ifdown(struct dst_entry *dst, struct net_device *dev,
>  	if (!unregister) {
>  		dst->input = dst->output = dst_discard;
>  	} else {
> -		dst->dev = &loopback_dev;
> -		dev_hold(&loopback_dev);
> +		dst->dev = loopback_dev;
> +		dev_hold(dst->dev);
>  		dev_put(dev);
>  		if (dst->neighbour && dst->neighbour->dev == dev) {
> -			dst->neighbour->dev = &loopback_dev;
> +			dst->neighbour->dev = loopback_dev;
>  			dev_put(dev);
> -			dev_hold(&loopback_dev);
> +			dev_hold(dst->neighbour->dev);
>  		}
>  	}
>  }
> diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
> index fa6604f..9fea83e 100644
> --- a/net/decnet/dn_dev.c
> +++ b/net/decnet/dn_dev.c
> @@ -868,10 +868,10 @@ last_chance:
>  		rv = dn_dev_get_first(dev, addr);
>  		read_unlock(&dev_base_lock);
>  		dev_put(dev);
> -		if (rv == 0 || dev == &loopback_dev)
> +		if (rv == 0 || dev == loopback_dev)
>  			return rv;
>  	}
> -	dev = &loopback_dev;
> +	dev = loopback_dev;
>  	dev_hold(dev);
>  	goto last_chance;
>  }
> diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
> index a4a6209..8c04ebc 100644
> --- a/net/decnet/dn_route.c
> +++ b/net/decnet/dn_route.c
> @@ -883,7 +883,7 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old
>  					.scope = RT_SCOPE_UNIVERSE,
>  				     } },
>  			    .mark = oldflp->mark,
> -			    .iif = loopback_dev.ifindex,
> +			    .iif = loopback_dev->ifindex,
>  			    .oif = oldflp->oif };
>  	struct dn_route *rt = NULL;
>  	struct net_device *dev_out = NULL, *dev;
> @@ -900,7 +900,7 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old
>  		       "dn_route_output_slow: dst=%04x src=%04x mark=%d"
>  		       " iif=%d oif=%d\n", dn_ntohs(oldflp->fld_dst),
>  		       dn_ntohs(oldflp->fld_src),
> -		       oldflp->mark, loopback_dev.ifindex, oldflp->oif);
> +		       oldflp->mark, loopback_dev->ifindex, oldflp->oif);
>  
>  	/* If we have an output interface, verify its a DECnet device */
>  	if (oldflp->oif) {
> @@ -953,7 +953,7 @@ source_ok:
>  		err = -EADDRNOTAVAIL;
>  		if (dev_out)
>  			dev_put(dev_out);
> -		dev_out = &loopback_dev;
> +		dev_out = loopback_dev;
>  		dev_hold(dev_out);
>  		if (!fl.fld_dst) {
>  			fl.fld_dst =
> @@ -962,7 +962,7 @@ source_ok:
>  			if (!fl.fld_dst)
>  				goto out;
>  		}
> -		fl.oif = loopback_dev.ifindex;
> +		fl.oif = loopback_dev->ifindex;
>  		res.type = RTN_LOCAL;
>  		goto make_route;
>  	}
> @@ -1008,7 +1008,7 @@ source_ok:
>  					if (dev_out)
>  						dev_put(dev_out);
>  					if (dn_dev_islocal(neigh->dev, fl.fld_dst)) {
> -						dev_out = &loopback_dev;
> +						dev_out = loopback_dev;
>  						res.type = RTN_LOCAL;
>  					} else {
>  						dev_out = neigh->dev;
> @@ -1029,7 +1029,7 @@ source_ok:
>  		/* Possible improvement - check all devices for local addr */
>  		if (dn_dev_islocal(dev_out, fl.fld_dst)) {
>  			dev_put(dev_out);
> -			dev_out = &loopback_dev;
> +			dev_out = loopback_dev;
>  			dev_hold(dev_out);
>  			res.type = RTN_LOCAL;
>  			goto select_source;
> @@ -1065,7 +1065,7 @@ select_source:
>  			fl.fld_src = fl.fld_dst;
>  		if (dev_out)
>  			dev_put(dev_out);
> -		dev_out = &loopback_dev;
> +		dev_out = loopback_dev;
>  		dev_hold(dev_out);
>  		fl.oif = dev_out->ifindex;
>  		if (res.fi)
> diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
> index 5b77bda..808f529 100644
> --- a/net/ipv4/devinet.c
> +++ b/net/ipv4/devinet.c
> @@ -203,7 +203,7 @@ static void inetdev_destroy(struct in_device *in_dev)
>  	ASSERT_RTNL();
>  
>  	dev = in_dev->dev;
> -	if (dev == &loopback_dev)
> +	if (dev == loopback_dev)
>  		return;
>  
>  	in_dev->dead = 1;
> @@ -1058,7 +1058,7 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
>  			in_dev = inetdev_init(dev);
>  			if (!in_dev)
>  				return notifier_from_errno(-ENOMEM);
> -			if (dev == &loopback_dev) {
> +			if (dev == loopback_dev) {
>  				IN_DEV_CONF_SET(in_dev, NOXFRM, 1);
>  				IN_DEV_CONF_SET(in_dev, NOPOLICY, 1);
>  			}
> @@ -1074,7 +1074,7 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
>  	case NETDEV_UP:
>  		if (dev->mtu < 68)
>  			break;
> -		if (dev == &loopback_dev) {
> +		if (dev == loopback_dev) {
>  			struct in_ifaddr *ifa;
>  			if ((ifa = inet_alloc_ifa()) != NULL) {
>  				ifa->ifa_local
...

 
Read Message
Read Message
Read Message
Previous Topic: [RFC][PATCH] Make (hr)timers use struct pid instead of pid_t
Next Topic: [PATCH 1/1] Dynamically allocate the loopback device
Goto Forum:
  


Current Time: Wed Oct 01 03:05:59 GMT 2025

Total time taken to generate the page: 0.09212 seconds