Netdev List
 help / color / mirror / Atom feed
* [PATCH 03/12] sfc: Workaround flush failures on Falcon B0
From: Ben Hutchings @ 2010-06-01 21:17 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers
In-Reply-To: <1275426967.2114.25.camel@achroite.uk.solarflarecom.com>

From: Steve Hodgson <shodgson@solarflare.com>

Under certain conditions a PHY may backpressure Falcon B0
in such a way that flushes timeout. In normal circumstances
the phy poller would fix the PHY, and the flush could complete.

But efx_nic_flush_queues() is always called after efx_stop_all(),
so the poller has been stopped. Even if this weren't the case,
how long would we have to wait for the poller to fix this? And
several callers of efx_nic_flush_queues() are about to reset
the device anyway - so we don't need to do anything.

Work around this bug by scheduling a reset. Ensure that the
MAC is never rewired back into the datapath before the reset
runs (we already ignore all rx events anyway).

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 drivers/net/sfc/efx.c         |   13 +++++++++++--
 drivers/net/sfc/falcon.c      |    8 +++++---
 drivers/net/sfc/nic.c         |    3 ---
 drivers/net/sfc/workarounds.h |    2 +-
 4 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 0319000..d1a1d32 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -27,6 +27,7 @@
 #include "nic.h"
 
 #include "mcdi.h"
+#include "workarounds.h"
 
 /**************************************************************************
  *
@@ -556,10 +557,18 @@ static void efx_fini_channels(struct efx_nic *efx)
 	BUG_ON(efx->port_enabled);
 
 	rc = efx_nic_flush_queues(efx);
-	if (rc)
+	if (rc && EFX_WORKAROUND_7803(efx)) {
+		/* Schedule a reset to recover from the flush failure. The
+		 * descriptor caches reference memory we're about to free,
+		 * but falcon_reconfigure_mac_wrapper() won't reconnect
+		 * the MACs because of the pending reset. */
+		EFX_ERR(efx, "Resetting to recover from flush failure\n");
+		efx_schedule_reset(efx, RESET_TYPE_ALL);
+	} else if (rc) {
 		EFX_ERR(efx, "failed to flush queues\n");
-	else
+	} else {
 		EFX_LOG(efx, "successfully flushed all queues\n");
+	}
 
 	efx_for_each_channel(channel, efx) {
 		EFX_LOG(channel->efx, "shut down chan %d\n", channel->channel);
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 655b697..8558865 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -548,7 +548,9 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
 {
 	struct efx_link_state *link_state = &efx->link_state;
 	efx_oword_t reg;
-	int link_speed;
+	int link_speed, isolate;
+
+	isolate = (efx->reset_pending != RESET_TYPE_NONE);
 
 	switch (link_state->speed) {
 	case 10000: link_speed = 3; break;
@@ -570,7 +572,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
 	 * discarded. */
 	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
 		EFX_SET_OWORD_FIELD(reg, FRF_BB_TXFIFO_DRAIN_EN,
-				    !link_state->up);
+				    !link_state->up || isolate);
 	}
 
 	efx_writeo(efx, &reg, FR_AB_MAC_CTRL);
@@ -584,7 +586,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
 	EFX_SET_OWORD_FIELD(reg, FRF_AZ_RX_XOFF_MAC_EN, 1);
 	/* Unisolate the MAC -> RX */
 	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0)
-		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, 1);
+		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, !isolate);
 	efx_writeo(efx, &reg, FR_AZ_RX_CFG);
 }
 
diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c
index 5d3aaec..ec0bb80 100644
--- a/drivers/net/sfc/nic.c
+++ b/drivers/net/sfc/nic.c
@@ -1219,9 +1219,6 @@ int efx_nic_flush_queues(struct efx_nic *efx)
 		rx_queue->flushed = FLUSH_DONE;
 	}
 
-	if (EFX_WORKAROUND_7803(efx))
-		return 0;
-
 	return -ETIMEDOUT;
 }
 
diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h
index 518f7fc..782e45a 100644
--- a/drivers/net/sfc/workarounds.h
+++ b/drivers/net/sfc/workarounds.h
@@ -54,7 +54,7 @@
 /* Increase filter depth to avoid RX_RESET */
 #define EFX_WORKAROUND_7244 EFX_WORKAROUND_FALCON_A
 /* Flushes may never complete */
-#define EFX_WORKAROUND_7803 EFX_WORKAROUND_FALCON_A
+#define EFX_WORKAROUND_7803 EFX_WORKAROUND_FALCON_AB
 /* Leak overlength packets rather than free */
 #define EFX_WORKAROUND_8071 EFX_WORKAROUND_FALCON_A
 
-- 
1.6.2.5


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


^ permalink raw reply related

* [PATCH 02/12] sfc: Reschedule any resets scheduled inside efx_pm_freeze()
From: Ben Hutchings @ 2010-06-01 21:17 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers
In-Reply-To: <1275426967.2114.25.camel@achroite.uk.solarflarecom.com>

From: Steve Hodgson <shodgson@solarflare.com>

efx_pm_freeze() sets efx->state = STATE_FINI, which means
efx_reset_work() will abort any scheduled resets.

efx_pm_thaw() should reschedule efx_reset_work() again,
since a freeze/thaw will not have reset the hardware.

This bug was spotted by inspection - there is no real world example of
this happening.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 drivers/net/sfc/efx.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 1564605..0319000 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -1886,6 +1886,9 @@ static void efx_reset_work(struct work_struct *data)
 {
 	struct efx_nic *efx = container_of(data, struct efx_nic, reset_work);
 
+	if (efx->reset_pending == RESET_TYPE_NONE)
+		return;
+
 	/* If we're not RUNNING then don't reset. Leave the reset_pending
 	 * flag set so that efx_pci_probe_main will be retried */
 	if (efx->state != STATE_RUNNING) {
@@ -2332,6 +2335,9 @@ static int efx_pm_thaw(struct device *dev)
 
 	efx->type->resume_wol(efx);
 
+	/* Reschedule any quenched resets scheduled during efx_pm_freeze() */
+	queue_work(reset_workqueue, &efx->reset_work);
+
 	return 0;
 }
 
-- 
1.6.2.5


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


^ permalink raw reply related

* [PATCH 01/12] sfc: Rename struct efx_mcdi_phy_cfg to efx_mcdi_phy_data
From: Ben Hutchings @ 2010-06-01 21:17 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers
In-Reply-To: <1275426967.2114.25.camel@achroite.uk.solarflarecom.com>

Most of its members are constant capabilities, not configuration.  The
new name is also consistent with the name of the pointer to it in
struct efx_nic and the names of structures used by other PHY drivers.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 drivers/net/sfc/mcdi_phy.c |   20 ++++++++++----------
 1 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/net/sfc/mcdi_phy.c b/drivers/net/sfc/mcdi_phy.c
index 6032c0e..5c23f22 100644
--- a/drivers/net/sfc/mcdi_phy.c
+++ b/drivers/net/sfc/mcdi_phy.c
@@ -20,7 +20,7 @@
 #include "nic.h"
 #include "selftest.h"
 
-struct efx_mcdi_phy_cfg {
+struct efx_mcdi_phy_data {
 	u32 flags;
 	u32 type;
 	u32 supported_cap;
@@ -35,7 +35,7 @@ struct efx_mcdi_phy_cfg {
 };
 
 static int
-efx_mcdi_get_phy_cfg(struct efx_nic *efx, struct efx_mcdi_phy_cfg *cfg)
+efx_mcdi_get_phy_cfg(struct efx_nic *efx, struct efx_mcdi_phy_data *cfg)
 {
 	u8 outbuf[MC_CMD_GET_PHY_CFG_OUT_LEN];
 	size_t outlen;
@@ -259,7 +259,7 @@ static u32 ethtool_to_mcdi_cap(u32 cap)
 
 static u32 efx_get_mcdi_phy_flags(struct efx_nic *efx)
 {
-	struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
+	struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
 	enum efx_phy_mode mode, supported;
 	u32 flags;
 
@@ -307,7 +307,7 @@ static u32 mcdi_to_ethtool_media(u32 media)
 
 static int efx_mcdi_phy_probe(struct efx_nic *efx)
 {
-	struct efx_mcdi_phy_cfg *phy_data;
+	struct efx_mcdi_phy_data *phy_data;
 	u8 outbuf[MC_CMD_GET_LINK_OUT_LEN];
 	u32 caps;
 	int rc;
@@ -405,7 +405,7 @@ fail:
 
 int efx_mcdi_phy_reconfigure(struct efx_nic *efx)
 {
-	struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
+	struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
 	u32 caps = (efx->link_advertising ?
 		    ethtool_to_mcdi_cap(efx->link_advertising) :
 		    phy_cfg->forced_cap);
@@ -446,7 +446,7 @@ void efx_mcdi_phy_decode_link(struct efx_nic *efx,
  */
 void efx_mcdi_phy_check_fcntl(struct efx_nic *efx, u32 lpa)
 {
-	struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
+	struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
 	u32 rmtadv;
 
 	/* The link partner capabilities are only relevent if the
@@ -505,7 +505,7 @@ static void efx_mcdi_phy_remove(struct efx_nic *efx)
 
 static void efx_mcdi_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
 {
-	struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
+	struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
 	u8 outbuf[MC_CMD_GET_LINK_OUT_LEN];
 	int rc;
 
@@ -535,7 +535,7 @@ static void efx_mcdi_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *e
 
 static int efx_mcdi_phy_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
 {
-	struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
+	struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
 	u32 caps;
 	int rc;
 
@@ -674,7 +674,7 @@ out:
 static int efx_mcdi_phy_run_tests(struct efx_nic *efx, int *results,
 				  unsigned flags)
 {
-	struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
+	struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
 	u32 mode;
 	int rc;
 
@@ -712,7 +712,7 @@ static int efx_mcdi_phy_run_tests(struct efx_nic *efx, int *results,
 
 const char *efx_mcdi_phy_test_name(struct efx_nic *efx, unsigned int index)
 {
-	struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
+	struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
 
 	if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_BIST_LBN)) {
 		if (index == 0)
-- 
1.6.2.5


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


^ permalink raw reply related

* [PATCH 00/12] sfc changes for 2.6.36
From: Ben Hutchings @ 2010-06-01 21:16 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers

Here's a first series of changes for 2.6.36.

The major feature here is RX buffer recycling, which improves
performance on networks with heavy multicast traffic.  Other than that,
there are various bug fixes and cleanup.

Ben.

Ben Hutchings (3):
  sfc: Rename struct efx_mcdi_phy_cfg to efx_mcdi_phy_data
  sfc: Only count bad packets in rx_errors
  sfc: Get port number from CS_PORT_NUM, not PCI function number

Steve Hodgson (9):
  sfc: Reschedule any resets scheduled inside efx_pm_freeze()
  sfc: Workaround flush failures on Falcon B0
  sfc: Synchronise link_advertising and wanted_fc on Siena
  sfc: Wait for the link to stay up before running loopback selftest
  sfc: Allow DRV_GEN events to be used outside of selftests
  sfc: Remove efx_rx_queue::add_lock
  sfc: Support only two rx buffers per page
  sfc: Recycle discarded rx buffers back onto the queue
  sfc: Allow shared pages to be recycled

 drivers/net/sfc/efx.c         |   69 +++-----
 drivers/net/sfc/efx.h         |    4 +-
 drivers/net/sfc/falcon.c      |    8 +-
 drivers/net/sfc/mcdi_phy.c    |   21 ++-
 drivers/net/sfc/net_driver.h  |   46 +++--
 drivers/net/sfc/nic.c         |   55 +++++--
 drivers/net/sfc/nic.h         |    4 +-
 drivers/net/sfc/rx.c          |  393 +++++++++++++++++++----------------------
 drivers/net/sfc/selftest.c    |   26 ++--
 drivers/net/sfc/siena.c       |    4 +
 drivers/net/sfc/workarounds.h |    2 +-
 11 files changed, 317 insertions(+), 315 deletions(-)

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


^ permalink raw reply

* [PATCH] IP: Increment INADDRERRORS if routing for a packet is not successful
From: Christoph Lameter @ 2010-06-01 21:13 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, David Miller

Something like this would have been very helpful during recent debugging
of multicast issues. Silent discards are bad.


If the kernel perceives that something is wrong with an incoming packet then the
IP stack currently silently discards packets. This makes it difficult to diagnose
problems with the network configurations (such as a misbehaving kernel
subsystem discarding multicast packets because the reverse path filter
does not like multicast subscriptions on the second NIC with rp_filter=1).

It is also necessary to know how many inbound packets are discarded to
assess networking issues in general with a NIC.

Signed-off-by: Christoph Lameter <cl@linux-foundation.org>
Acked-by: Stephen Hemminger <shemminger@vyatta.com>

---
 net/ipv4/route.c |    3 +++
 1 file changed, 3 insertions(+)

Index: linux-2.6/net/ipv4/route.c
===================================================================
--- linux-2.6.orig/net/ipv4/route.c	2010-06-01 11:46:10.000000000 -0500
+++ linux-2.6/net/ipv4/route.c	2010-06-01 11:52:55.000000000 -0500
@@ -2981,6 +2981,9 @@ static int inet_rtm_getroute(struct sk_b
 		rt = skb_rtable(skb);
 		if (err == 0 && rt->u.dst.error)
 			err = -rt->u.dst.error;
+		if (err)
+			IP_INC_STATS_BH(dev_net(skb->dev),
+					IPSTATS_MIB_INADDRERRORS);
 	} else {
 		struct flowi fl = {
 			.nl_u = {



^ permalink raw reply

* Re: [PATCH] [ath5k][leds] Ability to disable leds support. If leds support enabled do not force mac802.11 leds layer selection.
From: Bob Copeland @ 2010-06-01 20:34 UTC (permalink / raw)
  To: Dmytro Milinevskyy
  Cc: ath5k-devel, Jiri Slaby, Nick Kossifidis, Luis R. Rodriguez,
	John W. Linville, GeunSik Lim, Greg Kroah-Hartman, Lukas Turek,
	Mark Hindley, Johannes Berg, Jiri Kosina, Kalle Valo, Keng-Yu Lin,
	Luca Verdesca, Shahar Or, linux-wireless, netdev, linux-kernel
In-Reply-To: <4c056b50.0c3fdf0a.500b.44af@mx.google.com>

On Wed, Apr 7, 2010 at 2:58 PM, Dmytro Milinevskyy
<milinevskyy@gmail.com> wrote:
> Hello!

Thanks, comments inline.


> +config ATH5K_LEDS
> +       tristate "Atheros 5xxx wireless cards LEDs support"
> +       depends on ATH5K
> +       ---help---
> +         Atheros 5xxx LED support.
> +

This can select the proper LED classes?  Then you can get rid of another
ifdef check later.

> -/* GPIO-controlled software LED */
> -#define AR5K_SOFTLED_PIN       0
> -#define AR5K_SOFTLED_ON                0
> -#define AR5K_SOFTLED_OFF       1
> -

Please drop this hunk, no problem keeping it around.

> +#ifdef CONFIG_ATH5K_LEDS
>  /* LED functions */
>  int ath5k_init_leds(struct ath5k_softc *sc);
>  void ath5k_led_enable(struct ath5k_softc *sc);
>  void ath5k_led_off(struct ath5k_softc *sc);
>  void ath5k_unregister_leds(struct ath5k_softc *sc);
> +#else
> +#define ath5k_init_leds(sc) do {} while (0)
> +#define ath5k_led_enable(sc) do {} while (0)
> +#define ath5k_led_off(sc) do {} while (0)
> +#define ath5k_unregister_leds(sc) do {} while (0)
> +#endif

I prefer:

#ifdef
...
#else
static inline int ath5k_init_leds(struct ath5k_softc *sc)
{
    return 0;
}
...
#endif

so you get type-checking.  Also this doesn't quite work in your version:

    int foo = ath5k_init_leds(sc);

> +#ifdef CONFIG_ATH5K_LEDS
>  /*
>  * State for LED triggers
>  */
>  struct ath5k_led
>  {
> -       char name[ATH5K_LED_MAX_NAME_LEN + 1];  /* name of the LED in sysfs */
>        struct ath5k_softc *sc;                 /* driver state */
> +#ifdef CONFIG_LEDS_CLASS
> +       char name[ATH5K_LED_MAX_NAME_LEN + 1];  /* name of the LED in sysfs */
>        struct led_classdev led_dev;            /* led classdev */
> +#endif
>  };
> +#endif

Why move name?

>  /* Rfkill */
>  struct ath5k_rfkill {
> @@ -186,9 +190,6 @@ struct ath5k_softc {
>
>        u8                      bssidmask[ETH_ALEN];
>
> -       unsigned int            led_pin,        /* GPIO pin for driving LED */
> -                               led_on;         /* pin setting for LED on */
> -
>        struct tasklet_struct   restq;          /* reset tasklet */
>
>        unsigned int            rxbufsize;      /* rx size based on mtu */
> @@ -196,7 +197,6 @@ struct ath5k_softc {
>        spinlock_t              rxbuflock;
>        u32                     *rxlink;        /* link ptr in last RX desc */
>        struct tasklet_struct   rxtq;           /* rx intr tasklet */
> -       struct ath5k_led        rx_led;         /* rx led */
>
>        struct list_head        txbuf;          /* transmit buffer */
>        spinlock_t              txbuflock;
> @@ -204,7 +204,14 @@ struct ath5k_softc {
>        struct ath5k_txq        txqs[AR5K_NUM_TX_QUEUES];       /* tx queues */
>        struct ath5k_txq        *txq;           /* main tx queue */
>        struct tasklet_struct   txtq;           /* tx intr tasklet */
> +
> +
> +#ifdef CONFIG_ATH5K_LEDS
> +       unsigned int            led_pin,        /* GPIO pin for driving LED */
> +                               led_on;         /* pin setting for LED on */
> +       struct ath5k_led        rx_led;         /* rx led */
>        struct ath5k_led        tx_led;         /* tx led */
> +#endif

You might want to do this in two stages: move the led-dependent things
together in the structure (or into a separate structure) and then only
have one #ifdef section.

Still too many ifdefs in general.

-- 
Bob Copeland %% www.bobcopeland.com

^ permalink raw reply

* [PATCH] [ath5k][leds] Ability to disable leds support. If leds support enabled do not force mac802.11 leds layer selection.
From: Dmytro Milinevskyy @ 2010-04-07 18:58 UTC (permalink / raw)
  To: ath5k-devel
  Cc: Jiri Slaby, Nick Kossifidis, Luis R. Rodriguez, Bob Copeland,
	John W. Linville, GeunSik Lim, Greg Kroah-Hartman, Lukas Turek,
	Mark Hindley, Johannes Berg, Jiri Kosina, Kalle Valo, Keng-Yu Lin,
	Luca Verdesca, Shahar Or, linux-wireless, netdev, linux-kernel,
	Dmytro Milinevskyy

Hello!

Here is the patch to disable ath5k leds support on build stage.
However if the leds support was enabled do not force selection of 802.11 leds layer.

I've applied suggestion given by Pavel Roskin.

Best regards,

--Dima

---
 drivers/net/wireless/ath/ath5k/Kconfig  |   10 +++++++---
 drivers/net/wireless/ath/ath5k/Makefile |    2 +-
 drivers/net/wireless/ath/ath5k/ath5k.h  |   16 +++++++++++-----
 drivers/net/wireless/ath/ath5k/base.h   |   17 ++++++++++++-----
 drivers/net/wireless/ath/ath5k/gpio.c   |    2 ++
 drivers/net/wireless/ath/ath5k/led.c    |    9 +++++++++
 6 files changed, 42 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig
index eb83b7b..6b5677e 100644
--- a/drivers/net/wireless/ath/ath5k/Kconfig
+++ b/drivers/net/wireless/ath/ath5k/Kconfig
@@ -1,9 +1,6 @@
 config ATH5K
 	tristate "Atheros 5xxx wireless cards support"
 	depends on PCI && MAC80211
-	select MAC80211_LEDS
-	select LEDS_CLASS
-	select NEW_LEDS
 	---help---
 	  This module adds support for wireless adapters based on
 	  Atheros 5xxx chipset.
@@ -18,6 +15,13 @@ config ATH5K
 	  If you choose to build a module, it'll be called ath5k. Say M if
 	  unsure.
 
+
+config ATH5K_LEDS
+	tristate "Atheros 5xxx wireless cards LEDs support"
+	depends on ATH5K
+	---help---
+	  Atheros 5xxx LED support.
+
 config ATH5K_DEBUG
 	bool "Atheros 5xxx debugging"
 	depends on ATH5K
diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile
index cc09595..6d552dd 100644
--- a/drivers/net/wireless/ath/ath5k/Makefile
+++ b/drivers/net/wireless/ath/ath5k/Makefile
@@ -10,8 +10,8 @@ ath5k-y				+= phy.o
 ath5k-y				+= reset.o
 ath5k-y				+= attach.o
 ath5k-y				+= base.o
-ath5k-y				+= led.o
 ath5k-y				+= rfkill.o
 ath5k-y				+= ani.o
 ath5k-$(CONFIG_ATH5K_DEBUG)	+= debug.o
+ath5k-$(CONFIG_ATH5K_LEDS) += led.o
 obj-$(CONFIG_ATH5K)		+= ath5k.o
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 2785946..615b9ca 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -920,11 +920,6 @@ enum ath5k_power_mode {
 #define AR5K_LED_ASSOC	3 /*IEEE80211_S_ASSOC*/
 #define AR5K_LED_RUN	4 /*IEEE80211_S_RUN*/
 
-/* GPIO-controlled software LED */
-#define AR5K_SOFTLED_PIN	0
-#define AR5K_SOFTLED_ON		0
-#define AR5K_SOFTLED_OFF	1
-
 /*
  * Chipset capabilities -see ath5k_hw_get_capability-
  * get_capability function is not yet fully implemented
@@ -1148,11 +1143,18 @@ struct ath5k_hw {
 int ath5k_hw_attach(struct ath5k_softc *sc);
 void ath5k_hw_detach(struct ath5k_hw *ah);
 
+#ifdef CONFIG_ATH5K_LEDS
 /* LED functions */
 int ath5k_init_leds(struct ath5k_softc *sc);
 void ath5k_led_enable(struct ath5k_softc *sc);
 void ath5k_led_off(struct ath5k_softc *sc);
 void ath5k_unregister_leds(struct ath5k_softc *sc);
+#else
+#define ath5k_init_leds(sc) do {} while (0)
+#define ath5k_led_enable(sc) do {} while (0)
+#define ath5k_led_off(sc) do {} while (0)
+#define ath5k_unregister_leds(sc) do {} while (0)
+#endif
 
 /* Reset Functions */
 int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial);
@@ -1233,7 +1235,11 @@ int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time);
 int ath5k_hw_init_desc_functions(struct ath5k_hw *ah);
 
 /* GPIO Functions */
+#ifdef CONFIG_ATH5K_LEDS
 void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state);
+#else
+#define ath5k_hw_set_ledstate(ah, state) do {} while (0)
+#endif
 int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio);
 int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio);
 u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio);
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index 56221bc..e493d34 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -86,15 +86,19 @@ struct ath5k_txq {
 
 #define ATH5K_LED_MAX_NAME_LEN 31
 
+#ifdef CONFIG_ATH5K_LEDS
 /*
  * State for LED triggers
  */
 struct ath5k_led
 {
-	char name[ATH5K_LED_MAX_NAME_LEN + 1];	/* name of the LED in sysfs */
 	struct ath5k_softc *sc;			/* driver state */
+#ifdef CONFIG_LEDS_CLASS
+	char name[ATH5K_LED_MAX_NAME_LEN + 1];	/* name of the LED in sysfs */
 	struct led_classdev led_dev;		/* led classdev */
+#endif
 };
+#endif
 
 /* Rfkill */
 struct ath5k_rfkill {
@@ -186,9 +190,6 @@ struct ath5k_softc {
 
 	u8			bssidmask[ETH_ALEN];
 
-	unsigned int		led_pin,	/* GPIO pin for driving LED */
-				led_on;		/* pin setting for LED on */
-
 	struct tasklet_struct	restq;		/* reset tasklet */
 
 	unsigned int		rxbufsize;	/* rx size based on mtu */
@@ -196,7 +197,6 @@ struct ath5k_softc {
 	spinlock_t		rxbuflock;
 	u32			*rxlink;	/* link ptr in last RX desc */
 	struct tasklet_struct	rxtq;		/* rx intr tasklet */
-	struct ath5k_led	rx_led;		/* rx led */
 
 	struct list_head	txbuf;		/* transmit buffer */
 	spinlock_t		txbuflock;
@@ -204,7 +204,14 @@ struct ath5k_softc {
 	struct ath5k_txq	txqs[AR5K_NUM_TX_QUEUES];	/* tx queues */
 	struct ath5k_txq	*txq;		/* main tx queue */
 	struct tasklet_struct	txtq;		/* tx intr tasklet */
+
+
+#ifdef CONFIG_ATH5K_LEDS
+	unsigned int		led_pin,	/* GPIO pin for driving LED */
+				led_on;		/* pin setting for LED on */
+	struct ath5k_led	rx_led;		/* rx led */
 	struct ath5k_led	tx_led;		/* tx led */
+#endif
 
 	struct ath5k_rfkill	rf_kill;
 
diff --git a/drivers/net/wireless/ath/ath5k/gpio.c b/drivers/net/wireless/ath/ath5k/gpio.c
index 64a27e7..9e757b3 100644
--- a/drivers/net/wireless/ath/ath5k/gpio.c
+++ b/drivers/net/wireless/ath/ath5k/gpio.c
@@ -25,6 +25,7 @@
 #include "debug.h"
 #include "base.h"
 
+#ifdef CONFIG_ATH5K_LEDS
 /*
  * Set led state
  */
@@ -76,6 +77,7 @@ void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state)
 	else
 		AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led_5210);
 }
+#endif
 
 /*
  * Set GPIO inputs
diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c
index 67aa52e..df8e8d2 100644
--- a/drivers/net/wireless/ath/ath5k/led.c
+++ b/drivers/net/wireless/ath/ath5k/led.c
@@ -121,6 +121,7 @@ ath5k_led_brightness_set(struct led_classdev *led_dev,
 		ath5k_led_on(led->sc);
 }
 
+#ifdef CONFIG_LEDS_CLASS
 static int
 ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led,
 		   const char *name, char *trigger)
@@ -140,13 +141,16 @@ ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led,
 	}
 	return err;
 }
+#endif
 
 static void
 ath5k_unregister_led(struct ath5k_led *led)
 {
 	if (!led->sc)
 		return;
+#ifdef CONFIG_LEDS_CLASS
 	led_classdev_unregister(&led->led_dev);
+#endif
 	ath5k_led_off(led->sc);
 	led->sc = NULL;
 }
@@ -177,6 +181,7 @@ int ath5k_init_leds(struct ath5k_softc *sc)
 
 	ath5k_led_enable(sc);
 
+#ifdef CONFIG_LEDS_CLASS
 	snprintf(name, sizeof(name), "ath5k-%s::rx", wiphy_name(hw->wiphy));
 	ret = ath5k_register_led(sc, &sc->rx_led, name,
 		ieee80211_get_rx_led_name(hw));
@@ -186,6 +191,10 @@ int ath5k_init_leds(struct ath5k_softc *sc)
 	snprintf(name, sizeof(name), "ath5k-%s::tx", wiphy_name(hw->wiphy));
 	ret = ath5k_register_led(sc, &sc->tx_led, name,
 		ieee80211_get_tx_led_name(hw));
+#else
+    sc->rx_led.sc = sc;
+    sc->tx_led.sc = sc;
+#endif
 out:
 	return ret;
 }
-- 
1.7.1


^ permalink raw reply related

* Re: [PATCHv2] Refactor update of IPv6 flow destination address for srcrt (RH) option
From: Joe Perches @ 2010-06-01 20:08 UTC (permalink / raw)
  To: Arnaud Ebalard
  Cc: David S. Miller,
	YOSHIFUJI Hideaki / 吉藤英明, netdev
In-Reply-To: <8739x6d0ky.fsf@small.ssi.corp>

On Tue, 2010-06-01 at 21:17 +0200, Arnaud Ebalard wrote:
> I received a comment (privately) about the fact that the transform isn't
> equivalent as its sets final_p in all cases now, and asked if it matters?
> 
> It does not: in current code, final_p is always initialized to NULL when
> it is declared. I also verified it is not used by anything between the
> declaration and the code I replace by the helper.
> 
> In fact, one additional thing which can be done is to remove the
> initialization final_p to NULL when it is declared. The updated version
> below does that.
> 
> Patch is against net-2.6. Tested on 2.6.34.
[]
> +static inline struct in6_addr *srcrt_dst_flow_update(struct in6_addr *final,
> +						     struct in6_addr *fl6dst,
> +						     const struct ipv6_txoptions *opt)
> +{
> +	if (opt && opt->srcrt) {
> +		const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt;
> +		ipv6_addr_copy(final, fl6dst);
> +		ipv6_addr_copy(fl6dst, rt0->addr);
> +		return final;
> +	}
> +	return NULL;
> +}
> +

Should this be inline?  Maybe it'd be better moved to exthdrs.c

Perhaps this is clearer as something like:

/**
 * fl6_update_dst - update flow destination address
 *
 * @fl: flowlabel fl_dst to update
 * @opt: struct ipv6_txoptions
 * @orig: original fl_dst if modified
 *
 * Returns NULL if no txoptions or no srcrt, otherwise
 * returns orig and initial value of fl->fl6_dst set in orig
 */
struct in6_addr *fl6_update_dst(struct ip6_flowlabel *fl,
				const struct ipv6_txoptions *opt,
				struct in6_addr *orig)
{
	if (!opt || !opt->srcrt)
		return NULL;

	ipv6_addr_copy(orig, &fl->fl6_dst);
	ipv6_addr_copy(&fl->fl6_dst, ((struct rt0_hdr *)opt->srcrt)->addr);
	return orig;
}



^ permalink raw reply

* [PATCH] xfrm: force a dst reference in __xfrm_route_forward()
From: Eric Dumazet @ 2010-06-01 20:04 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

Packets going through __xfrm_route_forward() have a not refcounted dst
entry, since we enabled a noref forwarding path.

xfrm_lookup() might incorrectly release this dst entry.

It's a bit late to make invasive changes in xfrm_lookup(), so lets force
a refcount in this path.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
 net/xfrm/xfrm_policy.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index d965a2b..4bf27d9 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -2153,6 +2153,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
 		return 0;
 	}
 
+	skb_dst_force(skb);
 	dst = skb_dst(skb);
 
 	res = xfrm_lookup(net, &dst, &fl, NULL, 0) == 0;



^ permalink raw reply related

* [2.6.35-rc1 regression] tg3 vpd r/w failed
From: Mikael Pettersson @ 2010-06-01 20:03 UTC (permalink / raw)
  To: netdev; +Cc: Matt Carlson, linux-kernel

Booting 2.6.35-rc1 on a Sun Blade 2500 Red with builtin tg3 I get:

tg3.c:v3.110 (April 9, 2010)
PCI: Enabling device: (0000:00:03.0), cmd 2
...
tg3 0000:00:03.0: vpd r/w failed.  This is likely a firmware bug on this device.  Contact the card vendor for a firmware update.
tg3 0000:00:03.0: vpd r/w failed.  This is likely a firmware bug on this device.  Contact the card vendor for a firmware update.
tg3 0000:00:03.0: vpd r/w failed.  This is likely a firmware bug on this device.  Contact the card vendor for a firmware update.
tg3 0000:00:03.0: eth0: Tigon3 [partno(none) rev 1002] (PCI:66MHz:64-bit) MAC address ...
tg3 0000:00:03.0: eth0: attached PHY is 5703 (10/100/1000Base-T Ethernet) (WireSpeed[1])
tg3 0000:00:03.0: eth0: RXcsums[1] LinkChgREG[0] MIirq[0] ASF[0] TSOcap[1]
tg3 0000:00:03.0: eth0: dma_rwctrl[763f0000] dma_mask[32-bit]
...
tg3 0000:00:03.0: eth0: No firmware running
tg3 0000:00:03.0: eth0: Link is up at 100 Mbps, full duplex
tg3 0000:00:03.0: eth0: Flow control is on for TX and on for RX

The three 'vpd r/w failed' messages are new and did not occur with 2.6.34
or earlier kernels.

/Mikael

^ permalink raw reply

* Re: [PATCHv2] Refactor update of IPv6 flow destination address for srcrt (RH) option
From: Arnaud Ebalard @ 2010-06-01 19:17 UTC (permalink / raw)
  To: David S. Miller
  Cc: YOSHIFUJI Hideaki / 吉藤英明, netdev
In-Reply-To: <87wruid8rx.fsf@small.ssi.corp>

Hi,

I received a comment (privately) about the fact that the transform isn't
equivalent as its sets final_p in all cases now, and asked if it matters?

It does not: in current code, final_p is always initialized to NULL when
it is declared. I also verified it is not used by anything between the
declaration and the code I replace by the helper.

In fact, one additional thing which can be done is to remove the
initialization final_p to NULL when it is declared. The updated version
below does that.

Patch is against net-2.6. Tested on 2.6.34.

Cheers,

a+


>From 50e59bf48323777a05476e0d094f15b67194f0bd Mon Sep 17 00:00:00 2001
From: Arnaud Ebalard <arno@natisbad.org>
Date: Tue, 1 Jun 2010 19:40:54 +0200
Subject: [PATCHv2] Refactor update of IPv6 flow destination address for srcrt (RH) option

There are more than a dozen occurrences of following code in the
IPv6 stack:

    if (opt && opt->srcrt) {
            struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
            ipv6_addr_copy(&final, &fl.fl6_dst);
            ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
            final_p = &final;
    }

Replace those with a helper. Note that the helper overrides final_p
in all cases. This is ok as final_p was previously initialized to
NULL when declared.

Signed-off-by: Arnaud Ebalard <arno@natisbad.org>
---
 include/net/ipv6.h               |   13 +++++++++++++
 net/dccp/ipv6.c                  |   30 ++++++------------------------
 net/ipv6/af_inet6.c              |    9 ++-------
 net/ipv6/datagram.c              |   18 ++++--------------
 net/ipv6/inet6_connection_sock.c |    9 ++-------
 net/ipv6/raw.c                   |   10 ++--------
 net/ipv6/syncookies.c            |    9 ++-------
 net/ipv6/tcp_ipv6.c              |   27 ++++++---------------------
 net/ipv6/udp.c                   |   11 +++--------
 9 files changed, 40 insertions(+), 96 deletions(-)

diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 2600b69..9edfa1c 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -290,6 +290,19 @@ static inline void ipv6_addr_copy(struct in6_addr *a1, const struct in6_addr *a2
 	memcpy(a1, a2, sizeof(struct in6_addr));
 }
 
+static inline struct in6_addr *srcrt_dst_flow_update(struct in6_addr *final,
+						     struct in6_addr *fl6dst,
+						     const struct ipv6_txoptions *opt)
+{
+	if (opt && opt->srcrt) {
+		const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt;
+		ipv6_addr_copy(final, fl6dst);
+		ipv6_addr_copy(fl6dst, rt0->addr);
+		return final;
+	}
+	return NULL;
+}
+
 static inline void ipv6_addr_prefix(struct in6_addr *pfx, 
 				    const struct in6_addr *addr,
 				    int plen)
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 0916988..38151db 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -248,7 +248,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct sk_buff *skb;
 	struct ipv6_txoptions *opt = NULL;
-	struct in6_addr *final_p = NULL, final;
+	struct in6_addr *final_p, final;
 	struct flowi fl;
 	int err = -1;
 	struct dst_entry *dst;
@@ -265,13 +265,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
 
 	opt = np->opt;
 
-	if (opt != NULL && opt->srcrt != NULL) {
-		const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt;
-
-		ipv6_addr_copy(&final, &fl.fl6_dst);
-		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-		final_p = &final;
-	}
+	final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, opt);
 
 	err = ip6_dst_lookup(sk, &dst, &fl);
 	if (err)
@@ -545,19 +539,13 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
 		goto out_overflow;
 
 	if (dst == NULL) {
-		struct in6_addr *final_p = NULL, final;
+		struct in6_addr *final_p, final;
 		struct flowi fl;
 
 		memset(&fl, 0, sizeof(fl));
 		fl.proto = IPPROTO_DCCP;
 		ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
-		if (opt != NULL && opt->srcrt != NULL) {
-			const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt;
-
-			ipv6_addr_copy(&final, &fl.fl6_dst);
-			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-			final_p = &final;
-		}
+		final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, opt);
 		ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);
 		fl.oif = sk->sk_bound_dev_if;
 		fl.fl_ip_dport = inet_rsk(req)->rmt_port;
@@ -885,7 +873,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 	struct inet_sock *inet = inet_sk(sk);
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct dccp_sock *dp = dccp_sk(sk);
-	struct in6_addr *saddr = NULL, *final_p = NULL, final;
+	struct in6_addr *saddr = NULL, *final_p, final;
 	struct flowi fl;
 	struct dst_entry *dst;
 	int addr_type;
@@ -988,13 +976,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 	fl.fl_ip_sport = inet->inet_sport;
 	security_sk_classify_flow(sk, &fl);
 
-	if (np->opt != NULL && np->opt->srcrt != NULL) {
-		const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
-
-		ipv6_addr_copy(&final, &fl.fl6_dst);
-		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-		final_p = &final;
-	}
+	final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, np->opt);
 
 	err = ip6_dst_lookup(sk, &dst, &fl);
 	if (err)
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index e733942..9df2373 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -651,7 +651,7 @@ int inet6_sk_rebuild_header(struct sock *sk)
 
 	if (dst == NULL) {
 		struct inet_sock *inet = inet_sk(sk);
-		struct in6_addr *final_p = NULL, final;
+		struct in6_addr *final_p, final;
 		struct flowi fl;
 
 		memset(&fl, 0, sizeof(fl));
@@ -665,12 +665,7 @@ int inet6_sk_rebuild_header(struct sock *sk)
 		fl.fl_ip_sport = inet->inet_sport;
 		security_sk_classify_flow(sk, &fl);
 
-		if (np->opt && np->opt->srcrt) {
-			struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
-			ipv6_addr_copy(&final, &fl.fl6_dst);
-			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-			final_p = &final;
-		}
+		final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, np->opt);
 
 		err = ip6_dst_lookup(sk, &dst, &fl);
 		if (err) {
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 7126846..378fd58 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -38,10 +38,11 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 	struct sockaddr_in6	*usin = (struct sockaddr_in6 *) uaddr;
 	struct inet_sock      	*inet = inet_sk(sk);
 	struct ipv6_pinfo      	*np = inet6_sk(sk);
-	struct in6_addr		*daddr, *final_p = NULL, final;
+	struct in6_addr		*daddr, *final_p, final;
 	struct dst_entry	*dst;
 	struct flowi		fl;
 	struct ip6_flowlabel	*flowlabel = NULL;
+	struct ipv6_txoptions   *opt;
 	int			addr_type;
 	int			err;
 
@@ -155,19 +156,8 @@ ipv4_connected:
 
 	security_sk_classify_flow(sk, &fl);
 
-	if (flowlabel) {
-		if (flowlabel->opt && flowlabel->opt->srcrt) {
-			struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt;
-			ipv6_addr_copy(&final, &fl.fl6_dst);
-			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-			final_p = &final;
-		}
-	} else if (np->opt && np->opt->srcrt) {
-		struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
-		ipv6_addr_copy(&final, &fl.fl6_dst);
-		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-		final_p = &final;
-	}
+	opt = flowlabel ? flowlabel->opt : np->opt;
+	final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, opt);
 
 	err = ip6_dst_lookup(sk, &dst, &fl);
 	if (err)
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 0c5e3c3..14b5ec5 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -185,7 +185,7 @@ int inet6_csk_xmit(struct sk_buff *skb)
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct flowi fl;
 	struct dst_entry *dst;
-	struct in6_addr *final_p = NULL, final;
+	struct in6_addr *final_p, final;
 
 	memset(&fl, 0, sizeof(fl));
 	fl.proto = sk->sk_protocol;
@@ -199,12 +199,7 @@ int inet6_csk_xmit(struct sk_buff *skb)
 	fl.fl_ip_dport = inet->inet_dport;
 	security_sk_classify_flow(sk, &fl);
 
-	if (np->opt && np->opt->srcrt) {
-		struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
-		ipv6_addr_copy(&final, &fl.fl6_dst);
-		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-		final_p = &final;
-	}
+	final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, np->opt);
 
 	dst = __inet6_csk_dst_check(sk, np->dst_cookie);
 
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 4a4dcbe..f161a54 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -725,7 +725,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
 {
 	struct ipv6_txoptions opt_space;
 	struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name;
-	struct in6_addr *daddr, *final_p = NULL, final;
+	struct in6_addr *daddr, *final_p, final;
 	struct inet_sock *inet = inet_sk(sk);
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct raw6_sock *rp = raw6_sk(sk);
@@ -847,13 +847,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
 	if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
 		ipv6_addr_copy(&fl.fl6_src, &np->saddr);
 
-	/* merge ip6_build_xmit from ip6_output */
-	if (opt && opt->srcrt) {
-		struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
-		ipv6_addr_copy(&final, &fl.fl6_dst);
-		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-		final_p = &final;
-	}
+	final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, opt);
 
 	if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
 		fl.oif = np->mcast_oif;
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index 34d1f06..edcaa92 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -240,17 +240,12 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
 	 * me if there is a preferred way.
 	 */
 	{
-		struct in6_addr *final_p = NULL, final;
+		struct in6_addr *final_p, final;
 		struct flowi fl;
 		memset(&fl, 0, sizeof(fl));
 		fl.proto = IPPROTO_TCP;
 		ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
-		if (np->opt && np->opt->srcrt) {
-			struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
-			ipv6_addr_copy(&final, &fl.fl6_dst);
-			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-			final_p = &final;
-		}
+		final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, np->opt);
 		ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);
 		fl.oif = sk->sk_bound_dev_if;
 		fl.mark = sk->sk_mark;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 2b7c3a1..212315a 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -129,7 +129,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 	struct inet_connection_sock *icsk = inet_csk(sk);
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct tcp_sock *tp = tcp_sk(sk);
-	struct in6_addr *saddr = NULL, *final_p = NULL, final;
+	struct in6_addr *saddr = NULL, *final_p, final;
 	struct flowi fl;
 	struct dst_entry *dst;
 	int addr_type;
@@ -250,12 +250,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 	fl.fl_ip_dport = usin->sin6_port;
 	fl.fl_ip_sport = inet->inet_sport;
 
-	if (np->opt && np->opt->srcrt) {
-		struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
-		ipv6_addr_copy(&final, &fl.fl6_dst);
-		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-		final_p = &final;
-	}
+	final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, np->opt);
 
 	security_sk_classify_flow(sk, &fl);
 
@@ -477,7 +472,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct sk_buff * skb;
 	struct ipv6_txoptions *opt = NULL;
-	struct in6_addr * final_p = NULL, final;
+	struct in6_addr * final_p, final;
 	struct flowi fl;
 	struct dst_entry *dst;
 	int err = -1;
@@ -494,12 +489,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
 	security_req_classify_flow(req, &fl);
 
 	opt = np->opt;
-	if (opt && opt->srcrt) {
-		struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
-		ipv6_addr_copy(&final, &fl.fl6_dst);
-		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-		final_p = &final;
-	}
+	final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, opt);
 
 	err = ip6_dst_lookup(sk, &dst, &fl);
 	if (err)
@@ -1392,18 +1382,13 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 		goto out_overflow;
 
 	if (dst == NULL) {
-		struct in6_addr *final_p = NULL, final;
+		struct in6_addr *final_p, final;
 		struct flowi fl;
 
 		memset(&fl, 0, sizeof(fl));
 		fl.proto = IPPROTO_TCP;
 		ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
-		if (opt && opt->srcrt) {
-			struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
-			ipv6_addr_copy(&final, &fl.fl6_dst);
-			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-			final_p = &final;
-		}
+		final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, opt);
 		ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr);
 		fl.oif = sk->sk_bound_dev_if;
 		fl.mark = sk->sk_mark;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 87be586..33aa47c 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -927,7 +927,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
 	struct inet_sock *inet = inet_sk(sk);
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name;
-	struct in6_addr *daddr, *final_p = NULL, final;
+	struct in6_addr *daddr, *final_p, final;
 	struct ipv6_txoptions *opt = NULL;
 	struct ip6_flowlabel *flowlabel = NULL;
 	struct flowi fl;
@@ -1097,14 +1097,9 @@ do_udp_sendmsg:
 		ipv6_addr_copy(&fl.fl6_src, &np->saddr);
 	fl.fl_ip_sport = inet->inet_sport;
 
-	/* merge ip6_build_xmit from ip6_output */
-	if (opt && opt->srcrt) {
-		struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
-		ipv6_addr_copy(&final, &fl.fl6_dst);
-		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-		final_p = &final;
+	final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, opt);
+	if (final_p)
 		connected = 0;
-	}
 
 	if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) {
 		fl.oif = np->mcast_oif;
-- 
1.7.1


^ permalink raw reply related

* [net-2.6 PATCH] enic: bug fix: make the set/get netlink VF_PORT support symmetrical
From: Scott Feldman @ 2010-06-01 18:59 UTC (permalink / raw)
  To: davem; +Cc: chrisw, netdev

From: Scott Feldman <scofeldm@cisco.com>

To make get/set netlink VF_PORT truly symmetrical, we need to keep track
of what items are set and only return those items on get.  Previously, the
driver wasn't differentiating between a set of attr with a NULL string,
for example, and not setting the attr at all.  We only want to return
the NULL string if the attr was actually set with a NULL string.  Otherwise,
don't return the attr.

Signed-off-by: Scott Feldman <scofeldm@cisco.com>
---
 drivers/net/enic/enic.h      |    7 +
 drivers/net/enic/enic_main.c |  200 ++++++++++++++++++++----------------------
 2 files changed, 104 insertions(+), 103 deletions(-)


diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index 85f2a2e..45e86d1 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -74,7 +74,14 @@ struct enic_msix_entry {
 	void *devid;
 };
 
+#define ENIC_SET_APPLIED		(1 << 0)
+#define ENIC_SET_REQUEST		(1 << 1)
+#define ENIC_SET_NAME			(1 << 2)
+#define ENIC_SET_INSTANCE		(1 << 3)
+#define ENIC_SET_HOST			(1 << 4)
+
 struct enic_port_profile {
+	u32 set;
 	u8 request;
 	char name[PORT_PROFILE_MAX];
 	u8 instance_uuid[PORT_UUID_MAX];
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 6586b5c..bc7d6b9 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -1029,8 +1029,7 @@ static int enic_dev_init_done(struct enic *enic, int *done, int *error)
 	return err;
 }
 
-static int enic_set_port_profile(struct enic *enic, u8 request, u8 *mac,
-	char *name, u8 *instance_uuid, u8 *host_uuid)
+static int enic_set_port_profile(struct enic *enic, u8 *mac)
 {
 	struct vic_provinfo *vp;
 	u8 oui[3] = VIC_PROVINFO_CISCO_OUI;
@@ -1040,97 +1039,112 @@ static int enic_set_port_profile(struct enic *enic, u8 request, u8 *mac,
 		"%02X%02X-%02X%02X%02X%02X%0X%02X";
 	int err;
 
-	if (!name)
-		return -EINVAL;
+	err = enic_vnic_dev_deinit(enic);
+	if (err)
+		return err;
 
-	if (!is_valid_ether_addr(mac))
-		return -EADDRNOTAVAIL;
+	switch (enic->pp.request) {
 
-	vp = vic_provinfo_alloc(GFP_KERNEL, oui, VIC_PROVINFO_LINUX_TYPE);
-	if (!vp)
-		return -ENOMEM;
+	case PORT_REQUEST_ASSOCIATE:
 
-	vic_provinfo_add_tlv(vp,
-		VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR,
-		strlen(name) + 1, name);
-
-	vic_provinfo_add_tlv(vp,
-		VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR,
-		ETH_ALEN, mac);
-
-	if (instance_uuid) {
-		uuid = instance_uuid;
-		sprintf(uuid_str, uuid_fmt,
-			uuid[0],  uuid[1],  uuid[2],  uuid[3],
-			uuid[4],  uuid[5],  uuid[6],  uuid[7],
-			uuid[8],  uuid[9],  uuid[10], uuid[11],
-			uuid[12], uuid[13], uuid[14], uuid[15]);
-		vic_provinfo_add_tlv(vp,
-			VIC_LINUX_PROV_TLV_CLIENT_UUID_STR,
-			sizeof(uuid_str), uuid_str);
-	}
+		if (!(enic->pp.set & ENIC_SET_NAME) || !strlen(enic->pp.name))
+			return -EINVAL;
 
-	if (host_uuid) {
-		uuid = host_uuid;
-		sprintf(uuid_str, uuid_fmt,
-			uuid[0],  uuid[1],  uuid[2],  uuid[3],
-			uuid[4],  uuid[5],  uuid[6],  uuid[7],
-			uuid[8],  uuid[9],  uuid[10], uuid[11],
-			uuid[12], uuid[13], uuid[14], uuid[15]);
-		vic_provinfo_add_tlv(vp,
-			VIC_LINUX_PROV_TLV_HOST_UUID_STR,
-			sizeof(uuid_str), uuid_str);
-	}
+		if (!is_valid_ether_addr(mac))
+			return -EADDRNOTAVAIL;
 
-	err = enic_vnic_dev_deinit(enic);
-	if (err)
-		goto err_out;
+		vp = vic_provinfo_alloc(GFP_KERNEL, oui,
+			VIC_PROVINFO_LINUX_TYPE);
+		if (!vp)
+			return -ENOMEM;
 
-	memset(&enic->pp, 0, sizeof(enic->pp));
+		vic_provinfo_add_tlv(vp,
+			VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR,
+			strlen(enic->pp.name) + 1, enic->pp.name);
 
-	err = enic_dev_init_prov(enic, vp);
-	if (err)
-		goto err_out;
+		vic_provinfo_add_tlv(vp,
+			VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR,
+			ETH_ALEN, mac);
+
+		if (enic->pp.set & ENIC_SET_INSTANCE) {
+			uuid = enic->pp.instance_uuid;
+			sprintf(uuid_str, uuid_fmt,
+				uuid[0],  uuid[1],  uuid[2],  uuid[3],
+				uuid[4],  uuid[5],  uuid[6],  uuid[7],
+				uuid[8],  uuid[9],  uuid[10], uuid[11],
+				uuid[12], uuid[13], uuid[14], uuid[15]);
+			vic_provinfo_add_tlv(vp,
+				VIC_LINUX_PROV_TLV_CLIENT_UUID_STR,
+				sizeof(uuid_str), uuid_str);
+		}
 
-	enic->pp.request = request;
-	memcpy(enic->pp.name, name, PORT_PROFILE_MAX);
-	if (instance_uuid)
-		memcpy(enic->pp.instance_uuid,
-			instance_uuid, PORT_UUID_MAX);
-	if (host_uuid)
-		memcpy(enic->pp.host_uuid,
-			host_uuid, PORT_UUID_MAX);
+		if (enic->pp.set & ENIC_SET_HOST) {
+			uuid = enic->pp.host_uuid;
+			sprintf(uuid_str, uuid_fmt,
+				uuid[0],  uuid[1],  uuid[2],  uuid[3],
+				uuid[4],  uuid[5],  uuid[6],  uuid[7],
+				uuid[8],  uuid[9],  uuid[10], uuid[11],
+				uuid[12], uuid[13], uuid[14], uuid[15]);
+			vic_provinfo_add_tlv(vp,
+				VIC_LINUX_PROV_TLV_HOST_UUID_STR,
+				sizeof(uuid_str), uuid_str);
+		}
 
-err_out:
-	vic_provinfo_free(vp);
+		err = enic_dev_init_prov(enic, vp);
+		vic_provinfo_free(vp);
+		if (err)
+			return err;
+		break;
 
-	return err;
-}
+	case PORT_REQUEST_DISASSOCIATE:
+		break;
 
-static int enic_unset_port_profile(struct enic *enic)
-{
-	memset(&enic->pp, 0, sizeof(enic->pp));
-	return enic_vnic_dev_deinit(enic);
+	default:
+		return -EINVAL;
+	}
+
+	enic->pp.set |= ENIC_SET_APPLIED;
+	return 0;
 }
 
 static int enic_set_vf_port(struct net_device *netdev, int vf,
 	struct nlattr *port[])
 {
 	struct enic *enic = netdev_priv(netdev);
-	char *name = NULL;
-	u8 *instance_uuid = NULL;
-	u8 *host_uuid = NULL;
-	u8 request = PORT_REQUEST_DISASSOCIATE;
+
+	memset(&enic->pp, 0, sizeof(enic->pp));
+
+	if (port[IFLA_PORT_REQUEST]) {
+		enic->pp.set |= ENIC_SET_REQUEST;
+		enic->pp.request = nla_get_u8(port[IFLA_PORT_REQUEST]);
+	}
+
+	if (port[IFLA_PORT_PROFILE]) {
+		enic->pp.set |= ENIC_SET_NAME;
+		memcpy(enic->pp.name, nla_data(port[IFLA_PORT_PROFILE]),
+			PORT_PROFILE_MAX);
+	}
+
+	if (port[IFLA_PORT_INSTANCE_UUID]) {
+		enic->pp.set |= ENIC_SET_INSTANCE;
+		memcpy(enic->pp.instance_uuid,
+			nla_data(port[IFLA_PORT_INSTANCE_UUID]), PORT_UUID_MAX);
+	}
+
+	if (port[IFLA_PORT_HOST_UUID]) {
+		enic->pp.set |= ENIC_SET_HOST;
+		memcpy(enic->pp.host_uuid,
+			nla_data(port[IFLA_PORT_HOST_UUID]), PORT_UUID_MAX);
+	}
 
 	/* don't support VFs, yet */
 	if (vf != PORT_SELF_VF)
 		return -EOPNOTSUPP;
 
-	if (port[IFLA_PORT_REQUEST])
-		request = nla_get_u8(port[IFLA_PORT_REQUEST]);
+	if (!(enic->pp.set & ENIC_SET_REQUEST))
+		return -EOPNOTSUPP;
 
-	switch (request) {
-	case PORT_REQUEST_ASSOCIATE:
+	if (enic->pp.request == PORT_REQUEST_ASSOCIATE) {
 
 		/* If the interface mac addr hasn't been assigned,
 		 * assign a random mac addr before setting port-
@@ -1139,30 +1153,9 @@ static int enic_set_vf_port(struct net_device *netdev, int vf,
 
 		if (is_zero_ether_addr(netdev->dev_addr))
 			random_ether_addr(netdev->dev_addr);
-
-		if (port[IFLA_PORT_PROFILE])
-			name = nla_data(port[IFLA_PORT_PROFILE]);
-
-		if (port[IFLA_PORT_INSTANCE_UUID])
-			instance_uuid =
-				nla_data(port[IFLA_PORT_INSTANCE_UUID]);
-
-		if (port[IFLA_PORT_HOST_UUID])
-			host_uuid = nla_data(port[IFLA_PORT_HOST_UUID]);
-
-		return enic_set_port_profile(enic, request,
-			netdev->dev_addr, name,
-			instance_uuid, host_uuid);
-
-	case PORT_REQUEST_DISASSOCIATE:
-
-		return enic_unset_port_profile(enic);
-
-	default:
-		break;
 	}
 
-	return -EOPNOTSUPP;
+	return enic_set_port_profile(enic, netdev->dev_addr);
 }
 
 static int enic_get_vf_port(struct net_device *netdev, int vf,
@@ -1172,14 +1165,12 @@ static int enic_get_vf_port(struct net_device *netdev, int vf,
 	int err, error, done;
 	u16 response = PORT_PROFILE_RESPONSE_SUCCESS;
 
-	/* don't support VFs, yet */
-	if (vf != PORT_SELF_VF)
-		return -EOPNOTSUPP;
+	if (!(enic->pp.set & ENIC_SET_APPLIED))
+		return -ENODATA;
 
 	err = enic_dev_init_done(enic, &done, &error);
-
 	if (err)
-		return err;
+		error = err;
 
 	switch (error) {
 	case ERR_SUCCESS:
@@ -1202,12 +1193,15 @@ static int enic_get_vf_port(struct net_device *netdev, int vf,
 
 	NLA_PUT_U16(skb, IFLA_PORT_REQUEST, enic->pp.request);
 	NLA_PUT_U16(skb, IFLA_PORT_RESPONSE, response);
-	NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX,
-		enic->pp.name);
-	NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX,
-		enic->pp.instance_uuid);
-	NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX,
-		enic->pp.host_uuid);
+	if (enic->pp.set & ENIC_SET_NAME)
+		NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX,
+			enic->pp.name);
+	if (enic->pp.set & ENIC_SET_INSTANCE)
+		NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX,
+			enic->pp.instance_uuid);
+	if (enic->pp.set & ENIC_SET_HOST)
+		NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX,
+			enic->pp.host_uuid);
 
 	return 0;
 


^ permalink raw reply related

* Re: [RFC] netfilter: WIP: Xtables idletimer target implementation
From: Luciano Coelho @ 2010-06-01 18:41 UTC (permalink / raw)
  To: ext Jan Engelhardt
  Cc: ext Patrick McHardy, netfilter-devel@vger.kernel.org,
	netdev@vger.kernel.org, Timo Teras
In-Reply-To: <alpine.LSU.2.01.1006012035350.15461@obet.zrqbmnf.qr>

On Tue, 2010-06-01 at 20:38 +0200, ext Jan Engelhardt wrote:
> On Tuesday 2010-06-01 20:33, Luciano Coelho wrote:
> >On Mon, 2010-05-31 at 21:51 +0200, ext Jan Engelhardt wrote:
> >> On Monday 2010-05-31 21:12, Luciano Coelho wrote:
> >> >
> >> >I considered this option, but then I didn't find a proper place where to
> >> >include the attribute in sysfs, since I cannot add it as part of the
> >> >interface (eg. /sys/class/net/wlan0/idletimer) as I was doing before.
> >> 
> >> You couldn't have done that before either, because the interface name
> >> in ipt_ip may refer to an interface that does not exist at all times.
> >> 
> >> >The other option would be to make the idletimer as part of the
> >> >xt_IDLETIMER module object in sysfs
> >> >(ie. /sys/module/xt_IDLETIMER/<user_supplied_name>), but it looks out of
> >> >place.
> >> 
> >> I like it. It follows /proc/net/xt_{hashlimit,recent}/<user_supplied_name>.
> >
> >I'm starting to like this more and more too, as my code is getting much
> >smaller ;)
> >
> >One quick question, though.  Do you have any ideas on how I can make
> >sure that the user doesn't supply the same name twice (ie. two rules
> >with the same user_supplied_name)?
> 
> What's so bad about multiple rules being able to reset the timer?

