* [PATCH 1/3] stmmac: fixed dma lib build when turn-on the debug option
From: Giuseppe CAVALLARO @ 2011-04-11 9:16 UTC (permalink / raw)
To: netdev; +Cc: Giuseppe Cavallaro
This patch fixes a compilation error when build the
dwmac_lib with the DEBUG option enabled.
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/stmmac/dwmac_lib.c | 28 ++++++++++++++--------------
1 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/net/stmmac/dwmac_lib.c b/drivers/net/stmmac/dwmac_lib.c
index d65fab1..e250935 100644
--- a/drivers/net/stmmac/dwmac_lib.c
+++ b/drivers/net/stmmac/dwmac_lib.c
@@ -26,9 +26,9 @@
#undef DWMAC_DMA_DEBUG
#ifdef DWMAC_DMA_DEBUG
-#define DBG(fmt, args...) printk(fmt, ## args)
+#define DWMAC_LIB_DBG(fmt, args...) printk(fmt, ## args)
#else
-#define DBG(fmt, args...) do { } while (0)
+#define DWMAC_LIB_DBG(fmt, args...) do { } while (0)
#endif
/* CSR1 enables the transmit DMA to check for new descriptor */
@@ -152,7 +152,7 @@ int dwmac_dma_interrupt(void __iomem *ioaddr,
/* read the status register (CSR5) */
u32 intr_status = readl(ioaddr + DMA_STATUS);
- DBG(INFO, "%s: [CSR5: 0x%08x]\n", __func__, intr_status);
+ DWMAC_LIB_DBG(KERN_INFO "%s: [CSR5: 0x%08x]\n", __func__, intr_status);
#ifdef DWMAC_DMA_DEBUG
/* It displays the DMA process states (CSR5 register) */
show_tx_process_state(intr_status);
@@ -160,43 +160,43 @@ int dwmac_dma_interrupt(void __iomem *ioaddr,
#endif
/* ABNORMAL interrupts */
if (unlikely(intr_status & DMA_STATUS_AIS)) {
- DBG(INFO, "CSR5[15] DMA ABNORMAL IRQ: ");
+ DWMAC_LIB_DBG(KERN_INFO "CSR5[15] DMA ABNORMAL IRQ: ");
if (unlikely(intr_status & DMA_STATUS_UNF)) {
- DBG(INFO, "transmit underflow\n");
+ DWMAC_LIB_DBG(KERN_INFO "transmit underflow\n");
ret = tx_hard_error_bump_tc;
x->tx_undeflow_irq++;
}
if (unlikely(intr_status & DMA_STATUS_TJT)) {
- DBG(INFO, "transmit jabber\n");
+ DWMAC_LIB_DBG(KERN_INFO "transmit jabber\n");
x->tx_jabber_irq++;
}
if (unlikely(intr_status & DMA_STATUS_OVF)) {
- DBG(INFO, "recv overflow\n");
+ DWMAC_LIB_DBG(KERN_INFO "recv overflow\n");
x->rx_overflow_irq++;
}
if (unlikely(intr_status & DMA_STATUS_RU)) {
- DBG(INFO, "receive buffer unavailable\n");
+ DWMAC_LIB_DBG(KERN_INFO "receive buffer unavailable\n");
x->rx_buf_unav_irq++;
}
if (unlikely(intr_status & DMA_STATUS_RPS)) {
- DBG(INFO, "receive process stopped\n");
+ DWMAC_LIB_DBG(KERN_INFO "receive process stopped\n");
x->rx_process_stopped_irq++;
}
if (unlikely(intr_status & DMA_STATUS_RWT)) {
- DBG(INFO, "receive watchdog\n");
+ DWMAC_LIB_DBG(KERN_INFO "receive watchdog\n");
x->rx_watchdog_irq++;
}
if (unlikely(intr_status & DMA_STATUS_ETI)) {
- DBG(INFO, "transmit early interrupt\n");
+ DWMAC_LIB_DBG(KERN_INFO "transmit early interrupt\n");
x->tx_early_irq++;
}
if (unlikely(intr_status & DMA_STATUS_TPS)) {
- DBG(INFO, "transmit process stopped\n");
+ DWMAC_LIB_DBG(KERN_INFO "transmit process stopped\n");
x->tx_process_stopped_irq++;
ret = tx_hard_error;
}
if (unlikely(intr_status & DMA_STATUS_FBI)) {
- DBG(INFO, "fatal bus error\n");
+ DWMAC_LIB_DBG(KERN_INFO "fatal bus error\n");
x->fatal_bus_error_irq++;
ret = tx_hard_error;
}
@@ -215,7 +215,7 @@ int dwmac_dma_interrupt(void __iomem *ioaddr,
/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
- DBG(INFO, "\n\n");
+ DWMAC_LIB_DBG(KERN_INFO "\n\n");
return ret;
}
--
1.7.4.2
^ permalink raw reply related
* [PATCH 3/3] stmmac: fix Transmit Underflow error
From: Giuseppe CAVALLARO @ 2011-04-11 9:16 UTC (permalink / raw)
To: netdev; +Cc: Giuseppe Cavallaro
In-Reply-To: <1302513406-3758-1-git-send-email-peppe.cavallaro@st.com>
On some old MAC chips without COE sometime the
Transmit Underflow error is issued.
The driver aborted all the transmission process
and initialized it from scratch.
This breaks the network activity as raised by Nachiketa
on a SPEAr board.
The patch is to fix this rare underflow event.
The driver will only clear the interrupt and the Tx
DMA will go out the Suspend state as soon as the
descriptor is fetched again.
The driver will continue to bump-up the DMA FIFO threshold
that, indeed, helped somebody to prevent this kind of error
in the past as well.
Reported-by: Nachiketa Prachanda <nprachanda@ncomputing.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/stmmac/stmmac_main.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
index 442a7ca..ba9daec 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/stmmac/stmmac_main.c
@@ -749,7 +749,6 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv)
priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
priv->xstats.threshold = tc;
}
- stmmac_tx_err(priv);
} else if (unlikely(status == tx_hard_error))
stmmac_tx_err(priv);
}
--
1.7.4.2
^ permalink raw reply related
* [PATCH 2/3] stmmac: fix open funct when exit on error
From: Giuseppe CAVALLARO @ 2011-04-11 9:16 UTC (permalink / raw)
To: netdev; +Cc: Giuseppe Cavallaro, Shiraz Hashim
In-Reply-To: <1302513406-3758-1-git-send-email-peppe.cavallaro@st.com>
This patch reviews the open function and fixes some
errors when exit with an error state.
It also moves the request_irq after core is initialized
when interrupts are properly masked.
Signed-off-by: Shiraz Hashim <shiraz.hashim@st.com>
Hacked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/stmmac/stmmac_main.c | 48 ++++++++++++++++++++++---------------
1 files changed, 28 insertions(+), 20 deletions(-)
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
index 62fa51e..442a7ca 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/stmmac/stmmac_main.c
@@ -780,21 +780,6 @@ static int stmmac_open(struct net_device *dev)
stmmac_verify_args();
- ret = stmmac_init_phy(dev);
- if (unlikely(ret)) {
- pr_err("%s: Cannot attach to PHY (error: %d)\n", __func__, ret);
- return ret;
- }
-
- /* Request the IRQ lines */
- ret = request_irq(dev->irq, stmmac_interrupt,
- IRQF_SHARED, dev->name, dev);
- if (unlikely(ret < 0)) {
- pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
- __func__, dev->irq, ret);
- return ret;
- }
-
#ifdef CONFIG_STMMAC_TIMER
priv->tm = kzalloc(sizeof(struct stmmac_timer *), GFP_KERNEL);
if (unlikely(priv->tm == NULL)) {
@@ -813,6 +798,11 @@ static int stmmac_open(struct net_device *dev)
} else
priv->tm->enable = 1;
#endif
+ ret = stmmac_init_phy(dev);
+ if (unlikely(ret)) {
+ pr_err("%s: Cannot attach to PHY (error: %d)\n", __func__, ret);
+ goto open_error;
+ }
/* Create and initialize the TX/RX descriptors chains. */
priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
@@ -821,12 +811,11 @@ static int stmmac_open(struct net_device *dev)
init_dma_desc_rings(dev);
/* DMA initialization and SW reset */
- if (unlikely(priv->hw->dma->init(priv->ioaddr, priv->plat->pbl,
- priv->dma_tx_phy,
- priv->dma_rx_phy) < 0)) {
-
+ ret = priv->hw->dma->init(priv->ioaddr, priv->plat->pbl,
+ priv->dma_tx_phy, priv->dma_rx_phy);
+ if (ret < 0) {
pr_err("%s: DMA initialization failed\n", __func__);
- return -1;
+ goto open_error;
}
/* Copy the MAC addr into the HW */
@@ -848,6 +837,15 @@ static int stmmac_open(struct net_device *dev)
writel(0xffffffff, priv->ioaddr + MMC_HIGH_INTR_MASK);
writel(0xffffffff, priv->ioaddr + MMC_LOW_INTR_MASK);
+ /* Request the IRQ lines */
+ ret = request_irq(dev->irq, stmmac_interrupt,
+ IRQF_SHARED, dev->name, dev);
+ if (unlikely(ret < 0)) {
+ pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
+ __func__, dev->irq, ret);
+ goto open_error;
+ }
+
/* Enable the MAC Rx/Tx */
stmmac_enable_mac(priv->ioaddr);
@@ -878,7 +876,17 @@ static int stmmac_open(struct net_device *dev)
napi_enable(&priv->napi);
skb_queue_head_init(&priv->rx_recycle);
netif_start_queue(dev);
+
return 0;
+
+open_error:
+#ifdef CONFIG_STMMAC_TIMER
+ kfree(priv->tm);
+#endif
+ if (priv->phydev)
+ phy_disconnect(priv->phydev);
+
+ return ret;
}
/**
--
1.7.4.2
^ permalink raw reply related
* oops during unregister_netdevice interface enslaved to bond
From: Frank Blaschka @ 2011-04-11 9:06 UTC (permalink / raw)
To: netdev, linux-s390, opurdila, davem, fubar
Hi,
with 2.6.39-rc1/2 I realized and oops in one of our bonding tests.
The test is:
1) enslave netdevice to a bond
2) close the netdevcie
3) hot unplug the netdevice
<1>[27649.970474] Unable to handle kernel pointer dereference at virtual kernel address (null)
<4>[27649.970477] Oops: 0004 [#1] SMP
<4>[27649.970479] Modules linked in: bonding sunrpc qeth_l2 qeth_l3 binfmt_misc dm_multipath scsi_dh dm_mod ipv6 lcs qeth c
cwgroup [last unloaded: scsi_wait_scan]
<4>[27649.970488] CPU: 0 Tainted: G W 2.6.39-rc2.48.x.20110407-s390xgit #1
<4>[27649.970490] Process kworker/u:1 (pid: 25, task: 000000007ec4c838, ksp: 000000007ec535a8)
<4>[27649.970493] Krnl PSW : 0704100180000000 000000000055444e (klist_put+0x46/0xd4)
<4>[27649.970498] R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:0 CC:1 PM:0 EA:3
<4>[27649.970501] Krnl GPRS: 0000000000000410 07000000ffffffff 0000000000000000 0000000000000001
<4>[27649.970504] 00000000003e57c6 0000000000000001 000000007bac3d30 000000007bad5005
<4>[27649.970507] 000000007a2bb000 0000000000000000 0000000000000001 0000000000000000
<4>[27649.970509] 000000007d3f2c28 00000000005c1230 000000007ec53a98 000000007ec53a58
<4>[27649.970518] Krnl Code: 0000000000554440: 5710d000 x %r1,0(%r13)
<4>[27649.970521] 0000000000554444: e3b090200004 lg %r11,32(%r9)
<4>[27649.970524] 000000000055444a: a7280000 lhi %r2,0
<4>[27649.970528] >000000000055444e: ba219000 cs %r2,%r1,0(%r9)
<4>[27649.970531] 0000000000554452: 1222 ltr %r2,%r2
<4>[27649.970534] 0000000000554454: a774003c brc 7,5544cc
<4>[27649.970537] 0000000000554458: b90200aa ltgr %r10,%r10
<4>[27649.970540] 000000000055445c: a784000e brc 8,554478
<4>[27649.970542] Call Trace:
<4>[27649.970543] ([<000000000058a848>] bin_vm_ops+0x28/0xe8)
<4>[27649.970548] [<00000000003e57de>] device_del+0x7e/0x1d0
<4>[27649.970551] [<00000000004af858>] rollback_registered_many+0x1ac/0x268
<4>[27649.970554] [<00000000004af9f2>] rollback_registered+0x52/0x74
<4>[27649.970556] [<00000000004afa9e>] unregister_netdevice_queue+0x8a/0xe0
<4>[27649.970559] [<00000000004afc40>] unregister_netdev+0x34/0x40
<4>[27649.970562] [<000003c001a74cfc>] qeth_l2_remove_device+0xf8/0x120 [qeth_l2]
<4>[27649.970566] [<000003c003d87040>] qeth_core_remove_device+0x94/0x180 [qeth]
<4>[27649.970572] [<000003c00124c83e>] ccwgroup_remove+0x66/0x74 [ccwgroup]
<4>[27649.970575] [<00000000003e8d24>] __device_release_driver+0x7c/0xec
<4>[27649.970578] [<00000000003e8dcc>] device_release_driver+0x38/0x48
<4>[27649.970581] [<00000000003e87ee>] bus_remove_device+0xca/0xf4
<4>[27649.970584] [<00000000003e58b0>] device_del+0x150/0x1d0
<4>[27649.970587] [<00000000003e5956>] device_unregister+0x26/0x38
<4>[27649.970589] [<000003c00124c7bc>] ccwgroup_ungroup_callback+0x5c/0x78 [ccwgroup]
<4>[27649.970592] [<00000000002a3ca0>] sysfs_schedule_callback_work+0x38/0xa8
<4>[27649.970595] [<000000000015d1c6>] process_one_work+0x176/0x428
<4>[27649.970598] [<0000000000160ec2>] worker_thread+0x17a/0x398
<4>[27649.970601] [<0000000000166e2a>] kthread+0xa6/0xb0
<4>[27649.970603] [<00000000005614de>] kernel_thread_starter+0x6/0xc
<4>[27649.970606] [<00000000005614d8>] kernel_thread_starter+0x0/0xc
<4>[27649.970609] Last Breaking-Event-Address:
<4>[27649.970610] [<0000000000554538>] klist_del+0x4/0xc
<4>[27649.970613]
<0>[27649.970614] Kernel panic - not syncing: Fatal exception: panic_on_oops
<4>[27649.970617] CPU: 0 Tainted: G D W 2.6.39-rc2.48.x.20110407-s390xgit #1
<4>[27649.970619] Process kworker/u:1 (pid: 25, task: 000000007ec4c838, ksp: 000000007ec535a8)
<4>[27649.970622] 000000007ec53700 000000007ec53680 0000000000000002 0000000000000000
<4>[27649.970625] 000000007ec53720 000000007ec53698 000000007ec53698 000000000055ddae
<4>[27649.970629] 0000000000000001 0000000000000000 000000007bad5005 0000000000100ebe
<4>[27649.970632] 000000000000000d 000000000000000c 000000007ec536e8 0000000000000000
<4>[27649.970636] 0000000000000000 0000000000100a00 000000007ec53680 000000007ec536c0
<4>[27649.970640] Call Trace:
<4>[27649.970641] ([<0000000000882408>] die_lock+0x0/0x4)
I bisect the problem down to 2.6.38 development. Commit introduced the problem is:
commit 443457242beb6716b43db4d62fe148eab5515505
Author: Octavian Purdila <opurdila@ixiacom.com>
Date: Mon Dec 13 12:44:07 2010 +0000
net: factorize sync-rcu call in unregister_netdevice_many
Add dev_close_many and dev_deactivate_many to factorize another
sync-rcu operation on the netdevice unregister path.
$ modprobe dummy numdummies=10000
$ ip link set dev dummy* up
$ time rmmod dummy
Without the patch With the patch
real 0m 24.63s real 0m 5.15s
user 0m 0.00s user 0m 0.00s
sys 0m 6.05s sys 0m 5.14s
I don't know if this commit is bad or if it exposes a problem in the bonding code.
Without bonding I'm not able to reproduce the problem. Can anybody help?
Thanks,
Frank
^ permalink raw reply
* [PATCH 2/2] bonding:delete unused rlb_interval_counter
From: Weiping Pan(潘卫平) @ 2011-04-11 8:17 UTC (permalink / raw)
To: fubar, andy; +Cc: netdev, linux-kernel, Weiping Pan
In-Reply-To: <cover.1302509480.git.panweiping3@gmail.com>
Now, alb_bond_info uses rx_ntt,rlb_update_delay_counter and
rlb_update_retry_counter to decide when to call rlb_update_rx_clients().
Signed-off-by: Weiping Pan(潘卫平) <panweiping3@gmail.com>
---
drivers/net/bonding/bond_alb.h | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h
index f2a1d0a..01ed1fb 100644
--- a/drivers/net/bonding/bond_alb.h
+++ b/drivers/net/bonding/bond_alb.h
@@ -139,7 +139,6 @@ struct alb_bond_info {
struct slave *next_rx_slave;/* next slave to be assigned
* to a new rx client for
*/
- u32 rlb_interval_counter;
u8 primary_is_promisc; /* boolean */
u32 rlb_promisc_timeout_counter;/* counts primary
* promiscuity time
--
1.7.4
^ permalink raw reply related
* [PATCH 0/2] bonding:delete two unused variables
From: Weiping Pan(潘卫平) @ 2011-04-11 8:17 UTC (permalink / raw)
To: fubar, andy; +Cc: netdev, linux-kernel, Weiping Pan
I found that variable alb_timer and rlb_interval_counter in struct
alb_bond_info are not used by other codes any more, so delete them.
Weiping Pan(潘卫平) (2):
bonding:delete unused alb_timer
bonding:delete unused rlb_interval_counter
drivers/net/bonding/bond_alb.h | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
--
1.7.4
^ permalink raw reply
* [PATCH 1/2] bonding:delete unused alb_timer
From: Weiping Pan(潘卫平) @ 2011-04-11 8:17 UTC (permalink / raw)
To: fubar, andy; +Cc: netdev, linux-kernel, Weiping Pan
In-Reply-To: <cover.1302509480.git.panweiping3@gmail.com>
Now bonding-alb uses delayed_work instead of timer_list.
Signed-off-by: Weiping Pan(潘卫平) <panweiping3@gmail.com>
---
drivers/net/bonding/bond_alb.h | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h
index 86861f0..f2a1d0a 100644
--- a/drivers/net/bonding/bond_alb.h
+++ b/drivers/net/bonding/bond_alb.h
@@ -122,7 +122,6 @@ struct tlb_slave_info {
};
struct alb_bond_info {
- struct timer_list alb_timer;
struct tlb_client_info *tx_hashtbl; /* Dynamically allocated */
spinlock_t tx_hashtbl_lock;
u32 unbalanced_load;
--
1.7.4
^ permalink raw reply related
* Re: ipv6: Add support for RTA_PREFSRC
From: Florian Westphal @ 2011-04-11 7:58 UTC (permalink / raw)
To: Daniel Walter; +Cc: Florian Westphal, David Miller, netdev@vger.kernel.org
In-Reply-To: <1302506552.8923.21.camel@localhost>
Daniel Walter <dwalter@barracuda.com> wrote:
> On Thu, 2011-04-07 at 14:25 -0700, Florian Westphal wrote:
> > David Miller <davem@davemloft.net> wrote:
> > > This would be akin to ipv4's FIB_RES_PREFSRC
> >
> > OK, I'll bite.
> >
> > Whats wrong with using ipv6 addrlabels to pick the desired address,
> > and, if there is a problem, why is it not fixable?
> >
> > Just wondering...
> Hi,
>
> As far as I've understood addrlabels, they allow me to define the
> overall preferred source. As soon I want to select the default src
> only for a given route, addrlabels cannot do the job.
> for example:
> ip-addresses on eth0
> 2001:0DB8::1/64
> 2001:0DB8::2/64
> routes
> 2001:0DB8::/64
> 2001:0DB8:0:dead::/64 via 2001:0DB8::1234/64
>
> addrlabel allow me to set the default source address to 2001:0DB8::1 for
> both routes. with pref_src selection one is able to set the default
> outgoing address for each route to the needed address, which may be
> 2001:0DB8::1 for the first route, and 2001:0DB8::2 for the remaining.
>
> Please feel free to correct me if I misunderstood something.
ip addrlabel add label 1000 prefix 2001:db8::1
ip addrlabel add label 1000 prefix 2001:db8::/64
ip addrlabel add label 1001 prefix 2001:db8::2
ip addrlabel add label 1001 prefix 2001:0DB8:0:dead::/64
ip route add 2001:db8:0:dead::/64 via 2001:db8::1234
This should tell the stack to pick 2001:db8::1 as the
source address when talking to 2001:db8::/64, and to
use 2001:db8::2 when talking to 2001:0DB8:0:dead::42.
^ permalink raw reply
* Re: ipv6: Add support for RTA_PREFSRC
From: Daniel Walter @ 2011-04-11 7:22 UTC (permalink / raw)
To: Florian Westphal; +Cc: David Miller, netdev@vger.kernel.org
In-Reply-To: <20110407212552.GA11115@Chamillionaire.breakpoint.cc>
On Thu, 2011-04-07 at 14:25 -0700, Florian Westphal wrote:
> David Miller <davem@davemloft.net> wrote:
> > From: Daniel Walter <dwalter@barracuda.com>
> > Date: Mon, 4 Apr 2011 09:56:44 +0200
> > > This reduces the RTA_PREFSRC support to netlink only, unless
> > > we break the struct.
> >
> [..]
> > Since you do the prefsrc extraction in at least two places, make a
> > helper function that does the whole "if prefsrc.plen use prefsrc, else
> > use ipv6_dev_get_saddr()"
> >
> > This would be akin to ipv4's FIB_RES_PREFSRC
>
> OK, I'll bite.
>
> Whats wrong with using ipv6 addrlabels to pick the desired address,
> and, if there is a problem, why is it not fixable?
>
> Just wondering...
Hi,
As far as I've understood addrlabels, they allow me to define the
overall preferred source. As soon I want to select the default src
only for a given route, addrlabels cannot do the job.
for example:
ip-addresses on eth0
2001:0DB8::1/64
2001:0DB8::2/64
routes
2001:0DB8::/64
2001:0DB8:0:dead::/64 via 2001:0DB8::1234/64
addrlabel allow me to set the default source address to 2001:0DB8::1 for
both routes. with pref_src selection one is able to set the default
outgoing address for each route to the needed address, which may be
2001:0DB8::1 for the first route, and 2001:0DB8::2 for the remaining.
Please feel free to correct me if I misunderstood something.
--
Barracuda Networks solutions are now available as virtual appliances.
Visit www.barracudanetworks.com/vx for more information.
^ permalink raw reply
* [PATCH 1/1] ipv6: RTA_PREFSRC support for ipv6 route source address selection
From: Daniel Walter @ 2011-04-11 7:03 UTC (permalink / raw)
To: netdev; +Cc: linux-kernel, David Miller
[ipv6] Add support for RTA_PREFSRC
This patch allows a user to select the preferred source address
for a specific IPv6-Route. It can be set via a netlink message
setting RTA_PREFSRC to a valid IPv6 address which must be
up on the device the route will be bound to.
Signed-off-by: Daniel Walter <dwalter@barracuda.com>
---
Repost patch, after fixing some issues pointed out on netdev@
applies clean against current linux-2.6 HEAD
include/net/ip6_fib.h | 2 +
include/net/ip6_route.h | 7 ++++
net/ipv6/addrconf.c | 2 +
net/ipv6/ip6_output.c | 8 ++--
net/ipv6/route.c | 72 +++++++++++++++++++++++++++++++++++++++++++++--
5 files changed, 84 insertions(+), 7 deletions(-)
---
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index bc3cde0..98348d5 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -42,6 +42,7 @@ struct fib6_config {
struct in6_addr fc_dst;
struct in6_addr fc_src;
+ struct in6_addr fc_prefsrc;
struct in6_addr fc_gateway;
unsigned long fc_expires;
@@ -107,6 +108,7 @@ struct rt6_info {
struct rt6key rt6i_dst ____cacheline_aligned_in_smp;
u32 rt6i_flags;
struct rt6key rt6i_src;
+ struct rt6key rt6i_prefsrc;
u32 rt6i_metric;
u32 rt6i_peer_genid;
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index c850e5f..86b1cb4 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -84,6 +84,12 @@ extern int ip6_route_add(struct fib6_config *cfg);
extern int ip6_ins_rt(struct rt6_info *);
extern int ip6_del_rt(struct rt6_info *);
+extern int ip6_route_get_saddr(struct net *net,
+ struct rt6_info *rt,
+ struct in6_addr *daddr,
+ unsigned int prefs,
+ struct in6_addr *saddr);
+
extern struct rt6_info *rt6_lookup(struct net *net,
const struct in6_addr *daddr,
const struct in6_addr *saddr,
@@ -141,6 +147,7 @@ struct rt6_rtnl_dump_arg {
extern int rt6_dump_route(struct rt6_info *rt, void *p_arg);
extern void rt6_ifdown(struct net *net, struct net_device *dev);
extern void rt6_mtu_change(struct net_device *dev, unsigned mtu);
+extern void rt6_remove_prefsrc(struct inet6_ifaddr *ifp);
/*
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 3daaf3c..26f9e14 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -825,6 +825,8 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
dst_release(&rt->dst);
}
+ /* clean up prefsrc entries */
+ rt6_remove_prefsrc(ifp);
out:
in6_ifa_put(ifp);
}
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 1820887..0ce081b 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -930,10 +930,10 @@ static int ip6_dst_lookup_tail(struct sock *sk,
goto out_err_release;
if (ipv6_addr_any(&fl6->saddr)) {
- err = ipv6_dev_get_saddr(net, ip6_dst_idev(*dst)->dev,
- &fl6->daddr,
- sk ? inet6_sk(sk)->srcprefs : 0,
- &fl6->saddr);
+ struct rt6_info *rt = (struct rt6_info *) *dst;
+ err = ip6_route_get_saddr(net, rt, dst,
+ sk ? inet6_sk(sk)->srcprefs : 0,
+ &fl6->saddr);
if (err)
goto out_err_release;
}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 843406f..2688b2e 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1325,6 +1325,16 @@ int ip6_route_add(struct fib6_config *cfg)
if (dev == NULL)
goto out;
+ if (!ipv6_addr_any(&cfg->fc_prefsrc)) {
+ if (!ipv6_chk_addr(net, &cfg->fc_prefsrc, dev, 0)) {
+ err = -EINVAL;
+ goto out;
+ }
+ ipv6_addr_copy(&rt->rt6i_prefsrc.addr, &cfg->fc_prefsrc);
+ rt->rt6i_prefsrc.plen = 128;
+ } else
+ rt->rt6i_prefsrc.plen = 0;
+
if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) {
rt->rt6i_nexthop = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev);
if (IS_ERR(rt->rt6i_nexthop)) {
@@ -2037,6 +2047,55 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
return rt;
}
+int ip6_route_get_saddr(struct net *net,
+ struct rt6_info *rt,
+ struct in6_addr *daddr,
+ unsigned int prefs,
+ struct in6_addr *saddr)
+{
+ struct inet6_dev *idev = ip6_dst_idev(&rt->dst);
+ int err = 0;
+ if (rt->rt6i_prefsrc.plen)
+ ipv6_addr_copy(saddr, &rt->rt6i_prefsrc.addr);
+ else
+ err = ipv6_dev_get_saddr(net, idev ? idev->dev : NULL,
+ daddr, prefs, saddr);
+ return err;
+}
+
+/* remove deleted ip from prefsrc entries */
+struct arg_dev_net_ip {
+ struct net_device *dev;
+ struct net *net;
+ struct in6_addr *addr;
+};
+
+static int fib6_remove_prefsrc(struct rt6_info *rt, void *arg)
+{
+ struct net_device *dev = ((struct arg_dev_net_ip *)arg)->dev;
+ struct net *net = ((struct arg_dev_net_ip *)arg)->net;
+ struct in6_addr *addr = ((struct arg_dev_net_ip *)arg)->addr;
+
+ if (((void *)rt->rt6i_dev == dev || dev == NULL) &&
+ rt != net->ipv6.ip6_null_entry &&
+ ipv6_addr_equal(addr, &rt->rt6i_prefsrc.addr)) {
+ /* remove prefsrc entry */
+ rt->rt6i_prefsrc.plen = 0;
+ }
+ return 0;
+}
+
+void rt6_remove_prefsrc(struct inet6_ifaddr *ifp)
+{
+ struct net *net = dev_net(ifp->idev->dev);
+ struct arg_dev_net_ip adni = {
+ .dev = ifp->idev->dev,
+ .net = net,
+ .addr = &ifp->addr,
+ };
+ fib6_clean_all(net, fib6_remove_prefsrc, 0, &adni);
+}
+
struct arg_dev_net {
struct net_device *dev;
struct net *net;
@@ -2183,6 +2242,9 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
nla_memcpy(&cfg->fc_src, tb[RTA_SRC], plen);
}
+ if (tb[RTA_PREFSRC])
+ nla_memcpy(&cfg->fc_prefsrc, tb[RTA_PREFSRC], 16);
+
if (tb[RTA_OIF])
cfg->fc_ifindex = nla_get_u32(tb[RTA_OIF]);
@@ -2325,13 +2387,17 @@ static int rt6_fill_node(struct net *net,
#endif
NLA_PUT_U32(skb, RTA_IIF, iif);
} else if (dst) {
- struct inet6_dev *idev = ip6_dst_idev(&rt->dst);
struct in6_addr saddr_buf;
- if (ipv6_dev_get_saddr(net, idev ? idev->dev : NULL,
- dst, 0, &saddr_buf) == 0)
+ if (ip6_route_get_saddr(net, rt, dst, 0, &saddr_buf) == 0)
NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
}
+ if (rt->rt6i_prefsrc.plen) {
+ struct in6_addr saddr_buf;
+ ipv6_addr_copy(&saddr_buf, &rt->rt6i_prefsrc.addr);
+ NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
+ }
+
if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)
goto nla_put_failure;
Barracuda Networks AG
Vorsitzender des Aufsichtsrates/ Chairman of the supervisory board: Dean Drako
Vorstand/ Executive Board: Dr. Wieland Alge, Mag. Guenter Klausner
Sitz der Gesellschaft/ Registered office: 6020 Innsbruck, Austria
Handelsgericht Innsbruck Firmenbuch/ Registration Number: 184392s
UID-Nr/ VAT Number: ATU47509003
Diese Nachricht und allfaellige angehaengte Dokumente sind vertraulich und nur fuer den/die Adressaten bestimmt. Sollten Sie nicht der beabsichtigte Adressat sein, ist jede Offenlegung, Weiterleitung oder sonstige Verwendung dieser Information nicht gestattet. In diesem Fall bitten wir, den Absender zu verstaendigen und die Information zu vernichten. Fuer Uebermittlungsfehler oder sonstige Irrtuemer bei Uebermittlung besteht keine Haftung.
This message and any attached files are confidential and intended solely for the addressee(s). Any publication, transmission or other use of the information by a person or entity other than the intended addressee is prohibited. If you receive this in error please contact the sender and delete the material. The sender does not accept liability for any errors or omissions as a result of the transmission.
Barracuda Networks solutions are now available as virtual appliances.
Visit www.barracudanetworks.com/vx for more information.
^ permalink raw reply related
* Re: [PATCH net-next-2.6 v3 2/3] sctp: Add ASCONF operation on the single-homed host
From: Wei Yongjun @ 2011-04-11 5:41 UTC (permalink / raw)
To: Michio Honda; +Cc: netdev, lksctp-developers
In-Reply-To: <02627A77-8793-4EEC-9540-F2DECBB8E23A@sfc.wide.ad.jp>
comment inline.
> SCTP can change the IP address on the single-homed host.
> In this case, the SCTP association transmits an ASCONF packet including addition of the new IP address and deletion of the old address.
> This patch implements this functionality.
>
> Signed-off-by: Michio Honda <micchie@sfc.wide.ad.jp>
> ---
> diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
> index c70d8cc..d7a4ee3 100644
> --- a/include/net/sctp/constants.h
> +++ b/include/net/sctp/constants.h
> @@ -441,4 +441,8 @@ enum {
> */
> #define SCTP_AUTH_RANDOM_LENGTH 32
>
> +/* ASCONF PARAMETERS */
> +#define SCTP_ASCONF_V4_PARAM_LEN 16
> +#define SCTP_ASCONF_V6_PARAM_LEN 28
> +
> #endif /* __sctp_constants_h__ */
> diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
> index 9352d12..498a3cf 100644
> --- a/include/net/sctp/sm.h
> +++ b/include/net/sctp/sm.h
> @@ -259,6 +259,7 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
> struct sctp_chunk *asconf);
> int sctp_process_asconf_ack(struct sctp_association *asoc,
> struct sctp_chunk *asconf_ack);
> +void sctp_path_check_and_react(struct sctp_association *, struct sockaddr *);
> struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc,
> __u32 new_cum_tsn, size_t nstreams,
> struct sctp_fwdtsn_skip *skiplist);
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index cc9185c..400ee8a 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -1901,6 +1901,9 @@ struct sctp_association {
> * after reaching 4294967295.
> */
> __u32 addip_serial;
> + union sctp_addr *asconf_addr_del_pending;
> + __u32 asconf_del_pending_cid;
> + int src_out_of_asoc_ok;
>
> /* SCTP AUTH: list of the endpoint shared keys. These
> * keys are provided out of band by the user applicaton
> diff --git a/net/sctp/associola.c b/net/sctp/associola.c
> index 6b04287..2dfd0e8 100644
> --- a/net/sctp/associola.c
> +++ b/net/sctp/associola.c
> @@ -279,6 +279,9 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
> asoc->peer.asconf_capable = 0;
> if (sctp_addip_noauth)
> asoc->peer.asconf_capable = 1;
> + asoc->asconf_addr_del_pending = NULL;
> + asoc->asconf_del_pending_cid = 0;
> + asoc->src_out_of_asoc_ok = 0;
>
> /* Create an input queue. */
> sctp_inq_init(&asoc->base.inqueue);
> @@ -443,6 +446,10 @@ void sctp_association_free(struct sctp_association *asoc)
>
> asoc->peer.transport_count = 0;
>
> + /* Free pending address space being deleted */
> + if (asoc->asconf_addr_del_pending != NULL)
> + kfree(asoc->asconf_addr_del_pending);
> +
> /* Free any cached ASCONF_ACK chunk. */
> sctp_assoc_free_asconf_acks(asoc);
>
> @@ -1277,7 +1284,7 @@ void sctp_assoc_update(struct sctp_association *asoc,
> */
> void sctp_assoc_update_retran_path(struct sctp_association *asoc)
> {
> - struct sctp_transport *t, *next;
> + struct sctp_transport *t, *next, *unconfirmed;
> struct list_head *head = &asoc->peer.transport_addr_list;
> struct list_head *pos;
>
> @@ -1287,7 +1294,7 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc)
> /* Find the next transport in a round-robin fashion. */
> t = asoc->peer.retran_path;
> pos = &t->transports;
> - next = NULL;
> + next = unconfirmed = NULL;
>
> while (1) {
> /* Skip the head. */
> @@ -1318,11 +1325,15 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc)
> */
> if (t->state != SCTP_UNCONFIRMED && !next)
> next = t;
> + else if (t->state == SCTP_UNCONFIRMED)
> + unconfirmed = t;
> }
> }
>
> if (t)
> asoc->peer.retran_path = t;
> + else if (unconfirmed)
> + asoc->peer.retran_path = t = unconfirmed;
>
> SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association"
> " %p addr: ",
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index 865ce7b..56c97ce 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -332,6 +332,13 @@ static void sctp_v6_get_saddr(struct sctp_sock *sk,
> matchlen = bmatchlen;
> }
> }
> + if (laddr->state == SCTP_ADDR_NEW && asoc->src_out_of_asoc_ok) {
> + bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a);
> + if (!baddr || (matchlen < bmatchlen)) {
> + baddr = &laddr->a;
> + matchlen = bmatchlen;
> + }
> + }
> }
>
> if (baddr) {
> diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
> index 26dc005..033ea20 100644
> --- a/net/sctp/outqueue.c
> +++ b/net/sctp/outqueue.c
> @@ -344,7 +344,14 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)
> break;
> }
> } else {
> - list_add_tail(&chunk->list, &q->control_chunk_list);
> + /* We add the ASCONF for the only one newly added address at
> + * the front of the queue
> + */
> + if (q->asoc->src_out_of_asoc_ok && \
> + chunk->chunk_hdr->type == SCTP_CID_ASCONF)
> + list_add(&chunk->list, &q->control_chunk_list);
> + else
> + list_add_tail(&chunk->list, &q->control_chunk_list);
> SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> }
>
> @@ -850,6 +857,24 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
> case SCTP_CID_SHUTDOWN:
> case SCTP_CID_ECN_ECNE:
> case SCTP_CID_ASCONF:
> + /* RFC 5061, 5.3
> + * F1) This means that until such time as the ASCONF
> + * containing the add is acknowledged, the sender MUST
> + * NOT use the new IP address as a source for ANY SCTP
> + * packet except on carrying an ASCONF Chunk.
> + */
> + if (asoc->src_out_of_asoc_ok) {
> + SCTP_DEBUG_PRINTK("outq_flush: out_of_asoc_ok, transmit chunk type %d\n",
> + chunk->chunk_hdr->type);
> + packet = &transport->packet;
> + sctp_packet_config(packet, vtag,
> + asoc->peer.ecn_capable);
> + sctp_packet_append_chunk(packet, chunk);
> + error = sctp_packet_transmit(packet);
> + if (error < 0)
> + return error;
> + goto sctp_flush_out;
> + }
> case SCTP_CID_FWD_TSN:
> status = sctp_packet_transmit_chunk(packet, chunk,
> one_packet);
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 152976e..b8ec3cc 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -510,7 +510,8 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
> sctp_v4_dst_saddr(&dst_saddr, dst, htons(bp->port));
> rcu_read_lock();
> list_for_each_entry_rcu(laddr, &bp->address_list, list) {
> - if (!laddr->valid || (laddr->state != SCTP_ADDR_SRC))
> + if (!laddr->valid || (laddr->state != SCTP_ADDR_SRC &&
> + asoc->src_out_of_asoc_ok == 0))
> continue;
> if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a))
> goto out_unlock;
> diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
> index de98665..5a085b3 100644
> --- a/net/sctp/sm_make_chunk.c
> +++ b/net/sctp/sm_make_chunk.c
> @@ -2651,6 +2651,61 @@ __u32 sctp_generate_tsn(const struct sctp_endpoint *ep)
> return retval;
> }
>
> +void
> +sctp_path_check_and_react(struct sctp_association *asoc, struct sockaddr *sa)
> +{
> + struct sctp_transport *trans;
> + int addrnum, family;
> + struct sctp_sockaddr_entry *saddr;
> + struct sctp_bind_addr *bp;
> + union sctp_addr *tmpaddr;
> +
> + family = sa->sa_family;
> + bp = &asoc->base.bind_addr;
> + addrnum = 0;
> + /* count up the number of local addresses in the same family */
> + list_for_each_entry(saddr, &bp->address_list, list) {
> + if (saddr->a.sa.sa_family == family) {
> + tmpaddr = &saddr->a;
> + if (family == AF_INET6 &&
> + ipv6_addr_type(&tmpaddr->v6.sin6_addr) &
> + IPV6_ADDR_LINKLOCAL) {
> + continue;
> + }
> + addrnum++;
> + }
> + }
> + if (addrnum == 1) {
> + union sctp_addr *tmpaddr;
> + tmpaddr = (union sctp_addr *)sa;
> + SCTP_DEBUG_PRINTK_IPADDR("pcheck_react: only 1 local addr in asoc %p ",
> + " family %d\n", asoc, tmpaddr, family);
> + list_for_each_entry(trans, &asoc->peer.transport_addr_list,
> + transports) {
> + /* reset path information and release refcount to the
> + * dst_entry based on the src change */
> + sctp_transport_hold(trans);
> + trans->cwnd = min(4*asoc->pathmtu,
> + max_t(__u32, 2*asoc->pathmtu, 4380));
> + trans->ssthresh = asoc->peer.i.a_rwnd;
> + trans->rtt = 0;
> + trans->srtt = 0;
> + trans->rttvar = 0;
> + trans->rto = asoc->rto_initial;
> + dst_release(trans->dst);
> + trans->dst = NULL;
> + memset(&trans->saddr, 0, sizeof(union sctp_addr));
> + sctp_transport_route(trans, NULL,
> + sctp_sk(asoc->base.sk));
> + SCTP_DEBUG_PRINTK_IPADDR("we freed dst_entry (asoc: %p dst: ",
> + " trans: %p)\n", asoc, (&trans->ipaddr), trans);
> + trans->rto_pending = 1;
> + sctp_transport_put(trans);
> + }
> + }
> + return;
> +}
> +
> /*
> * ADDIP 3.1.1 Address Configuration Change Chunk (ASCONF)
> * 0 1 2 3
> @@ -2744,11 +2799,29 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc,
> int addr_param_len = 0;
> int totallen = 0;
> int i;
> + sctp_addip_param_t del_param; /* 8 Bytes (Type 0xC002, Len and CrrID) */
> + sctp_addip_param_t spr_param;
> + struct sctp_af *del_af;
> + struct sctp_af *spr_af;
> + int del_addr_param_len = 0;
> + int spr_addr_param_len = 0;
> + int del_paramlen = sizeof(sctp_addip_param_t);
> + int spr_paramlen = sizeof(sctp_addip_param_t);
> + union sctp_addr_param del_addr_param; /* (v4) 8 Bytes, (v6) 20 Bytes */
> + union sctp_addr_param spr_addr_param;
> + int v4 = 0;
> + int v6 = 0;
>
> /* Get total length of all the address parameters. */
> addr_buf = addrs;
> for (i = 0; i < addrcnt; i++) {
> addr = (union sctp_addr *)addr_buf;
> + if (addr != NULL) {
> + if (addr->sa.sa_family == AF_INET)
> + v4 = 1;
> + else if (addr->sa.sa_family == AF_INET6)
> + v6 = 1;
> + }
> af = sctp_get_af_specific(addr->v4.sin_family);
> addr_param_len = af->to_addr_param(addr, &addr_param);
>
> @@ -2757,6 +2830,40 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc,
>
> addr_buf += af->sockaddr_len;
> }
> + /* Add the length of a pending address being deleted */
> + if (flags == SCTP_PARAM_ADD_IP && asoc->asconf_addr_del_pending) {
> + if ((asoc->asconf_addr_del_pending->sa.sa_family == AF_INET
> + && v4) ||
> + (asoc->asconf_addr_del_pending->sa.sa_family == AF_INET6
> + && v6)) {
> + del_af = sctp_get_af_specific(
> + asoc->asconf_addr_del_pending->sa.sa_family);
> + del_addr_param_len = del_af->to_addr_param(
> + asoc->asconf_addr_del_pending, &del_addr_param);
> + totallen += del_paramlen;
> + totallen += del_addr_param_len;
> + SCTP_DEBUG_PRINTK("mkasconf_update_ip: now we picked del_pending addr, totallen for all addresses is %d\n",
> + totallen);
> + /* for Set Primary (equal size as del parameters */
> + totallen += del_paramlen;
> + totallen += del_addr_param_len;
> + }
> + if (v4) {
> + if (totallen != SCTP_ASCONF_V4_PARAM_LEN * 2 &&
> + totallen != SCTP_ASCONF_V4_PARAM_LEN * 3) {
> + SCTP_DEBUG_PRINTK("mkasconf_update_ip: incorrect total length of ASCONF parameters, del + add MUST be 32 bytes, but %d bytes\n", totallen);
> + return NULL;
> + }
> + } else if (v6) {
> + if (totallen != SCTP_ASCONF_V6_PARAM_LEN * 2 &&
> + totallen != SCTP_ASCONF_V6_PARAM_LEN * 3) {
> + SCTP_DEBUG_PRINTK("mkasconf_update_ip: incorrect total length of ASCONF parameters, del + add MUST be 56 bytes, but %d bytes\n", totallen);
> + return NULL;
> + }
> + }
We really need this length check? we accept both v4 and v6 address
if allowed.
> + }
> + SCTP_DEBUG_PRINTK("mkasconf_update_ip: call mkasconf() for %d bytes\n",
> + totallen);
>
> /* Create an asconf chunk with the required length. */
> retval = sctp_make_asconf(asoc, laddr, totallen);
> @@ -2778,6 +2885,32 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc,
>
> addr_buf += af->sockaddr_len;
> }
> + if (flags == SCTP_PARAM_ADD_IP && asoc->asconf_addr_del_pending) {
> + addr = asoc->asconf_addr_del_pending;
> + del_af = sctp_get_af_specific(addr->v4.sin_family);
> + del_addr_param_len = del_af->to_addr_param(addr,
> + &del_addr_param);
> + del_param.param_hdr.type = SCTP_PARAM_DEL_IP;
> + del_param.param_hdr.length = htons(del_paramlen +
> + del_addr_param_len);
> + del_param.crr_id = i;
> + asoc->asconf_del_pending_cid = i;
> +
> + sctp_addto_chunk(retval, del_paramlen, &del_param);
> + sctp_addto_chunk(retval, del_addr_param_len, &del_addr_param);
> + /* For SET_PRIMARY */
SET_PRIMARY is unnecessary, since we have only one address.
> + addr_buf = addrs;
> + addr = (union sctp_addr *)addr_buf;
> + spr_af = sctp_get_af_specific(addr->v4.sin_family);
> + spr_addr_param_len = spr_af->to_addr_param(addr,
> + &spr_addr_param);
> + spr_param.param_hdr.type = SCTP_PARAM_SET_PRIMARY;
> + spr_param.param_hdr.length = htons(spr_paramlen +
> + spr_addr_param_len);
> + spr_param.crr_id = (i+1);
> + sctp_addto_chunk(retval, spr_paramlen, &spr_param);
> + sctp_addto_chunk(retval, spr_addr_param_len, &spr_addr_param);
> + }
> return retval;
> }
>
> @@ -2990,7 +3123,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
> * an Error Cause TLV set to the new error code 'Request to
> * Delete Source IP Address'
> */
> - if (sctp_cmp_addr_exact(sctp_source(asconf), &addr))
> + if (sctp_cmp_addr_exact(&asconf->source, &addr))
> return SCTP_ERROR_DEL_SRC_IP;
>
> /* Section 4.2.2
> @@ -3193,16 +3326,37 @@ static void sctp_asconf_param_success(struct sctp_association *asoc,
> local_bh_enable();
> list_for_each_entry(transport, &asoc->peer.transport_addr_list,
> transports) {
> - if (transport->state == SCTP_ACTIVE)
> + if (transport->state == SCTP_ACTIVE &&
> + !asoc->src_out_of_asoc_ok)
> continue;
> dst_release(transport->dst);
> sctp_transport_route(transport, NULL,
> sctp_sk(asoc->base.sk));
> }
> + asoc->src_out_of_asoc_ok = 0;
> break;
> case SCTP_PARAM_DEL_IP:
> local_bh_disable();
> sctp_del_bind_addr(bp, &addr);
> + if (asoc->asconf_addr_del_pending != NULL) {
> + if ((addr.sa.sa_family == AF_INET) &&
> + (asoc->asconf_addr_del_pending->sa.sa_family ==
> + AF_INET)) {
> + if (asoc->asconf_addr_del_pending->v4.sin_addr.s_addr == addr.v4.sin_addr.s_addr) {
> + kfree(asoc->asconf_addr_del_pending);
> + asoc->asconf_del_pending_cid = 0;
> + asoc->asconf_addr_del_pending = NULL;
> + }
> + } else if ((addr.sa.sa_family == AF_INET6) &&
> + (asoc->asconf_addr_del_pending->sa.sa_family ==
> + AF_INET6)) {
> + if (ipv6_addr_equal(&asoc->asconf_addr_del_pending->v6.sin6_addr, &addr.v6.sin6_addr)) {
> + kfree(asoc->asconf_addr_del_pending);
> + asoc->asconf_del_pending_cid = 0;
> + asoc->asconf_addr_del_pending = NULL;
> + }
> + }
> + }
> local_bh_enable();
> list_for_each_entry(transport, &asoc->peer.transport_addr_list,
> transports) {
> @@ -3293,6 +3447,8 @@ int sctp_process_asconf_ack(struct sctp_association *asoc,
> int no_err = 1;
> int retval = 0;
> __be16 err_code = SCTP_ERROR_NO_ERROR;
> + sctp_addip_param_t *first_asconf_param = NULL;
> + int first_asconf_paramlen;
>
> /* Skip the chunkhdr and addiphdr from the last asconf sent and store
> * a pointer to address parameter.
> @@ -3307,6 +3463,8 @@ int sctp_process_asconf_ack(struct sctp_association *asoc,
> length = ntohs(addr_param->v4.param_hdr.length);
> asconf_param = (sctp_addip_param_t *)((void *)addr_param + length);
> asconf_len -= length;
> + first_asconf_param = asconf_param;
> + first_asconf_paramlen = ntohs(first_asconf_param->param_hdr.length);
>
> /* ADDIP 4.1
> * A8) If there is no response(s) to specific TLV parameter(s), and no
> @@ -3361,6 +3519,35 @@ int sctp_process_asconf_ack(struct sctp_association *asoc,
> asconf_len -= length;
> }
>
> + /* When the source address obviously changes to newly added one, we
> + reset the cwnd to re-probe the path condition
> + */
> + if (no_err && first_asconf_param->param_hdr.type == SCTP_PARAM_ADD_IP) {
> + if (first_asconf_paramlen == SCTP_ASCONF_V4_PARAM_LEN) {
> + struct sockaddr_in sin;
> +
> + memset(&sin, 0, sizeof(struct sockaddr_in));
> + sin.sin_family = AF_INET;
> + memcpy(&sin.sin_addr.s_addr, first_asconf_param + 1,
> + sizeof(struct in_addr));
> + sctp_path_check_and_react(asoc,
> + (struct sockaddr *)&sin);
> +
> + } else if (first_asconf_paramlen == SCTP_ASCONF_V6_PARAM_LEN) {
> + struct sockaddr_in6 sin6;
> +
> + memset(&sin6, 0, sizeof(struct sockaddr_in6));
> + sin6.sin6_family = AF_INET6;
> + memcpy(&sin6.sin6_addr, first_asconf_param + 1,
> + sizeof(struct in6_addr));
> + sctp_path_check_and_react(asoc,
> + (struct sockaddr *)&sin6);
> + } else {
> + SCTP_DEBUG_PRINTK("funny asconf_paramlen? (%d)\n",
> + first_asconf_paramlen);
> + }
> + }
> +
> /* Free the cached last sent asconf chunk. */
> list_del_init(&asconf->transmitted_list);
> sctp_chunk_free(asconf);
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index 3951a10..2bfe2a9 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -527,6 +527,7 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
> struct list_head *p;
> int i;
> int retval = 0;
> + struct sctp_transport *trans = NULL;
>
> if (!sctp_addip_enable)
> return retval;
> @@ -583,13 +584,10 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
> goto out;
> }
>
> - retval = sctp_send_asconf(asoc, chunk);
> - if (retval)
> - goto out;
> -
> /* Add the new addresses to the bind address list with
> * use_as_src set to 0.
> */
> + SCTP_DEBUG_PRINTK("snd_asconf_addip: next, add_bind_addr with ADDR_NEW flag\n");
> addr_buf = addrs;
> for (i = 0; i < addrcnt; i++) {
> addr = (union sctp_addr *)addr_buf;
> @@ -599,6 +597,28 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
> SCTP_ADDR_NEW, GFP_ATOMIC);
> addr_buf += af->sockaddr_len;
> }
> + list_for_each_entry(trans, &asoc->peer.transport_addr_list,
> + transports) {
> + if (asoc->asconf_addr_del_pending != NULL)
> + /* This ADDIP ASCONF piggybacks DELIP for the
> + * last address, so need to select src addr
> + * from the out_of_asoc addrs
> + */
> + asoc->src_out_of_asoc_ok = 1;
> + /* Clear the source and route cache in the path */
> + memset(&trans->saddr, 0, sizeof(union sctp_addr));
> + dst_release(trans->dst);
> + trans->cwnd = min(4*asoc->pathmtu, max_t(__u32,
> + 2*asoc->pathmtu, 4380));
> + trans->ssthresh = asoc->peer.i.a_rwnd;
> + trans->rto = asoc->rto_initial;
> + trans->rtt = 0;
> + trans->srtt = 0;
> + trans->rttvar = 0;
> + sctp_transport_route(trans, NULL,
> + sctp_sk(asoc->base.sk));
> + }
> + retval = sctp_send_asconf(asoc, chunk);
> }
>
> out:
> @@ -711,7 +731,9 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
> struct sctp_sockaddr_entry *saddr;
> int i;
> int retval = 0;
> + int stored = 0;
>
> + chunk = NULL;
> if (!sctp_addip_enable)
> return retval;
>
> @@ -762,8 +784,42 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
> bp = &asoc->base.bind_addr;
> laddr = sctp_find_unmatch_addr(bp, (union sctp_addr *)addrs,
> addrcnt, sp);
> - if (!laddr)
> - continue;
> + if ((laddr == NULL) && (addrcnt == 1)) {
> + union sctp_addr *sa_addr = NULL;
> +
> + if (asoc->asconf_addr_del_pending == NULL) {
> + asoc->asconf_addr_del_pending =
> + kmalloc(sizeof(union sctp_addr),
> + GFP_ATOMIC);
> + memset(asoc->asconf_addr_del_pending, 0,
> + sizeof(union sctp_addr));
> + if (addrs->sa_family == AF_INET) {
> + struct sockaddr_in *sin;
> +
> + sin = (struct sockaddr_in *)addrs;
> + asoc->asconf_addr_del_pending->v4.sin_family = AF_INET;
> + memcpy(&asoc->asconf_addr_del_pending->v4.sin_addr, &sin->sin_addr, sizeof(struct in_addr));
> + } else if (addrs->sa_family == AF_INET6) {
> + struct sockaddr_in6 *sin6;
> +
> + sin6 = (struct sockaddr_in6 *)addrs;
> + asoc->asconf_addr_del_pending->v6.sin6_family = AF_INET6;
> + memcpy(&asoc->asconf_addr_del_pending->v6.sin6_addr, &sin6->sin6_addr, sizeof(struct in6_addr));
> + }
> + sa_addr = (union sctp_addr *)addrs;
> + SCTP_DEBUG_PRINTK_IPADDR("send_asconf_del_ip: keep the last address asoc: %p ",
> + " at %p\n", asoc, sa_addr,
> + asoc->asconf_addr_del_pending);
> + stored = 1;
> + goto skip_mkasconf;
> + } else {
> + SCTP_DEBUG_PRINTK_IPADDR("send_asconf_del_ip: asoc %p, deleting last address ",
> + " is already stored at %p\n", asoc,
> + asoc->asconf_addr_del_pending,
> + asoc->asconf_addr_del_pending);
> + continue;
> + }
> + }
>
> /* We do not need RCU protection throughout this loop
> * because this is done under a socket lock from the
> @@ -776,6 +832,7 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
> goto out;
> }
>
> +skip_mkasconf:
> /* Reset use_as_src flag for the addresses in the bind address
> * list that are to be deleted.
> */
> @@ -797,10 +854,16 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
> list_for_each_entry(transport, &asoc->peer.transport_addr_list,
> transports) {
> dst_release(transport->dst);
> + /* Clear source address cache */
> + memset(&transport->saddr, 0, sizeof(union sctp_addr));
> sctp_transport_route(transport, NULL,
> sctp_sk(asoc->base.sk));
> }
>
> + if (stored) {
> + /* We don't need to transmit ASCONF */
> + continue;
> + }
> retval = sctp_send_asconf(asoc, chunk);
> }
> out:
You should split this patch to two or more for better review:
the receive side for ASCONF with ADDIP and DELIP paramaters from new IP
the send side for ASCONF operation on single-homed host
^ permalink raw reply
* Re: [PATCH net-next-2.6 v3 1/3] sctp: Add Auto-ASCONF support
From: Wei Yongjun @ 2011-04-11 5:26 UTC (permalink / raw)
To: Michio Honda; +Cc: netdev, lksctp-developers
In-Reply-To: <701EB2FD-B100-4DFE-B013-C9D57CBCDA5E@sfc.wide.ad.jp>
Comment inline.
> SCTP reconfigure the IP addresses in the association by using ASCONF chunks as mentioned in RFC5061.
> For example, we can start to use the newly configured IP address in the existing association.
> ASCONF operation is invoked in two ways:
> First is done by the application to call sctp_bindx() system call.
> Second is automatic operation in the SCTP stack with address events in the host computer (called auto_asconf) .
> The former is already implemented, but the latter is not yet. This patch enables it with one sysctl parameter and setsockopt() system call.
>
> Signed-off-by: Michio Honda <micchie@sfc.wide.ad.jp>
> ---
> diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
> index 11684d9..11c3060 100644
> --- a/include/linux/sysctl.h
> +++ b/include/linux/sysctl.h
> @@ -767,6 +767,7 @@ enum {
> NET_SCTP_SNDBUF_POLICY = 15,
> NET_SCTP_SACK_TIMEOUT = 16,
> NET_SCTP_RCVBUF_POLICY = 17,
> + NET_SCTP_AUTO_ASCONF_ENABLE = 18,
This defined is unnecessary.
> };
>
> /* /proc/sys/net/bridge */
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index 505845d..75ba6a4 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -121,6 +121,7 @@ extern int sctp_copy_local_addr_list(struct sctp_bind_addr *,
> int flags);
> extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
> extern int sctp_register_pf(struct sctp_pf *, sa_family_t);
> +void sctp_addr_wq_mgmt(union sctp_addr *, int);
>
> /*
> * sctp/socket.c
> @@ -135,6 +136,7 @@ void sctp_sock_rfree(struct sk_buff *skb);
> void sctp_copy_sock(struct sock *newsk, struct sock *sk,
> struct sctp_association *asoc);
> extern struct percpu_counter sctp_sockets_allocated;
> +int sctp_asconf_mgmt(struct sctp_endpoint *);
>
> /*
> * sctp/primitive.c
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index cc9185c..3e0351a 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -205,6 +205,11 @@ extern struct sctp_globals {
> * It is a list of sctp_sockaddr_entry.
> */
> struct list_head local_addr_list;
> + int auto_asconf_enable;
> + struct list_head addr_waitq;
> + struct timer_list addr_wq_timer;
> + struct list_head auto_asconf_eplist;
> + spinlock_t addr_wq_lock;
>
> /* Lock that protects the local_addr_list writers */
> spinlock_t addr_list_lock;
> @@ -264,6 +269,11 @@ extern struct sctp_globals {
> #define sctp_port_hashtable (sctp_globals.port_hashtable)
> #define sctp_local_addr_list (sctp_globals.local_addr_list)
> #define sctp_local_addr_lock (sctp_globals.addr_list_lock)
> +#define sctp_auto_asconf_eplist (sctp_globals.auto_asconf_eplist)
> +#define sctp_addr_waitq (sctp_globals.addr_waitq)
> +#define sctp_addr_wq_timer (sctp_globals.addr_wq_timer)
> +#define sctp_addr_wq_lock (sctp_globals.addr_wq_lock)
> +#define sctp_auto_asconf_enable (sctp_globals.auto_asconf_enable)
> #define sctp_scope_policy (sctp_globals.ipv4_scope_policy)
> #define sctp_addip_enable (sctp_globals.addip_enable)
> #define sctp_addip_noauth (sctp_globals.addip_noauth_enable)
> @@ -796,6 +806,15 @@ struct sctp_sockaddr_entry {
> __u8 valid;
> };
>
> +#define SCTP_NEWADDR 1
> +#define SCTP_DELADDR 2
> +#define SCTP_ADDRESS_TICK_DELAY 500
> +struct sctp_addr_wait {
> + struct list_head list;
> + union sctp_addr a;
> + int cmd;
> +};
> +
How about use struct sctp_sockaddr_entry directly? It has all the fields
we need.
> typedef struct sctp_chunk *(sctp_packet_phandler_t)(struct sctp_association *);
>
> /* This structure holds lists of chunks as we are assembling for
> @@ -1239,6 +1258,7 @@ sctp_scope_t sctp_scope(const union sctp_addr *);
> int sctp_in_scope(const union sctp_addr *addr, const sctp_scope_t scope);
> int sctp_is_any(struct sock *sk, const union sctp_addr *addr);
> int sctp_addr_is_valid(const union sctp_addr *addr);
> +int sctp_is_ep_boundall(struct sock *sk);
>
>
> /* What type of endpoint? */
> @@ -1267,6 +1287,7 @@ struct sctp_ep_common {
> /* Fields to help us manage our entries in the hash tables. */
> struct hlist_node node;
> int hashent;
> + struct list_head auto_asconf_list;
>
> /* Runtime type information. What kind of endpoint is this? */
> sctp_endpoint_type_t type;
> @@ -1369,6 +1390,7 @@ struct sctp_endpoint {
> /* SCTP-AUTH: endpoint shared keys */
> struct list_head endpoint_shared_keys;
> __u16 active_key_id;
> + int do_auto_asconf;
> };
>
> /* Recover the outter endpoint structure. */
> diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h
> index e73ebda..75c96b1 100644
> --- a/include/net/sctp/user.h
> +++ b/include/net/sctp/user.h
> @@ -91,6 +91,7 @@ typedef __s32 sctp_assoc_t;
> #define SCTP_PEER_AUTH_CHUNKS 26 /* Read only */
> #define SCTP_LOCAL_AUTH_CHUNKS 27 /* Read only */
> #define SCTP_GET_ASSOC_NUMBER 28 /* Read only */
> +#define SCTP_AUTO_ASCONF 29
>
> /* Internal Socket Options. Some of the sctp library functions are
> * implemented using these socket options.
> diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
> index faf71d1..426715f 100644
> --- a/net/sctp/bind_addr.c
> +++ b/net/sctp/bind_addr.c
> @@ -536,6 +536,23 @@ int sctp_in_scope(const union sctp_addr *addr, sctp_scope_t scope)
> return 0;
> }
>
> +int sctp_is_ep_boundall(struct sock *sk)
> +{
> + struct sctp_bind_addr *bp;
> + struct sctp_sockaddr_entry *addr;
> +
> + bp = &sctp_sk(sk)->ep->base.bind_addr;
> + if (sctp_list_single_entry(&bp->address_list)) {
> + addr = list_entry(bp->address_list.next,
> + struct sctp_sockaddr_entry, list);
> + if (sctp_is_any(sk, &addr->a))
> + return 1;
> + else
> + return 0;
those two lines are unnecessary.
> + }
> + return 1;
should be 'return 0;'
> +}
> +
> /********************************************************************
> * 3rd Level Abstractions
> ********************************************************************/
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index 865ce7b..1b31b4d 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -105,6 +105,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
> addr->valid = 1;
> spin_lock_bh(&sctp_local_addr_lock);
> list_add_tail_rcu(&addr->list, &sctp_local_addr_list);
> + sctp_addr_wq_mgmt(&addr->a, SCTP_NEWADDR);
> spin_unlock_bh(&sctp_local_addr_lock);
> }
> break;
> @@ -115,6 +116,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
> if (addr->a.sa.sa_family == AF_INET6 &&
> ipv6_addr_equal(&addr->a.v6.sin6_addr,
> &ifa->addr)) {
> + sctp_addr_wq_mgmt(&addr->a, SCTP_DELADDR);
> found = 1;
> addr->valid = 0;
> list_del_rcu(&addr->list);
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 152976e..f9e0bd6 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -636,6 +636,194 @@ static void sctp_v4_ecn_capable(struct sock *sk)
> INET_ECN_xmit(sk);
> }
>
> +void sctp_addr_wq_timeout_handler(unsigned long arg)
> +{
> + struct sctp_addr_wait *addrw = NULL;
> + union sctp_addr *addr = NULL;
> + struct sctp_ep_common *epb = NULL;
> + struct sctp_endpoint *ep = NULL;
> +
> + spin_lock_bh(&sctp_addr_wq_lock);
> +retry_wq:
> + if (list_empty(&sctp_addr_waitq)) {
> + SCTP_DEBUG_PRINTK("sctp_addrwq_timo_handler: nothing in addr waitq\n");
> + spin_unlock_bh(&sctp_addr_wq_lock);
> + return;
> + }
retry_wq should be move to here.
> + addrw = list_first_entry(&sctp_addr_waitq, struct sctp_addr_wait, list);
> + if (addrw->cmd != SCTP_NEWADDR && addrw->cmd != SCTP_DELADDR) {
> + SCTP_DEBUG_PRINTK("sctp_addrwq_timo_handler: cmd is neither NEWADDR nor DELADDR\n");
> + list_del(&addrw->list);
> + kfree(addrw);
> + goto retry_wq;
> + }
> +
> + addr = &addrw->a;
> + SCTP_DEBUG_PRINTK_IPADDR("sctp_addrwq_timo_handler: the first ent in wq %p is ",
> + " for cmd %d at entry %p\n", &sctp_addr_waitq, addr, addrw->cmd,
> + addrw);
> +
> + /* Now we send an ASCONF for each association */
> + /* Note. we currently don't handle link local IPv6 addressees */
> + if (addr->sa.sa_family == AF_INET6) {
> + struct in6_addr *in6 = (struct in6_addr *)&addr->v6.sin6_addr;
> +
> + if (ipv6_addr_type(&addr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) {
> + SCTP_DEBUG_PRINTK("sctp_timo_handler: link local, hence don't tell eps\n");
> + list_del(&addrw->list);
> + kfree(addrw);
> + goto retry_wq;
> + }
> + if (ipv6_chk_addr(&init_net, in6, NULL, 0) == 0 &&
> + addrw->cmd == SCTP_NEWADDR) {
> + unsigned long timeo_val;
> +
> + SCTP_DEBUG_PRINTK("sctp_timo_handler: this is on DAD, trying %d sec later\n",
> + SCTP_ADDRESS_TICK_DELAY);
> + timeo_val = jiffies;
> + timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY);
> + (void)mod_timer(&sctp_addr_wq_timer, timeo_val);
> + spin_unlock_bh(&sctp_addr_wq_lock);
> + return;
> + }
> + }
> + list_for_each_entry(epb, &sctp_auto_asconf_eplist, auto_asconf_list) {
> + if (epb == NULL) {
> + SCTP_DEBUG_PRINTK("addrwq_timo_handler: no epb\n");
> + continue;
> + }
> + if (!sctp_is_ep_boundall(epb->sk))
> + /* ignore bound-specific endpoints */
> + continue;
> + ep = sctp_ep(epb);
> + sctp_bh_lock_sock(epb->sk);
> + if (sctp_asconf_mgmt(ep) < 0) {
since you process only one ip each time, your should take an address param.
> + SCTP_DEBUG_PRINTK("sctp_addrwq_timo_handler: sctp_asconf_mgmt failed\n");
> + sctp_bh_unlock_sock(epb->sk);
> + continue;
> + }
> + sctp_bh_unlock_sock(epb->sk);
> + }
> +
> + list_del(&addrw->list);
> + kfree(addrw);
> +
> + if (list_empty(&sctp_addr_waitq)) {
> + spin_unlock_bh(&sctp_addr_wq_lock);
> + return;
> + } else
> + goto retry_wq;
better to use if (!list_empty(&sctp_addr_waitq))
goto retry_wq;
> +
> + spin_unlock_bh(&sctp_addr_wq_lock);
> +}
> +
> +static void sctp_free_addr_wq()
> +{
> + struct sctp_addr_wait *addrw = NULL;
> + struct sctp_addr_wait *temp = NULL;
> +
> + spin_lock_bh(&sctp_addr_wq_lock);
> + (void)del_timer(&sctp_addr_wq_timer);
(void) is useless.
> + list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) {
> + list_del(&addrw->list);
> + kfree(addrw);
> + }
> + spin_unlock_bh(&sctp_addr_wq_lock);
> +}
> +
> +void sctp_addr_wq_mgmt(union sctp_addr *reqaddr, int cmd)
> +{
> + struct sctp_addr_wait *addrw = NULL;
> + struct sctp_addr_wait *addrw_new = NULL;
> + unsigned long timeo_val;
> + union sctp_addr *tmpaddr;
> +
> + /* first, we check if an opposite message already exist in the queue.
> + * If we found such message, it is removed.
> + * This operation is a bit stupid, but the DHCP client attaches the
> + * new address after a couple of addition and deletion of that address
> + */
> +
> + if (reqaddr == NULL) {
> + SCTP_DEBUG_PRINTK("sctp_addr_wq_mgmt: no address message?\n");
> + return;
> + }
reqaddr never be NULL.
> +
> + spin_lock_bh(&sctp_addr_wq_lock);
> + /* Offsets existing events in addr_wq */
> + list_for_each_entry(addrw, &sctp_addr_waitq, list) {
> + if (addrw->a.sa.sa_family != reqaddr->sa.sa_family)
> + continue;
> + if (reqaddr->sa.sa_family == AF_INET) {
> + if (reqaddr->v4.sin_addr.s_addr ==
> + addrw->a.v4.sin_addr.s_addr) {
> + if (cmd != addrw->cmd) {
> + tmpaddr = &addrw->a;
> + SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt offsets existing entry for %d ",
> + " in waitq %p\n", addrw->cmd,
> + tmpaddr, &sctp_addr_waitq);
> + list_del(&addrw->list);
> + kfree(addrw);
> + /* nothing to do anymore */
> + spin_unlock_bh(&sctp_addr_wq_lock);
> + return;
> + }
> + }
> + } else if (reqaddr->sa.sa_family == AF_INET6) {
> + if (ipv6_addr_equal(&reqaddr->v6.sin6_addr,
> + &addrw->a.v6.sin6_addr)) {
> + if (cmd != addrw->cmd) {
> + tmpaddr = &addrw->a;
> + SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt: offsets existing entry for %d ",
> + " in waitq %p\n", addrw->cmd,
> + tmpaddr, &sctp_addr_waitq);
> + list_del(&addrw->list);
> + kfree(addrw);
> + spin_unlock_bh(&sctp_addr_wq_lock);
> + return;
> + }
> + }
> + }
> + }
The above code can split to other function, sush as sctp_addr_wq_lookup().
If we found one address is exists, and different cmd, delete this address,
with same cmd, just return.
> +
> + /* OK, we have to add the new address to the wait queue */
> + addrw_new = kzalloc(sizeof(struct sctp_addr_wait), GFP_ATOMIC);
> + if (addrw_new == NULL) {
> + SCTP_DEBUG_PRINTK("sctp_addr_weitq_mgmt no memory? return\n");
> + spin_unlock_bh(&sctp_addr_wq_lock);
> + return;
> + }
> + if (reqaddr->sa.sa_family == AF_INET) {
> + addrw_new->a.v4.sin_family = AF_INET;
> + addrw_new->a.v4.sin_addr.s_addr = reqaddr->v4.sin_addr.s_addr;
> + } else if (reqaddr->sa.sa_family == AF_INET6) {
> + addrw_new->a.v6.sin6_family = AF_INET6;
> + ipv6_addr_copy(&addrw_new->a.v6.sin6_addr,
> + &reqaddr->v6.sin6_addr);
> + } else {
> + SCTP_DEBUG_PRINTK("sctp_addr_waitq_mgmt: Unknown family of request addr, return\n");
> + kfree(addrw_new);
> + spin_unlock_bh(&sctp_addr_wq_lock);
> + return;
> + }
> + addrw_new->cmd = cmd;
If we struct sctp_sockaddr_entry *addr, the above code will be very
simple:
addr_new = kmemdup(addr, sizeof(*addr), GFP_ATOMIC);
> + list_add_tail(&addrw_new->list, &sctp_addr_waitq);
> + tmpaddr = &addrw_new->a;
> + SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt add new entry for cmd:%d ",
> + " in waitq %p, start a timer\n",
> + addrw_new->cmd, tmpaddr, &sctp_addr_waitq);
> +
> + if (timer_pending(&sctp_addr_wq_timer)) {
> + SCTP_DEBUG_PRINTK("sctp_addr_wq_mgmt: addr_wq timer is already running\n");
> + spin_unlock_bh(&sctp_addr_wq_lock);
> + return;
> + }
> + timeo_val = jiffies;
> + timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY);
> + (void)mod_timer(&sctp_addr_wq_timer, timeo_val);
if (!timer_pending(&sctp_addr_wq_timer))
mod_timer(&sctp_addr_wq_timer, jiffies + ... );
> + spin_unlock_bh(&sctp_addr_wq_lock);
> +}
> +
> /* Event handler for inet address addition/deletion events.
> * The sctp_local_addr_list needs to be protocted by a spin lock since
> * multiple notifiers (say IPv4 and IPv6) may be running at the same
> @@ -663,6 +851,7 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
> addr->valid = 1;
> spin_lock_bh(&sctp_local_addr_lock);
> list_add_tail_rcu(&addr->list, &sctp_local_addr_list);
> + sctp_addr_wq_mgmt(&addr->a, SCTP_NEWADDR);
> spin_unlock_bh(&sctp_local_addr_lock);
> }
> break;
> @@ -673,6 +862,7 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
> if (addr->a.sa.sa_family == AF_INET &&
> addr->a.v4.sin_addr.s_addr ==
> ifa->ifa_local) {
> + sctp_addr_wq_mgmt(&addr->a, SCTP_DELADDR);
> found = 1;
> addr->valid = 0;
> list_del_rcu(&addr->list);
> @@ -1280,6 +1470,14 @@ SCTP_STATIC __init int sctp_init(void)
> spin_lock_init(&sctp_local_addr_lock);
> sctp_get_local_addr_list();
>
> + /* Initialize the address event list */
> + INIT_LIST_HEAD(&sctp_addr_waitq);
> + INIT_LIST_HEAD(&sctp_auto_asconf_eplist);
> + spin_lock_init(&sctp_addr_wq_lock);
> + sctp_addr_wq_timer.expires = 0;
> + setup_timer(&sctp_addr_wq_timer, sctp_addr_wq_timeout_handler,
> + (unsigned long)NULL);
> +
setup_timer(&sctp_addr_wq_timer, sctp_addr_wq_timeout_handler, 0);
> status = sctp_v4_protosw_init();
>
> if (status)
> @@ -1344,6 +1542,7 @@ err_chunk_cachep:
> /* Exit handler for the SCTP protocol. */
> SCTP_STATIC __exit void sctp_exit(void)
> {
> + sctp_free_addr_wq();
> /* BUG. This should probably do something useful like clean
> * up all the remaining associations and all that memory.
> */
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index 3951a10..27dffa3 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -807,6 +807,47 @@ out:
> return retval;
> }
>
> +/* set addr events to assocs in the endpoint. ep and addr_wq must be locked */
> +int
> +sctp_asconf_mgmt(struct sctp_endpoint *ep)
hmm, it seem we should take a struct sock * as the param
or struct sctp_sock *.
and the auto_asconf_list can take the sock list, not ep list.
> +{
> + struct sock *sk = ep->base.sk;
> + struct sctp_addr_wait *addrw = NULL;
> + union sctp_addr *addr = NULL;
> + int cmd;
> + int error = 0;
> +
> + if (ep == NULL || sk == NULL)
> + return -EINVAL;
> + if (list_empty(&sctp_addr_waitq)) {
> + SCTP_DEBUG_PRINTK("asconf_mgmt: nothing in the wq\n");
> + return -EINVAL;
> + }
> + addrw = list_first_entry(&sctp_addr_waitq, struct sctp_addr_wait, list);
> + if (addrw->cmd != SCTP_NEWADDR && addrw->cmd != SCTP_DELADDR)
> + return -EINVAL;
> + addr = &addrw->a;
> + addr->v4.sin_port = htons(ep->base.bind_addr.port);
> + cmd = addrw->cmd;
> +
> + SCTP_DEBUG_PRINTK("sctp_asconf_mgmt sk:%p ep:%p\n", sk, ep);
> + if (cmd == SCTP_NEWADDR) {
> + error = sctp_send_asconf_add_ip(sk, (struct sockaddr *)addr, 1);
> + if (error) {
> + SCTP_DEBUG_PRINTK("asconf_mgmt: send_asconf_add_ip returns %d\n", error);
> + return error;
> + }
> + } else if (cmd == SCTP_DELADDR) {
> + error = sctp_send_asconf_del_ip(sk, (struct sockaddr *)addr, 1);
> + if (error) {
> + SCTP_DEBUG_PRINTK("asconf_mgmt: send_asconf_del_ip returns %d\n", error);
> + return error;
> + }
> + }
> +
> + return 0;
> +}
> +
> /* Helper for tunneling sctp_bindx() requests through sctp_setsockopt()
> *
> * API 8.1
> @@ -3341,6 +3382,45 @@ static int sctp_setsockopt_del_key(struct sock *sk,
>
> }
>
> +/*
> + * 8.1.23 SCTP_AUTO_ASCONF
> + *
> + * This option will enable or disable the use of the automatic generation of
> + * ASCONF chunks to add and delete addresses to an existing association. Note
> + * that this option has two caveats namely: a) it only affects sockets that
> + * are bound to all addresses available to the SCTP stack, and b) the system
> + * administrator may have an overriding control that turns the ASCONF feature
> + * off no matter what setting the socket option may have.
> + * This option expects an integer boolean flag, where a non-zero value turns on
> + * the option, and a zero value turns off the option.
> + * Note. In this implementation, socket operation overrides default parameter
> + * being set by sysctl as well as FreeBSD implementation
> + */
> +static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval,
> + unsigned int optlen)
> +{
> + int val;
> + struct sctp_endpoint *ep = sctp_sk(sk)->ep;
> +
> + if (optlen < sizeof(int))
> + return -EINVAL;
> + if (get_user(val, (int __user *)optval))
> + return -EFAULT;
> + if (!sctp_is_ep_boundall(sk) && val)
> + return -EINVAL;
> + if ((val && ep->do_auto_asconf) || (!val && !ep->do_auto_asconf))
> + return 0;
> +
> + if (val == 0 && ep->do_auto_asconf) {
> + list_del(&ep->base.auto_asconf_list);
> + ep->do_auto_asconf = 0;
> + } else if (val && !ep->do_auto_asconf) {
> + list_add_tail(&ep->base.auto_asconf_list,
> + &sctp_auto_asconf_eplist);
> + ep->do_auto_asconf = 1;
> + }
> + return 0;
> +}
>
> /* API 6.2 setsockopt(), getsockopt()
> *
> @@ -3488,6 +3568,9 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
> case SCTP_AUTH_DELETE_KEY:
> retval = sctp_setsockopt_del_key(sk, optval, optlen);
> break;
> + case SCTP_AUTO_ASCONF:
> + retval = sctp_setsockopt_auto_asconf(sk, optval, optlen);
> + break;
> default:
> retval = -ENOPROTOOPT;
> break;
> @@ -3770,6 +3853,13 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
> local_bh_disable();
> percpu_counter_inc(&sctp_sockets_allocated);
> sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
> + if (sctp_auto_asconf_enable) {
> + list_add_tail(&ep->base.auto_asconf_list,
> + &sctp_auto_asconf_eplist);
> + ep->do_auto_asconf = 1;
> + } else
> + ep->do_auto_asconf = 0;
> + SCTP_DEBUG_PRINTK("sctp_init_sk sk:%p ep:%p\n", sk, ep);
> local_bh_enable();
>
> return 0;
> @@ -3784,6 +3874,10 @@ SCTP_STATIC void sctp_destroy_sock(struct sock *sk)
>
> /* Release our hold on the endpoint. */
> ep = sctp_sk(sk)->ep;
> + if (ep->do_auto_asconf) {
> + ep->do_auto_asconf = 0;
> + list_del(&ep->base.auto_asconf_list);
> + }
> sctp_endpoint_free(ep);
> local_bh_disable();
> percpu_counter_dec(&sctp_sockets_allocated);
> @@ -5283,6 +5377,28 @@ static int sctp_getsockopt_assoc_number(struct sock *sk, int len,
> return 0;
> }
>
> +/*
> + * 8.1.23 SCTP_AUTO_ASCONF
> + * See the corresponding setsockopt entry as description
> + */
> +static int sctp_getsockopt_auto_asconf(struct sock *sk, int len,
> + char __user *optval, int __user *optlen)
> +{
> + int val = 0;
> +
> + if (len < sizeof(int))
> + return -EINVAL;
> +
> + len = sizeof(int);
> + if (sctp_sk(sk)->ep->do_auto_asconf && sctp_is_ep_boundall(sk))
> + val = 1;
> + if (put_user(len, optlen))
> + return -EFAULT;
> + if (copy_to_user(optval, &val, len))
> + return -EFAULT;
> + return 0;
> +}
> +
> SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
> char __user *optval, int __user *optlen)
> {
> @@ -5415,6 +5531,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
> case SCTP_GET_ASSOC_NUMBER:
> retval = sctp_getsockopt_assoc_number(sk, len, optval, optlen);
> break;
> + case SCTP_AUTO_ASCONF:
> + retval = sctp_getsockopt_auto_asconf(sk, len, optval, optlen);
> + break;
> default:
> retval = -ENOPROTOOPT;
> break;
> diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
> index 50cb57f..df39789 100644
> --- a/net/sctp/sysctl.c
> +++ b/net/sctp/sysctl.c
> @@ -183,6 +183,13 @@ static ctl_table sctp_table[] = {
> .proc_handler = proc_dointvec,
> },
> {
> + .procname = "auto_asconf_enable",
> + .data = &sctp_auto_asconf_enable,
> + .maxlen = sizeof(int),
> + .mode = 0644,
> + .proc_handler = proc_dointvec,
> + },
> + {
> .procname = "prsctp_enable",
> .data = &sctp_prsctp_enable,
> .maxlen = sizeof(int),
>
>
sctp_auto_asconf_enable should have a default value to 0.
This patch should also be split to three.
sctp: provide sysctl to enable/disable auto asconf
sctp: add auto-asconf support
sctp: implement socket option SCTP_AUTO_ASCONF
^ permalink raw reply
* [PATCH RESEND] uts: Set default hostname to "localhost", rather than "(none)"
From: Josh Triplett @ 2011-04-11 5:01 UTC (permalink / raw)
To: David Miller, netdev, Serge E. Hallyn, Andrew Morton,
Linus Torvalds
The "hostname" tool falls back to setting the hostname to "localhost" if
/etc/hostname does not exist. Distribution init scripts have the same
fallback. However, if userspace never calls sethostname, such as when
booting with init=/bin/sh, or otherwise booting a minimal system without
the usual init scripts, the default hostname of "(none)" remains,
unhelpfully appearing in various places such as prompts
("root@(none):~#") and logs. Furthrmore, "(none)" doesn't typically
resolve to anything useful, while "localhost" does.
Change the default hostname to "localhost". This removes the need for
the standard fallback, provides a useful default for systems that never
call sethostname, and makes minimal systems that much more useful with
less configuration.
Signed-off-by: Josh Triplett <josh@joshtriplett.org>
---
Looked at "(none)" one too many times, and figured I ought to do
something about it.
Resending, and adding CCs for networking and UTS.
include/linux/uts.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/include/linux/uts.h b/include/linux/uts.h
index 73eb1ed..610bec2 100644
--- a/include/linux/uts.h
+++ b/include/linux/uts.h
@@ -9,7 +9,7 @@
#endif
#ifndef UTS_NODENAME
-#define UTS_NODENAME "(none)" /* set by sethostname() */
+#define UTS_NODENAME "localhost" /* set by sethostname() */
#endif
#ifndef UTS_DOMAINNAME
--
1.7.4.1
^ permalink raw reply related
* [GIT] Networking
From: David Miller @ 2011-04-11 4:31 UTC (permalink / raw)
To: torvalds; +Cc: akpm, netdev, linux-kernel
There is going to be a merge conflict to resolve, due to the tree
wide spelling fixes that went in last week, but it's trivial to
resolve.
1) ipset bug fixes from Jozsef Kadlecsik.
2) Fix regression in rt_iif management in ipv4 routes, reported
and fixed by OGAWA Hirofumi.
3) Link sensing and RX ring buffer corruption fixes in mlx4 driver,
from Yevgeny Petrilin.
4) Add some IDs to smsc95xx driver, from Steve Glendinning.
5) Add some IDs to mv88e6131 driver, from Peter Korsgaard.
6) Fix dead loop in pppoe driver, from Ulrich Weber.
7) Fix suspend/resume in be2net driver, from Padmanabh Ratnakar and
Sarveswara Rao Mygapula.
8) B43 wireless doesn't allocate large enough RX buffers, from John
W. Linville.
9) Array missing entry for 9485 revisions in ath9k driver, fix from
Senthil Balasubramanian.
10) Fix duplicate wireless frames on cooked monitor, from Helmut
Schaa.
11) Validate NVS file struct descriptor length given by the user,
fix from Luciano Coelho.
12) Add IDs to p54usb driver, from Christian Lamparter.
13) Don't try to cancel work that never was created in rt2x00 driver,
from Stanislaw Gruszka.
14) Fix mac_lock handling in smsc911x driver, from Enric Balletbo i Serra.
15) Handle firmware heartbeat failure properly in bnx driver, from
Rasesh Mody and Debashis Dutt.
16) Fix shutdown crash in be2net driver, from Ajit Khaparde.
17) Missed setting rxhash of socket in ipv6 code, from Neil Horman.
Please pull, thanks a lot!
The following changes since commit 4263a2f1dad8c8e7ce2352a0cbc882c2b0c044a9:
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6 (2011-04-10 09:56:10 -0700)
are available in the git repository at:
master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6.git master
Ajit Khaparde (1):
be2net: Fix a potential crash during shutdown.
Christian Lamparter (1):
p54usb: IDs for two new devices
David S. Miller (2):
Merge branch 'master' of git://git.kernel.org/.../kaber/nf-2.6
Merge branch 'master' of git://git.kernel.org/.../linville/wireless-2.6
David Sterba (1):
netfilter: h323: bug in parsing of ASN1 SEQOF field
Enric Balletbo i Serra (2):
smsc911x: fix mac_lock acquision before calling smsc911x_mac_read
can: mcp251x: Allow pass IRQ flags through platform data.
Florian Westphal (4):
netfilter: af_info: add network namespace parameter to route hook
netfilter: af_info: add 'strict' parameter to limit lookup to .oif
netfilter: xt_addrtype: replace rt6_lookup with nf_afinfo->route
netfilter: xt_conntrack: fix inverted conntrack direction test
Hans Schillstrom (1):
IPVS: fix NULL ptr dereference in ip_vs_ctl.c ip_vs_genl_dump_daemons()
Helmut Schaa (1):
mac80211: Fix duplicate frames on cooked monitor
Ian Campbell (1):
MAINTAINERS: add entry for Xen network backend
Johannes Berg (1):
mac80211: fix comment regarding aggregation buf_size
John W. Linville (2):
b43: allocate receive buffers big enough for max frame len + offset
iwlwifi: accept EEPROM version 0x423 for iwl6000
Jozsef Kadlecsik (2):
netfilter: ipset: list:set timeout variant fixes
netfilter: ipset: references are protected by rwlock instead of mutex
Jussi Kivilinna (2):
zd1211rw: remove URB_SHORT_NOT_OK flag in zd_usb_iowrite16v_async()
zd1211rw: reset rx idle timer from tasklet
Larry Finger (1):
rtlwifi: Fix some warnings/bugs
Luciano Coelho (2):
wl12xx: fix module author's email address in the spi and sdio modules
wl12xx: fix potential buffer overflow in testmode nvs push
Neil Horman (1):
ipv6: Enable RFS sk_rxhash tracking for ipv6 sockets (v2)
OGAWA Hirofumi (1):
ipv4: Fix "Set rt->rt_iif more sanely on output routes."
Padmanabh Ratnakar (2):
be2net: Rename some struct members for clarity
be2net: Fix suspend/resume operation
Peter Korsgaard (1):
dsa/mv88e6131: add support for mv88e6085 switch
Rasesh Mody (1):
bna: Fix for handling firmware heartbeat failure
Senthil Balasubramanian (1):
ath9k: Fix phy info print message with AR9485 chipset.
Stanislaw Gruszka (1):
rt2x00: fix cancelling uninitialized work
Steve Glendinning (1):
net: Add support for SMSC LAN9530, LAN9730 and LAN89530
Ulrich Weber (1):
pppoe: drop PPPOX_ZOMBIEs in pppoe_flush_dev
Yevgeny Petrilin (2):
mlx4: Sensing link type at device initialization
mlx4_en: Restoring RX buffer pointer in case of failure
MAINTAINERS | 7 ++
drivers/net/benet/be.h | 4 +-
drivers/net/benet/be_main.c | 19 ++--
drivers/net/bna/bfa_ioc.c | 10 +--
drivers/net/can/mcp251x.c | 3 +-
drivers/net/mlx4/en_rx.c | 4 +
drivers/net/mlx4/main.c | 5 +
drivers/net/mlx4/mlx4.h | 2 +
drivers/net/mlx4/sense.c | 4 +-
drivers/net/pppoe.c | 2 +-
drivers/net/smsc911x.c | 8 +-
drivers/net/usb/smsc95xx.c | 15 +++
drivers/net/wireless/ath/ath9k/hw.c | 1 +
drivers/net/wireless/b43/dma.c | 2 +-
drivers/net/wireless/b43/dma.h | 2 +-
drivers/net/wireless/iwlwifi/iwl-eeprom.h | 2 +-
drivers/net/wireless/p54/p54usb.c | 2 +
drivers/net/wireless/rt2x00/rt2x00dev.c | 6 +-
drivers/net/wireless/rtlwifi/efuse.c | 2 +-
drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | 2 +-
drivers/net/wireless/rtlwifi/usb.c | 2 +-
drivers/net/wireless/wl12xx/sdio.c | 2 +-
drivers/net/wireless/wl12xx/spi.c | 2 +-
drivers/net/wireless/wl12xx/testmode.c | 5 +-
drivers/net/wireless/zd1211rw/zd_usb.c | 20 ++++-
drivers/net/wireless/zd1211rw/zd_usb.h | 1 +
include/linux/can/platform/mcp251x.h | 2 +
include/linux/netfilter.h | 3 +-
include/linux/netfilter/ipset/ip_set.h | 2 +-
include/linux/netfilter/ipset/ip_set_ahash.h | 3 +-
include/net/ip_vs.h | 2 +-
include/net/mac80211.h | 15 +++-
include/net/route.h | 5 +-
net/dsa/mv88e6131.c | 23 ++++-
net/dsa/mv88e6xxx.h | 2 +
net/ipv4/netfilter.c | 5 +-
net/ipv4/route.c | 8 +-
net/ipv4/xfrm4_policy.c | 1 +
net/ipv6/netfilter.c | 13 ++-
net/ipv6/tcp_ipv6.c | 4 +-
net/ipv6/udp.c | 3 +
net/mac80211/rx.c | 2 +-
net/netfilter/Kconfig | 1 -
net/netfilter/ipset/ip_set_bitmap_ip.c | 3 +-
net/netfilter/ipset/ip_set_bitmap_ipmac.c | 3 +-
net/netfilter/ipset/ip_set_bitmap_port.c | 3 +-
net/netfilter/ipset/ip_set_core.c | 109 +++++++++++++--------
net/netfilter/ipset/ip_set_list_set.c | 53 +++++------
net/netfilter/ipvs/ip_vs_ctl.c | 2 +-
net/netfilter/nf_conntrack_h323_asn1.c | 2 +-
net/netfilter/nf_conntrack_h323_main.c | 16 ++--
net/netfilter/xt_TCPMSS.c | 2 +-
net/netfilter/xt_addrtype.c | 42 ++++++---
net/netfilter/xt_conntrack.c | 2 +-
54 files changed, 301 insertions(+), 164 deletions(-)
^ permalink raw reply
* Re: [PATCH net-next-2.6 v3 0/3] sctp: Patch series
From: Wei Yongjun @ 2011-04-11 2:19 UTC (permalink / raw)
To: David Miller; +Cc: micchie, netdev, linux-sctp
In-Reply-To: <20110410.185236.59685173.davem@davemloft.net>
> From: Michio Honda <micchie@sfc.wide.ad.jp>
> Date: Fri, 8 Apr 2011 14:18:30 +0900
>
> [ Changed lksctp to linux-sctp@vger.kernel.org as that is the mailing
> list provided in linux/MAINTAINERS ]
>
>> Series of 5 patches to support auto_asconf and the other related
>> functionalities that auto_asconf relies on.
> ...
>> [1/3] Add Auto-ASCONF support
>> [2/3] Add ASCONF operation on the single-homed host
>> [3/3] Add a valid address list in association local
> Can an SCTP expert please review these patches?
I am review these patches now, I will check ASAP, but this will
spend some time since this patchset is too big. :-)
^ permalink raw reply
* Re: [PATCH] Add support for SMSC LAN9530, LAN9730 and LAN89530
From: David Miller @ 2011-04-11 1:59 UTC (permalink / raw)
To: steve.glendinning; +Cc: netdev
In-Reply-To: <1302288719-17103-1-git-send-email-steve.glendinning@smsc.com>
From: Steve Glendinning <steve.glendinning@smsc.com>
Date: Fri, 8 Apr 2011 19:51:59 +0100
> This patch adds support for SMSC's LAN9530, LAN9730 and LAN89530 USB
> ethernet controllers to the existing smsc95xx driver by adding
> their new USB VID/PID pairs.
>
> Signed-off-by: Steve Glendinning <steve.glendinning@smsc.com>
Applied, thanks.
^ permalink raw reply
* Re: [net-next PATCH 1/3] vxge: always enable hardware time stamp
From: David Miller @ 2011-04-11 1:58 UTC (permalink / raw)
To: jdmason; +Cc: netdev
In-Reply-To: <1302297083-22665-1-git-send-email-jdmason@kudzu.us>
From: Jon Mason <jdmason@kudzu.us>
Date: Fri, 8 Apr 2011 16:11:21 -0500
> Hardware time stamp calculation can only be enabled by the privileged
> function. Enable it always by default and simply use the ethtool
> interface to set a flag to indicate whether or not the respective
> function driver should indicate the timestamp along with the received
> packet.
>
> Also, make certain fields in vxge_hw_device_config bit-fields to reduce
> the size of the struct.
>
> Signed-off-by: Jon Mason <jdmason@kudzu.us>
Doesn't this have some performance or latency impact?
I think it should be stay off by default, people who want this know
they want it and can turn it on if they want to.
^ permalink raw reply
* Re: [PATCH] net: bnx2: convert to hw_features
From: David Miller @ 2011-04-11 1:57 UTC (permalink / raw)
To: mirq-linux; +Cc: netdev, mchan
In-Reply-To: <20110410144746.AAFBF13A64@rere.qmqm.pl>
From: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Date: Sun, 10 Apr 2011 16:47:46 +0200 (CEST)
> Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Applied.
^ permalink raw reply
* Re: [PATCH] net: ksz884x: convert to hw_features
From: David Miller @ 2011-04-11 1:56 UTC (permalink / raw)
To: mirq-linux; +Cc: netdev, Tristram.Ha
In-Reply-To: <20110410131321.BE47D13909@rere.qmqm.pl>
From: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Date: Sun, 10 Apr 2011 15:13:21 +0200 (CEST)
> This also fixes possible race when changing receive checksum state
> and removes IPV6_CSUM_GEN_HACK as it's always set.
>
> BTW, The claim about fake IPV6 checksum looks dubious. If that were true,
> then there's a problem in networking core and should be fixed there and not
> in random drivers.
>
> BTW#2, there's no MAINTAINERS entry for this driver. I assume this driver
> is supported by Micrel?
>
> Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Applied.
^ permalink raw reply
* Re: [PATCH] net: via-velocity: convert to hw_features
From: David Miller @ 2011-04-11 1:56 UTC (permalink / raw)
To: mirq-linux; +Cc: netdev, romieu
In-Reply-To: <20110410131321.A6EA9138DD@rere.qmqm.pl>
From: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Date: Sun, 10 Apr 2011 15:13:21 +0200 (CEST)
> Trivial conversion.
>
> This also enables toggling TX VLAN offload and fixes TX checksumming
> race with offload changes.
>
> Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Applied.
^ permalink raw reply
* Re: [PATCH] net: stmmac: convert to hw_features
From: David Miller @ 2011-04-11 1:56 UTC (permalink / raw)
To: mirq-linux; +Cc: netdev, peppe.cavallaro
In-Reply-To: <20110409124655.A015B13909@rere.qmqm.pl>
From: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Date: Sat, 9 Apr 2011 14:46:55 +0200 (CEST)
> This also removes TSO as it's made fully in software --- better to leave this
> to networking core.
>
> If the MAC features can be detected at probe time and not at open, then
> stmmac_fix_features could be simplified by limiting hw_features. That's
> also better for users as they don't see offloads being togglable but
> never turned on.
>
> Redundant fallbacks for TX csum are removed as it's already handled
> by network core.
>
> Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Applied.
^ permalink raw reply
* Re: [PATCH] net: 8139cp: convert to hw_features
From: David Miller @ 2011-04-11 1:56 UTC (permalink / raw)
To: mirq-linux; +Cc: netdev
In-Reply-To: <20110409105818.F217813909@rere.qmqm.pl>
From: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Date: Sat, 9 Apr 2011 12:58:18 +0200 (CEST)
> Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Applied.
^ permalink raw reply
* Re: [PATCH v2] net: r8169: convert to hw_features
From: David Miller @ 2011-04-11 1:55 UTC (permalink / raw)
To: mirq-linux; +Cc: netdev, romieu, dave
In-Reply-To: <20110408163556.D8D1213909@rere.qmqm.pl>
From: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Date: Fri, 8 Apr 2011 18:35:56 +0200 (CEST)
> Simple conversion with a bit of needed cleanup.
>
> This also fixes:
> - confusion around vlan_features in rtl8169_vlan_mode(),
> - problem with broken TSO for too big MTU (the limit is set
> at 0xFFF --- max MSS field value).
>
> SG+IP_CSUM+TSO is left disabled by default, based on suggestion by
> David Dillow.
>
> Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Applied.
^ permalink raw reply
* Re: [PATCH] net: benet: convert to hw_features - fixup
From: David Miller @ 2011-04-11 1:55 UTC (permalink / raw)
To: mirq-linux; +Cc: netdev, sathya.perla, subbu.seetharaman, ajit.khaparde
In-Reply-To: <20110408123847.76855138DD@rere.qmqm.pl>
From: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Date: Fri, 8 Apr 2011 14:38:47 +0200 (CEST)
> Fix up after merge with NETIF_F_RXHASH implementation.
>
> This allows to toggle NETIF_F_RXHASH and NETIF_F_HW_VLAN_TX.
>
> Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Applied.
^ permalink raw reply
* Re: [PATCH] net: Remove invalid offloads
From: David Miller @ 2011-04-11 1:55 UTC (permalink / raw)
To: mirq-linux; +Cc: netdev, pantelis.antoniou, vbordug, leoli, linuxppc-dev
In-Reply-To: <20110408123846.D947E13909@rere.qmqm.pl>
From: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Date: Fri, 8 Apr 2011 14:38:46 +0200 (CEST)
> Remove offload changing ethtool ops which drivers don't really support:
>
> - fs_enet
> - ucc_geth
>
> Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Applied.
^ 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