Netdev List
 help / color / mirror / Atom feed
* Re: [net-next-2.6 PATCH 3/3] net: forbid underlaying devices to change its type
From: Jay Vosburgh @ 2010-03-10 21:04 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: netdev, bonding-devel, davem, shemminger, kaber
In-Reply-To: <20100310203019.GF2834@psychotron.redhat.com>

Jiri Pirko <jpirko@redhat.com> wrote:

>It's not desired for underlaying devices to change type. At the time, there is
>for example possible to have bond with changed type from Ethernet to Infiniband
>as a port of a bridge. This patch fixes this.

	Do the current initscripts / sysconfig packages do things such
that this restriction won't break things?  I.e., do those packages have
a dependency on being able to change the type after setting up, e.g., a
VLAN over bonding on Infiniband?

	This isn't to suggest that this change should be rejected if the
above is true; rather, I'm curious as to how this came up as a problem,
and whether initscripts / sysconfig require concurrent changes.

	In any event, it all seems reasonable to me, so, at least for
the bonding bits:

Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>

	-J


>Signed-off-by: Jiri Pirko <jpirko@redhat.com>
>---
> drivers/net/macvlan.c  |    3 +++
> net/8021q/vlan.c       |    4 ++++
> net/bridge/br_notify.c |    4 ++++
> 3 files changed, 11 insertions(+), 0 deletions(-)
>
>diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
>index 40faa36..445e73c 100644
>--- a/drivers/net/macvlan.c
>+++ b/drivers/net/macvlan.c
>@@ -748,6 +748,9 @@ static int macvlan_device_event(struct notifier_block *unused,
> 		list_for_each_entry_safe(vlan, next, &port->vlans, list)
> 			vlan->dev->rtnl_link_ops->dellink(vlan->dev, NULL);
> 		break;
>+	case NETDEV_PRE_TYPE_CHANGE:
>+		/* Forbid underlaying device to change its type. */
>+		return NOTIFY_BAD;
> 	}
> 	return NOTIFY_DONE;
> }
>diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
>index 4535122..c39a5f4 100644
>--- a/net/8021q/vlan.c
>+++ b/net/8021q/vlan.c
>@@ -530,6 +530,10 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
> 		}
> 		unregister_netdevice_many(&list);
> 		break;
>+
>+	case NETDEV_PRE_TYPE_CHANGE:
>+		/* Forbid underlaying device to change its type. */
>+		return NOTIFY_BAD;
> 	}
>
> out:
>diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c
>index 763a3ec..1413b72 100644
>--- a/net/bridge/br_notify.c
>+++ b/net/bridge/br_notify.c
>@@ -82,6 +82,10 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
> 	case NETDEV_UNREGISTER:
> 		br_del_if(br, dev);
> 		break;
>+
>+	case NETDEV_PRE_TYPE_CHANGE:
>+		/* Forbid underlaying device to change its type. */
>+		return NOTIFY_BAD;
> 	}
>
> 	/* Events that may cause spanning tree to refresh */
>-- 
>1.6.6.1
>
>--
>To unsubscribe from this list: send the line "unsubscribe netdev" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [RFC][PATCH] ns: Syscalls for better namespace sharing control.
From: Daniel Lezcano @ 2010-03-10 21:16 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Pavel Emelyanov, Sukadev Bhattiprolu, Serge Hallyn,
	Linux Netdev List, containers, Netfilter Development Mailinglist,
	Ben Greear
In-Reply-To: <m1lje2qzf4.fsf@fess.ebiederm.org>

Eric W. Biederman wrote:
> Daniel Lezcano <daniel.lezcano@free.fr> writes:
>   

[ ... ]

> I guess my meaning is I was expecting.
> child = fork();
> if (child == 0) {
> 	execve(...);
> }
> waitpid(child);
>
> This puts /bin/sh in the container as well.
>   

Eric,

at this point I did not fall in any obvious bug and I was able to enter 
/ execute commands directly inside the container.

Excellent !

Thanks
  -- Daniel



^ permalink raw reply

* [GIT]: Networking
From: David Miller @ 2010-03-10 21:16 UTC (permalink / raw)
  To: torvalds; +Cc: akpm, netdev, linux-kernel


Similar to the pull request I sent a few days ago except the TCP stall
hang regression fix is now in here too (thanks to Eric Dumazet) as
well as qeth bug fixes (via Ursula Braun) a tg3 bug fix in
->poll_controller (from Louis Rilling) and a regression fix in
dev_mc_add() (also from Eric Dumazet).

1) bfin_can build fix from Barry Song.

2) gianfar TX ring SMP race fix from Anton Vorontsov

3) Add support for smc91x on Qualcomm MSM boards, from David Brown.

4) Hot plug removal crash fix in cxgb3 from Divy Le Ray.

5) It's possible to bombard a socket sufficiently such that
   socket backlog accumulates forever.  Put in a limit point at
   which we'll simply start dropping frames.  From Zhu Yi and
   Eric Dumazet.

6) Barrier fixes in r8169 and typhoon from David Dillow.

7) MAINTAINER tweaks for CAN protocol and bridge.

8) Fix excessive route cache rebuilds, from Eric Dumazet.

9) Fix TCP synack packet sizing, also from Eric.

10) CPMAC bug fixes for VLAN receive, and PHY chip fallbacks,
    from Florian Fainelli.

11) Fix RCU handling in bridging code, from Herbert Xu.

12) Fix ipsec flow ID handling, also from Herbert.

13) Fix address length check regression in AF_PACKET, from Jiri Pirko.

14) %pI4 conversion in sunrpc from Joe Perches.  Joe sent this two
    months ago and the NFS folks didn't integrate, Trond told me
    I could take this in via net-2.6 if I like so that's what I've
    done.

15) TIPC oops and RX filtering fixes from Neil Horman.

16) QLCNIC bug fixes from Sucheta Chakraborty.  ETHTOOL get
    TX csum status was horked, add some missing driver stats,
    multicast addr handling fix, and better firmware image
    validation.

17) GRE tunnel header destination address checking fix from Timo Teräs.

18) Missing change to remove obsoleted bnx2x firmware, from
    Vladislav Zolotarov.

19) IPV6 addrconf timer bug fixes from Stephen Hemminger.

20) Fix for packet corruption and TX hang over NFSv2 in
    e1000e, from Jesse Brandeburg.

21) Pegasus USB ID addition, from Petko Manolov.

22) Various use-after-free, leak, et al. fixes from Dan Carpenter.

23) 4K buffer on kernel stack regression fix in Bluetooth from Marcel
    Holtmann.

24) When Ingo added the sync wakeup hints to the networking
    socket handling, he missed tcp_prequeue().  From Mike Galbraith.

25) And the usual assortment of wireless fixes and cures from
    John Linville and the crew.

26) Fix TCP hang, can't test TTL on timewait socket, from Eric
    Dumazet.

27) qeth bug fixes (unsafe checksumming settings, etc.)
    via Ursula Braun.

28) ->poll_controller() passes wrong device pointer to tg3_interrupt(),
    fix from Louis Rilling

29) Fix a regression added to dev_mc_add() (could return with
    lock held), from Eric Dumazet.

Please pull, thanks a lot!

The following changes since commit 57d54889cd00db2752994b389ba714138652e60c:
  Linus Torvalds (1):
        Linux 2.6.34-rc1

are available in the git repository at:

  master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6.git master

Ajit Khaparde (2):
      be2net: remove usage of be_pci_func
      be2net: remove unused code in be_load_fw

Amit Kumar Salecha (2):
      qlcnic: fix bios version check
      qlcnic: remove extra space from board names

Anton Vorontsov (1):
      gianfar: Fix TX ring processing on SMP machines

Barry Song (1):
      can: fix bfin_can build error after alloc_candev() change

Breno Leitao (1):
      s2io: Fixing debug message

Bryan Polk (1):
      rt2x00: Add USB ID for CEIVA adapter to rt73usb

Dan Carpenter (8):
      zd1211rw: fix potential array underflow
      cpmac: use after free
      cassini: fix off by one
      davinci_emac: off by one
      bridge: cleanup: remove unneed check
      ems_usb: cleanup: remove uneeded check
      sock.c: potential null dereference
      irda-usb: add error handling and fix leak

David Brown (1):
      net: smc91x: Support Qualcomm MSM development boards.

David Dillow (2):
      r8169: use correct barrier between cacheable and non-cacheable memory
      typhoon: fix incorrect use of smp_wmb()

David S. Miller (2):
      Merge branch 'master' of git://git.kernel.org/.../linville/wireless-next-2.6
      MAINTAINERS: Add netdev to bridge entry.

Divy Le Ray (1):
      cxgb3: fix hot plug removal crash

Eric Dumazet (7):
      tcp: Add SNMP counters for backlog and min_ttl drops
      net: fix route cache rebuilds
      tcp: Fix tcp_make_synack()
      ethtool: Use noinline_for_stack
      tcp: Fix tcp_v4_rcv()
      net: Annotates neigh_invalidate()
      net: Fix dev_mc_add()

Figo.zhang (1):
      fix a race in ks8695_poll

Florian Fainelli (3):
      cpmac: fix the receiving of 802.1q frames
      cpmac: fallback to switch mode if no PHY chip found
      cpmac: bump version to 0.5.2

Frank Blaschka (2):
      qeth: l3 send dhcp in non pass thru mode
      qeth: change checksumming default for HiperSockets

Greg Ungerer (1):
      net: add ColdFire support to the smc91x driver

Helmut Schaa (2):
      rt2x00: fix rt2800pci compilation with SoC
      rt2x00: Export rt2x00soc_probe from rt2x00soc

Herbert Xu (3):
      ipsec: Fix bogus bundle flowi
      bridge: Use RCU list primitive in __br_mdb_ip_get
      bridge: Fix RCU race in br_multicast_stop

Jeff Garzik (2):
      ethtool: Add direct access to ops->get_sset_count
      ethtool: Add direct access to ops->get_sset_count

Jesse Brandeburg (1):
      e1000e: fix packet corruption and tx hang during NFSv2

Jiri Pirko (2):
      af_packet: move strict addr_len check right before dev_[mc/unicast]_[add/del]
      rndis_wlan: correct multicast_list handling V3

Joe Perches (2):
      net/sunrpc: Remove uses of NIPQUAD, use %pI4
      net/sunrpc: Convert (void)snprintf to snprintf

Johannes Berg (2):
      ar9170: load firmware asynchronously
      iwlwifi: load firmware asynchronously before mac80211 registration

Jouni Malinen (1):
      mac80211: Fix reassociation processing (within ESS roaming)

Jussi Kivilinna (1):
      asix: fix setting mac address for AX88772

Louis Rilling (1):
      tg3: Fix tg3_poll_controller() passing wrong pointer to tg3_interrupt()

Marcel Holtmann (1):
      Bluetooth: Use single_open() for inquiry cache within debugfs

Matthew Garrett (1):
      rfkill: Add support for KEY_RFKILL

Mike Galbraith (1):
      net: add scheduler sync hint to tcp_prequeue().

Ming Lei (1):
      ath9k: fix lockdep warning when unloading module

Neil Horman (3):
      tipc: Fix oops on send prior to entering networked mode (v3)
      tipc: fix endianness on tipc subscriber messages
      tipc: filter out messages not intended for this host

Oliver Hartkopp (1):
      MAINTAINER: Correct CAN Maintainer responsibilities and paths

Petko Manolov (1):
      another pegasus usb net device

Randy Dunlap (1):
      bridge: depends on INET

Sarveshwar Bandi (1):
      be2net: download NCSI section during firmware update

Stanislaw Gruszka (1):
      airo: return from set_wep_key() when key length is zero

Sucheta Chakraborty (4):
      qlcnic: fix tx csum status
      qlcnic: additional driver statistics.
      qlcnic: fix multicast handling
      qlcnic: validate unified fw image

Sujith (1):
      mac80211: Fix HT rate control configuration

Timo Teräs (1):
      gre: fix hard header destination address checking

Ursula Braun (3):
      qeth: enable kmsg hash processing in qeth_core_sys.c
      qeth: set promisc off after trace disabling failure
      qeth: no recovery after layer mismatch (z/VM NICs)

Vladislav Zolotarov (1):
      bnx2x: Removed FW 5.2.7

Wolfgang Grandegger (1):
      MAINTAINERS: add netdev to CAN network layer and drivers entries

YOSHIFUJI Hideaki (2):
      ipv6: Optmize translation between IPV6_PREFER_SRC_xxx and RT6_LOOKUP_F_xxx.
      ipv6 ip6_tunnel: eliminate unused recursion field from ip6_tnl{}.

Zhu Yi (9):
      net: add limit for socket backlog
      tcp: use limited socket backlog
      udp: use limited socket backlog
      llc: use limited socket backlog
      sctp: use limited socket backlog
      tipc: use limited socket backlog
      x25: use limited socket backlog
      net: backlog functions rename
      net: add __must_check to sk_add_backlog

stephen hemminger (4):
      IPv6: addrconf dad timer unnecessary bh_disable
      IPv6: addrconf timer race
      IPv6: addrconf notify when address is unavailable
      IPv6: fix race between cleanup and add/delete address

 MAINTAINERS                              |   21 +-
 drivers/net/Kconfig                      |    2 +-
 drivers/net/arm/ks8695net.c              |    2 +-
 drivers/net/benet/be.h                   |    5 -
 drivers/net/benet/be_cmds.c              |    6 -
 drivers/net/benet/be_hw.h                |    5 +-
 drivers/net/benet/be_main.c              |   25 +-
 drivers/net/can/bfin_can.c               |    3 +-
 drivers/net/can/usb/ems_usb.c            |    4 +-
 drivers/net/cassini.c                    |    2 +-
 drivers/net/cpmac.c                      |   14 +-
 drivers/net/cxgb3/cxgb3_main.c           |    1 +
 drivers/net/davinci_emac.c               |    2 +-
 drivers/net/e1000e/defines.h             |    2 +
 drivers/net/e1000e/ich8lan.c             |   10 +
 drivers/net/gianfar.c                    |    5 +-
 drivers/net/irda/irda-usb.c              |    4 +
 drivers/net/qlcnic/qlcnic.h              |   13 +-
 drivers/net/qlcnic/qlcnic_ethtool.c      |   17 +
 drivers/net/qlcnic/qlcnic_hw.c           |   32 +-
 drivers/net/qlcnic/qlcnic_init.c         |  156 +-
 drivers/net/qlcnic/qlcnic_main.c         |    5 +
 drivers/net/r8169.c                      |    4 +-
 drivers/net/s2io.c                       |    6 +-
 drivers/net/smc91x.h                     |   42 +
 drivers/net/tg3.c                        |    2 +-
 drivers/net/typhoon.c                    |    6 +-
 drivers/net/usb/asix.c                   |   30 +-
 drivers/net/usb/pegasus.h                |    6 +-
 drivers/net/wireless/airo.c              |    3 +-
 drivers/net/wireless/ath/ar9170/ar9170.h |    1 +
 drivers/net/wireless/ath/ar9170/main.c   |   10 +-
 drivers/net/wireless/ath/ar9170/usb.c    |  170 +-
 drivers/net/wireless/ath/ath9k/rc.c      |    6 +-
 drivers/net/wireless/ath/ath9k/xmit.c    |    4 +-
 drivers/net/wireless/iwlwifi/iwl-agn.c   |  157 +-
 drivers/net/wireless/iwlwifi/iwl-dev.h   |    2 +
 drivers/net/wireless/rndis_wlan.c        |   66 +-
 drivers/net/wireless/rt2x00/rt2800pci.c  |    2 +-
 drivers/net/wireless/rt2x00/rt2x00soc.c  |    1 +
 drivers/net/wireless/rt2x00/rt73usb.c    |    2 +
 drivers/net/wireless/zd1211rw/zd_mac.c   |   10 +-
 drivers/s390/net/qeth_core.h             |    3 +-
 drivers/s390/net/qeth_core_main.c        |    5 +-
 drivers/s390/net/qeth_core_sys.c         |    3 +
 drivers/s390/net/qeth_l2_main.c          |   16 +-
 drivers/s390/net/qeth_l3_main.c          |   82 +-
 firmware/bnx2x-e1-5.2.7.0.fw.ihex        |10178 -----------------------
 firmware/bnx2x-e1h-5.2.7.0.fw.ihex       |12847 ------------------------------
 include/linux/ethtool.h                  |   24 +-
 include/linux/rfkill.h                   |    2 +-
 include/linux/snmp.h                     |    2 +
 include/net/ip6_route.h                  |   18 +
 include/net/ip6_tunnel.h                 |    1 -
 include/net/mac80211.h                   |    3 +-
 include/net/sock.h                       |   17 +-
 include/net/tcp.h                        |    2 +-
 include/net/xfrm.h                       |    3 +-
 net/bluetooth/hci_sysfs.c                |   41 +-
 net/bridge/Kconfig                       |    1 +
 net/bridge/br_multicast.c                |    8 +-
 net/core/dev_mcast.c                     |    5 +-
 net/core/ethtool.c                       |  103 +-
 net/core/neighbour.c                     |    2 +
 net/core/sock.c                          |   19 +-
 net/dccp/minisocks.c                     |    2 +-
 net/ipv4/ip_gre.c                        |    7 +-
 net/ipv4/proc.c                          |    2 +
 net/ipv4/route.c                         |   50 +-
 net/ipv4/tcp_ipv4.c                      |   15 +-
 net/ipv4/tcp_minisocks.c                 |    2 +-
 net/ipv4/tcp_output.c                    |   18 +-
 net/ipv4/udp.c                           |    6 +-
 net/ipv4/xfrm4_policy.c                  |    5 +-
 net/ipv6/addrconf.c                      |  102 +-
 net/ipv6/fib6_rules.c                    |   11 +-
 net/ipv6/route.c                         |   11 +-
 net/ipv6/tcp_ipv6.c                      |    7 +-
 net/ipv6/udp.c                           |   28 +-
 net/ipv6/xfrm6_policy.c                  |    3 +-
 net/llc/llc_c_ac.c                       |    2 +-
 net/llc/llc_conn.c                       |    3 +-
 net/mac80211/mlme.c                      |   19 +-
 net/mac80211/rate.h                      |    5 +-
 net/packet/af_packet.c                   |    6 +-
 net/rfkill/input.c                       |    8 +
 net/sctp/input.c                         |   42 +-
 net/sctp/socket.c                        |    3 +
 net/sunrpc/xprtrdma/transport.c          |    7 +-
 net/sunrpc/xprtsock.c                    |    9 +-
 net/tipc/bearer.c                        |   37 +-
 net/tipc/bearer.h                        |    2 +-
 net/tipc/link.c                          |    9 +
 net/tipc/net.c                           |   25 +-
 net/tipc/socket.c                        |    6 +-
 net/tipc/subscr.c                        |   57 +-
 net/tipc/subscr.h                        |    2 -
 net/x25/x25_dev.c                        |    2 +-
 net/xfrm/xfrm_policy.c                   |    7 +-
 99 files changed, 1103 insertions(+), 23668 deletions(-)
 delete mode 100644 firmware/bnx2x-e1-5.2.7.0.fw.ihex
 delete mode 100644 firmware/bnx2x-e1h-5.2.7.0.fw.ihex

^ permalink raw reply

* Re: [net-next-2.6 PATCH 3/3] net: forbid underlaying devices to change its type
From: Jiri Pirko @ 2010-03-10 21:17 UTC (permalink / raw)
  To: Jay Vosburgh; +Cc: netdev, bonding-devel, davem, shemminger, kaber
In-Reply-To: <23664.1268255050@death.nxdomain.ibm.com>

Wed, Mar 10, 2010 at 10:04:10PM CET, fubar@us.ibm.com wrote:
>Jiri Pirko <jpirko@redhat.com> wrote:
>
>>It's not desired for underlaying devices to change type. At the time, there is
>>for example possible to have bond with changed type from Ethernet to Infiniband
>>as a port of a bridge. This patch fixes this.
>
>	Do the current initscripts / sysconfig packages do things such
>that this restriction won't break things?  I.e., do those packages have
>a dependency on being able to change the type after setting up, e.g., a
>VLAN over bonding on Infiniband?
>
>	This isn't to suggest that this change should be rejected if the
>above is true; rather, I'm curious as to how this came up as a problem,
>and whether initscripts / sysconfig require concurrent changes.

I'm not aware initscripts / sysconfig require type change. In fanc this
wouldn't make sense. This popped up when I was converting mc_lists, I thought
if this is possible, tried with infiniband and it was. Therefore I decided
to fix this.

Jirka

>
>	In any event, it all seems reasonable to me, so, at least for
>the bonding bits:
>
>Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>
>
>	-J
>
>
>>Signed-off-by: Jiri Pirko <jpirko@redhat.com>
>>---
>> drivers/net/macvlan.c  |    3 +++
>> net/8021q/vlan.c       |    4 ++++
>> net/bridge/br_notify.c |    4 ++++
>> 3 files changed, 11 insertions(+), 0 deletions(-)
>>
>>diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
>>index 40faa36..445e73c 100644
>>--- a/drivers/net/macvlan.c
>>+++ b/drivers/net/macvlan.c
>>@@ -748,6 +748,9 @@ static int macvlan_device_event(struct notifier_block *unused,
>> 		list_for_each_entry_safe(vlan, next, &port->vlans, list)
>> 			vlan->dev->rtnl_link_ops->dellink(vlan->dev, NULL);
>> 		break;
>>+	case NETDEV_PRE_TYPE_CHANGE:
>>+		/* Forbid underlaying device to change its type. */
>>+		return NOTIFY_BAD;
>> 	}
>> 	return NOTIFY_DONE;
>> }
>>diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
>>index 4535122..c39a5f4 100644
>>--- a/net/8021q/vlan.c
>>+++ b/net/8021q/vlan.c
>>@@ -530,6 +530,10 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
>> 		}
>> 		unregister_netdevice_many(&list);
>> 		break;
>>+
>>+	case NETDEV_PRE_TYPE_CHANGE:
>>+		/* Forbid underlaying device to change its type. */
>>+		return NOTIFY_BAD;
>> 	}
>>
>> out:
>>diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c
>>index 763a3ec..1413b72 100644
>>--- a/net/bridge/br_notify.c
>>+++ b/net/bridge/br_notify.c
>>@@ -82,6 +82,10 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
>> 	case NETDEV_UNREGISTER:
>> 		br_del_if(br, dev);
>> 		break;
>>+
>>+	case NETDEV_PRE_TYPE_CHANGE:
>>+		/* Forbid underlaying device to change its type. */
>>+		return NOTIFY_BAD;
>> 	}
>>
>> 	/* Events that may cause spanning tree to refresh */
>>-- 
>>1.6.6.1
>>
>>--
>>To unsubscribe from this list: send the line "unsubscribe netdev" in
>>the body of a message to majordomo@vger.kernel.org
>>More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 6/13] bridge: Add core IGMP snooping support
From: Paul E. McKenney @ 2010-03-10 21:25 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: David Miller, herbert, eric.dumazet, netdev, shemminger
In-Reply-To: <201003101856.53525.arnd@arndb.de>

On Wed, Mar 10, 2010 at 06:56:53PM +0100, Arnd Bergmann wrote:
> On Wednesday 10 March 2010, David Miller wrote:
> > From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
> > Date: Wed, 10 Mar 2010 08:26:58 -0800
> >
> > > I have -tip commit a898def29e4119bc01ebe7ca97423181f4c0ea2d that
> > > converts some of the rcu_dereference()s in net/core/filter.c,
> > > net/core/dev.c, net/decnet/dn_route.c, net/packet/af_packet.c, and
> > > net/ipv4/route.c to rcu_dereference_bh().
> > > 
> > > How should we coordinate the removal of the rcu_read_lock() calls?
> > 
> > Paul if you want to do this via your tree, feel free.
> 
> My feeling is that this should be combined with the annotations I'm doing,
> annotating one subsystem at a time, and doing changes like these in the
> process. I'm still unsure what interface extensions there will have to
> be, but I guess we can the new interfaces as empty wrappers in the 2.6.34
> phase, and do all of the conversions where there are potential or real
> bugs.
> 
> All the other annotations can get queued in subsystem maintainer trees
> where it makes sense or get put in one tree for all the others, to be
> merged in after 2.6.34 is out.

Makes sense to me -- and thank you, Arnd, for taking this on!!!

							Thanx, Paul

^ permalink raw reply

* Re: [RFC][ PATCH 1/3] vhost-net: support multiple buffer heads in receiver
From: David Stevens @ 2010-03-10 22:17 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: kvm, netdev, rusty, virtualization
In-Reply-To: <20100308074533.GA7482@redhat.com>

"Michael S. Tsirkin" <mst@redhat.com> wrote on 03/07/2010 11:45:33 PM:

> > > > +static int skb_head_len(struct sk_buff_head *skq)
> > > > +{
> > > > +       struct sk_buff *head;
> > > > +
> > > > +       head = skb_peek(skq);
> > > > +       if (head)
> > > > +               return head->len;
> > > > +       return 0;
> > > > +}
> > > > +
> > > 
> > > This is done without locking, which I think can crash
> > > if skb is consumed after we peek it but before we read the
> > > length.
> > 
> >         This thread is the only legitimate consumer, right? But
> > qemu has the file descriptor and I guess we shouldn't trust
> > that it won't give it to someone else; it'd break vhost, but
> > a crash would be inappropriate, of course. I'd like to avoid
> > the lock, but I have another idea here, so will investigate.

        I looked at this some more and actually, I'm not sure I
see a crash here.
        First, without qemu, or something it calls, being broken
as root, nothing else should ever read from the socket, in which
case the length will be exactly right for the next packet we
read. No problem.
        But if by some error this skb is freed, we'll have valid
memory address that isn't the length field of the next packet
we'll read.
        If the length is negative or more than available in the
vring, we'll fail the buffer allocation, exit the loop, and
get the new head length of the receive queue the next time
around -- no problem.
        If the length field is 0, we'll exit the loop even
though we have data to read, but will get that packet the
next time we get in here, again, with the right length.
No problem.
        If the length field is big enough to allocate buffer
space for it, but smaller than the new head we have to read,
the recvmsg will fail with EMSGSIZE, drop the packet, exit
the loop and be back in business with the next packet. No
problem.
        Otherwise, the packet will fit and be delivered.

        I don't much like the notion of using skb->head when
it's garbage, but that can only happen if qemu has broken,
and I don't see a crash unless the skb is not only freed
but no longer a valid memory address for reading at all,
and all within the race window.
        Since the code handles other failure cases (not
enough ring buffers or packet not fitting in the allocated
buffers), the actual length value only matters in the
sense that it prevents us from using buffers unnecessarily--
something that isn't all that relevant if it's hosed enough
to have unauthorized readers on the socket.

        Is this case worth the performance penalty we'll no
doubt pay for either locking the socket or always allocating
for a max-sized packet? I'll experiment with a couple
solutions here, but unless I've missed something, we might
be better off just leaving it as-is.

                                                        +-DLS



^ permalink raw reply

* Re: problem with kernel ipconfig over usb ethernet on v.2.6.33-rc3
From: David Miller @ 2010-03-10 22:33 UTC (permalink / raw)
  To: chripell; +Cc: netdev
In-Reply-To: <cabda6421001102318m972e0bdw3f44962b5307d4b@mail.gmail.com>

From: christian pellegrin <chripell@gmail.com>
Date: Mon, 11 Jan 2010 08:18:13 +0100

> I can try more elaborate schemes like: if the ethX specified by ip=
> is not present at the first try just wait 10 seconds and try again
> (perhaps repeat this two time just to be sure).

Please let me know if this patch makes your setup work
properly.

It loops one second at a time, for up to 12 seconds, waiting
for a usable non-loopback device to appear.

diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 10a6a60..6789092 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -187,6 +187,16 @@ struct ic_device {
 static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */
 static struct net_device *ic_dev __initdata = NULL;	/* Selected device */
 
+static bool __init ic_device_match(struct net_device *dev)
+{
+	if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) :
+	    (!(dev->flags & IFF_LOOPBACK) &&
+	     (dev->flags & (IFF_POINTOPOINT|IFF_BROADCAST)) &&
+	     strncmp(dev->name, "dummy", 5)))
+		return true;
+	return false;
+}
+
 static int __init ic_open_devs(void)
 {
 	struct ic_device *d, **last;
@@ -207,10 +217,7 @@ static int __init ic_open_devs(void)
 	for_each_netdev(&init_net, dev) {
 		if (dev->flags & IFF_LOOPBACK)
 			continue;
-		if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) :
-		    (!(dev->flags & IFF_LOOPBACK) &&
-		     (dev->flags & (IFF_POINTOPOINT|IFF_BROADCAST)) &&
-		     strncmp(dev->name, "dummy", 5))) {
+		if (ic_device_match(dev)) {
 			int able = 0;
 			if (dev->mtu >= 364)
 				able |= IC_BOOTP;
@@ -228,7 +235,7 @@ static int __init ic_open_devs(void)
 			}
 			if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL))) {
 				rtnl_unlock();
-				return -1;
+				return -ENOMEM;
 			}
 			d->dev = dev;
 			*last = d;
@@ -253,7 +260,7 @@ static int __init ic_open_devs(void)
 			printk(KERN_ERR "IP-Config: Device `%s' not found.\n", user_dev_name);
 		else
 			printk(KERN_ERR "IP-Config: No network devices available.\n");
-		return -1;
+		return -ENODEV;
 	}
 	return 0;
 }
@@ -1303,6 +1310,32 @@ __be32 __init root_nfs_parse_addr(char *name)
 	return addr;
 }
 
+#define DEVICE_WAIT_MAX		12 /* 12 seconds */
+
+static int __init wait_for_devices(void)
+{
+	int i;
+
+	msleep(CONF_PRE_OPEN);
+	for (i = 0; i < DEVICE_WAIT_MAX; i++) {
+		struct net_device *dev;
+		int found = 0;
+
+		rtnl_lock();
+		for_each_netdev(&init_net, dev) {
+			if (ic_device_match(dev)) {
+				found = 1;
+				break;
+			}
+		}
+		rtnl_unlock();
+		if (found)
+			return 0;
+		ssleep(1);
+	}
+	return -ENODEV;
+}
+
 /*
  *	IP Autoconfig dispatcher.
  */
@@ -1313,6 +1346,7 @@ static int __init ip_auto_config(void)
 #ifdef IPCONFIG_DYNAMIC
 	int retries = CONF_OPEN_RETRIES;
 #endif
+	int err;
 
 #ifdef CONFIG_PROC_FS
 	proc_net_fops_create(&init_net, "pnp", S_IRUGO, &pnp_seq_fops);
@@ -1325,12 +1359,15 @@ static int __init ip_auto_config(void)
 #ifdef IPCONFIG_DYNAMIC
  try_try_again:
 #endif
-	/* Give hardware a chance to settle */
-	msleep(CONF_PRE_OPEN);
+	/* Wait for devices to appear */
+	err = wait_for_devices();
+	if (err)
+		return err;
 
 	/* Setup all network devices */
-	if (ic_open_devs() < 0)
-		return -1;
+	err = ic_open_devs();
+	if (err)
+		return err;
 
 	/* Give drivers a chance to settle */
 	ssleep(CONF_POST_OPEN);

^ permalink raw reply related

* Re: [Bonding-devel] [net-next-2.6 PATCH 2/3] bonding: check return value of nofitier when changing type
From: Stephen Hemminger @ 2010-03-10 22:47 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: netdev, kaber, fubar, bonding-devel, davem
In-Reply-To: <20100310202935.GE2834@psychotron.redhat.com>

On Wed, 10 Mar 2010 21:29:35 +0100
Jiri Pirko <jpirko@redhat.com> wrote:

> diff --git a/net/core/dev.c b/net/core/dev.c
> index bcc490c..5de4a15 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -1084,9 +1084,9 @@ void netdev_state_change(struct net_device *dev)
>  }
>  EXPORT_SYMBOL(netdev_state_change);
>  
> -void netdev_bonding_change(struct net_device *dev, unsigned long event)
> +int netdev_bonding_change(struct net_device *dev, unsigned long event)
>  {
> -	call_netdevice_notifiers(event, dev);
> +	return call_netdevice_notifiers(event, dev);
>  }
>  EXPORT_SYMBOL(netdev_bonding_change);
>  

I don't think all this pre-post stuff needed.
Since this is general (not just bonding) how about

int netdev_change_type(struct net_device *dev, int newtype)
{
	int ret, oldtype;

	if (dev->flags & IFF_UP)
		return -EBUSY;

	oldtype = dev->type;
	dev->type = newtype;
	ret = call_netdevice_notifier(NETDEV_CHANGETYPE, dev);
	ret = notifier_to_errno(ret);
	if (ret)
	     dev->type = oldtype;

	return ret;
}
	     

^ permalink raw reply

* Re: BNX2: Kernel crashes with 2.6.31 and 2.6.31.9
From: Brian Haley @ 2010-03-10 23:09 UTC (permalink / raw)
  To: Michael Chan; +Cc: Bruno Prémont, Benjamin Li, NetDEV, Linux-Kernel
In-Reply-To: <4B90189B.2040801@hp.com>

Brian Haley wrote:
> Hi Michael,
> 
> Michael Chan wrote:
>> Do we have timers running in this environment?  The timer in the bnx2
>> driver, bnx2_timer(), needs to run to provide a heart beat to the
>> firmware.  In netpoll mode without timer interrupts, if we are regularly
>> calling the NAPI poll function, it should also be able to provide the
>> heartbeat.  Without the heartbeat, the firmware will reset the chip and
>> result in the NETDEV WATCHDOG.
> 
> We have also been seeing watchdog timeouts with bnx2, below is a
> stack trace with Benjamin's debug patch applied.  Normally we were
> only seeing them under heavy load, but this one was at boot.  We haven't
> tried the latest firmware/driver from 2.6.33 yet.  You can contact me
> offline if you need more detailed info.

Following-up since I have more info on this issue.

I'm able to cause a netdev_watchdog timeout by changing the coalesce
settings on my bnx2, I built a little test program for it:

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <linux/if.h>
#include <linux/ethtool.h>
#include <linux/sockios.h>

main()
{
	struct ifreq ifr;
	struct ethtool_coalesce ecoal;
	int fd, err;
	int sleeptime = 5;
	char *ifname = "eth0";

	fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (fd < 0) {
		perror("socket");
		exit(1);
	}

	bzero(&ifr, sizeof(ifr));
	bcopy(ifname, ifr.ifr_name, sizeof(ifname));

	bzero(&ecoal, sizeof(ecoal));

	printf("Running ETHTOOL_GCOALESCE on %s\n", ifname);
	ecoal.cmd = ETHTOOL_GCOALESCE;
	ifr.ifr_data = (caddr_t)&ecoal;
	err = ioctl(fd, SIOCETHTOOL, &ifr);
	if (err)
		perror("ETHTOOL_GCOALESCE");
	printf("Sleeping %d seconds\n", sleeptime);
	sleep(sleeptime);

	ecoal.rx_coalesce_usecs = 0;
	ecoal.rx_max_coalesced_frames = 1;
	ecoal.rx_coalesce_usecs_irq = 0;
	ecoal.rx_max_coalesced_frames_irq = 1;

	printf("Setting ETHTOOL_SCOALESCE on %s\n", ifname);
	ecoal.cmd = ETHTOOL_SCOALESCE;
	ifr.ifr_data = (caddr_t)&ecoal;
	err = ioctl(fd, SIOCETHTOOL, &ifr);
	if (err)
		perror("ETHTOOL_SCOALESCE");
}

[    2.428093] bnx2 0000:04:00.0: firmware: requesting bnx2/bnx2-rv2p-06-5.0.0.j3.fw
[    2.432526] eth0: Broadcom NetXtreme II BCM5708 1000Base-T (B2) PCI-X 64-bit 133MHz found at mem f6000000, IRQ 41, node addr 00:1c:c4:e1:cc:ea
[    2.439520] bnx2 0000:42:00.0: PCI INT A -> GSI 34 (level, low) -> IRQ 34

lspci shows this is a HP 373i, it's the onboard NIC.

Running this on one particular system I get:

Mar 10 07:48:58 N1002563 kernel: [  870.780023] ------------[ cut here ]------------
Mar 10 07:48:58 N1002563 kernel: [  870.780037] WARNING: at net/sched/sch_generic.c:261 dev_watchdog+0x12d/0x1d5()
Mar 10 07:48:58 N1002563 kernel: [  870.780041] Hardware name: ProLiant DL385 G5 
Mar 10 07:48:58 N1002563 kernel: [  870.780046] NETDEV WATCHDOG: eth0 (bnx2): transmit queue 0 timed out
Mar 10 07:48:58 N1002563 kernel: [  870.780050] Modules linked in: mptctl ipmi_devintf deflate zlib_deflate ctr twofish twofish_common camellia serpent blowfish cast5 des_generic cbc cryptd aes_x86_64 aes_generic xcbc rmd160 sha256_generic sha1_generic crypto_null af_key sg bonding sctp crc32c libcrc32c loop psmouse serio_raw container amd64_edac_mod edac_core i2c_piix4 shpchp pci_hotplug ipmi_si i2c_core ipmi_msghandler hpilo processor evdev ext3 jbd mbcache sd_mod crc_t10dif usbhid hid ata_generic libata ide_pci_generic e1000e bnx2 mptsas mptscsih mptbase serverworks scsi_transport_sas ide_core ehci_hcd scsi_mod ohci_hcd uhci_hcd button thermal fan thermal_sys edd [last unloaded: scsi_wait_scan]
Mar 10 07:48:58 N1002563 kernel: [  870.780133] Pid: 0, comm: swapper Not tainted 2.6.32-clim-4-amd64 #1
Mar 10 07:48:58 N1002563 kernel: [  870.780137] Call Trace:
Mar 10 07:48:58 N1002563 kernel: [  870.780141]  <IRQ>  [<ffffffff812697a0>] ? dev_watchdog+0x12d/0x1d5
Mar 10 07:48:58 N1002563 kernel: [  870.780156]  [<ffffffff81049914>] warn_slowpath_common+0x77/0xa4
Mar 10 07:48:58 N1002563 kernel: [  870.780170]  [<ffffffff810499b6>] warn_slowpath_fmt+0x64/0x66
Mar 10 07:48:58 N1002563 kernel: [  870.780177]  [<ffffffff81045df7>] ? default_wake_function+0xd/0xf
Mar 10 07:48:58 N1002563 kernel: [  870.780184]  [<ffffffff81035fa7>] ? __wake_up_common+0x46/0x76
Mar 10 07:48:58 N1002563 kernel: [  870.780191]  [<ffffffff8103b414>] ? __wake_up+0x43/0x50
Mar 10 07:48:58 N1002563 kernel: [  870.780198]  [<ffffffff81253829>] ? netdev_drivername+0x43/0x4b
Mar 10 07:48:58 N1002563 kernel: [  870.780204]  [<ffffffff812697a0>] dev_watchdog+0x12d/0x1d5
Mar 10 07:48:58 N1002563 kernel: [  870.780214]  [<ffffffff8105e84a>] ? delayed_work_timer_fn+0x0/0x3d
Mar 10 07:48:58 N1002563 kernel: [  870.780219]  [<ffffffff8105e7ee>] ? __queue_work+0x35/0x3d
Mar 10 07:48:58 N1002563 kernel: [  870.780227]  [<ffffffff81269673>] ? dev_watchdog+0x0/0x1d5
Mar 10 07:48:58 N1002563 kernel: [  870.780234]  [<ffffffff8105655a>] run_timer_softirq+0x1ff/0x2a1
Mar 10 07:48:58 N1002563 kernel: [  870.780242]  [<ffffffff810205a1>] ? lapic_next_event+0x18/0x1c
Mar 10 07:48:58 N1002563 kernel: [  870.780249]  [<ffffffff8104f9e3>] __do_softirq+0xde/0x19f
Mar 10 07:48:58 N1002563 kernel: [  870.780256]  [<ffffffff8100ccec>] call_softirq+0x1c/0x28
Mar 10 07:48:58 N1002563 kernel: [  870.780262]  [<ffffffff8100e8b1>] do_softirq+0x41/0x81
Mar 10 07:48:58 N1002563 kernel: [  870.780268]  [<ffffffff8104f7bd>] irq_exit+0x36/0x75
Mar 10 07:48:58 N1002563 kernel: [  870.780274]  [<ffffffff81020f33>] smp_apic_timer_interrupt+0x88/0x96
Mar 10 07:48:58 N1002563 kernel: [  870.780287]  [<ffffffff8100c6b3>] apic_timer_interrupt+0x13/0x20
Mar 10 07:48:58 N1002563 kernel: [  870.780291]  <EOI>  [<ffffffff81027740>] ? native_safe_halt+0x6/0x8
Mar 10 07:48:58 N1002563 kernel: [  870.780304]  [<ffffffff81012da3>] ? default_idle+0x55/0x74
Mar 10 07:48:58 N1002563 kernel: [  870.780309]  [<ffffffff810131ce>] ? c1e_idle+0xf4/0xfb
Mar 10 07:48:58 N1002563 kernel: [  870.780315]  [<ffffffff81065529>] ? atomic_notifier_call_chain+0x13/0x15
Mar 10 07:48:58 N1002563 kernel: [  870.780321]  [<ffffffff8100aeec>] ? cpu_idle+0x5b/0x93
Mar 10 07:48:58 N1002563 kernel: [  870.780329]  [<ffffffff81304144>] ? start_secondary+0x1a8/0x1ac
Mar 10 07:48:58 N1002563 kernel: [  870.780334] ---[ end trace 08b420ca1e09a176 ]---
Mar 10 07:48:58 N1002563 kernel: [  870.780339] bnx2: eth0 DEBUG: intr_sem[0]
Mar 10 07:48:58 N1002563 kernel: [  870.780345] bnx2: eth0 DEBUG: EMAC_TX_STATUS[00000008] RPM_MGMT_PKT_CTRL[00000000]
Mar 10 07:48:58 N1002563 kernel: [  870.780352] bnx2: eth0 DEBUG: MCP_STATE_P0[00000000] MCP_STATE_P1[00000000]
Mar 10 07:48:58 N1002563 kernel: [  870.780357] bnx2: eth0 DEBUG: HC_STATS_INTERRUPT_STATUS[00000000]
Mar 10 07:49:03 N1002563 kernel: [  875.780020] bnx2: eth0 DEBUG: intr_sem[0]
Mar 10 07:49:03 N1002563 kernel: [  875.780026] bnx2: eth0 DEBUG: EMAC_TX_STATUS[00000008] RPM_MGMT_PKT_CTRL[00000000]
Mar 10 07:49:03 N1002563 kernel: [  875.780038] bnx2: eth0 DEBUG: MCP_STATE_P0[00000000] MCP_STATE_P1[00000000]
Mar 10 07:49:03 N1002563 kernel: [  875.780043] bnx2: eth0 DEBUG: HC_STATS_INTERRUPT_STATUS[00000000]

This debug message would repeat every 5 seconds, eventually
the systems locks-up.

This is running a 2.6.32-8 stable kernel, I've tried a version with Ben's
patch from this thread installed with no change in behavior.  I'm in the
process of backporting all the upstream changes to see if that helps.

Guessing it's a race condition caused by these calls in bnx2_set_coalesce():

        if (netif_running(bp->dev)) {
                bnx2_netif_stop(bp);
                bnx2_init_nic(bp, 0);
                bnx2_netif_start(bp);
        }

Thanks for any help,

-Brian

^ permalink raw reply

* Re: BNX2: Kernel crashes with 2.6.31 and 2.6.31.9
From: Michael Chan @ 2010-03-10 23:32 UTC (permalink / raw)
  To: Brian Haley; +Cc: Bruno Prémont, Benjamin Li, NetDEV, Linux-Kernel
In-Reply-To: <4B98268D.2020206@hp.com>


On Wed, 2010-03-10 at 15:09 -0800, Brian Haley wrote:
> Brian Haley wrote:
> > Hi Michael,
> > 
> > Michael Chan wrote:
> >> Do we have timers running in this environment?  The timer in the bnx2
> >> driver, bnx2_timer(), needs to run to provide a heart beat to the
> >> firmware.  In netpoll mode without timer interrupts, if we are regularly
> >> calling the NAPI poll function, it should also be able to provide the
> >> heartbeat.  Without the heartbeat, the firmware will reset the chip and
> >> result in the NETDEV WATCHDOG.
> > 
> > We have also been seeing watchdog timeouts with bnx2, below is a
> > stack trace with Benjamin's debug patch applied.  Normally we were
> > only seeing them under heavy load, but this one was at boot.  We haven't
> > tried the latest firmware/driver from 2.6.33 yet.  You can contact me
> > offline if you need more detailed info.
> 
> Following-up since I have more info on this issue.
> 
> I'm able to cause a netdev_watchdog timeout by changing the coalesce
> settings on my bnx2, I built a little test program for it:

Do you run this program in a loop?  How quickly do you see the NETDEV
WATCHDOG?

> 
> #include <stdio.h>
> #include <stdlib.h>
> #include <strings.h>
> #include <unistd.h>
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <netinet/in.h>
> #include <linux/if.h>
> #include <linux/ethtool.h>
> #include <linux/sockios.h>
> 
> main()
> {
> 	struct ifreq ifr;
> 	struct ethtool_coalesce ecoal;
> 	int fd, err;
> 	int sleeptime = 5;
> 	char *ifname = "eth0";
> 
> 	fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
> 	if (fd < 0) {
> 		perror("socket");
> 		exit(1);
> 	}
> 
> 	bzero(&ifr, sizeof(ifr));
> 	bcopy(ifname, ifr.ifr_name, sizeof(ifname));
> 
> 	bzero(&ecoal, sizeof(ecoal));
> 
> 	printf("Running ETHTOOL_GCOALESCE on %s\n", ifname);
> 	ecoal.cmd = ETHTOOL_GCOALESCE;
> 	ifr.ifr_data = (caddr_t)&ecoal;
> 	err = ioctl(fd, SIOCETHTOOL, &ifr);
> 	if (err)
> 		perror("ETHTOOL_GCOALESCE");
> 	printf("Sleeping %d seconds\n", sleeptime);
> 	sleep(sleeptime);
> 
> 	ecoal.rx_coalesce_usecs = 0;
> 	ecoal.rx_max_coalesced_frames = 1;
> 	ecoal.rx_coalesce_usecs_irq = 0;
> 	ecoal.rx_max_coalesced_frames_irq = 1;

These rx settings should be ok.  Did you change the tx settings?  If the
tx settings are all zeros, you won't get any TX interrupts and you can
get a NETDEV WATCHDOG.

Run ethtool -c eth0 to see what the tx settings are.  Thanks.

> 
> 	printf("Setting ETHTOOL_SCOALESCE on %s\n", ifname);
> 	ecoal.cmd = ETHTOOL_SCOALESCE;
> 	ifr.ifr_data = (caddr_t)&ecoal;
> 	err = ioctl(fd, SIOCETHTOOL, &ifr);
> 	if (err)
> 		perror("ETHTOOL_SCOALESCE");
> }
> 
> [    2.428093] bnx2 0000:04:00.0: firmware: requesting bnx2/bnx2-rv2p-06-5.0.0.j3.fw
> [    2.432526] eth0: Broadcom NetXtreme II BCM5708 1000Base-T (B2) PCI-X 64-bit 133MHz found at mem f6000000, IRQ 41, node addr 00:1c:c4:e1:cc:ea
> [    2.439520] bnx2 0000:42:00.0: PCI INT A -> GSI 34 (level, low) -> IRQ 34
> 
> lspci shows this is a HP 373i, it's the onboard NIC.
> 
> Running this on one particular system I get:
> 
> Mar 10 07:48:58 N1002563 kernel: [  870.780023] ------------[ cut here ]------------
> Mar 10 07:48:58 N1002563 kernel: [  870.780037] WARNING: at net/sched/sch_generic.c:261 dev_watchdog+0x12d/0x1d5()
> Mar 10 07:48:58 N1002563 kernel: [  870.780041] Hardware name: ProLiant DL385 G5 
> Mar 10 07:48:58 N1002563 kernel: [  870.780046] NETDEV WATCHDOG: eth0 (bnx2): transmit queue 0 timed out
> Mar 10 07:48:58 N1002563 kernel: [  870.780050] Modules linked in: mptctl ipmi_devintf deflate zlib_deflate ctr twofish twofish_common camellia serpent blowfish cast5 des_generic cbc cryptd aes_x86_64 aes_generic xcbc rmd160 sha256_generic sha1_generic crypto_null af_key sg bonding sctp crc32c libcrc32c loop psmouse serio_raw container amd64_edac_mod edac_core i2c_piix4 shpchp pci_hotplug ipmi_si i2c_core ipmi_msghandler hpilo processor evdev ext3 jbd mbcache sd_mod crc_t10dif usbhid hid ata_generic libata ide_pci_generic e1000e bnx2 mptsas mptscsih mptbase serverworks scsi_transport_sas ide_core ehci_hcd scsi_mod ohci_hcd uhci_hcd button thermal fan thermal_sys edd [last unloaded: scsi_wait_scan]
> Mar 10 07:48:58 N1002563 kernel: [  870.780133] Pid: 0, comm: swapper Not tainted 2.6.32-clim-4-amd64 #1
> Mar 10 07:48:58 N1002563 kernel: [  870.780137] Call Trace:
> Mar 10 07:48:58 N1002563 kernel: [  870.780141]  <IRQ>  [<ffffffff812697a0>] ? dev_watchdog+0x12d/0x1d5
> Mar 10 07:48:58 N1002563 kernel: [  870.780156]  [<ffffffff81049914>] warn_slowpath_common+0x77/0xa4
> Mar 10 07:48:58 N1002563 kernel: [  870.780170]  [<ffffffff810499b6>] warn_slowpath_fmt+0x64/0x66
> Mar 10 07:48:58 N1002563 kernel: [  870.780177]  [<ffffffff81045df7>] ? default_wake_function+0xd/0xf
> Mar 10 07:48:58 N1002563 kernel: [  870.780184]  [<ffffffff81035fa7>] ? __wake_up_common+0x46/0x76
> Mar 10 07:48:58 N1002563 kernel: [  870.780191]  [<ffffffff8103b414>] ? __wake_up+0x43/0x50
> Mar 10 07:48:58 N1002563 kernel: [  870.780198]  [<ffffffff81253829>] ? netdev_drivername+0x43/0x4b
> Mar 10 07:48:58 N1002563 kernel: [  870.780204]  [<ffffffff812697a0>] dev_watchdog+0x12d/0x1d5
> Mar 10 07:48:58 N1002563 kernel: [  870.780214]  [<ffffffff8105e84a>] ? delayed_work_timer_fn+0x0/0x3d
> Mar 10 07:48:58 N1002563 kernel: [  870.780219]  [<ffffffff8105e7ee>] ? __queue_work+0x35/0x3d
> Mar 10 07:48:58 N1002563 kernel: [  870.780227]  [<ffffffff81269673>] ? dev_watchdog+0x0/0x1d5
> Mar 10 07:48:58 N1002563 kernel: [  870.780234]  [<ffffffff8105655a>] run_timer_softirq+0x1ff/0x2a1
> Mar 10 07:48:58 N1002563 kernel: [  870.780242]  [<ffffffff810205a1>] ? lapic_next_event+0x18/0x1c
> Mar 10 07:48:58 N1002563 kernel: [  870.780249]  [<ffffffff8104f9e3>] __do_softirq+0xde/0x19f
> Mar 10 07:48:58 N1002563 kernel: [  870.780256]  [<ffffffff8100ccec>] call_softirq+0x1c/0x28
> Mar 10 07:48:58 N1002563 kernel: [  870.780262]  [<ffffffff8100e8b1>] do_softirq+0x41/0x81
> Mar 10 07:48:58 N1002563 kernel: [  870.780268]  [<ffffffff8104f7bd>] irq_exit+0x36/0x75
> Mar 10 07:48:58 N1002563 kernel: [  870.780274]  [<ffffffff81020f33>] smp_apic_timer_interrupt+0x88/0x96
> Mar 10 07:48:58 N1002563 kernel: [  870.780287]  [<ffffffff8100c6b3>] apic_timer_interrupt+0x13/0x20
> Mar 10 07:48:58 N1002563 kernel: [  870.780291]  <EOI>  [<ffffffff81027740>] ? native_safe_halt+0x6/0x8
> Mar 10 07:48:58 N1002563 kernel: [  870.780304]  [<ffffffff81012da3>] ? default_idle+0x55/0x74
> Mar 10 07:48:58 N1002563 kernel: [  870.780309]  [<ffffffff810131ce>] ? c1e_idle+0xf4/0xfb
> Mar 10 07:48:58 N1002563 kernel: [  870.780315]  [<ffffffff81065529>] ? atomic_notifier_call_chain+0x13/0x15
> Mar 10 07:48:58 N1002563 kernel: [  870.780321]  [<ffffffff8100aeec>] ? cpu_idle+0x5b/0x93
> Mar 10 07:48:58 N1002563 kernel: [  870.780329]  [<ffffffff81304144>] ? start_secondary+0x1a8/0x1ac
> Mar 10 07:48:58 N1002563 kernel: [  870.780334] ---[ end trace 08b420ca1e09a176 ]---
> Mar 10 07:48:58 N1002563 kernel: [  870.780339] bnx2: eth0 DEBUG: intr_sem[0]
> Mar 10 07:48:58 N1002563 kernel: [  870.780345] bnx2: eth0 DEBUG: EMAC_TX_STATUS[00000008] RPM_MGMT_PKT_CTRL[00000000]
> Mar 10 07:48:58 N1002563 kernel: [  870.780352] bnx2: eth0 DEBUG: MCP_STATE_P0[00000000] MCP_STATE_P1[00000000]
> Mar 10 07:48:58 N1002563 kernel: [  870.780357] bnx2: eth0 DEBUG: HC_STATS_INTERRUPT_STATUS[00000000]
> Mar 10 07:49:03 N1002563 kernel: [  875.780020] bnx2: eth0 DEBUG: intr_sem[0]
> Mar 10 07:49:03 N1002563 kernel: [  875.780026] bnx2: eth0 DEBUG: EMAC_TX_STATUS[00000008] RPM_MGMT_PKT_CTRL[00000000]
> Mar 10 07:49:03 N1002563 kernel: [  875.780038] bnx2: eth0 DEBUG: MCP_STATE_P0[00000000] MCP_STATE_P1[00000000]
> Mar 10 07:49:03 N1002563 kernel: [  875.780043] bnx2: eth0 DEBUG: HC_STATS_INTERRUPT_STATUS[00000000]
> 
> This debug message would repeat every 5 seconds, eventually
> the systems locks-up.
> 
> This is running a 2.6.32-8 stable kernel, I've tried a version with Ben's
> patch from this thread installed with no change in behavior.  I'm in the
> process of backporting all the upstream changes to see if that helps.
> 
> Guessing it's a race condition caused by these calls in bnx2_set_coalesce():
> 
>         if (netif_running(bp->dev)) {
>                 bnx2_netif_stop(bp);
>                 bnx2_init_nic(bp, 0);
>                 bnx2_netif_start(bp);
>         }
> 
> Thanks for any help,
> 
> -Brian
> 

^ permalink raw reply

* Re: BNX2: Kernel crashes with 2.6.31 and 2.6.31.9
From: Brian Haley @ 2010-03-11  2:09 UTC (permalink / raw)
  To: Michael Chan; +Cc: Bruno Prémont, Benjamin Li, NetDEV, Linux-Kernel
In-Reply-To: <1268263973.9775.95.camel@nseg_linux_HP1.broadcom.com>

Michael Chan wrote:
> On Wed, 2010-03-10 at 15:09 -0800, Brian Haley wrote:
>> Brian Haley wrote:
>>> Hi Michael,
>>>
>>> Michael Chan wrote:
>>>> Do we have timers running in this environment?  The timer in the bnx2
>>>> driver, bnx2_timer(), needs to run to provide a heart beat to the
>>>> firmware.  In netpoll mode without timer interrupts, if we are regularly
>>>> calling the NAPI poll function, it should also be able to provide the
>>>> heartbeat.  Without the heartbeat, the firmware will reset the chip and
>>>> result in the NETDEV WATCHDOG.
>>> We have also been seeing watchdog timeouts with bnx2, below is a
>>> stack trace with Benjamin's debug patch applied.  Normally we were
>>> only seeing them under heavy load, but this one was at boot.  We haven't
>>> tried the latest firmware/driver from 2.6.33 yet.  You can contact me
>>> offline if you need more detailed info.
>> Following-up since I have more info on this issue.
>>
>> I'm able to cause a netdev_watchdog timeout by changing the coalesce
>> settings on my bnx2, I built a little test program for it:
> 
> Do you run this program in a loop?  How quickly do you see the NETDEV
> WATCHDOG?

It's run once, and we see it almost immediately after ETHTOOL_SCOALESCE.

>> 	ecoal.rx_coalesce_usecs = 0;
>> 	ecoal.rx_max_coalesced_frames = 1;
>> 	ecoal.rx_coalesce_usecs_irq = 0;
>> 	ecoal.rx_max_coalesced_frames_irq = 1;
> 
> These rx settings should be ok.  Did you change the tx settings?  If the
> tx settings are all zeros, you won't get any TX interrupts and you can
> get a NETDEV WATCHDOG.

We did the read, so the TX should be what it was originally.

> Run ethtool -c eth0 to see what the tx settings are.  Thanks.

# ethtool -c eth0
Coalesce parameters for eth0:
Adaptive RX: off  TX: off
stats-block-usecs: 999936
sample-interval: 0
pkt-rate-low: 0
pkt-rate-high: 0

rx-usecs: 0
rx-frames: 1
rx-usecs-irq: 0
rx-frames-irq: 1

tx-usecs: 80
tx-frames: 20
tx-usecs-irq: 18
tx-frames-irq: 2

rx-usecs-low: 0
rx-frame-low: 0
tx-usecs-low: 0
tx-frame-low: 0

rx-usecs-high: 0
rx-frame-high: 0
tx-usecs-high: 0
tx-frame-high: 0

If I run 'ethtool -c eth0' after the watchdog triggers either the NIC
or system completely hangs.

-Brian

^ permalink raw reply

* [PATCH v6] rps: Receive Packet Steering
From: Tom Herbert @ 2010-03-11  7:00 UTC (permalink / raw)
  To: davem, netdev; +Cc: bhutchings, shemminger, eric.dumazet

Added explicit entries entries in sysfs to set RPS cpus for each device queue.  This includes:

- Create RX queue instances which are attached to each netdevice (netdev_rx_queue).  These are analogous to the netdev_queue structures which are used for transmit.  RX queue instances hold an rps_map.
- RX queues are allocated in alloc_netdev_mq for the given queue_count (basically we're assuming #RX queues == #TX queues).  If a driver does not call alloc_netdev_mq, a single instance is created in register_netdevice.
- Added subdrectories in sysfs for per-queue RPS settings.  These are in /sys/class/net/eth<n>/queues/rx-<n>.  The "queues" directory is not necessary, but keeps the eth<n> directory clean (I don't have a stong opinion on this).  Presumably, if TX queues needed entries that could go under tx-<n>

Also addessed some previous issues raised:
- Copy rxhash in skb_clone
- Took __netif_receive_skb out of kernel-doc
- Removed VLA containing VLA ugliness (rx queues above fixed that)
- Copy and clear rps_mask before calling net_rps_action


diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index c79a88b..468da0a 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -223,6 +223,7 @@ struct netif_rx_stats {
 	unsigned dropped;
 	unsigned time_squeeze;
 	unsigned cpu_collision;
+	unsigned received_rps;
 };
 
 DECLARE_PER_CPU(struct netif_rx_stats, netdev_rx_stat);
@@ -530,6 +531,22 @@ struct netdev_queue {
 	unsigned long		tx_dropped;
 } ____cacheline_aligned_in_smp;
 
+/*
+ * This structure holds an RPS map which can be of variable length.  The
+ * map is an array of CPUs.
+ */
+struct rps_map {
+	unsigned int len;
+	struct rcu_head rcu;
+	u16 cpus[0];
+};
+#define RPS_MAP_SIZE(_num) (sizeof(struct rps_map) + (_num * sizeof(u16)))
+
+/* This structure contains an instance of an RX queue. */
+struct netdev_rx_queue {
+	struct kobject kobj;
+	struct rps_map *rps_map;
+} ____cacheline_aligned_in_smp;
 
 /*
  * This structure defines the management hooks for network devices.
@@ -878,6 +895,13 @@ struct net_device {
 
 	unsigned char		broadcast[MAX_ADDR_LEN];	/* hw bcast add	*/
 
+	struct kset		*queues_kset;
+
+	struct netdev_rx_queue	**_rx;
+
+	/* Number of RX queues allocated at alloc_netdev_mq() time  */
+	unsigned int		num_rx_queues;
+
 	struct netdev_queue	rx_queue;
 
 	struct netdev_queue	*_tx ____cacheline_aligned_in_smp;
@@ -1311,14 +1335,16 @@ static inline int unregister_gifconf(unsigned int family)
  */
 struct softnet_data {
 	struct Qdisc		*output_queue;
-	struct sk_buff_head	input_pkt_queue;
 	struct list_head	poll_list;
 	struct sk_buff		*completion_queue;
 
+	/* Elements below can be accessed between CPUs for RPS */
+	struct call_single_data	csd ____cacheline_aligned_in_smp;
+	struct sk_buff_head	input_pkt_queue;
 	struct napi_struct	backlog;
 };
 
-DECLARE_PER_CPU(struct softnet_data,softnet_data);
+DECLARE_PER_CPU_ALIGNED(struct softnet_data, softnet_data);
 
 #define HAVE_NETIF_QUEUE
 
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 03f816a..58e1dda 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -267,6 +267,7 @@ typedef unsigned char *sk_buff_data_t;
  *	@mac_header: Link layer header
  *	@_skb_dst: destination entry
  *	@sp: the security path, used for xfrm
+ *	@rxhash: the packet hash computed on receive
  *	@cb: Control buffer. Free for use by every layer. Put private vars here
  *	@len: Length of actual data
  *	@data_len: Data length
@@ -320,6 +321,8 @@ struct sk_buff {
 	struct sock		*sk;
 	struct net_device	*dev;
 
+	__u32			rxhash;
+
 	/*
 	 * This is the control buffer. It is free to use for every
 	 * layer. Please put your private variables there. If you
diff --git a/net/core/dev.c b/net/core/dev.c
index bcc490c..939b1a2 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1931,7 +1931,7 @@ out_kfree_skb:
 	return rc;
 }
 
-static u32 skb_tx_hashrnd;
+static u32 hashrnd __read_mostly;
 
 u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb)
 {
@@ -1949,7 +1949,7 @@ u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb)
 	else
 		hash = skb->protocol;
 
-	hash = jhash_1word(hash, skb_tx_hashrnd);
+	hash = jhash_1word(hash, hashrnd);
 
 	return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32);
 }
@@ -2175,6 +2175,157 @@ int weight_p __read_mostly = 64;            /* old backlog weight */
 
 DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, };
 
+/*
+ * get_rps_cpu is called from netif_receive_skb and returns the target
+ * CPU from the RPS map of the receiving queue for a given skb.
+ */
+static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb)
+{
+	struct ipv6hdr *ip6;
+	struct iphdr *ip;
+	struct netdev_rx_queue *rxqueue;
+	struct rps_map *map;
+	int cpu = -1;
+	u8 ip_proto;
+	u32 addr1, addr2, ports, ihl;
+
+	rcu_read_lock();
+
+	if (skb_rx_queue_recorded(skb)) {
+		u16 index = skb_get_rx_queue(skb);
+		if (unlikely(index >= dev->num_rx_queues)) {
+			if (net_ratelimit()) {
+				WARN(1, "Recieved packet on %s for queue %u, "
+				    "but number of RX queues is %u\n",
+				     dev->name, index, dev->num_rx_queues);
+			}
+			goto done;
+		}
+		rxqueue = dev->_rx[index];
+	} else
+		rxqueue = dev->_rx[0];
+
+	if (!rxqueue->rps_map)
+		goto done;
+
+	if (skb->rxhash)
+		goto got_hash; /* Skip hash computation on packet header */
+
+	switch (skb->protocol) {
+	case __constant_htons(ETH_P_IP):
+		if (!pskb_may_pull(skb, sizeof(*ip)))
+			goto done;
+
+		ip = (struct iphdr *) skb->data;
+		ip_proto = ip->protocol;
+		addr1 = ip->saddr;
+		addr2 = ip->daddr;
+		ihl = ip->ihl;
+		break;
+	case __constant_htons(ETH_P_IPV6):
+		if (!pskb_may_pull(skb, sizeof(*ip6)))
+			goto done;
+
+		ip6 = (struct ipv6hdr *) skb->data;
+		ip_proto = ip6->nexthdr;
+		addr1 = ip6->saddr.s6_addr32[3];
+		addr2 = ip6->daddr.s6_addr32[3];
+		ihl = (40 >> 2);
+		break;
+	default:
+		goto done;
+	}
+	ports = 0;
+	switch (ip_proto) {
+	case IPPROTO_TCP:
+	case IPPROTO_UDP:
+	case IPPROTO_DCCP:
+	case IPPROTO_ESP:
+	case IPPROTO_AH:
+	case IPPROTO_SCTP:
+	case IPPROTO_UDPLITE:
+		if (pskb_may_pull(skb, (ihl * 4) + 4))
+			ports = *((u32 *) (skb->data + (ihl * 4)));
+		break;
+
+	default:
+		break;
+	}
+
+	skb->rxhash = jhash_3words(addr1, addr2, ports, hashrnd);
+	if (!skb->rxhash)
+		skb->rxhash = 1;
+
+got_hash:
+	map = rcu_dereference(rxqueue->rps_map);
+	if (map) {
+		u16 tcpu = map->cpus[((u64) skb->rxhash * map->len) >> 32];
+
+		if (cpu_online(tcpu)) {
+			cpu = tcpu;
+			goto done;
+		}
+	}
+
+done:
+	rcu_read_unlock();
+	return cpu;
+}
+
+static DEFINE_PER_CPU(cpumask_t, rps_remote_softirq_cpus);
+
+/* Called from hardirq (IPI) context */
+static void trigger_softirq(void *data)
+{
+	struct softnet_data *queue = data;
+	__napi_schedule(&queue->backlog);
+	__get_cpu_var(netdev_rx_stat).received_rps++;
+}
+
+/*
+ * enqueue_to_backlog is called to queue an skb to a per CPU backlog
+ * queue (may be a remote CPU queue).
+ */
+static int enqueue_to_backlog(struct sk_buff *skb, int cpu)
+{
+	struct softnet_data *queue;
+	unsigned long flags;
+
+	queue = &per_cpu(softnet_data, cpu);
+
+	local_irq_save(flags);
+	__get_cpu_var(netdev_rx_stat).total++;
+
+	spin_lock(&queue->input_pkt_queue.lock);
+	if (queue->input_pkt_queue.qlen <= netdev_max_backlog) {
+		if (queue->input_pkt_queue.qlen) {
+enqueue:
+			__skb_queue_tail(&queue->input_pkt_queue, skb);
+			spin_unlock_irqrestore(&queue->input_pkt_queue.lock,
+			    flags);
+			return NET_RX_SUCCESS;
+		}
+
+		/* Schedule NAPI for backlog device */
+		if (napi_schedule_prep(&queue->backlog)) {
+			if (cpu != smp_processor_id()) {
+				cpu_set(cpu,
+				    __get_cpu_var(rps_remote_softirq_cpus));
+				__raise_softirq_irqoff(NET_RX_SOFTIRQ);
+			} else
+				__napi_schedule(&queue->backlog);
+		}
+		goto enqueue;
+	}
+
+	spin_unlock(&queue->input_pkt_queue.lock);
+
+	__get_cpu_var(netdev_rx_stat).dropped++;
+	local_irq_restore(flags);
+
+	kfree_skb(skb);
+	return NET_RX_DROP;
+}
 
 /**
  *	netif_rx	-	post buffer to the network code
@@ -2193,8 +2344,7 @@ DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, };
 
 int netif_rx(struct sk_buff *skb)
 {
-	struct softnet_data *queue;
-	unsigned long flags;
+	int cpu;
 
 	/* if netpoll wants it, pretend we never saw it */
 	if (netpoll_rx(skb))
@@ -2203,31 +2353,11 @@ int netif_rx(struct sk_buff *skb)
 	if (!skb->tstamp.tv64)
 		net_timestamp(skb);
 
-	/*
-	 * The code is rearranged so that the path is the most
-	 * short when CPU is congested, but is still operating.
-	 */
-	local_irq_save(flags);
-	queue = &__get_cpu_var(softnet_data);
-
-	__get_cpu_var(netdev_rx_stat).total++;
-	if (queue->input_pkt_queue.qlen <= netdev_max_backlog) {
-		if (queue->input_pkt_queue.qlen) {
-enqueue:
-			__skb_queue_tail(&queue->input_pkt_queue, skb);
-			local_irq_restore(flags);
-			return NET_RX_SUCCESS;
-		}
-
-		napi_schedule(&queue->backlog);
-		goto enqueue;
-	}
-
-	__get_cpu_var(netdev_rx_stat).dropped++;
-	local_irq_restore(flags);
+	cpu = get_rps_cpu(skb->dev, skb);
+	if (cpu < 0)
+		cpu = smp_processor_id();
 
-	kfree_skb(skb);
-	return NET_RX_DROP;
+	return enqueue_to_backlog(skb, cpu);
 }
 EXPORT_SYMBOL(netif_rx);
 
@@ -2464,22 +2594,7 @@ void netif_nit_deliver(struct sk_buff *skb)
 	rcu_read_unlock();
 }
 
-/**
- *	netif_receive_skb - process receive buffer from network
- *	@skb: buffer to process
- *
- *	netif_receive_skb() is the main receive data processing function.
- *	It always succeeds. The buffer may be dropped during processing
- *	for congestion control or by the protocol layers.
- *
- *	This function may only be called from softirq context and interrupts
- *	should be enabled.
- *
- *	Return values (usually ignored):
- *	NET_RX_SUCCESS: no congestion
- *	NET_RX_DROP: packet was dropped
- */
-int netif_receive_skb(struct sk_buff *skb)
+int __netif_receive_skb(struct sk_buff *skb)
 {
 	struct packet_type *ptype, *pt_prev;
 	struct net_device *orig_dev;
@@ -2588,6 +2703,33 @@ out:
 	rcu_read_unlock();
 	return ret;
 }
+
+/**
+ *	netif_receive_skb - process receive buffer from network
+ *	@skb: buffer to process
+ *
+ *	netif_receive_skb() is the main receive data processing function.
+ *	It always succeeds. The buffer may be dropped during processing
+ *	for congestion control or by the protocol layers.
+ *
+ *	This function may only be called from softirq context and interrupts
+ *	should be enabled.
+ *
+ *	Return values (usually ignored):
+ *	NET_RX_SUCCESS: no congestion
+ *	NET_RX_DROP: packet was dropped
+ */
+int netif_receive_skb(struct sk_buff *skb)
+{
+	int cpu;
+
+	cpu = get_rps_cpu(skb->dev, skb);
+
+	if (cpu < 0)
+		return __netif_receive_skb(skb);
+	else
+		return enqueue_to_backlog(skb, cpu);
+}
 EXPORT_SYMBOL(netif_receive_skb);
 
 /* Network device is going away, flush any packets still pending  */
@@ -2914,16 +3056,16 @@ static int process_backlog(struct napi_struct *napi, int quota)
 	do {
 		struct sk_buff *skb;
 
-		local_irq_disable();
+		spin_lock_irq(&queue->input_pkt_queue.lock);
 		skb = __skb_dequeue(&queue->input_pkt_queue);
 		if (!skb) {
 			__napi_complete(napi);
-			local_irq_enable();
+			spin_unlock_irq(&queue->input_pkt_queue.lock);
 			break;
 		}
-		local_irq_enable();
+		spin_unlock_irq(&queue->input_pkt_queue.lock);
 
-		netif_receive_skb(skb);
+		__netif_receive_skb(skb);
 	} while (++work < quota && jiffies == start_time);
 
 	return work;
@@ -3012,6 +3154,21 @@ void netif_napi_del(struct napi_struct *napi)
 }
 EXPORT_SYMBOL(netif_napi_del);
 
+/*
+ * net_rps_action sends any pending IPI's for rps.  This is only called from
+ * softirq and interrupts must be enabled.
+ */
+static void net_rps_action(cpumask_t *mask)
+{
+	int cpu;
+
+	/* Send pending IPI's to kick RPS processing on remote cpus. */
+	for_each_cpu_mask_nr(cpu, *mask) {
+		struct softnet_data *queue = &per_cpu(softnet_data, cpu);
+		if (cpu_online(cpu))
+			__smp_call_function_single(cpu, &queue->csd, 0);
+	}
+}
 
 static void net_rx_action(struct softirq_action *h)
 {
@@ -3019,6 +3176,7 @@ static void net_rx_action(struct softirq_action *h)
 	unsigned long time_limit = jiffies + 2;
 	int budget = netdev_budget;
 	void *have;
+	cpumask_t rps_mask;
 
 	local_irq_disable();
 
@@ -3081,8 +3239,13 @@ static void net_rx_action(struct softirq_action *h)
 		netpoll_poll_unlock(have);
 	}
 out:
+	cpumask_copy(&rps_mask, &__get_cpu_var(rps_remote_softirq_cpus));
+	cpus_clear(__get_cpu_var(rps_remote_softirq_cpus));
+
 	local_irq_enable();
 
+	net_rps_action(&rps_mask);
+
 #ifdef CONFIG_NET_DMA
 	/*
 	 * There may not be any more sk_buffs coming right now, so push
@@ -3327,10 +3490,10 @@ static int softnet_seq_show(struct seq_file *seq, void *v)
 {
 	struct netif_rx_stats *s = v;
 
-	seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
+	seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
 		   s->total, s->dropped, s->time_squeeze, 0,
 		   0, 0, 0, 0, /* was fastroute */
-		   s->cpu_collision);
+		   s->cpu_collision, s->received_rps);
 	return 0;
 }
 
@@ -5067,6 +5230,29 @@ int register_netdevice(struct net_device *dev)
 
 	dev->iflink = -1;
 
+	if (!dev->num_rx_queues) {
+		/*
+		 * Allocate a single RX queue if driver never called
+		 * alloc_netdev_mq
+		 */
+
+		dev->_rx = kzalloc(sizeof(struct netdev_rx_queue *),
+		    GFP_KERNEL);
+		if (!dev->_rx) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		dev->_rx[0] = kzalloc(sizeof(struct netdev_rx_queue),
+		    GFP_KERNEL);
+		if (!dev->_rx[0]) {
+			kfree(dev->_rx);
+			ret = -ENOMEM;
+			goto out;
+		}
+		dev->num_rx_queues = 1;
+	}
+
 	/* Init, if this function is available */
 	if (dev->netdev_ops->ndo_init) {
 		ret = dev->netdev_ops->ndo_init(dev);
@@ -5424,9 +5610,11 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
 		void (*setup)(struct net_device *), unsigned int queue_count)
 {
 	struct netdev_queue *tx;
+	struct netdev_rx_queue **rx;
 	struct net_device *dev;
 	size_t alloc_size;
 	struct net_device *p;
+	int i;
 
 	BUG_ON(strlen(name) >= sizeof(dev->name));
 
@@ -5452,6 +5640,27 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
 		goto free_p;
 	}
 
+	/*
+	 * Allocate RX queue structures, this includes an array of pointers
+	 * and netdev_queue_rx stuctures (individually allocated since
+	 * each has a kobject).
+	 */
+	rx = kzalloc(queue_count *
+	    sizeof(struct netdev_rx_queue *), GFP_KERNEL);
+	if (!rx) {
+		printk(KERN_ERR "alloc_netdev: Unable to allocate "
+		       "rx queues array.\n");
+		goto free_tx;
+	}
+	for (i = 0; i < queue_count; i++) {
+		rx[i] = kzalloc(sizeof(struct netdev_rx_queue), GFP_KERNEL);
+		if (!rx[i]) {
+			printk(KERN_ERR "alloc_netdev: Unable to allocate "
+			    "rx queues.\n");
+			goto free_rx;
+		}
+	}
+
 	dev = PTR_ALIGN(p, NETDEV_ALIGN);
 	dev->padded = (char *)dev - (char *)p;
 
@@ -5466,6 +5675,9 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
 	dev->num_tx_queues = queue_count;
 	dev->real_num_tx_queues = queue_count;
 
+	dev->_rx = rx;
+	dev->num_rx_queues = queue_count;
+
 	dev->gso_max_size = GSO_MAX_SIZE;
 
 	netdev_init_queues(dev);
@@ -5480,9 +5692,12 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
 	strcpy(dev->name, name);
 	return dev;
 
+free_rx:
+	for (i = 0; i < queue_count; i++)
+		kfree(rx[i]);
+	kfree(rx);
 free_tx:
 	kfree(tx);
-
 free_p:
 	kfree(p);
 	return NULL;
@@ -5505,6 +5720,12 @@ void free_netdev(struct net_device *dev)
 
 	kfree(dev->_tx);
 
+	/*
+	 * Free RX queue pointer array.  Actual netdev_rx_queue objects are
+	 * freed by kobject release.
+	 */
+	kfree(dev->_rx);
+
 	/* Flush device addresses */
 	dev_addr_flush(dev);
 
@@ -5985,6 +6206,10 @@ static int __init net_dev_init(void)
 		queue->completion_queue = NULL;
 		INIT_LIST_HEAD(&queue->poll_list);
 
+		queue->csd.func = trigger_softirq;
+		queue->csd.info = queue;
+		queue->csd.flags = 0;
+
 		queue->backlog.poll = process_backlog;
 		queue->backlog.weight = weight_p;
 		queue->backlog.gro_list = NULL;
@@ -6023,7 +6248,7 @@ subsys_initcall(net_dev_init);
 
 static int __init initialize_hashrnd(void)
 {
-	get_random_bytes(&skb_tx_hashrnd, sizeof(skb_tx_hashrnd));
+	get_random_bytes(&hashrnd, sizeof(hashrnd));
 	return 0;
 }
 
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 099c753..a07d6ec 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -466,6 +466,196 @@ static struct attribute_group wireless_group = {
 };
 #endif
 
+/*
+ * RX queue sysfs structures and functions.
+ */
+struct rx_queue_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct netdev_rx_queue *queue,
+	    struct rx_queue_attribute *attr, char *buf);
+	ssize_t (*store)(struct netdev_rx_queue *queue,
+	    struct rx_queue_attribute *attr, const char *buf, size_t len);
+};
+#define to_rx_queue_attr(_attr) container_of(_attr,		\
+    struct rx_queue_attribute, attr)
+
+#define to_rx_queue(obj) container_of(obj, struct netdev_rx_queue, kobj)
+
+static ssize_t rx_queue_attr_show(struct kobject *kobj, struct attribute *attr,
+				  char *buf)
+{
+	struct rx_queue_attribute *attribute = to_rx_queue_attr(attr);
+	struct netdev_rx_queue *queue = to_rx_queue(kobj);
+
+	if (!attribute->show)
+		return -EIO;
+
+	return attribute->show(queue, attribute, buf);
+}
+
+static ssize_t rx_queue_attr_store(struct kobject *kobj, struct attribute *attr,
+				   const char *buf, size_t count)
+{
+	struct rx_queue_attribute *attribute = to_rx_queue_attr(attr);
+	struct netdev_rx_queue *queue = to_rx_queue(kobj);
+
+	if (!attribute->store)
+		return -EIO;
+
+	return attribute->store(queue, attribute, buf, count);
+}
+
+static struct sysfs_ops rx_queue_sysfs_ops = {
+	.show = rx_queue_attr_show,
+	.store = rx_queue_attr_store,
+};
+
+static ssize_t show_rps_map(struct netdev_rx_queue *queue,
+			    struct rx_queue_attribute *attribute, char *buf)
+{
+	size_t len = 0;
+	struct rps_map *map;
+	int i;
+	cpumask_t mask;
+
+	cpus_clear(mask);
+
+	rcu_read_lock();
+	map = rcu_dereference(queue->rps_map);
+	if (map) {
+		for (i = 0; i < map->len; i++)
+			cpu_set(map->cpus[i], mask);
+
+		len += cpumask_scnprintf(buf + len, PAGE_SIZE, &mask);
+		if (PAGE_SIZE - len < 3) {
+			rcu_read_unlock();
+			return -EINVAL;
+		}
+	}
+	rcu_read_unlock();
+
+	len += sprintf(buf + len, "\n");
+	return len;
+}
+
+static void rps_map_release(struct rcu_head *rcu)
+{
+	struct rps_map *map = container_of(rcu, struct rps_map, rcu);
+
+	kfree(map);
+}
+
+ssize_t store_rps_map(struct netdev_rx_queue *queue,
+		      struct rx_queue_attribute *attribute,
+		      const char *buf, size_t len)
+{
+	struct rps_map *old_map, *map;
+	cpumask_t mask;
+	int err, cpu, i, weight;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	err = bitmap_parse(buf, len, cpumask_bits(&mask), nr_cpumask_bits);
+	if (err)
+		return err;
+
+	weight = cpumask_weight(&mask);
+	if (weight) {
+		map = kzalloc(RPS_MAP_SIZE(weight), GFP_KERNEL);
+		if (!map)
+			return -ENOMEM;
+
+		cpus_and(mask, mask, cpu_online_map);
+		i = 0;
+		for_each_cpu_mask(cpu, mask)
+			map->cpus[i++] = cpu;
+		map->len = i;
+	} else
+		map = NULL;
+
+	rtnl_lock();
+	old_map = queue->rps_map;
+	rcu_assign_pointer(queue->rps_map, map);
+	rtnl_unlock();
+
+	if (old_map)
+		call_rcu(&old_map->rcu, rps_map_release);
+
+	return len;
+}
+
+static struct rx_queue_attribute rps_cpus_attribute =
+	__ATTR(rps_cpus, S_IRUGO | S_IWUSR, show_rps_map, store_rps_map);
+
+static struct attribute *rx_queue_default_attrs[] = {
+	&rps_cpus_attribute.attr,
+	NULL
+};
+
+static void rx_queue_release(struct kobject *kobj)
+{
+	struct netdev_rx_queue *queue = to_rx_queue(kobj);
+
+	kfree(queue);
+}
+
+static struct kobj_type rx_queue_ktype = {
+	.sysfs_ops = &rx_queue_sysfs_ops,
+	.release = rx_queue_release,
+	.default_attrs = rx_queue_default_attrs,
+};
+
+static int rx_queue_add_kobject(struct net_device *net, int index)
+{
+	int error = 0;
+	struct netdev_rx_queue *queue = net->_rx[index];
+	struct kobject *kobj = &queue->kobj;
+
+	kobj->kset = net->queues_kset;
+	error = kobject_init_and_add(kobj, &rx_queue_ktype, NULL,
+	    "rx-%u", index);
+	if (error) {
+		kobject_put(kobj);
+		return error;
+	}
+
+	kobject_uevent(kobj, KOBJ_ADD);
+
+	return error;
+}
+
+static int rx_queue_register_kobjects(struct net_device *net)
+{
+	int error = 0;
+	int i;
+
+	net->queues_kset = kset_create_and_add("queues",
+	    NULL, &net->dev.kobj);
+	if (!net->queues_kset)
+		return -ENOMEM;
+	for (i = 0; i < net->num_rx_queues; i++) {
+		error = rx_queue_add_kobject(net, i);
+		if (error)
+			break;
+	}
+
+	if (error)
+		while (--i >= 0)
+			kobject_put(&net->_rx[i]->kobj);
+
+	return error;
+}
+
+static void rx_queue_remove_kobjects(struct net_device *net)
+{
+	int i;
+
+	for (i = 0; i < net->num_rx_queues; i++)
+		kobject_put(&net->_rx[i]->kobj);
+	kset_unregister(net->queues_kset);
+}
+
 #endif /* CONFIG_SYSFS */
 
 #ifdef CONFIG_HOTPLUG
@@ -529,12 +719,15 @@ void netdev_unregister_kobject(struct net_device * net)
 	if (!net_eq(dev_net(net), &init_net))
 		return;
 
+	rx_queue_remove_kobjects(net);
+
 	device_del(dev);
 }
 
 /* Create sysfs entries for network device. */
 int netdev_register_kobject(struct net_device *net)
 {
+	int error = 0;
 	struct device *dev = &(net->dev);
 	const struct attribute_group **groups = net->sysfs_groups;
 
@@ -563,7 +756,17 @@ int netdev_register_kobject(struct net_device *net)
 	if (!net_eq(dev_net(net), &init_net))
 		return 0;
 
-	return device_add(dev);
+	error = device_add(dev);
+	if (error)
+		return error;
+
+	error = rx_queue_register_kobjects(net);
+	if (error) {
+		device_del(dev);
+		return error;
+	}
+
+	return error;
 }
 
 int netdev_class_create_file(struct class_attribute *class_attr)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 93c4e06..472c767 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -581,6 +581,7 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
 	C(len);
 	C(data_len);
 	C(mac_len);
+	C(rxhash);
 	n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
 	n->cloned = 1;
 	n->nohdr = 0;

^ permalink raw reply related

* Re: [Bonding-devel] [net-next-2.6 PATCH 2/3] bonding: check return value of nofitier when changing type
From: Jiri Pirko @ 2010-03-11  7:59 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev, kaber, fubar, bonding-devel, davem
In-Reply-To: <20100310144710.605ef033@nehalam>

Wed, Mar 10, 2010 at 11:47:10PM CET, shemminger@linux-foundation.org wrote:
>On Wed, 10 Mar 2010 21:29:35 +0100
>Jiri Pirko <jpirko@redhat.com> wrote:
>
>> diff --git a/net/core/dev.c b/net/core/dev.c
>> index bcc490c..5de4a15 100644
>> --- a/net/core/dev.c
>> +++ b/net/core/dev.c
>> @@ -1084,9 +1084,9 @@ void netdev_state_change(struct net_device *dev)
>>  }
>>  EXPORT_SYMBOL(netdev_state_change);
>>  
>> -void netdev_bonding_change(struct net_device *dev, unsigned long event)
>> +int netdev_bonding_change(struct net_device *dev, unsigned long event)
>>  {
>> -	call_netdevice_notifiers(event, dev);
>> +	return call_netdevice_notifiers(event, dev);
>>  }
>>  EXPORT_SYMBOL(netdev_bonding_change);
>>  
>
>I don't think all this pre-post stuff needed.
>Since this is general (not just bonding) how about

Well actually I reused NETDEV_BONDING_OLDTYPE. This and NETDEV_BONDING_NEWTYPE
is used in inetdev_event() and addrconf_notify(). These functions apparently
need to be notified before and after the change.

>
>int netdev_change_type(struct net_device *dev, int newtype)
>{
>	int ret, oldtype;
>
>	if (dev->flags & IFF_UP)
>		return -EBUSY;
>
>	oldtype = dev->type;
>	dev->type = newtype;
>	ret = call_netdevice_notifier(NETDEV_CHANGETYPE, dev);
>	ret = notifier_to_errno(ret);
>	if (ret)
>	     dev->type = oldtype;
>
>	return ret;
>}

I see you point here, but that would be another notifier event. Do you suggest
to have 3 of them finally? NETDEV_BONDING_OLDTYPE, NETDEV_BONDING_NEWTYPE and
NETDEV_CHANGETYPE. Looks a bit redundant to me...

Thanks.

Jirka


^ permalink raw reply

* Re: [RFC PATCH net-next 0/7 v2]IPv6:netfilter: defragment
From: Shan Wei @ 2010-03-11  9:16 UTC (permalink / raw)
  To: YOSHIFUJI Hideaki
  Cc: Patrick McHardy, David Miller, Alexey Dobriyan, Yasuyuki KOZAKAI,
	netdev@vger.kernel.org, netfilter-devel,
	yoshfuji@linux-ipv6.org >> YOSHIFUJI Hideaki
In-Reply-To: <4B97D34C.4020509@gmail.com>

yoshifuji-san:

YOSHIFUJI Hideaki wrote, at 03/11/2010 01:13 AM:
> Well, because the context of defragment are different
> from standard ones (e.g., In netfilter, defragment can
> happen even on forwarding path, and the result is always
> thrown away anyway), I think it is not a good idea to
> touch standard MIB here. However I'm okay to increment
> other stats like InDiscards, OurDiscards and netfilter
> specific stats.

Not only on router, but also on host, if conntrack fails to reassemble
fragments, the fragments will not be forwarded to IPv4/IPv6 stack.
So, these fragments can't be traced from MIB counter.

And, IPv4 conntrack records these fragments.
Is the context of IPv4 defragment different from IPv6?

> On the other hand, I'd even say we should NOT send
> icmp here (at least by default) because standard routers
> never send such packet.

Yes,for routers, the patch-set does not send icmp message to
source host. It only does on destination host with IPv6 connection 
track enable.

-- 
Best Regards
-----
Shan Wei
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH] TI DaVinci EMAC: Convert to dev_pm_ops
From: Chaithrika U S @ 2010-03-11  8:37 UTC (permalink / raw)
  To: netdev
  Cc: davem, --cc=khilman, davinci-linux-open-source, nsekhar,
	sudhakar.raj, Chaithrika U S

Migrate from the legacy PM hooks to use dev_pm_ops structure.

Signed-off-by: Chaithrika U S <chaithrika@ti.com>
---

This patch applies to Linus' kernel tree.
The fixes provided in this patch[1] are needed for EMAC driver to build.
[1]http://patchwork.kernel.org/patch/84267/

 drivers/net/davinci_emac.c |   27 ++++++++++++++++-----------
 1 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index 2526a9b..eb67fa6 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -2829,31 +2829,37 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static
-int davinci_emac_suspend(struct platform_device *pdev, pm_message_t state)
+static int davinci_emac_suspend(struct device *dev)
 {
-	struct net_device *dev = platform_get_drvdata(pdev);
+	struct platform_device *pdev = to_platform_device(dev);
+	struct net_device *ndev = platform_get_drvdata(pdev);
 
-	if (netif_running(dev))
-		emac_dev_stop(dev);
+	if (netif_running(ndev))
+		emac_dev_stop(ndev);
 
 	clk_disable(emac_clk);
 
 	return 0;
 }
 
-static int davinci_emac_resume(struct platform_device *pdev)
+static int davinci_emac_resume(struct device *dev)
 {
-	struct net_device *dev = platform_get_drvdata(pdev);
+	struct platform_device *pdev = to_platform_device(dev);
+	struct net_device *ndev = platform_get_drvdata(pdev);
 
 	clk_enable(emac_clk);
 
-	if (netif_running(dev))
-		emac_dev_open(dev);
+	if (netif_running(ndev))
+		emac_dev_open(ndev);
 
 	return 0;
 }
 
+static const struct dev_pm_ops davinci_emac_pm_ops = {
+	.suspend	= davinci_emac_suspend,
+	.resume		= davinci_emac_resume,
+};
+
 /**
  * davinci_emac_driver: EMAC platform driver structure
  */
@@ -2861,11 +2867,10 @@ static struct platform_driver davinci_emac_driver = {
 	.driver = {
 		.name	 = "davinci_emac",
 		.owner	 = THIS_MODULE,
+		.pm	 = &davinci_emac_pm_ops,
 	},
 	.probe = davinci_emac_probe,
 	.remove = __devexit_p(davinci_emac_remove),
-	.suspend = davinci_emac_suspend,
-	.resume = davinci_emac_resume,
 };
 
 /**
-- 
1.5.6


^ permalink raw reply related

* Re: [PATCH v6] rps: Receive Packet Steering
From: Changli Gao @ 2010-03-11  9:45 UTC (permalink / raw)
  To: Tom Herbert; +Cc: davem, netdev, bhutchings, shemminger, eric.dumazet
In-Reply-To: <alpine.DEB.1.00.1003102249380.21248@pokey.mtv.corp.google.com>

On Thu, Mar 11, 2010 at 3:00 PM, Tom Herbert <therbert@google.com> wrote:
> diff --git a/net/core/skbuff.c b/net/core/skbuff.c
> index 93c4e06..472c767 100644
> --- a/net/core/skbuff.c
> +++ b/net/core/skbuff.c
> @@ -581,6 +581,7 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
>        C(len);
>        C(data_len);
>        C(mac_len);
> +       C(rxhash);
>        n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
>        n->cloned = 1;
>        n->nohdr = 0;

Why not do the same thing in function __copy_skb_header()?

-- 
Regards,
Changli Gao(xiaosuo@gmail.com)

^ permalink raw reply

* Re: [Bonding-devel] [net-next-2.6 PATCH 2/3] bonding: check return value of nofitier when changing type
From: Jiri Pirko @ 2010-03-11  9:53 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev, kaber, fubar, bonding-devel, davem
In-Reply-To: <20100311075908.GA2785@psychotron.redhat.com>

Thu, Mar 11, 2010 at 08:59:09AM CET, jpirko@redhat.com wrote:
>Wed, Mar 10, 2010 at 11:47:10PM CET, shemminger@linux-foundation.org wrote:
>>On Wed, 10 Mar 2010 21:29:35 +0100
>>Jiri Pirko <jpirko@redhat.com> wrote:
>>
>>> diff --git a/net/core/dev.c b/net/core/dev.c
>>> index bcc490c..5de4a15 100644
>>> --- a/net/core/dev.c
>>> +++ b/net/core/dev.c
>>> @@ -1084,9 +1084,9 @@ void netdev_state_change(struct net_device *dev)
>>>  }
>>>  EXPORT_SYMBOL(netdev_state_change);
>>>  
>>> -void netdev_bonding_change(struct net_device *dev, unsigned long event)
>>> +int netdev_bonding_change(struct net_device *dev, unsigned long event)
>>>  {
>>> -	call_netdevice_notifiers(event, dev);
>>> +	return call_netdevice_notifiers(event, dev);
>>>  }
>>>  EXPORT_SYMBOL(netdev_bonding_change);
>>>  
>>
>>I don't think all this pre-post stuff needed.
>>Since this is general (not just bonding) how about
>
>Well actually I reused NETDEV_BONDING_OLDTYPE. This and NETDEV_BONDING_NEWTYPE
>is used in inetdev_event() and addrconf_notify(). These functions apparently
>need to be notified before and after the change.
>
>>
>>int netdev_change_type(struct net_device *dev, int newtype)
>>{
>>	int ret, oldtype;
>>
>>	if (dev->flags & IFF_UP)
>>		return -EBUSY;
>>
>>	oldtype = dev->type;
>>	dev->type = newtype;

Also, the type change is not only about dev->type. See for example
ether_setup(). This function and it's puprose might be misleading...

>>	ret = call_netdevice_notifier(NETDEV_CHANGETYPE, dev);
>>	ret = notifier_to_errno(ret);
>>	if (ret)
>>	     dev->type = oldtype;
>>
>>	return ret;
>>}
>
>I see you point here, but that would be another notifier event. Do you suggest
>to have 3 of them finally? NETDEV_BONDING_OLDTYPE, NETDEV_BONDING_NEWTYPE and
>NETDEV_CHANGETYPE. Looks a bit redundant to me...
>
>Thanks.
>
>Jirka
>

^ permalink raw reply

* [PATCH] DRIVER: Libertas: Fixed coding style in rx.c
From: Stewart Malik @ 2010-03-11  9:58 UTC (permalink / raw)
  To: dcbw; +Cc: libertas-dev, linux-wireless, netdev, linux-kernel, Stewart Malik

---
 drivers/net/wireless/libertas/rx.c |   50 ++++++++++++++++++------------------
 1 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index 2daf8ff..7a867e3 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -38,10 +38,10 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
 	struct sk_buff *skb);
 
 /**
- *  @brief This function computes the avgSNR .
+ *  @brief	This function computes the avgSNR .
  *
- *  @param priv    A pointer to struct lbs_private structure
- *  @return 	   avgSNR
+ *  @param	priv	A pointer to struct lbs_private structure
+ *  @return	avgSNR
  */
 static u8 lbs_getavgsnr(struct lbs_private *priv)
 {
@@ -56,10 +56,10 @@ static u8 lbs_getavgsnr(struct lbs_private *priv)
 }
 
 /**
- *  @brief This function computes the AvgNF
+ *  @brief	This function computes the AvgNF
  *
- *  @param priv    A pointer to struct lbs_private structure
- *  @return 	   AvgNF
+ *  @param	priv	A pointer to struct lbs_private structure
+ *  @return	AvgNF
  */
 static u8 lbs_getavgnf(struct lbs_private *priv)
 {
@@ -74,11 +74,11 @@ static u8 lbs_getavgnf(struct lbs_private *priv)
 }
 
 /**
- *  @brief This function save the raw SNR/NF to our internel buffer
+ *  @brief	This function save the raw SNR/NF to our internel buffer
  *
- *  @param priv    A pointer to struct lbs_private structure
- *  @param prxpd   A pointer to rxpd structure of received packet
- *  @return 	   n/a
+ *  @param	priv	A pointer to struct lbs_private structure
+ *  @param	prxpd	A pointer to rxpd structure of received packet
+ *  @return	n/a
  */
 static void lbs_save_rawSNRNF(struct lbs_private *priv, struct rxpd *p_rx_pd)
 {
@@ -93,11 +93,11 @@ static void lbs_save_rawSNRNF(struct lbs_private *priv, struct rxpd *p_rx_pd)
 }
 
 /**
- *  @brief This function computes the RSSI in received packet.
+ *  @brief	This function computes the RSSI in received packet.
  *
- *  @param priv    A pointer to struct lbs_private structure
- *  @param prxpd   A pointer to rxpd structure of received packet
- *  @return 	   n/a
+ *  @param	priv	A pointer to struct lbs_private structure
+ *  @param	prxpd	A pointer to rxpd structure of received packet
+ *  @return	n/a
  */
 static void lbs_compute_rssi(struct lbs_private *priv, struct rxpd *p_rx_pd)
 {
@@ -134,9 +134,9 @@ static void lbs_compute_rssi(struct lbs_private *priv, struct rxpd *p_rx_pd)
  *  @brief This function processes received packet and forwards it
  *  to kernel/upper layer
  *
- *  @param priv    A pointer to struct lbs_private
- *  @param skb     A pointer to skb which includes the received packet
- *  @return 	   0 or -1
+ *  @param	priv	A pointer to struct lbs_private
+ *  @param	skb		A pointer to skb which includes the received packet
+ *  @return	0 or -1
  */
 int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
 {
@@ -196,7 +196,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
 		 *    before the snap_type.
 		 */
 		p_ethhdr = (struct ethhdr *)
-		    ((u8 *) & p_rx_pkt->eth803_hdr
+		    ((u8 *) &p_rx_pkt->eth803_hdr
 		     + sizeof(p_rx_pkt->eth803_hdr) + sizeof(p_rx_pkt->rfc1042_hdr)
 		     - sizeof(p_rx_pkt->eth803_hdr.dest_addr)
 		     - sizeof(p_rx_pkt->eth803_hdr.src_addr)
@@ -213,7 +213,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
 		hdrchop = (u8 *)p_ethhdr - (u8 *)p_rx_pd;
 	} else {
 		lbs_deb_hex(LBS_DEB_RX, "RX Data: LLC/SNAP",
-			(u8 *) & p_rx_pkt->rfc1042_hdr,
+			(u8 *) &p_rx_pkt->rfc1042_hdr,
 			sizeof(p_rx_pkt->rfc1042_hdr));
 
 		/* Chop off the rxpd */
@@ -254,8 +254,8 @@ EXPORT_SYMBOL_GPL(lbs_process_rxed_packet);
  *  @brief This function converts Tx/Rx rates from the Marvell WLAN format
  *  (see Table 2 in Section 3.1) to IEEE80211_RADIOTAP_RATE units (500 Kb/s)
  *
- *  @param rate    Input rate
- *  @return 	   Output Rate (0 if invalid)
+ *  @param	rate	Input rate
+ *  @return	Output Rate (0 if invalid)
  */
 static u8 convert_mv_rate_to_radiotap(u8 rate)
 {
@@ -294,9 +294,9 @@ static u8 convert_mv_rate_to_radiotap(u8 rate)
  *  @brief This function processes a received 802.11 packet and forwards it
  *  to kernel/upper layer
  *
- *  @param priv    A pointer to struct lbs_private
- *  @param skb     A pointer to skb which includes the received packet
- *  @return 	   0 or -1
+ *  @param	priv	A pointer to struct lbs_private
+ *  @param	skb		A pointer to skb which includes the received packet
+ *  @return	0 or -1
  */
 static int process_rxed_802_11_packet(struct lbs_private *priv,
 	struct sk_buff *skb)
@@ -313,7 +313,7 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
 	p_rx_pkt = (struct rx80211packethdr *) skb->data;
 	prxpd = &p_rx_pkt->rx_pd;
 
-	// lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, min(skb->len, 100));
+	/* lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, min(skb->len, 100)); */
 
 	if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
 		lbs_deb_rx("rx err: frame received with bad length\n");
-- 
1.6.0.4


^ permalink raw reply related

* Re: [net-next-2.6 PATCH] ixgbe: convert to use netdev_for_each_mc_addr
From: Jiri Pirko @ 2010-03-11 10:08 UTC (permalink / raw)
  To: Jeff Kirsher; +Cc: netdev, davem
In-Reply-To: <9929d2391002240130p17bbc1acj74e3c8306a3f664@mail.gmail.com>

Wed, Feb 24, 2010 at 10:30:54AM CET, jeffrey.t.kirsher@intel.com wrote:
>On Tue, Feb 23, 2010 at 11:05, Jiri Pirko <jpirko@redhat.com> wrote:
>>
>> Signed-off-by: Jiri Pirko <jpirko@redhat.com>
>> ---
>>  drivers/net/ixgbe/ixgbe_common.c |   16 +++++++---------
>>  drivers/net/ixgbe/ixgbe_common.h |    5 ++---
>>  drivers/net/ixgbe/ixgbe_main.c   |   24 ++----------------------
>>  drivers/net/ixgbe/ixgbe_type.h   |    3 +--
>>  4 files changed, 12 insertions(+), 36 deletions(-)
>>
>
>Thanks Jiri, I have added the patch to my queue of ixgbe patches.

Hi Jeff,

when do you think this and ixgbevf bits will be merged into net-next-2.6?

Thanks a lot.

Jirka
>
>-- 
>Cheers,
>Jeff

^ permalink raw reply

* ixgbevf: bug in error handling
From: Dan Carpenter @ 2010-03-11 10:33 UTC (permalink / raw)
  To: Greg Rose; +Cc: netdev, kernel-janitors

Hi Greg,

drivers/net/ixgbevf/ixgbevf_main.c +3013 ixgbevf_tx_map(96) warn: unsigned 'i' is never less than zero.
  3010          while (count >= 0) {
  3011                  count--;
  3012                  i--;
  3013                  if (i < 0)
  3014                          i += tx_ring->count;

	There is a problem here because i is unsigned and just wraps 
	around instead of being less than 0.

  3015                  tx_buffer_info = &tx_ring->tx_buffer_info[i];
  3016                  ixgbevf_unmap_and_free_tx_resource(adapter, tx_buffer_info);
  3017          }

regards,
dan carpenter

^ permalink raw reply

* [PATCH 0/7] tcp: bugs and cleanup for 2.6.34-rc1
From: William Allen Simpson @ 2010-03-11 11:35 UTC (permalink / raw)
  To: Linus Torvalds, Andrew Morton
  Cc: Linux Kernel Developers, Linux Kernel Network Developers,
	David Miller

I'd have thought that there would be greater interest about patching
crashing bugs, signed versus unsigned (underflow) bugs, TCP DoS bugs,
TCP data corruption, and TCP performance problems....

There's been ample warning.  Zero-day security issues will be reported
to the usual announcement lists.  In particular, these 0day exploits
affect systems as far back as the 2005 changeover to git.

Combination of patches reported in October, November, December, January,
and February, for 2.6.32, 2.6.33, and now 2.6.34.

This code has had previous review and several months of limited testing.

Some portions were removed during the various TCPCT part 1 patch splits,
then were cut off by the sudden unexpected end of that merge window.
[03 Dec 2009]  I've restarted the sub-numbering (again).

Of particular interest are the TCPCT header extensions that already
appear in the next phase of testing with other platforms.  These patches
allow correct reception without data corruption.

The remainder of the original TCPCT part 2 will be merged with part 3.

[Updated to 2010 Mar 08 2.6.34-rc1.]

^ permalink raw reply

* [PATCH net-2.6] be2net: fix mccq create for big endian architectures
From: Ajit Khaparde @ 2010-03-11 11:35 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

The request to create an mccq was being dispatched without
doing a byte swap of num_pages. This byte swap is necessary
for Big Endian systems like PPC. Not having this fix leads
mccq create to fail on BE ASICs running newer version of
firmware, thereby causing driver initialization failure.

Signed-off-by: Ajit Khaparde <ajitk@serverengines.com>
---
 drivers/net/benet/be_cmds.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index c592153..50e6259 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -673,7 +673,7 @@ int be_cmd_mccq_create(struct be_adapter *adapter,
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 			OPCODE_COMMON_MCC_CREATE, sizeof(*req));
 
-	req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
+	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
 
 	AMAP_SET_BITS(struct amap_mcc_context, valid, ctxt, 1);
 	AMAP_SET_BITS(struct amap_mcc_context, ring_size, ctxt,
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH v3 1/7] net: tcp_header_len_th and tcp_option_len_th
From: William Allen Simpson @ 2010-03-11 11:41 UTC (permalink / raw)
  To: Linus Torvalds, Andrew Morton
  Cc: Linux Kernel Developers, Linux Kernel Network Developers,
	David Miller
In-Reply-To: <4B98D592.6040301@gmail.com>

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

Redefine two TCP header functions to accept TCP header pointer.
When subtracting, return signed int to allow error checking.

These functions will be used in subsequent patches that implement
additional features.

Signed-off-by: William.Allen.Simpson@gmail.com
---
  include/linux/tcp.h |   12 ++++++++++++
  1 files changed, 12 insertions(+), 0 deletions(-)

[-- Attachment #2: len_th+2a3+2.6.34-rc1.patch --]
[-- Type: text/plain, Size: 719 bytes --]

diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index a778ee0..48ddeb8 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -225,6 +225,18 @@ static inline unsigned int tcp_optlen(const struct sk_buff *skb)
 	return (tcp_hdr(skb)->doff - 5) * 4;
 }
 
+/* Length of fixed header plus standard options. */
+static inline unsigned int tcp_header_len_th(const struct tcphdr *th)
+{
+	return th->doff * 4;
+}
+
+/* Length of standard options only.  This could be negative. */
+static inline int tcp_option_len_th(const struct tcphdr *th)
+{
+	return (int)(th->doff * 4) - sizeof(*th);
+}
+
 /* This defines a selective acknowledgement block. */
 struct tcp_sack_block_wire {
 	__be32	start_seq;
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH v4 2/7] net: remove old tcp_optlen function
From: William Allen Simpson @ 2010-03-11 11:53 UTC (permalink / raw)
  To: Linus Torvalds, Andrew Morton
  Cc: Linux Kernel Developers, Linux Kernel Network Developers,
	David Miller, Michael Chan
In-Reply-To: <4B98D592.6040301@gmail.com>

The tcp_optlen() function returns a potential *negative* unsigned.

In the only two existing files using the old tcp_optlen() function,
clean up confusing and inconsistent mixing of both byte and word
offsets, and other coding style issues.  Document assumptions.

Quoth David Miller:
    This is transmit, and the packets can only come from the Linux
    TCP stack, not some external entity.

    You're being way too anal here, and adding these checks to
    drivers would be just a lot of rediculious bloat. [sic]

Therefore, there are *no* checks for bad TCP and IP header sizes, nor
any semantic changes.  The drivers should function exactly as existing,
although usage of int should ameliorate the issues.

No response from testers in 21+ weeks.

[removed comment references to commit log]

Requires:
   net: tcp_header_len_th and tcp_option_len_th

Signed-off-by: William.Allen.Simpson@gmail.com
CC: Michael Chan <mchan@broadcom.com>
---
  drivers/net/bnx2.c  |   29 +++++++++++++-----------
  drivers/net/tg3.c   |   60 +++++++++++++++++++++++---------------------------
  include/linux/tcp.h |    5 ----
  3 files changed, 44 insertions(+), 50 deletions(-)

^ permalink raw reply

* Re: [PATCH v4 2/7] net: remove old tcp_optlen function
From: William Allen Simpson @ 2010-03-11 11:54 UTC (permalink / raw)
  To: Linus Torvalds, Andrew Morton
  Cc: Linux Kernel Developers, Linux Kernel Network Developers,
	David Miller, Michael Chan
In-Reply-To: <4B98D9A2.8060603@gmail.com>

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

The tcp_optlen() function returns a potential *negative* unsigned.

In the only two existing files using the old tcp_optlen() function,
clean up confusing and inconsistent mixing of both byte and word
offsets, and other coding style issues.  Document assumptions.

Quoth David Miller:
    This is transmit, and the packets can only come from the Linux
    TCP stack, not some external entity.

    You're being way too anal here, and adding these checks to
    drivers would be just a lot of rediculious bloat. [sic]

Therefore, there are *no* checks for bad TCP and IP header sizes, nor
any semantic changes.  The drivers should function exactly as existing,
although usage of int should ameliorate the issues.

No response from testers in 21+ weeks.

[removed comment references to commit log]

Requires:
   net: tcp_header_len_th and tcp_option_len_th

Signed-off-by: William.Allen.Simpson@gmail.com
CC: Michael Chan <mchan@broadcom.com>
---
  drivers/net/bnx2.c  |   29 +++++++++++++-----------
  drivers/net/tg3.c   |   60 +++++++++++++++++++++++---------------------------
  include/linux/tcp.h |    5 ----
  3 files changed, 44 insertions(+), 50 deletions(-)

[-- Attachment #2: len_th+2b4+2.6.34-rc1.patch --]
[-- Type: text/plain, Size: 6918 bytes --]

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 381887b..87607b8 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -6335,6 +6335,8 @@ bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp)
 /* Called with netif_tx_lock.
  * bnx2_tx_int() runs without netif_tx_lock unless it needs to call
  * netif_wake_queue().
+ *
+ * No TCP or IP length checking, as required by David Miller.
  */
 static netdev_tx_t
 bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -6378,19 +6380,19 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
 			(TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16));
 	}
 #endif
-	if ((mss = skb_shinfo(skb)->gso_size)) {
-		u32 tcp_opt_len;
-		struct iphdr *iph;
+	mss = skb_shinfo(skb)->gso_size;
+	if (mss != 0) {
+		struct tcphdr *th = tcp_hdr(skb);
+		int tcp_opt_words = th->doff - (sizeof(*th) >> 2);
+		/* assumes positive tcp_opt_words without checking */
 
 		vlan_tag_flags |= TX_BD_FLAGS_SW_LSO;
 
-		tcp_opt_len = tcp_optlen(skb);
-
 		if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) {
 			u32 tcp_off = skb_transport_offset(skb) -
 				      sizeof(struct ipv6hdr) - ETH_HLEN;
 
-			vlan_tag_flags |= ((tcp_opt_len >> 2) << 8) |
+			vlan_tag_flags |= (tcp_opt_words << 8) |
 					  TX_BD_FLAGS_SW_FLAGS;
 			if (likely(tcp_off == 0))
 				vlan_tag_flags &= ~TX_BD_FLAGS_TCP6_OFF0_MSK;
@@ -6403,14 +6405,15 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
 				mss |= (tcp_off & 0xc) << TX_BD_TCP6_OFF2_SHL;
 			}
 		} else {
-			iph = ip_hdr(skb);
-			if (tcp_opt_len || (iph->ihl > 5)) {
-				vlan_tag_flags |= ((iph->ihl - 5) +
-						   (tcp_opt_len >> 2)) << 8;
-			}
+			struct iphdr *iph = ip_hdr(skb);
+			int ip_opt_words = iph->ihl - (sizeof(*iph) >> 2);
+			/* assumes positive ip_opt_words without checking */
+			int opt_words = ip_opt_words + tcp_opt_words;
+
+			if (opt_words > 0)
+				vlan_tag_flags |= opt_words << 8;
 		}
-	} else
-		mss = 0;
+	}
 
 	mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
 	if (pci_dma_mapping_error(bp->pdev, mapping)) {
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 0fa7688..6ad8184 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -5481,6 +5481,8 @@ static void tg3_set_txd(struct tg3_napi *tnapi, int entry,
 
 /* hard_start_xmit for devices that don't have any bugs and
  * support TG3_FLG2_HW_TSO_2 and TG3_FLG2_HW_TSO_3 only.
+ *
+ * No TCP or IP length checking, as required by David Miller.
  */
 static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
 				  struct net_device *dev)
@@ -5515,9 +5517,9 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
 
 	entry = tnapi->tx_prod;
 	base_flags = 0;
-	mss = 0;
-	if ((mss = skb_shinfo(skb)->gso_size) != 0) {
-		int tcp_opt_len, ip_tcp_len;
+	mss = skb_shinfo(skb)->gso_size;
+	if (mss != 0) {
+		struct tcphdr *th;
 		u32 hdrlen;
 
 		if (skb_header_cloned(skb) &&
@@ -5525,18 +5527,16 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
 			dev_kfree_skb(skb);
 			goto out_unlock;
 		}
+		th = tcp_hdr(skb);
 
 		if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
 			hdrlen = skb_headlen(skb) - ETH_HLEN;
 		else {
 			struct iphdr *iph = ip_hdr(skb);
 
-			tcp_opt_len = tcp_optlen(skb);
-			ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
-
+			hdrlen = ip_hdrlen(skb) + tcp_header_len_th(th);
+			iph->tot_len = htons(mss + hdrlen);
 			iph->check = 0;
-			iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
-			hdrlen = ip_tcp_len + tcp_opt_len;
 		}
 
 		if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) {
@@ -5550,7 +5550,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
 		base_flags |= (TXD_FLAG_CPU_PRE_DMA |
 			       TXD_FLAG_CPU_POST_DMA);
 
-		tcp_hdr(skb)->check = 0;
+		th->check = 0;
 
 	}
 	else if (skb->ip_summed == CHECKSUM_PARTIAL)
@@ -5683,6 +5683,8 @@ tg3_tso_bug_end:
 
 /* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and
  * support TG3_FLG2_HW_TSO_1 or firmware TSO only.
+ *
+ * No TCP or IP length checking, as required by David Miller.
  */
 static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
 					  struct net_device *dev)
@@ -5721,20 +5723,21 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
 	if (skb->ip_summed == CHECKSUM_PARTIAL)
 		base_flags |= TXD_FLAG_TCPUDP_CSUM;
 
-	if ((mss = skb_shinfo(skb)->gso_size) != 0) {
+	mss = skb_shinfo(skb)->gso_size;
+	if (mss != 0) {
 		struct iphdr *iph;
-		u32 tcp_opt_len, ip_tcp_len, hdr_len;
+		struct tcphdr *th;
+		u32 hdr_len;
+		int opt_bytes;
 
 		if (skb_header_cloned(skb) &&
 		    pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
 			dev_kfree_skb(skb);
 			goto out_unlock;
 		}
+		th = tcp_hdr(skb);
+		hdr_len = ip_hdrlen(skb) + tcp_header_len_th(th);
 
-		tcp_opt_len = tcp_optlen(skb);
-		ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
-
-		hdr_len = ip_tcp_len + tcp_opt_len;
 		if (unlikely((ETH_HLEN + hdr_len) > 80) &&
 			     (tp->tg3_flags2 & TG3_FLG2_TSO_BUG))
 			return (tg3_tso_bug(tp, skb));
@@ -5746,13 +5749,14 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
 		iph->check = 0;
 		iph->tot_len = htons(mss + hdr_len);
 		if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) {
-			tcp_hdr(skb)->check = 0;
+			th->check = 0;
 			base_flags &= ~TXD_FLAG_TCPUDP_CSUM;
 		} else
-			tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
-								 iph->daddr, 0,
-								 IPPROTO_TCP,
-								 0);
+			th->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
+						       0, IPPROTO_TCP, 0);
+
+		opt_bytes = hdr_len - sizeof(*iph) - sizeof(*th);
+		/* assumes positive opt_bytes without checking */
 
 		if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) {
 			mss |= (hdr_len & 0xc) << 12;
@@ -5763,19 +5767,11 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
 			mss |= hdr_len << 9;
 		else if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_1) ||
 			 GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
-			if (tcp_opt_len || iph->ihl > 5) {
-				int tsflags;
-
-				tsflags = (iph->ihl - 5) + (tcp_opt_len >> 2);
-				mss |= (tsflags << 11);
-			}
+			if (opt_bytes > 0)
+				mss |= opt_bytes << (11 - 2);
 		} else {
-			if (tcp_opt_len || iph->ihl > 5) {
-				int tsflags;
-
-				tsflags = (iph->ihl - 5) + (tcp_opt_len >> 2);
-				base_flags |= tsflags << 12;
-			}
+			if (opt_bytes > 0)
+				base_flags |= opt_bytes << (12 - 2);
 		}
 	}
 #if TG3_VLAN_TAG_USED
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 48ddeb8..854ad65 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -220,11 +220,6 @@ static inline unsigned int tcp_hdrlen(const struct sk_buff *skb)
 	return tcp_hdr(skb)->doff * 4;
 }
 
-static inline unsigned int tcp_optlen(const struct sk_buff *skb)
-{
-	return (tcp_hdr(skb)->doff - 5) * 4;
-}
-
 /* Length of fixed header plus standard options. */
 static inline unsigned int tcp_header_len_th(const struct tcphdr *th)
 {
-- 
1.6.3.3


^ 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