Ahhmm... Nothing! Thank you, I think I'm getting code-blind :)

-- 
Cheers,
Luca.


^ permalink raw reply

* Re: [v5 Patch 1/3] netpoll: add generic support for bridge and bonding devices
From: Jay Vosburgh @ 2010-06-01 18:42 UTC (permalink / raw)
  To: Cong Wang
  Cc: Flavio Leitner, linux-kernel, Matt Mackall, netdev, bridge,
	Andy Gospodarek, Neil Horman, Jeff Moyer, Stephen Hemminger,
	bonding-devel, David Miller
In-Reply-To: <4C04D98D.4020509@redhat.com>

Cong Wang <amwang@redhat.com> wrote:

>On 06/01/10 03:08, Flavio Leitner wrote:
>> On Mon, May 31, 2010 at 01:56:52PM +0800, Cong Wang wrote:
>>> Hi, Flavio,
>>>
>>> Please use the attached patch instead, try to see if it solves
>>> all your problems.
>>
>> I tried and it hangs. No backtraces this time.
>> The bond_change_active_slave() prints before NETDEV_BONDING_FAILOVER
>> notification, so I think it won't work.
>
>Ah, I thought the same.
>
>>
>> Please, correct if I'm wrong, but when a failover happens with your
>> patch applied, the netconsole would be disabled forever even with
>> another healthy slave, right?
>>
>
>Yes, this is an easy solution, because bonding has several modes,
>it is complex to make netpoll work in different modes.

	If I understand correctly, the root cause of the problem with
netconsole and bonding is that bonding is, ultimately, performing
printks with a write lock held, and when netconsole recursively calls
into bonding to send the printk over the netconsole, there is a deadlock
(when the bonding xmit function attempts to acquire the same lock for
read).

	You're trying to avoid the deadlock by shutting off netconsole
(permanently, it looks like) for one problem case: a failover, which
does some printks with a write lock held.

	This doesn't look to me like a complete solution, there are
other cases in bonding that will do printk with write locks held.  I
suspect those will also hang netconsole as things exist today, and won't
be affected by your patch below.

	For example:

	The sysfs functions to set the primary (bonding_store_primary)
or active (bonding_store_active_slave) options: a pr_info is called to
provide a log message of the results.  These could be tested by setting
the primary or active options via sysfs, e.g.,

echo eth0 > /sys/class/net/bond0/bonding/primary
echo eth0 > /sys/class/net/bond0/bonding/active

	If the kernel is defined with DEBUG, there are a few pr_debug
calls within write_locks (bond_del_vlan, for example).

	If the slave's underlying device driver's ndo_vlan_rx_register
or ndo_vlan_rx_kill_vid functions call printk (and it looks like some do
for error cases, e.g., igbvf, ehea, enic), those would also presumably
deadlock (because bonding holds its write_lock when calling the ndo_
vlan functions).

	It also appears that (with the patch below) some nominally
