* はじめまして。
From: 今井玲子 @ 2005-06-30 23:15 UTC (permalink / raw)
To: netdev
こんばんわ♪
はずかしくってちょっと書きづらいんだけど、
すごいH☆なサイトをがあるの知ってますか?
有名な人がいっぱいで隠し撮りやいろんな種類の動画が盛りだくさん♪
芸能人のもあるから驚きだよ!
とりあえずサンプル見てみよ☆
http://the-premium-movie.com
^ permalink raw reply
* Re: [Fastboot] Re: Re: tg3: issue for reboot/kexec
From: Eric W. Biederman @ 2005-06-30 23:21 UTC (permalink / raw)
To: Greg KH; +Cc: netdev, fastboot, linux-pm
In-Reply-To: <20050625033328.GC3934@kroah.com>
[-- Attachment #1: Type: text/plain, Size: 2527 bytes --]
Greg KH <greg@kroah.com> writes:
> On Fri, Jun 24, 2005 at 05:46:52PM -0700, randy_dunlap wrote:
>> On Fri, 24 Jun 2005 17:02:17 -0700 Haren Myneni wrote:
>>
>> |
>> | Hello,
>> | The kexec boot on power blade (JS20) is not successfull without
>> | doing 'ifdown <ethernet device>'. Based on my initial look in tg3 code,
>> | the driver does not have shutdown nor reboot notifier code unlike in
>> | other drivers. Hence, I added the the following patch (based on e1000)
>> | and it is working. Is it OK to include this patch? If not, any help to
>> | track down the issue would be appreciated.
>> |
>> | My system is having the following cards:
>> | 0000:11:01.0 Ethernet controller: Broadcom Corporation NetXtreme
>> | BCM5704S Gigabit Ethernet (rev 03)
>> | 0000:11:01.1 Ethernet controller: Broadcom Corporation NetXtreme
>> | BCM5704S Gigabit Ethernet (rev 03)
>> |
>> | lspci -n -s 0000:11:01
>> | 0000:11:01.0 Class 0200: 14e4:16a8 (rev 03)
>> | 0000:11:01.1 Class 0200: 14e4:16a8 (rev 03)
>>
>> [adding fastboot & linux-pm mailing lists]
>>
>> There was just a SCSI driver patch that tried to use a reboot
>> notifier on shutdown and the patch got this comment:
>>
>> Subject: Re: [PATCH] 2.6 aacraid: shutdown notification
>> Message-ID: <42BC6D6F.5090402@us.ibm.com>
>> From: Mark Haverkamp <markh@osdl.org>
>>
>> and reply From: Brian King <brking@us.ibm.com>:
>> | The pci_driver->shutdown method should be used instead of registering
>> | a reboot notifier.
>>
>> so is there a good reason that network drivers should use the
>> reboot notifier instead of pci_driver->shutdown,
>> or should we be converting drivers to use pci_driver->shutdown
>> instead?
>> My quick look favors pci_driver->shutdown.
A couple stray bits of feedback. Downing the interface is generally
a user space requirement like unmounting filesystems.
/sbin/kexec and /sbin/reboot both perform this operation so I don't
see how this bug was hit.
I am wondering here if the problem was on on going DMA transaction
or something else. If the problem was not an on going DMA transaction
then this problem is going to crop back up when people start
messing with the kexec on panic, because it indicates the
driver initialization is not robust.
> Yes, don't add a reboot notifier, use the shutdown function instead.
Sounds right to me.
However I have gotten feedback a couple of times that
driver writers tend to prefer using reboot notifiers. In part
because shutdown functions don't exist for non-pci devices.
Eric
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply
* Re: [Fastboot] Re: Re: tg3: issue for reboot/kexec
From: Greg KH @ 2005-06-30 23:33 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: netdev, fastboot, linux-pm
In-Reply-To: <m18y0rl9bq.fsf@ebiederm.dsl.xmission.com>
[-- Attachment #1: Type: text/plain, Size: 646 bytes --]
On Thu, Jun 30, 2005 at 05:21:45PM -0600, Eric W. Biederman wrote:
> However I have gotten feedback a couple of times that
> driver writers tend to prefer using reboot notifiers. In part
> because shutdown functions don't exist for non-pci devices.
That's a very lame excuse. All busses should have shutdown functions.
And any device that is just bypassing all of the existing bus logic is
still tying into the driver core directly (which is a bad thing by
itself, but that's a different matter.) And there's a shutdown method
there too.
So there is no excuse to not use it. Please, if they complain, point
them to me :)
thanks,
greg k-h
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply
* Re: [Fastboot] Re: Re: tg3: issue for reboot/kexec
From: Eric W. Biederman @ 2005-06-30 23:52 UTC (permalink / raw)
To: Greg KH; +Cc: netdev, fastboot, linux-pm
In-Reply-To: <20050630233354.GA22287@kroah.com>
[-- Attachment #1: Type: text/plain, Size: 2031 bytes --]
Greg KH <greg@kroah.com> writes:
> On Thu, Jun 30, 2005 at 05:21:45PM -0600, Eric W. Biederman wrote:
>> However I have gotten feedback a couple of times that
>> driver writers tend to prefer using reboot notifiers. In part
>> because shutdown functions don't exist for non-pci devices.
>
> That's a very lame excuse. All busses should have shutdown functions.
> And any device that is just bypassing all of the existing bus logic is
> still tying into the driver core directly (which is a bad thing by
> itself, but that's a different matter.) And there's a shutdown method
> there too.
>
> So there is no excuse to not use it. Please, if they complain, point
> them to me :)
Ok.
Then there is still my complaint and device_shutdown doesn't get called
on module removal which means it really doesn't get implemented. Perhaps
with kexec now being in the mainline kernel this will get better.
Currently I have the following patch outstanding against the e1000
driver because on reboot on some boxes it card revisions
it places the card into a sleep state the driver initialization
routing cannot get the card out of.
And yes the e1000 is bad and is using a reboot_notifier.
Eric
e1000_main.c | 2 +-
1 files changed, 1 insertion(+), 1 deletion(-)
diff -uNr linux-2.4.29-kexec-apic-virtwire-on-shutdownx86_64/drivers/net/e1000/e1000_main.c linux-2.4.29-e1000-no-poweroff-on-reboot/drivers/net/e1000/e1000_main.c
--- linux-2.4.29-kexec-apic-virtwire-on-shutdownx86_64/drivers/net/e1000/e1000_main.c Tue Feb 15 14:17:09 2005
+++ linux-2.4.29-e1000-no-poweroff-on-reboot/drivers/net/e1000/e1000_main.c Wed Feb 16 05:49:00 2005
@@ -2777,7 +2777,7 @@
case SYS_POWER_OFF:
while((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) {
if(pci_dev_driver(pdev) == &e1000_driver)
- e1000_suspend(pdev, 3);
+ e1000_suspend(pdev, (event == SYS_DOWN)?0:3);
}
}
return NOTIFY_DONE;
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply
* Re: [PATCH] multipath routing algorithm, better patch
From: Patrick McHardy @ 2005-07-01 0:43 UTC (permalink / raw)
To: Patrick Jenkins; +Cc: linux-kernel, Maillist netdev
In-Reply-To: <Pine.GSO.4.61.0506302014160.7400@rac1.wam.umd.edu>
Patrick Jenkins wrote:
> Hi,
>
> The last patch wont work, this should.
>
> This patch assigns the multipath routing algorithm into the fib_info
> struct's fib_mp_alg variable. Previously, the algorithm was always set to
> IP_MP_ALG_NONE which was incorrect. This patch corrects the problem by
> assigning the correct value when a fib_info is initialized.
>
> This patch was tested against kernel 2.6.12.1 for all multipath routing
> algorithms (none, round robin, interface round robin, random, weighted
> random).
Multiple algorithms can be compiled in at once, so this patch is wrong.
mp_alg is supplied by userspace:
if (rta->rta_mp_alg) {
mp_alg = *rta->rta_mp_alg;
if (mp_alg < IP_MP_ALG_NONE ||
mp_alg > IP_MP_ALG_MAX)
goto err_inval;
}
If it isn't set correctly its an iproute problem. Did you actually
experience any problems?
Regards
Patrick
^ permalink raw reply
* Re: [Fastboot] Re: Re: tg3: issue for reboot/kexec
From: Haren Myneni @ 2005-07-01 1:18 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: linux-pm, fastboot, netdev
In-Reply-To: <m18y0rl9bq.fsf@ebiederm.dsl.xmission.com>
[-- Attachment #1: Type: text/plain, Size: 598 bytes --]
Eric W. Biederman wrote:
>A couple stray bits of feedback. Downing the interface is generally
>a user space requirement like unmounting filesystems.
>/sbin/kexec and /sbin/reboot both perform this operation so I don't
>see how this bug was hit.
>
>
>
Thanks for your feedback. We are still working on kexec tools for PPC64.
In the mean time, I was using a temporary tool which does not do ifdown.
I was in the impression that the kexec boot will be successful since the
normal kexec code path (kernel/sys.c) contains device_shutdown/reboot
notifier. It turns out I am wrong.
Thanks
Haren
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply
* Re: [Fastboot] Re: Re: tg3: issue for reboot/kexec
From: Eric W. Biederman @ 2005-07-01 1:27 UTC (permalink / raw)
To: Haren Myneni; +Cc: linux-pm, fastboot, netdev
In-Reply-To: <42C499DD.3050009@us.ibm.com>
[-- Attachment #1: Type: text/plain, Size: 797 bytes --]
Haren Myneni <haren@us.ibm.com> writes:
> Eric W. Biederman wrote:
>
>>A couple stray bits of feedback. Downing the interface is generally
>>a user space requirement like unmounting filesystems.
>>/sbin/kexec and /sbin/reboot both perform this operation so I don't
>>see how this bug was hit.
>>
>>
>>
> Thanks for your feedback. We are still working on kexec tools for PPC64. In the
> mean time, I was using a temporary tool which does not do ifdown. I was in the
> impression that the kexec boot will be successful since the normal kexec code
> path (kernel/sys.c) contains device_shutdown/reboot notifier. It turns out I am
> wrong.
Buggy drivers will do that to you as well. But not doing a clean shutdown
(downing interfaces, and unmounting the filesystems) doesn't help things :)
Eric
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply
* Re: -mm -> 2.6.13 merge status (dropped patches?)
From: David S. Miller @ 2005-07-01 2:52 UTC (permalink / raw)
To: akpm; +Cc: 76306.1226, netdev, jgarzik, linux-kernel
In-Reply-To: <20050630161456.2ef0ab32.akpm@osdl.org>
From: Andrew Morton <akpm@osdl.org>
Date: Thu, 30 Jun 2005 16:14:56 -0700
> Chuck Ebbert <76306.1226@compuserve.com> wrote:
> >
> > What happened to:
> >
> > remove-last_rx-update-from-loopback-device.patch
>
> Davem rejected it. hm, I can't find the email trail - it was cc'ed to
> netdev@oss.sgi.com mid-March, but nothing seems to have been sent back.
Every network device must reliably set ->last_rx, there are parts
of the kernel which depend upon this attribute having an accurate
value.
The bonding driver is one example. And whilst one can argue that
loopback is unlikely to be used as part of a bond, it's massively
better from a consistency perspective if this invariant can be
relied upon across all networking drivers.
In short, the NUMA scalability hacks to loopback have gotten out
of control, and we need to stop this madness somewhere.
^ permalink raw reply
* general bonding question
From: Raz Ben-Jehuda(caro) @ 2005-07-01 9:00 UTC (permalink / raw)
To: netdev
To any of you that deal with the nic bonding driver.
Is there a special reason why the bond interface is not using
the slave device features, such as "scatter gather" or hardware checksum ?
I think of fixing the driver but i thought it would better to advise first.
--
Raz
Long Live the Penguin
^ permalink raw reply
* problems with 2.6.12
From: Eric Lammerts @ 2005-07-01 15:35 UTC (permalink / raw)
To: madwifi-devel; +Cc: tommy.christensen, herbert, davem, netdev
Hello all,
I was having problems with 2.6.12 + madwifi in master mode. No packets were
going out. With tcpdump I see DHCP requests coming in, with strace I see the
dhcp daemon sending replies out, but they don't show up in tcpdump.
It's caused by this change:
http://oss.sgi.com/projects/netdev/archive/2005-05/msg00109.html
which btw also causes problems for other people:
http://marc.theaimsgroup.com/?l=linux-kernel&m=111853727810345&w=2
Madwifi doesn't call netif_carrier_on() in master mode, so Linux drops all
packets. When I remove the dev_deactivate() line, it works fine again.
Should we fix madwifi or the kernel?
Eric
^ permalink raw reply
* Re: problems with 2.6.12
From: Tommy Christensen @ 2005-07-01 16:33 UTC (permalink / raw)
To: Eric Lammerts; +Cc: madwifi-devel, herbert, davem, netdev
In-Reply-To: <42C562A4.9070501@lammerts.org>
Eric Lammerts wrote:
> Hello all,
> I was having problems with 2.6.12 + madwifi in master mode. No packets
> were going out. With tcpdump I see DHCP requests coming in, with strace
> I see the dhcp daemon sending replies out, but they don't show up in
> tcpdump.
>
> It's caused by this change:
> http://oss.sgi.com/projects/netdev/archive/2005-05/msg00109.html
>
> which btw also causes problems for other people:
> http://marc.theaimsgroup.com/?l=linux-kernel&m=111853727810345&w=2
Auch. And vlan interfaces are having trouble as well.
> Madwifi doesn't call netif_carrier_on() in master mode, so Linux drops
> all packets. When I remove the dev_deactivate() line, it works fine again.
Netdevices are "born" with carrier on, so if your code don't call
netif_carrier_off() or set dev->state directly, I don't see how you
can end up in this state. Could you investigate this?
> Should we fix madwifi or the kernel?
The code is there for a reason, so hopefully we can work this out.
-Tommy
^ permalink raw reply
* Re: [PATCH] multipath routing algorithm, better patch
From: Thomas Graf @ 2005-07-01 17:41 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Patrick Jenkins, linux-kernel, Maillist netdev
In-Reply-To: <42C4919A.5000009@trash.net>
* Patrick McHardy <42C4919A.5000009@trash.net> 2005-07-01 02:43
> Multiple algorithms can be compiled in at once, so this patch is wrong.
> mp_alg is supplied by userspace:
>
> if (rta->rta_mp_alg) {
> mp_alg = *rta->rta_mp_alg;
>
> if (mp_alg < IP_MP_ALG_NONE ||
> mp_alg > IP_MP_ALG_MAX)
> goto err_inval;
> }
>
> If it isn't set correctly its an iproute problem. Did you actually
> experience any problems?
Well, my patch for iproute2 to enable multipath algorithm selection
is currently being merged to Stephen together with the ematch bits.
We had to work out a dependency on GNU flex first (the berkley
version uses the same executable names) so the inclusion was
delayed a bit.
^ permalink raw reply
* Re: [PATCH] multipath routing algorithm, better patch
From: Patrick McHardy @ 2005-07-01 19:34 UTC (permalink / raw)
To: Thomas Graf; +Cc: Patrick Jenkins, linux-kernel, Maillist netdev
In-Reply-To: <20050701174117.GW16076@postel.suug.ch>
Thomas Graf wrote:
> * Patrick McHardy <42C4919A.5000009@trash.net> 2005-07-01 02:43
>
>>If it isn't set correctly its an iproute problem. Did you actually
>>experience any problems?
>
> Well, my patch for iproute2 to enable multipath algorithm selection
> is currently being merged to Stephen together with the ematch bits.
> We had to work out a dependency on GNU flex first (the berkley
> version uses the same executable names) so the inclusion was
> delayed a bit.
So its no problem but simply missing support. BTW, do you know if
Stephen's new CVS repository is exported somewhere?
Regards
Patrick
^ permalink raw reply
* [patch 2.6.13-rc1] b44: attempt alternative rx/tx desc alloc if normal alloc fails
From: John W. Linville @ 2005-07-01 20:18 UTC (permalink / raw)
To: netdev; +Cc: jgarzik, linux-kernel
The b44 hardware can only handle DMA to physical addresses below 1GB.
In response to this fact, the x86 implementation of pci_alloc_consistent
allocates memory w/ the GFP_DMA flag set. On the x86, this forces
allocations to come from the lowest 16MB of physical memory.
Since the low 16MB memory pool is easily exhausted, some users will
experience failures when attempting to open the b44 driver. Since
any memory below 1GB is actually usable, this patch makes a second
allocation attempt and manually checks the results for acceptability.
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
OK, so this seems a bit yucky...but it is not really any worse than
some existing hacks in the b44 driver to deal w/ essentially the same
issue. Look for other references to B44_DMA_MASK to see for yourself.
drivers/net/b44.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++------
drivers/net/b44.h | 2 +
2 files changed, 66 insertions(+), 8 deletions(-)
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -1085,13 +1085,25 @@ static void b44_free_consistent(struct b
bp->tx_buffers = NULL;
}
if (bp->rx_ring) {
- pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
- bp->rx_ring, bp->rx_ring_dma);
+ if (bp->flags & B44_FLAG_RX_RING_HACK) {
+ pci_unmap_single(bp->pdev, (dma_addr_t)bp->rx_ring,
+ DMA_TABLE_BYTES,
+ PCI_DMA_FROMDEVICE);
+ kfree(bp->rx_ring);
+ } else
+ pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
+ bp->rx_ring, bp->rx_ring_dma);
bp->rx_ring = NULL;
}
if (bp->tx_ring) {
- pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
- bp->tx_ring, bp->tx_ring_dma);
+ if (bp->flags & B44_FLAG_TX_RING_HACK) {
+ pci_unmap_single(bp->pdev, (dma_addr_t)bp->tx_ring,
+ DMA_TABLE_BYTES,
+ PCI_DMA_TODEVICE);
+ kfree(bp->tx_ring);
+ } else
+ pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
+ bp->tx_ring, bp->tx_ring_dma);
bp->tx_ring = NULL;
}
}
@@ -1118,12 +1130,56 @@ static int b44_alloc_consistent(struct b
size = DMA_TABLE_BYTES;
bp->rx_ring = pci_alloc_consistent(bp->pdev, size, &bp->rx_ring_dma);
- if (!bp->rx_ring)
- goto out_err;
+ if (!bp->rx_ring) {
+ /* Allocation may have failed due to pci_alloc_consistent
+ insisting on use of GFP_DMA, which is more restrictive
+ than necessary... */
+ struct dma_desc *rx_ring;
+ dma_addr_t rx_ring_dma;
+
+ if (!(rx_ring = (struct dma_desc *)kmalloc(size, GFP_KERNEL)))
+ goto out_err;
+
+ memset(rx_ring, 0, size);
+ rx_ring_dma = pci_map_single(bp->pdev, rx_ring,
+ DMA_TABLE_BYTES,
+ PCI_DMA_FROMDEVICE);
+
+ if (rx_ring_dma + size > B44_DMA_MASK) {
+ kfree(rx_ring);
+ goto out_err;
+ }
+
+ bp->rx_ring = rx_ring;
+ bp->rx_ring_dma = rx_ring_dma;
+ bp->flags |= B44_FLAG_RX_RING_HACK;
+ }
bp->tx_ring = pci_alloc_consistent(bp->pdev, size, &bp->tx_ring_dma);
- if (!bp->tx_ring)
- goto out_err;
+ if (!bp->tx_ring) {
+ /* Allocation may have failed due to pci_alloc_consistent
+ insisting on use of GFP_DMA, which is more restrictive
+ than necessary... */
+ struct dma_desc *tx_ring;
+ dma_addr_t tx_ring_dma;
+
+ if (!(tx_ring = (struct dma_desc *)kmalloc(size, GFP_KERNEL)))
+ goto out_err;
+
+ memset(tx_ring, 0, size);
+ tx_ring_dma = pci_map_single(bp->pdev, tx_ring,
+ DMA_TABLE_BYTES,
+ PCI_DMA_TODEVICE);
+
+ if (tx_ring_dma + size > B44_DMA_MASK) {
+ kfree(tx_ring);
+ goto out_err;
+ }
+
+ bp->tx_ring = tx_ring;
+ bp->tx_ring_dma = tx_ring_dma;
+ bp->flags |= B44_FLAG_TX_RING_HACK;
+ }
return 0;
diff --git a/drivers/net/b44.h b/drivers/net/b44.h
--- a/drivers/net/b44.h
+++ b/drivers/net/b44.h
@@ -400,6 +400,8 @@ struct b44 {
#define B44_FLAG_ADV_100HALF 0x04000000
#define B44_FLAG_ADV_100FULL 0x08000000
#define B44_FLAG_INTERNAL_PHY 0x10000000
+#define B44_FLAG_RX_RING_HACK 0x20000000
+#define B44_FLAG_TX_RING_HACK 0x40000000
u32 rx_offset;
--
John W. Linville
linville@tuxdriver.com
^ permalink raw reply
* [PATCH 2.6.13-rc1 0/17] bonding: Sysfs Support
From: Radheka Godse @ 2005-07-01 20:22 UTC (permalink / raw)
To: fubar, bonding-devel; +Cc: netdev
This patch set is an updated sysfs bonding patch to the one sent
previously in April. The patch is upto date with all recent bonding
and kernel changes and applies cleanly to linux-2.6.13-rc1. It adds
sysfs entry for the "Xmit Hash Policy" for new bonding module param;
incorporates feedback and bug fixes on all known issues and has been
tested on linux-2.6.13-rc1.
The interface is pretty simple. Here are some notes on how it could be
used:
The file /sys/class/net/bonding_masters contains the names of all the
active bonds. To add or remove bonds, write a whitespace-delimited list of
interface names to this file. For example:
echo "bond1 bond2 bond3" > /sys/class/net/bonding_masters
will create three bonds with the given names. If any other bonds exist,
they will be deleted.
echo "bond0 bond2 bond3" > /sys/class/net/bonding_masters
would then create bond0 and remove bond1.
For each bond, there is a directory /sys/class/net/<bondname>/bonding.
In this directory are a number of files which control the bond. The names
of these files match the existing module parameters and do the same
things.
The slaves file contains a whitespace-delimited list of interface names,
which are slaves to the bond. This file behaves much the same as the
"bonding_masters" file; just write a list of your desired interfaces to
this file.
Likewise, the arp_targets file contains a whitespace-delimited list of
IP addresses and should be written to in a similar fashion.
The other files contain single values(numeric and/or mnemonic).
Some caveats:
- slaves can only be assigned when the interface is up
- mode can only be changed when the interface is down
- Xmit hash policy can be changed only when interface is down
Warnings and status messages will be logged and can be viewed with dmesg.
Example:
modprobe bonding
echo "bond0 bond1" > /sys/class/net/bonding_masters
echo "6" > /sys/class/net/bond0/bonding/mode
echo "1000" > /sys/class/net/bond0/bonding/miimon
ifconfig bond0 192.168.0.1
echo "eth0 eth1" > /sys/class/net/bond0/bonding/slaves
# bond0 is now ready to use
echo "1" > /sys/class/net/bond1/bonding/mode
# ... and so on for bond1
These patches were generated against 2.6.12 with Jay's upstream patches.
It applies cleanly to kernel 2.6.13-rc1.
- Radheka Godse
- Mitch Williams
^ permalink raw reply
* [PATCH 2.6.13-rc1 1/17] bonding: make some functions not static
From: Radheka Godse @ 2005-07-01 20:29 UTC (permalink / raw)
To: fubar, bonding-devel; +Cc: netdev
This patch prepares for adding sysfs functionality to bonding by making
some functions in bond_main non-static and adding protos into the header.
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bonding.h linux-2.6.12post-sysfs/drivers/net/bonding/bonding.h
--- linux-2.6.12post/drivers/net/bonding/bonding.h 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bonding.h 2005-06-30 13:58:27.000000000 -0700
@@ -255,6 +255,17 @@
struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
+void bond_deinit(struct net_device *bond_dev);
+int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
+int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev);
+void bond_mii_monitor(struct net_device *bond_dev);
+void bond_loadbalance_arp_mon(struct net_device *bond_dev);
+void bond_activebackup_arp_mon(struct net_device *bond_dev);
+void bond_set_mode_ops(struct bonding *bond, int mode);
+int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl);
+const char *bond_mode_name(int mode);
+void bond_select_active_slave(struct bonding *bond);
+void bond_change_active_slave(struct bonding *bond, struct slave *new_active);
#endif /* _LINUX_BONDING_H */
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_main.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c
--- linux-2.6.12post/drivers/net/bonding/bond_main.c 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c 2005-06-30 13:53:55.000000000 -0700
@@ -1453,7 +1453,7 @@
*
* Warning: Caller must hold curr_slave_lock for writing.
*/
-static void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
+void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
{
struct slave *old_active = bond->curr_active_slave;
@@ -1527,7 +1527,7 @@
*
* Warning: Caller must hold curr_slave_lock for writing.
*/
-static void bond_select_active_slave(struct bonding *bond)
+void bond_select_active_slave(struct bonding *bond)
{
struct slave *best_slave;
@@ -1595,7 +1595,7 @@
/*---------------------------------- IOCTL ----------------------------------*/
-static int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev)
+int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev)
{
dprintk("bond_dev=%p\n", bond_dev);
dprintk("slave_dev=%p\n", slave_dev);
@@ -2030,7 +2030,7 @@
* for Bonded connections:
* The first up interface should be left on and all others downed.
*/
-static int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
+int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
{
struct bonding *bond = bond_dev->priv;
struct slave *slave, *oldcurrent;
@@ -2479,7 +2479,7 @@
/*-------------------------------- Monitoring -------------------------------*/
/* this function is called regularly to monitor each slave's link. */
-static void bond_mii_monitor(struct net_device *bond_dev)
+void bond_mii_monitor(struct net_device *bond_dev)
{
struct bonding *bond = bond_dev->priv;
struct slave *slave, *oldcurrent;
@@ -2904,7 +2904,7 @@
* arp is transmitted to generate traffic. see activebackup_arp_monitor for
* arp monitoring in active backup mode.
*/
-static void bond_loadbalance_arp_mon(struct net_device *bond_dev)
+void bond_loadbalance_arp_mon(struct net_device *bond_dev)
{
struct bonding *bond = bond_dev->priv;
struct slave *slave, *oldcurrent;
@@ -3042,7 +3042,7 @@
* may have received.
* see loadbalance_arp_monitor for arp monitoring in load balancing mode
*/
-static void bond_activebackup_arp_mon(struct net_device *bond_dev)
+void bond_activebackup_arp_mon(struct net_device *bond_dev)
{
struct bonding *bond = bond_dev->priv;
struct slave *slave;
@@ -4484,7 +4484,7 @@
/*
* set bond mode specific net device operations
*/
-static inline void bond_set_mode_ops(struct bonding *bond, int mode)
+void bond_set_mode_ops(struct bonding *bond, int mode)
{
struct net_device *bond_dev = bond->dev;
@@ -4603,7 +4603,7 @@
/* De-initialize device specific data.
* Caller must hold rtnl_lock.
*/
-static inline void bond_deinit(struct net_device *bond_dev)
+void bond_deinit(struct net_device *bond_dev)
{
struct bonding *bond = bond_dev->priv;
@@ -4639,7 +4639,7 @@
* Convert string input module parms. Accept either the
* number of the mode or its string name.
*/
-static inline int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl)
+int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl)
{
int i;
^ permalink raw reply
* [PATCH 2.6.13-rc1 1/17] bonding: make some functions not static
From: Radheka Godse @ 2005-07-01 20:36 UTC (permalink / raw)
To: fubar, bonding-devel; +Cc: netdev
This patch prepares for adding sysfs functionality to bonding by making
some functions in bond_main non-static and adding protos into the header.
Signed-off-by: Radheka Godse <radheka.godse@intel.com>
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bonding.h linux-2.6.12post-sysfs/drivers/net/bonding/bonding.h
--- linux-2.6.12post/drivers/net/bonding/bonding.h 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bonding.h 2005-06-30 13:58:27.000000000 -0700
@@ -255,6 +255,17 @@
struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
+void bond_deinit(struct net_device *bond_dev);
+int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
+int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev);
+void bond_mii_monitor(struct net_device *bond_dev);
+void bond_loadbalance_arp_mon(struct net_device *bond_dev);
+void bond_activebackup_arp_mon(struct net_device *bond_dev);
+void bond_set_mode_ops(struct bonding *bond, int mode);
+int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl);
+const char *bond_mode_name(int mode);
+void bond_select_active_slave(struct bonding *bond);
+void bond_change_active_slave(struct bonding *bond, struct slave *new_active);
#endif /* _LINUX_BONDING_H */
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_main.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c
--- linux-2.6.12post/drivers/net/bonding/bond_main.c 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c 2005-06-30 13:53:55.000000000 -0700
@@ -1453,7 +1453,7 @@
*
* Warning: Caller must hold curr_slave_lock for writing.
*/
-static void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
+void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
{
struct slave *old_active = bond->curr_active_slave;
@@ -1527,7 +1527,7 @@
*
* Warning: Caller must hold curr_slave_lock for writing.
*/
-static void bond_select_active_slave(struct bonding *bond)
+void bond_select_active_slave(struct bonding *bond)
{
struct slave *best_slave;
@@ -1595,7 +1595,7 @@
/*---------------------------------- IOCTL ----------------------------------*/
-static int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev)
+int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev)
{
dprintk("bond_dev=%p\n", bond_dev);
dprintk("slave_dev=%p\n", slave_dev);
@@ -2030,7 +2030,7 @@
* for Bonded connections:
* The first up interface should be left on and all others downed.
*/
-static int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
+int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
{
struct bonding *bond = bond_dev->priv;
struct slave *slave, *oldcurrent;
@@ -2479,7 +2479,7 @@
/*-------------------------------- Monitoring -------------------------------*/
/* this function is called regularly to monitor each slave's link. */
-static void bond_mii_monitor(struct net_device *bond_dev)
+void bond_mii_monitor(struct net_device *bond_dev)
{
struct bonding *bond = bond_dev->priv;
struct slave *slave, *oldcurrent;
@@ -2904,7 +2904,7 @@
* arp is transmitted to generate traffic. see activebackup_arp_monitor for
* arp monitoring in active backup mode.
*/
-static void bond_loadbalance_arp_mon(struct net_device *bond_dev)
+void bond_loadbalance_arp_mon(struct net_device *bond_dev)
{
struct bonding *bond = bond_dev->priv;
struct slave *slave, *oldcurrent;
@@ -3042,7 +3042,7 @@
* may have received.
* see loadbalance_arp_monitor for arp monitoring in load balancing mode
*/
-static void bond_activebackup_arp_mon(struct net_device *bond_dev)
+void bond_activebackup_arp_mon(struct net_device *bond_dev)
{
struct bonding *bond = bond_dev->priv;
struct slave *slave;
@@ -4484,7 +4484,7 @@
/*
* set bond mode specific net device operations
*/
-static inline void bond_set_mode_ops(struct bonding *bond, int mode)
+void bond_set_mode_ops(struct bonding *bond, int mode)
{
struct net_device *bond_dev = bond->dev;
@@ -4603,7 +4603,7 @@
/* De-initialize device specific data.
* Caller must hold rtnl_lock.
*/
-static inline void bond_deinit(struct net_device *bond_dev)
+void bond_deinit(struct net_device *bond_dev)
{
struct bonding *bond = bond_dev->priv;
@@ -4639,7 +4639,7 @@
* Convert string input module parms. Accept either the
* number of the mode or its string name.
*/
-static inline int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl)
+int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl)
{
int i;
^ permalink raw reply
* [PATCH 2.6.13-rc1 2/17] bonding: split bond creation into new function
From: Radheka Godse @ 2005-07-01 20:38 UTC (permalink / raw)
To: fubar, bonding-devel; +Cc: netdev
This patch moves the work of creating a new bond into a separate function,
instead of being inline in bonding_init. This function is non-static and
proto is added to the header, for use by the sysfs interface.
Signed-off-by: Radheka Godse <radheka.godse@intel.com>
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bonding.h linux-2.6.12post-sysfs/drivers/net/bonding/bonding.h
--- linux-2.6.12post/drivers/net/bonding/bonding.h 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bonding.h 2005-06-30 13:58:27.000000000 -0700
@@ -255,6 +255,7 @@
struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
+int bond_create(char *name, struct bond_params *params, struct bonding **newbond);
void bond_deinit(struct net_device *bond_dev);
int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev);
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_main.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c
--- linux-2.6.12post/drivers/net/bonding/bond_main.c 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c 2005-06-30 13:53:55.000000000 -0700
@@ -555,6 +555,7 @@
static char *xmit_hash_policy = NULL;
static int arp_interval = BOND_LINK_ARP_INTERV;
static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
+struct bond_params bonding_defaults;
module_param(max_bonds, int, 0);
MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
@@ -4530,12 +4531,10 @@
* Does not allocate but creates a /proc entry.
* Allowed to fail.
*/
-static int __init bond_init(struct net_device *bond_dev, struct bond_params *params)
+static int bond_init(struct net_device *bond_dev, struct bond_params *params)
{
struct bonding *bond = bond_dev->priv;
- dprintk("Begin bond_init for %s\n", bond_dev->name);
-
/* initialize rwlocks */
rwlock_init(&bond->lock);
rwlock_init(&bond->curr_slave_lock);
@@ -4919,61 +5025,81 @@
return 0;
}
+/* Create a new bond based on the specified name and bonding parameters.
+ * Caller must NOT hold rtnl_lock; we need to release it here before we
+ * set up our sysfs entries.
+ */
+int bond_create(char *name, struct bond_params *params, struct bonding **newbond)
+{
+ struct net_device *bond_dev;
+ int res;
+
+ rtnl_lock();
+ bond_dev = alloc_netdev(sizeof(struct bonding), name, ether_setup);
+ if (!bond_dev) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: eek! can't alloc netdev!\n",
+ name);
+ res = -ENOMEM;
+ goto out_rtnl;
+ }
+
+ /* bond_init() must be called after dev_alloc_name() (for the
+ * /proc files), but before register_netdevice(), because we
+ * need to set function pointers.
+ */
+
+ res = bond_init(bond_dev, params);
+ if (res < 0) {
+ goto out_netdev;
+ }
+
+ SET_MODULE_OWNER(bond_dev);
+
+ res = register_netdevice(bond_dev);
+ if (res < 0) {
+ goto out_bond;
+ }
+ if (newbond)
+ *newbond = bond_dev->priv;
+
+ rtnl_unlock(); /* allows sysfs registration of net device */
+ res = bond_create_sysfs_entry(bond_dev->priv);
+ goto done;
+out_bond:
+ bond_deinit(bond_dev);
+out_netdev:
+ free_netdev(bond_dev);
+out_rtnl:
+ rtnl_unlock();
+done:
+ return res;
+}
+
static int __init bonding_init(void)
{
- struct bond_params params;
int i;
int res;
+ char new_bond_name[8]; /* Enough room for 999 bonds at init. */
printk(KERN_INFO "%s", version);
- res = bond_check_params(¶ms);
+ res = bond_check_params(&bonding_defaults);
if (res) {
- return res;
+ goto out;
}
- rtnl_lock();
-
#ifdef CONFIG_PROC_FS
bond_create_proc_dir();
#endif
for (i = 0; i < max_bonds; i++) {
- struct net_device *bond_dev;
-
- bond_dev = alloc_netdev(sizeof(struct bonding), "", ether_setup);
- if (!bond_dev) {
- res = -ENOMEM;
- goto out_err;
- }
-
- res = dev_alloc_name(bond_dev, "bond%d");
- if (res < 0) {
- free_netdev(bond_dev);
- goto out_err;
- }
-
- /* bond_init() must be called after dev_alloc_name() (for the
- * /proc files), but before register_netdevice(), because we
- * need to set function pointers.
- */
- res = bond_init(bond_dev, ¶ms);
- if (res < 0) {
- free_netdev(bond_dev);
- goto out_err;
- }
-
- SET_MODULE_OWNER(bond_dev);
-
- res = register_netdevice(bond_dev);
- if (res < 0) {
- bond_deinit(bond_dev);
- free_netdev(bond_dev);
- goto out_err;
- }
+ sprintf(new_bond_name, "bond%d",i);
+ res = bond_create(new_bond_name,&bonding_defaults, NULL);
+ if (res)
+ goto err;
}
- rtnl_unlock();
register_netdevice_notifier(&bond_netdev_notifier);
register_inetaddr_notifier(&bond_inetaddr_notifier);
^ permalink raw reply
* [PATCH 2.6.13-rc1 3/17] bonding: export some structs to bonding.h
From: Radheka Godse @ 2005-07-01 20:39 UTC (permalink / raw)
To: fubar, bonding-devel; +Cc: netdev
This patch exposes some data structures for use by the sysfs interface.
Signed-off-by: Radheka Godse <radheka.godse@intel.com>
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bonding.h linux-2.6.12post-sysfs/drivers/net/bonding/bonding.h
--- linux-2.6.12post/drivers/net/bonding/bonding.h 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bonding.h 2005-06-30 13:58:27.000000000 -0700
@@ -152,6 +152,11 @@
u32 arp_targets[BOND_MAX_ARP_TARGETS];
};
+struct bond_parm_tbl {
+ char *modename;
+ int mode;
+};
+
struct vlan_entry {
struct list_head vlan_list;
u32 vlan_ip;
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_main.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c
--- linux-2.6.12post/drivers/net/bonding/bond_main.c 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c 2005-06-30 13:53:55.000000000 -0700
@@ -585,7 +585,7 @@
static const char *version =
DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n";
-static LIST_HEAD(bond_dev_list);
+LIST_HEAD(bond_dev_list);
#ifdef CONFIG_PROC_FS
static struct proc_dir_entry *bond_proc_dir = NULL;
@@ -604,18 +604,14 @@
* command comes from an application using
* another ABI version.
*/
-struct bond_parm_tbl {
- char *modename;
- int mode;
-};
-static struct bond_parm_tbl bond_lacp_tbl[] = {
+struct bond_parm_tbl bond_lacp_tbl[] = {
{ "slow", AD_LACP_SLOW},
{ "fast", AD_LACP_FAST},
{ NULL, -1},
};
-static struct bond_parm_tbl bond_mode_tbl[] = {
+struct bond_parm_tbl bond_mode_tbl[] = {
{ "balance-rr", BOND_MODE_ROUNDROBIN},
{ "active-backup", BOND_MODE_ACTIVEBACKUP},
{ "balance-xor", BOND_MODE_XOR},
@@ -626,7 +622,7 @@
{ NULL, -1},
};
-static struct bond_parm_tbl xmit_hashtype_tbl[] = {
+struct bond_parm_tbl xmit_hashtype_tbl[] = {
{ "layer2", BOND_XMIT_POLICY_LAYER2},
{ "layer3+4", BOND_XMIT_POLICY_LAYER34},
{ NULL, -1},
@@ -634,12 +630,11 @@
/*-------------------------- Forward declarations ---------------------------*/
-static inline void bond_set_mode_ops(struct bonding *bond, int mode);
static void bond_send_gratuitous_arp(struct bonding *bond);
/*---------------------------- General routines -----------------------------*/
-static const char *bond_mode_name(int mode)
+const char *bond_mode_name(int mode)
{
switch (mode) {
case BOND_MODE_ROUNDROBIN :
^ permalink raw reply
* [PATCH 2.6.13-rc1 4/17] bonding: return pointer to slave from enslave
From: Radheka Godse @ 2005-07-01 20:41 UTC (permalink / raw)
To: fubar, bonding-devel; +Cc: netdev
This patch changes the bond_enslave function so that it (optionally)
returns a pointer tothe slave struct for a new slave. This
functionality is not used by the existing ioctl interface, but will be
used by the sysfs interface.
This function is also made non-static and a proto is placed in the header.
Signed-off-by: Radheka Godse <radheka.godse@intel.com>
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bonding.h linux-2.6.12post-sysfs/drivers/net/bonding/bonding.h
--- linux-2.6.12post/drivers/net/bonding/bonding.h 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bonding.h 2005-06-30 13:58:27.000000000 -0700
@@ -262,6 +262,7 @@
int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
int bond_create(char *name, struct bond_params *params, struct bonding **newbond);
void bond_deinit(struct net_device *bond_dev);
+int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev, struct slave **vassal);
int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev);
void bond_mii_monitor(struct net_device *bond_dev);
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_main.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c
--- linux-2.6.12post/drivers/net/bonding/bond_main.c 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c 2005-06-30 13:53:55.000000000 -0700
@@ -1601,7 +1601,7 @@
}
/* enslave device <slave> to bond device <master> */
-static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
+int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev, struct slave **vassal)
{
struct bonding *bond = bond_dev->priv;
struct slave *new_slave = NULL;
@@ -1992,6 +1992,8 @@
new_slave->link != BOND_LINK_DOWN ? "n up" : " down");
/* enslave is successful */
+ if (vassal)
+ *vassal=new_slave;
return 0;
/* Undo stages on error */
@@ -4049,6 +4051,7 @@
return -EINVAL;
}
+ down_write(&(bonding_rwsem));
slave_dev = dev_get_by_name(ifr->ifr_slave);
dprintk("slave_dev=%p: \n", slave_dev);
@@ -4060,7 +4063,7 @@
switch (cmd) {
case BOND_ENSLAVE_OLD:
case SIOCBONDENSLAVE:
- res = bond_enslave(bond_dev, slave_dev);
+ res = bond_enslave(bond_dev, slave_dev, NULL);
break;
case BOND_RELEASE_OLD:
case SIOCBONDRELEASE:
^ permalink raw reply
* [PATCH 2.6.13-rc1 5/17] bonding: reset RLB flag during ALB init
From: Radheka Godse @ 2005-07-01 20:43 UTC (permalink / raw)
To: fubar, bonding-devel; +Cc: netdev
This patch makes the ALB init function explicitly clear the RLB flag if
RLB is not used. This is required by the sysfs interfaces, which allows
the user to change mode without destroying the bond.
Signed-off-by: Radheka Godse <radheka.godse@intel.com>
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_alb.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_alb.c
--- linux-2.6.12post/drivers/net/bonding/bond_alb.c 2005-06-17 12:48:29.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_alb.c 2005-06-28 18:21:35.000000000 -0700
@@ -1256,6 +1256,8 @@
tlb_deinitialize(bond);
return res;
}
+ } else {
+ bond->alb_info.rlb_enabled = 0;
}
return 0;
^ permalink raw reply
* [PATCH 2.6.13-rc1 6/17] bonding: ALB init kmalloc inside spinlock bugfix
From: Radheka Godse @ 2005-07-01 20:45 UTC (permalink / raw)
To: fubar, bonding-devel; +Cc: netdev
This patch corrects bug in ALB init where kmalloc called inside a held
lock causes stacdump in debug mode
Signed-off-by: Radheka Godse <radheka.godse@intel.com>
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_alb.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_alb.c
--- linux-2.6.12post/drivers/net/bonding/bond_alb.c 2005-06-17 12:48:29.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_alb.c 2005-06-28 18:21:35.000000000 -0700
@@ -198,20 +198,21 @@
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
int size = TLB_HASH_TABLE_SIZE * sizeof(struct tlb_client_info);
+ struct tlb_client_info *new_hashtbl;
int i;
spin_lock_init(&(bond_info->tx_hashtbl_lock));
- _lock_tx_hashtbl(bond);
-
- bond_info->tx_hashtbl = kmalloc(size, GFP_KERNEL);
- if (!bond_info->tx_hashtbl) {
+ new_hashtbl = kmalloc(size, GFP_KERNEL);
+ if (!new_hashtbl) {
printk(KERN_ERR DRV_NAME
": Error: %s: Failed to allocate TLB hash table\n",
bond->dev->name);
- _unlock_tx_hashtbl(bond);
return -1;
}
+ _lock_tx_hashtbl(bond);
+
+ bond_info->tx_hashtbl = new_hashtbl;
memset(bond_info->tx_hashtbl, 0, size);
@@ -798,21 +801,22 @@
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
struct packet_type *pk_type = &(BOND_ALB_INFO(bond).rlb_pkt_type);
+ struct rlb_client_info *new_hashtbl;
int size = RLB_HASH_TABLE_SIZE * sizeof(struct rlb_client_info);
int i;
spin_lock_init(&(bond_info->rx_hashtbl_lock));
- _lock_rx_hashtbl(bond);
-
- bond_info->rx_hashtbl = kmalloc(size, GFP_KERNEL);
- if (!bond_info->rx_hashtbl) {
+ new_hashtbl = kmalloc(size, GFP_KERNEL);
+ if (!new_hashtbl) {
printk(KERN_ERR DRV_NAME
": Error: %s: Failed to allocate RLB hash table\n",
bond->dev->name);
- _unlock_rx_hashtbl(bond);
return -1;
}
+ _lock_rx_hashtbl(bond);
+
+ bond_info->rx_hashtbl = new_hashtbl;
bond_info->rx_hashtbl_head = RLB_NULL_INDEX;
^ permalink raw reply
* Re: [PATCH] multipath routing algorithm, better patch
From: Thomas Graf @ 2005-07-01 20:46 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Patrick Jenkins, linux-kernel, Maillist netdev
In-Reply-To: <42C59ABA.1070305@trash.net>
* Patrick McHardy <42C59ABA.1070305@trash.net> 2005-07-01 21:34
> So its no problem but simply missing support. BTW, do you know if
> Stephen's new CVS repository is exported somewhere?
cvs -d :pserver:cvsanon@developer.osdl.org/repos cvs login
cvs -d :pserver:cvsanon@developer.osdl.org/repos cvs co iproute2
^ permalink raw reply
* [PATCH 2.6.13-rc1 7/17] bonding: make sysfs consistent with ifenslave behavior
From: Radheka Godse @ 2005-07-01 20:47 UTC (permalink / raw)
To: fubar, bonding-devel; +Cc: netdev
For consistency with ifenslave, instead of exiting with an error, updated
bonding sysfs to close and attempt to enslave an up adapter.
Signed-off-by: Radheka Godse <radheka.godse@intel.com>
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_main.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c
--- linux-2.6.12post/drivers/net/bonding/bond_main.c 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c 2005-06-30 13:53:55.000000000 -0700
@@ -1665,10 +1665,19 @@
*/
if ((slave_dev->flags & IFF_UP)) {
printk(KERN_ERR DRV_NAME
- ": Error: %s is up\n",
- slave_dev->name);
+ ": %s: Warning: %s is up. Closing it "
+ "before adding to the bond.\n",
+ bond_dev->name, slave_dev->name);
res = -EPERM;
- goto err_undo_flags;
+ res = dev_close(slave_dev);
+ if (res)
+ {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Error: Failed to close %s.\n",
+ bond_dev->name, slave_dev->name);
+ res = -EPERM;
+ goto err_undo_flags;
+ }
}
if (slave_dev->set_mac_address == NULL) {
^ permalink raw reply
* [PATCH 2.6.13-rc1 8/17] bonding: SYSFS INTERFACE (large)
From: Radheka Godse @ 2005-07-01 20:48 UTC (permalink / raw)
To: fubar, bonding-devel; +Cc: netdev
This large patch adds the sysfs interface to channel bonding. It will
allow users to add and remove bonds, add and remove slaves, and change
all bonding parameters without using ifenslave.
The ifenslave interface still works.
Signed-off-by: Radheka Godse <radheka.godse@intel.com>
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bonding.h linux-2.6.12post-sysfs/drivers/net/bonding/bonding.h
--- linux-2.6.12post/drivers/net/bonding/bonding.h 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bonding.h 2005-06-30 13:58:27.000000000 -0700
@@ -37,6 +37,7 @@
#include <linux/timer.h>
#include <linux/proc_fs.h>
#include <linux/if_bonding.h>
+#include <linux/kobject.h>
#include "bond_3ad.h"
#include "bond_alb.h"
@@ -262,6 +259,13 @@
int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
int bond_create(char *name, struct bond_params *params, struct bonding **newbond);
void bond_deinit(struct net_device *bond_dev);
+int bond_create_sysfs(void);
+void bond_destroy_sysfs(void);
+void bond_destroy_sysfs_entry(struct bonding *bond);
+int bond_create_sysfs_entry(struct bonding *bond);
+int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave);
+void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave);
+int bond_check_abi_ver(void);
int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev, struct slave **vassal);
int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev);
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_main.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c
--- linux-2.6.12post/drivers/net/bonding/bond_main.c 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c 2005-06-30 13:53:55.000000000 -0700
@@ -591,6 +591,7 @@
static struct proc_dir_entry *bond_proc_dir = NULL;
#endif
+extern struct rw_semaphore bonding_rwsem;
static u32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ;
static int arp_ip_count = 0;
static int bond_mode = BOND_MODE_ROUNDROBIN;
@@ -1994,6 +1994,9 @@
}
}
+ res = bond_create_slave_symlinks(bond_dev, slave_dev);
+ if (res)
+ goto err_unset_master;
printk(KERN_INFO DRV_NAME
": %s: enslaving %s as a%s interface with a%s link.\n",
bond_dev->name, slave_dev->name,
@@ -2165,6 +2176,9 @@
write_unlock_bh(&bond->lock);
+ /* must do this from outside any spinlocks */
+ bond_destroy_slave_symlinks(bond_dev, slave_dev);
+
bond_del_vlans_from_slave(bond, slave_dev);
/* If the mode USES_PRIMARY, then we should only remove its
@@ -2256,6 +2263,7 @@
*/
write_unlock_bh(&bond->lock);
+ bond_destroy_slave_symlinks(bond_dev, slave_dev);
bond_del_vlans_from_slave(bond, slave_dev);
/* If the mode USES_PRIMARY, then we should only remove its
@@ -2436,6 +2444,22 @@
}
}
+int bond_check_abi_ver(void)
+{
+ int retval = 1;
+
+ if (orig_app_abi_ver == -1) {
+ orig_app_abi_ver = BOND_ABI_VERSION;
+ app_abi_ver = BOND_ABI_VERSION;
+ }
+ else {
+ if (app_abi_ver == 0)
+ retval = 0;
+ }
+
+ return retval;
+}
+
static int bond_info_query(struct net_device *bond_dev, struct ifbond *info)
{
struct bonding *bond = bond_dev->priv;
@@ -3569,7 +3593,10 @@
bond_remove_proc_entry(bond);
bond_create_proc_entry(bond);
#endif
-
+ down_write(&(bonding_rwsem));
+ bond_destroy_sysfs_entry(bond);
+ bond_create_sysfs_entry(bond);
+ up_write(&(bonding_rwsem));
return NOTIFY_DONE;
}
@@ -4101,6 +4128,7 @@
orig_app_abi_ver = prev_abi_ver;
}
+ up_write(&(bonding_rwsem));
return res;
}
@@ -5000,18 +4990,22 @@
goto err;
}
+ res = bond_create_sysfs();
+ if (res)
+ goto err;
+
register_netdevice_notifier(&bond_netdev_notifier);
register_inetaddr_notifier(&bond_inetaddr_notifier);
- return 0;
-
-out_err:
- /* free and unregister all bonds that were successfully added */
+ goto out;
+err:
+ rtnl_lock();
bond_free_all();
-
+ bond_destroy_sysfs();
rtnl_unlock();
-
+out:
return res;
+
}
static void __exit bonding_exit(void)
@@ -5021,6 +5053,7 @@
rtnl_lock();
bond_free_all();
+ bond_destroy_sysfs();
rtnl_unlock();
}
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_sysfs.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_sysfs.c
--- linux-2.6.12post/drivers/net/bonding/bond_sysfs.c 1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_sysfs.c 2005-06-30 13:54:22.000000000 -0700
@@ -0,0 +1,1493 @@
+
+/*
+ * Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ *
+ * Changes:
+ *
+ * 2004/12/12 - Mitch Williams <mitch.a.williams at intel dot com>
+ * - Initial creation of sysfs interface.
+ *
+ * 2005/06/22 - Radheka Godse <radheka.godse at intel dot com>
+ * - Added ifenslave -c type functionality to sysfs
+ * - Added sysfs files for attributes such as MII Status and
+ * 802.3ad aggregator that are displayed in /proc
+ * - Added "name value" format to sysfs "mode" and
+ * "lacp_rate", for e.g., "active-backup 1" or "slow 0" for
+ * consistency and ease of script parsing
+ * - Fixed reversal of octets in arp_ip_targets via sysfs
+ * - sysfs support to handle bond interface re-naming
+ * - Moved all sysfs entries into /sys/class/net instead of
+ * of using a standalone subsystem.
+ * - Added sysfs symlinks between masters and slaves
+ * - Corrected bugs in sysfs unload path when creating bonds
+ * with existing interface names.
+ * - Removed redundant sysfs stat file since it duplicates slave info
+ * from the proc file
+ * - Fixed errors in sysfs show/store arp targets.
+ * - For consistency with ifenslave, instead of exiting
+ * with an error, updated bonding sysfs to
+ * close and attempt to enslave an up adapter.
+ * - Fixed NULL dereference when adding a slave interface
+ * that does not exist.
+ * - Added checks in sysfs bonding to reject invalid ip addresses
+ * - Synch up with post linux-2.6.12 bonding changes
+ * - Created sysfs bond attrib for xmit_hash_policy
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/in.h>
+#include <linux/sysfs.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/inet.h>
+#include <linux/rtnetlink.h>
+
+/* #define BONDING_DEBUG 1 */
+#include "bonding.h"
+#define to_class_dev(obj) container_of(obj,struct class_device,kobj)
+#define to_net_dev(class) container_of(class, struct net_device, class_dev)
+#define to_bond(cd) ((struct bonding *)(to_net_dev(cd)->priv))
+
+/*---------------------------- Declarations -------------------------------*/
+
+/* Macros for real simple parsing of text. */
+#define eat_nonalnum(str,whence,max) \
+ while (whence < max) {if (!isalnum(str[whence])) whence++; else break;};
+#define find_next_nonalpha(str,whence,max) \
+ while (whence < max) {if (isalnum(str[whence])) whence++; else break;};
+
+extern struct list_head bond_dev_list;
+extern struct bond_params bonding_defaults;
+extern struct bond_parm_tbl bond_mode_tbl[];
+extern struct bond_parm_tbl bond_lacp_tbl[];
+extern struct bond_parm_tbl xmit_hashtype_tbl[];
+
+static struct class *netdev_class;
+/*--------------------------- Data Structures -----------------------------*/
+
+/* Bonding sysfs lock. Why can't we just use the subsytem lock?
+ * Because kobject_register tries to acquire the subsystem lock. If
+ * we already hold the lock (which we would if the user was creating
+ * a new bond through the sysfs interface), we deadlock.
+ */
+
+struct rw_semaphore bonding_rwsem;
+
+
+
+
+/*------------------------------ Functions --------------------------------*/
+
+/*
+ * "show" function for the bond_masters attribute.
+ * The class parameter is ignored.
+ */
+static ssize_t bonding_show_bonds(struct class *cls, char *buffer)
+{
+ int res = 0;
+ struct bonding *bond;
+
+ down_read(&(bonding_rwsem));
+
+ list_for_each_entry(bond, &bond_dev_list, bond_list) {
+ res += sprintf(buffer + res, "%s ",
+ bond->dev->name);
+ if (res > (PAGE_SIZE - IFNAMSIZ)) {
+ dprintk("eek! too many bonds!\n");
+ break;
+ }
+ }
+ res += sprintf(buffer + res, "\n");
+ res++;
+ up_read(&(bonding_rwsem));
+ return res;
+}
+
+/*
+ * "store" function for the bond_masters attribute. This is what
+ * creates and deletes entire bonds.
+ *
+ * The class parameter is ignored.
+ *
+ * This function uses the eat_nonalnum and eat_alnum macros, define
+ * above. Why not use sscanf()? Scanf can get strings, but can't filter
+ * out inappropriate characters. For example, we can't have bonds named
+ * "foo/bar" or "foo*bar" or "Does this work?" as these aren't valid
+ * filenames. While we could use scanf to get strings and then validate
+ * them, this is quicker.
+ * The above examples give us these results:
+ * "foo/bar" gives two bonds, "foo" and "bar".
+ * "foo*bar" gives two bonds, "foo" and "bar".
+ * "Does this work?" gives three bonds, "Does", "this", and "work".
+ */
+
+static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t count)
+{
+ char name[IFNAMSIZ];
+ int i, res, found, pos = 0;
+ struct bonding *bond;
+ struct bonding *nxt;
+
+ down_write(&(bonding_rwsem));
+ /* First process adds */
+ eat_nonalnum(buffer, pos, count);
+ /* Pos now points to the first alpha character. */
+ i = pos;
+ find_next_nonalpha(buffer, i, count);
+ /* i now points to the next character past the end of the bond name. */
+ if (i - pos >= IFNAMSIZ) {
+ printk(KERN_ERR DRV_NAME "Interface name %.*s too large! Ignoring.\n",
+ i - pos, buffer + pos);
+ up_write(&(bonding_rwsem));
+ return -EPERM;
+ }
+ /* Copy the bond name so we can deal with it separately. */
+ strncpy(name, buffer + pos, i - pos);
+ /* Don't forget the null terminator! */
+ name[i - pos] = 0;
+ while (strlen(name)) {
+ /* Got a bond name in name. Is it already in the list? */
+ found = 0;
+ list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) {
+ if (strnicmp(bond->dev->name, name, IFNAMSIZ) == 0) {
+ /* Temporarily set a meaningless flag. When
+ * we get done with the loop, we'll check all of these.
+ * If the bond doesn't have this flag set, then we need
+ * to remove the bond. If the flag has it set, then
+ * we can just clear the flag.
+ */
+ bond->flags |= IFF_DYNAMIC;
+ found = 1;
+ break; /* Found it, so go to next name */
+ }
+ }
+ if (found == 0) {
+ printk(KERN_INFO DRV_NAME ": %s is being created...\n", name);
+ res = bond_create(name, &bonding_defaults, &bond);
+ if (res) {
+ up_write(&(bonding_rwsem));
+ printk(KERN_INFO DRV_NAME ": %s interface already exists. Bond creation failed.\n", name);
+ return res;
+ }
+ printk(KERN_INFO DRV_NAME ": %s created.\n", name);
+ /* Set the flag so we don't delete
+ * this interface in the loop below.
+ */
+ bond->flags |= IFF_DYNAMIC;
+ }
+ /* Scan for the next name. i still has the location of
+ * the char just past the end of the last name we handled.
+ */
+ pos = i;
+ eat_nonalnum(buffer, pos, count);
+ i = pos;
+ find_next_nonalpha(buffer, i, count);
+ if (i - pos >= IFNAMSIZ) {
+ printk(KERN_ERR DRV_NAME
+ ": %.*s interface name too large! Ignoring.\n",
+ i - pos, buffer + pos);
+ up_write(&(bonding_rwsem));
+ return -EPERM;
+ }
+ strncpy(name, buffer + pos, i - pos);
+ name[i - pos] = 0;
+ } /* end of while loop and end of input */
+
+ /* Now we do deletes. Walk through the list, and check to see
+ * if the flag didn't get set. If it's set, clear it. If it's
+ * not set, delete the bond.
+ */
+ list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) {
+ if (bond->flags & IFF_DYNAMIC) {
+ bond->flags &= ~IFF_DYNAMIC;
+ } else {
+ printk(KERN_INFO DRV_NAME ": %s is being deleted...\n", bond->dev->name);
+ rtnl_lock();
+ unregister_netdevice(bond->dev);
+ bond_deinit(bond->dev);
+ bond_destroy_sysfs_entry(bond);
+ rtnl_unlock();
+ printk(KERN_INFO DRV_NAME ": %s deleted.\n", bond->dev->name);
+ }
+ }
+ /* Always return either count or an error. If you return 0, you'll
+ * get called forever, which is bad.
+ */
+ up_write(&(bonding_rwsem));
+ return count;
+}
+/* class attribute for bond_masters file. This ends up in /sys/class/net */
+static CLASS_ATTR(bonding_masters, S_IWUSR | S_IRUGO,
+ bonding_show_bonds, bonding_store_bonds);
+
+int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave)
+{
+ char linkname[IFNAMSIZ+7];
+ int ret = 0;
+
+ /* first, create a link from the slave back to the master */
+ ret = sysfs_create_link(&(slave->class_dev.kobj), &(master->class_dev.kobj),
+ "master");
+ if (ret)
+ return ret;
+ /* next, create a link from the master to the slave */
+ sprintf(linkname,"slave_%s",slave->name);
+ ret = sysfs_create_link(&(master->class_dev.kobj), &(slave->class_dev.kobj),
+ linkname);
+ return ret;
+
+}
+
+void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave)
+{
+ char linkname[IFNAMSIZ+7];
+
+ sysfs_remove_link(&(slave->class_dev.kobj), "master");
+ sprintf(linkname,"slave_%s",slave->name);
+ sysfs_remove_link(&(master->class_dev.kobj), linkname);
+}
+
+
+/*
+ * Show the slaves in the current bond.
+ */
+static ssize_t bonding_show_slaves(struct class_device *cd, char *buf)
+{
+ struct slave *slave;
+ int i, res = 0;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+
+ read_lock_bh(&bond->lock);
+ bond_for_each_slave(bond, slave, i) {
+ res += sprintf(buf + res, "%s ", slave->dev->name);
+ if (res > (PAGE_SIZE - IFNAMSIZ)) {
+ dprintk("eek! too many slaves!\n");
+ break;
+ }
+ }
+ read_unlock_bh(&bond->lock);
+ res += sprintf(buf + res, "\n");
+ res++;
+ up_read(&(bonding_rwsem));
+ return res;
+}
+
+/*
+ * Set the slaves in the current bond. The bond interface must be
+ * up for this to succeed.
+ * This function is largely the same flow as bonding_update_bonds().
+ */
+static ssize_t bonding_store_slaves(struct class_device *cd, const char *buffer, size_t count)
+{
+ char name[IFNAMSIZ];
+ int i, j, res, found, pos = 0, ret = count;
+ struct slave *slave;
+ struct net_device *dev = 0;
+ struct bonding *bond = to_bond(cd);
+
+ if (!bond_check_abi_ver())
+ {
+ printk(KERN_ERR DRV_NAME
+ ": Error: your version of ifenslave is incompatible "
+ "with the sysfs interface in this version of bonding. "
+ "Upgrade ifenslave to version 1 or greater and reload "
+ "bonding.\n");
+ return -EINVAL;
+ }
+
+ down_write(&(bonding_rwsem));
+
+ /* Quick sanity check -- is the bond interface up? */
+ if (!(bond->dev->flags & IFF_UP)) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Unable to update slaves because interface is down.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ /* Note: We can't hold bond->lock here, as bond_create grabs it. */
+
+ /* First process adds */
+
+ /* Copy the first name we find. */
+ eat_nonalnum(buffer, pos, count);
+ i = pos;
+ find_next_nonalpha(buffer, i, count);
+ if (i - pos >= IFNAMSIZ) {
+ printk(KERN_ERR DRV_NAME ": %s: Slave name %.*s too large! Ignoring.\n",
+ bond->dev->name,
+ i - pos, buffer + pos);
+ ret = -EPERM;
+ goto out;
+ }
+ strncpy(name, buffer + pos, i - pos);
+ name[i - pos] = 0;
+
+ while (strlen(name)) {
+ /* Got a slave name in name. Is it already there? */
+ found = 0;
+ read_lock_bh(&bond->lock);
+ bond_for_each_slave(bond, slave, j) {
+ if (strnicmp(slave->dev->name, name, IFNAMSIZ) == 0) {
+ /* Temporarily set a meaningless flag. When
+ * we get done with the loop, we'll check all of these.
+ * If the slave doesn't have this flag set, then we need
+ * to remove the slave. If the flag has it set, then
+ * we can just clear the flag.
+ */
+ slave->original_flags |= IFF_DYNAMIC;
+ found = 1;
+ break; /* Found it, so go to next name */
+ }
+ }
+ read_unlock_bh(&bond->lock);
+ if (found == 0) {
+ printk(KERN_INFO DRV_NAME ": %s: Adding slave %s.\n",
+ bond->dev->name, name);
+ dev = dev_get_by_name(name);
+ if (!dev) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Interface %s does not exist!\n",
+ bond->dev->name, name);
+ ret = -EPERM;
+ goto out;
+ }
+ else {
+ dev_put(dev);
+ }
+
+
+ if (dev->flags & IFF_SLAVE) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Interface %s is already enslaved!\n",
+ bond->dev->name, name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ /* If this is the first slave, then we need to set
+ the master's hardware address to be the same as the
+ slave's. */
+ if (!(*((u32 *) & (bond->dev->dev_addr[0])))) {
+ memcpy(bond->dev->dev_addr, dev->dev_addr,
+ dev->addr_len);
+ }
+
+ /* Set the slave's MTU to match the bond */
+ if (dev->mtu != bond->dev->mtu) {
+ if (dev->change_mtu) {
+ res = dev->change_mtu(dev,
+ bond->dev->mtu);
+ if (res) {
+ ret = res;
+ goto out;
+ }
+ } else {
+ dev->mtu = bond->dev->mtu;
+ }
+ }
+ rtnl_lock();
+ res = bond_enslave(bond->dev, dev, &slave);
+ rtnl_unlock();
+ if (res) {
+ ret = res;
+ goto out;
+ }
+ slave->original_flags |= IFF_DYNAMIC;
+ }
+ /* Get the next name in the buffer. */
+ pos = i;
+ eat_nonalnum(buffer, pos, count);
+ i = pos;
+ find_next_nonalpha(buffer, i, count);
+ if (i - pos >= IFNAMSIZ) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Slave name %.*s too large! Ignoring.\n",
+ bond->dev->name, i - pos, buffer + pos);
+ ret = -EPERM;
+ goto out;
+ }
+ strncpy(name, buffer + pos, i - pos);
+ name[i - pos] = 0;
+ } /* End of while loop, and end of input. */
+
+ /* Now handle deletes.
+ * We can't use bond_for_each_slave here because we might modify
+ * the list when we're inside the loop. We can't hold the lock
+ * either because bond_release grabs it.
+ */
+ slave = bond->first_slave;
+ i = bond->slave_cnt;
+ while (i > 0) {
+ BUG_ON(slave == 0);
+ if (slave->original_flags & IFF_DYNAMIC) {
+ slave->original_flags &= ~IFF_DYNAMIC;
+ slave = slave->next;
+ } else {
+ /* Didn't find the name of this slave in the list, so
+ * remove the slave.
+ */
+ printk(KERN_INFO DRV_NAME
+ ": %s: Removing slave %s\n",
+ bond->dev->name,
+ slave->dev->name);
+ dev = slave->dev;
+ slave = slave->next;
+ rtnl_lock();
+ res = bond_release(bond->dev, dev);
+ rtnl_unlock();
+ if (res) {
+ ret = res;
+ goto out;
+ }
+ /* set the slave MTU to the default */
+ if (dev->change_mtu) {
+ dev->change_mtu(dev, 1500);
+ } else {
+ dev->mtu = 1500;
+ }
+ }
+ i--;
+ }
+
+out:
+ up_write(&(bonding_rwsem));
+ return ret;
+}
+static CLASS_DEVICE_ATTR(slaves, S_IRUGO | S_IWUSR, bonding_show_slaves, bonding_store_slaves);
+
+/*
+ * Show and set the bonding mode. The bond interface must be down to
+ * change the mode.
+ */
+static ssize_t bonding_show_mode(struct class_device *cd, char *buf)
+{
+ int count;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ count = sprintf(buf, "%s %d\n",
+ bond_mode_tbl[bond->params.mode].modename,
+ bond->params.mode) + 1;
+ up_read(&(bonding_rwsem));
+ return count;
+}
+
+static ssize_t bonding_store_mode(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+ down_write(&(bonding_rwsem));
+
+ if (bond->dev->flags & IFF_UP) {
+ printk(KERN_ERR DRV_NAME
+ "Unable to update mode of %s because interface is up.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ new_value = bond_parse_parm((char *)buf, bond_mode_tbl);
+ if (new_value < 0) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Ignoring invalid mode value %.*s.\n",
+ bond->dev->name,
+ (int)strlen(buf) - 1, buf);
+ ret = -EINVAL;
+ goto out;
+ } else {
+ bond->params.mode = new_value;
+ bond_set_mode_ops(bond, bond->params.mode);
+ printk(KERN_INFO DRV_NAME ": %s: setting mode to %s (%d).\n",
+ bond->dev->name, bond_mode_tbl[new_value].modename, new_value);
+ }
+out:
+ up_write(&(bonding_rwsem));
+ return ret;
+}
+static CLASS_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, bonding_show_mode, bonding_store_mode);
+
+/*
+ * Show and set the bonding transmit hash method. The bond interface must be down to
+ * change the xmit hash policy.
+ */
+static ssize_t bonding_show_xmit_hash(struct class_device *cd, char *buf)
+{
+ int count;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ if ((bond->params.mode != BOND_MODE_XOR) &&
+ (bond->params.mode != BOND_MODE_8023AD)) {
+ // Not Applicable
+ count = sprintf(buf, "NA\n") + 1;
+ } else {
+ count = sprintf(buf, "%s %d\n",
+ xmit_hashtype_tbl[bond->params.xmit_policy].modename,
+ bond->params.xmit_policy) + 1;
+ }
+ up_read(&(bonding_rwsem));
+
+ return count;
+}
+
+static ssize_t bonding_store_xmit_hash(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+ down_write(&(bonding_rwsem));
+
+ if (bond->dev->flags & IFF_UP) {
+ printk(KERN_ERR DRV_NAME
+ "%s: Interface is up. Unable to update xmit policy.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ if ((bond->params.mode != BOND_MODE_XOR) &&
+ (bond->params.mode != BOND_MODE_8023AD)) {
+ printk(KERN_ERR DRV_NAME
+ "%s: Transmit hash policy is irrelevant in this mode.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ new_value = bond_parse_parm((char *)buf, xmit_hashtype_tbl);
+ if (new_value < 0) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Ignoring invalid xmit hash policy value %.*s.\n",
+ bond->dev->name,
+ (int)strlen(buf) - 1, buf);
+ ret = -EINVAL;
+ goto out;
+ } else {
+ bond->params.xmit_policy = new_value;
+ bond_set_mode_ops(bond, bond->params.mode);
+ printk(KERN_INFO DRV_NAME ": %s: setting xmit hash policy to %s (%d).\n",
+ bond->dev->name, xmit_hashtype_tbl[new_value].modename, new_value);
+ }
+out:
+ up_write(&(bonding_rwsem));
+ return ret;
+}
+static CLASS_DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR, bonding_show_xmit_hash, bonding_store_xmit_hash);
+
+/*
+ * Show and set the arp timer interval. There are two tricky bits
+ * here. First, if ARP monitoring is activated, then we must disable
+ * MII monitoring. Second, if the ARP timer isn't running, we must
+ * start it.
+ */
+static ssize_t bonding_show_arp_interval(struct class_device *cd, char *buf)
+{
+ int count;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ count = sprintf(buf, "%d\n", bond->params.arp_interval) + 1;
+ up_read(&(bonding_rwsem));
+ return count;
+}
+
+static ssize_t bonding_store_arp_interval(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+ down_write(&(bonding_rwsem));
+
+ sscanf(buf, "%d", &new_value);
+ if (new_value < 0) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Invalid arp_interval value %d not in range %d-%d; rejected.\n",
+ bond->dev->name, new_value, 1, INT_MAX);
+ ret = -EINVAL;
+ goto out;
+ } else {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting ARP monitoring interval to %d.\n",
+ bond->dev->name, new_value);
+ bond->params.arp_interval = new_value;
+ if (bond->params.miimon) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: ARP monitoring cannot be used with MII monitoring. "
+ "%s Disabling MII monitoring.\n",
+ bond->dev->name, bond->dev->name);
+ bond->params.miimon = 0;
+ /* Kill MII timer, else it brings bond's link down */
+ if (bond->arp_timer.function) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Kill MII timer, else it brings bond's link down...\n",
+ bond->dev->name);
+ del_timer_sync(&bond->mii_timer);
+ }
+ }
+ if (!bond->params.arp_targets[0]) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: ARP monitoring has been set up, "
+ "but no ARP targets have been specified.\n",
+ bond->dev->name);
+ }
+ if (bond->dev->flags & IFF_UP) {
+ /* If the interface is up, we may need to fire off
+ * the ARP timer. If the interface is down, the
+ * timer will get fired off when the open function
+ * is called.
+ */
+ if (bond->arp_timer.function) {
+ /* The timer's already set up, so fire it off */
+ mod_timer(&bond->arp_timer, jiffies + 1);
+ } else {
+ /* Set up the timer. */
+ init_timer(&bond->arp_timer);
+ bond->arp_timer.expires = jiffies + 1;
+ bond->arp_timer.data =
+ (unsigned long) bond->dev;
+ if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
+ bond->arp_timer.function =
+ (void *)
+ &bond_activebackup_arp_mon;
+ } else {
+ bond->arp_timer.function =
+ (void *)
+ &bond_loadbalance_arp_mon;
+ }
+ add_timer(&bond->arp_timer);
+ }
+ }
+ }
+
+out:
+ up_write(&(bonding_rwsem));
+ return ret;
+}
+static CLASS_DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR , bonding_show_arp_interval, bonding_store_arp_interval);
+
+/*
+ * Show and set the arp targets.
+ */
+static ssize_t bonding_show_arp_targets(struct class_device *cd, char *buf)
+{
+ int i, res = 0;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+
+ for (i = 0; (i < BOND_MAX_ARP_TARGETS) && bond->params.arp_targets[i];
+ i++) {
+ res += sprintf(buf + res, "%u.%u.%u.%u",
+ NIPQUAD(bond->params.arp_targets[i]));
+ if ((i+1 < BOND_MAX_ARP_TARGETS) && bond->params.arp_targets[i+1])
+ res += sprintf(buf + res, " ");
+ else
+ res += sprintf(buf + res, "\n");
+ res++;
+ }
+
+ up_read(&(bonding_rwsem));
+ return res;
+}
+
+static ssize_t bonding_store_arp_targets(struct class_device *cd, const char *buf, size_t count)
+{
+ int octet1, octet2, octet3, octet4, ret = count;
+ int newpos = 0, pos = 0, i = 0;
+ struct bonding *bond = to_bond(cd);
+ const char *delimiter;
+
+ down_write(&(bonding_rwsem));
+
+ memset(bond->params.arp_targets, 0, sizeof(bond->params.arp_targets));
+ if (sscanf(buf, "%d.%d.%d.%d%n", &octet1, &octet2, &octet3, &octet4, &pos) != 4) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Invalid arp targets.\n", bond->dev->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* check for delimiting white space */
+ delimiter = buf + pos;
+ if(*delimiter != ' ' && *delimiter != '\n' ) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Invalid arp targets with missing whitespace.\n", bond->dev->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ while ((pos < count) && (i < BOND_MAX_ARP_TARGETS)) {
+ if ( (octet1 < 0) || (octet1 > 255)
+ || (octet2 < 0) || (octet2 > 255)
+ || (octet3 < 0) || (octet3 > 255)
+ || (octet4 < 0) || (octet4 > 255)
+ || ((octet1 == 0) && (octet2 == 0) &&
+ (octet3 == 0) && (octet4 == 0))
+ || ((octet1 == 255) && (octet2 == 255) &&
+ (octet3 == 255) && (octet4 == 255))
+ ) {
+ memset(bond->params.arp_targets, 0, sizeof(bond->params.arp_targets));
+ printk(KERN_ERR DRV_NAME
+ ": %s: Unable to add arp target %d.%d.%d.%d\n",
+ bond->dev->name, octet1, octet2, octet3, octet4);
+ ret = -EINVAL;
+ goto out;
+ } else {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Adding arp target %d.%d.%d.%d\n",
+ bond->dev->name, octet1, octet2, octet3, octet4);
+ bond->params.arp_targets[i] = htonl
+ ((((u32) octet1 & 0xff) << 24) |
+ (((u32) octet2 & 0xff) << 16) |
+ (((u32) octet3 & 0xff) << 8) | ((u32) octet4 &
+ 0xff));
+
+ i++;
+ }
+
+ newpos = 0;
+ if (sscanf(buf + pos, "%d.%d.%d.%d%n", &octet1, &octet2, &octet3,
+ &octet4, &newpos) != 4 && newpos != 0) {
+ memset(bond->params.arp_targets, 0, sizeof(bond->params.arp_targets));
+ printk(KERN_ERR DRV_NAME
+ ": %s: Invalid arp targets specified.\n", bond->dev->name);
+ ret = -EINVAL;
+ goto out;
+ }
+ if (newpos == 0) {
+ break;
+ }
+
+ pos += newpos;
+ /* check for delimiting white space */
+ delimiter = buf + pos;
+ if(*delimiter != ' ' && *delimiter != '\n' ) {
+ memset(bond->params.arp_targets, 0, sizeof(bond->params.arp_targets));
+ printk(KERN_ERR DRV_NAME
+ ": %s: Invalid arp targets with missing whitespace.\n", bond->dev->name);
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+out:
+ up_write(&(bonding_rwsem));
+ return ret;
+}
+static CLASS_DEVICE_ATTR(arp_ip_target, S_IRUGO | S_IWUSR , bonding_show_arp_targets, bonding_store_arp_targets);
+
+/*
+ * Show and set the up and down delays. These must be multiples of the
+ * MII monitoring value, and are stored internally as the multiplier.
+ * Thus, we must translate to MS for the real world.
+ */
+static ssize_t bonding_show_downdelay(struct class_device *cd, char *buf)
+{
+ int count;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ count = sprintf(buf, "%d\n", bond->params.downdelay * bond->params.miimon) + 1;
+ up_read(&(bonding_rwsem));
+ return count;
+}
+
+static ssize_t bonding_store_downdelay(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+ down_write(&(bonding_rwsem));
+
+ if (!(bond->params.miimon)) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Unable to set down delay as MII monitoring is disabled\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ sscanf(buf, "%d", &new_value);
+ if (new_value < 0) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Invalid down delay value %d not in range %d-%d; rejected.\n",
+ bond->dev->name, new_value, 1, INT_MAX);
+ ret = -EINVAL;
+ goto out;
+ } else {
+ if ((new_value % bond->params.miimon) != 0) {
+ printk(KERN_WARNING DRV_NAME
+ ": %s: Warning: down delay (%d) is not a multiple "
+ "of miimon (%d), delay rounded to %d ms\n",
+ bond->dev->name, new_value, bond->params.miimon,
+ (new_value / bond->params.miimon) *
+ bond->params.miimon);
+ }
+ bond->params.downdelay = new_value / bond->params.miimon;
+ printk(KERN_INFO DRV_NAME ": %s: Setting down delay to %d.\n",
+ bond->dev->name, bond->params.downdelay * bond->params.miimon);
+
+ }
+
+out:
+ up_write(&(bonding_rwsem));
+ return ret;
+}
+static CLASS_DEVICE_ATTR(down_delay, S_IRUGO | S_IWUSR , bonding_show_downdelay, bonding_store_downdelay);
+
+static ssize_t bonding_show_updelay(struct class_device *cd, char *buf)
+{
+ int count;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ count = sprintf(buf, "%d\n", bond->params.updelay * bond->params.miimon) + 1;
+ up_read(&(bonding_rwsem));
+ return count;
+
+}
+
+static ssize_t bonding_store_updelay(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+ down_write(&(bonding_rwsem));
+
+ if (!(bond->params.miimon)) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Unable to set up delay as MII monitoring is disabled\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ sscanf(buf, "%d", &new_value);
+ if (new_value < 0) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Invalid down delay value %d not in range %d-%d; rejected.\n",
+ bond->dev->name, new_value, 1, INT_MAX);
+ ret = -EINVAL;
+ goto out;
+ } else {
+ if ((new_value % bond->params.miimon) != 0) {
+ printk(KERN_WARNING DRV_NAME
+ ": %s: Warning: up delay (%d) is not a multiple "
+ "of miimon (%d), updelay rounded to %d ms\n",
+ bond->dev->name, new_value, bond->params.miimon,
+ (new_value / bond->params.miimon) *
+ bond->params.miimon);
+ }
+ bond->params.updelay = new_value / bond->params.miimon;
+ printk(KERN_INFO DRV_NAME ": %s: Setting up delay to %d.\n",
+ bond->dev->name, bond->params.updelay * bond->params.miimon);
+
+ }
+
+out:
+ up_write(&(bonding_rwsem));
+ return ret;
+}
+static CLASS_DEVICE_ATTR(up_delay, S_IRUGO | S_IWUSR , bonding_show_updelay, bonding_store_updelay);
+
+/*
+ * Show and set the LACP interval. Interface must be down, and the mode
+ * must be set to 802.3ad mode.
+ */
+static ssize_t bonding_show_lacp(struct class_device *cd, char *buf)
+{
+ int count;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ count = sprintf(buf, "%s %d\n",
+ bond_lacp_tbl[bond->params.lacp_fast].modename,
+ bond->params.lacp_fast) + 1;
+ up_read(&(bonding_rwsem));
+ return count;
+}
+
+static ssize_t bonding_store_lacp(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+ down_write(&(bonding_rwsem));
+
+ if (bond->dev->flags & IFF_UP) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Unable to update LACP rate because interface is up.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ if (bond->params.mode != BOND_MODE_8023AD) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Unable to update LACP rate because bond is not in 802.3ad mode.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ new_value = bond_parse_parm((char *)buf, bond_lacp_tbl);
+
+ if ((new_value == 1) || (new_value == 0)) {
+ bond->params.lacp_fast = new_value;
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting LACP rate to %s (%d).\n",
+ bond->dev->name, bond_lacp_tbl[new_value].modename, new_value);
+ } else {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Ignoring invalid LACP rate value %.*s.\n",
+ bond->dev->name, (int)strlen(buf) - 1, buf);
+ ret = -EINVAL;
+ }
+out:
+ up_write(&(bonding_rwsem));
+ return ret;
+}
+static CLASS_DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, bonding_show_lacp, bonding_store_lacp);
+
+/*
+ * Show and set the MII monitor interval. There are two tricky bits
+ * here. First, if MII monitoring is activated, then we must disable
+ * ARP monitoring. Second, if the timer isn't running, we must
+ * start it.
+ */
+static ssize_t bonding_show_miimon(struct class_device *cd, char *buf)
+{
+ int count;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ count = sprintf(buf, "%d\n", bond->params.miimon) + 1;
+ up_read(&(bonding_rwsem));
+ return count;
+}
+
+static ssize_t bonding_store_miimon(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+
+ sscanf(buf, "%d", &new_value);
+ if (new_value < 0) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Invalid miimon value %d not in range %d-%d; rejected.\n",
+ bond->dev->name, new_value, 1, INT_MAX);
+ ret = -EINVAL;
+ goto out;
+ } else {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting MII monitoring interval to %d.\n",
+ bond->dev->name, new_value);
+ bond->params.miimon = new_value;
+ if(bond->params.updelay)
+ printk(KERN_INFO DRV_NAME
+ ": %s: Note: Updating updelay (to %d) "
+ "since it is a multiple of the miimon value.\n",
+ bond->dev->name,
+ bond->params.updelay * bond->params.miimon);
+ if(bond->params.downdelay)
+ printk(KERN_INFO DRV_NAME
+ ": %s: Note: Updating downdelay (to %d) "
+ "since it is a multiple of the miimon value.\n",
+ bond->dev->name,
+ bond->params.downdelay * bond->params.miimon);
+ if (bond->params.arp_interval) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: MII monitoring cannot be used with "
+ "ARP monitoring. Disabling ARP monitoring...\n",
+ bond->dev->name);
+ bond->params.arp_interval = 0;
+ /* Kill ARP timer, else it brings bond's link down */
+ if (bond->mii_timer.function) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Kill ARP timer, else it brings bond's link down...\n",
+ bond->dev->name);
+ del_timer_sync(&bond->arp_timer);
+ }
+ }
+
+ if (bond->dev->flags & IFF_UP) {
+ /* If the interface is up, we may need to fire off
+ * the MII timer. If the interface is down, the
+ * timer will get fired off when the open function
+ * is called.
+ */
+ if (bond->mii_timer.function) {
+ /* The timer's already set up, so fire it off */
+ mod_timer(&bond->mii_timer, jiffies + 1);
+ } else {
+ /* Set up the timer. */
+ init_timer(&bond->mii_timer);
+ bond->mii_timer.expires = jiffies + 1;
+ bond->mii_timer.data =
+ (unsigned long) bond->dev;
+ bond->mii_timer.function =
+ (void *) &bond_mii_monitor;
+ add_timer(&bond->mii_timer);
+ }
+ }
+ }
+out:
+ up_read(&(bonding_rwsem));
+ return ret;
+}
+static CLASS_DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR, bonding_show_miimon, bonding_store_miimon);
+
+/*
+ * Show and set the primary slave. The store function is much
+ * simpler than bonding_store_slaves function because it only needs to
+ * handle one interface name.
+ * The bond must be a mode that supports a primary for this be
+ * set.
+ */
+static ssize_t bonding_show_primary(struct class_device *cd, char *buf)
+{
+ int count = 0;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ if (bond->primary_slave)
+ count = sprintf(buf, "%s\n", bond->primary_slave->dev->name) + 1;
+
+ up_read(&(bonding_rwsem));
+ return count;
+}
+
+static ssize_t bonding_store_primary(struct class_device *cd, const char *buf, size_t count)
+{
+ int i;
+ struct slave *slave;
+ struct bonding *bond = to_bond(cd);
+
+ down_write(&(bonding_rwsem));
+
+ write_lock_bh(&bond->lock);
+ if (!USES_PRIMARY(bond->params.mode)) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Unable to set primary slave; %s is in mode %d\n",
+ bond->dev->name, bond->dev->name, bond->params.mode);
+ } else {
+ bond_for_each_slave(bond, slave, i) {
+ if (strnicmp
+ (slave->dev->name, buf,
+ strlen(slave->dev->name)) == 0) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting %s as primary slave.\n",
+ bond->dev->name, slave->dev->name);
+ bond->primary_slave = slave;
+ bond_select_active_slave(bond);
+ goto out;
+ }
+ }
+
+ /* if we got here, then we didn't match the name of any slave */
+
+ if (strlen(buf) == 0 || buf[0] == '\n') {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting primary slave to None.\n",
+ bond->dev->name);
+ bond->primary_slave = 0;
+ bond_select_active_slave(bond);
+ } else {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Unable to set %.*s as primary slave as it is not a slave.\n",
+ bond->dev->name, (int)strlen(buf) - 1, buf);
+ }
+ }
+out:
+ write_unlock_bh(&bond->lock);
+ up_write(&(bonding_rwsem));
+ return count;
+}
+static CLASS_DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, bonding_show_primary, bonding_store_primary);
+
+/*
+ * Show and set the use_carrier flag.
+ */
+static ssize_t bonding_show_carrier(struct class_device *cd, char *buf)
+{
+ int count;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ count = sprintf(buf, "%d\n", bond->params.use_carrier) + 1;
+ up_read(&(bonding_rwsem));
+ return count;
+}
+
+static ssize_t bonding_store_carrier(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value;
+ struct bonding *bond = to_bond(cd);
+
+ down_write(&(bonding_rwsem));
+
+ sscanf(buf, "%d", &new_value);
+ if ((new_value == 0) || (new_value == 1)) {
+ bond->params.use_carrier = new_value;
+ printk(KERN_INFO DRV_NAME ": %s: Setting use_carrier to %d.\n",
+ bond->dev->name, new_value);
+ } else {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Ignoring invalid use_carrier value %d.\n",
+ bond->dev->name, new_value);
+ }
+ up_write(&(bonding_rwsem));
+ return count;
+}
+static CLASS_DEVICE_ATTR(use_carrier, S_IRUGO | S_IWUSR, bonding_show_carrier, bonding_store_carrier);
+
+
+/*
+ * Show and set currently active_slave.
+ */
+static ssize_t bonding_show_active_slave(struct class_device *cd, char *buf)
+{
+ struct slave *curr;
+ struct bonding *bond = to_bond(cd);
+ int count;
+
+ down_read(&(bonding_rwsem));
+
+ read_lock(&bond->curr_slave_lock);
+ curr = bond->curr_active_slave;
+ read_unlock(&bond->curr_slave_lock);
+
+ if (USES_PRIMARY(bond->params.mode)) {
+ count = sprintf(buf, "%s\n", (curr) ? curr->dev->name : "None") + 1;
+ }
+ else {
+ count = sprintf(buf, "%s\n", "None") + 1;
+ }
+ up_read(&(bonding_rwsem));
+ return count;
+}
+
+static ssize_t bonding_store_active_slave(struct class_device *cd, const char *buf, size_t count)
+{
+ int i;
+ struct slave *slave;
+ struct slave *old_active = NULL;
+ struct slave *new_active = NULL;
+ struct bonding *bond = to_bond(cd);
+
+ down_write(&(bonding_rwsem));
+
+ write_lock_bh(&bond->lock);
+ if (!USES_PRIMARY(bond->params.mode)) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Unable to change active slave; %s is in mode %d\n",
+ bond->dev->name, bond->dev->name, bond->params.mode);
+ } else {
+ bond_for_each_slave(bond, slave, i) {
+ if (strnicmp
+ (slave->dev->name, buf,
+ strlen(slave->dev->name)) == 0) {
+ old_active = bond->curr_active_slave;
+ new_active = slave;
+ if (new_active && (new_active == old_active)) {
+ /* do nothing */
+ printk(KERN_INFO DRV_NAME
+ ": %s: %s is already the current active slave.\n",
+ bond->dev->name, slave->dev->name);
+ goto out;
+ }
+ else {
+ if ((new_active) &&
+ (old_active) &&
+ (new_active->link == BOND_LINK_UP) &&
+ IS_UP(new_active->dev)) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting %s as active slave.\n",
+ bond->dev->name, slave->dev->name);
+ bond_change_active_slave(bond, new_active);
+ }
+ else {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Could not set %s as active slave; "
+ "either %s is down or the link is down.\n",
+ bond->dev->name, slave->dev->name,
+ slave->dev->name);
+ }
+ goto out;
+ }
+ }
+ }
+
+ /* if we got here, then we didn't match the name of any slave */
+
+ if (strlen(buf) == 0 || buf[0] == '\n') {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting active slave to None.\n",
+ bond->dev->name);
+ bond->primary_slave = 0;
+ bond_select_active_slave(bond);
+ } else {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Unable to set %.*s as active slave as it is not a slave.\n",
+ bond->dev->name, (int)strlen(buf) - 1, buf);
+ }
+ }
+out:
+ write_unlock_bh(&bond->lock);
+ up_write(&(bonding_rwsem));
+ return count;
+
+}
+static CLASS_DEVICE_ATTR(active_slave, S_IRUGO | S_IWUSR, bonding_show_active_slave, bonding_store_active_slave);
+
+
+/*
+ * Show link status of the bond interface.
+ */
+static ssize_t bonding_show_mii_status(struct class_device *cd, char *buf)
+{
+ int count;
+ struct slave *curr;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+
+ read_lock(&bond->curr_slave_lock);
+ curr = bond->curr_active_slave;
+ read_unlock(&bond->curr_slave_lock);
+
+ count = sprintf(buf, "%s\n", (curr) ? "up" : "down") + 1;
+ up_read(&(bonding_rwsem));
+ return count;
+}
+static CLASS_DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL);
+
+
+/*
+ * Show current 802.3ad aggregator ID.
+ */
+static ssize_t bonding_show_ad_aggregator(struct class_device *cd, char *buf)
+{
+ int count = 0;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ if (bond->params.mode == BOND_MODE_8023AD) {
+ struct ad_info ad_info;
+ count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.aggregator_id) + 1;
+ }
+ up_read(&(bonding_rwsem));
+ return count;
+}
+static CLASS_DEVICE_ATTR(ad_aggregator, S_IRUGO, bonding_show_ad_aggregator, NULL);
+
+
+/*
+ * Show number of active 802.3ad ports.
+ */
+static ssize_t bonding_show_ad_num_ports(struct class_device *cd, char *buf)
+{
+ int count = 0;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ if (bond->params.mode == BOND_MODE_8023AD) {
+ struct ad_info ad_info;
+ count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0: ad_info.ports) + 1;
+ }
+ up_read(&(bonding_rwsem));
+ return count;
+}
+static CLASS_DEVICE_ATTR(ad_num_ports, S_IRUGO, bonding_show_ad_num_ports, NULL);
+
+
+/*
+ * Show current 802.3ad actor key.
+ */
+static ssize_t bonding_show_ad_actor_key(struct class_device *cd, char *buf)
+{
+ int count = 0;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ if (bond->params.mode == BOND_MODE_8023AD) {
+ struct ad_info ad_info;
+ count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.actor_key) + 1;
+ }
+ up_read(&(bonding_rwsem));
+ return count;
+}
+static CLASS_DEVICE_ATTR(ad_actor_key, S_IRUGO, bonding_show_ad_actor_key, NULL);
+
+
+/*
+ * Show current 802.3ad partner key.
+ */
+static ssize_t bonding_show_ad_partner_key(struct class_device *cd, char *buf)
+{
+ int count = 0;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ if (bond->params.mode == BOND_MODE_8023AD) {
+ struct ad_info ad_info;
+ count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.partner_key) + 1;
+ }
+ up_read(&(bonding_rwsem));
+ return count;
+}
+static CLASS_DEVICE_ATTR(ad_partner_key, S_IRUGO, bonding_show_ad_partner_key, NULL);
+
+
+/*
+ * Show current 802.3ad partner mac.
+ */
+static ssize_t bonding_show_ad_partner_mac(struct class_device *cd, char *buf)
+{
+ int count = 0;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ if (bond->params.mode == BOND_MODE_8023AD) {
+ struct ad_info ad_info;
+ if (!bond_3ad_get_active_agg_info(bond, &ad_info)) {
+ count = sprintf(buf,"%02x:%02x:%02x:%02x:%02x:%02x\n",
+ ad_info.partner_system[0],
+ ad_info.partner_system[1],
+ ad_info.partner_system[2],
+ ad_info.partner_system[3],
+ ad_info.partner_system[4],
+ ad_info.partner_system[5]) + 1;
+ }
+ }
+ up_read(&(bonding_rwsem));
+ return count;
+}
+static CLASS_DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL);
+
+
+
+static struct attribute *per_bond_attrs[] = {
+ &class_device_attr_slaves.attr,
+ &class_device_attr_mode.attr,
+ &class_device_attr_arp_interval.attr,
+ &class_device_attr_arp_ip_target.attr,
+ &class_device_attr_down_delay.attr,
+ &class_device_attr_up_delay.attr,
+ &class_device_attr_lacp_rate.attr,
+ &class_device_attr_xmit_hash_policy.attr,
+ &class_device_attr_miimon.attr,
+ &class_device_attr_primary.attr,
+ &class_device_attr_use_carrier.attr,
+ &class_device_attr_active_slave.attr,
+ &class_device_attr_mii_status.attr,
+ &class_device_attr_ad_aggregator.attr,
+ &class_device_attr_ad_num_ports.attr,
+ &class_device_attr_ad_actor_key.attr,
+ &class_device_attr_ad_partner_key.attr,
+ &class_device_attr_ad_partner_mac.attr,
+ NULL,
+};
+
+static struct attribute_group bonding_group = {
+ .name = "bonding",
+ .attrs = per_bond_attrs,
+};
+
+/*
+ * Initialize sysfs. This sets up the bonding_masters file in
+ * /sys/class/net.
+ */
+int bond_create_sysfs(void)
+{
+ int ret = 0;
+ struct bonding *firstbond;
+
+ init_rwsem(&bonding_rwsem);
+
+ /* get the netdev class pointer */
+ firstbond = container_of(bond_dev_list.next, struct bonding, bond_list);
+ if (!firstbond)
+ {
+ return -ENODEV;
+
+ }
+ netdev_class = firstbond->dev->class_dev.class;
+ if (!netdev_class)
+ {
+ return -ENODEV;
+ }
+ ret = class_create_file(netdev_class, &class_attr_bonding_masters);
+
+ return ret;
+
+}
+
+/*
+ * Remove /sys/class/net/bonding_masters.
+ */
+void bond_destroy_sysfs(void)
+{
+ if (netdev_class)
+ class_remove_file(netdev_class, &class_attr_bonding_masters);
+}
+
+/*
+ * Initialize sysfs for each bond. This sets up and registers
+ * the 'bondctl' directory for each individual bond under /sys/class/net.
+ */
+int bond_create_sysfs_entry(struct bonding *bond)
+{
+ struct net_device *dev = bond->dev;
+ int err;
+
+ err = sysfs_create_group(&(dev->class_dev.kobj), &bonding_group);
+ if (err) {
+ printk(KERN_EMERG "eek! didn't create group!\n");
+ }
+
+ return err;
+}
+/*
+ * Remove sysfs entries for each bond.
+ */
+void bond_destroy_sysfs_entry(struct bonding *bond)
+{
+ struct net_device *dev = bond->dev;
+
+ sysfs_remove_group(&(dev->class_dev.kobj), &bonding_group);
+}
+
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/Makefile linux-2.6.12post-sysfs/drivers/net/bonding/Makefile
--- linux-2.6.12post/drivers/net/bonding/Makefile 2005-06-17 12:48:29.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/Makefile 2005-06-28 18:22:23.000000000 -0700
@@ -4,5 +4,5 @@
obj-$(CONFIG_BONDING) += bonding.o
-bonding-objs := bond_main.o bond_3ad.o bond_alb.o
+bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox