Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH] 8139cp: Prevent dev_close/cp_interrupt race on MTU change
From: David Woodhouse @ 2012-12-19 20:55 UTC (permalink / raw)
  To: David Miller; +Cc: jogreene, netdev
In-Reply-To: <20121219.124014.891279563982531558.davem@davemloft.net>

[-- Attachment #1: Type: text/plain, Size: 438 bytes --]

On Wed, 2012-12-19 at 12:40 -0800, David Miller wrote:
> You sent this as a "request for testing" last week, but I saw
> no testing on real hardware whatsoever.

Thanks for the reminder :)

Seems to work fine here. I haven't confirmed whether I actually see the
race or not but changing MTU on a live device works fine, even when it's
being ping-flooded.

Tested-by: David Woodhouse <David.Woodhouse@intel.com>

-- 
dwmw2


[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 6171 bytes --]

^ permalink raw reply

* Re: [PATCH] ipv6: addrconf.c: remove unnecessary "if"
From: David Miller @ 2012-12-19 20:51 UTC (permalink / raw)
  To: dinggnu; +Cc: kuznet, jmorris, yoshfuji, kaber, netdev, linux-kernel
In-Reply-To: <1355868536-1622-1-git-send-email-dinggnu@gmail.com>

From: Cong Ding <dinggnu@gmail.com>
Date: Tue, 18 Dec 2012 23:08:56 +0100

> the value of err is always negative if it goes to errout, so we don't need to
> check the value of err.
> 
> Signed-off-by: Cong Ding <dinggnu@gmail.com>

Applied.

^ permalink raw reply

* Re: [PATCH] bridge: Correctly encode addresses when dumping mdb entries
From: David Miller @ 2012-12-19 20:50 UTC (permalink / raw)
  To: vyasevic; +Cc: netdev, shemminger
In-Reply-To: <1355867648-17316-1-git-send-email-vyasevic@redhat.com>

From: Vlad Yasevich <vyasevic@redhat.com>
Date: Tue, 18 Dec 2012 16:54:08 -0500

> When dumping mdb table, set the addresses the kernel returns
> based on the address protocol type.
> 
> Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>

Applied.

^ permalink raw reply

* Re: [PATCH v2] bridge: Do not unregister all PF_BRIDGE rtnl operations
From: David Miller @ 2012-12-19 20:50 UTC (permalink / raw)
  To: vyasevic; +Cc: netdev, shemminger
In-Reply-To: <1355944428-32051-1-git-send-email-vyasevic@redhat.com>

From: Vlad Yasevich <vyasevic@redhat.com>
Date: Wed, 19 Dec 2012 14:13:48 -0500

> Bridge fdb and link rtnl operations are registered in
> core/rtnetlink.  Bridge mdb operations are registred
> in bridge/mdb.  When removing bridge module, do not
> unregister ALL PF_BRIDGE ops since that would remove
> the ops from rtnetlink as well.  Do remove mdb ops when
> bridge is destroyed.
> 
> Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>

Applied.

^ permalink raw reply

* Re: [PATCH net] net: qmi_wwan: add ZTE MF880
From: David Miller @ 2012-12-19 20:50 UTC (permalink / raw)
  To: bjorn-yOkvZcmFvRU
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA, linux-usb-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1355926551-30316-1-git-send-email-bjorn-yOkvZcmFvRU@public.gmane.org>

From: Bjørn Mork <bjorn-yOkvZcmFvRU@public.gmane.org>
Date: Wed, 19 Dec 2012 15:15:51 +0100

> The driver description files gives these names to the vendor specific
> functions on this modem:
> 
>  diag: VID_19D2&PID_0284&MI_00
>  nmea: VID_19D2&PID_0284&MI_01
>  at:   VID_19D2&PID_0284&MI_02
>  mdm:  VID_19D2&PID_0284&MI_03
>  net:  VID_19D2&PID_0284&MI_04
> 
> Signed-off-by: Bjørn Mork <bjorn-yOkvZcmFvRU@public.gmane.org>

Applied.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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 2/2] drivers/net: Use of_match_ptr() macro in smsc911x.c
From: David Miller @ 2012-12-19 20:50 UTC (permalink / raw)
  To: sachin.kamat; +Cc: netdev, steve.glendinning, patches, nico
In-Reply-To: <1355915830-29481-2-git-send-email-sachin.kamat@linaro.org>

From: Sachin Kamat <sachin.kamat@linaro.org>
Date: Wed, 19 Dec 2012 16:47:10 +0530

> Add CONFIG_OF guard and use of_match_ptr macro.
> 
> Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>

Applied.

^ permalink raw reply

* Re: [PATCH 1/2] drivers/net: Use of_match_ptr() macro in smc91x.c
From: David Miller @ 2012-12-19 20:50 UTC (permalink / raw)
  To: sachin.kamat; +Cc: netdev, steve.glendinning, patches, nico
In-Reply-To: <1355915830-29481-1-git-send-email-sachin.kamat@linaro.org>

From: Sachin Kamat <sachin.kamat@linaro.org>
Date: Wed, 19 Dec 2012 16:47:09 +0530

> This eliminates having an #ifdef returning NULL for the case
> when OF is disabled.
> 
> Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>

Applied.

^ permalink raw reply

* Re: [PATCH 3/3] use generic usbnet_manage_power()
From: David Miller @ 2012-12-19 20:47 UTC (permalink / raw)
  To: oliver; +Cc: netdev, oneukum
In-Reply-To: <1355841972-1068-1-git-send-email-oliver@neukum.org>

From: Oliver Neukum <oliver@neukum.org>
Date: Tue, 18 Dec 2012 15:46:12 +0100

> This covers the drivers that can use a primitive
> implementation.
> 
> Signed-off-by: Oliver Neukum <oneukum@suse.de>

Applied.

^ permalink raw reply

* Re: [PATCH 2/3] usbnet: generic manage_power()
From: David Miller @ 2012-12-19 20:47 UTC (permalink / raw)
  To: oliver; +Cc: netdev, oneukum
In-Reply-To: <1355841952-1025-1-git-send-email-oliver@neukum.org>

From: Oliver Neukum <oliver@neukum.org>
Date: Tue, 18 Dec 2012 15:45:52 +0100

> Centralise common code for manage_power() in usbnet
> by making a generic simple implementation
> 
> Signed-off-by: Oliver Neukum <oneukum@suse.de>

Applied.

^ permalink raw reply

* Re: [PATCH 1/3] usbnet: handle PM failure gracefully
From: David Miller @ 2012-12-19 20:47 UTC (permalink / raw)
  To: oliver; +Cc: netdev, oneukum
In-Reply-To: <1355841929-983-1-git-send-email-oliver@neukum.org>

From: Oliver Neukum <oliver@neukum.org>
Date: Tue, 18 Dec 2012 15:45:29 +0100

> If a device fails to do remote wakeup, this is no reason
> to abort an open totally. This patch just continues without
> runtime PM.
> 
> Signed-off-by: Oliver Neukum <oneukum@suse.de>

Applied.

^ permalink raw reply

* Re: [PATCH] ksz884x: fix receive polling race condition
From: David Miller @ 2012-12-19 20:45 UTC (permalink / raw)
  To: buytenh; +Cc: Tristram.Ha, dannyfeng, netdev, cphealy
In-Reply-To: <20121218135700.GT23447@wantstofly.org>

From: Lennert Buytenhek <buytenh@wantstofly.org>
Date: Tue, 18 Dec 2012 14:57:00 +0100

> The ksz884x driver does receive processing in a custom tasklet, and
> seems to be assuming that since it takes its private interface spinlock
> with spin_lock_irq(), it won't be running concurrently with its own
> interrupt handler, as it cannot be preempted by it, but since its
> interrupt handler doesn't do any locking whatsoever, the receive
> processing tasklet and interrupt handler can end up running concurrently
> on different CPUs.
> 
> As a result of this, the ksz884x receive path ends up locking up fairly
> easily, when the receive processing tasklet's reenabling of receive
> interrupts (due to it being done with polling the receive ring) races
> with the interrupt handler's disabling of receive interrupts (due to a
> new receive interrupt coming in) resulting in the receive interrupt
> being masked but the receive processing tasklet not being scheduled.
> 
> Fix this by making the ksz884x interrupt handler take its private
> interface spinlock.  This requires upgrading the spin_lock() in the
> transmit cleanup tasklet to a spin_lock_irq(), as otherwise the IRQ
> handler can preempt transmit cleanup and deadlock the system, but
> with those two changes, no more receive lockups have been observed.
> 
> Reported-by: Chris Healy <cphealy@gmail.com>
> Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org>

Applied, thanks.

^ permalink raw reply

* Re: [PATCH 2/2] qlcnic: update driver version
From: David Miller @ 2012-12-19 20:43 UTC (permalink / raw)
  To: sony.chacko; +Cc: netdev, Dept_NX_Linux_NIC_Driver
In-Reply-To: <1355853591-29917-3-git-send-email-sony.chacko@qlogic.com>

From: Sony Chacko <sony.chacko@qlogic.com>
Date: Tue, 18 Dec 2012 12:59:51 -0500

> From: Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
> 
> Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>

Applied.

^ permalink raw reply

* Re: [PATCH 1/2] qlcnic: fix unused variable warnings
From: David Miller @ 2012-12-19 20:43 UTC (permalink / raw)
  To: sony.chacko; +Cc: netdev, Dept_NX_Linux_NIC_Driver, shahed.shaikh
In-Reply-To: <1355853591-29917-2-git-send-email-sony.chacko@qlogic.com>

From: Sony Chacko <sony.chacko@qlogic.com>
Date: Tue, 18 Dec 2012 12:59:50 -0500

> From: Shahed Shaikh <shahed.shaikh@qlogic.com>
> 
> qlcnic_hw.c:370: warning: variable cmd_desc set but not used
> qlcnic_hw.c:368: warning: variable consumer set but not used
> qlcnic_main.c:448: warning: variable ref_count set but not used
> qlcnic_main.c:534: warning: variable mem_base set but not used
> qlcnic_ctx.c:137: warning: variable tmp_tmpl set but not used
> qlcnic_ctx.c:133: warning: variable version set but not used
> qlcnic_minidump.c:200: warning: variable opcode set but not used
> 
> Signed-off-by: Shahed Shaikh <shahed.shaikh@qlogic.com>
> Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>

Applied.

^ permalink raw reply

* Re: [PATCH] 8139cp: Prevent dev_close/cp_interrupt race on MTU change
From: David Miller @ 2012-12-19 20:40 UTC (permalink / raw)
  To: jogreene; +Cc: netdev, David.Woodhouse
In-Reply-To: <1355946468-3290-1-git-send-email-jogreene@redhat.com>

From: John Greene <jogreene@redhat.com>
Date: Wed, 19 Dec 2012 14:47:48 -0500

> commit:  cb64edb6b89491edfdbae52ba7db9a8b8391d339 upstream
> 
> Above commit may introduce a race between cp_interrupt and dev_close
> / change MTU / dev_open up state. Changes cp_interrupt to tolerate
> this.  Change spin_locking in cp_interrupt to avoid possible
> but unobserved race.
> 
> Reported-by: "Francois Romieu" <romieu@fr.zoreil.com>
> 
> Tested on virtual hardware, Tx MTU size up to 4096, max tx payload
>     was ping -s 4068 for MTU of 4096. No real hardware, need test
>     assist.
> 
> Signed-off-by: "John Greene" <jogreene@redhat.com>

You sent this as a "request for testing" last week, but I saw
no testing on real hardware whatsoever.

^ permalink raw reply

* Re: pull request: wireless 2012-12-19
From: David Miller @ 2012-12-19 20:39 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20121219183220.GB1912@tuxdriver.com>

From: "John W. Linville" <linville@tuxdriver.com>
Date: Wed, 19 Dec 2012 13:32:20 -0500

> Please pull these fixes for the 3.8 stream.
> 
> Gabor Juhos provides and rt2x00 fix to properly clear-out the skb->cb
> for reporting tx_status.  Recent changes made this necessary where it
> previously was not.
> 
> Vladimir Kondratiev gives us a fix for a build issue that caused some
> ath9k devices to be skipped in the build based on unrelated config
> choices.

Pulled, thanks John.

^ permalink raw reply

* Re: [PATCH V2 00/12] Add basic VLAN support to bridges
From: Vlad Yasevich @ 2012-12-19 20:03 UTC (permalink / raw)
  To: Shmulik Ladkani; +Cc: netdev, shemminger, davem, or.gerlitz, jhs, mst
In-Reply-To: <20121219213716.778d6449.shmulik.ladkani@gmail.com>

On 12/19/2012 02:37 PM, Shmulik Ladkani wrote:
> Hi Vlad,
>
> On Wed, 19 Dec 2012 09:13:10 -0500 Vlad Yasevich <vyasevic@redhat.com> wrote:
>>> Why the "untagged vlan" is per-bridge global?
>> It's not.  There is a per port untagged pointer where you can designate
>> which VLAN is untagged/native on a port.
>
> Ok (misinterpreted the text in the cover letter).
>
>>> 802.1q switches usually allow conifguring per-vlan, per-port
>>> tagged/untagged egress policy: each vid has its port membership map and
>>> an accompanying port egress-policy map.
>>> This gives great flexibility defining all sorts of configurations.
>>
>> Right, and that's what's provided here.
>>    * Each VLAN has port membership map (net_bridge_vlan.portgroup).
>>    * Each port has a list of vlans configured as well
>> (net_port_vlan.vlan_list).
>>    * Each port also has a single vlan that can be untagged
>> (net_bridge_port.untagged).
>>    * The bridge also has a single untagged vlan (net_bridge.untagged)
>>
>> The limitation (in switches as well) is that only a single VLAN
>> may be untagged on any 1 port.
>
> Switches usually allow you to configure each port's egress policy per
> vlan, and allow you to configure multiple vlans to _egress_ untagged
> on a port.
>
>> If you have more then 1, you don't know
>> which VLAN the untagged traffic belongs to.
>
> The port's PVID uniquely determines VID to associate with the frame
> during _ingress_ on that port - in the case frame arrived untagged.
>
> This is unrelated to whether a frame having a specific VID would _egress_
> tagged or untagged on that port.
>


Ahh...  I see what you mean.  You would like to separate
ingress policy and egress policy with regard to how tags are applied...
I haven't seen that type of config before.