normal usage patterns will immediately disable netconsole.  The one that
comes to mind is if the primary= option is set (to "eth1" for this
example), but that slave not enslaved first (the slaves are added, say,
eth0 then eth1).  In that situation, when the primary slave (eth1 here)
is added, the first thing that will happen is a failover, and that will
disable netconsole.

	Thoughts?

	-J

>Would you like to test the following patch?
>
>Thanks much!
>
>diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
>index 5e12462..59ade92 100644
>--- a/drivers/net/bonding/bond_main.c
>+++ b/drivers/net/bonding/bond_main.c
>@@ -1109,6 +1109,14 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
> 	if (old_active == new_active)
> 		return;
>
>+	write_unlock_bh(&bond->curr_slave_lock);
>+	read_unlock(&bond->lock);
>+
>+	netdev_bonding_change(bond->dev, NETDEV_BONDING_DESLAVE);
>+
>+	read_lock(&bond->lock);
>+	write_lock_bh(&bond->curr_slave_lock);
>+
> 	if (new_active) {
> 		new_active->jiffies = jiffies;
>

---
	-Jay Vosburgh, IBM Linux Technology Center, fubar@us.ibm.com

^ permalink raw reply

* [PATCH] iproute2: add VF_PORT support
From: Scott Feldman @ 2010-06-01 18:40 UTC (permalink / raw)
  To: shemminger; +Cc: chrisw, netdev, arnd

From: Scott Feldman <scofeldm@cisco.com>

Add support for recently added IFLA_VF_PORTS.  VF port netlink msg layout is

        [IFLA_NUM_VF]
        [IFLA_VF_PORTS]
                [IFLA_VF_PORT]
                        [IFLA_PORT_*], ...
                [IFLA_VF_PORT]
                        [IFLA_PORT_*], ...
                ...
        [IFLA_PORT_SELF]
                [IFLA_PORT_*], ...

The iproute2 cmd line for link set is now:

Usage: ip link add link DEV [ name ] NAME
                   [ txqueuelen PACKETS ]
                   [ address LLADDR ]
                   [ broadcast LLADDR ]
                   [ mtu MTU ]
                   type TYPE [ ARGS ]
       ip link delete DEV type TYPE [ ARGS ]

       ip link set DEVICE [ { up | down } ]
                          [ arp { on | off } ]
                          [ dynamic { on | off } ]
                          [ multicast { on | off } ]
                          [ allmulticast { on | off } ]
                          [ promisc { on | off } ]
                          [ trailers { on | off } ]
                          [ txqueuelen PACKETS ]
                          [ name NEWNAME ]
                          [ address LLADDR ]
                          [ broadcast LLADDR ]
                          [ mtu MTU ]
                          [ netns PID ]
                          [ alias NAME ]
                          [ port MODE { PROFILE | VSI } ]
                          [ vf NUM [ mac LLADDR ]
                                   [ vlan VLANID [ qos VLAN-QOS ] ]
                                   [ rate TXRATE ]
                                   [ port MODE { PROFILE | VSI } ] ]
       ip link show [ DEVICE ]

TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | can }
MODE := { assoc | preassoc | preassocrr | disassoc }
PROFILE := profile PROFILE
           [ instance UUID ]
           [ host UUID ]
VSI := vsi mgr MGRID type VTID ver VER
       [ instance UUID ]

Signed-off-by: Scott Feldman <scofeldm@cisco.com>
---
 ip/ipaddress.c |  115 ++++++++++++++++++++++++++++
 ip/iplink.c    |  227 +++++++++++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 304 insertions(+), 38 deletions(-)


diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 3a411b1..5c3e696 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -187,6 +187,107 @@ static void print_linktype(FILE *fp, struct rtattr *tb)
 	}
 }
 
+static void print_port(FILE *fp, struct rtattr *port[])
+{
+	struct ifla_port_vsi *vsi;
+#define uuid_fmt "%02X%02X%02X%02X-%02X%02X-%02X%02X-" \
+	"%02X%02X-%02X%02X%02X%02X%02X%02X"
+	unsigned char *uuid;
+	__u8 request;
+	__u16 response;
+
+	if (port[IFLA_PORT_VF])
+		fprintf(fp, "\n    vf %d port",
+			*(__u32 *)RTA_DATA(port[IFLA_PORT_VF]));
+	else
+		fprintf(fp, "\n    port");
+
+	if (port[IFLA_PORT_REQUEST]) {
+		request = *(__u8 *)RTA_DATA(port[IFLA_PORT_REQUEST]);
+		fprintf(fp, " %s",
+			request == PORT_REQUEST_PREASSOCIATE ? "preassoc" :
+			request == PORT_REQUEST_PREASSOCIATE_RR ? "preassocrr" :
+			request == PORT_REQUEST_ASSOCIATE ? "assoc" :
+			request == PORT_REQUEST_DISASSOCIATE ? "disassoc" :
+			"unknown request");
+	}
+
+	if (port[IFLA_PORT_PROFILE])
+		fprintf(fp, " profile \"%s\"",
+			(char *)RTA_DATA(port[IFLA_PORT_PROFILE]));
+
+	if (port[IFLA_PORT_VSI_TYPE]) {
+		vsi = RTA_DATA(port[IFLA_PORT_VSI_TYPE]);
+		fprintf(fp, " vsi mgr %d type 0x%02x%02x%02x ver %d",
+			vsi->vsi_mgr_id, vsi->vsi_type_id[0],
+			vsi->vsi_type_id[1], vsi->vsi_type_id[2],
+			vsi->vsi_type_version);
+	}
+
+	if (port[IFLA_PORT_RESPONSE]) {
+		response = *(__u16 *)RTA_DATA(port[IFLA_PORT_RESPONSE]);
+		fprintf(fp, " status: %s",
+			response == PORT_VDP_RESPONSE_SUCCESS ?
+				"SUCCESS" :
+			response == PORT_VDP_RESPONSE_INVALID_FORMAT ?
+				"INVALID FORMAT" :
+			response == PORT_VDP_RESPONSE_INSUFFICIENT_RESOURCES ?
+				"INSUFFICIENT RESOURCES" :
+			response == PORT_VDP_RESPONSE_UNUSED_VTID ?
+				"UNUSED VTID" :
+			response == PORT_VDP_RESPONSE_VTID_VIOLATION ?
+				"VTID VIOLATION" :
+			response == PORT_VDP_RESPONSE_VTID_VERSION_VIOALTION ?
+				"VTID VERSION VIOLATION" :
+			response == PORT_VDP_RESPONSE_OUT_OF_SYNC ?
+				"OUT-OF-SYNC" :
+			response == PORT_PROFILE_RESPONSE_SUCCESS ?
+				"SUCCESS" :
+			response == PORT_PROFILE_RESPONSE_INPROGRESS ?
+				"IN-PROGRESS" :
+			response == PORT_PROFILE_RESPONSE_INVALID ?
+				"INVALID" :
+			response == PORT_PROFILE_RESPONSE_BADSTATE ?
+				"BAD STATE" :
+			response ==PORT_PROFILE_RESPONSE_INSUFFICIENT_RESOURCES?
+				"INSUFFICIENT RESOURCES" :
+			response == PORT_PROFILE_RESPONSE_ERROR ?
+				"ERROR" :
+			"UNKNOWN RESPONSE");
+	}
+
+	if (port[IFLA_PORT_INSTANCE_UUID]) {
+		uuid = RTA_DATA(port[IFLA_PORT_INSTANCE_UUID]);
+		fprintf(fp, "\n        instance "uuid_fmt,
+			uuid[0],  uuid[1],  uuid[2],  uuid[3],
+			uuid[4],  uuid[5],  uuid[6],  uuid[7],
+			uuid[8],  uuid[9],  uuid[10], uuid[11],
+			uuid[12], uuid[13], uuid[14], uuid[15]);
+	}
+
+	if (port[IFLA_PORT_HOST_UUID]) {
+		uuid = RTA_DATA(port[IFLA_PORT_HOST_UUID]);
+		fprintf(fp, "\n            host "uuid_fmt,
+			uuid[0],  uuid[1],  uuid[2],  uuid[3],
+			uuid[4],  uuid[5],  uuid[6],  uuid[7],
+			uuid[8],  uuid[9],  uuid[10], uuid[11],
+			uuid[12], uuid[13], uuid[14], uuid[15]);
+	}
+}
+
+static void print_vfport(FILE *fp, struct rtattr *vfport)
+{
+	struct rtattr *port[IFLA_PORT_MAX+1];
+
+	if (vfport->rta_type != IFLA_VF_PORT) {
+		fprintf(stderr, "BUG: rta type is %d\n", vfport->rta_type);
+		return;
+	}
+
+	parse_rtattr_nested(port, IFLA_PORT_MAX, vfport);
+	print_port(fp, port);
+}
+
 static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
 {
 	struct ifla_vf_mac *vf_mac;
@@ -421,6 +522,20 @@ int print_linkinfo(const struct sockaddr_nl *who,
 			print_vfinfo(fp, i);
 	}
 
+	if (do_link && tb[IFLA_PORT_SELF]) {
+		struct rtattr *port[IFLA_PORT_MAX+1];
+		parse_rtattr_nested(port, IFLA_PORT_MAX, tb[IFLA_PORT_SELF]);
+		print_port(fp, port);
+	}
+
+	if (do_link && tb[IFLA_VF_PORTS] && tb[IFLA_NUM_VF]) {
+		struct rtattr *i, *vfports = tb[IFLA_VF_PORTS];
+		int rem = RTA_PAYLOAD(vfports);
+		for (i = RTA_DATA(vfports); RTA_OK(i, rem);
+			i = RTA_NEXT(i, rem))
+			print_vfport(fp, i);
+	}
+
 	fprintf(fp, "\n");
 	fflush(fp);
 	return 0;
diff --git a/ip/iplink.c b/ip/iplink.c
index cb2c4f5..04f55ee 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -68,14 +68,22 @@ void iplink_usage(void)
 	fprintf(stderr, "	                  [ mtu MTU ]\n");
 	fprintf(stderr, "	                  [ netns PID ]\n");
 	fprintf(stderr, "			  [ alias NAME ]\n");
+	fprintf(stderr, "			  [ port MODE { PROFILE | VSI } ]\n");
 	fprintf(stderr, "	                  [ vf NUM [ mac LLADDR ]\n");
 	fprintf(stderr, "				   [ vlan VLANID [ qos VLAN-QOS ] ]\n");
-	fprintf(stderr, "				   [ rate TXRATE ] ] \n");
+	fprintf(stderr, "				   [ rate TXRATE ]\n");
+	fprintf(stderr, "				   [ port MODE { PROFILE | VSI } ] ]\n");
 	fprintf(stderr, "       ip link show [ DEVICE ]\n");
 
 	if (iplink_have_newlink()) {
 		fprintf(stderr, "\n");
 		fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | can }\n");
+		fprintf(stderr, "MODE := { assoc | preassoc | preassocrr | disassoc }\n");
+		fprintf(stderr, "PROFILE := profile PROFILE\n");
+		fprintf(stderr, "           [ instance UUID ]\n");
+		fprintf(stderr, "           [ host UUID ]\n");
+		fprintf(stderr, "VSI := vsi mgr MGRID type VTID ver VER\n");
+		fprintf(stderr, "       [ instance UUID ]\n");
 	}
 	exit(-1);
 }
@@ -176,55 +184,170 @@ struct iplink_req {
 	char			buf[1024];
 };
 
-int iplink_parse_vf(int vf, int *argcp, char ***argvp,
-			   struct iplink_req *req)
+void iplink_parse_port(int vf, int *argcp, char ***argvp,
+		       struct iplink_req *req)
+{
+	int argc = *argcp;
+	char **argv = *argvp;
+	struct rtattr *nest, *nest_inner = NULL;
+	struct ifla_port_vsi port_vsi;
+	char *port_profile = NULL;
+	char *instance_uuid = NULL;
+	char *host_uuid = NULL;
+	unsigned char uuid[16];
+	char *uuid_fmt = "%02X%02X%02X%02X-%02X%02X-%02X%02X-"
+		"%02X%02X-%02X%02X%02X%02X%02X%02X";
+	int parsed;
+	int manager_id = -1;
+	int type_id = -1;
+	int type_id_version = -1;
+	int request = -1;
+	int vsi = 0;
+
+	if (NEXT_ARG_OK()) {
+		NEXT_ARG();
+		if (matches(*argv, "assoc") == 0)
+			request = PORT_REQUEST_ASSOCIATE;
+		else if (matches(*argv, "preassoc") == 0)
+			request = PORT_REQUEST_PREASSOCIATE;
+		else if (matches(*argv, "preassocrr") == 0)
+			request = PORT_REQUEST_PREASSOCIATE_RR;
+		else if (matches(*argv, "disassoc") == 0)
+			request = PORT_REQUEST_DISASSOCIATE;
+	}
+
+	while (NEXT_ARG_OK()) {
+		NEXT_ARG();
+		if (matches(*argv, "vsi") == 0) {
+			vsi = 1;
+		} else if (matches(*argv, "mgr") == 0) {
+			NEXT_ARG();
+			if (get_integer(&manager_id, *argv, 0))
+				invarg("Invalid \"mgr\" value\n", *argv);
+		} else if (matches(*argv, "type") == 0) {
+			NEXT_ARG();
+			if (get_integer(&type_id, *argv, 0))
+				invarg("Invalid \"type\" value\n", *argv);
+		} else if (matches(*argv, "ver") == 0) {
+			NEXT_ARG();
+			if (get_integer(&type_id_version, *argv, 0))
+				invarg("Invalid \"ver\" value\n", *argv);
+		} else if (matches(*argv, "profile") == 0) {
+			NEXT_ARG();
+			port_profile = *argv;
+		} else if (matches(*argv, "instance") == 0) {
+			NEXT_ARG();
+			instance_uuid = *argv;
+		} else if (matches(*argv, "host") == 0) {
+			NEXT_ARG();
+			host_uuid = *argv;
+		} else {
+			/* rewind arg */
+			PREV_ARG();
+			break;
+		}
+	}
+
+	if (argc == *argcp)
+		incomplete_command();
+
+	if (vf == PORT_SELF_VF) {
+		nest = addattr_nest(&req->n, sizeof(*req), IFLA_PORT_SELF);
+	} else {
+		nest = addattr_nest(&req->n, sizeof(*req), IFLA_VF_PORTS);
+		nest_inner = addattr_nest(&req->n, sizeof(*req), IFLA_VF_PORT);
+		addattr_l(&req->n, sizeof(*req), IFLA_PORT_VF,
+			(uint32_t *)&vf, sizeof(uint32_t));
+	}
+
+	if (port_profile)
+		addattr_l(&req->n, sizeof(*req), IFLA_PORT_PROFILE,
+			port_profile, strlen(port_profile));
+
+	if (instance_uuid) {
+		parsed = sscanf(instance_uuid, uuid_fmt,
+			&uuid[0],  &uuid[1],  &uuid[2],  &uuid[3],
+			&uuid[4],  &uuid[5],  &uuid[6],  &uuid[7],
+			&uuid[8],  &uuid[9],  &uuid[10], &uuid[11],
+			&uuid[12], &uuid[13], &uuid[14], &uuid[15]);
+		if (parsed != sizeof(uuid))
+			invarg("Invalid \"uuid\" value\n", instance_uuid);
+		addattr_l(&req->n, sizeof(*req), IFLA_PORT_INSTANCE_UUID,
+			uuid, sizeof(uuid));
+
+	}
+
+	if (host_uuid) {
+		parsed = sscanf(host_uuid, uuid_fmt,
+			&uuid[0],  &uuid[1],  &uuid[2],  &uuid[3],
+			&uuid[4],  &uuid[5],  &uuid[6],  &uuid[7],
+			&uuid[8],  &uuid[9],  &uuid[10], &uuid[11],
+			&uuid[12], &uuid[13], &uuid[14], &uuid[15]);
+		if (parsed != sizeof(uuid))
+			invarg("Invalid \"uuid\" value\n", host_uuid);
+		addattr_l(&req->n, sizeof(*req), IFLA_PORT_HOST_UUID,
+			uuid, sizeof(uuid));
+
+	}
+
+	if (vsi) {
+		port_vsi.vsi_mgr_id = manager_id;
+		memcpy(&port_vsi.vsi_type_id, &type_id,
+			sizeof(port_vsi.vsi_type_id));
+		port_vsi.vsi_type_version = type_id_version;
+		addattr_l(&req->n, sizeof(*req), IFLA_PORT_VSI_TYPE,
+			&port_vsi, sizeof(port_vsi));
+	}
+
+	addattr_l(&req->n, sizeof(*req), IFLA_PORT_REQUEST,
+		&request, 1);
+
+	if (nest_inner)
+		addattr_nest_end(&req->n, nest_inner);
+	addattr_nest_end(&req->n, nest);
+
+	*argcp = argc;
+	*argvp = argv;
+}
+
+void iplink_parse_vf(int vf, int *argcp, char ***argvp,
+		     struct iplink_req *req)
 {
 	int len, argc = *argcp;
 	char **argv = *argvp;
+	struct rtattr *vflist;
 	struct rtattr *vfinfo;
-
-	vfinfo = addattr_nest(&req->n, sizeof(*req), IFLA_VF_INFO);
+	char *mac = NULL;
+	char *vlan = NULL;
+	char *qos = NULL;
+	char *rate = NULL;
+	struct ifla_vf_mac ivm = { .vf = vf, };
+	struct ifla_vf_vlan ivv = { .vf = vf, .qos = 0, };
+	struct ifla_vf_tx_rate ivt = { .vf = vf, };
 
 	while (NEXT_ARG_OK()) {
 		NEXT_ARG();
-		if (matches(*argv, "mac") == 0) {
-			struct ifla_vf_mac ivm;
+		if (matches(*argv, "port") == 0) {
+			iplink_parse_port(vf, &argc, &argv, req);
+		} else if (matches(*argv, "mac") == 0) {
 			NEXT_ARG();
-			ivm.vf = vf;
-			len = ll_addr_a2n((char *)ivm.mac, 32, *argv);
-			if (len < 0)
-				return -1;
-			addattr_l(&req->n, sizeof(*req), IFLA_VF_MAC, &ivm, sizeof(ivm));
+			mac = *argv;
 		} else if (matches(*argv, "vlan") == 0) {
-			struct ifla_vf_vlan ivv;
 			NEXT_ARG();
-			if (get_unsigned(&ivv.vlan, *argv, 0)) {
-				invarg("Invalid \"vlan\" value\n", *argv);
-			}
-			ivv.vf = vf;
-			ivv.qos = 0;
+			vlan = *argv;
 			if (NEXT_ARG_OK()) {
 				NEXT_ARG();
 				if (matches(*argv, "qos") == 0) {
 					NEXT_ARG();
-					if (get_unsigned(&ivv.qos, *argv, 0)) {
-						invarg("Invalid \"qos\" value\n", *argv);
-					}
+					qos = *argv;
 				} else {
 					/* rewind arg */
 					PREV_ARG();
 				}
 			}
-			addattr_l(&req->n, sizeof(*req), IFLA_VF_VLAN, &ivv, sizeof(ivv));
 		} else if (matches(*argv, "rate") == 0) {
-			struct ifla_vf_tx_rate ivt;
 			NEXT_ARG();
-			if (get_unsigned(&ivt.rate, *argv, 0)) {
-				invarg("Invalid \"rate\" value\n", *argv);
-			}
-			ivt.vf = vf;
-			addattr_l(&req->n, sizeof(*req), IFLA_VF_TX_RATE, &ivt, sizeof(ivt));
-		
+			rate = *argv;
 		} else {
 			/* rewind arg */
 			PREV_ARG();
@@ -235,11 +358,43 @@ int iplink_parse_vf(int vf, int *argcp, char ***argvp,
 	if (argc == *argcp)
 		incomplete_command();
 
-	addattr_nest_end(&req->n, vfinfo);
+	if (mac || vlan || rate) {
+
+		vflist = addattr_nest(&req->n, sizeof(*req), IFLA_VFINFO_LIST);
+		vfinfo = addattr_nest(&req->n, sizeof(*req), IFLA_VF_INFO);
+
+		if (mac) {
+			len = ll_addr_a2n((char *)ivm.mac, 32, mac);
+			if (len < 0)
+				invarg("Invalid \"mac\" value\n", mac);
+			addattr_l(&req->n, sizeof(*req), IFLA_VF_MAC,
+				&ivm, sizeof(ivm));
+		}
+
+		if (vlan) {
+			if (get_unsigned(&ivv.vlan, vlan, 0))
+				invarg("Invalid \"vlan\" value\n", vlan);
+			if (qos) {
+				if (get_unsigned(&ivv.qos, qos, 0))
+					invarg("Invalid \"qos\" value\n", qos);
+			}
+			addattr_l(&req->n, sizeof(*req), IFLA_VF_VLAN,
+				&ivv, sizeof(ivv));
+		}
+
+		if (rate) {
+			if (get_unsigned(&ivt.rate, rate, 0))
+				invarg("Invalid \"rate\" value\n", rate);
+			addattr_l(&req->n, sizeof(*req), IFLA_VF_TX_RATE,
+				&ivt, sizeof(ivt));
+		}
+
+		addattr_nest_end(&req->n, vfinfo);
+		addattr_nest_end(&req->n, vflist);
+	}
 
 	*argcp = argc;
 	*argvp = argv;
-	return 0;
 }
 
 
@@ -349,18 +504,14 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 				req->i.ifi_flags |= IFF_NOARP;
 			} else
 				return on_off("noarp");
+		} else if (strcmp(*argv, "port") == 0) {
+			iplink_parse_port(vf, &argc, &argv, req);
 		} else if (strcmp(*argv, "vf") == 0) {
-			struct rtattr *vflist;
 			NEXT_ARG();
 			if (get_integer(&vf,  *argv, 0)) {
 				invarg("Invalid \"vf\" value\n", *argv);
 			}
-			vflist = addattr_nest(&req->n, sizeof(*req),
-					      IFLA_VFINFO_LIST);
-			len = iplink_parse_vf(vf, &argc, &argv, req);
-			if (len < 0)
-				return -1;
-			addattr_nest_end(&req->n, vflist);
+			iplink_parse_vf(vf, &argc, &argv, req);
 #ifdef IFF_DYNAMIC
 		} else if (matches(*argv, "dynamic") == 0) {
 			NEXT_ARG();


^ permalink raw reply related

* Re: [RFC] netfilter: WIP: Xtables idletimer target implementation
From: Jan Engelhardt @ 2010-06-01 18:38 UTC (permalink / raw)
  To: Luciano Coelho
  Cc: ext Patrick McHardy, netfilter-devel@vger.kernel.org,
	netdev@vger.kernel.org, Timo Teras
In-Reply-To: <1275417197.14585.2.camel@powerslave>


On Tuesday 2010-06-01 20:33, Luciano Coelho wrote:
>On Mon, 2010-05-31 at 21:51 +0200, ext Jan Engelhardt wrote:
>> On Monday 2010-05-31 21:12, Luciano Coelho wrote:
>> >
>> >I considered this option, but then I didn't find a proper place where to
>> >include the attribute in sysfs, since I cannot add it as part of the
>> >interface (eg. /sys/class/net/wlan0/idletimer) as I was doing before.
>> 
>> You couldn't have done that before either, because the interface name
>> in ipt_ip may refer to an interface that does not exist at all times.
>> 
>> >The other option would be to make the idletimer as part of the
>> >xt_IDLETIMER module object in sysfs
>> >(ie. /sys/module/xt_IDLETIMER/<user_supplied_name>), but it looks out of
>> >place.
>> 
>> I like it. It follows /proc/net/xt_{hashlimit,recent}/<user_supplied_name>.
>
>I'm starting to like this more and more too, as my code is getting much
>smaller ;)
>
>One quick question, though.  Do you have any ideas on how I can make
>sure that the user doesn't supply the same name twice (ie. two rules
>with the same user_supplied_name)?

What's so bad about multiple rules being able to reset the timer?


^ permalink raw reply

* Re: [RFC] netfilter: WIP: Xtables idletimer target implementation
From: Luciano Coelho @ 2010-06-01 18:33 UTC (permalink / raw)
  To: ext Jan Engelhardt
  Cc: ext Patrick McHardy, netfilter-devel@vger.kernel.org,
	netdev@vger.kernel.org, Timo Teras
In-Reply-To: <alpine.LSU.2.01.1005312143470.23758@obet.zrqbmnf.qr>

On Mon, 2010-05-31 at 21:51 +0200, ext Jan Engelhardt wrote:
> On Monday 2010-05-31 21:12, Luciano Coelho wrote:
> >
> >I considered this option, but then I didn't find a proper place where to
> >include the attribute in sysfs, since I cannot add it as part of the
> >interface (eg. /sys/class/net/wlan0/idletimer) as I was doing before.
> 
> You couldn't have done that before either, because the interface name
> in ipt_ip may refer to an interface that does not exist at all times.
> 
> >The other option would be to make the idletimer as part of the
> >xt_IDLETIMER module object in sysfs
> >(ie. /sys/module/xt_IDLETIMER/<user_supplied_name>), but it looks out of
> >place.
> 
> I like it. It follows /proc/net/xt_{hashlimit,recent}/<user_supplied_name>.

I'm starting to like this more and more too, as my code is getting much
smaller ;)

