* [rfc | patch 0/6] netpoll: add support for the bonding driver
@ 2005-07-01 23:05 Jeff Moyer
2005-07-01 23:06 ` Jeff Moyer
` (6 more replies)
0 siblings, 7 replies; 9+ messages in thread
From: Jeff Moyer @ 2005-07-01 23:05 UTC (permalink / raw)
To: mpm; +Cc: netdev, linux-kernel
Hi,
The following patch series provides netpoll support for the bonding driver.
The best way to describe the approach taken is to walk through how it
works. We'll use netconsole as our example.
Netconsole registers a console, and so release_console_sem will trigger the
write_msg implementation in netconsole.ko. This, in turn, calls
netpoll_send_udp. netpoll_send_udp will then call netpoll_send_skb, which
then calls into the network drivers hard_start_xmit routine. It is
important to note that netpoll_send_skb takes care to not call the
hard_start_xmit routine if netif_queue_stopped(dev) returns true. In this
case, it instead calls netpoll_poll, to hopefully free up some tx
descriptors. After this is done, and the queue is woken up, the
hard_start_xmit routine can and will be called.
For all network drivers up to this point, this was the end of the line.
Netpoll would no longer have to be concerned with the skb. It will be
sent off to the network by the driver. However, this is not the case with
the bonding driver.
In the case of the bonding driver, we have now called its hard_start_xmit
routine, which can be one of many, depending on the configured bonging_mode
(specified at module load time). For all of my testing, I have used
dynamic link aggregation (802.3ad). So, in this case, we will call
bond_3ad_xmit_xor. In all cases, the hard_start_xmit routine selects the
proper slave device over which to send the packet, and fills in the
skb->dev pointer to point at that device. Then, they all send the skb off
to bond_dev_queue_xmit.
bond_dev_queue_xmit will then send the skb off to the networking layer via
dev_queue_xmit. dev_queue_xmit is then responsible for calling the
underlying network device's hard_start_xmit routine. Note that
dev_queue_xmit cannot be called with interrupts disabled.
And so, we bring our discussion back to netpoll. In the case of netpoll,
we cannot have the bonding driver call into dev_queue_xmit. For
netconsole, we have disabled irqs before calling netpoll_send_skb (and we
may even be called from interrupt context, in the case of sysrq-X). This
is not the only problem with allowing the bonding driver to call
dev_queue_xmit. We also have to deal with the fact that the underlying
network device may not be ready to send. As in the case described above,
we may be short on tx descriptors. In such a case, we need to be able to
call the driver's poll_controller routine to clear them out. And so, we
have to modify bond_dev_queue_xmit to call *back* into the netpoll code.
The call chain will look something like this:
printk
release_console_sem
call_console_drivers
write_msg
netpoll_send_udp <----- skb->dev points to bond0
netpoll_send_skb
bond_3ad_xmit_xor
bond_dev_queue_xmit
netpoll_send_skb <------ skb->dev now points to real_dev
(may have to call dev->poll_controller, and perform a
napi poll here)
dev->hard_start_xmit
I wrote a test module to exercise the receive code path, as well. The
module registers a struct netpoll with an rx_hook. It then responds to
each packet it receives with a "PONG". For this case, our call path now
looks as follows:
net_rx
dev->poll
netif_receive_skb
netpoll_rx
__netpoll_rx
module_rx_routine
netpoll_send_udp
netpoll_send_skb <-- skb->dev points at bond0
bond_3ad_xmit_xor
bond_dev_queue_xmit
netpoll_send_skb <-- skb->dev points at real_dev
And here it gets tricky. If we are sending out over the same interface
on which the packet arrived, then we will have to either queue the packet,
or drop it. This functionality is already implemented in netpoll, so if we
filled in our queue routine to point at netpoll_queue, then at this point
we will call that via the ->drop pointer in our netpoll structure. So,
continuing along, we have:
netpoll_queue
schedule_work
and we are done. If the packet was schedule to head out a different
device, then we would continue with the send path:
dev->hard_start_xmit
New netpoll function implemented by the network drivers:
net_device->netpoll_setup
This is required, since the bonding device has to walk through each slave
and point its slave_dev->npinfo at the npinfo for the master device. The
reason for this is so that when we're doing the napi polling, we can set
the rx_flags appropriately.
net_device->netpoll_start_xmit
This routine is required since, otherwise, there is no way to intercept
packets bound for interfaces that are not ready for them. Of course, it
requires further logic in the bonding driver to then call into the
netpoll_send_skb routine (which is a new export).
Note that neither of these pointers has to be filled in by the driver.
These functions should only be implemented where needed, and to date, that
is only in the bonding driver.
Newly exported are:
netpoll_send_skb
This is exported so that the bonding driver can queue a packet to be sent
via the real ethernet device it has chosen.
netpoll_poll_dev
This is a new routine that was created and exported so that the
poll_controller implementation in the bonding driver could poll each of
the underlying real devices without duplicating all of the logic that
exists internally to netpoll already.
To test this, as I mentioned above, I wrote a simple module which, upon
receipt of any packet, sends out a packet with the message "PONG". I fired
up netcat to send test packets, and receive the responses. I also loaded
the netconsole module for the very same interface, bond0, and issue a
series of sysrq-X's, both via sysrq-trigger and via the keyboard. I did
this while simultaneously testing the PING server on an SMP machine. As
things stand, it is very stable in my environment.
And so, the patch set follows. Any and all comments are appreciated.
Thanks,
Jeff
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [rfc | patch 0/6] netpoll: add support for the bonding driver
2005-07-01 23:05 [rfc | patch 0/6] netpoll: add support for the bonding driver Jeff Moyer
@ 2005-07-01 23:06 ` Jeff Moyer
2005-07-01 23:06 ` Jeff Moyer
` (5 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Jeff Moyer @ 2005-07-01 23:06 UTC (permalink / raw)
To: mpm, netdev, linux-kernel
Initialize npinfo->rx_flags. The way it stands now, this will have random
garbage, and so will incur a locking penalty even when an rx_hook isn't
registered and we are not active in the netpoll polling code.
Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
---
--- linux-2.6.12/net/core/netpoll.c.orig 2005-07-01 14:02:56.039174635 -0400
+++ linux-2.6.12/net/core/netpoll.c 2005-07-01 14:03:16.688739508 -0400
@@ -639,6 +639,7 @@ int netpoll_setup(struct netpoll *np)
if (!npinfo)
goto release;
+ npinfo->rx_flags = 0;
npinfo->rx_np = NULL;
npinfo->poll_lock = SPIN_LOCK_UNLOCKED;
npinfo->poll_owner = -1;
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [rfc | patch 0/6] netpoll: add support for the bonding driver
2005-07-01 23:05 [rfc | patch 0/6] netpoll: add support for the bonding driver Jeff Moyer
2005-07-01 23:06 ` Jeff Moyer
@ 2005-07-01 23:06 ` Jeff Moyer
2005-07-01 23:08 ` [rfc | patch 3/6] netpoll: change poll_napi to take a net_device Jeff Moyer
` (4 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Jeff Moyer @ 2005-07-01 23:06 UTC (permalink / raw)
To: mpm, netdev, linux-kernel
Move the poll_lock and poll_owner to the struct net_device. This change is
important for the bonding driver support, as multiple real devices will
point at the same netpoll_info. In such cases, we would be artificially
limiting ourselves to calling the polling routine of only one member of a
bond at a time.
To understand how this benefits the bonding driver, let's consider a
netpoll client that sends packets in response to receiving packets. Let's
assume a packet comes in on eth0, and the response is to be delivered over
eth1. If the poll_lock lived in the npinfo (and hence, there was only one
per bond), then we would have to queue the packet. With this patch in
place, we can send the outbound packet immediately.
Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
---
--- linux-2.6.12/net/core/netpoll.c.orig 2005-07-01 14:52:11.932101811 -0400
+++ linux-2.6.12/net/core/netpoll.c 2005-07-01 14:53:59.322183590 -0400
@@ -131,19 +131,20 @@ static int checksum_udp(struct sk_buff *
static void poll_napi(struct netpoll *np)
{
struct netpoll_info *npinfo = np->dev->npinfo;
+ struct net_device *dev = np->dev;
int budget = 16;
- if (test_bit(__LINK_STATE_RX_SCHED, &np->dev->state) &&
- npinfo->poll_owner != smp_processor_id() &&
- spin_trylock(&npinfo->poll_lock)) {
+ if (test_bit(__LINK_STATE_RX_SCHED, &dev->state) &&
+ dev->poll_owner != smp_processor_id() &&
+ spin_trylock(&dev->poll_lock)) {
npinfo->rx_flags |= NETPOLL_RX_DROP;
atomic_inc(&trapped);
- np->dev->poll(np->dev, &budget);
+ dev->poll(dev, &budget);
atomic_dec(&trapped);
npinfo->rx_flags &= ~NETPOLL_RX_DROP;
- spin_unlock(&npinfo->poll_lock);
+ spin_unlock(&dev->poll_lock);
}
}
@@ -246,7 +247,6 @@ repeat:
static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
{
int status;
- struct netpoll_info *npinfo;
repeat:
if(!np || !np->dev || !netif_running(np->dev)) {
@@ -255,8 +255,7 @@ repeat:
}
/* avoid recursion */
- npinfo = np->dev->npinfo;
- if (npinfo->poll_owner == smp_processor_id() ||
+ if (dev->poll_owner == smp_processor_id() ||
np->dev->xmit_lock_owner == smp_processor_id()) {
if (np->drop)
np->drop(skb);
@@ -641,8 +640,6 @@ int netpoll_setup(struct netpoll *np)
npinfo->rx_flags = 0;
npinfo->rx_np = NULL;
- npinfo->poll_lock = SPIN_LOCK_UNLOCKED;
- npinfo->poll_owner = -1;
npinfo->rx_lock = SPIN_LOCK_UNLOCKED;
} else
npinfo = ndev->npinfo;
--- linux-2.6.12/net/core/dev.c.orig 2005-07-01 14:52:08.613655521 -0400
+++ linux-2.6.12/net/core/dev.c 2005-07-01 14:52:38.495669512 -0400
@@ -3069,6 +3069,10 @@ struct net_device *alloc_netdev(int size
setup(dev);
strcpy(dev->name, name);
+#ifdef CONFIG_NETPOLL
+ dev->poll_owner = -1;
+ dev->poll_lock = SPIN_LOCK_UNLOCKED;
+#endif
return dev;
}
EXPORT_SYMBOL(alloc_netdev);
--- linux-2.6.12/include/linux/netpoll.h.orig 2005-07-01 14:52:16.016420312 -0400
+++ linux-2.6.12/include/linux/netpoll.h 2005-07-01 14:52:38.495669512 -0400
@@ -24,8 +24,6 @@ struct netpoll {
};
struct netpoll_info {
- spinlock_t poll_lock;
- int poll_owner;
int rx_flags;
spinlock_t rx_lock;
struct netpoll *rx_np; /* netpoll that registered an rx_hook */
@@ -63,16 +61,16 @@ static inline int netpoll_rx(struct sk_b
static inline void netpoll_poll_lock(struct net_device *dev)
{
if (dev->npinfo) {
- spin_lock(&dev->npinfo->poll_lock);
- dev->npinfo->poll_owner = smp_processor_id();
+ spin_lock(&dev->poll_lock);
+ dev->poll_owner = smp_processor_id();
}
}
static inline void netpoll_poll_unlock(struct net_device *dev)
{
if (dev->npinfo) {
- dev->npinfo->poll_owner = -1;
- spin_unlock(&dev->npinfo->poll_lock);
+ dev->poll_owner = -1;
+ spin_unlock(&dev->poll_lock);
}
}
--- linux-2.6.12/include/linux/netdevice.h.orig 2005-07-01 14:52:22.666310731 -0400
+++ linux-2.6.12/include/linux/netdevice.h 2005-07-01 14:52:38.496669345 -0400
@@ -469,6 +469,8 @@ struct net_device
int (*neigh_setup)(struct net_device *dev, struct neigh_parms *);
#ifdef CONFIG_NETPOLL
struct netpoll_info *npinfo;
+ spinlock_t poll_lock;
+ int poll_owner;
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
void (*poll_controller)(struct net_device *dev);
^ permalink raw reply [flat|nested] 9+ messages in thread
* [rfc | patch 3/6] netpoll: change poll_napi to take a net_device
2005-07-01 23:05 [rfc | patch 0/6] netpoll: add support for the bonding driver Jeff Moyer
2005-07-01 23:06 ` Jeff Moyer
2005-07-01 23:06 ` Jeff Moyer
@ 2005-07-01 23:08 ` Jeff Moyer
2005-07-01 23:08 ` [rfc | patch 4/6] netpoll: add netpoll hooks to support the bonding driver Jeff Moyer
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Jeff Moyer @ 2005-07-01 23:08 UTC (permalink / raw)
To: mpm, netdev, linux-kernel
(sorry for munging the subject of the prior two patches)
The poll_napi routine is not specific to a netpoll. It really should be
able to be called with a struct net_device. Changing the routine to take a
struct net_device makes it easier to support the bonding driver, since we
will be implementing a netpoll_poll_dev routine, that will not have a
struct netpoll associated with it.
Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
---
--- linux-2.6.12/net/core/netpoll.c.orig 2005-07-01 14:12:33.986337259 -0400
+++ linux-2.6.12/net/core/netpoll.c 2005-07-01 14:20:45.848186887 -0400
@@ -128,10 +128,9 @@ static int checksum_udp(struct sk_buff *
* network adapter, forcing superfluous retries and possibly timeouts.
* Thus, we set our budget to greater than 1.
*/
-static void poll_napi(struct netpoll *np)
+static void poll_napi(struct net_device *dev)
{
- struct netpoll_info *npinfo = np->dev->npinfo;
- struct net_device *dev = np->dev;
+ struct netpoll_info *npinfo = dev->npinfo;
int budget = 16;
if (test_bit(__LINK_STATE_RX_SCHED, &dev->state) &&
@@ -156,7 +155,7 @@ void netpoll_poll(struct netpoll *np)
/* Process pending work on NIC */
np->dev->poll_controller(np->dev);
if (np->dev->poll)
- poll_napi(np);
+ poll_napi(np->dev);
zap_completion_queue();
}
^ permalink raw reply [flat|nested] 9+ messages in thread
* [rfc | patch 4/6] netpoll: add netpoll hooks to support the bonding driver
2005-07-01 23:05 [rfc | patch 0/6] netpoll: add support for the bonding driver Jeff Moyer
` (2 preceding siblings ...)
2005-07-01 23:08 ` [rfc | patch 3/6] netpoll: change poll_napi to take a net_device Jeff Moyer
@ 2005-07-01 23:08 ` Jeff Moyer
2005-07-01 23:09 ` [rfc | patch 5/6] netpoll: modify bonding driver to support netpoll Jeff Moyer
` (2 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Jeff Moyer @ 2005-07-01 23:08 UTC (permalink / raw)
To: mpm, netdev, linux-kernel
Implement hooks in the netpoll code to support the bonding driver (and
hopefully other virtual device drivers, as well). The key additions here
are netpoll_poll_dev(new) and netpoll_send_skb(newly exported).
netpoll_send_skb
This is exported so that the bonding driver can queue a packet to be sent
via the real ethernet device it has chosen.
netpoll_poll_dev
This is a new routine that was created and exported so that the
poll_controller implementation in the bonding driver could poll each of
the underlying real devices without duplicating all of the logic that
exists internally to netpoll already.
Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
---
--- linux-2.6.12/net/core/netpoll.c.orig 2005-07-01 15:02:05.503951082 -0400
+++ linux-2.6.12/net/core/netpoll.c 2005-07-01 15:02:36.718705979 -0400
@@ -147,19 +147,27 @@ static void poll_napi(struct net_device
}
}
-void netpoll_poll(struct netpoll *np)
+void netpoll_poll_dev(struct net_device *dev)
{
- if(!np->dev || !netif_running(np->dev) || !np->dev->poll_controller)
+ if(!netif_running(dev) || !dev->poll_controller)
return;
/* Process pending work on NIC */
- np->dev->poll_controller(np->dev);
- if (np->dev->poll)
- poll_napi(np->dev);
+ dev->poll_controller(dev);
+ if (dev->poll)
+ poll_napi(dev);
zap_completion_queue();
}
+void netpoll_poll(struct netpoll *np)
+{
+ if(!np->dev)
+ return;
+
+ netpoll_poll_dev(np->dev);
+}
+
static void refill_skbs(void)
{
struct sk_buff *skb;
@@ -243,48 +251,59 @@ repeat:
return skb;
}
-static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
+/*
+ * This function can be called from virtual device drivers, such as the
+ * bonding driver. In this case, skb->dev is filled in with the real
+ * device over which the packet needs to be sent. For this reason, we use
+ * the skb->dev instead of np->dev. Essentially, np->dev can be, for
+ * example, bond0, while we actually need to send the packet out over eth0.
+ */
+void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
{
int status;
+ struct net_device *dev = skb->dev;
repeat:
- if(!np || !np->dev || !netif_running(np->dev)) {
+ if(!np || !dev || !netif_running(dev)) {
__kfree_skb(skb);
return;
}
/* avoid recursion */
if (dev->poll_owner == smp_processor_id() ||
- np->dev->xmit_lock_owner == smp_processor_id()) {
- if (np->drop)
+ dev->xmit_lock_owner == smp_processor_id()) {
+ if (np && np->drop)
np->drop(skb);
else
__kfree_skb(skb);
return;
}
- spin_lock(&np->dev->xmit_lock);
- np->dev->xmit_lock_owner = smp_processor_id();
+ spin_lock(&dev->xmit_lock);
+ dev->xmit_lock_owner = smp_processor_id();
/*
* network drivers do not expect to be called if the queue is
* stopped.
*/
- if (netif_queue_stopped(np->dev)) {
- np->dev->xmit_lock_owner = -1;
- spin_unlock(&np->dev->xmit_lock);
+ if (netif_queue_stopped(dev)) {
+ dev->xmit_lock_owner = -1;
+ spin_unlock(&dev->xmit_lock);
- netpoll_poll(np);
+ netpoll_poll_dev(dev);
goto repeat;
}
- status = np->dev->hard_start_xmit(skb, np->dev);
- np->dev->xmit_lock_owner = -1;
- spin_unlock(&np->dev->xmit_lock);
+ if (dev->netpoll_start_xmit)
+ status = dev->netpoll_start_xmit(np, skb, dev);
+ else
+ status = dev->hard_start_xmit(skb, dev);
+ dev->xmit_lock_owner = -1;
+ spin_unlock(&dev->xmit_lock);
/* transmit busy */
if(status) {
- netpoll_poll(np);
+ netpoll_poll_dev(dev);
goto repeat;
}
}
@@ -715,6 +734,11 @@ int netpoll_setup(struct netpoll *np)
npinfo->rx_np = np;
spin_unlock_irqrestore(&npinfo->rx_lock, flags);
}
+
+ /* Call the device specific netpoll initialization routine. */
+ if (ndev->netpoll_setup)
+ ndev->netpoll_setup(ndev, npinfo);
+
/* last thing to do is link it to the net device structure */
ndev->npinfo = npinfo;
@@ -766,5 +790,7 @@ EXPORT_SYMBOL(netpoll_parse_options);
EXPORT_SYMBOL(netpoll_setup);
EXPORT_SYMBOL(netpoll_cleanup);
EXPORT_SYMBOL(netpoll_send_udp);
+EXPORT_SYMBOL(netpoll_send_skb);
EXPORT_SYMBOL(netpoll_poll);
+EXPORT_SYMBOL(netpoll_poll_dev);
EXPORT_SYMBOL(netpoll_queue);
--- linux-2.6.12/net/core/dev.c.orig 2005-07-01 14:59:50.161654219 -0400
+++ linux-2.6.12/net/core/dev.c 2005-07-01 15:00:23.437103656 -0400
@@ -1655,15 +1655,15 @@ int netif_receive_skb(struct sk_buff *sk
int ret = NET_RX_DROP;
unsigned short type;
- /* if we've gotten here through NAPI, check netpoll */
- if (skb->dev->poll && netpoll_rx(skb))
+ skb_bond(skb);
+
+ /* if there is a netpoll client registered, check netpoll */
+ if (skb->dev->npinfo && netpoll_rx(skb))
return NET_RX_DROP;
if (!skb->stamp.tv_sec)
net_timestamp(&skb->stamp);
- skb_bond(skb);
-
__get_cpu_var(netdev_rx_stat).total++;
skb->h.raw = skb->nh.raw = skb->data;
--- linux-2.6.12/include/linux/netpoll.h.orig 2005-07-01 14:59:56.135657708 -0400
+++ linux-2.6.12/include/linux/netpoll.h 2005-07-01 15:00:23.437103656 -0400
@@ -30,7 +30,9 @@ struct netpoll_info {
};
void netpoll_poll(struct netpoll *np);
+void netpoll_poll_dev(struct net_device *dev);
void netpoll_send_udp(struct netpoll *np, const char *msg, int len);
+void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb);
int netpoll_parse_options(struct netpoll *np, char *opt);
int netpoll_setup(struct netpoll *np);
int netpoll_trap(void);
--- linux-2.6.12/include/linux/netdevice.h.orig 2005-07-01 14:59:59.835040624 -0400
+++ linux-2.6.12/include/linux/netdevice.h 2005-07-01 15:00:23.438103489 -0400
@@ -41,6 +41,7 @@
struct divert_blk;
struct vlan_group;
struct ethtool_ops;
+struct netpoll;
struct netpoll_info;
/* source back-compat hooks */
#define SET_ETHTOOL_OPS(netdev,ops) \
@@ -473,7 +474,12 @@ struct net_device
int poll_owner;
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
+ void (*netpoll_setup)(struct net_device *dev,
+ struct netpoll_info *npinfo);
void (*poll_controller)(struct net_device *dev);
+ int (*netpoll_start_xmit)(struct netpoll *np,
+ struct sk_buff *skb,
+ struct net_device *dev);
#endif
/* bridge stuff */
^ permalink raw reply [flat|nested] 9+ messages in thread
* [rfc | patch 5/6] netpoll: modify bonding driver to support netpoll
2005-07-01 23:05 [rfc | patch 0/6] netpoll: add support for the bonding driver Jeff Moyer
` (3 preceding siblings ...)
2005-07-01 23:08 ` [rfc | patch 4/6] netpoll: add netpoll hooks to support the bonding driver Jeff Moyer
@ 2005-07-01 23:09 ` Jeff Moyer
2005-07-01 23:10 ` [rfc | patch 6/6] netpoll: fix deadlock in arp_reply Jeff Moyer
2005-07-01 23:38 ` [rfc | patch 0/6] netpoll: add support for the bonding driver Matt Mackall
6 siblings, 0 replies; 9+ messages in thread
From: Jeff Moyer @ 2005-07-01 23:09 UTC (permalink / raw)
To: mpm, netdev, linux-kernel
Implement netpoll hooks in the bonding driver. We register the following
netpoll specific routines:
bond_netpoll_setup
This routine associates the struct netpoll_info of the master device with
each of the slave devices.
bond_xmit_netpoll
This routine sets bonding->netpoll to the struct netpoll provided by
netpoll_send_skb. This pointer is then passed along to netpoll_send_skb
in bond_dev_queue_xmit, when we are ready to send the skb out over the
real network device.
bond_poll_controller
This routine calls netpoll_poll_dev for each of the slaves in the bond.
When a new slave is added to the bond, if it does not support netpoll, then
netpoll is disabled for the bond. When a slave is released, that slave's
npinfo pointer is cleared.
I have tested this code extensively, and it works well in my environment.
Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
---
--- linux-2.6.12/drivers/net/bonding/bond_main.c.orig 2005-06-29 14:28:08.000000000 -0400
+++ linux-2.6.12/drivers/net/bonding/bond_main.c 2005-06-30 19:33:50.641009622 -0400
@@ -821,8 +821,12 @@ int bond_dev_queue_xmit(struct bonding *
}
skb->priority = 1;
- dev_queue_xmit(skb);
-
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ if (bond->netpoll)
+ netpoll_send_skb(bond->netpoll, skb);
+ else
+#endif
+ dev_queue_xmit(skb);
return 0;
}
@@ -1567,6 +1571,45 @@ static void bond_detach_slave(struct bon
bond->slave_cnt--;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static int slaves_support_netpoll(struct net_device *bond_dev)
+{
+ struct bonding *bond = bond_dev->priv;
+ struct slave *slave;
+ int i;
+
+ bond_for_each_slave(bond, slave, i) {
+ if (!slave->dev->poll_controller)
+ return 0;
+ }
+
+ return 1;
+}
+
+static void bond_poll_controller(struct net_device *bond_dev)
+{
+ struct bonding *bond = bond_dev->priv;
+ struct slave *slave;
+ int i;
+
+ bond_for_each_slave(bond, slave, i) {
+ if (slave->dev->poll_controller)
+ netpoll_poll_dev(slave->dev);
+ }
+}
+
+static void bond_netpoll_setup(struct net_device *bond_dev,
+ struct netpoll_info *npinfo)
+{
+ struct bonding *bond = bond_dev->priv;
+ struct slave *slave;
+ int i;
+
+ bond_for_each_slave(bond, slave, i)
+ slave->dev->npinfo = npinfo;
+}
+#endif
+
/*---------------------------------- IOCTL ----------------------------------*/
static int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev)
@@ -1969,6 +2012,17 @@ static int bond_enslave(struct net_devic
new_slave->state == BOND_STATE_ACTIVE ? "n active" : " backup",
new_slave->link != BOND_LINK_DOWN ? "n up" : " down");
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ if (slaves_support_netpoll(bond_dev)) {
+ bond_dev->poll_controller = bond_poll_controller;
+ slave_dev->npinfo = bond_dev->npinfo;
+ } else if (bond_dev->poll_controller) {
+ bond_dev->poll_controller = NULL;
+ printk("New slave device %s does not support netpoll.\n",
+ slave_dev->name);
+ printk("netpoll disabled for %s.\n", bond_dev->name);
+ }
+#endif
/* enslave is successful */
return 0;
@@ -2173,6 +2227,9 @@ static int bond_release(struct net_devic
slave_dev->flags &= ~IFF_NOARP;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ slave_dev->npinfo = NULL;
+#endif
kfree(slave);
return 0; /* deletion OK */
@@ -4203,6 +4260,21 @@ out:
return 0;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+int bond_xmit_netpoll(struct netpoll *np, struct sk_buff *skb,
+ struct net_device *bond_dev)
+{
+ struct bonding *bond = bond_dev->priv;
+ int ret;
+
+ bond->netpoll = np;
+ ret = bond_dev->hard_start_xmit(skb, bond_dev);
+ bond->netpoll = NULL;
+
+ return ret;
+}
+#endif
+
/*------------------------- Device initialization ---------------------------*/
/*
@@ -4277,6 +4349,10 @@ static int __init bond_init(struct net_d
bond_dev->destructor = free_netdev;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ bond_dev->netpoll_setup = bond_netpoll_setup;
+ bond_dev->netpoll_start_xmit = bond_xmit_netpoll;
+#endif
/* Initialize the device options */
bond_dev->tx_queue_len = 0;
bond_dev->flags |= IFF_MASTER|IFF_MULTICAST;
--- linux-2.6.12/drivers/net/bonding/bonding.h.orig 2005-06-29 14:29:40.000000000 -0400
+++ linux-2.6.12/drivers/net/bonding/bonding.h 2005-06-30 19:02:54.000000000 -0400
@@ -33,6 +33,7 @@
#include <linux/timer.h>
#include <linux/proc_fs.h>
#include <linux/if_bonding.h>
+#include <linux/netpoll.h>
#include "bond_3ad.h"
#include "bond_alb.h"
@@ -203,6 +204,9 @@ struct bonding {
struct bond_params params;
struct list_head vlan_list;
struct vlan_group *vlgrp;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ struct netpoll *netpoll;
+#endif
};
/**
^ permalink raw reply [flat|nested] 9+ messages in thread
* [rfc | patch 6/6] netpoll: fix deadlock in arp_reply
2005-07-01 23:05 [rfc | patch 0/6] netpoll: add support for the bonding driver Jeff Moyer
` (4 preceding siblings ...)
2005-07-01 23:09 ` [rfc | patch 5/6] netpoll: modify bonding driver to support netpoll Jeff Moyer
@ 2005-07-01 23:10 ` Jeff Moyer
2005-07-01 23:38 ` [rfc | patch 0/6] netpoll: add support for the bonding driver Matt Mackall
6 siblings, 0 replies; 9+ messages in thread
From: Jeff Moyer @ 2005-07-01 23:10 UTC (permalink / raw)
To: mpm, netdev, linux-kernel
This fixes an obvious deadlock in the netpoll code. netpoll_rx takes the
npinfo->rx_lock. netpoll_rx is also the only caller of arp_reply (through
__netpoll_rx). As such, it is not necessary to take this lock.
Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
--- linux-2.6.12/net/core/netpoll.c.orig 2005-07-01 17:55:24.313339068 -0400
+++ linux-2.6.12/net/core/netpoll.c 2005-07-01 17:55:57.354863472 -0400
@@ -370,11 +370,8 @@ static void arp_reply(struct sk_buff *sk
struct sk_buff *send_skb;
struct netpoll *np = NULL;
- spin_lock_irqsave(&npinfo->rx_lock, flags);
if (npinfo->rx_np && npinfo->rx_np->dev == skb->dev)
np = npinfo->rx_np;
- spin_unlock_irqrestore(&npinfo->rx_lock, flags);
-
if (!np)
return;
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [rfc | patch 0/6] netpoll: add support for the bonding driver
2005-07-01 23:05 [rfc | patch 0/6] netpoll: add support for the bonding driver Jeff Moyer
` (5 preceding siblings ...)
2005-07-01 23:10 ` [rfc | patch 6/6] netpoll: fix deadlock in arp_reply Jeff Moyer
@ 2005-07-01 23:38 ` Matt Mackall
2005-07-01 23:43 ` Jeff Moyer
6 siblings, 1 reply; 9+ messages in thread
From: Matt Mackall @ 2005-07-01 23:38 UTC (permalink / raw)
To: Jeff Moyer; +Cc: netdev, linux-kernel
On Fri, Jul 01, 2005 at 07:05:54PM -0400, Jeff Moyer wrote:
> New netpoll function implemented by the network drivers:
>
> net_device->netpoll_setup
> This is required, since the bonding device has to walk through each slave
> and point its slave_dev->npinfo at the npinfo for the master device. The
> reason for this is so that when we're doing the napi polling, we can set
> the rx_flags appropriately.
>
> net_device->netpoll_start_xmit
> This routine is required since, otherwise, there is no way to intercept
> packets bound for interfaces that are not ready for them. Of course, it
> requires further logic in the bonding driver to then call into the
> netpoll_send_skb routine (which is a new export).
>
> Note that neither of these pointers has to be filled in by the driver.
> These functions should only be implemented where needed, and to date, that
> is only in the bonding driver.
>
> Newly exported are:
>
> netpoll_send_skb
> This is exported so that the bonding driver can queue a packet to be sent
> via the real ethernet device it has chosen.
>
> netpoll_poll_dev
> This is a new routine that was created and exported so that the
> poll_controller implementation in the bonding driver could poll each of
> the underlying real devices without duplicating all of the logic that
> exists internally to netpoll already.
>
>
> To test this, as I mentioned above, I wrote a simple module which, upon
> receipt of any packet, sends out a packet with the message "PONG". I fired
> up netcat to send test packets, and receive the responses. I also loaded
> the netconsole module for the very same interface, bond0, and issue a
> series of sysrq-X's, both via sysrq-trigger and via the keyboard. I did
> this while simultaneously testing the PING server on an SMP machine. As
> things stand, it is very stable in my environment.
>
> And so, the patch set follows. Any and all comments are appreciated.
Patches 1, 3, and 6 are unrelated bugfixes and should just go in.
I don't like that we rely on queueing to process round trips for PONG.
Is this really unavoidable?
And I think the most controversial thing here is moving locks from npinfo
into the device.
Not really happy about how incestuous this makes the bonding driver
with netpoll. I'll try to think more about it over the weekend.
--
Mathematics is the supreme nostalgia of our time.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [rfc | patch 0/6] netpoll: add support for the bonding driver
2005-07-01 23:38 ` [rfc | patch 0/6] netpoll: add support for the bonding driver Matt Mackall
@ 2005-07-01 23:43 ` Jeff Moyer
0 siblings, 0 replies; 9+ messages in thread
From: Jeff Moyer @ 2005-07-01 23:43 UTC (permalink / raw)
To: Matt Mackall; +Cc: netdev, linux-kernel
==> Regarding Re: [rfc | patch 0/6] netpoll: add support for the bonding driver; Matt Mackall <mpm@selenic.com> adds:
mpm> On Fri, Jul 01, 2005 at 07:05:54PM -0400, Jeff Moyer wrote:
>> New netpoll function implemented by the network drivers:
>>
net_device-> netpoll_setup
>> This is required, since the bonding device has to walk through each
>> slave and point its slave_dev->npinfo at the npinfo for the master
>> device. The reason for this is so that when we're doing the napi
>> polling, we can set the rx_flags appropriately.
>>
net_device-> netpoll_start_xmit
>> This routine is required since, otherwise, there is no way to intercept
>> packets bound for interfaces that are not ready for them. Of course, it
>> requires further logic in the bonding driver to then call into the
>> netpoll_send_skb routine (which is a new export).
>>
>> Note that neither of these pointers has to be filled in by the driver.
>> These functions should only be implemented where needed, and to date,
>> that is only in the bonding driver.
>>
>> Newly exported are:
>>
>> netpoll_send_skb This is exported so that the bonding driver can queue a
>> packet to be sent via the real ethernet device it has chosen.
>>
>> netpoll_poll_dev This is a new routine that was created and exported so
>> that the poll_controller implementation in the bonding driver could poll
>> each of the underlying real devices without duplicating all of the logic
>> that exists internally to netpoll already.
>>
>>
>> To test this, as I mentioned above, I wrote a simple module which, upon
>> receipt of any packet, sends out a packet with the message "PONG". I
>> fired up netcat to send test packets, and receive the responses. I also
>> loaded the netconsole module for the very same interface, bond0, and
>> issue a series of sysrq-X's, both via sysrq-trigger and via the
>> keyboard. I did this while simultaneously testing the PING server on an
>> SMP machine. As things stand, it is very stable in my environment.
>>
>> And so, the patch set follows. Any and all comments are appreciated.
mpm> Patches 1, 3, and 6 are unrelated bugfixes and should just go in.
Right. Sorry I lumped them together.
mpm> I don't like that we rely on queueing to process round trips for PONG.
mpm> Is this really unavoidable?
That's how it works without these patches, too.
mpm> And I think the most controversial thing here is moving locks from
mpm> npinfo into the device.
Well, as I mentioned, that's a bit of an optimization, if you will.
mpm> Not really happy about how incestuous this makes the bonding driver
mpm> with netpoll. I'll try to think more about it over the weekend.
I'd be delighted if you came up with a better way to do things. However, I
think you'll find that this is about as clean as it gets.
-Jeff
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2005-07-01 23:43 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-07-01 23:05 [rfc | patch 0/6] netpoll: add support for the bonding driver Jeff Moyer
2005-07-01 23:06 ` Jeff Moyer
2005-07-01 23:06 ` Jeff Moyer
2005-07-01 23:08 ` [rfc | patch 3/6] netpoll: change poll_napi to take a net_device Jeff Moyer
2005-07-01 23:08 ` [rfc | patch 4/6] netpoll: add netpoll hooks to support the bonding driver Jeff Moyer
2005-07-01 23:09 ` [rfc | patch 5/6] netpoll: modify bonding driver to support netpoll Jeff Moyer
2005-07-01 23:10 ` [rfc | patch 6/6] netpoll: fix deadlock in arp_reply Jeff Moyer
2005-07-01 23:38 ` [rfc | patch 0/6] netpoll: add support for the bonding driver Matt Mackall
2005-07-01 23:43 ` Jeff Moyer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).