I did say "Basic VLAN support". :)

In this set of patches ingress and egress policies are hardcoded the same...

So, consider that what I am calling "untagged" in this series is
really vlan associated with PVID.  To change the egress policy, we
could add an untagged bitmap into the vlan.  Then the bitmap from the 
vlan would determine the egress policy.  If the port is in the "tagged"
bitmap, frame leaves tagged. If the port is in the "untagged" bitmap,
frame leaves untagged.

The code to make this would would be simple enough.  The more 
interesting part would be the configuration :)


>>> Personally, I'd prefer a fully flexible vlan bridge allowing all sorts
>>> of configurations (as available in 802.1q switches).
>>>
>>> What's the reason limiting such configurations?
>>
>> So, what do you see that's missing?
>

[ snip good example ]

>
> The bridge constructs needed for supporting such setups are:
> - per port: PVID
> - per VLAN: port membership map
> - per VLAN: port egress policy map

Ok, so from above, membership map is the exiting port_bitmap.  Egress
policy map could be new untagged_bitmap.  We wouldn't need a tagged 
policy map since a port can't be "in egress policy, but not in 
membership map".

Membership port_bitmap is consulted on egress for basic forward/drop 
decision (just as it is now).  Egress policy (untagged bitmap) is 
consulted to see how the forwarding is done.

Sounds about right?  If so, I could probably work something up.
Will probably leave the configuration for later as that might take a bit
longer to figure out.

-vlad

>
> I agree, tools other than a vlan bridge may implement such setups, but
> using the vlan bridge would be preferred, mainly due to the simplicity.
>
> Regards,
> Shmulik
>

^ permalink raw reply

* [PATCH] 8139cp: Prevent dev_close/cp_interrupt race on MTU change
From: John Greene @ 2012-12-19 19:47 UTC (permalink / raw)
  To: netdev; +Cc: John Greene, David S. Miller, David Woodhouse

commit:  cb64edb6b89491edfdbae52ba7db9a8b8391d339 upstream

Above commit may introduce a race between cp_interrupt and dev_close
/ change MTU / dev_open up state. Changes cp_interrupt to tolerate
this.  Change spin_locking in cp_interrupt to avoid possible
but unobserved race.

Reported-by: "Francois Romieu" <romieu@fr.zoreil.com>

Tested on virtual hardware, Tx MTU size up to 4096, max tx payload
    was ping -s 4068 for MTU of 4096. No real hardware, need test
    assist.

Signed-off-by: "John Greene" <jogreene@redhat.com>
CC: "David S. Miller" <davem@davemloft.net>
CC: "David Woodhouse" <David.Woodhouse@intel.com>
---
 drivers/net/ethernet/realtek/8139cp.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index 0da3f5e..585c35c 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -577,28 +577,30 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
 {
 	struct net_device *dev = dev_instance;
 	struct cp_private *cp;
+	int handled = 0;
 	u16 status;
 
 	if (unlikely(dev == NULL))
 		return IRQ_NONE;
 	cp = netdev_priv(dev);
 
+	spin_lock(&cp->lock);
+
 	status = cpr16(IntrStatus);
 	if (!status || (status == 0xFFFF))
-		return IRQ_NONE;
+		goto out_unlock;
+
+	handled = 1;
 
 	netif_dbg(cp, intr, dev, "intr, status %04x cmd %02x cpcmd %04x\n",
 		  status, cpr8(Cmd), cpr16(CpCmd));
 
 	cpw16(IntrStatus, status & ~cp_rx_intr_mask);
 
-	spin_lock(&cp->lock);
-
 	/* close possible race's with dev_close */
 	if (unlikely(!netif_running(dev))) {
 		cpw16(IntrMask, 0);
-		spin_unlock(&cp->lock);
-		return IRQ_HANDLED;
+		goto out_unlock;
 	}
 
 	if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr))
@@ -612,7 +614,6 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
 	if (status & LinkChg)
 		mii_check_media(&cp->mii_if, netif_msg_link(cp), false);
 
-	spin_unlock(&cp->lock);
 
 	if (status & PciErr) {
 		u16 pci_status;
@@ -625,7 +626,10 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
 		/* TODO: reset hardware */
 	}
 
-	return IRQ_HANDLED;
+out_unlock:
+	spin_unlock(&cp->lock);
+
+	return IRQ_RETVAL(handled);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-- 
1.7.11.7

^ permalink raw reply related

* Re: [PATCH V2 00/12] Add basic VLAN support to bridges
From: Shmulik Ladkani @ 2012-12-19 19:37 UTC (permalink / raw)
  To: vyasevic; +Cc: netdev, shemminger, davem, or.gerlitz, jhs, mst
In-Reply-To: <50D1CB76.50202@redhat.com>

Hi Vlad,

On Wed, 19 Dec 2012 09:13:10 -0500 Vlad Yasevich <vyasevic@redhat.com> wrote:
> > Why the "untagged vlan" is per-bridge global?
> It's not.  There is a per port untagged pointer where you can designate 
> which VLAN is untagged/native on a port.

Ok (misinterpreted the text in the cover letter).

> > 802.1q switches usually allow conifguring per-vlan, per-port
> > tagged/untagged egress policy: each vid has its port membership map and
> > an accompanying port egress-policy map.
> > This gives great flexibility defining all sorts of configurations.
> 
> Right, and that's what's provided here.
>   * Each VLAN has port membership map (net_bridge_vlan.portgroup).
>   * Each port has a list of vlans configured as well 
> (net_port_vlan.vlan_list).
>   * Each port also has a single vlan that can be untagged 
> (net_bridge_port.untagged).
>   * The bridge also has a single untagged vlan (net_bridge.untagged)
> 
> The limitation (in switches as well) is that only a single VLAN
> may be untagged on any 1 port. 

Switches usually allow you to configure each port's egress policy per
vlan, and allow you to configure multiple vlans to _egress_ untagged
on a port.

> If you have more then 1, you don't know
> which VLAN the untagged traffic belongs to.

The port's PVID uniquely determines VID to associate with the frame
during _ingress_ on that port - in the case frame arrived untagged.

This is unrelated to whether a frame having a specific VID would _egress_
tagged or untagged on that port.

> > Personally, I'd prefer a fully flexible vlan bridge allowing all sorts
> > of configurations (as available in 802.1q switches).
> >
> > What's the reason limiting such configurations?
> 
> So, what do you see that's missing?

I suspect some configurations wouldn't be possible at current design,
please let me know what do you think.

Take for example such a configuration:

 +---+---+
 |   |   |
p1  p2   p3

A bridge with 3 ports: p1 p2 p3.
(the bridge interface itself is irrelevant for this discussion)
	
This setup expects all traffic at those ports to be untagged.

I'd like p1 to be bridged to p2, but not to p3.

I'd like p3 to be bridged to p2, but not to p1.

Set the following:

p1 - PVID is 1
    member of VLANs 1(egress untagged), 2(egress untagged)

p3 - PVID is 3
    member of VLANs 3(egress untagged), 2(egress untagged)

p2 - PVID is 2
    member of VLANs 1,2,3 (all egress untagged)

Or putting it differently:

VLAN 1 ports membership: p1, p2
       egress policy:    U   U

