Skip to contentSkip to conversation

network device ops phase 1

RFC In review Stephen Hemminger 3 participants 4 messages Nov 7, 2008 – Nov 14, 2008

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

RFC 1/1 network device ops phase 1

This early work on a series of patches to separate the management portions of the network device (immutable function pointers) from the data structure part of the network device.

This patch involves some hackery to maintain compatablity between the new and old model, so all 300+ drivers don't have to be changed at once. There are two copies of the same function pointers during the transistional step. As the transistion is completed the nag message can be changed to an WARN_ON, and the compatiablity code can be made configurable.

A couple function pointers aren't moved:
* destructor can't be in net_device_ops because it may need to be referenced after the module is unloaded.
* hard_start_xmit is in the fast path for transmit.

---
 include/linux/if.h        |    3 +
 include/linux/netdevice.h |  213 +++++++++++++++++++++++++++++++++------------
 net/Kconfig               |    3 +
 net/core/dev.c            |  109 +++++++++++++++++-------
 net/core/neighbour.c      |    3 +-
 net/core/netpoll.c        |    7 +-
 net/sched/sch_generic.c   |    4 +-
 7 files changed, 250 insertions(+), 92 deletions(-)
include/linux/if.h +3 -0
index 2a6e296..4286deb 100644
@@ -67,6 +67,8 @@
 #define IFF_ISATAP	0x80		/* ISATAP interface (RFC4214)	*/
 #define IFF_MASTER_ARPMON 0x100		/* bonding master, ARP mon in use */
 
+#define IFF_NETDEV_OPS  0x8000		/* network devices ops allocated */
+
 #define IF_GET_IFACE	0x0001		/* for querying only */
 #define IF_GET_PROTO	0x0002
 
@@ -94,6 +96,7 @@
 #define IF_PROTO_FR_ETH_PVC 0x200B
 #define IF_PROTO_RAW    0x200C          /* RAW Socket                   */
 
+
 /* RFC 2863 operational status */
 enum {
 	IF_OPER_UNKNOWN,
include/linux/netdevice.h +157 -56

278 lines not on this page · raw message

net/Kconfig +3 -0
index 8c3d97c..4e2e40b 100644
@@ -32,6 +32,9 @@ config NET_NS
 	  Allow user space to create what appear to be multiple instances
 	  of the network stack.
 
+config COMPAT_NET_DEV_OPS
+       def_bool y
+
 source "net/packet/Kconfig"
 source "net/unix/Kconfig"
 source "net/xfrm/Kconfig"
net/core/dev.c +79 -30

247 lines not on this page · raw message

net/core/neighbour.c +2 -1
index d9bbe01..96c84a1 100644
@@ -1330,6 +1330,7 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
 {
 	struct neigh_parms *p, *ref;
 	struct net *net;
+	const struct net_device_ops *ops = dev->netdev_ops;
 
 	net = dev_net(dev);
 	ref = lookup_neigh_params(tbl, net, 0);
@@ -1343,7 +1344,7 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
 		p->reachable_time =
 				neigh_rand_reach_time(p->base_reachable_time);
 
-		if (dev->neigh_setup && dev->neigh_setup(dev, p)) {
+		if (ops->neigh_setup && ops->neigh_setup(dev, p)) {
 			kfree(p);
 			return NULL;
 		}
net/core/netpoll.c +4 -3
index 34f5d07..e0e43b9 100644
@@ -172,12 +172,13 @@ static void service_arp_queue(struct netpoll_info *npi)
 void netpoll_poll(struct netpoll *np)
 {
 	struct net_device *dev = np->dev;
+	const struct net_device_ops *ops = dev->netdev_ops;
 
-	if (!dev || !netif_running(dev) || !dev->poll_controller)
+	if (!dev || !netif_running(dev) || !ops->poll_controller)
 		return;
 
 	/* Process pending work on NIC */
-	dev->poll_controller(dev);
+	ops->poll_controller(dev);
 
 	poll_napi(dev);
 
@@ -694,7 +695,7 @@ int netpoll_setup(struct netpoll *np)
 		atomic_inc(&npinfo->refcnt);
 	}
 
-	if (!ndev->poll_controller) {
+	if (!ndev->netdev_ops->poll_controller) {
 		printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n",
 		       np->name, np->dev_name);
 		err = -ENOTSUPP;
net/sched/sch_generic.c +2 -2
index 1192da2..b906d76 100644
@@ -224,7 +224,7 @@ static void dev_watchdog(unsigned long arg)
 				char drivername[64];
 				WARN_ONCE(1, KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit timed out\n",
 				       dev->name, netdev_drivername(dev, drivername, 64));
-				dev->tx_timeout(dev);
+				dev->netdev_ops->tx_timeout(dev);
 			}
 			if (!mod_timer(&dev->watchdog_timer,
 				       round_jiffies(jiffies +
@@ -239,7 +239,7 @@ static void dev_watchdog(unsigned long arg)
 
 void __netdev_watchdog_up(struct net_device *dev)
 {
-	if (dev->tx_timeout) {
+	if (dev->netdev_ops->tx_timeout) {
 		if (dev->watchdog_timeo <= 0)
 			dev->watchdog_timeo = 5*HZ;
 		if (!mod_timer(&dev->watchdog_timer,
Signature · 1 line
1.5.4.3
maintainer
#1 lore raw

From: Stephen Hemminger <[email protected]>
Date: Fri, 7 Nov 2008 15:50:23 -0800

Quoted 3 lines

This early work on a series of patches to separate the management portions of the network device (immutable function pointers) from the data structure part of the network device.

...

I think this is a good way to attack this kind of transition.

Fix the build errors, do some testing, and please resubmit:

net/core/dev.c: In function ‘register_netdevice’:
net/core/dev.c:4075: error: ‘struct net_device_ops’ has no member named ‘poll_controller’ net/core/dev.c:4075: error: ‘struct net_device’ has no member named ‘poll_controller’ make[2]: *** [net/core/dev.o] Error 1
make[1]: *** [net/core] Error 2
make: *** [net] Error 2
make: *** Waiting for unfinished jobs....

Thanks.

#2 lore raw
Quoted 20 lines · On Mon, 10 Nov 2008 17:02:11 -0800 (PST) David Miller <[email protected]>…

From: Stephen Hemminger <[email protected]>
Date: Fri, 7 Nov 2008 15:50:23 -0800

Quoted 3 lines

This early work on a series of patches to separate the management portions of the network device (immutable function pointers) from the data structure part of the network device.

...

I think this is a good way to attack this kind of transition.

Fix the build errors, do some testing, and please resubmit:

net/core/dev.c: In function ‘register_netdevice’:
net/core/dev.c:4075: error: ‘struct net_device_ops’ has no member named ‘poll_controller’ net/core/dev.c:4075: error: ‘struct net_device’ has no member named ‘poll_controller’ make[2]: *** [net/core/dev.o] Error 1
make[1]: *** [net/core] Error 2
make: *** [net] Error 2
make: *** Waiting for unfinished jobs....

Quoted 1 line

Thanks.

This is one case where I wish GCC had more C++ style anonymous structures so the following would work, and avoid the copying and allocation.

struct net_device_ops {
int (*init)(struct net_device *);
...
};

struct net_device {
...
#ifdef CONFIG_COMPAT_XXX
struct net_device_ops;
#endif
struct net_device_ops *ops;
};

void register_netdevice(struct net_device *dev)
{
...

#ifdef CONFIG_COMPAT_XXX
      if (ops == NULL) {
         printk("loser device %s", dev->name);
         dev->ops = (struct net_device_ops *) dev->init;
      }

#endif

}

#3 lore raw
In reply to Stephen Hemminger

include/linux/netdevice.h struct netdev_queue { · line 457

Quoted 4 lines · Stephen Hemminger
include/linux/netdevice.h +4 -0
+
+/*
+ * This structure defines the management hooks for network devices.
+ * The following hooks can bed defined and are optonal (can be null)

s/bed/be/, /optonal/optional/

Quoted 3 lines

+ * unless otherwise noted.
+ *

- k