* Re: suspicious RCU usage warnings in 3.3.0
From: David Miller @ 2012-04-12 1:08 UTC (permalink / raw)
To: paulmck; +Cc: shemminger, mroos, linux-kernel, netdev
In-Reply-To: <20120412004507.GF2473@linux.vnet.ibm.com>
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Date: Wed, 11 Apr 2012 17:45:07 -0700
> If I am confused about the simple function call, and if control is really
> passing via an interrupt or exception, then rcu_irq_enter() should be
> called on entry to the interrupt or exception and rcu_irq_exit() should
> be called on exit.
Hmm, it seems the convention changed such that platforms aren't
supposed to invoke do_softirq() from their trap return trap any more.
It's handled completely by irq_exit().
When did that start happening? :-)
Anyways I bet that's the problem, sparc64 invokes do_softirq() in it's
trap return path if softirqs are pending, and that doesn't do any
of the RCU frobbing you mention.
^ permalink raw reply
* Re: suspicious RCU usage warnings in 3.3.0
From: Paul E. McKenney @ 2012-04-12 1:53 UTC (permalink / raw)
To: David Miller; +Cc: shemminger, mroos, linux-kernel, netdev
In-Reply-To: <20120411.210319.370705937753558953.davem@davemloft.net>
On Wed, Apr 11, 2012 at 09:03:19PM -0400, David Miller wrote:
> From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
> Date: Wed, 11 Apr 2012 17:45:07 -0700
>
> > On Wed, Apr 11, 2012 at 08:18:54PM -0400, David Miller wrote:
> >> From: Stephen Hemminger <shemminger@vyatta.com>
> >> Date: Wed, 11 Apr 2012 17:10:04 -0700
> >>
> >> > On Wed, 11 Apr 2012 16:08:37 -0700
> >> > "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> wrote:
> >> >
> >> >> Hmmm... What CPU family is this running on? From the look of the
> >> >> stack, it is sneaking out of idle into softirq without telling RCU.
> >> >> This would cause RCU to complain bitterly about being invoked from
> >> >> the idle loop -- and RCU ignores CPUs in the idle loop.
> >> >>
> >> >> Thanx, Paul
> >> >
> >> > Sun4... Ping David.
> >>
> >> So is there anything specific I need to do in the sparc64
> >> idle loop?
> >
> > Hmmm... I must confess that I don't immediately see how control
> > is passing from cpu_idle() in arch/sparc/kernel/process_64.c to
> > __handle_softirq().
> >
> > But it looks like a simple function call in the call trace:
>
> It's coming from the trap return code path at the end of hardware
> interrupt processing, on the IRQ stack.
Ah! I should have guessed something like that was happening given
that __handle_softirq() is written in assembly.
Thanx, Paul
^ permalink raw reply
* linux-next: build failure after merge of the wireless-next tree
From: Stephen Rothwell @ 2012-04-12 2:24 UTC (permalink / raw)
To: John W. Linville
Cc: linux-next, linux-kernel, Thomas Pedersen, David Miller, netdev
[-- Attachment #1: Type: text/plain, Size: 1844 bytes --]
Hi John,
After merging the wireless-next tree, today's linux-next build (x86_64
allmodconfig) failed like this:
net/wireless/nl80211.c: In function 'nl80211_ch_switch_notify':
net/wireless/nl80211.c:8060:2: error: implicit declaration of function 'NLA_PUT_U32' [-Werror=implicit-function-declaration]
Caused by commit 5314526b1743 ("cfg80211: add channel switch notify
event") interacting with commit 9360ffd18597 ("wireless: Stop using
NLA_PUT*()") from the net-next tree.
I added the following merge fix patch.
John, you may like to cherry-pick that commit from Dave's tree (or back
merge that part of Dave's tree or get Dave to merge you tree and start
further work on top of the merge).
From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Thu, 12 Apr 2012 12:21:01 +1000
Subject: [PATCH] cfg80211: NLA_PUT_U32 api change merge fix
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
net/wireless/nl80211.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index f727a1f..f7d2ebb 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -8057,9 +8057,12 @@ void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
return;
}
- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, type);
+ if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
+ goto nla_put_failure;
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq))
+ goto nla_put_failure;
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, type))
+ goto nla_put_failure;
genlmsg_end(msg, hdr);
--
1.7.10.rc3
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply related
* Re: [PATCH 00/10] Wireless patches for wireless-testing
From: Johannes Berg @ 2012-04-12 3:39 UTC (permalink / raw)
To: greearb-my8/4N5VtI7c+919tysfdA
Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1334166738-28243-1-git-send-email-greearb-my8/4N5VtI7c+919tysfdA@public.gmane.org>
On Wed, 2012-04-11 at 10:52 -0700, greearb-my8/4N5VtI7c+919tysfdA@public.gmane.org wrote:
> From: Ben Greear <greearb-my8/4N5VtI7c+919tysfdA@public.gmane.org>
>
> Support Ethtool stats for Wireless, including in-depth
> stats for ath9k, and add some additional ath9k stats
> to debugfs. Support scanning on-channel.
Please don't mix two completely different things in a single series of
patches. I almost skipped this completely since I already saw the
ethtool stuff and don't care about ath9k stats, but clearly I need to
look at the scan thing ...
johannes
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 08/10] mac80211: Support on-channel scan option.
From: Johannes Berg @ 2012-04-12 3:45 UTC (permalink / raw)
To: greearb; +Cc: linux-wireless, netdev
In-Reply-To: <1334166738-28243-9-git-send-email-greearb@candelatech.com>
On Wed, 2012-04-11 at 10:52 -0700, greearb@candelatech.com wrote:
> static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
> struct cfg80211_scan_request *req)
> @@ -438,10 +461,43 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
> local->scan_req = req;
> local->scan_sdata = sdata;
>
> - if (local->ops->hw_scan)
> + if (local->ops->hw_scan) {
> __set_bit(SCAN_HW_SCANNING, &local->scanning);
> - else
> - __set_bit(SCAN_SW_SCANNING, &local->scanning);
> + } else {
> + /* If we are scanning only on the current channel, then
> + * we do not need to stop normal activities
> + */
> + if ((req->n_channels == 1) &&
> + (req->channels[0]->center_freq ==
> + local->hw.conf.channel->center_freq)) {
how about "else if {", then the indentation isn't so deep and you can
have much nicer code in the entire block :)
> + unsigned long next_delay;
please add a blank line after variable declarations.
> + }
> + else {
please read the coding style documentation
> @@ -672,6 +704,12 @@ void ieee80211_scan_work(struct work_struct *work)
>
> sdata = local->scan_sdata;
>
> + /* When scanning on-channel, the first-callback means completeed. */
typo "completed"
> + if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) {
> + aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning);
> + goto out_complete;
> + }
how does the onchannel bit get cleared?
Shouldn't you be calling pre/post scan hooks?
I'm a bit divided over this. On the one hand, it seems like a mildly
useful optimisation, on the other though it adds a bunch of complexity
for multi-channel we've been thinking about... Not that we want to
support multi-channel with SW scan anyway, but still.
johannes
^ permalink raw reply
* Re: [PATCH 05/10] mac80211: Add more ethtools stats: survey, rates, etc
From: Johannes Berg @ 2012-04-12 3:46 UTC (permalink / raw)
To: greearb-my8/4N5VtI7c+919tysfdA
Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1334166738-28243-6-git-send-email-greearb-my8/4N5VtI7c+919tysfdA@public.gmane.org>
On Wed, 2012-04-11 at 10:52 -0700, greearb-my8/4N5VtI7c+919tysfdA@public.gmane.org wrote:
> --- a/net/mac80211/cfg.c
> +++ b/net/mac80211/cfg.c
> @@ -19,6 +19,7 @@
> #include "cfg.h"
> #include "rate.h"
> #include "mesh.h"
> +#include "../wireless/core.h"
NACK. Don't do that.
johannes
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 06/10] mac80211: Add sta_state to ethtool stats.
From: Johannes Berg @ 2012-04-12 3:49 UTC (permalink / raw)
To: greearb; +Cc: linux-wireless, netdev
In-Reply-To: <1334166738-28243-7-git-send-email-greearb@candelatech.com>
On Wed, 2012-04-11 at 10:52 -0700, greearb@candelatech.com wrote:
> From: Ben Greear <greearb@candelatech.com>
>
> Helps to know how the station is doing in it's association
> attempt.
>
> Signed-off-by: Ben Greear <greearb@candelatech.com>
> ---
> :100644 100644 bbaf564... a63834d... M net/mac80211/cfg.c
> net/mac80211/cfg.c | 6 ++++--
> 1 files changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
> index bbaf564..a63834d 100644
> --- a/net/mac80211/cfg.c
> +++ b/net/mac80211/cfg.c
> @@ -118,7 +118,7 @@ static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
> "rx_duplicates", "rx_fragments", "rx_dropped",
> "tx_packets", "tx_bytes", "tx_fragments",
> "tx_filtered", "tx_retry_failed", "tx_retries",
> - "beacon_loss", "txrate", "rxrate", "signal",
> + "beacon_loss", "sta_state", "txrate", "rxrate", "signal",
> "channel", "noise", "ch_time", "ch_time_busy",
> "ch_time_ext_busy", "ch_time_rx", "ch_time_tx"
> };
> @@ -534,10 +534,12 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
> data[i++] += sta->beacon_loss_count;
>
> if (!do_once) {
> - i += 3;
> + i += 4;
> goto after_once;
> }
>
> + data[i++] = sta->sta_state;
> +
Gee, I wish it was easier to tell if you were adding it to the right
spot in the list ... any way that could be made easier?
johannes
^ permalink raw reply
* Regression due to "ath9k: fix going to full-sleep on PS idle"
From: Linus Torvalds @ 2012-04-12 4:22 UTC (permalink / raw)
To: Heinz Diehl
Cc: linux-kernel, Greg KH, akpm, alan, linux-wireless Mailing List,
Sujith Manoharan, ath9k-devel@lists.ath9k.org, John W. Linville,
David Miller, Network Development
On Wed, Apr 11, 2012 at 9:16 PM, Heinz Diehl <htd@fancy-poultry.org> wrote:
> On 12.04.2012, Sergio Correia wrote:
>
>> is there any chance for this one to be included in this review cycle?
>>
>> http://www.spinics.net/lists/linux-wireless/msg87999.html
>
> Thanks for pointing this out! This patch fixes my network problems
> which forced me to go back to a previous kernel.
You guys need to fix the subject line (like this), and make sure that
the right people are cc'd. This is not a "stable" issue - stable
cannot revert stuff that hasn't been reverted upstream.
So instead of stable and Greg, it should be netdev and Davem.
David/John: multiple people are complaining about that commit. It
really should be reverted, or a fix found. It's broken.
I can do the revert, but it would be better coming from the networking people.
Linus
^ permalink raw reply
* Re: suspicious RCU usage warnings in 3.3.0
From: Paul E. McKenney @ 2012-04-12 4:54 UTC (permalink / raw)
To: David Miller; +Cc: shemminger, mroos, linux-kernel, netdev
In-Reply-To: <20120411.210843.716144028821174908.davem@davemloft.net>
On Wed, Apr 11, 2012 at 09:08:43PM -0400, David Miller wrote:
> From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
> Date: Wed, 11 Apr 2012 17:45:07 -0700
>
> > If I am confused about the simple function call, and if control is really
> > passing via an interrupt or exception, then rcu_irq_enter() should be
> > called on entry to the interrupt or exception and rcu_irq_exit() should
> > be called on exit.
>
> Hmm, it seems the convention changed such that platforms aren't
> supposed to invoke do_softirq() from their trap return trap any more.
> It's handled completely by irq_exit().
>
> When did that start happening? :-)
Heh! It appears that git doesn't go back far enough for me to find the
answer to that question. ;-)
> Anyways I bet that's the problem, sparc64 invokes do_softirq() in it's
> trap return path if softirqs are pending, and that doesn't do any
> of the RCU frobbing you mention.
The following untested patch that probably does not even build is offered
up for your amusement. I don't know enough about SPARC's needs for
alignment, handling of branch-delay slots, and so on for this to have
any chance of working, but hey! ;-)
Thanx, Paul
------------------------------------------------------------------------
sparc64: Eliminate obsolete __handle_softirq() function
The invocation of softirq is now handled by irq_exit(), so there is no
need for sparc64 to invoke it on the trap-return path. In fact, doing so
is a bug because if the trap occurred in the idle loop, this invocation
can result in lockdep-RCU failures. The problem is that RCU ignores idle
CPUs, and the sparc64 trap-return path to the softirq handlers fails to
tell RCU that the CPU must be considered non-idle while those handlers
are executing. This means that RCU is ignoring any RCU read-side critical
sections in those handlers, which in turn means that RCU-protected data
can be yanked out from under those read-side critical sections.
The shiny new lockdep-RCU ability to detect RCU read-side critical sections
that RCU is ignoring located this problem.
The fix is straightforward: Make sparc64 stop manually invoking the
softirq handlers.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
rtrap_64.S | 7 -------
1 file changed, 7 deletions(-)
diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S
index 77f1b95..9171fc2 100644
--- a/arch/sparc/kernel/rtrap_64.S
+++ b/arch/sparc/kernel/rtrap_64.S
@@ -20,11 +20,6 @@
.text
.align 32
-__handle_softirq:
- call do_softirq
- nop
- ba,a,pt %xcc, __handle_softirq_continue
- nop
__handle_preemption:
call schedule
wrpr %g0, RTRAP_PSTATE, %pstate
@@ -89,9 +84,7 @@ rtrap:
cmp %l1, 0
/* mm/ultra.S:xcall_report_regs KNOWS about this load. */
- bne,pn %icc, __handle_softirq
ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
-__handle_softirq_continue:
rtrap_xcall:
sethi %hi(0xf << 20), %l4
and %l1, %l4, %l4
^ permalink raw reply related
* Regression due to "ath9k: fix going to full-sleep on PS idle"
From: Sujith Manoharan @ 2012-04-12 5:07 UTC (permalink / raw)
To: Linus Torvalds
Cc: ath9k-devel@lists.ath9k.org, KH, linux-wireless Mailing List,
linux-kernel, John W. Linville, Greg, Heinz Diehl,
Network Development, akpm, David Miller, alan
In-Reply-To: <CA+55aFxWD1bE0oiR4GpLP19MCm2CzwuApuYhcE_NF7bC+tFYjg@mail.gmail.com>
Linus Torvalds wrote:
> You guys need to fix the subject line (like this), and make sure that
> the right people are cc'd. This is not a "stable" issue - stable
> cannot revert stuff that hasn't been reverted upstream.
>
> So instead of stable and Greg, it should be netdev and Davem.
>
> David/John: multiple people are complaining about that commit. It
> really should be reverted, or a fix found. It's broken.
>
> I can do the revert, but it would be better coming from the networking people.
John has already reverted the commit:
http://git.kernel.org/?p=linux/kernel/git/linville/wireless.git;a=commit;h=011afa1ed8c408d694957d2474d89dc81a60b70c
Sujith
^ permalink raw reply
* [PATCH] drivers/net: Remove CONFIG_WIZNET_TX_FLOW option
From: Mike Sinkovsky @ 2012-04-12 6:14 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: Mike Sinkovsky
This option was there for debugging race conditions,
just remove it, and assume TX_FLOW is always enabled.
Signed-off-by: Mike Sinkovsky <msink@permonline.ru>
---
This replaces patch from Paul Gortmaker:
"[PATCH 3/5] drivers/net: remove IS_ENABLED usage from wiznet drivers
The use of IS_ENABLED in C code (vs just in CPP #if directives)
causes us to carry the burden of a huge autoconf.h file. It is
also misleading in that a casual inspection of the code would
leave one thinking that the if statements were evaluated at
runtime, when TX_FLOW is a Kconfig bool and hence evaluated
at configure time as an either/or."
Just remove this option instead.
drivers/net/ethernet/wiznet/Kconfig | 8 --------
drivers/net/ethernet/wiznet/w5100.c | 5 ++---
drivers/net/ethernet/wiznet/w5300.c | 9 +++------
3 files changed, 5 insertions(+), 17 deletions(-)
diff --git a/drivers/net/ethernet/wiznet/Kconfig b/drivers/net/ethernet/wiznet/Kconfig
index c8291bf..cb18043 100644
--- a/drivers/net/ethernet/wiznet/Kconfig
+++ b/drivers/net/ethernet/wiznet/Kconfig
@@ -70,12 +70,4 @@ config WIZNET_BUS_ANY
Performance may decrease compared to explicitly selected bus mode.
endchoice
-config WIZNET_TX_FLOW
- bool "Use transmit flow control"
- depends on WIZNET_W5100 || WIZNET_W5300
- default y
- help
- This enables transmit flow control for WIZnet chips.
- If unsure, say Y.
-
endif # NET_VENDOR_WIZNET
diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c
index 157d2f0..22e2c5c 100644
--- a/drivers/net/ethernet/wiznet/w5100.c
+++ b/drivers/net/ethernet/wiznet/w5100.c
@@ -441,8 +441,7 @@ static int w5100_start_tx(struct sk_buff *skb, struct net_device *ndev)
struct w5100_priv *priv = netdev_priv(ndev);
u16 offset;
- if (IS_ENABLED(CONFIG_WIZNET_TX_FLOW))
- netif_stop_queue(ndev);
+ netif_stop_queue(ndev);
offset = w5100_read16(priv, W5100_S0_TX_WR);
w5100_writebuf(priv, offset, skb->data, skb->len);
@@ -517,7 +516,7 @@ static irqreturn_t w5100_interrupt(int irq, void *ndev_instance)
w5100_write(priv, W5100_S0_IR, ir);
mmiowb();
- if (IS_ENABLED(CONFIG_WIZNET_TX_FLOW) && (ir & S0_IR_SENDOK)) {
+ if (ir & S0_IR_SENDOK) {
netif_dbg(priv, tx_done, ndev, "tx done\n");
netif_wake_queue(ndev);
}
diff --git a/drivers/net/ethernet/wiznet/w5300.c b/drivers/net/ethernet/wiznet/w5300.c
index 86d07bb..63cb9dd 100644
--- a/drivers/net/ethernet/wiznet/w5300.c
+++ b/drivers/net/ethernet/wiznet/w5300.c
@@ -273,9 +273,7 @@ static void w5300_hw_start(struct w5300_priv *priv)
S0_MR_MACRAW : S0_MR_MACRAW_MF);
mmiowb();
w5300_command(priv, S0_CR_OPEN);
- w5300_write(priv, W5300_S0_IMR, IS_ENABLED(CONFIG_WIZNET_TX_FLOW) ?
- S0_IR_RECV | S0_IR_SENDOK :
- S0_IR_RECV);
+ w5300_write(priv, W5300_S0_IMR, S0_IR_RECV | S0_IR_SENDOK);
w5300_write(priv, W5300_IMR, IR_S0);
mmiowb();
}
@@ -371,8 +369,7 @@ static int w5300_start_tx(struct sk_buff *skb, struct net_device *ndev)
{
struct w5300_priv *priv = netdev_priv(ndev);
- if (IS_ENABLED(CONFIG_WIZNET_TX_FLOW))
- netif_stop_queue(ndev);
+ netif_stop_queue(ndev);
w5300_write_frame(priv, skb->data, skb->len);
mmiowb();
@@ -439,7 +436,7 @@ static irqreturn_t w5300_interrupt(int irq, void *ndev_instance)
w5300_write(priv, W5300_S0_IR, ir);
mmiowb();
- if (IS_ENABLED(CONFIG_WIZNET_TX_FLOW) && (ir & S0_IR_SENDOK)) {
+ if (ir & S0_IR_SENDOK) {
netif_dbg(priv, tx_done, ndev, "tx done\n");
netif_wake_queue(ndev);
}
--
1.6.3.3
^ permalink raw reply related
* Re: [PATCH 4/4] net: Remove redundant spi driver bus initialization
From: Gabor Juhos @ 2012-04-12 6:23 UTC (permalink / raw)
To: Lars-Peter Clausen
Cc: linux-kernel, David S. Miller, Frederic Lambert, netdev
In-Reply-To: <1334091089-10138-4-git-send-email-lars@metafoo.de>
2012.04.10. 22:51 keltezéssel, Lars-Peter Clausen írta:
> In ancient times it was necessary to manually initialize the bus field of an
> spi_driver to spi_bus_type. These days this is done in spi_driver_register() so
> we can drop the manual assignment.
>
> The patch was generated using the following coccinelle semantic patch:
> // <smpl>
> @@
> identifier _driver;
> @@
> struct spi_driver _driver = {
> .driver = {
> - .bus = &spi_bus_type,
> },
> };
> // </smpl>
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Gabor Juhos <juhosg@openwrt.org>
> Cc: Frederic Lambert <frdrc66@gmail.com>
> Cc: netdev@vger.kernel.org
> ---
> drivers/net/phy/spi_ks8995.c | 1 -
> 1 file changed, 1 deletion(-)
Acked-by: Gabor Juhos <juhosg@openwrt.org>
^ permalink raw reply
* [net-next V7 PATCH] virtio-net: send gratuitous packets when needed
From: Jason Wang @ 2012-04-12 6:43 UTC (permalink / raw)
To: netdev, rusty, virtualization, linux-kernel, mst
As hypervior does not have the knowledge of guest network configuration, it's
better to ask guest to send gratuitous packets when needed.
This patch implements VIRTIO_NET_F_GUEST_ANNOUNCE feature: hypervisor would
notice the guest when it thinks it's time for guest to announce the link
presnece. Guest tests VIRTIO_NET_S_ANNOUNCE bit during config change interrupt
and woule send gratuitous packets through netif_notify_peers() and ack the
notification through ctrl vq.
We need to make sure the atomicy of read and ack in guest otherwise we may ack
more times than being notified. This is done through handling the whole config
change interrupt in an non-reentrant workqueue.
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
Changes from v6:
- move the whole event processing to system_nrt_wq
- introduce the config_enable and config_lock to synchronize with dev removing
and pm
- protect the ack with rtnl_lock
Changes from v5:
- notify the chain before acking the link annoucement
- ack the link announcement notification through control vq
Changes from v4:
- typos
- handle workqueue unconditionally
- move VIRTIO_NET_S_ANNOUNCE to bit 8 to separate rw bits from ro bits
Changes from v3:
- cancel the workqueue during freeze
Changes from v2:
- fix the race between unregister_dev() and workqueue
---
drivers/net/virtio_net.c | 64 +++++++++++++++++++++++++++++++++++++++++---
include/linux/virtio_net.h | 14 ++++++++++
2 files changed, 73 insertions(+), 5 deletions(-)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 4de2760..23403b6 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -66,12 +66,21 @@ struct virtnet_info {
/* Host will merge rx buffers for big packets (shake it! shake it!) */
bool mergeable_rx_bufs;
+ /* enable config space updates */
+ bool config_enable;
+
/* Active statistics */
struct virtnet_stats __percpu *stats;
/* Work struct for refilling if we run low on memory. */
struct delayed_work refill;
+ /* Work struct for config space updates */
+ struct work_struct config_work;
+
+ /* Lock for config space updates */
+ struct mutex config_lock;
+
/* Chain pages by the private ptr. */
struct page *pages;
@@ -781,6 +790,16 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
return status == VIRTIO_NET_OK;
}
+static void virtnet_ack_link_announce(struct virtnet_info *vi)
+{
+ rtnl_lock();
+ if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_ANNOUNCE,
+ VIRTIO_NET_CTRL_ANNOUNCE_ACK, NULL,
+ 0, 0))
+ dev_warn(&vi->dev->dev, "Failed to ack link announce.\n");
+ rtnl_unlock();
+}
+
static int virtnet_close(struct net_device *dev)
{
struct virtnet_info *vi = netdev_priv(dev);
@@ -952,20 +971,31 @@ static const struct net_device_ops virtnet_netdev = {
#endif
};
-static void virtnet_update_status(struct virtnet_info *vi)
+static void virtnet_config_changed_work(struct work_struct *work)
{
+ struct virtnet_info *vi =
+ container_of(work, struct virtnet_info, config_work);
u16 v;
+ mutex_lock(&vi->config_lock);
+ if (!vi->config_enable)
+ goto done;
+
if (virtio_config_val(vi->vdev, VIRTIO_NET_F_STATUS,
offsetof(struct virtio_net_config, status),
&v) < 0)
- return;
+ goto done;
+
+ if (v & VIRTIO_NET_S_ANNOUNCE) {
+ netif_notify_peers(vi->dev);
+ virtnet_ack_link_announce(vi);
+ }
/* Ignore unknown (future) status bits */
v &= VIRTIO_NET_S_LINK_UP;
if (vi->status == v)
- return;
+ goto done;
vi->status = v;
@@ -976,13 +1006,15 @@ static void virtnet_update_status(struct virtnet_info *vi)
netif_carrier_off(vi->dev);
netif_stop_queue(vi->dev);
}
+done:
+ mutex_unlock(&vi->config_lock);
}
static void virtnet_config_changed(struct virtio_device *vdev)
{
struct virtnet_info *vi = vdev->priv;
- virtnet_update_status(vi);
+ queue_work(system_nrt_wq, &vi->config_work);
}
static int init_vqs(struct virtnet_info *vi)
@@ -1076,6 +1108,9 @@ static int virtnet_probe(struct virtio_device *vdev)
goto free;
INIT_DELAYED_WORK(&vi->refill, refill_work);
+ mutex_init(&vi->config_lock);
+ vi->config_enable = true;
+ INIT_WORK(&vi->config_work, virtnet_config_changed_work);
sg_init_table(vi->rx_sg, ARRAY_SIZE(vi->rx_sg));
sg_init_table(vi->tx_sg, ARRAY_SIZE(vi->tx_sg));
@@ -1111,7 +1146,7 @@ static int virtnet_probe(struct virtio_device *vdev)
otherwise get link status from config. */
if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) {
netif_carrier_off(dev);
- virtnet_update_status(vi);
+ queue_work(system_nrt_wq, &vi->config_work);
} else {
vi->status = VIRTIO_NET_S_LINK_UP;
netif_carrier_on(dev);
@@ -1170,10 +1205,17 @@ static void __devexit virtnet_remove(struct virtio_device *vdev)
{
struct virtnet_info *vi = vdev->priv;
+ /* Prevent config work handler from accessing the device. */
+ mutex_lock(&vi->config_lock);
+ vi->config_enable = false;
+ mutex_unlock(&vi->config_lock);
+
unregister_netdev(vi->dev);
remove_vq_common(vi);
+ flush_work(&vi->config_work);
+
free_percpu(vi->stats);
free_netdev(vi->dev);
}
@@ -1183,6 +1225,11 @@ static int virtnet_freeze(struct virtio_device *vdev)
{
struct virtnet_info *vi = vdev->priv;
+ /* Prevent config work handler from accessing the device */
+ mutex_lock(&vi->config_lock);
+ vi->config_enable = false;
+ mutex_unlock(&vi->config_lock);
+
virtqueue_disable_cb(vi->rvq);
virtqueue_disable_cb(vi->svq);
if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ))
@@ -1196,6 +1243,8 @@ static int virtnet_freeze(struct virtio_device *vdev)
remove_vq_common(vi);
+ flush_work(&vi->config_work);
+
return 0;
}
@@ -1216,6 +1265,10 @@ static int virtnet_restore(struct virtio_device *vdev)
if (!try_fill_recv(vi, GFP_KERNEL))
queue_delayed_work(system_nrt_wq, &vi->refill, 0);
+ mutex_lock(&vi->config_lock);
+ vi->config_enable = true;
+ mutex_unlock(&vi->config_lock);
+
return 0;
}
#endif
@@ -1233,6 +1286,7 @@ static unsigned int features[] = {
VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_UFO,
VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ,
VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN,
+ VIRTIO_NET_F_GUEST_ANNOUNCE,
};
static struct virtio_driver virtio_net_driver = {
diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
index 970d5a2..2470f54 100644
--- a/include/linux/virtio_net.h
+++ b/include/linux/virtio_net.h
@@ -49,8 +49,11 @@
#define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support */
#define VIRTIO_NET_F_CTRL_VLAN 19 /* Control channel VLAN filtering */
#define VIRTIO_NET_F_CTRL_RX_EXTRA 20 /* Extra RX mode control support */
+#define VIRTIO_NET_F_GUEST_ANNOUNCE 21 /* Guest can announce device on the
+ * network */
#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */
+#define VIRTIO_NET_S_ANNOUNCE 2 /* Announcement is needed */
struct virtio_net_config {
/* The config defining mac address (if VIRTIO_NET_F_MAC) */
@@ -152,4 +155,15 @@ struct virtio_net_ctrl_mac {
#define VIRTIO_NET_CTRL_VLAN_ADD 0
#define VIRTIO_NET_CTRL_VLAN_DEL 1
+/*
+ * Control link announce acknowledgement
+ *
+ * The command VIRTIO_NET_CTRL_ANNOUNCE_ACK is used to indicate that
+ * driver has recevied the notification; device would clear the
+ * VIRTIO_NET_S_ANNOUNCE bit in the status field after it receives
+ * this command.
+ */
+#define VIRTIO_NET_CTRL_ANNOUNCE 3
+ #define VIRTIO_NET_CTRL_ANNOUNCE_ACK 0
+
#endif /* _LINUX_VIRTIO_NET_H */
^ permalink raw reply related
* [net-next PATCH v2 0/8] Managing the forwarding database(FDB)
From: John Fastabend @ 2012-04-12 6:57 UTC (permalink / raw)
To: shemminger, mst, davem, bhutchings, sri
Cc: hadi, jeffrey.t.kirsher, netdev, gregory.v.rose, krkumar2
The following series is a submission for net-next to allow
embedded switches and other stacked devices other then the
Linux bridge to manage a forwarding database.
Previously posted and discussed here,
http://lists.openwall.net/netdev/2012/03/19/26
This version addresses feedback from Ben Hutchings to fix
a typo in the multicast dump routines and to better handle
error cases on add/del fdb. Notify hooks were added for
the NTF_SELF case as well to bring it inline with the
SW net/bridge.
Additionally this version changes the macvlan patch to use
a flag to disable promisc mode. This was decided on over
adding additional modes.
Thanks for the feedback and review. I've tested this with
the 'br' tool published by Stephen Hemminger and pktgen.
.John
---
Greg Rose (1):
ixgbe: UTA table incorrectly programmed
John Fastabend (7):
macvlan: add FDB bridge ops and macvlan flags
ixgbe: allow RAR table to be updated in promisc mode
ixgbe: enable FDB netdevice ops
net: rtnetlink notify events for FDB NTF_SELF adds and deletes
net: add fdb generic dump routine
net: addr_list: add exclusive dev_uc_add and dev_mc_add
net: add generic PF_BRIDGE:RTM_ FDB hooks
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 121 ++++++++---
drivers/net/macvlan.c | 61 +++++-
include/linux/if_link.h | 3
include/linux/if_macvlan.h | 1
include/linux/neighbour.h | 3
include/linux/netdevice.h | 25 ++
include/linux/rtnetlink.h | 4
net/bridge/br_device.c | 3
net/bridge/br_fdb.c | 128 +++---------
net/bridge/br_netlink.c | 12 -
net/bridge/br_private.h | 15 +
net/core/dev_addr_lists.c | 97 ++++++++-
net/core/rtnetlink.c | 267 +++++++++++++++++++++++++
13 files changed, 567 insertions(+), 173 deletions(-)
--
Signature
^ permalink raw reply
* [net-next PATCH v2 1/8] net: add generic PF_BRIDGE:RTM_ FDB hooks
From: John Fastabend @ 2012-04-12 6:57 UTC (permalink / raw)
To: shemminger, mst, davem, bhutchings, sri
Cc: hadi, jeffrey.t.kirsher, netdev, gregory.v.rose, krkumar2
In-Reply-To: <20120412064858.3112.65818.stgit@jf-dev1-dcblab>
This adds two new flags NTF_MASTER and NTF_SELF that can
now be used to specify where PF_BRIDGE netlink commands should
be sent. NTF_MASTER sends the commands to the 'dev->master'
device for parsing. Typically this will be the linux net/bridge,
or open-vswitch devices. Also without any flags set the command
will be handled by the master device as well so that current user
space tools continue to work as expected.
The NTF_SELF flag will push the PF_BRIDGE commands to the
device. In the basic example below the commands are then parsed
and programmed in the embedded bridge.
Note if both NTF_SELF and NTF_MASTER bits are set then the
command will be sent to both 'dev->master' and 'dev' this allows
user space to easily keep the embedded bridge and software bridge
in sync.
There is a slight complication in the case with both flags set
when an error occurs. To resolve this the rtnl handler clears
the NTF_ flag in the netlink ack to indicate which sets completed
successfully. The add/del handlers will abort as soon as any
error occurs.
To support this new net device ops were added to call into
the device and the existing bridging code was refactored
to use these. There should be no required changes in user space
to support the current bridge behavior.
A basic setup with a SR-IOV enabled NIC looks like this,
veth0 veth2
| |
------------
| bridge0 | <---- software bridging
------------
/
/
ethx.y ethx
VF PF
\ \ <---- propagate FDB entries to HW
\ \
--------------------
| Embedded Bridge | <---- hardware offloaded switching
--------------------
In this case the embedded bridge must be managed to allow 'veth0'
to communicate with 'ethx.y' correctly. At present drivers managing
the embedded bridge either send frames onto the network which
then get dropped by the switch OR the embedded bridge will flood
these frames. With this patch we have a mechanism to manage the
embedded bridge correctly from user space. This example is specific
to SR-IOV but replacing the VF with another PF or dropping this
into the DSA framework generates similar management issues.
Examples session using the 'br'[1] tool to add, dump and then
delete a mac address with a new "embedded" option and enabled
ixgbe driver:
# br fdb add 22:35:19:ac:60:59 dev eth3
# br fdb
port mac addr flags
veth0 22:35:19:ac:60:58 static
veth0 9a:5f:81:f7:f6:ec local
eth3 00:1b:21:55:23:59 local
eth3 22:35:19:ac:60:59 static
veth0 22:35:19:ac:60:57 static
#br fdb add 22:35:19:ac:60:59 embedded dev eth3
#br fdb
port mac addr flags
veth0 22:35:19:ac:60:58 static
veth0 9a:5f:81:f7:f6:ec local
eth3 00:1b:21:55:23:59 local
eth3 22:35:19:ac:60:59 static
veth0 22:35:19:ac:60:57 static
eth3 22:35:19:ac:60:59 local embedded
#br fdb del 22:35:19:ac:60:59 embedded dev eth3
I added a couple lines to 'br' to set the flags correctly is all. It
is my opinion that the merit of this patch is now embedded and SW
bridges can both be modeled correctly in user space using very nearly
the same message passing.
[1] 'br' tool was published as an RFC here and will be renamed 'bridge'
http://patchwork.ozlabs.org/patch/117664/
Thanks to Jamal Hadi Salim, Stephen Hemminger and Ben Hutchings for
valuable feedback, suggestions, and review.
v2: fixed api descriptions and error case with both NTF_SELF and
NTF_MASTER set plus updated patch description.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
---
include/linux/neighbour.h | 3 +
include/linux/netdevice.h | 23 +++++++
include/linux/rtnetlink.h | 4 +
net/bridge/br_device.c | 3 +
net/bridge/br_fdb.c | 128 +++++++++-----------------------------
net/bridge/br_netlink.c | 12 ----
net/bridge/br_private.h | 15 ++++
net/core/rtnetlink.c | 152 +++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 228 insertions(+), 112 deletions(-)
diff --git a/include/linux/neighbour.h b/include/linux/neighbour.h
index b188f68..275e5d6 100644
--- a/include/linux/neighbour.h
+++ b/include/linux/neighbour.h
@@ -33,6 +33,9 @@ enum {
#define NTF_PROXY 0x08 /* == ATF_PUBL */
#define NTF_ROUTER 0x80
+#define NTF_SELF 0x02
+#define NTF_MASTER 0x04
+
/*
* Neighbor Cache Entry States.
*/
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 5cbaa20..7600c61 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -54,6 +54,7 @@
#include <net/netprio_cgroup.h>
#include <linux/netdev_features.h>
+#include <linux/neighbour.h>
struct netpoll_info;
struct device;
@@ -905,6 +906,16 @@ struct netdev_fcoe_hbainfo {
* feature set might be less than what was returned by ndo_fix_features()).
* Must return >0 or -errno if it changed dev->features itself.
*
+ * int (*ndo_fdb_add)(struct ndmsg *ndm, struct net_device *dev,
+ * unsigned char *addr, u16 flags)
+ * Adds an FDB entry to dev for addr.
+ * int (*ndo_fdb_del)(struct ndmsg *ndm, struct net_device *dev,
+ * unsigned char *addr)
+ * Deletes the FDB entry from dev coresponding to addr.
+ * int (*ndo_fdb_dump)(struct sk_buff *skb, struct netlink_callback *cb,
+ * struct net_device *dev, int idx)
+ * Used to add FDB entries to dump requests. Implementers should add
+ * entries to skb and update idx with the number of entries.
*/
struct net_device_ops {
int (*ndo_init)(struct net_device *dev);
@@ -1002,6 +1013,18 @@ struct net_device_ops {
netdev_features_t features);
int (*ndo_neigh_construct)(struct neighbour *n);
void (*ndo_neigh_destroy)(struct neighbour *n);
+
+ int (*ndo_fdb_add)(struct ndmsg *ndm,
+ struct net_device *dev,
+ unsigned char *addr,
+ u16 flags);
+ int (*ndo_fdb_del)(struct ndmsg *ndm,
+ struct net_device *dev,
+ unsigned char *addr);
+ int (*ndo_fdb_dump)(struct sk_buff *skb,
+ struct netlink_callback *cb,
+ struct net_device *dev,
+ int idx);
};
/*
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 577592e..2c1de89 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -801,6 +801,10 @@ rtattr_failure:
return table;
}
+extern int ndo_dflt_fdb_dump(struct sk_buff *skb,
+ struct netlink_callback *cb,
+ struct net_device *dev,
+ int idx);
#endif /* __KERNEL__ */
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index ba829de..d6e5929 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -317,6 +317,9 @@ static const struct net_device_ops br_netdev_ops = {
.ndo_add_slave = br_add_slave,
.ndo_del_slave = br_del_slave,
.ndo_fix_features = br_fix_features,
+ .ndo_fdb_add = br_fdb_add,
+ .ndo_fdb_del = br_fdb_delete,
+ .ndo_fdb_dump = br_fdb_dump,
};
static void br_dev_free(struct net_device *dev)
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 80dbce4..5945c54 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -535,44 +535,38 @@ errout:
}
/* Dump information about entries, in response to GETNEIGH */
-int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
+int br_fdb_dump(struct sk_buff *skb,
+ struct netlink_callback *cb,
+ struct net_device *dev,
+ int idx)
{
- struct net *net = sock_net(skb->sk);
- struct net_device *dev;
- int idx = 0;
-
- rcu_read_lock();
- for_each_netdev_rcu(net, dev) {
- struct net_bridge *br = netdev_priv(dev);
- int i;
-
- if (!(dev->priv_flags & IFF_EBRIDGE))
- continue;
+ struct net_bridge *br = netdev_priv(dev);
+ int i;
- for (i = 0; i < BR_HASH_SIZE; i++) {
- struct hlist_node *h;
- struct net_bridge_fdb_entry *f;
+ if (!(dev->priv_flags & IFF_EBRIDGE))
+ goto out;
- hlist_for_each_entry_rcu(f, h, &br->hash[i], hlist) {
- if (idx < cb->args[0])
- goto skip;
+ for (i = 0; i < BR_HASH_SIZE; i++) {
+ struct hlist_node *h;
+ struct net_bridge_fdb_entry *f;
- if (fdb_fill_info(skb, br, f,
- NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq,
- RTM_NEWNEIGH,
- NLM_F_MULTI) < 0)
- break;
+ hlist_for_each_entry_rcu(f, h, &br->hash[i], hlist) {
+ if (idx < cb->args[0])
+ goto skip;
+
+ if (fdb_fill_info(skb, br, f,
+ NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq,
+ RTM_NEWNEIGH,
+ NLM_F_MULTI) < 0)
+ break;
skip:
- ++idx;
- }
+ ++idx;
}
}
- rcu_read_unlock();
-
- cb->args[0] = idx;
- return skb->len;
+out:
+ return idx;
}
/* Update (create or replace) forwarding database entry */
@@ -614,43 +608,11 @@ static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr,
}
/* Add new permanent fdb entry with RTM_NEWNEIGH */
-int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+int br_fdb_add(struct ndmsg *ndm, struct net_device *dev,
+ unsigned char *addr, u16 nlh_flags)
{
- struct net *net = sock_net(skb->sk);
- struct ndmsg *ndm;
- struct nlattr *tb[NDA_MAX+1];
- struct net_device *dev;
struct net_bridge_port *p;
- const __u8 *addr;
- int err;
-
- ASSERT_RTNL();
- err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
- if (err < 0)
- return err;
-
- ndm = nlmsg_data(nlh);
- if (ndm->ndm_ifindex == 0) {
- pr_info("bridge: RTM_NEWNEIGH with invalid ifindex\n");
- return -EINVAL;
- }
-
- dev = __dev_get_by_index(net, ndm->ndm_ifindex);
- if (dev == NULL) {
- pr_info("bridge: RTM_NEWNEIGH with unknown ifindex\n");
- return -ENODEV;
- }
-
- if (!tb[NDA_LLADDR] || nla_len(tb[NDA_LLADDR]) != ETH_ALEN) {
- pr_info("bridge: RTM_NEWNEIGH with invalid address\n");
- return -EINVAL;
- }
-
- addr = nla_data(tb[NDA_LLADDR]);
- if (!is_valid_ether_addr(addr)) {
- pr_info("bridge: RTM_NEWNEIGH with invalid ether address\n");
- return -EINVAL;
- }
+ int err = 0;
if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE))) {
pr_info("bridge: RTM_NEWNEIGH with invalid state %#x\n", ndm->ndm_state);
@@ -670,14 +632,14 @@ int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
rcu_read_unlock();
} else {
spin_lock_bh(&p->br->hash_lock);
- err = fdb_add_entry(p, addr, ndm->ndm_state, nlh->nlmsg_flags);
+ err = fdb_add_entry(p, addr, ndm->ndm_state, nlh_flags);
spin_unlock_bh(&p->br->hash_lock);
}
return err;
}
-static int fdb_delete_by_addr(struct net_bridge_port *p, const u8 *addr)
+static int fdb_delete_by_addr(struct net_bridge_port *p, u8 *addr)
{
struct net_bridge *br = p->br;
struct hlist_head *head = &br->hash[br_mac_hash(addr)];
@@ -692,40 +654,12 @@ static int fdb_delete_by_addr(struct net_bridge_port *p, const u8 *addr)
}
/* Remove neighbor entry with RTM_DELNEIGH */
-int br_fdb_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+int br_fdb_delete(struct ndmsg *ndm, struct net_device *dev,
+ unsigned char *addr)
{
- struct net *net = sock_net(skb->sk);
- struct ndmsg *ndm;
struct net_bridge_port *p;
- struct nlattr *llattr;
- const __u8 *addr;
- struct net_device *dev;
int err;
- ASSERT_RTNL();
- if (nlmsg_len(nlh) < sizeof(*ndm))
- return -EINVAL;
-
- ndm = nlmsg_data(nlh);
- if (ndm->ndm_ifindex == 0) {
- pr_info("bridge: RTM_DELNEIGH with invalid ifindex\n");
- return -EINVAL;
- }
-
- dev = __dev_get_by_index(net, ndm->ndm_ifindex);
- if (dev == NULL) {
- pr_info("bridge: RTM_DELNEIGH with unknown ifindex\n");
- return -ENODEV;
- }
-
- llattr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_LLADDR);
- if (llattr == NULL || nla_len(llattr) != ETH_ALEN) {
- pr_info("bridge: RTM_DELNEIGH with invalid address\n");
- return -EINVAL;
- }
-
- addr = nla_data(llattr);
-
p = br_port_get_rtnl(dev);
if (p == NULL) {
pr_info("bridge: RTM_DELNEIGH %s not a bridge port\n",
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 346b368..1fa0535 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -232,18 +232,6 @@ int __init br_netlink_init(void)
br_rtm_setlink, NULL, NULL);
if (err)
goto err3;
- err = __rtnl_register(PF_BRIDGE, RTM_NEWNEIGH,
- br_fdb_add, NULL, NULL);
- if (err)
- goto err3;
- err = __rtnl_register(PF_BRIDGE, RTM_DELNEIGH,
- br_fdb_delete, NULL, NULL);
- if (err)
- goto err3;
- err = __rtnl_register(PF_BRIDGE, RTM_GETNEIGH,
- NULL, br_fdb_dump, NULL);
- if (err)
- goto err3;
return 0;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 0b67a63..929b9f6 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -363,9 +363,18 @@ extern int br_fdb_insert(struct net_bridge *br,
extern void br_fdb_update(struct net_bridge *br,
struct net_bridge_port *source,
const unsigned char *addr);
-extern int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb);
-extern int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
-extern int br_fdb_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
+
+extern int br_fdb_delete(struct ndmsg *ndm,
+ struct net_device *dev,
+ unsigned char *addr);
+extern int br_fdb_add(struct ndmsg *nlh,
+ struct net_device *dev,
+ unsigned char *addr,
+ u16 nlh_flags);
+extern int br_fdb_dump(struct sk_buff *skb,
+ struct netlink_callback *cb,
+ struct net_device *dev,
+ int idx);
/* br_forward.c */
extern void br_deliver(const struct net_bridge_port *to,
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 545a969..5ec09d5 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -35,7 +35,9 @@
#include <linux/security.h>
#include <linux/mutex.h>
#include <linux/if_addr.h>
+#include <linux/if_bridge.h>
#include <linux/pci.h>
+#include <linux/etherdevice.h>
#include <asm/uaccess.h>
@@ -1978,6 +1980,152 @@ errout:
rtnl_set_sk_err(net, RTNLGRP_LINK, err);
}
+static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+ struct net *net = sock_net(skb->sk);
+ struct net_device *master = NULL;
+ struct ndmsg *ndm;
+ struct nlattr *tb[NDA_MAX+1];
+ struct net_device *dev;
+ u8 *addr;
+ int err;
+
+ err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
+ if (err < 0)
+ return err;
+
+ ndm = nlmsg_data(nlh);
+ if (ndm->ndm_ifindex == 0) {
+ pr_info("PF_BRIDGE: RTM_NEWNEIGH with invalid ifindex\n");
+ return -EINVAL;
+ }
+
+ dev = __dev_get_by_index(net, ndm->ndm_ifindex);
+ if (dev == NULL) {
+ pr_info("PF_BRIDGE: RTM_NEWNEIGH with unknown ifindex\n");
+ return -ENODEV;
+ }
+
+ if (!tb[NDA_LLADDR] || nla_len(tb[NDA_LLADDR]) != ETH_ALEN) {
+ pr_info("PF_BRIDGE: RTM_NEWNEIGH with invalid address\n");
+ return -EINVAL;
+ }
+
+ addr = nla_data(tb[NDA_LLADDR]);
+ if (!is_valid_ether_addr(addr)) {
+ pr_info("PF_BRIDGE: RTM_NEWNEIGH with invalid ether address\n");
+ return -EINVAL;
+ }
+
+ err = -EOPNOTSUPP;
+
+ /* Support fdb on master device the net/bridge default case */
+ if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) &&
+ (dev->priv_flags & IFF_BRIDGE_PORT)) {
+ master = dev->master;
+ err = master->netdev_ops->ndo_fdb_add(ndm, dev, addr,
+ nlh->nlmsg_flags);
+ if (err)
+ goto out;
+ else
+ ndm->ndm_flags &= ~NTF_MASTER;
+ }
+
+ /* Embedded bridge, macvlan, and any other device support */
+ if ((ndm->ndm_flags & NTF_SELF) && dev->netdev_ops->ndo_fdb_add) {
+ err = dev->netdev_ops->ndo_fdb_add(ndm, dev, addr,
+ nlh->nlmsg_flags);
+
+ if (!err)
+ ndm->ndm_flags &= ~NTF_SELF;
+ }
+out:
+ return err;
+}
+
+static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+ struct net *net = sock_net(skb->sk);
+ struct ndmsg *ndm;
+ struct nlattr *llattr;
+ struct net_device *dev;
+ int err = -EINVAL;
+ __u8 *addr;
+
+ if (nlmsg_len(nlh) < sizeof(*ndm))
+ return -EINVAL;
+
+ ndm = nlmsg_data(nlh);
+ if (ndm->ndm_ifindex == 0) {
+ pr_info("PF_BRIDGE: RTM_DELNEIGH with invalid ifindex\n");
+ return -EINVAL;
+ }
+
+ dev = __dev_get_by_index(net, ndm->ndm_ifindex);
+ if (dev == NULL) {
+ pr_info("PF_BRIDGE: RTM_DELNEIGH with unknown ifindex\n");
+ return -ENODEV;
+ }
+
+ llattr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_LLADDR);
+ if (llattr == NULL || nla_len(llattr) != ETH_ALEN) {
+ pr_info("PF_BRIGDE: RTM_DELNEIGH with invalid address\n");
+ return -EINVAL;
+ }
+
+ addr = nla_data(llattr);
+ err = -EOPNOTSUPP;
+
+ /* Support fdb on master device the net/bridge default case */
+ if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) &&
+ (dev->priv_flags & IFF_BRIDGE_PORT)) {
+ struct net_device *master = dev->master;
+
+ if (master->netdev_ops->ndo_fdb_del)
+ err = master->netdev_ops->ndo_fdb_del(ndm, dev, addr);
+
+ if (err)
+ goto out;
+ else
+ ndm->ndm_flags &= ~NTF_MASTER;
+ }
+
+ /* Embedded bridge, macvlan, and any other device support */
+ if ((ndm->ndm_flags & NTF_SELF) && dev->netdev_ops->ndo_fdb_del) {
+ err = dev->netdev_ops->ndo_fdb_del(ndm, dev, addr);
+
+ if (!err)
+ ndm->ndm_flags &= ~NTF_SELF;
+ }
+out:
+ return err;
+}
+
+static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ int idx = 0;
+ struct net *net = sock_net(skb->sk);
+ struct net_device *dev;
+
+ rcu_read_lock();
+ for_each_netdev_rcu(net, dev) {
+ if (dev->priv_flags & IFF_BRIDGE_PORT) {
+ struct net_device *master = dev->master;
+ const struct net_device_ops *ops = master->netdev_ops;
+
+ if (ops->ndo_fdb_dump)
+ idx = ops->ndo_fdb_dump(skb, cb, dev, idx);
+ }
+
+ if (dev->netdev_ops->ndo_fdb_dump)
+ idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, idx);
+ }
+ rcu_read_unlock();
+
+ cb->args[0] = idx;
+ return skb->len;
+}
+
/* Protected by RTNL sempahore. */
static struct rtattr **rta_buf;
static int rtattr_max;
@@ -2150,5 +2298,9 @@ void __init rtnetlink_init(void)
rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all, NULL);
rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all, NULL);
+
+ rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, rtnl_fdb_add, NULL, NULL);
+ rtnl_register(PF_BRIDGE, RTM_DELNEIGH, rtnl_fdb_del, NULL, NULL);
+ rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, rtnl_fdb_dump, NULL);
}
^ permalink raw reply related
* [net-next PATCH v2 2/8] net: addr_list: add exclusive dev_uc_add and dev_mc_add
From: John Fastabend @ 2012-04-12 6:57 UTC (permalink / raw)
To: shemminger, mst, davem, bhutchings, sri
Cc: hadi, jeffrey.t.kirsher, netdev, gregory.v.rose, krkumar2
In-Reply-To: <20120412064858.3112.65818.stgit@jf-dev1-dcblab>
This adds a dev_uc_add_excl() and dev_mc_add_excl() calls
similar to the original dev_{uc|mc}_add() except it sets
the global bit and returns -EEXIST for duplicat entires.
This is useful for drivers that support SR-IOV, macvlan
devices and any other devices that need to manage the
unicast and multicast lists.
v2: fix typo UNICAST should be MULTICAST in dev_mc_add_excl()
CC: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
---
include/linux/netdevice.h | 2 +
net/core/dev_addr_lists.c | 97 ++++++++++++++++++++++++++++++++++++++-------
2 files changed, 83 insertions(+), 16 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 7600c61..3f738ca 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2569,6 +2569,7 @@ extern int dev_addr_init(struct net_device *dev);
/* Functions used for unicast addresses handling */
extern int dev_uc_add(struct net_device *dev, unsigned char *addr);
+extern int dev_uc_add_excl(struct net_device *dev, unsigned char *addr);
extern int dev_uc_del(struct net_device *dev, unsigned char *addr);
extern int dev_uc_sync(struct net_device *to, struct net_device *from);
extern void dev_uc_unsync(struct net_device *to, struct net_device *from);
@@ -2578,6 +2579,7 @@ extern void dev_uc_init(struct net_device *dev);
/* Functions used for multicast addresses handling */
extern int dev_mc_add(struct net_device *dev, unsigned char *addr);
extern int dev_mc_add_global(struct net_device *dev, unsigned char *addr);
+extern int dev_mc_add_excl(struct net_device *dev, unsigned char *addr);
extern int dev_mc_del(struct net_device *dev, unsigned char *addr);
extern int dev_mc_del_global(struct net_device *dev, unsigned char *addr);
extern int dev_mc_sync(struct net_device *to, struct net_device *from);
diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c
index 626698f..c4cc2bc 100644
--- a/net/core/dev_addr_lists.c
+++ b/net/core/dev_addr_lists.c
@@ -21,12 +21,35 @@
* General list handling functions
*/
+static int __hw_addr_create_ex(struct netdev_hw_addr_list *list,
+ unsigned char *addr, int addr_len,
+ unsigned char addr_type, bool global)
+{
+ struct netdev_hw_addr *ha;
+ int alloc_size;
+
+ alloc_size = sizeof(*ha);
+ if (alloc_size < L1_CACHE_BYTES)
+ alloc_size = L1_CACHE_BYTES;
+ ha = kmalloc(alloc_size, GFP_ATOMIC);
+ if (!ha)
+ return -ENOMEM;
+ memcpy(ha->addr, addr, addr_len);
+ ha->type = addr_type;
+ ha->refcount = 1;
+ ha->global_use = global;
+ ha->synced = false;
+ list_add_tail_rcu(&ha->list, &list->list);
+ list->count++;
+
+ return 0;
+}
+
static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
unsigned char *addr, int addr_len,
unsigned char addr_type, bool global)
{
struct netdev_hw_addr *ha;
- int alloc_size;
if (addr_len > MAX_ADDR_LEN)
return -EINVAL;
@@ -46,21 +69,7 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
}
}
-
- alloc_size = sizeof(*ha);
- if (alloc_size < L1_CACHE_BYTES)
- alloc_size = L1_CACHE_BYTES;
- ha = kmalloc(alloc_size, GFP_ATOMIC);
- if (!ha)
- return -ENOMEM;
- memcpy(ha->addr, addr, addr_len);
- ha->type = addr_type;
- ha->refcount = 1;
- ha->global_use = global;
- ha->synced = false;
- list_add_tail_rcu(&ha->list, &list->list);
- list->count++;
- return 0;
+ return __hw_addr_create_ex(list, addr, addr_len, addr_type, global);
}
static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr,
@@ -377,6 +386,34 @@ EXPORT_SYMBOL(dev_addr_del_multiple);
*/
/**
+ * dev_uc_add_excl - Add a global secondary unicast address
+ * @dev: device
+ * @addr: address to add
+ */
+int dev_uc_add_excl(struct net_device *dev, unsigned char *addr)
+{
+ struct netdev_hw_addr *ha;
+ int err;
+
+ netif_addr_lock_bh(dev);
+ list_for_each_entry(ha, &dev->uc.list, list) {
+ if (!memcmp(ha->addr, addr, dev->addr_len) &&
+ ha->type == NETDEV_HW_ADDR_T_UNICAST) {
+ err = -EEXIST;
+ goto out;
+ }
+ }
+ err = __hw_addr_create_ex(&dev->uc, addr, dev->addr_len,
+ NETDEV_HW_ADDR_T_UNICAST, true);
+ if (!err)
+ __dev_set_rx_mode(dev);
+out:
+ netif_addr_unlock_bh(dev);
+ return err;
+}
+EXPORT_SYMBOL(dev_uc_add_excl);
+
+/**
* dev_uc_add - Add a secondary unicast address
* @dev: device
* @addr: address to add
@@ -501,6 +538,34 @@ EXPORT_SYMBOL(dev_uc_init);
* Multicast list handling functions
*/
+/**
+ * dev_mc_add_excl - Add a global secondary multicast address
+ * @dev: device
+ * @addr: address to add
+ */
+int dev_mc_add_excl(struct net_device *dev, unsigned char *addr)
+{
+ struct netdev_hw_addr *ha;
+ int err;
+
+ netif_addr_lock_bh(dev);
+ list_for_each_entry(ha, &dev->mc.list, list) {
+ if (!memcmp(ha->addr, addr, dev->addr_len) &&
+ ha->type == NETDEV_HW_ADDR_T_MULTICAST) {
+ err = -EEXIST;
+ goto out;
+ }
+ }
+ err = __hw_addr_create_ex(&dev->mc, addr, dev->addr_len,
+ NETDEV_HW_ADDR_T_MULTICAST, true);
+ if (!err)
+ __dev_set_rx_mode(dev);
+out:
+ netif_addr_unlock_bh(dev);
+ return err;
+}
+EXPORT_SYMBOL(dev_mc_add_excl);
+
static int __dev_mc_add(struct net_device *dev, unsigned char *addr,
bool global)
{
^ permalink raw reply related
* [net-next PATCH v2 3/8] net: add fdb generic dump routine
From: John Fastabend @ 2012-04-12 6:57 UTC (permalink / raw)
To: shemminger, mst, davem, bhutchings, sri
Cc: hadi, jeffrey.t.kirsher, netdev, gregory.v.rose, krkumar2
In-Reply-To: <20120412064858.3112.65818.stgit@jf-dev1-dcblab>
This adds a generic dump routine drivers can call. It
should be sufficient to handle any bridging model that
uses the unicast address list. This should be most SR-IOV
enabled NICs.
v2: return error on nlmsg_put and use -EMSGSIZE instead
of -ENOMEM this is inline other usages
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
---
net/core/rtnetlink.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 84 insertions(+), 0 deletions(-)
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 5ec09d5..347c420 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1980,6 +1980,37 @@ errout:
rtnl_set_sk_err(net, RTNLGRP_LINK, err);
}
+static int nlmsg_populate_fdb_fill(struct sk_buff *skb,
+ struct net_device *dev,
+ u8 *addr, u32 pid, u32 seq,
+ int type, unsigned int flags)
+{
+ struct nlmsghdr *nlh;
+ struct ndmsg *ndm;
+
+ nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), NLM_F_MULTI);
+ if (!nlh)
+ return -EMSGSIZE;
+
+ ndm = nlmsg_data(nlh);
+ ndm->ndm_family = AF_BRIDGE;
+ ndm->ndm_pad1 = 0;
+ ndm->ndm_pad2 = 0;
+ ndm->ndm_flags = flags;
+ ndm->ndm_type = 0;
+ ndm->ndm_ifindex = dev->ifindex;
+ ndm->ndm_state = NUD_PERMANENT;
+
+ if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr))
+ goto nla_put_failure;
+
+ return nlmsg_end(skb, nlh);
+
+nla_put_failure:
+ nlmsg_cancel(skb, nlh);
+ return -EMSGSIZE;
+}
+
static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
struct net *net = sock_net(skb->sk);
@@ -2101,6 +2132,59 @@ out:
return err;
}
+static int nlmsg_populate_fdb(struct sk_buff *skb,
+ struct netlink_callback *cb,
+ struct net_device *dev,
+ int *idx,
+ struct netdev_hw_addr_list *list)
+{
+ struct netdev_hw_addr *ha;
+ int err;
+ u32 pid, seq;
+
+ pid = NETLINK_CB(cb->skb).pid;
+ seq = cb->nlh->nlmsg_seq;
+
+ list_for_each_entry(ha, &list->list, list) {
+ if (*idx < cb->args[0])
+ goto skip;
+
+ err = nlmsg_populate_fdb_fill(skb, dev, ha->addr,
+ pid, seq, 0, NTF_SELF);
+ if (err < 0)
+ break;
+skip:
+ *idx += 1;
+ }
+ return 0;
+}
+
+/**
+ * ndo_dflt_fdb_dump: default netdevice operation to dump an FDB table.
+ * @nlh: netlink message header
+ * @dev: netdevice
+ *
+ * Default netdevice operation to dump the existing unicast address list.
+ * Returns zero on success.
+ */
+int ndo_dflt_fdb_dump(struct sk_buff *skb,
+ struct netlink_callback *cb,
+ struct net_device *dev,
+ int idx)
+{
+ int err;
+
+ netif_addr_lock_bh(dev);
+ err = nlmsg_populate_fdb(skb, cb, dev, &idx, &dev->uc);
+ if (err)
+ goto out;
+ nlmsg_populate_fdb(skb, cb, dev, &idx, &dev->mc);
+out:
+ netif_addr_unlock_bh(dev);
+ return idx;
+}
+EXPORT_SYMBOL(ndo_dflt_fdb_dump);
+
static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
{
int idx = 0;
^ permalink raw reply related
* [net-next PATCH v2 4/8] net: rtnetlink notify events for FDB NTF_SELF adds and deletes
From: John Fastabend @ 2012-04-12 6:57 UTC (permalink / raw)
To: shemminger, mst, davem, bhutchings, sri
Cc: hadi, jeffrey.t.kirsher, netdev, gregory.v.rose, krkumar2
In-Reply-To: <20120412064858.3112.65818.stgit@jf-dev1-dcblab>
It is useful to be able to monitor for FDB events in user space.
This patch adds support to generate netlink events when a change
is made to a device supporting the FDB ops.
This brings embedded switches inline with the SW net/bridge which
triggers events on FDB updates as well.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
---
net/core/rtnetlink.c | 35 +++++++++++++++++++++++++++++++++--
1 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 347c420..4b7ed7b 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -2011,6 +2011,33 @@ nla_put_failure:
return -EMSGSIZE;
}
+static inline size_t rtnl_fdb_nlmsg_size(void)
+{
+ return NLMSG_ALIGN(sizeof(struct ndmsg)) + nla_total_size(ETH_ALEN);
+}
+
+static void rtnl_fdb_notify(struct net_device *dev, u8 *addr, int type)
+{
+ struct net *net = dev_net(dev);
+ struct sk_buff *skb;
+ int err = -ENOBUFS;
+
+ skb = nlmsg_new(rtnl_fdb_nlmsg_size(), GFP_ATOMIC);
+ if (!skb)
+ goto errout;
+
+ err = nlmsg_populate_fdb_fill(skb, dev, addr, 0, 0, type, NTF_SELF);
+ if (err < 0) {
+ kfree_skb(skb);
+ goto errout;
+ }
+
+ rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
+ return;
+errout:
+ rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
+}
+
static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
struct net *net = sock_net(skb->sk);
@@ -2067,8 +2094,10 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
err = dev->netdev_ops->ndo_fdb_add(ndm, dev, addr,
nlh->nlmsg_flags);
- if (!err)
+ if (!err) {
+ rtnl_fdb_notify(dev, addr, RTM_NEWNEIGH);
ndm->ndm_flags &= ~NTF_SELF;
+ }
}
out:
return err;
@@ -2125,8 +2154,10 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
if ((ndm->ndm_flags & NTF_SELF) && dev->netdev_ops->ndo_fdb_del) {
err = dev->netdev_ops->ndo_fdb_del(ndm, dev, addr);
- if (!err)
+ if (!err) {
+ rtnl_fdb_notify(dev, addr, RTM_DELNEIGH);
ndm->ndm_flags &= ~NTF_SELF;
+ }
}
out:
return err;
^ permalink raw reply related
* [net-next PATCH v2 5/8] ixgbe: enable FDB netdevice ops
From: John Fastabend @ 2012-04-12 6:57 UTC (permalink / raw)
To: shemminger, mst, davem, bhutchings, sri
Cc: hadi, jeffrey.t.kirsher, netdev, gregory.v.rose, krkumar2
In-Reply-To: <20120412064858.3112.65818.stgit@jf-dev1-dcblab>
Enable FDB ops on ixgbe when in SR-IOV mode.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 71 +++++++++++++++++++++++++
1 files changed, 71 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 3e26b1f..8b37395 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -6681,6 +6681,74 @@ static int ixgbe_set_features(struct net_device *netdev,
return 0;
}
+static int ixgbe_ndo_fdb_add(struct ndmsg *ndm,
+ struct net_device *dev,
+ unsigned char *addr,
+ u16 flags)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ int err = -EOPNOTSUPP;
+
+ if (ndm->ndm_state & NUD_PERMANENT) {
+ pr_info("%s: FDB only supports static addresses\n",
+ ixgbe_driver_name);
+ return -EINVAL;
+ }
+
+ if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
+ if (is_unicast_ether_addr(addr))
+ err = dev_uc_add_excl(dev, addr);
+ else if (is_multicast_ether_addr(addr))
+ err = dev_mc_add_excl(dev, addr);
+ else
+ err = -EINVAL;
+ }
+
+ /* Only return duplicate errors if NLM_F_EXCL is set */
+ if (err == -EEXIST && !(flags & NLM_F_EXCL))
+ err = 0;
+
+ return err;
+}
+
+static int ixgbe_ndo_fdb_del(struct ndmsg *ndm,
+ struct net_device *dev,
+ unsigned char *addr)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ int err = -EOPNOTSUPP;
+
+ if (ndm->ndm_state & NUD_PERMANENT) {
+ pr_info("%s: FDB only supports static addresses\n",
+ ixgbe_driver_name);
+ return -EINVAL;
+ }
+
+ if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
+ if (is_unicast_ether_addr(addr))
+ err = dev_uc_del(dev, addr);
+ else if (is_multicast_ether_addr(addr))
+ err = dev_mc_del(dev, addr);
+ else
+ err = -EINVAL;
+ }
+
+ return err;
+}
+
+static int ixgbe_ndo_fdb_dump(struct sk_buff *skb,
+ struct netlink_callback *cb,
+ struct net_device *dev,
+ int idx)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+
+ if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
+ idx = ndo_dflt_fdb_dump(skb, cb, dev, idx);
+
+ return idx;
+}
+
static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_open = ixgbe_open,
.ndo_stop = ixgbe_close,
@@ -6717,6 +6785,9 @@ static const struct net_device_ops ixgbe_netdev_ops = {
#endif /* IXGBE_FCOE */
.ndo_set_features = ixgbe_set_features,
.ndo_fix_features = ixgbe_fix_features,
+ .ndo_fdb_add = ixgbe_ndo_fdb_add,
+ .ndo_fdb_del = ixgbe_ndo_fdb_del,
+ .ndo_fdb_dump = ixgbe_ndo_fdb_dump,
};
static void __devinit ixgbe_probe_vf(struct ixgbe_adapter *adapter,
^ permalink raw reply related
* [net-next PATCH v2 6/8] ixgbe: allow RAR table to be updated in promisc mode
From: John Fastabend @ 2012-04-12 6:57 UTC (permalink / raw)
To: shemminger, mst, davem, bhutchings, sri
Cc: hadi, jeffrey.t.kirsher, netdev, gregory.v.rose, krkumar2
In-Reply-To: <20120412064858.3112.65818.stgit@jf-dev1-dcblab>
This allows RAR table updates while in promiscuous. With
SR-IOV enabled it is valuable to allow the RAR table to
be updated even when in promisc mode to configure forwarding
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 21 +++++++++++----------
1 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 8b37395..25a7ed9 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -3462,16 +3462,17 @@ void ixgbe_set_rx_mode(struct net_device *netdev)
}
ixgbe_vlan_filter_enable(adapter);
hw->addr_ctrl.user_set_promisc = false;
- /*
- * Write addresses to available RAR registers, if there is not
- * sufficient space to store all the addresses then enable
- * unicast promiscuous mode
- */
- count = ixgbe_write_uc_addr_list(netdev);
- if (count < 0) {
- fctrl |= IXGBE_FCTRL_UPE;
- vmolr |= IXGBE_VMOLR_ROPE;
- }
+ }
+
+ /*
+ * Write addresses to available RAR registers, if there is not
+ * sufficient space to store all the addresses then enable
+ * unicast promiscuous mode
+ */
+ count = ixgbe_write_uc_addr_list(netdev);
+ if (count < 0) {
+ fctrl |= IXGBE_FCTRL_UPE;
+ vmolr |= IXGBE_VMOLR_ROPE;
}
if (adapter->num_vfs) {
^ permalink raw reply related
* [net-next PATCH v2 7/8] ixgbe: UTA table incorrectly programmed
From: John Fastabend @ 2012-04-12 6:57 UTC (permalink / raw)
To: shemminger, mst, davem, bhutchings, sri
Cc: hadi, jeffrey.t.kirsher, netdev, gregory.v.rose, krkumar2
In-Reply-To: <20120412064858.3112.65818.stgit@jf-dev1-dcblab>
From: Greg Rose <gregory.v.rose@intel.com>
The UTA table was being set to the functional equivalent of promiscuous
mode. This was resulting in traffic from the virtual function being
flooded onto the wire and the PF device. This resulted in additional
overhead for VF traffic sent to the network and in the case of traffic
sent to the PF or another VF resulted in unwanted packets on the wire.
This was actually not the intended behavior. Now that we can program
the embedded switch correctly we can remove this snippit of code. Users
who want to support this should configure the FDB correctly using the
FDB ops.
Signed-off-by: Greg Rose <gregory.v.rose@intel.com>
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 29 -------------------------
1 files changed, 0 insertions(+), 29 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 25a7ed9..10606bd 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -2904,33 +2904,6 @@ static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,
IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(reg_idx), rscctrl);
}
-/**
- * ixgbe_set_uta - Set unicast filter table address
- * @adapter: board private structure
- *
- * The unicast table address is a register array of 32-bit registers.
- * The table is meant to be used in a way similar to how the MTA is used
- * however due to certain limitations in the hardware it is necessary to
- * set all the hash bits to 1 and use the VMOLR ROPE bit as a promiscuous
- * enable bit to allow vlan tag stripping when promiscuous mode is enabled
- **/
-static void ixgbe_set_uta(struct ixgbe_adapter *adapter)
-{
- struct ixgbe_hw *hw = &adapter->hw;
- int i;
-
- /* The UTA table only exists on 82599 hardware and newer */
- if (hw->mac.type < ixgbe_mac_82599EB)
- return;
-
- /* we only need to do this if VMDq is enabled */
- if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
- return;
-
- for (i = 0; i < 128; i++)
- IXGBE_WRITE_REG(hw, IXGBE_UTA(i), ~0);
-}
-
#define IXGBE_MAX_RX_DESC_POLL 10
static void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter,
struct ixgbe_ring *ring)
@@ -3224,8 +3197,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
/* Program registers for the distribution of queues */
ixgbe_setup_mrqc(adapter);
- ixgbe_set_uta(adapter);
-
/* set_rx_buffer_len must be called before ring initialization */
ixgbe_set_rx_buffer_len(adapter);
^ permalink raw reply related
* [net-next PATCH v2 8/8] macvlan: add FDB bridge ops and macvlan flags
From: John Fastabend @ 2012-04-12 6:57 UTC (permalink / raw)
To: shemminger, mst, davem, bhutchings, sri
Cc: hadi, jeffrey.t.kirsher, netdev, gregory.v.rose, krkumar2
In-Reply-To: <20120412064858.3112.65818.stgit@jf-dev1-dcblab>
This adds FDB bridge ops to the macvlan device passthru mode.
Additionally a flags field was added and a NOPROMISC bit to
allow users to use passthru mode without the driver calling
dev_set_promiscuity(). The flags field is a u16 placed in a
4 byte hole (consuming 2 bytes) of the macvlan_dev struct.
We want to do this so that the macvlan driver or stack
above the macvlan driver does not have to process every
packet. For the use case where we know all the MAC addresses
of the endstations above us this works well.
This patch is a result of Roopa Prabhu's work. Follow up
patches are needed for VEPA and VEB macvlan modes.
v2: Change from distinct nopromisc mode to a flags field to
configure this. This avoids the tendency to add a new
mode every time we need some slightly different behavior.
CC: Roopa Prabhu <roprabhu@cisco.com>
CC: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
---
drivers/net/macvlan.c | 61 ++++++++++++++++++++++++++++++++++++++++----
include/linux/if_link.h | 3 ++
include/linux/if_macvlan.h | 1 +
3 files changed, 59 insertions(+), 6 deletions(-)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index b17fc90..df782c0 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -312,7 +312,8 @@ static int macvlan_open(struct net_device *dev)
int err;
if (vlan->port->passthru) {
- dev_set_promiscuity(lowerdev, 1);
+ if (!(vlan->flags & MACVLAN_FLAG_NOPROMISC))
+ dev_set_promiscuity(lowerdev, 1);
goto hash_add;
}
@@ -344,12 +345,15 @@ static int macvlan_stop(struct net_device *dev)
struct macvlan_dev *vlan = netdev_priv(dev);
struct net_device *lowerdev = vlan->lowerdev;
+ dev_uc_unsync(lowerdev, dev);
+ dev_mc_unsync(lowerdev, dev);
+
if (vlan->port->passthru) {
- dev_set_promiscuity(lowerdev, -1);
+ if (!(vlan->flags & MACVLAN_FLAG_NOPROMISC))
+ dev_set_promiscuity(lowerdev, 1);
goto hash_del;
}
- dev_mc_unsync(lowerdev, dev);
if (dev->flags & IFF_ALLMULTI)
dev_set_allmulti(lowerdev, -1);
@@ -399,10 +403,11 @@ static void macvlan_change_rx_flags(struct net_device *dev, int change)
dev_set_allmulti(lowerdev, dev->flags & IFF_ALLMULTI ? 1 : -1);
}
-static void macvlan_set_multicast_list(struct net_device *dev)
+static void macvlan_set_mac_lists(struct net_device *dev)
{
struct macvlan_dev *vlan = netdev_priv(dev);
+ dev_uc_sync(vlan->lowerdev, dev);
dev_mc_sync(vlan->lowerdev, dev);
}
@@ -542,6 +547,43 @@ static int macvlan_vlan_rx_kill_vid(struct net_device *dev,
return 0;
}
+static int macvlan_fdb_add(struct ndmsg *ndm,
+ struct net_device *dev,
+ unsigned char *addr,
+ u16 flags)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ int err = -EINVAL;
+
+ if (!vlan->port->passthru)
+ return -EOPNOTSUPP;
+
+ if (is_unicast_ether_addr(addr))
+ err = dev_uc_add_excl(dev, addr);
+ else if (is_multicast_ether_addr(addr))
+ err = dev_mc_add_excl(dev, addr);
+
+ return err;
+}
+
+static int macvlan_fdb_del(struct ndmsg *ndm,
+ struct net_device *dev,
+ unsigned char *addr)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ int err = -EINVAL;
+
+ if (!vlan->port->passthru)
+ return -EOPNOTSUPP;
+
+ if (is_unicast_ether_addr(addr))
+ err = dev_uc_del(dev, addr);
+ else if (is_multicast_ether_addr(addr))
+ err = dev_mc_del(dev, addr);
+
+ return err;
+}
+
static void macvlan_ethtool_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *drvinfo)
{
@@ -572,11 +614,14 @@ static const struct net_device_ops macvlan_netdev_ops = {
.ndo_change_mtu = macvlan_change_mtu,
.ndo_change_rx_flags = macvlan_change_rx_flags,
.ndo_set_mac_address = macvlan_set_mac_address,
- .ndo_set_rx_mode = macvlan_set_multicast_list,
+ .ndo_set_rx_mode = macvlan_set_mac_lists,
.ndo_get_stats64 = macvlan_dev_get_stats64,
.ndo_validate_addr = eth_validate_addr,
.ndo_vlan_rx_add_vid = macvlan_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = macvlan_vlan_rx_kill_vid,
+ .ndo_fdb_add = macvlan_fdb_add,
+ .ndo_fdb_del = macvlan_fdb_del,
+ .ndo_fdb_dump = ndo_dflt_fdb_dump,
};
void macvlan_common_setup(struct net_device *dev)
@@ -711,6 +756,9 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
if (data && data[IFLA_MACVLAN_MODE])
vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
+ if (data && data[IFLA_MACVLAN_FLAGS])
+ vlan->flags = nla_get_u16(data[IFLA_MACVLAN_FLAGS]);
+
if (vlan->mode == MACVLAN_MODE_PASSTHRU) {
if (port->count)
return -EINVAL;
@@ -782,7 +830,8 @@ nla_put_failure:
}
static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = {
- [IFLA_MACVLAN_MODE] = { .type = NLA_U32 },
+ [IFLA_MACVLAN_MODE] = { .type = NLA_U32 },
+ [IFLA_MACVLAN_FLAGS] = { .type = NLA_U16 },
};
int macvlan_link_register(struct rtnl_link_ops *ops)
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 2f4fa93..f715750 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -255,6 +255,7 @@ struct ifla_vlan_qos_mapping {
enum {
IFLA_MACVLAN_UNSPEC,
IFLA_MACVLAN_MODE,
+ IFLA_MACVLAN_FLAGS,
__IFLA_MACVLAN_MAX,
};
@@ -267,6 +268,8 @@ enum macvlan_mode {
MACVLAN_MODE_PASSTHRU = 8,/* take over the underlying device */
};
+#define MACVLAN_FLAG_NOPROMISC 1
+
/* SR-IOV virtual function management section */
enum {
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
index d103dca..f65e8d2 100644
--- a/include/linux/if_macvlan.h
+++ b/include/linux/if_macvlan.h
@@ -60,6 +60,7 @@ struct macvlan_dev {
struct net_device *lowerdev;
struct macvlan_pcpu_stats __percpu *pcpu_stats;
enum macvlan_mode mode;
+ u16 flags;
int (*receive)(struct sk_buff *skb);
int (*forward)(struct net_device *dev, struct sk_buff *skb);
struct macvtap_queue *taps[MAX_MACVTAP_QUEUES];
^ permalink raw reply related
* [RFC v3] Add TCP encap_rcv hook
From: Simon Horman @ 2012-04-12 7:42 UTC (permalink / raw)
To: dev-yBygre7rU0TnMu66kgdUjQ, netdev-u79uwXL29TY76Z2rM5mHXA
This hook is based on a hook of the same name provided by UDP. It provides
a way for to receive packets that have a TCP header and treat them in some
alternate way.
It is intended to be used by an implementation of the STT tunneling
protocol within Open vSwtich's datapath. A prototype of such an
implementation has been made.
The STT draft is available at
http://tools.ietf.org/html/draft-davie-stt-01
My prototype STT implementation has been posted to the dev-UOEtcQmXneFl884UGnbwIQ@public.gmane.org
The first version can be found at:
http://www.mail-archive.com/dev-yBygre7rU0TnMu66kgdUjQ@public.gmane.org/msg08877.html
Signed-off-by: Simon Horman <horms-/R6kz+dDXgpPR4JQBCEnsQ@public.gmane.org>
---
include/linux/tcp.h | 3 +++
net/ipv4/tcp_ipv4.c | 23 ++++++++++++++++++++++-
2 files changed, 25 insertions(+), 1 deletion(-)
v3
* First post to netdev
* Replace more UDP references with TCP
* Move socket accesses to inside socket lock
and release lock on return.
v2
* Fix comment to refer to TCP rather than UDP
* Allow skb to continue traversing the stack if
the encap_rcv callback returns a positive value.
This is the same behaviour as the UDP hook.
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index b6c62d2..7210b23 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -472,6 +472,9 @@ struct tcp_sock {
* contains related tcp_cookie_transactions fields.
*/
struct tcp_cookie_values *cookie_values;
+
+ /* For encapsulation sockets. */
+ int (*encap_rcv)(struct sock *sk, struct sk_buff *skb);
};
static inline struct tcp_sock *tcp_sk(const struct sock *sk)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 3a25cf7..9898f71 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1666,8 +1666,10 @@ int tcp_v4_rcv(struct sk_buff *skb)
const struct iphdr *iph;
const struct tcphdr *th;
struct sock *sk;
+ struct tcp_sock *tp;
int ret;
struct net *net = dev_net(skb->dev);
+ int (*encap_rcv)(struct sock *sk, struct sk_buff *skb);
if (skb->pkt_type != PACKET_HOST)
goto discard_it;
@@ -1726,9 +1728,27 @@ process:
bh_lock_sock_nested(sk);
ret = 0;
+
+ tp = tcp_sk(sk);
+ encap_rcv = ACCESS_ONCE(tp->encap_rcv);
+ if (encap_rcv != NULL) {
+ /*
+ * This is an encapsulation socket so pass the skb to
+ * the socket's tcp_encap_rcv() hook. Otherwise, just
+ * fall through and pass this up the TCP socket.
+ * up->encap_rcv() returns the following value:
+ * <=0 if skb was successfully passed to the encap
+ * handler or was discarded by it.
+ * >0 if skb should be passed on to TCP.
+ */
+ if (encap_rcv(sk, skb) <= 0) {
+ ret = 0;
+ goto unlock_sock;
+ }
+ }
+
if (!sock_owned_by_user(sk)) {
#ifdef CONFIG_NET_DMA
- struct tcp_sock *tp = tcp_sk(sk);
if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY);
if (tp->ucopy.dma_chan)
@@ -1744,6 +1764,7 @@ process:
NET_INC_STATS_BH(net, LINUX_MIB_TCPBACKLOGDROP);
goto discard_and_relse;
}
+unlock_sock:
bh_unlock_sock(sk);
sock_put(sk);
--
1.7.9.5
^ permalink raw reply related
* Re: [net-next PATCH v2 8/8] macvlan: add FDB bridge ops and macvlan flags
From: John Fastabend @ 2012-04-12 8:09 UTC (permalink / raw)
To: mst, sri
Cc: shemminger, davem, bhutchings, hadi, jeffrey.t.kirsher, netdev,
gregory.v.rose, krkumar2
In-Reply-To: <20120412065754.3112.31357.stgit@jf-dev1-dcblab>
On 4/11/2012 11:57 PM, John Fastabend wrote:
> This adds FDB bridge ops to the macvlan device passthru mode.
> Additionally a flags field was added and a NOPROMISC bit to
> allow users to use passthru mode without the driver calling
> dev_set_promiscuity(). The flags field is a u16 placed in a
> 4 byte hole (consuming 2 bytes) of the macvlan_dev struct.
>
> We want to do this so that the macvlan driver or stack
> above the macvlan driver does not have to process every
> packet. For the use case where we know all the MAC addresses
> of the endstations above us this works well.
>
> This patch is a result of Roopa Prabhu's work. Follow up
> patches are needed for VEPA and VEB macvlan modes.
>
> v2: Change from distinct nopromisc mode to a flags field to
> configure this. This avoids the tendency to add a new
> mode every time we need some slightly different behavior.
>
> CC: Roopa Prabhu <roprabhu@cisco.com>
> CC: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
> ---
>
oops this introduces an error in dev_set_promiscuity and I missed
adding flags to macvlan_fill_info() and the change routine
macvlan_changelink(). As it stands the flags can only be set at
creation time and can not be queried. I'll submit a v3 with this
fixup in the morning.
I suspect the addition below should be good enough. might try
to clean up the changelink logic a bit first.
---
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index df782c0..65c6d26 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -350,7 +350,7 @@ static int macvlan_stop(struct net_device *dev)
if (vlan->port->passthru) {
if (!(vlan->flags & MACVLAN_FLAG_NOPROMISC))
- dev_set_promiscuity(lowerdev, 1);
+ dev_set_promiscuity(lowerdev, -1);
goto hash_del;
}
@@ -808,6 +808,19 @@ static int macvlan_changelink(struct net_device *dev,
struct macvlan_dev *vlan = netdev_priv(dev);
if (data && data[IFLA_MACVLAN_MODE])
vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
+ if (data && data[IFLA_MACVLAN_FLAGS]) {
+ __u16 flags = nla_get_u16(data[IFLA_MACVLAN_FLAGS]);
+
+ flags &= MACVLAN_FLAG_NOPROMISC;
+
+ if ((flags ^ vlan->flags) && (flags & MACVLAN_FLAG_NOPROMISC))
+ dev_set_promiscuity(vlan->lowerdev, -1);
+ else if ((flags ^ vlan->flags) &&
+ !(flags & MACVLAN_FLAG_NOPROMISC))
+ dev_set_promiscuity(vlan->lowerdev, 1);
+
+ vlan->flags = flags;
+ }
return 0;
}
@@ -823,6 +836,8 @@ static int macvlan_fill_info(struct sk_buff *skb,
if (nla_put_u32(skb, IFLA_MACVLAN_MODE, vlan->mode))
goto nla_put_failure;
+ if (nla_put_u16(skb, IFLA_MACVLAN_FLAGS, vlan->flags))
+ goto nla_put_failure;
return 0;
nla_put_failure:
[root@jf-dev1-dcblab net-n
^ permalink raw reply related
* [PATCH] 8139cp: set intr mask after its handler is registered
From: Jason Wang @ 2012-04-12 8:10 UTC (permalink / raw)
To: netdev, davem, linux-kernel
We set intr mask before its handler is registered, this does not work well when
8139cp is sharing irq line with other devices. As the irq could be enabled by
the device before 8139cp's hander is registered which may lead unhandled
irq. Fix this by introducing an helper cp_irq_enable() and call it after
request_irq().
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
drivers/net/ethernet/realtek/8139cp.c | 10 ++++++++--
1 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index abc7907..b3287c0 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -958,6 +958,11 @@ static inline void cp_start_hw (struct cp_private *cp)
cpw8(Cmd, RxOn | TxOn);
}
+static void cp_enable_irq(struct cp_private *cp)
+{
+ cpw16_f(IntrMask, cp_intr_mask);
+}
+
static void cp_init_hw (struct cp_private *cp)
{
struct net_device *dev = cp->dev;
@@ -997,8 +1002,6 @@ static void cp_init_hw (struct cp_private *cp)
cpw16(MultiIntr, 0);
- cpw16_f(IntrMask, cp_intr_mask);
-
cpw8_f(Cfg9346, Cfg9346_Lock);
}
@@ -1130,6 +1133,8 @@ static int cp_open (struct net_device *dev)
if (rc)
goto err_out_hw;
+ cp_enable_irq(cp);
+
netif_carrier_off(dev);
mii_check_media(&cp->mii_if, netif_msg_link(cp), true);
netif_start_queue(dev);
@@ -2031,6 +2036,7 @@ static int cp_resume (struct pci_dev *pdev)
/* FIXME: sh*t may happen if the Rx ring buffer is depleted */
cp_init_rings_index (cp);
cp_init_hw (cp);
+ cp_enable_irq(cp);
netif_start_queue (dev);
spin_lock_irqsave (&cp->lock, flags);
^ permalink raw reply related
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