VLAN 2 ports membership: p1, p2, p3
       egress policy:    U   U   U

VLAN 3 ports membership:     p2, p3
       egress policy:        U   U

Now, untagged traffic arriving at p1 will be assigned its PVID, which
is 1, an thus forced to egress via p2 (the only other member of VLAN 1).
Upon egress on p2, it will egress untagged.

(similarly for ingress in p3, only egress at p2 is possible, again
 untagged).

If untagged traffic arrives at p2, it will be assigned its PVID, which
is 2, and thus it may egress on either p1 or p3 (they are both members
of VLAN 2).
Actual port of egress is according to FDB match.
Again egress would be untagged.

This setup might sound exotic, but similar patterns may be used in
reality.
Although the example is synthetic and simplistic, still it demonstrates
the vast flexibility allowed by a 802.1q bridge.

The bridge constructs needed for supporting such setups are:
- per port: PVID
- per VLAN: port membership map
- per VLAN: port egress policy map

I agree, tools other than a vlan bridge may implement such setups, but
using the vlan bridge would be preferred, mainly due to the simplicity.

Regards,
Shmulik

^ permalink raw reply

* Re: PMTU discovery is broken on kernel 3.7.1 for UDP sockets
From: Ben Hutchings @ 2012-12-19 19:37 UTC (permalink / raw)
  To: Yurij M. Plotnikov; +Cc: netdev, Alexandra N. Kossovsky
In-Reply-To: <50D1CECE.7090706@oktetlabs.ru>

On Wed, 2012-12-19 at 18:27 +0400, Yurij M. Plotnikov wrote:
> On 12/19/12 17:35, Ben Hutchings wrote:
> > On Wed, 2012-12-19 at 17:10 +0400, Yurij M. Plotnikov wrote:
> >    
> >> On kernel 3.7.1 I get strange behaviour of IP_MTU_DISCOVER socket
> >> option. The behaviour in case of IP_PMTUDISC_DO and IP_PMTUDISC_WANT
> >> values of IP_MTU_DISCOVER socket option on SOCK_DGRAM socket are the
> >> same and packet is always sent with "Don't Fragment" bit in case of
> >> IP_PMTUDISC_WANT. Also, the value of IP_MTU socket option is not updated.
> >>      
> > You could try reverting:
> >
> > commit ee9a8f7ab2edf801b8b514c310455c94acc232f6
> > Author: Steffen Klassert<steffen.klassert@secunet.com>
> > Date:   Mon Oct 8 00:56:54 2012 +0000
> >
> >      ipv4: Don't report stale pmtu values to userspace
> >
> >      We report cached pmtu values even if they are already expired.
> >      Change this to not report these values after they are expired
> >      and fix a race in the expire time calculation, as suggested by
> >      Eric Dumazet.
> >
> > Still, PMTU information is not supposed to expire for 10 minutes...
> >
> >    
> With reverted commit there is no such problem on 3.7.1: IP_MTU is 
> updated and DF is set only for the first packet in case of 
> IP_PMTUDISC_WANT.
[...]

So it looks like something is going wrong with the expiry calculation
here.

This change shouldn't affect the PMTU actually used by the kernel, but
could affect Onload since that relies on netlink route updates to keep
in synch.  You didn't say you were using Onload, but if you are then we
should not bother netdev with this until we can demonstrate a problem
that involves only the kernel stack.

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* [PATCH v2] bridge:  Do not unregister all PF_BRIDGE rtnl operations
From: Vlad Yasevich @ 2012-12-19 19:13 UTC (permalink / raw)
  To: netdev; +Cc: davem, shemminger

Bridge fdb and link rtnl operations are registered in
core/rtnetlink.  Bridge mdb operations are registred
in bridge/mdb.  When removing bridge module, do not
unregister ALL PF_BRIDGE ops since that would remove
the ops from rtnetlink as well.  Do remove mdb ops when
bridge is destroyed.

Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
---
 net/bridge/br_mdb.c       |    7 +++++++
 net/bridge/br_multicast.c |    1 +
 net/bridge/br_netlink.c   |    1 -
 net/bridge/br_private.h   |    1 +
 4 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
index 9cf5d2b..3e05cc3 100644
--- a/net/bridge/br_mdb.c
+++ b/net/bridge/br_mdb.c
@@ -482,3 +482,10 @@ void br_mdb_init(void)
 	rtnl_register(PF_BRIDGE, RTM_NEWMDB, br_mdb_add, NULL, NULL);
 	rtnl_register(PF_BRIDGE, RTM_DELMDB, br_mdb_del, NULL, NULL);
 }
+
+void br_mdb_uninit(void)
+{
+	rtnl_unregister(PF_BRIDGE, RTM_GETMDB);
+	rtnl_unregister(PF_BRIDGE, RTM_NEWMDB);
+	rtnl_unregister(PF_BRIDGE, RTM_DELMDB);
+}
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index dce9def..5391ca4 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1633,6 +1633,7 @@ void br_multicast_stop(struct net_bridge *br)
 	del_timer_sync(&br->multicast_querier_timer);
 	del_timer_sync(&br->multicast_query_timer);
 
+	br_mdb_uninit();
 	spin_lock_bh(&br->multicast_lock);
 	mdb = mlock_dereference(br->mdb, br);
 	if (!mdb)
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index dead9df..97ba018 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -305,5 +305,4 @@ int __init br_netlink_init(void)
 void __exit br_netlink_fini(void)
 {
 	rtnl_link_unregister(&br_link_ops);
-	rtnl_unregister_all(PF_BRIDGE);
 }
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 49b85af4..8d83be5 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -447,6 +447,7 @@ extern struct net_bridge_port_group *br_multicast_new_port_group(
 				struct net_bridge_port_group *next,
 				unsigned char state);
 extern void br_mdb_init(void);
+extern void br_mdb_uninit(void);
 extern void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
 			  struct br_ip *group, int type);
 
-- 
1.7.7.6

^ permalink raw reply related

* Re: TCP delayed ACK heuristic
From: Rick Jones @ 2012-12-19 18:39 UTC (permalink / raw)
  To: Cong Wang
  Cc: David Laight, netdev, Ben Greear, David Miller, Eric Dumazet,
	Stephen Hemminger, Thomas Graf
In-Reply-To: <1355900436.6665.16.camel@cr0>

On 12/18/2012 11:00 PM, Cong Wang wrote:
> On Tue, 2012-12-18 at 16:39 +0000, David Laight wrote:
>> There are problems with only implementing the acks
>> specified by RFC1122.
>
> Yeah, the problem is if we can violate this RFC for getting better
> performance. Or it is just a no-no?
>
> Although RFC 2525 mentions this as "Stretch ACK Violation", I am still
> not sure if that means we can violate RFC1122 legally.

The term used in RFC1122 is "SHOULD" not "MUST."  Same for RFC2525 when 
it talks about "Stretch ACK Violation."   A TCP stack may have behaviour 
which differs from a SHOULD so long as there is a reasonable reason for it.

rick jones

^ permalink raw reply

* pull request: wireless 2012-12-19
From: John W. Linville @ 2012-12-19 18:32 UTC (permalink / raw)
  To: davem; +Cc: linux-wireless, netdev, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2690 bytes --]

Dave,