One quick question, though.  Do you have any ideas on how I can make
sure that the user doesn't supply the same name twice (ie. two rules
with the same user_supplied_name)?

The problem is that the userspace always re-adds all the existing rules
before inserting a new one and only later deletes the old rules. :\


-- 
Cheers,
Luca.


^ permalink raw reply

* Re: Kernel panic with the b44 driver in 2.6.35-rc1
From: François Valenduc @ 2010-06-01 18:06 UTC (permalink / raw)
  To: netdev
In-Reply-To: <20100601133318.GA26701@tuxdriver.com>

Le 01/06/10 15:33, John W. Linville a écrit :
> On Mon, May 31, 2010 at 09:58:43PM +0200, news.gmane.org wrote:
> 
>> I have a kernel panic at startup with the b44 driver with the 2.6.35-rc1
>> kernel. I have submitted a bug report (see
>> https://bugzilla.kernel.org/show_bug.cgi?id=16074) but until know, I
>> din't get any answer yet. Does anybody knows what's happening. I have
>> tried several git-bisect run but I didn't find any conclusive result.
>> The first bad-commit was different each time and if I revert it, the
>> problem still occurs anyway.
> 
> This patch is already on its way to Linus -- it should fix the problem
> you are seeing:
> 
> commit da1fdb02d9200ff28b6f3a380d21930335fe5429
> Author: Christoph Fritz <chf.fritz@googlemail.com>
> Date:   Fri May 28 10:45:59 2010 +0200
> 
>     ssb: fix NULL ptr deref when pcihost_wrapper is used
>     
>     Ethernet driver b44 does register ssb by it's pcihost_wrapper
>     and doesn't set ssb_chipcommon. A check on this value
>     introduced with commit d53cdbb94a52a920d5420ed64d986c3523a56743
>     and ea2db495f92ad2cf3301623e60cb95b4062bc484 triggers:
>     
>     BUG: unable to handle kernel NULL pointer dereference at 00000010
>     IP: [<c1266c36>] ssb_is_sprom_available+0x16/0x30
>     
>     Signed-off-by: Christoph Fritz <chf.fritz@googlemail.com>
>     Signed-off-by: John W. Linville <linville@tuxdriver.com>
> 
This patch indeed solve my problem.

Thanks for your help,
François Valenduc


^ permalink raw reply

* Call trace related to bonding seen in 2.6.34
From: Narendra_K @ 2010-06-01 17:45 UTC (permalink / raw)
  To: netdev; +Cc: fubar

Hello,

Call trace related to bond_mii_monitor  as described in this thread -
http://patchwork.ozlabs.org/patch/41288/ was seen on 2.6.34 kernel.
(Trace is similar to what is described in the post dated 2009-12-17
21:31:36.) The trace is seen when the network service is stopped. The
issue occurs when the network service is started and stopped in quick
succession. 

Bonding device configuration parameters are as below -

Bonding driver version:3.6.0
Mode: balance-alb (issue is also seen with active-backup mode)
Miimon=100
3 slaves with link up and one slave with link down.

Though this requires more thought and investigation, I thought this
could be a good data point. The below change to the bonding driver
seemed to make the issue go away -

drivers/net/bonding/bond_main.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c
b/drivers/net/bonding/bond_main.c
index 0075514..f280aaf 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -2408,7 +2408,7 @@ void bond_mii_monitor(struct work_struct *work)
        }

 re_arm:
-       if (bond->params.miimon)
+       if (bond->params.miimon && !bond->kill_timers)
                queue_delayed_work(bond->wq, &bond->mii_work,
 
msecs_to_jiffies(bond->params.miimon));
 out:




Any thoughts ?


With regards,
Narendra K



^ permalink raw reply related

* Re: [PATCH] cls_u32: use skb_copy_bits() to dereference data safely
From: Changli Gao @ 2010-06-01 17:47 UTC (permalink / raw)
  To: hadi; +Cc: David S. Miller, netdev
In-Reply-To: <1275395667.3587.38.camel@bigi>

On Tue, Jun 1, 2010 at 8:34 PM, jamal <hadi@cyberus.ca> wrote:
> Hi Changli,
>
> On Mon, 2010-05-31 at 10:24 +0800, Changli Gao wrote:
>> use skb_copy_bits() to dereference data safely
>>
>> the original skb->data dereference isn't safe, as there isn't any skb->len or
>> skb_is_nonlinear() check.
>
> I dont see any safety issue in current code in this respect. Do you have
> a specific scenario where this would be unsafe? We inspect in 32 bit
> chunks walking the packet data and stop when there is no more packet
> data.

I added the following debug code into cls_u32.c

                for (i = n->sel.nkeys; i>0; i--, key++) {
+                       int off;
+
+                       off = key->off+(off2&key->offmask) + (ptr - skb->data);
+                       if (off + 4 > skb->len)
+                               printk("skb->len: %d, off: %d\n",
skb->len, off);

                        if
((*(__be32*)(ptr+key->off+(off2&key->offmask))^key->val)&key->mask) {
                                n = n->next;
@@ -179,8 +186,13 @@ check_terminal:

                ht = n->ht_down;
                sel = 0;
-               if (ht->divisor)
+               if (ht->divisor) {
+                       int off = ptr - skb->data + n->sel.hoff;
+                       if (off + 4 > skb->len)
+                               printk("skb->len: %d, off: %d\n", skb->len,
+                                       off);
                        sel =
ht->divisor&u32_hash_fold(*(__be32*)(ptr+n->sel.hoff),
&n->sel,n->fshift);
+               }

the tc filter command is:

tc filter add dev eth0 parent 8001:0 proto ip  u32 match u32
0x00000000 0x0000ffff at 40

Then I execute nc to connect to an UDP port:

localhost linux # nc -u 192.168.235.1 80

localhost linux #

just press enter.

I got these demsg:

[ 7525.330604] skb->len: 43, off: 54

we are trying to access the memory out of this skb.

>
>> skb_copy_bits() is used instead in this patch. And
>> when the skb isn't long enough, we terminate the function u32_classify()
>> immediately with -1.
>>
>
> That could be a very interesting optimization - but i see it as _very
> hard_ to do with current u32 given it has branching and different
> branches would have different lengths etc. You'd have to essentially do
> some math in user space as to what min length would suffice given
> a specified filter and pass that to the kernel.
>

It isn't an optimization, but an error exit. :)

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

^ permalink raw reply

* Re: [PATCH 3/3] vhost: apply cpumask and cgroup to vhost workers
From: Sridhar Samudrala @ 2010-06-01 17:19 UTC (permalink / raw)
  To: Tejun Heo
  Cc: Michael S. Tsirkin, Oleg Nesterov, netdev, lkml,
	kvm@vger.kernel.org, Andrew Morton, Dmitri Vorobiev, Jiri Kosina,
	Thomas Gleixner, Ingo Molnar, Andi Kleen
In-Reply-To: <4C04D453.9040208@kernel.org>

On Tue, 2010-06-01 at 11:35 +0200, Tejun Heo wrote:
> Apply the cpumask and cgroup of the initializing task to the created
> vhost worker.
> 
> Based on Sridhar Samudrala's patch.  Li Zefan spotted a bug in error
> path (twice), fixed (twice).
> 
> Signed-off-by: Tejun Heo <tj@kernel.org>
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Cc: Sridhar Samudrala <samudrala.sridhar@gmail.com>
> Cc: Li Zefan <lizf@cn.fujitsu.com>
> ---
>  drivers/vhost/vhost.c |   34 ++++++++++++++++++++++++++++++----
>  1 file changed, 30 insertions(+), 4 deletions(-)
> 
> Index: work/drivers/vhost/vhost.c
> ===================================================================
> --- work.orig/drivers/vhost/vhost.c
> +++ work/drivers/vhost/vhost.c
> @@ -23,6 +23,7 @@
>  #include <linux/highmem.h>
>  #include <linux/slab.h>
>  #include <linux/kthread.h>
> +#include <linux/cgroup.h>
> 
>  #include <linux/net.h>
>  #include <linux/if_packet.h>
> @@ -187,11 +188,29 @@ long vhost_dev_init(struct vhost_dev *de
>  		    struct vhost_virtqueue *vqs, int nvqs)
>  {
>  	struct task_struct *worker;
> -	int i;
> +	cpumask_var_t mask;
> +	int i, ret = -ENOMEM;
> +
> +	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
> +		goto out_free_mask;

I think this is another bug in the error path. You should simply
do a return instead of a goto here when aloc_cpu_mask fails.

Thanks
Sridhar
> 
>  	worker = kthread_create(vhost_worker, dev, "vhost-%d", current->pid);
> -	if (IS_ERR(worker))
> -		return PTR_ERR(worker);
> +	if (IS_ERR(worker)) {
> +		ret = PTR_ERR(worker);
> +		goto out_free_mask;
> +	}
> +
> +	ret = sched_getaffinity(current->pid, mask);
> +	if (ret)
> +		goto out_stop_worker;
> +
> +	ret = sched_setaffinity(worker->pid, mask);
> +	if (ret)
> +		goto out_stop_worker;
> +
> +	ret = cgroup_attach_task_current_cg(worker);
> +	if (ret)
> +		goto out_stop_worker;
> 
>  	dev->vqs = vqs;
>  	dev->nvqs = nvqs;
> @@ -214,7 +233,14 @@ long vhost_dev_init(struct vhost_dev *de
>  	}
> 
>  	wake_up_process(worker);	/* avoid contributing to loadavg */
> -	return 0;
> +	ret = 0;
> +	goto out_free_mask;
> +
> +out_stop_worker:
> +	kthread_stop(worker);
> +out_free_mask:
> +	free_cpumask_var(mask);
> +	return ret;
>  }
> 
>  /* Caller should have device mutex */
> --
> 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: Fore 200 firmware
From: Ben Hutchings @ 2010-06-01 17:12 UTC (permalink / raw)
  To: Meelis Roos; +Cc: chas3, netdev
In-Reply-To: <alpine.SOC.1.00.1006011902490.22519@math.ut.ee>

On Tue, Jun 01, 2010 at 06:03:31PM +0100, Meelis Roos wrote:
> > >does not have to redo the detective work I am doing. Packaging it along 
> > >with linux-atm packages (atm-tools in Debian) does not seem correct, so 
> > >do we need to make a special firmware package out of it or just add to 
> > >some other firmware repo that is packaged already?
> > 
> > i dont care which happens really.  i would to think it is part of
> > atm-tools since the fore200e driver really isnt useful with the
> > atm tools.
> 
> OK, so we should push the distro maintainers of it to create a suggested 
> firmware package or just include the fore firmware unconditionally - 
> once it is in released linux-atm.
> 
> > >What's the licence of the firmware anyway - unknown likely?
> > 
> > it says the firmware is gpl.  look at fore200e_firmware_copyright
> > in one of the old kernel distros.
> 
> Well, there is no source to fulfill the GPL... but there also should be 
> no problem redistributing it.
[...]
 
The GPL says (approximately) that people are allowed to redistribute binaries
only if they also redistribute source.  If the source is not available to the
public then anyone redistributing it is relying on the assumption that the
copyright holder didn't really mean this condition and will not enforce it.
At any time the copyright holder could sue them for copyright infringement,
and they would have to rely on a defence such as laches.

This is a common problem with firmware images that were added to the kernel
long ago.  To reduce legal risk, Debian has been removing these images and
will not include them in any future releases, even in the non-free archive
section, unless this is fixed.  Please do not try to add this firmware to
Debian without getting an appropriate licence.
 
Ben.

-- 
Ben Hutchings
We get into the habit of living before acquiring the habit of thinking.
                                                              - Albert Camus

^ permalink raw reply

* [PATCH net-next-2.6] net: CONFIG_NET_NS reduction
From: Eric Dumazet @ 2010-06-01 16:51 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Patrick McHardy

Use read_pnet() and write_pnet() to reduce number of ifdef CONFIG_NET_NS

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
 include/linux/netdevice.h            |    6 +-----
 include/net/cfg80211.h               |   15 ++-------------
 include/net/genetlink.h              |   15 ++-------------
 include/net/netfilter/nf_conntrack.h |    6 +-----
 include/net/sock.h                   |   10 ++--------
 net/ipv6/addrlabel.c                 |    6 +-----
 net/netfilter/nf_conntrack_core.c    |    8 ++------
 7 files changed, 11 insertions(+), 55 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index a249161..bd6b753 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1087,11 +1087,7 @@ static inline void netdev_for_each_tx_queue(struct net_device *dev,
 static inline
 struct net *dev_net(const struct net_device *dev)
 {
-#ifdef CONFIG_NET_NS
-	return dev->nd_net;
-#else
-	return &init_net;
-#endif
+	return read_pnet(&dev->nd_net);
 }
 
 static inline
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index b44a2e5..e7ebeb8 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1330,26 +1330,15 @@ struct wiphy {
 	char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
 };
 
-#ifdef CONFIG_NET_NS
-static inline struct net *wiphy_net(struct wiphy *wiphy)
-{
-	return wiphy->_net;
-}
-
-static inline void wiphy_net_set(struct wiphy *wiphy, struct net *net)
-{
-	wiphy->_net = net;
-}
-#else
 static inline struct net *wiphy_net(struct wiphy *wiphy)
 {
-	return &init_net;
+	return read_pnet(&wiphy->_net);
 }
 
 static inline void wiphy_net_set(struct wiphy *wiphy, struct net *net)
 {
+	write_pnet(&wiphy->_net, net);
 }
-#endif
 
 /**
  * wiphy_priv - return priv from wiphy
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index eb551ba..f7dcd2c 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -68,26 +68,15 @@ struct genl_info {
 #endif
 };
 
-#ifdef CONFIG_NET_NS
 static inline struct net *genl_info_net(struct genl_info *info)
 {
-	return info->_net;
+	return read_pnet(&info->_net);
 }
 
 static inline void genl_info_net_set(struct genl_info *info, struct net *net)
 {
-	info->_net = net;
+	write_pnet(&info->_net, net);
 }
-#else
-static inline struct net *genl_info_net(struct genl_info *info)
-{
-	return &init_net;
-}
-
-static inline void genl_info_net_set(struct genl_info *info, struct net *net)
-{
-}
-#endif
 
 /**
  * struct genl_ops - generic netlink operations
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index bde095f..bbfdd94 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -152,11 +152,7 @@ extern struct net init_net;
 
 static inline struct net *nf_ct_net(const struct nf_conn *ct)
 {
-#ifdef CONFIG_NET_NS
-	return ct->ct_net;
-#else
-	return &init_net;
-#endif
+	return read_pnet(&ct->ct_net);
 }
 
 /* Alter reply tuple (maybe alter helper). */
diff --git a/include/net/sock.h b/include/net/sock.h
index ca241ea..3461e5d 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1724,19 +1724,13 @@ static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb, int copied_e
 static inline
 struct net *sock_net(const struct sock *sk)
 {
-#ifdef CONFIG_NET_NS
-	return sk->sk_net;
-#else
-	return &init_net;
-#endif
+	return read_pnet(&sk->sk_net);
 }
 
 static inline
 void sock_net_set(struct sock *sk, struct net *net)
 {
-#ifdef CONFIG_NET_NS
-	sk->sk_net = net;
-#endif
+	write_pnet(&sk->sk_net, net);
 }
 
 /*
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c
index 8c4348c..f0e774c 100644
--- a/net/ipv6/addrlabel.c
+++ b/net/ipv6/addrlabel.c
@@ -53,11 +53,7 @@ static struct ip6addrlbl_table
 static inline
 struct net *ip6addrlbl_net(const struct ip6addrlbl_entry *lbl)
 {
-#ifdef CONFIG_NET_NS
-	return lbl->lbl_net;
-#else
-	return &init_net;
-#endif
+	return read_pnet(&lbl->lbl_net);
 }
 
 /*
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index eeeb8bc..7728898 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -619,9 +619,7 @@ struct nf_conn *nf_conntrack_alloc(struct net *net, u16 zone,
 	ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev = NULL;
 	/* Don't set timer yet: wait for confirmation */
 	setup_timer(&ct->timeout, death_by_timeout, (unsigned long)ct);
-#ifdef CONFIG_NET_NS
-	ct->ct_net = net;
-#endif
+	write_pnet(&ct->ct_net, net);
 #ifdef CONFIG_NF_CONNTRACK_ZONES
 	if (zone) {
 		struct nf_conntrack_zone *nf_ct_zone;
@@ -1363,9 +1361,7 @@ static int nf_conntrack_init_init_net(void)
 		goto err_extend;
 #endif
 	/* Set up fake conntrack: to never be deleted, not in any hashes */
-#ifdef CONFIG_NET_NS
-	nf_conntrack_untracked.ct_net = &init_net;
-#endif
+	write_pnet(&nf_conntrack_untracked.ct_net, &init_net);
 	atomic_set(&nf_conntrack_untracked.ct_general.use, 1);
 	/*  - and look it like as a confirmed connection */
 	set_bit(IPS_CONFIRMED_BIT, &nf_conntrack_untracked.status);



^ permalink raw reply related

* Re: pull request: wireless-2.6 2010-05-28
From: reinette chatre @ 2010-06-01 16:22 UTC (permalink / raw)
  To: sedat.dilek@gmail.com
  Cc: John W. Linville, davem@davemloft.net,
	linux-wireless@vger.kernel.org, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, Zheng, Jiajia, Kolekar, Abhijeet,
	Berg, Johannes
In-Reply-To: <AANLkTil8SLseSeq1M_Xg7P4AqMy3V_0jxc7by2Xuaqnb@mail.gmail.com>

Hi Sedat,

On Sat, 2010-05-29 at 06:34 -0700, Sedat Dilek wrote:
> Two people confirmed the patch in [2] fixes:
> 1. iwlwifi-2.6 GIT master (commit f10a237c95abd6d64a3a24553bd1d3bcddd9108b)
> 2. compat-wireless (2010-05-21)
> 
> And it fixes also the above mentionned combination.

We are working on getting this patch upstream. The version tested
contains a significant amount of duplicated code as well as some cleanup
code mixed in. It is thus not appropriate for an upstream submission at
this time.

> As a suggestion:
> What about "copying" bug-reports (incl. its history) from IWL-BTS into
> linux-wireless ML?
> For example (dri-devel related) bug-reports from
> bugzilla.freedesktop.org are "copied" into dri-devel ML.

Pointing people to the bug report seems to work ok. What benefit does
the above have?

Reinette

^ permalink raw reply

* [PATCH] Refactor update of IPv6 flow destination address for srcrt (RH) option
From: Arnaud Ebalard @ 2010-06-01 16:20 UTC (permalink / raw)
  To: David S. Miller
  Cc: YOSHIFUJI Hideaki / 吉藤英明, netdev

Hi,

While playing with associated code, I noticed there are more than a
dozen occurrences of the following in the IPv6 stack:

    if (opt && opt->srcrt) {
            struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
            ipv6_addr_copy(&final, &fl.fl6_dst);
            ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
            final_p = &final;
    }

Maybe this can be replaced with a helper (not sure about the name
though).


Signed-off-by: Arnaud Ebalard <arno@natisbad.org>
---
 include/net/ipv6.h               |   13 +++++++++++++
 net/dccp/ipv6.c                  |   24 +++---------------------
 net/ipv6/af_inet6.c              |    7 +------
 net/ipv6/datagram.c              |   16 +++-------------
 net/ipv6/inet6_connection_sock.c |    7 +------
 net/ipv6/raw.c                   |    8 +-------
 net/ipv6/syncookies.c            |    7 +------
 net/ipv6/tcp_ipv6.c              |   21 +++------------------
 net/ipv6/udp.c                   |    9 ++-------
 9 files changed, 28 insertions(+), 84 deletions(-)

diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 2600b69..9edfa1c 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -290,6 +290,19 @@ static inline void ipv6_addr_copy(struct in6_addr *a1, const struct in6_addr *a2
 	memcpy(a1, a2, sizeof(struct in6_addr));
 }
 
+static inline struct in6_addr *srcrt_dst_flow_update(struct in6_addr *final,
+						     struct in6_addr *fl6dst,
+						     const struct ipv6_txoptions *opt)
+{
+	if (opt && opt->srcrt) {
+		const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt;
+		ipv6_addr_copy(final, fl6dst);
+		ipv6_addr_copy(fl6dst, rt0->addr);
+		return final;
+	}
+	return NULL;
+}
+
 static inline void ipv6_addr_prefix(struct in6_addr *pfx, 
 				    const struct in6_addr *addr,
 				    int plen)
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 0916988..fc435ba 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -265,13 +265,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
 
 	opt = np->opt;
 
-	if (opt != NULL && opt->srcrt != NULL) {
-		const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt;
-
-		ipv6_addr_copy(&final, &fl.fl6_dst);
-		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-		final_p = &final;
-	}
+	final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, opt);
 
 	err = ip6_dst_lookup(sk, &dst, &fl);
 	if (err)
@@ -551,13 +545,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
 		memset(&fl, 0, sizeof(fl));
 		fl.proto = IPPROTO_DCCP;
 		ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
-		if (opt != NULL && opt->srcrt != NULL) {
-			const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt;
-
-			ipv6_addr_copy(&final, &fl.fl6_dst);
-			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-			final_p = &final;
-		}
+		final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, opt);
 		ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);
 		fl.oif = sk->sk_bound_dev_if;
 		fl.fl_ip_dport = inet_rsk(req)->rmt_port;
@@ -988,13 +976,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 	fl.fl_ip_sport = inet->inet_sport;
 	security_sk_classify_flow(sk, &fl);
 
-	if (np->opt != NULL && np->opt->srcrt != NULL) {
-		const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
-
-		ipv6_addr_copy(&final, &fl.fl6_dst);
-		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-		final_p = &final;
-	}
+	final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, np->opt);
 
 	err = ip6_dst_lookup(sk, &dst, &fl);
 	if (err)
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index e733942..d6e6491 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -665,12 +665,7 @@ int inet6_sk_rebuild_header(struct sock *sk)
 		fl.fl_ip_sport = inet->inet_sport;
 		security_sk_classify_flow(sk, &fl);
 
-		if (np->opt && np->opt->srcrt) {
-			struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
-			ipv6_addr_copy(&final, &fl.fl6_dst);
-			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-			final_p = &final;
-		}
+		final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, np->opt);
 
 		err = ip6_dst_lookup(sk, &dst, &fl);
 		if (err) {
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 7126846..2fcba06 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -42,6 +42,7 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 	struct dst_entry	*dst;
 	struct flowi		fl;
 	struct ip6_flowlabel	*flowlabel = NULL;
+	struct ipv6_txoptions   *opt;
 	int			addr_type;
 	int			err;
 
@@ -155,19 +156,8 @@ ipv4_connected:
 
 	security_sk_classify_flow(sk, &fl);
 
-	if (flowlabel) {
-		if (flowlabel->opt && flowlabel->opt->srcrt) {
-			struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt;
-			ipv6_addr_copy(&final, &fl.fl6_dst);
-			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-			final_p = &final;
-		}
-	} else if (np->opt && np->opt->srcrt) {
-		struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
-		ipv6_addr_copy(&final, &fl.fl6_dst);
-		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-		final_p = &final;
-	}
+	opt = flowlabel ? flowlabel->opt : np->opt;
+	final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, opt);
 
 	err = ip6_dst_lookup(sk, &dst, &fl);
 	if (err)
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 0c5e3c3..505c8de 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -199,12 +199,7 @@ int inet6_csk_xmit(struct sk_buff *skb)
 	fl.fl_ip_dport = inet->inet_dport;
 	security_sk_classify_flow(sk, &fl);
 
-	if (np->opt && np->opt->srcrt) {
-		struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
-		ipv6_addr_copy(&final, &fl.fl6_dst);
-		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-		final_p = &final;
-	}
+	final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, np->opt);
 
 	dst = __inet6_csk_dst_check(sk, np->dst_cookie);
 
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 4a4dcbe..91211bd 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -847,13 +847,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
 	if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
 		ipv6_addr_copy(&fl.fl6_src, &np->saddr);
 
-	/* merge ip6_build_xmit from ip6_output */
-	if (opt && opt->srcrt) {
-		struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
-		ipv6_addr_copy(&final, &fl.fl6_dst);
-		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-		final_p = &final;
-	}
+	final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, opt);
 
 	if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
 		fl.oif = np->mcast_oif;
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index 34d1f06..7d27bc7 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -245,12 +245,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
 		memset(&fl, 0, sizeof(fl));
 		fl.proto = IPPROTO_TCP;
 		ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
-		if (np->opt && np->opt->srcrt) {
-			struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
-			ipv6_addr_copy(&final, &fl.fl6_dst);
-			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-			final_p = &final;
-		}
+		final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, np->opt);
 		ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);
 		fl.oif = sk->sk_bound_dev_if;
 		fl.mark = sk->sk_mark;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 2b7c3a1..2dcb536 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -250,12 +250,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 	fl.fl_ip_dport = usin->sin6_port;
 	fl.fl_ip_sport = inet->inet_sport;
 
-	if (np->opt && np->opt->srcrt) {
-		struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
-		ipv6_addr_copy(&final, &fl.fl6_dst);
-		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-		final_p = &final;
-	}
+	final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, np->opt);
 
 	security_sk_classify_flow(sk, &fl);
 
@@ -494,12 +489,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
 	security_req_classify_flow(req, &fl);
 
 	opt = np->opt;
-	if (opt && opt->srcrt) {
-		struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
-		ipv6_addr_copy(&final, &fl.fl6_dst);
-		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-		final_p = &final;
-	}
+	final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, opt);
 
 	err = ip6_dst_lookup(sk, &dst, &fl);
 	if (err)
@@ -1398,12 +1388,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 		memset(&fl, 0, sizeof(fl));
 		fl.proto = IPPROTO_TCP;
 		ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
-		if (opt && opt->srcrt) {
-			struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
-			ipv6_addr_copy(&final, &fl.fl6_dst);
-			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-			final_p = &final;
-		}
+		final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, opt);
 		ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr);
 		fl.oif = sk->sk_bound_dev_if;
 		fl.mark = sk->sk_mark;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 87be586..a46ad07 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1097,14 +1097,9 @@ do_udp_sendmsg:
 		ipv6_addr_copy(&fl.fl6_src, &np->saddr);
 	fl.fl_ip_sport = inet->inet_sport;
 
-	/* merge ip6_build_xmit from ip6_output */
-	if (opt && opt->srcrt) {
-		struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
-		ipv6_addr_copy(&final, &fl.fl6_dst);
-		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
-		final_p = &final;
+	final_p = srcrt_dst_flow_update(&final, &fl.fl6_dst, opt);
+	if (final_p)
 		connected = 0;
-	}
 
 	if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) {
 		fl.oif = np->mcast_oif;
-- 
1.7.1



^ 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