Please pull these fixes for the 3.8 stream.

Gabor Juhos provides and rt2x00 fix to properly clear-out the skb->cb
for reporting tx_status.  Recent changes made this necessary where it
previously was not.

Vladimir Kondratiev gives us a fix for a build issue that caused some
ath9k devices to be skipped in the build based on unrelated config
choices.

Please let me know if there are problems!

Thanks,

John

---

The following changes since commit c1e37ea287979052e3eab441e58da3899a8e2389:

  net: fec: forbid FEC_PTP on SoCs that do not support (2012-12-18 16:26:18 -0800)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git for-davem

for you to fetch changes up to d67df2b9edfc42ccc0a9ee5332e2821d487d6b3b:

  Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless into for-davem (2012-12-19 13:00:00 -0500)

----------------------------------------------------------------

Gabor Juhos (1):
      rt2x00: zero-out rx_status

John W. Linville (1):
      Merge branch 'master' of git://git.kernel.org/.../linville/wireless into for-davem

Vladimir Kondratiev (1):
      wireless: fix Atheros drivers compilation

 drivers/net/wireless/Makefile           | 2 +-
 drivers/net/wireless/rt2x00/rt2x00dev.c | 8 ++++++++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 062dfdf..67156ef 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -47,7 +47,7 @@ obj-$(CONFIG_RT2X00)	+= rt2x00/
 
 obj-$(CONFIG_P54_COMMON)	+= p54/
 
-obj-$(CONFIG_ATH_COMMON)	+= ath/
+obj-$(CONFIG_ATH_CARDS)		+= ath/
 
 obj-$(CONFIG_MAC80211_HWSIM)	+= mac80211_hwsim.o
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 4ffb6a5..44f8b3f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -685,6 +685,14 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp)
 	 * to mac80211.
 	 */
 	rx_status = IEEE80211_SKB_RXCB(entry->skb);
+
+	/* Ensure that all fields of rx_status are initialized
+	 * properly. The skb->cb array was used for driver
+	 * specific informations, so rx_status might contain
+	 * garbage.
+	 */
+	memset(rx_status, 0, sizeof(*rx_status));
+
 	rx_status->mactime = rxdesc.timestamp;
 	rx_status->band = rt2x00dev->curr_band;
 	rx_status->freq = rt2x00dev->curr_freq;
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply related

* [PATCH net-next V4 01/13] vlan: wrap hw-acceleration calls in separate functions.
From: Vlad Yasevich @ 2012-12-19 17:48 UTC (permalink / raw)
  To: netdev; +Cc: shemminger, davem, or.gerlitz, jhs, mst, erdnetdev, jiri
In-Reply-To: <1355939304-21804-1-git-send-email-vyasevic@redhat.com>

Wrap VLAN hardware acceleration calls into separate functions.  This way
other code can re-use it.

Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
---
 include/linux/if_vlan.h |   57 +++++++++++++++++++++++++++++++++++++++++++++++
 net/8021q/vlan.c        |    4 +--
 net/8021q/vlan_core.c   |   24 ++++++-------------
 3 files changed, 66 insertions(+), 19 deletions(-)

diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index d06cc5c..e1deb91 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -158,6 +158,63 @@ static inline bool vlan_uses_dev(const struct net_device *dev)
 #endif
 
 /**
+ * vlan_hw_buggy - Check to see if VLAN hw acceleration is supported.
+ * @dev: netdevice of the lowerdev/hw nic
+ *
+ * Checks to see if HW and driver report VLAN acceleration correctly.
+ */
+static inline bool vlan_hw_buggy(const struct net_device *dev)
+{
+	const struct net_device_ops *ops = dev->netdev_ops;
+
+	if ((dev->features & NETIF_F_HW_VLAN_FILTER) &&
+	    (!ops->ndo_vlan_rx_add_vid || !ops->ndo_vlan_rx_kill_vid))
+		return true;
+
+	return false;
+}
+
+/**
+ * vlan_vid_add_hw - Add the VLAN vid to the HW filter
+ * @dev: netdevice of the lowerdev/hw nic
+ * @vid: vlan id.
+ *
+ * Inserts the vid into the HW vlan filter table if hw supports it.
+ */
+static inline int vlan_vid_add_hw(struct net_device *dev,
+				  unsigned short vid)
+{
+	const struct net_device_ops *ops = dev->netdev_ops;
+	int err = 0;
+
+	if ((dev->features & NETIF_F_HW_VLAN_FILTER) &&
+	    ops->ndo_vlan_rx_add_vid)
+		err = ops->ndo_vlan_rx_add_vid(dev, vid);
+
+	return err;
+}
+
+/**
+ * vlan_vid_del_hw - Delete the VLAN vid from the HW filter
+ * @dev: netdevice of the lowerdev/hw nic
+ * @vid: vlan id.
+ *
+ * Delete the vid from the HW vlan filter table if hw supports it.
+ */
+static inline int vlan_vid_del_hw(struct net_device *dev,
+				  unsigned short vid)
+{
+	const struct net_device_ops *ops = dev->netdev_ops;
+	int err = 0;
+
+	if ((dev->features & NETIF_F_HW_VLAN_FILTER) &&
+	    ops->ndo_vlan_rx_kill_vid)
+		err = ops->ndo_vlan_rx_add_vid(dev, vid);
+
+	return err;
+}
+
+/**
  * vlan_insert_tag - regular VLAN tag inserting
  * @skb: skbuff to tag
  * @vlan_tci: VLAN TCI to insert
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index a292e80..d1ac63f 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -115,15 +115,13 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
 int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id)
 {
 	const char *name = real_dev->name;
-	const struct net_device_ops *ops = real_dev->netdev_ops;
 
 	if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
 		pr_info("VLANs not supported on %s\n", name);
 		return -EOPNOTSUPP;
 	}
 
-	if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&
-	    (!ops->ndo_vlan_rx_add_vid || !ops->ndo_vlan_rx_kill_vid)) {
+	if (vlan_hw_buggy(real_dev)) {
 		pr_info("Device %s has buggy VLAN hw accel\n", name);
 		return -EOPNOTSUPP;
 	}
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index 65e06ab..4ca82aa 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -212,7 +212,6 @@ static int __vlan_vid_add(struct vlan_info *vlan_info, unsigned short vid,
 			  struct vlan_vid_info **pvid_info)
 {
 	struct net_device *dev = vlan_info->real_dev;
-	const struct net_device_ops *ops = dev->netdev_ops;
 	struct vlan_vid_info *vid_info;
 	int err;
 
@@ -220,13 +219,10 @@ static int __vlan_vid_add(struct vlan_info *vlan_info, unsigned short vid,
 	if (!vid_info)
 		return -ENOMEM;
 
-	if ((dev->features & NETIF_F_HW_VLAN_FILTER) &&
-	    ops->ndo_vlan_rx_add_vid) {
-		err =  ops->ndo_vlan_rx_add_vid(dev, vid);
-		if (err) {
-			kfree(vid_info);
-			return err;
-		}
+	err = vlan_vid_add_hw(dev, vid);
+	if (err) {
+		kfree(vid_info);
+		return err;
 	}
 	list_add(&vid_info->list, &vlan_info->vid_list);
 	vlan_info->nr_vids++;
@@ -274,17 +270,13 @@ static void __vlan_vid_del(struct vlan_info *vlan_info,
 			   struct vlan_vid_info *vid_info)
 {
 	struct net_device *dev = vlan_info->real_dev;
-	const struct net_device_ops *ops = dev->netdev_ops;
 	unsigned short vid = vid_info->vid;
 	int err;
 
-	if ((dev->features & NETIF_F_HW_VLAN_FILTER) &&
-	     ops->ndo_vlan_rx_kill_vid) {
-		err = ops->ndo_vlan_rx_kill_vid(dev, vid);
-		if (err) {
-			pr_warn("failed to kill vid %d for device %s\n",
-				vid, dev->name);
-		}
+	err = vlan_vid_del_hw(dev, vid);
+	if (err) {
+		pr_warn("failed to kill vid %d for device %s\n",
+			vid, dev->name);
 	}
 	list_del(&vid_info->list);
 	kfree(vid_info);
-- 
1.7.7.6

^ permalink raw reply related

* [PATCH net-next V4 10/13] bridge: Add the ability to configure untagged vlans
From: Vlad Yasevich @ 2012-12-19 17:48 UTC (permalink / raw)
  To: netdev; +Cc: shemminger, davem, or.gerlitz, jhs, mst, erdnetdev, jiri
In-Reply-To: <1355939304-21804-1-git-send-email-vyasevic@redhat.com>

A user may designate a certain vlan as untagged.  This means that
any ingress frame is assigned to this vlan and any forwarding decisions
are made with this vlan in mind.  On egress, any frames tagged/labeled
with untagged vlan have the vlan tag removed and are send as regular
ethernet frames.

Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
---
 include/uapi/linux/if_bridge.h |    3 +
 net/bridge/br_if.c             |  139 ++++++++++++++++++++++++++++++++++++---
 net/bridge/br_netlink.c        |    6 +-
 net/bridge/br_private.h        |    2 +
 4 files changed, 137 insertions(+), 13 deletions(-)

diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h
index d0b4f5c..988d858 100644
--- a/include/uapi/linux/if_bridge.h
+++ b/include/uapi/linux/if_bridge.h
@@ -127,6 +127,9 @@ enum {
 	BR_VLAN_DEL,
 };
 
+#define BRIDGE_VLAN_INFO_MASTER		1
+#define BRIDGE_VLAN_INFO_UNTAGGED	2
+
 struct bridge_vlan_info {
 	u16 op_code;
 	u16 flags;
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 33bc740..c9f2c06 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -107,6 +107,36 @@ static void br_vlan_put(struct net_bridge_vlan *vlan)
 		br_vlan_destroy(vlan);
 }
 
+/* Must be protected by RTNL */
+static void br_vlan_add_untagged(struct net_bridge *br,
+				 struct net_bridge_vlan *vlan)
+{
+	struct net_bridge_vlan *untagged = rtnl_dereference(br->untagged);
+
+	if (untagged == vlan)
+		return;
+	else if (untagged) {
+		/* Untagged vlan is already set on the master,
+		 * so drop the ref since we'll be replacing it.
+		 */
+		br_vlan_put(untagged);
+	}
+	br_vlan_hold(vlan);
+	rcu_assign_pointer(br->untagged, vlan);
+}
+
+/* Must be protected by RTNL */
+static void br_vlan_del_untagged(struct net_bridge *br,
+				 struct net_bridge_vlan *vlan)
+{
+	struct net_bridge_vlan *untagged = rtnl_dereference(br->untagged);
+
+	if (untagged == vlan) {
+		br_vlan_put(vlan);
+		rcu_assign_pointer(br->untagged, NULL);
+	}
+}
+
 struct net_bridge_vlan *br_vlan_find(struct net_bridge *br, u16 vid)
 {
 	struct net_bridge_vlan *vlan;
@@ -131,7 +161,7 @@ struct net_bridge_vlan *br_vlan_add(struct net_bridge *br, u16 vid,
 
 	vlan = br_vlan_find(br, vid);
 	if (vlan)
-		return vlan;
+		goto untagged;
 
 	vlan = kzalloc(sizeof(struct net_bridge_vlan), GFP_KERNEL);
 	if (!vlan)
@@ -140,7 +170,7 @@ struct net_bridge_vlan *br_vlan_add(struct net_bridge *br, u16 vid,
 	vlan->vid = vid;
 	atomic_set(&vlan->refcnt, 1);
 
-	if (flags & BRIDGE_FLAGS_SELF) {
+	if (flags & BRIDGE_VLAN_INFO_MASTER) {
 		/* Set bit 0 that is associated with the bridge master
 		 * device.  Port numbers start with 1.
 		 */
@@ -148,15 +178,24 @@ struct net_bridge_vlan *br_vlan_add(struct net_bridge *br, u16 vid,
 	}
 
 	hlist_add_head_rcu(&vlan->hlist, &br->vlan_hlist[br_vlan_hash(vid)]);
+
+untagged:
+	if (flags & BRIDGE_VLAN_INFO_UNTAGGED)
+		br_vlan_add_untagged(br, vlan);
+
 	return vlan;
 }
 
 /* Must be protected by RTNL */
-static void br_vlan_del(struct net_bridge_vlan *vlan, u16 flags)
+static void br_vlan_del(struct net_bridge *br, struct net_bridge_vlan *vlan,
+			u16 flags)
 {
 	ASSERT_RTNL();
 
-	if (flags & BRIDGE_FLAGS_SELF) {
+	if (flags & BRIDGE_VLAN_INFO_UNTAGGED)
+		br_vlan_del_untagged(br, vlan);
+
+	if (flags & BRIDGE_VLAN_INFO_MASTER) {
 		/* Clear bit 0 that is associated with the bridge master
 		 * device.
 		 */
@@ -171,6 +210,14 @@ static void br_vlan_del(struct net_bridge_vlan *vlan, u16 flags)
 
 	vlan->vid = BR_INVALID_VID;
 
+	/* If, for whatever reason, bridge still has a ref on this vlan
+	 * through the @untagged pointer, drop that ref and clear untagged.
+	 */
+	if (rtnl_dereference(br->untagged) == vlan) {
+		br_vlan_put(vlan);
+		rcu_assign_pointer(br->untagged, NULL);
+	}
+
 	/* Drop the self-ref to trigger descrution. */
 	br_vlan_put(vlan);
 }
@@ -186,7 +233,7 @@ int br_vlan_delete(struct net_bridge *br, u16 vid, u16 flags)
 	if (!vlan)
 		return -ENOENT;
 
-	br_vlan_del(vlan, flags);
+	br_vlan_del(br, vlan, flags);
 	return 0;
 }
 
@@ -203,7 +250,9 @@ static void br_vlan_flush(struct net_bridge *br)
 	for (i = 0; i < BR_VID_HASH_SIZE; i++) {
 		hlist_for_each_entry_safe(vlan, node, tmp,
 					  &br->vlan_hlist[i], hlist) {
-			br_vlan_del(vlan, BRIDGE_FLAGS_SELF);
+			br_vlan_del(br, vlan,
+				    (BRIDGE_VLAN_INFO_MASTER |
+				     BRIDGE_VLAN_INFO_UNTAGGED));
 		}
 	}
 }
@@ -223,10 +272,62 @@ struct net_port_vlan *nbp_vlan_find(const struct net_bridge_port *p, u16 vid)
 	return NULL;
 }
 
+static int nbp_vlan_add_untagged(struct net_bridge_port *p,
+			  struct net_bridge_vlan *vlan,
+			  u16 flags)
+{
+	struct net_device *dev = p->dev;
+	struct net_bridge_vlan *untagged = rtnl_dereference(p->untagged);
+
+	if (untagged) {
+		/* Port already has untagged vlan set.  Drop the ref
+		 * to the old one since we'll be replace it.
+		 */
+		br_vlan_put(untagged);
+	} else {
+		if (!vlan_hw_buggy(dev)) {
+			int err = vlan_vid_add_hw(dev, 0);
+			if (err)
+				return err;
+		}
+	}
+
+	/* This VLAN is handled as untagged/native. Save an
+	 * additional ref.
+	 */
+	br_vlan_hold(vlan);
+	rcu_assign_pointer(p->untagged, vlan);
+
+	return 0;
+}
+
+static void nbp_vlan_delete_untagged(struct net_bridge_port *p,
+				     struct net_bridge_vlan *vlan)
+{
+	struct net_bridge_vlan *untagged = rtnl_dereference(p->untagged);
+
+	if (untagged != vlan)
+		return;
+
+	/* Remove VLAN from the device filter if it is supported. */
+	if (vlan_vid_del_hw(p->dev, 0)) {
+		pr_warn("failed to kill vid %d for device %s\n",
+			vlan->vid, p->dev->name);
+	}
+
+	/* If this VLAN is currently functioning as untagged, clear it.
+	 * It's safe to drop the refcount, since the vlan is still held
+	 * by the port.
+	 */
+	br_vlan_put(vlan);
+	rcu_assign_pointer(p->untagged, NULL);
+
+}
+
 /* Must be protected by RTNL */
 int nbp_vlan_add(struct net_bridge_port *p, u16 vid, u16 flags)
 {
-	struct net_port_vlan *pve;
+	struct net_port_vlan *pve = NULL;
 	struct net_bridge_vlan *vlan;
 	struct net_device *dev = p->dev;
 	int err;
@@ -272,11 +373,21 @@ int nbp_vlan_add(struct net_bridge_port *p, u16 vid, u16 flags)
 	set_bit(p->port_no, vlan->port_bitmap);
 
 	list_add_tail_rcu(&pve->list, &p->vlan_list);
+
+	if (flags & BRIDGE_VLAN_INFO_UNTAGGED) {
+		err = nbp_vlan_add_untagged(p, vlan, flags);
+		if (err)
+			goto del_vlan;
+	}
+
 	return 0;
 
 clean_up:
 	kfree(pve);
-	br_vlan_del(vlan, flags);
+	br_vlan_del(p->br, vlan, flags);
+	return err;
+del_vlan:
+	nbp_vlan_delete(p, vid, flags);
 	return err;
 }
 
@@ -293,6 +404,9 @@ int nbp_vlan_delete(struct net_bridge_port *p, u16 vid, u16 flags)
 	if (!pve)
 		return -ENOENT;
 
+	if (flags & BRIDGE_VLAN_INFO_UNTAGGED)
+		nbp_vlan_delete_untagged(p, pve->vlan);
+
 	/* Remove VLAN from the device filter if it is supported. */
 	if (vlan_vid_del_hw(dev, vid))
 		pr_warn("failed to kill vid %d for device %s\n",
@@ -308,7 +422,7 @@ int nbp_vlan_delete(struct net_bridge_port *p, u16 vid, u16 flags)
 	list_del_rcu(&pve->list);
 	kfree_rcu(pve, rcu);
 
-	br_vlan_del(vlan, flags);
+	br_vlan_del(p->br, vlan, flags);
 
 	return 0;
 }
@@ -320,8 +434,11 @@ static void nbp_vlan_flush(struct net_bridge_port *p)
 
 	ASSERT_RTNL();
 
-	list_for_each_entry_safe(pve, tmp, &p->vlan_list, list)
-		nbp_vlan_delete(p, pve->vid, BRIDGE_FLAGS_SELF);
+	list_for_each_entry_safe(pve, tmp, &p->vlan_list, list)  {
+		nbp_vlan_delete(p, pve->vid,
+				(BRIDGE_VLAN_INFO_MASTER |
+				 BRIDGE_VLAN_INFO_UNTAGGED));
+	}
 }
 
 static void release_nbp(struct kobject *kobj)
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 84c6f04..fc6ba39 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -197,7 +197,8 @@ static int br_afspec(struct net_bridge *br, struct net_bridge_port *p,
 			if (p)
 				err = nbp_vlan_add(p, vinfo->vid, vinfo->flags);
 			else {
-				u16 flags = vinfo->flags | BRIDGE_FLAGS_SELF;
+				u16 flags = vinfo->flags |
+					    BRIDGE_VLAN_INFO_MASTER;
 				if (!br_vlan_add(br, vinfo->vid, flags))
 					err = -ENOMEM;
 			}
@@ -208,7 +209,8 @@ static int br_afspec(struct net_bridge *br, struct net_bridge_port *p,
 				err = nbp_vlan_delete(p, vinfo->vid,
 						      vinfo->flags);
 			else {
-				u16 flags = vinfo->flags | BRIDGE_FLAGS_SELF;
+				u16 flags = vinfo->flags |
+					    BRIDGE_VLAN_INFO_MASTER;
 				err = br_vlan_delete(br, vinfo->vid, flags);
 			}
 			break;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index cc75212..9328463 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -179,6 +179,7 @@ struct net_bridge_port
 	struct netpoll			*np;
 #endif
 	struct list_head		vlan_list;
+	struct net_bridge_vlan __rcu	*untagged;
 };
 
 #define br_port_exists(dev) (dev->priv_flags & IFF_BRIDGE_PORT)
@@ -298,6 +299,7 @@ struct net_bridge
 	struct timer_list		gc_timer;
 	struct kobject			*ifobj;
 	struct hlist_head		vlan_hlist[BR_VID_HASH_SIZE];
+	struct net_bridge_vlan __rcu	*untagged;
 };
 
 struct br_input_skb_cb {
-- 
1.7.7.6

^ permalink raw reply related

* [PATCH net-next V4 08/13] bridge: Add netlink interface to configure vlans on bridge ports
From: Vlad Yasevich @ 2012-12-19 17:48 UTC (permalink / raw)
  To: netdev; +Cc: shemminger, davem, or.gerlitz, jhs, mst, erdnetdev, jiri
In-Reply-To: <1355939304-21804-1-git-send-email-vyasevic@redhat.com>

Add a netlink interface to add and remove vlan configuration on bridge port.
The interface uses the RTM_SETLINK message and encodes the vlan
configuration inside the IFLA_AF_SPEC.  It is possble to include multiple
vlans to either add or remove in a single message.

Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
---
 include/uapi/linux/if_bridge.h |   17 ++++++
 net/bridge/br_if.c             |    1 +
 net/bridge/br_netlink.c        |  107 +++++++++++++++++++++++++++++++++-------
 3 files changed, 107 insertions(+), 18 deletions(-)

diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h
index 52aa738..d0b4f5c 100644
--- a/include/uapi/linux/if_bridge.h
+++ b/include/uapi/linux/if_bridge.h
@@ -108,15 +108,32 @@ struct __fdb_entry {
  * [IFLA_AF_SPEC] = {
  *     [IFLA_BRIDGE_FLAGS]
  *     [IFLA_BRIDGE_MODE]
+ *     [IFLA_BRIDGE_VLAN_INFO]
  * }
  */
 enum {
 	IFLA_BRIDGE_FLAGS,
 	IFLA_BRIDGE_MODE,
+	IFLA_BRIDGE_VLAN_INFO,
 	__IFLA_BRIDGE_MAX,
 };
 #define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1)
 
+/* Bridge VLAN info
+ * [IFLA_BRIDGE_VLAN_INFO]
+ */
+enum {
+	BR_VLAN_ADD,
+	BR_VLAN_DEL,
+};
+
+struct bridge_vlan_info {
+	u16 op_code;
+	u16 flags;
+	u16 vid;
+	u16 unused;
+};
+
 /* Bridge multicast database attributes
  * [MDBA_MDB] = {
  *     [MDBA_MDB_ENTRY] = {
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index c30fe29..33bc740 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -23,6 +23,7 @@
 #include <linux/if_ether.h>
 #include <linux/slab.h>
 #include <net/sock.h>
+#include <linux/if_vlan.h>
 
 #include "br_private.h"
 
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index dead9df..84c6f04 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -16,6 +16,7 @@
 #include <net/rtnetlink.h>
 #include <net/net_namespace.h>
 #include <net/sock.h>
+#include <uapi/linux/if_bridge.h>
 
 #include "br_private.h"
 #include "br_private_stp.h"
@@ -119,10 +120,14 @@ nla_put_failure:
  */
 void br_ifinfo_notify(int event, struct net_bridge_port *port)
 {
-	struct net *net = dev_net(port->dev);
+	struct net *net;
 	struct sk_buff *skb;
 	int err = -ENOBUFS;
 
+	if (!port)
+		return;
+
+	net = dev_net(port->dev);
 	br_debug(port->br, "port %u(%s) event %d\n",
 		 (unsigned int)port->port_no, port->dev->name, event);
 
@@ -162,6 +167,57 @@ out:
 	return err;
 }
 
+const struct nla_policy ifla_br_policy[IFLA_MAX+1] = {
+	[IFLA_BRIDGE_FLAGS]	= { .type = NLA_U16 },
+	[IFLA_BRIDGE_MODE]	= { .type = NLA_U16 },
+	[IFLA_BRIDGE_VLAN_INFO]	= { .type = NLA_BINARY,
+				    .len = sizeof(struct bridge_vlan_info), },
+};
+
+static int br_afspec(struct net_bridge *br, struct net_bridge_port *p,
+		     struct nlattr *af_spec)
+{
+	struct nlattr *tb[IFLA_BRIDGE_MAX+1];
+	int err = 0;
+
+	err = nla_parse_nested(tb, IFLA_BRIDGE_MAX, af_spec, ifla_br_policy);
+	if (err)
+		return err;
+
+	if (tb[IFLA_BRIDGE_VLAN_INFO]) {
+		struct bridge_vlan_info *vinfo;
+
+		vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]);
+
+		if (vinfo->vid > VLAN_N_VID)
+			return -EINVAL;
+
+		switch (vinfo->op_code) {
+		case BR_VLAN_ADD:
+			if (p)
+				err = nbp_vlan_add(p, vinfo->vid, vinfo->flags);
+			else {
+				u16 flags = vinfo->flags | BRIDGE_FLAGS_SELF;
+				if (!br_vlan_add(br, vinfo->vid, flags))
+					err = -ENOMEM;
+			}
+			break;
+
+		case BR_VLAN_DEL:
+			if (p)
+				err = nbp_vlan_delete(p, vinfo->vid,
+						      vinfo->flags);
+			else {
+				u16 flags = vinfo->flags | BRIDGE_FLAGS_SELF;
+				err = br_vlan_delete(br, vinfo->vid, flags);
+			}
+			break;
+		}
+	}
+
+	return err;
+}
+
 static const struct nla_policy ifla_brport_policy[IFLA_BRPORT_MAX + 1] = {
 	[IFLA_BRPORT_STATE]	= { .type = NLA_U8 },
 	[IFLA_BRPORT_COST]	= { .type = NLA_U32 },
@@ -238,6 +294,7 @@ int br_setlink(struct net_device *dev, struct nlmsghdr *nlh)
 {
 	struct ifinfomsg *ifm;
 	struct nlattr *protinfo;
+	struct nlattr *afspec;
 	struct net_bridge_port *p;
 	struct nlattr *tb[IFLA_BRPORT_MAX + 1];
 	int err;
@@ -245,35 +302,49 @@ int br_setlink(struct net_device *dev, struct nlmsghdr *nlh)
 	ifm = nlmsg_data(nlh);
 
 	protinfo = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_PROTINFO);
-	if (!protinfo)
+	afspec = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_AF_SPEC);
+	if (!protinfo && !afspec)
 		return 0;
 
 	p = br_port_get_rtnl(dev);
-	if (!p)
+	/* We want to accept dev as bridge itself if the AF_SPEC
+	 * is set to see if someone is setting vlan info on the brigde.
+	 */
+	if (!p && ((dev->priv_flags & IFF_EBRIDGE) && !afspec))
 		return -EINVAL;
 
-	if (protinfo->nla_type & NLA_F_NESTED) {
-		err = nla_parse_nested(tb, IFLA_BRPORT_MAX,
-				       protinfo, ifla_brport_policy);
+	if (p && protinfo) {
+		if (protinfo->nla_type & NLA_F_NESTED) {
+			err = nla_parse_nested(tb, IFLA_BRPORT_MAX,
+					       protinfo, ifla_brport_policy);
+			if (err)
+				return err;
+
+			spin_lock_bh(&p->br->lock);
+			err = br_setport(p, tb);
+			spin_unlock_bh(&p->br->lock);
+		} else {
+			/* Binary compatability with old RSTP */
+			if (nla_len(protinfo) < sizeof(u8))
+				return -EINVAL;
+
+			spin_lock_bh(&p->br->lock);
+			err = br_set_port_state(p, nla_get_u8(protinfo));
+			spin_unlock_bh(&p->br->lock);
+		}
 		if (err)
-			return err;
-
-		spin_lock_bh(&p->br->lock);
-		err = br_setport(p, tb);
-		spin_unlock_bh(&p->br->lock);
-	} else {
-		/* Binary compatability with old RSTP */
-		if (nla_len(protinfo) < sizeof(u8))
-			return -EINVAL;
+			goto out;
+	}
 
-		spin_lock_bh(&p->br->lock);
-		err = br_set_port_state(p, nla_get_u8(protinfo));
-		spin_unlock_bh(&p->br->lock);
+	if (afspec) {
+		err = br_afspec((struct net_bridge *)netdev_priv(dev), p,
+				afspec);
 	}
 
 	if (err == 0)
 		br_ifinfo_notify(RTM_NEWLINK, p);
 
+out:
 	return err;
 }
 
-- 
1.7.7.6

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox