Netdev List
 help / color / mirror / Atom feed
* [net-next-2.6 PATCH 5/5] be2net: remove BUG_ON() when be2net runs out of mccq wrbs
From: Sathya Perla @ 2009-11-23  8:02 UTC (permalink / raw)
  To: netdev

The driver can run out of mccq wrbs when completions don't arrive
due to an unresponsive card. This must not hit a BUG_ON(); instead
log a msg and return an error.

Signed-off-by: Sathya Perla <sathyap@serverengines.com>
---
 drivers/net/benet/be_cmds.c |   89 +++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 85 insertions(+), 4 deletions(-)

diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index 2af87f1..8bd5315 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -349,7 +349,11 @@ static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter)
 	struct be_queue_info *mccq = &adapter->mcc_obj.q;
 	struct be_mcc_wrb *wrb;
 
-	BUG_ON(atomic_read(&mccq->used) >= mccq->len);
+	if (atomic_read(&mccq->used) >= mccq->len) {
+		dev_err(&adapter->pdev->dev, "Out of MCCQ wrbs\n");
+		return NULL;
+	}
+
 	wrb = queue_head_node(mccq);
 	queue_head_inc(mccq);
 	atomic_inc(&mccq->used);
@@ -499,6 +503,10 @@ int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
 	req = embedded_payload(wrb);
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -515,6 +523,7 @@ int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
 		*pmac_id = le32_to_cpu(resp->pmac_id);
 	}
 
+err:
 	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
@@ -529,6 +538,10 @@ int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id)
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
 	req = embedded_payload(wrb);
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -541,8 +554,8 @@ int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id)
 
 	status = be_mcc_notify_wait(adapter);
 
+err:
 	spin_unlock_bh(&adapter->mcc_lock);
-
 	return status;
 }
 
@@ -861,10 +874,15 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_get_stats *req;
 	struct be_sge *sge;
+	int status = 0;
 
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
 	req = nonemb_cmd->va;
 	sge = nonembedded_sgl(wrb);
 
@@ -879,8 +897,9 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
 
 	be_mcc_notify(adapter);
 
+err:
 	spin_unlock_bh(&adapter->mcc_lock);
-	return 0;
+	return status;
 }
 
 /* Uses synchronous mcc */
@@ -894,6 +913,10 @@ int be_cmd_link_status_query(struct be_adapter *adapter,
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
 	req = embedded_payload(wrb);
 
 	*link_up = false;
@@ -913,6 +936,7 @@ int be_cmd_link_status_query(struct be_adapter *adapter,
 		}
 	}
 
+err:
 	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
@@ -951,10 +975,15 @@ int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd)
 {
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_modify_eq_delay *req;
+	int status = 0;
 
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
 	req = embedded_payload(wrb);
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -969,8 +998,9 @@ int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd)
 
 	be_mcc_notify(adapter);
 
+err:
 	spin_unlock_bh(&adapter->mcc_lock);
-	return 0;
+	return status;
 }
 
 /* Uses sycnhronous mcc */
@@ -984,6 +1014,10 @@ int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
 	req = embedded_payload(wrb);
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -1002,6 +1036,7 @@ int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
 
 	status = be_mcc_notify_wait(adapter);
 
+err:
 	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
@@ -1018,6 +1053,10 @@ int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en)
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
 	req = embedded_payload(wrb);
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -1032,6 +1071,7 @@ int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en)
 
 	status = be_mcc_notify_wait(adapter);
 
+err:
 	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
@@ -1052,6 +1092,10 @@ int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id,
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
 	sge = nonembedded_sgl(wrb);
 	memset(req, 0, sizeof(*req));
 
@@ -1078,6 +1122,7 @@ int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id,
 
 	status = be_mcc_notify_wait(adapter);
 
+err:
 	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
@@ -1092,6 +1137,10 @@ int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc)
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
 	req = embedded_payload(wrb);
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -1104,6 +1153,7 @@ int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc)
 
 	status = be_mcc_notify_wait(adapter);
 
+err:
 	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
@@ -1118,6 +1168,10 @@ int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc)
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
 	req = embedded_payload(wrb);
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -1133,6 +1187,7 @@ int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc)
 		*rx_fc = le16_to_cpu(resp->rx_flow_control);
 	}
 
+err:
 	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
@@ -1199,6 +1254,10 @@ int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num,
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
 	req = embedded_payload(wrb);
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -1213,6 +1272,7 @@ int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num,
 
 	status = be_mcc_notify_wait(adapter);
 
+err:
 	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
@@ -1227,6 +1287,10 @@ int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state)
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
 	req = embedded_payload(wrb);
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -1243,6 +1307,7 @@ int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state)
 		*state = resp->beacon_state;
 	}
 
+err:
 	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
@@ -1258,6 +1323,10 @@ int be_cmd_read_port_type(struct be_adapter *adapter, u32 port,
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
 	req = embedded_payload(wrb);
 
 	be_wrb_hdr_prepare(wrb, sizeof(struct be_cmd_resp_port_type), true, 0);
@@ -1273,6 +1342,7 @@ int be_cmd_read_port_type(struct be_adapter *adapter, u32 port,
 			*connector = resp->data.connector;
 	}
 
+err:
 	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
@@ -1288,6 +1358,11 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = cmd->va;
 	sge = nonembedded_sgl(wrb);
 
 	be_wrb_hdr_prepare(wrb, cmd->size, false, 1);
@@ -1304,6 +1379,7 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
 
 	status = be_mcc_notify_wait(adapter);
 
+err:
 	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
@@ -1317,6 +1393,10 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc)
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
 	req = embedded_payload(wrb);
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req)+4, true, 0);
@@ -1333,6 +1413,7 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc)
 	if (!status)
 		memcpy(flashed_crc, req->params.data_buf, 4);
 
+err:
 	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
-- 
1.6.5.2


^ permalink raw reply related

* Re: [PATCH 0/1] Defer skb allocation for both mergeable buffers and big packets in virtio_net
From: Mark McLoughlin @ 2009-11-23  8:51 UTC (permalink / raw)
  To: Rusty Russell
  Cc: Shirley Ma, Michael S. Tsirkin, Avi Kivity, netdev, kvm,
	linux-kernel, Anthony Liguori
In-Reply-To: <200911231123.18898.rusty@rustcorp.com.au>

On Mon, 2009-11-23 at 11:23 +1030, Rusty Russell wrote:
> I'd like to drop big packet support from our driver, but I don't know
> how many kvm hosts will not offer mergable rx bufs yet.  Anthony?

Mergeable rx bufs were first added in kvm-80 and qemu-0.10.0

So e.g., it's in Fedora since Fedora 11 and RHEL since 5.4

Cheers,
Mark.


^ permalink raw reply

* Re: stmmac patches...
From: Giuseppe CAVALLARO @ 2009-11-23  8:57 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20091120.094019.163421376.davem@davemloft.net>

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi David,
David Miller wrote:
> From: Giuseppe CAVALLARO <peppe.cavallaro@st.com>
> Date: Fri, 20 Nov 2009 08:19:14 +0100
> 
>>> Please fix this up and resubmit both of your patches.
>> I've just resent the second patch:
>>  [PATCH (RESENT)] stmmac: do not fail when the timer cannot be used.
>> Let me know if I have to review something in my first patch as well.
> 
> I explicitly asked you to resubmit both patches, so that I would have
> them in a group together to apply to my tree.

I'm sending them at once.

> When changes are requested in some patches within a group, I mark
> the entire group in patchwork with state 'changed requested' and
> that's why I ask for the whole series to be resubmitted.
> 
> This means you should have resent the first patch even though I did
> not ask you to make any changes to it.

Thanks David for this. I know that it's not easy to manage an huge
amount of patches (especially when these have some defects ;-) ). My
personal goal is to sent patches clean and well done too.

Regards,
Peppe
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAksKTpEACgkQ2Xo3j31MSSI3XACfVFcY9yj2fzFOplC8A1oma9lp
6QYAmgNdMKvJt+MyUAZHsIqjqDpDAwdD
=Z6CD
-----END PGP SIGNATURE-----

^ permalink raw reply

* [PATCH 1/2] stmmac: fixed a compilation error when use the external timer
From: Giuseppe CAVALLARO @ 2009-11-23  8:58 UTC (permalink / raw)
  To: netdev; +Cc: Giuseppe Cavallaro

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/stmmac/stmmac_timer.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/stmmac/stmmac_timer.c b/drivers/net/stmmac/stmmac_timer.c
index b838c65..679f61f 100644
--- a/drivers/net/stmmac/stmmac_timer.c
+++ b/drivers/net/stmmac/stmmac_timer.c
@@ -63,7 +63,7 @@ int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm)
 
 	stmmac_rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
 	if (stmmac_rtc == NULL) {
-		pr_error("open rtc device failed\n");
+		pr_err("open rtc device failed\n");
 		return -ENODEV;
 	}
 
@@ -71,7 +71,7 @@ int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm)
 
 	/* Periodic mode is not supported */
 	if ((rtc_irq_set_freq(stmmac_rtc, &stmmac_task, tm->freq) < 0)) {
-		pr_error("set periodic failed\n");
+		pr_err("set periodic failed\n");
 		rtc_irq_unregister(stmmac_rtc, &stmmac_task);
 		rtc_class_close(stmmac_rtc);
 		return -1;
-- 
1.6.0.4


^ permalink raw reply related

* [PATCH 2/2] stmmac: do not fail when the timer cannot be used.
From: Giuseppe CAVALLARO @ 2009-11-23  8:59 UTC (permalink / raw)
  To: netdev; +Cc: Giuseppe Cavallaro

If the external timer cannot be used the driver
will continue to work without mitigation.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/stmmac/stmmac_main.c  |   50 ++++++++++++++++++++----------------
 drivers/net/stmmac/stmmac_timer.h |    1 +
 2 files changed, 29 insertions(+), 22 deletions(-)

diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
index c2f14dc..9542995 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/stmmac/stmmac_main.c
@@ -416,13 +416,8 @@ static void init_dma_desc_rings(struct net_device *dev)
 	unsigned int txsize = priv->dma_tx_size;
 	unsigned int rxsize = priv->dma_rx_size;
 	unsigned int bfsize = priv->dma_buf_sz;
-	int buff2_needed = 0;
-	int dis_ic = 0;
+	int buff2_needed = 0, dis_ic = 0;
 
-#ifdef CONFIG_STMMAC_TIMER
-	/* Using Timers disable interrupts on completion for the reception */
-	dis_ic = 1;
-#endif
 	/* Set the Buffer size according to the MTU;
 	 * indeed, in case of jumbo we need to bump-up the buffer sizes.
 	 */
@@ -437,6 +432,11 @@ static void init_dma_desc_rings(struct net_device *dev)
 	else
 		bfsize = DMA_BUFFER_SIZE;
 
+#ifdef CONFIG_STMMAC_TIMER
+	/* Disable interrupts on completion for the reception if timer is on */
+	if (likely(priv->tm->enable))
+		dis_ic = 1;
+#endif
 	/* If the MTU exceeds 8k so use the second buffer in the chain */
 	if (bfsize >= BUF_SIZE_8KiB)
 		buff2_needed = 1;
@@ -809,20 +809,22 @@ static void stmmac_tx(struct stmmac_priv *priv)
 
 static inline void stmmac_enable_irq(struct stmmac_priv *priv)
 {
-#ifndef CONFIG_STMMAC_TIMER
-	writel(DMA_INTR_DEFAULT_MASK, priv->dev->base_addr + DMA_INTR_ENA);
-#else
-	priv->tm->timer_start(tmrate);
+#ifdef CONFIG_STMMAC_TIMER
+	if (likely(priv->tm->enable))
+		priv->tm->timer_start(tmrate);
+	else
 #endif
+	writel(DMA_INTR_DEFAULT_MASK, priv->dev->base_addr + DMA_INTR_ENA);
 }
 
 static inline void stmmac_disable_irq(struct stmmac_priv *priv)
 {
-#ifndef CONFIG_STMMAC_TIMER
-	writel(0, priv->dev->base_addr + DMA_INTR_ENA);
-#else
-	priv->tm->timer_stop();
+#ifdef CONFIG_STMMAC_TIMER
+	if (likely(priv->tm->enable))
+		priv->tm->timer_stop();
+	else
 #endif
+	writel(0, priv->dev->base_addr + DMA_INTR_ENA);
 }
 
 static int stmmac_has_work(struct stmmac_priv *priv)
@@ -1031,22 +1033,23 @@ static int stmmac_open(struct net_device *dev)
 	}
 
 #ifdef CONFIG_STMMAC_TIMER
-	priv->tm = kmalloc(sizeof(struct stmmac_timer *), GFP_KERNEL);
+	priv->tm = kzalloc(sizeof(struct stmmac_timer *), GFP_KERNEL);
 	if (unlikely(priv->tm == NULL)) {
 		pr_err("%s: ERROR: timer memory alloc failed \n", __func__);
 		return -ENOMEM;
 	}
 	priv->tm->freq = tmrate;
 
-	/* Test if the HW timer can be actually used.
-	 * In case of failure continue with no timer. */
+	/* Test if the external timer can be actually used.
+	 * In case of failure continue without timer. */
 	if (unlikely((stmmac_open_ext_timer(dev, priv->tm)) < 0)) {
-		pr_warning("stmmaceth: cannot attach the HW timer\n");
+		pr_warning("stmmaceth: cannot attach the external timer.\n");
 		tmrate = 0;
 		priv->tm->freq = 0;
 		priv->tm->timer_start = stmmac_no_timer_started;
 		priv->tm->timer_stop = stmmac_no_timer_stopped;
-	}
+	} else
+		priv->tm->enable = 1;
 #endif
 
 	/* Create and initialize the TX/RX descriptors chains. */
@@ -1322,9 +1325,11 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	/* Interrupt on completition only for the latest segment */
 	priv->mac_type->ops->close_tx_desc(desc);
+
 #ifdef CONFIG_STMMAC_TIMER
-	/* Clean IC while using timers */
-	priv->mac_type->ops->clear_tx_ic(desc);
+	/* Clean IC while using timer */
+	if (likely(priv->tm->enable))
+		priv->mac_type->ops->clear_tx_ic(desc);
 #endif
 	/* To avoid raise condition */
 	priv->mac_type->ops->set_tx_owner(first);
@@ -2028,7 +2033,8 @@ static int stmmac_suspend(struct platform_device *pdev, pm_message_t state)
 
 #ifdef CONFIG_STMMAC_TIMER
 		priv->tm->timer_stop();
-		dis_ic = 1;
+		if (likely(priv->tm->enable))
+			dis_ic = 1;
 #endif
 		napi_disable(&priv->napi);
 
diff --git a/drivers/net/stmmac/stmmac_timer.h b/drivers/net/stmmac/stmmac_timer.h
index f795cae..6863590 100644
--- a/drivers/net/stmmac/stmmac_timer.h
+++ b/drivers/net/stmmac/stmmac_timer.h
@@ -26,6 +26,7 @@ struct stmmac_timer {
 	void (*timer_start) (unsigned int new_freq);
 	void (*timer_stop) (void);
 	unsigned int freq;
+	unsigned int enable;
 };
 
 /* Open the HW timer device and return 0 in case of success */
-- 
1.6.0.4


^ permalink raw reply related

* Re: [PATCH] irq: Add node_affinity CPU masks for smarter irqbalance hints
From: Peter P Waskiewicz Jr @ 2009-11-23  9:36 UTC (permalink / raw)
  To: Yong Zhang
  Cc: linux-kernel@vger.kernel.org, arjan@linux.jf.intel.com,
	davem@davemloft.net, netdev@vger.kernel.org
In-Reply-To: <2674af740911222332i65c0d066h79bf2c1ca1d5e4f0@mail.gmail.com>

On Sun, 2009-11-22 at 23:32 -0800, Yong Zhang wrote:
> On Mon, Nov 23, 2009 at 2:46 PM, Peter P Waskiewicz Jr
> <peter.p.waskiewicz.jr@intel.com> wrote:
> > This patchset adds a new CPU mask for SMP systems to the irq_desc
> > struct.  It also exposes an API for underlying device drivers to
> > assist irqbalance in making smarter decisions when balancing, especially
> > in a NUMA environment.  For example, an ethernet driver with MSI-X may
> > wish to limit the CPUs that an interrupt can be balanced within to
> > stay on a single NUMA node.  Current irqbalance operation can move the
> > interrupt off the node, resulting in cross-node memory accesses and
> > locks.
> >
> > The API is a get/set API within the kernel, along with a /proc entry
> > for the interrupt.
> >
> > Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
> > ---
> 
> 1) I think you should consider CONFIG_CPUMASK_OFFSTACK which will affect
>    node_affinity.
> 2) It seems like this patch can't work with SPARSE_IRQ.

This mechanism isn't going to be used by any internal kernel mechanism
for determining interrupt placement or operation.  It's purely something
that either a driver can modify, or external script (through /proc),
that irqbalance will make use of.  If irqbalance isn't running, or the
current version of irqbalance doesn't support reading node_affinity,
then it won't affect the system's operation.

If irqbalance does support it, it'll read whatever the supplied mask is,
and then will try and balance interrupts within that mask.  It will bail
if the mask is invalid, or won't apply to the running system, just like
how putting a bogus mask into smp_affinity is ignored.

If there's something I'm missing beyond this with the two suggestions
you've made (I looked into those two parameters and tried to draw
conclusions), please let me know.

Cheers,
-PJ Waskiewicz


^ permalink raw reply

* Re: [PATCH 1/1] Defer skb allocation for both mergeable buffers and big packets in virtio_net
From: Michael S. Tsirkin @ 2009-11-23  9:43 UTC (permalink / raw)
  To: Shirley Ma
  Cc: Eric Dumazet, Avi Kivity, Rusty Russell, netdev, kvm,
	linux-kernel
In-Reply-To: <1258734101.11049.1.camel@localhost.localdomain>

On Fri, Nov 20, 2009 at 08:21:41AM -0800, Shirley Ma wrote:
> On Fri, 2009-11-20 at 07:19 +0100, Eric Dumazet wrote:
> > Interesting use after free :)
> 
> Thanks for catching the stupid mistake. This is the updated patch for
> review.
> 
> Signed-off-by: Shirley Ma (xma@us.ibm.com)

some style comments. addressing them will make it
easier to review actual content.

> ------
> 
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index b9e002f..5699bd3 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -80,33 +80,50 @@ static inline struct skb_vnet_hdr *skb_vnet_hdr(struct sk_buff *skb)
>  	return (struct skb_vnet_hdr *)skb->cb;
>  }
>  
> -static void give_a_page(struct virtnet_info *vi, struct page *page)
> +static void give_pages(struct virtnet_info *vi, struct page *page)
>  {
> -	page->private = (unsigned long)vi->pages;
> +	struct page *npage = (struct page *)page->private;
> +
> +	if (!npage)
> +		page->private = (unsigned long)vi->pages;
> +	else {
> +		/* give a page list */
> +		while (npage) {
> +			if (npage->private == (unsigned long)0) {

should be !npage->private
and nesting is too deep here:
this is cleaner in a give_a_page subroutine
as it was.

> +				npage->private = (unsigned long)vi->pages;
> +				break;
> +			}
> +			npage = (struct page *)npage->private;
> +		}
> +	}
>  	vi->pages = page;
>  }
>  
> -static void trim_pages(struct virtnet_info *vi, struct sk_buff *skb)
> -{
> -	unsigned int i;
> -
> -	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
> -		give_a_page(vi, skb_shinfo(skb)->frags[i].page);
> -	skb_shinfo(skb)->nr_frags = 0;
> -	skb->data_len = 0;
> -}
> -
>  static struct page *get_a_page(struct virtnet_info *vi, gfp_t gfp_mask)

so in short, we are constantly walking a linked

>  {
>  	struct page *p = vi->pages;
>  
> -	if (p)
> +	if (p) {
>  		vi->pages = (struct page *)p->private;
> -	else
> +		/* use private to chain big packets */

packets? or pages?

> +		p->private = (unsigned long)0;

the comment is not really helpful:
you say you use private to chain but 0 does not
chain anything. You also do not need the cast to long?

> +	} else
>  		p = alloc_page(gfp_mask);
>  	return p;
>  }
>  
> +void virtio_free_pages(void *buf)
> +{
> +	struct page *page = (struct page *)buf;
> +	struct page *npage;
> +
> +	while (page) {
> +		npage = (struct page *)page->private;
> +		__free_pages(page, 0);
> +		page = npage;
> +	}
> +}
> +
>  static void skb_xmit_done(struct virtqueue *svq)
>  {
>  	struct virtnet_info *vi = svq->vdev->priv;
> @@ -118,12 +135,36 @@ static void skb_xmit_done(struct virtqueue *svq)
>  	netif_wake_queue(vi->dev);
>  }
>  
> -static void receive_skb(struct net_device *dev, struct sk_buff *skb,
> +static int set_skb_frags(struct sk_buff *skb, struct page *page,
> +				int offset, int len)
> +{
> +	int i = skb_shinfo(skb)->nr_frags;
> +	skb_frag_t *f;
> +
> +	i = skb_shinfo(skb)->nr_frags;
> +	f = &skb_shinfo(skb)->frags[i];
> +	f->page = page;
> +	f->page_offset = offset;
> +
> +	if (len > (PAGE_SIZE - f->page_offset))

brackets around math are not needed.

> +		f->size = PAGE_SIZE - f->page_offset;
> +	else
> +		f->size = len;
> +
> +	skb_shinfo(skb)->nr_frags++;
> +	skb->data_len += f->size;
> +	skb->len += f->size;
> +
> +	len -= f->size;
> +	return len;
> +}
> +
> +static void receive_skb(struct net_device *dev, void *buf,
>  			unsigned len)
>  {
>  	struct virtnet_info *vi = netdev_priv(dev);
> -	struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb);
> -	int err;
> +	struct skb_vnet_hdr *hdr;
> +	struct sk_buff *skb;
>  	int i;
>  
>  	if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) {
> @@ -132,39 +173,71 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
>  		goto drop;
>  	}
>  
> -	if (vi->mergeable_rx_bufs) {
> -		unsigned int copy;
> -		char *p = page_address(skb_shinfo(skb)->frags[0].page);
> +	if (!vi->mergeable_rx_bufs && !vi->big_packets) {
> +		skb = (struct sk_buff *)buf;
> +
> +		__skb_unlink(skb, &vi->recv);
> +
> +		hdr = skb_vnet_hdr(skb);
> +		len -= sizeof(hdr->hdr);
> +		skb_trim(skb, len);
> +	} else {
> +		struct page *page = (struct page *)buf;
> +		int copy, hdr_len, num_buf, offset;
> +		char *p;
> +
> +		p = page_address(page);
>  
> -		if (len > PAGE_SIZE)
> -			len = PAGE_SIZE;
> -		len -= sizeof(struct virtio_net_hdr_mrg_rxbuf);
> +		skb = netdev_alloc_skb(vi->dev, GOOD_COPY_LEN + NET_IP_ALIGN);
> +		if (unlikely(!skb)) {
> +			dev->stats.rx_dropped++;
> +			return;
> +		}
> +		skb_reserve(skb, NET_IP_ALIGN);
> +		hdr = skb_vnet_hdr(skb);
>  
> -		memcpy(&hdr->mhdr, p, sizeof(hdr->mhdr));
> -		p += sizeof(hdr->mhdr);
> +		if (vi->mergeable_rx_bufs) {
> +			hdr_len = sizeof(hdr->mhdr);

space and no brackets after sizeof.

> +			memcpy(&hdr->mhdr, p, hdr_len);
> +			num_buf = hdr->mhdr.num_buffers;
> +			offset = hdr_len;
> +			if (len > PAGE_SIZE)
> +				len = PAGE_SIZE;
> +		} else {
> +			/* big packtes 6 bytes alignment between virtio_net

typo

> +			 * header and data */

please think of a way to get rid of magic constants like 6 and 2
here and elsewhere.

> +			hdr_len = sizeof(hdr->hdr);
> +			memcpy(&hdr->hdr, p, hdr_len);
> +			offset = hdr_len + 6;
> +		}
> +
> +		p += offset;
>  
> +		len -= hdr_len;
>  		copy = len;
>  		if (copy > skb_tailroom(skb))
>  			copy = skb_tailroom(skb);
> -
>  		memcpy(skb_put(skb, copy), p, copy);
>  
>  		len -= copy;
>  
> -		if (!len) {
> -			give_a_page(vi, skb_shinfo(skb)->frags[0].page);
> -			skb_shinfo(skb)->nr_frags--;
> -		} else {
> -			skb_shinfo(skb)->frags[0].page_offset +=
> -				sizeof(hdr->mhdr) + copy;
> -			skb_shinfo(skb)->frags[0].size = len;
> -			skb->data_len += len;
> -			skb->len += len;
> +		if (!len)
> +			give_pages(vi, page);
> +		else {
> +			len = set_skb_frags(skb, page, copy + offset, len);
> +			/* process big packets */
> +			while (len > 0) {
> +				page = (struct page *)page->private;
> +				if (!page)
> +					break;
> +				len = set_skb_frags(skb, page, 0, len);
> +			}
> +			if (page && page->private)
> +				give_pages(vi, (struct page *)page->private);
>  		}
>  
> -		while (--hdr->mhdr.num_buffers) {
> -			struct sk_buff *nskb;
> -
> +		/* process mergeable buffers */
> +		while (vi->mergeable_rx_bufs && --num_buf) {
>  			i = skb_shinfo(skb)->nr_frags;
>  			if (i >= MAX_SKB_FRAGS) {
>  				pr_debug("%s: packet too long %d\n", dev->name,
> @@ -173,41 +246,20 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
>  				goto drop;
>  			}
>  
> -			nskb = vi->rvq->vq_ops->get_buf(vi->rvq, &len);
> -			if (!nskb) {
> +			page = vi->rvq->vq_ops->get_buf(vi->rvq, &len);
> +			if (!page) {
>  				pr_debug("%s: rx error: %d buffers missing\n",
>  					 dev->name, hdr->mhdr.num_buffers);
>  				dev->stats.rx_length_errors++;
>  				goto drop;
>  			}
>  
> -			__skb_unlink(nskb, &vi->recv);
> -			vi->num--;
> -
> -			skb_shinfo(skb)->frags[i] = skb_shinfo(nskb)->frags[0];
> -			skb_shinfo(nskb)->nr_frags = 0;
> -			kfree_skb(nskb);
> -
>  			if (len > PAGE_SIZE)
>  				len = PAGE_SIZE;
>  
> -			skb_shinfo(skb)->frags[i].size = len;
> -			skb_shinfo(skb)->nr_frags++;
> -			skb->data_len += len;
> -			skb->len += len;
> -		}
> -	} else {
> -		len -= sizeof(hdr->hdr);
> -
> -		if (len <= MAX_PACKET_LEN)
> -			trim_pages(vi, skb);
> +			set_skb_frags(skb, page, 0, len);
>  
> -		err = pskb_trim(skb, len);
> -		if (err) {
> -			pr_debug("%s: pskb_trim failed %i %d\n", dev->name,
> -				 len, err);
> -			dev->stats.rx_dropped++;
> -			goto drop;
> +			vi->num--;
>  		}
>  	}
>  
> @@ -271,107 +323,105 @@ drop:
>  	dev_kfree_skb(skb);
>  }
>  
> -static bool try_fill_recv_maxbufs(struct virtnet_info *vi, gfp_t gfp)
> +/* Returns false if we couldn't fill entirely (OOM). */
> +static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)
>  {
> -	struct sk_buff *skb;
>  	struct scatterlist sg[2+MAX_SKB_FRAGS];
> -	int num, err, i;
> +	int err = 0;
>  	bool oom = false;
>  
>  	sg_init_table(sg, 2+MAX_SKB_FRAGS);
>  	do {
> -		struct skb_vnet_hdr *hdr;
> -
> -		skb = netdev_alloc_skb(vi->dev, MAX_PACKET_LEN + NET_IP_ALIGN);
> -		if (unlikely(!skb)) {
> -			oom = true;
> -			break;
> -		}
> -
> -		skb_reserve(skb, NET_IP_ALIGN);
> -		skb_put(skb, MAX_PACKET_LEN);
> -
> -		hdr = skb_vnet_hdr(skb);
> -		sg_set_buf(sg, &hdr->hdr, sizeof(hdr->hdr));
> -
> -		if (vi->big_packets) {
> -			for (i = 0; i < MAX_SKB_FRAGS; i++) {
> -				skb_frag_t *f = &skb_shinfo(skb)->frags[i];
> -				f->page = get_a_page(vi, gfp);
> -				if (!f->page)
> -					break;
> -
> -				f->page_offset = 0;
> -				f->size = PAGE_SIZE;
> -
> -				skb->data_len += PAGE_SIZE;
> -				skb->len += PAGE_SIZE;
> -
> -				skb_shinfo(skb)->nr_frags++;
> +		/* allocate skb for MAX_PACKET_LEN len */
> +		if (!vi->big_packets && !vi->mergeable_rx_bufs) {
> +			struct skb_vnet_hdr *hdr;
> +			struct sk_buff *skb;
> +
> +			skb = netdev_alloc_skb(vi->dev,
> +					       MAX_PACKET_LEN + NET_IP_ALIGN);
> +			if (unlikely(!skb)) {
> +				oom = true;
> +				break;
>  			}
> -		}
> -
> -		num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1;
> -		skb_queue_head(&vi->recv, skb);
> -
> -		err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, num, skb);
> -		if (err < 0) {
> -			skb_unlink(skb, &vi->recv);
> -			trim_pages(vi, skb);
> -			kfree_skb(skb);
> -			break;
> -		}
> -		vi->num++;
> -	} while (err >= num);
> -	if (unlikely(vi->num > vi->max))
> -		vi->max = vi->num;
> -	vi->rvq->vq_ops->kick(vi->rvq);
> -	return !oom;
> -}
> -
> -/* Returns false if we couldn't fill entirely (OOM). */
> -static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)
> -{
> -	struct sk_buff *skb;
> -	struct scatterlist sg[1];
> -	int err;
> -	bool oom = false;
>  
> -	if (!vi->mergeable_rx_bufs)
> -		return try_fill_recv_maxbufs(vi, gfp);
> +			skb_reserve(skb, NET_IP_ALIGN);
> +			skb_put(skb, MAX_PACKET_LEN);
>  
> -	do {
> -		skb_frag_t *f;
> +			hdr = skb_vnet_hdr(skb);
> +			sg_set_buf(sg, &hdr->hdr, sizeof(hdr->hdr));
>  
> -		skb = netdev_alloc_skb(vi->dev, GOOD_COPY_LEN + NET_IP_ALIGN);
> -		if (unlikely(!skb)) {
> -			oom = true;
> -			break;
> -		}
> -
> -		skb_reserve(skb, NET_IP_ALIGN);
> -
> -		f = &skb_shinfo(skb)->frags[0];
> -		f->page = get_a_page(vi, gfp);
> -		if (!f->page) {
> -			oom = true;
> -			kfree_skb(skb);
> -			break;
> -		}
> +			skb_to_sgvec(skb, sg+1, 0, skb->len);
> +			skb_queue_head(&vi->recv, skb);
>  
> -		f->page_offset = 0;
> -		f->size = PAGE_SIZE;
> -
> -		skb_shinfo(skb)->nr_frags++;
> +			err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, 2, skb);
> +			if (err < 0) {
> +				skb_unlink(skb, &vi->recv);
> +				kfree_skb(skb);
> +				break;
> +			}
>  
> -		sg_init_one(sg, page_address(f->page), PAGE_SIZE);
> -		skb_queue_head(&vi->recv, skb);
> +		} else {
> +			struct page *first_page = NULL;
> +			struct page *page;
> +			int i = MAX_SKB_FRAGS + 2;

replace MAX_SKB_FRAGS + 2 with something symbolic? We have it in 2 palces now.
And comment.

> +			char *p;
> +
> +			/*
> +			 * chain pages for big packets, allocate skb
> +			 * late for both big packets and mergeable
> +			 * buffers
> +			 */
> +more:			page = get_a_page(vi, gfp);


terrible goto based loop
move stuff into subfunction, it will be much
more manageable, and convert this to a simple
for loop.


> +			if (!page) {
> +				if (first_page)
> +					give_pages(vi, first_page);
> +				oom = true;
> +				break;
> +			}
>  
> -		err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, 1, skb);
> -		if (err < 0) {
> -			skb_unlink(skb, &vi->recv);
> -			kfree_skb(skb);
> -			break;
> +			p = page_address(page);
> +			if (vi->mergeable_rx_bufs) {
> +				sg_init_one(sg, p, PAGE_SIZE);
> +				err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0,
> +							       1, page);
> +				if (err < 0) {
> +					give_pages(vi, page);
> +					break;
> +				}
> +			} else {
> +				int hdr_len = sizeof(struct virtio_net_hdr);
> +
> +				/*
> +				 * allocate MAX_SKB_FRAGS + 1 pages for
> +				 * big packets
> +				 */

and here it is MAX_SKB_FRAGS + 1

> +				page->private = (unsigned long)first_page;
> +				first_page = page;
> +				if (--i == 1) {

this is pretty hairy ... has to be this way?
What you are trying to do here
is fill buffer with pages, in a loop, with first one
using a partial page, and then add it.
Is that it?
So please code this in a straight forward manner.
it should be as simple as:

	offset = XXX
	for (i = 0; i < MAX_SKB_FRAGS + 2; ++i) {
		
		sg_set_buf(sg + i, p + offset, PAGE_SIZE - offset);
		offset = 0;

	}

	err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, MAX_SKB_FRAGS + 2, first_page);

> +					int offset = hdr_len + 6;
> +
> +					/*
> +					 * share one page between virtio_net
> +					 * header and data, and reserve 6 bytes
> +					 * for alignment
> +					 */
> +					sg_set_buf(sg, p, hdr_len);
> +					sg_set_buf(sg+1, p + offset,

space around +
sg + 1 here is same as &sg[i] in fact?

> +						   PAGE_SIZE - offset);
> +					err = vi->rvq->vq_ops->add_buf(vi->rvq,
> +							sg, 0,
> +							MAX_SKB_FRAGS + 2,
> +							first_page);
> +					if (err < 0) {
> +						give_pages(vi, first_page);
> +						break;
> +					}
> +
> +				} else {
> +					sg_set_buf(&sg[i], p, PAGE_SIZE);
> +					goto more;
> +				}
> +			}
>  		}
>  		vi->num++;
>  	} while (err > 0);
> @@ -411,14 +461,13 @@ static void refill_work(struct work_struct *work)
>  static int virtnet_poll(struct napi_struct *napi, int budget)
>  {
>  	struct virtnet_info *vi = container_of(napi, struct virtnet_info, napi);
> -	struct sk_buff *skb = NULL;
> +	void *buf = NULL;
>  	unsigned int len, received = 0;
>  
>  again:
>  	while (received < budget &&
> -	       (skb = vi->rvq->vq_ops->get_buf(vi->rvq, &len)) != NULL) {
> -		__skb_unlink(skb, &vi->recv);
> -		receive_skb(vi->dev, skb, len);
> +	       (buf = vi->rvq->vq_ops->get_buf(vi->rvq, &len)) != NULL) {
> +		receive_skb(vi->dev, buf, len);
>  		vi->num--;
>  		received++;
>  	}
> @@ -959,6 +1008,7 @@ static void __devexit virtnet_remove(struct virtio_device *vdev)
>  {
>  	struct virtnet_info *vi = vdev->priv;
>  	struct sk_buff *skb;
> +	int freed;
>  
>  	/* Stop all the virtqueues. */
>  	vdev->config->reset(vdev);
> @@ -970,11 +1020,17 @@ static void __devexit virtnet_remove(struct virtio_device *vdev)
>  	}
>  	__skb_queue_purge(&vi->send);
>  
> -	BUG_ON(vi->num != 0);
> -
>  	unregister_netdev(vi->dev);
>  	cancel_delayed_work_sync(&vi->refill);

I this we must flush here otherwise refill might be in progress.

>  
> +	if (vi->mergeable_rx_bufs || vi->big_packets) {
> +		freed = vi->rvq->vq_ops->destroy_buf(vi->rvq,
> +						     virtio_free_pages);
> +		vi->num -= freed;
> +	}
> +
> +	BUG_ON(vi->num != 0);
> +
>  	vdev->config->del_vqs(vi->vdev);
>  
>  	while (vi->pages)
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index fbd2ecd..aec7fe7 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -334,6 +334,29 @@ static bool vring_enable_cb(struct virtqueue *_vq)
>  	return true;
>  }
>  
> +static int vring_destroy_buf(struct virtqueue *_vq, void (*callback)(void *))
> +{
> +	struct vring_virtqueue *vq = to_vvq(_vq);
> +	void *ret;
> +	unsigned int i;
> +	int freed = 0;
> +
> +	START_USE(vq);
> +
> +	for (i = 0; i < vq->vring.num; i++) {
> +		if (vq->data[i]) {
> +			/* detach_buf clears data, so grab it now. */
> +			ret = vq->data[i];
> +			detach_buf(vq, i);
> +			callback(ret);
> +			freed++;
> +		}
> +	}
> +
> +	END_USE(vq);
> +	return freed;
> +}
> +
>  irqreturn_t vring_interrupt(int irq, void *_vq)
>  {
>  	struct vring_virtqueue *vq = to_vvq(_vq);

virtio ring bits really must be a separate patch.

> @@ -360,6 +383,7 @@ static struct virtqueue_ops vring_vq_ops = {
>  	.kick = vring_kick,
>  	.disable_cb = vring_disable_cb,
>  	.enable_cb = vring_enable_cb,
> +	.destroy_buf = vring_destroy_buf,

not sure what a good name is, but destroy_buf is not it.

>  };
>  
>  struct virtqueue *vring_new_virtqueue(unsigned int num,
> diff --git a/include/linux/virtio.h b/include/linux/virtio.h
> index 057a2e0..7b1e86c 100644
> --- a/include/linux/virtio.h
> +++ b/include/linux/virtio.h
> @@ -71,6 +71,7 @@ struct virtqueue_ops {
>  
>  	void (*disable_cb)(struct virtqueue *vq);
>  	bool (*enable_cb)(struct virtqueue *vq);
> +	int (*destroy_buf)(struct virtqueue *vq, void (*callback)(void *));

callback -> destructor?

>  };
>  
>  /**
> 
> 
> 
> 
> --
> 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

* [PATCH] iproute: "ip mroute show" doesn't show all output interfaces
From: Andreas Henriksson @ 2009-11-23  9:52 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Mark Borst

From: Mark Borst <mark@borst.org>

The command "ip mroute show" will only show the first Oif. 

mark@flappie:~$ ip mroute show
(192.168.1.1, 224.0.0.123)       Iif: _rename    Oifs: eth1 

mark@flappie:~$ cat /proc/net/ip_mr_cache 
Group    Origin   Iif     Pkts    Bytes    Wrong Oifs
7B0000E0 0101A8C0 2          0        0        0  0:1    1:1  

This shows 2 Oifs here. However, ipmroute.c, function read_mroute_list(), uses sscanf() with a %s mask for oiflist, which stops after the first whitespace (i.e. after Oif 0:1). The patch below fixes this to read until the newline (though I'm not sure whether this is the proper way to fix it).

After this patch:
mark@flappie:~/iproute-20090324/ip$ ./ip mroute show
(192.168.1.1, 224.0.0.123)       Iif: _rename    Oifs: eth1 eth0 


This patch originally submitted as http://bugs.debian.org/550097

Signed-off-by: Andreas Henriksson <andreas@fatal.se>

--- iproute-20090324-origdeb/ip/ipmroute.c	2009-10-07 17:21:00.000000000 +0200
+++ iproute-20090324/ip/ipmroute.c	2009-10-07 17:34:01.000000000 +0200
@@ -95,7 +95,7 @@
 		char obuf[256];
 
 		oiflist[0] = 0;
-		if (sscanf(buf, "%x%x%d%u%u%u%s", maddr.data, msrc.data, &vifi,
+		if (sscanf(buf, "%x%x%d%u%u%u%[^\n]", maddr.data, msrc.data, &vifi,
 			   &pkts, &b, &w, oiflist) < 6)
 			continue;

^ permalink raw reply

* [PATCH] iproute2: use -fPIC in lib/
From: Andreas Henriksson @ 2009-11-23 10:03 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Dmitry Baryshev
In-Reply-To: <39840bc80909201712o65b1c84m1bc453bf9d4329a@mail.gmail.com>

The static libnetlink.a library is exposed to other users in Debian via the
"iproute-dev" package. Apparently people are interested in using it in their
shared libraries and would like to see the code be position independent.

Patch below makes the code under lib/ build with -fPIC.

See http://bugs.debian.org/547602

Signed-off-by: Andreas Henriksson <andreas@fatal.se>

---

Resending patch since no comments has been received and it has not
appeared in the iproute git repository.


diff --git a/lib/Makefile b/lib/Makefile
index bc270bf..da2f0fc 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -1,3 +1,4 @@
+CFLAGS += -fPIC
 
 UTILOBJ=utils.o rt_names.o ll_types.o ll_proto.o ll_addr.o inet_proto.o
 

^ permalink raw reply related

* Strange CPU load when flushing route cache (kernel 2.6.31.6)
From: Jesper Dangaard Brouer @ 2009-11-23  9:58 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Linux Kernel Network Hackers, Robert Olsson

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

Hi Eric and netdev,

I have observed a strange route cache behaviour when I upgraded some
of my production Linux routers (1Gbit/s tg3) to kernel 2.6.31.6 (from
kernel 2.6.25.7).

Every time the route cache is flushed I get a CPU spike (in softirq)
with a tail.  I have attached some graphs that illustrate the issue
(hope vger.kernel.org will allow these attachments...)


I have done some tuning of the route cache:

 # From /etc/sysctl.conf
 #
 # Adjusting the route cache flush interval
 net/ipv4/route/secret_interval = 1200

 # Limiting the route cache size
 # ip_dst_cache slab objects is 256 bytes.
 # 2000000 * 256 bytes = 512 MB
 net/ipv4/route/max_size = 2000000

Boot parameters: "rhash_entries=262143 vmalloc=256M"

The rhash_entries is for the route cache hash size.  The vmalloc is
needed because I have _very_ large iptables rulesets (and is running
on a 32-bit kernel, due to old hardware).

Any thoughs on how to avoid these CPU spikes?
Or where the issue occurs in the code?

-- 
Med venlig hilsen / Best regards
  Jesper Brouer
  ComX Networks A/S
  Linux Network Kernel Developer
  Cand. Scient Datalog / MSc.CS
  Author of http://adsl-optimizer.dk
  LinkedIn: http://www.linkedin.com/in/brouer

[-- Attachment #2: CPU_usage.png --]
[-- Type: image/png, Size: 16710 bytes --]

[-- Attachment #3: CPU_usage_softirq.png --]
[-- Type: image/png, Size: 15344 bytes --]

[-- Attachment #4: PPS_eth1-rx.png --]
[-- Type: image/png, Size: 10930 bytes --]

[-- Attachment #5: route_cache.png --]
[-- Type: image/png, Size: 17499 bytes --]

[-- Attachment #6: softnet_time_squeeze.png --]
[-- Type: image/png, Size: 15145 bytes --]

^ permalink raw reply

* ixgbe question
From: Eric Dumazet @ 2009-11-23 10:21 UTC (permalink / raw)
  To: Peter P Waskiewicz Jr; +Cc: Linux Netdev List
In-Reply-To: <1258968980.2697.9.camel@ppwaskie-mobl2>

Hi Peter

I tried a pktgen stress on 82599EB card and could not split RX load on multiple cpus.

Setup is :

One 82599 card with fiber0 looped to fiber1, 10Gb link mode.
machine is a HPDL380 G6 with dual quadcore E5530 @2.4GHz (16 logical cpus)

I use one pktgen thread sending to fiber0 one many dst IP, and checked that fiber1
was using many RX queues :

grep fiber1 /proc/interrupts 
117:       1301      13060          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-0
118:        601       1402          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-1
119:        634        832          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-2
120:        601       1303          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-3
121:        620       1246          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-4
122:       1287      13088          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-5
123:        606       1354          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-6
124:        653        827          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-7
125:        639        825          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-8
126:        596       1199          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-9
127:       2013      24800          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-10
128:        648       1353          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-11
129:        601       1123          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-12
130:        625        834          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-13
131:        665       1409          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-14
132:       2637      31699          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-15
133:          1          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1:lsc



But only one CPU (CPU1) had a softirq running, 100%, and many frames were dropped

root@demodl380g6:/usr/src# ifconfig fiber0
fiber0    Link encap:Ethernet  HWaddr 00:1b:21:4a:fe:54  
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          Packets reçus:4 erreurs:0 :0 overruns:0 frame:0
          TX packets:309291576 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 lg file transmission:1000 
          Octets reçus:1368 (1.3 KB) Octets transmis:18557495682 (18.5 GB)

root@demodl380g6:/usr/src# ifconfig fiber1
fiber1    Link encap:Ethernet  HWaddr 00:1b:21:4a:fe:55  
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          Packets reçus:55122164 erreurs:0 :254169411 overruns:0 frame:0
          TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 lg file transmission:1000 
          Octets reçus:3307330968 (3.3 GB) Octets transmis:1368 (1.3 KB)


How and when multi queue rx can really start to use several cpus ?

Thanks
Eric


pktgen script :

pgset()
{
    local result

    echo $1 > $PGDEV

    result=`cat $PGDEV | fgrep "Result: OK:"`
    if [ "$result" = "" ]; then
         cat $PGDEV | fgrep Result:
    fi
}

pg()
{
    echo inject > $PGDEV
    cat $PGDEV
}


PGDEV=/proc/net/pktgen/kpktgend_4

 echo "Adding fiber0"
 pgset "add_device fiber0@0"


CLONE_SKB="clone_skb 15"

PKT_SIZE="pkt_size 60"


COUNT="count 100000000"
DELAY="delay 0"

PGDEV=/proc/net/pktgen/fiber0@0
  echo "Configuring $PGDEV"
 pgset "$COUNT"
 pgset "$CLONE_SKB"
 pgset "$PKT_SIZE"
 pgset "$DELAY"
 pgset "queue_map_min 0"
 pgset "queue_map_max 7"
 pgset "dst_min 192.168.0.2"
 pgset "dst_max 192.168.0.250"
 pgset "src_min 192.168.0.1"
 pgset "src_max 192.168.0.1"
 pgset "dst_mac  00:1b:21:4a:fe:55"


# Time to run
PGDEV=/proc/net/pktgen/pgctrl

 echo "Running... ctrl^C to stop"
 pgset "start" 
 echo "Done"

# Result can be vieved in /proc/net/pktgen/fiber0@0

for f in fiber0@0
do
 cat /proc/net/pktgen/$f
done



^ permalink raw reply

* Re: Strange CPU load when flushing route cache (kernel 2.6.31.6)
From: Eric Dumazet @ 2009-11-23 10:29 UTC (permalink / raw)
  To: Jesper Dangaard Brouer; +Cc: Linux Kernel Network Hackers, Robert Olsson
In-Reply-To: <1258970332.29747.262.camel@jdb-workstation>

Jesper Dangaard Brouer a écrit :
> Hi Eric and netdev,
> 
> I have observed a strange route cache behaviour when I upgraded some
> of my production Linux routers (1Gbit/s tg3) to kernel 2.6.31.6 (from
> kernel 2.6.25.7).
> 
> Every time the route cache is flushed I get a CPU spike (in softirq)
> with a tail.  I have attached some graphs that illustrate the issue
> (hope vger.kernel.org will allow these attachments...)
> 
> 
> I have done some tuning of the route cache:
> 
>  # From /etc/sysctl.conf
>  #
>  # Adjusting the route cache flush interval
>  net/ipv4/route/secret_interval = 1200
> 
>  # Limiting the route cache size
>  # ip_dst_cache slab objects is 256 bytes.
>  # 2000000 * 256 bytes = 512 MB
>  net/ipv4/route/max_size = 2000000
> 
> Boot parameters: "rhash_entries=262143 vmalloc=256M"
> 
> The rhash_entries is for the route cache hash size.  The vmalloc is
> needed because I have _very_ large iptables rulesets (and is running
> on a 32-bit kernel, due to old hardware).
> 
> Any thoughs on how to avoid these CPU spikes?
> Or where the issue occurs in the code?
> 

Sure, after a flush, we have to rebuild the cache, so extra work is expected.

(We receive a packet, notice the cached entry is obsolete, free it, allocate a new one
and inert it into cache)

If you dont want these spikes, just dont flush cache :)

Do you run a 2G/2G User/Kernel split kernel ?


^ permalink raw reply

* Re: ixgbe question
From: Badalian Vyacheslav @ 2009-11-23 10:30 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Peter P Waskiewicz Jr, Linux Netdev List
In-Reply-To: <4B0A6218.9040303@gmail.com>

Hello Eric. I paly with this card 3 weeks and maybe help for you :)

By default intel flower use only first cpu. Its strange.
If we add affinity to single cpu core for interrupt its will use this CPU core.
If we add affinity to two or more cpus its applying but don't work.
See ixgbe driver README from intel.com. Its have param for RSS flower. I think its do this :)
Also driver from intel.com have script for split RxTx->Cpu core but you must replace "tx rx" in code to "TxRx".

P.S. Please also see if you can and wont:
On e1000 and x86 kernel + 2xXeon 2core my TC rules load 3 min
On ixgbe and X86_64 kernel + 4xXeon 6core my TC rules load more 15 mins!
Its 64 bit regression?

Tc rules i can send to you if you ask me for it! Thanks!

Slavon


> Hi Peter
> 
> I tried a pktgen stress on 82599EB card and could not split RX load on multiple cpus.
> 
> Setup is :
> 
> One 82599 card with fiber0 looped to fiber1, 10Gb link mode.
> machine is a HPDL380 G6 with dual quadcore E5530 @2.4GHz (16 logical cpus)
> 
> I use one pktgen thread sending to fiber0 one many dst IP, and checked that fiber1
> was using many RX queues :
> 
> grep fiber1 /proc/interrupts 
> 117:       1301      13060          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-0
> 118:        601       1402          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-1
> 119:        634        832          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-2
> 120:        601       1303          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-3
> 121:        620       1246          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-4
> 122:       1287      13088          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-5
> 123:        606       1354          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-6
> 124:        653        827          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-7
> 125:        639        825          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-8
> 126:        596       1199          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-9
> 127:       2013      24800          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-10
> 128:        648       1353          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-11
> 129:        601       1123          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-12
> 130:        625        834          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-13
> 131:        665       1409          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-14
> 132:       2637      31699          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-15
> 133:          1          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1:lsc
> 
> 
> 
> But only one CPU (CPU1) had a softirq running, 100%, and many frames were dropped
> 
> root@demodl380g6:/usr/src# ifconfig fiber0
> fiber0    Link encap:Ethernet  HWaddr 00:1b:21:4a:fe:54  
>           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
>           Packets reçus:4 erreurs:0 :0 overruns:0 frame:0
>           TX packets:309291576 errors:0 dropped:0 overruns:0 carrier:0
>           collisions:0 lg file transmission:1000 
>           Octets reçus:1368 (1.3 KB) Octets transmis:18557495682 (18.5 GB)
> 
> root@demodl380g6:/usr/src# ifconfig fiber1
> fiber1    Link encap:Ethernet  HWaddr 00:1b:21:4a:fe:55  
>           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
>           Packets reçus:55122164 erreurs:0 :254169411 overruns:0 frame:0
>           TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
>           collisions:0 lg file transmission:1000 
>           Octets reçus:3307330968 (3.3 GB) Octets transmis:1368 (1.3 KB)
> 
> 
> How and when multi queue rx can really start to use several cpus ?
> 
> Thanks
> Eric
> 
> 
> pktgen script :
> 
> pgset()
> {
>     local result
> 
>     echo $1 > $PGDEV
> 
>     result=`cat $PGDEV | fgrep "Result: OK:"`
>     if [ "$result" = "" ]; then
>          cat $PGDEV | fgrep Result:
>     fi
> }
> 
> pg()
> {
>     echo inject > $PGDEV
>     cat $PGDEV
> }
> 
> 
> PGDEV=/proc/net/pktgen/kpktgend_4
> 
>  echo "Adding fiber0"
>  pgset "add_device fiber0@0"
> 
> 
> CLONE_SKB="clone_skb 15"
> 
> PKT_SIZE="pkt_size 60"
> 
> 
> COUNT="count 100000000"
> DELAY="delay 0"
> 
> PGDEV=/proc/net/pktgen/fiber0@0
>   echo "Configuring $PGDEV"
>  pgset "$COUNT"
>  pgset "$CLONE_SKB"
>  pgset "$PKT_SIZE"
>  pgset "$DELAY"
>  pgset "queue_map_min 0"
>  pgset "queue_map_max 7"
>  pgset "dst_min 192.168.0.2"
>  pgset "dst_max 192.168.0.250"
>  pgset "src_min 192.168.0.1"
>  pgset "src_max 192.168.0.1"
>  pgset "dst_mac  00:1b:21:4a:fe:55"
> 
> 
> # Time to run
> PGDEV=/proc/net/pktgen/pgctrl
> 
>  echo "Running... ctrl^C to stop"
>  pgset "start" 
>  echo "Done"
> 
> # Result can be vieved in /proc/net/pktgen/fiber0@0
> 
> for f in fiber0@0
> do
>  cat /proc/net/pktgen/$f
> done
> 
> 
> --
> 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

* macvlan: fix gso_max_size setting
From: Patrick McHardy @ 2009-11-23 10:33 UTC (permalink / raw)
  To: David S. Miller; +Cc: Linux Netdev List

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

Fix macvlan gso_max_size setting. Based on net-next-2.6.git.


[-- Attachment #2: x --]
[-- Type: text/plain, Size: 1184 bytes --]

commit 198a1fd488e7ebec080d1d2da7947cb9e1aacebf
Author: Patrick McHardy <kaber@trash.net>
Date:   Mon Nov 23 11:28:22 2009 +0100

    macvlan: fix gso_max_size setting
    
    gso_max_size must be set based on the value of the underlying device to
    support devices not using the full 64k.
    
    Signed-off-by: Patrick McHardy <kaber@trash.net>

diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index ae2b5c7..7b0ef0c 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -376,6 +376,7 @@ static int macvlan_init(struct net_device *dev)
 	dev->state		= (dev->state & ~MACVLAN_STATE_MASK) |
 				  (lowerdev->state & MACVLAN_STATE_MASK);
 	dev->features 		= lowerdev->features & MACVLAN_FEATURES;
+	dev->gso_max_size	= lowerdev->gso_max_size;
 	dev->iflink		= lowerdev->ifindex;
 	dev->hard_header_len	= lowerdev->hard_header_len;
 
@@ -652,6 +653,7 @@ static int macvlan_device_event(struct notifier_block *unused,
 	case NETDEV_FEAT_CHANGE:
 		list_for_each_entry(vlan, &port->vlans, list) {
 			vlan->dev->features = dev->features & MACVLAN_FEATURES;
+			vlan->dev->gso_max_size = dev->gso_max_size;
 			netdev_features_change(vlan->dev);
 		}
 		break;

^ permalink raw reply related

* Re: ixgbe question
From: Waskiewicz Jr, Peter P @ 2009-11-23 10:34 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Waskiewicz Jr, Peter P, Linux Netdev List
In-Reply-To: <4B0A6218.9040303@gmail.com>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 5581 bytes --]

On Mon, 23 Nov 2009, Eric Dumazet wrote:

> Hi Peter
> 
> I tried a pktgen stress on 82599EB card and could not split RX load on multiple cpus.
> 
> Setup is :
> 
> One 82599 card with fiber0 looped to fiber1, 10Gb link mode.
> machine is a HPDL380 G6 with dual quadcore E5530 @2.4GHz (16 logical cpus)

Can you specify kernel version and driver version?

> 
> I use one pktgen thread sending to fiber0 one many dst IP, and checked that fiber1
> was using many RX queues :
> 
> grep fiber1 /proc/interrupts 
> 117:       1301      13060          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-0
> 118:        601       1402          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-1
> 119:        634        832          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-2
> 120:        601       1303          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-3
> 121:        620       1246          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-4
> 122:       1287      13088          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-5
> 123:        606       1354          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-6
> 124:        653        827          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-7
> 125:        639        825          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-8
> 126:        596       1199          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-9
> 127:       2013      24800          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-10
> 128:        648       1353          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-11
> 129:        601       1123          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-12
> 130:        625        834          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-13
> 131:        665       1409          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-14
> 132:       2637      31699          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-15
> 133:          1          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1:lsc
> 
> 
> 
> But only one CPU (CPU1) had a softirq running, 100%, and many frames were dropped
> 
> root@demodl380g6:/usr/src# ifconfig fiber0
> fiber0    Link encap:Ethernet  HWaddr 00:1b:21:4a:fe:54  
>           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
>           Packets reçus:4 erreurs:0 :0 overruns:0 frame:0
>           TX packets:309291576 errors:0 dropped:0 overruns:0 carrier:0
>           collisions:0 lg file transmission:1000 
>           Octets reçus:1368 (1.3 KB) Octets transmis:18557495682 (18.5 GB)
> 
> root@demodl380g6:/usr/src# ifconfig fiber1
> fiber1    Link encap:Ethernet  HWaddr 00:1b:21:4a:fe:55  
>           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
>           Packets reçus:55122164 erreurs:0 :254169411 overruns:0 frame:0
>           TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
>           collisions:0 lg file transmission:1000 
>           Octets reçus:3307330968 (3.3 GB) Octets transmis:1368 (1.3 KB)

I stay in the states too much.  I love seeing net stats in French.  :-)

> 
> 
> How and when multi queue rx can really start to use several cpus ?

If you're sending one flow to many consumers, it's still one flow.  Even 
using RSS won't help, since it requires differing flows to spread load  
(5-tuple matches for flow distribution).

Cheers,
-PJ

^ permalink raw reply

* Re: ixgbe question
From: Eric Dumazet @ 2009-11-23 10:37 UTC (permalink / raw)
  To: Waskiewicz Jr, Peter P; +Cc: Linux Netdev List
In-Reply-To: <Pine.WNT.4.64.0911230225140.6352@ppwaskie-MOBL2.amr.corp.intel.com>

Waskiewicz Jr, Peter P a écrit :
> On Mon, 23 Nov 2009, Eric Dumazet wrote:
> 
>> Hi Peter
>>
>> I tried a pktgen stress on 82599EB card and could not split RX load on multiple cpus.
>>
>> Setup is :
>>
>> One 82599 card with fiber0 looped to fiber1, 10Gb link mode.
>> machine is a HPDL380 G6 with dual quadcore E5530 @2.4GHz (16 logical cpus)
> 
> Can you specify kernel version and driver version?


Well, I forgot to mention I am only working with net-next-2.6 tree.

Ubuntu 9.10 kernel (Fedora Core 12 installer was not able to recognize disks on this machine :( )

ixgbe: Intel(R) 10 Gigabit PCI Express Network Driver - version 2.0.44-k2


> 
>> I use one pktgen thread sending to fiber0 one many dst IP, and checked that fiber1
>> was using many RX queues :
>>
>> grep fiber1 /proc/interrupts 
>> 117:       1301      13060          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-0
>> 118:        601       1402          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-1
>> 119:        634        832          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-2
>> 120:        601       1303          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-3
>> 121:        620       1246          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-4
>> 122:       1287      13088          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-5
>> 123:        606       1354          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-6
>> 124:        653        827          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-7
>> 125:        639        825          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-8
>> 126:        596       1199          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-9
>> 127:       2013      24800          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-10
>> 128:        648       1353          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-11
>> 129:        601       1123          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-12
>> 130:        625        834          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-13
>> 131:        665       1409          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-14
>> 132:       2637      31699          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1-TxRx-15
>> 133:          1          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0   PCI-MSI-edge      fiber1:lsc
>>
>>
>>
>> But only one CPU (CPU1) had a softirq running, 100%, and many frames were dropped
>>
>> root@demodl380g6:/usr/src# ifconfig fiber0
>> fiber0    Link encap:Ethernet  HWaddr 00:1b:21:4a:fe:54  
>>           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
>>           Packets reçus:4 erreurs:0 :0 overruns:0 frame:0
>>           TX packets:309291576 errors:0 dropped:0 overruns:0 carrier:0
>>           collisions:0 lg file transmission:1000 
>>           Octets reçus:1368 (1.3 KB) Octets transmis:18557495682 (18.5 GB)
>>
>> root@demodl380g6:/usr/src# ifconfig fiber1
>> fiber1    Link encap:Ethernet  HWaddr 00:1b:21:4a:fe:55  
>>           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
>>           Packets reçus:55122164 erreurs:0 :254169411 overruns:0 frame:0
>>           TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
>>           collisions:0 lg file transmission:1000 
>>           Octets reçus:3307330968 (3.3 GB) Octets transmis:1368 (1.3 KB)
> 
> I stay in the states too much.  I love seeing net stats in French.  :-)

Ok :)

> 
>>
>> How and when multi queue rx can really start to use several cpus ?
> 
> If you're sending one flow to many consumers, it's still one flow.  Even 
> using RSS won't help, since it requires differing flows to spread load  
> (5-tuple matches for flow distribution).

Hm... I can try varying both src and dst on my pktgen test.

Thanks

^ permalink raw reply

* Request for help with iproute2 bugs.
From: Andreas Henriksson @ 2009-11-23 10:37 UTC (permalink / raw)
  To: netdev; +Cc: shemminger

Hello everybody!

This is a desperate attempt at finding people with time and motivation
to look into bugs that has been reported against the iproute package
in the debian bug tracking system. The reported bugs are usually
not Debian-specific...

You'll find the complete list at http://bugs.debian.org/iproute
If you have comments, please email them to <bugnumber>@bugs.debian.org


Here's a list of interesting candidates, hopefully you'll find some useful
comments if you follow the link (usually last comment at the bottom):

http://bugs.debian.org/532152 - incorrectly enumerates existing addresses.
  iproute: 'ip addr flush' exits with error on first try

http://bugs.debian.org/525933 - many ip-addresses not handled gracefully.
  iproute: "ip address" failes to list all IPs on an interface

http://bugs.debian.org/511720 - rip out flawed code in favor of sed ?
  iproute: ss filter parsing flawed

http://bugs.debian.org/532727
  iproute: "tc filter add ... protocol ip fw" broken?

http://bugs.debian.org/551937 - replacing ipv6 routes broken.
  iproute: "ip -6 route replace ..." behaves as "ip -6 route add ..."

http://bugs.debian.org/498498 - ipv6 specific blackhole routing.
  iproute: adding route blackholes doesn't work for IPv6

http://bugs.debian.org/508450 - weird behaviour confuses users.
   ip tun add fails to create tunnel without remote, though no error



-- 
Andreas Henriksson

^ permalink raw reply

* Buy 1, get 2 for free
From: Caroline Rangel @ 2009-11-23 10:56 UTC (permalink / raw)
  To: netdev

Perfect proportions are easily to get . http://vxre.pointinvent.com/


^ permalink raw reply

* Re: Request for help with iproute2 bugs.
From: Patrick McHardy @ 2009-11-23 11:03 UTC (permalink / raw)
  To: Andreas Henriksson; +Cc: netdev, shemminger
In-Reply-To: <20091123103742.GA14713@amd64.fatal.se>

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

Andreas Henriksson wrote:
> http://bugs.debian.org/532727
>   iproute: "tc filter add ... protocol ip fw" broken?
> 

This one is caused by a regression in iproute2. The attached patch
should fix it.

[-- Attachment #2: x --]
[-- Type: text/plain, Size: 1640 bytes --]

commit b3d80773099c13f60598857901cb2724c210614f
Author: Patrick McHardy <kaber@trash.net>
Date:   Mon Nov 23 12:00:46 2009 +0100

    f_fw: fix compat mode
    
    The kernel takes a lack of options as indication that the fw classifier
    should operate in compatibility mode, where marks are mapped directly to
    classids.
    
    Commit e22b42a (tc mask patch) broke this by adding an empty TCA_OPTIONS
    attribute even if no handle is specified. Restore the old behaviour.
    
    Signed-off-by: Patrick McHardy <kaber@trash.net>

diff --git a/tc/f_fw.c b/tc/f_fw.c
index b511735..cc8ea2d 100644
--- a/tc/f_fw.c
+++ b/tc/f_fw.c
@@ -38,15 +38,13 @@ static int fw_parse_opt(struct filter_util *qu, char *handle, int argc, char **a
 	struct tc_police tp;
 	struct tcmsg *t = NLMSG_DATA(n);
 	struct rtattr *tail;
+	__u32 mask = 0;
+	int mask_set = 0;
 
 	memset(&tp, 0, sizeof(tp));
 
-	tail = NLMSG_TAIL(n);
-	addattr_l(n, 4096, TCA_OPTIONS, NULL, 0);
-
 	if (handle) {
 		char *slash;
-		__u32 mask = 0;
 		if ((slash = strchr(handle, '/')) != NULL)
 			*slash = '\0';
 		if (get_u32(&t->tcm_handle, handle, 0)) {
@@ -58,13 +56,19 @@ static int fw_parse_opt(struct filter_util *qu, char *handle, int argc, char **a
 				fprintf(stderr, "Illegal \"handle\" mask\n");
 				return -1;
 			}
-			addattr32(n, MAX_MSG, TCA_FW_MASK, mask);
+			mask_set = 1;
 		}
 	}
 
 	if (argc == 0)
 		return 0;
 
+	tail = NLMSG_TAIL(n);
+	addattr_l(n, 4096, TCA_OPTIONS, NULL, 0);
+
+	if (mask_set)
+		addattr32(n, MAX_MSG, TCA_FW_MASK, mask);
+
 	while (argc > 0) {
 		if (matches(*argv, "classid") == 0 ||
 		    matches(*argv, "flowid") == 0) {

^ permalink raw reply related

* Re: [net-next-2.6 PATCH v7 5/7 RFC] TCPCT part 1e: implement socket option TCP_COOKIE_TRANSACTIONS
From: William Allen Simpson @ 2009-11-23 11:16 UTC (permalink / raw)
  To: Joe Perches; +Cc: David Miller, netdev
In-Reply-To: <1258873848.16503.12.camel@Joe-Laptop.home>

Joe Perches wrote:
> On Sun, 2009-11-22 at 01:25 -0500, William Allen Simpson wrote:
>> David Miller wrote:
>>> From: William Allen Simpson <william.allen.simpson@gmail.com>
>>> Date: Fri, 20 Nov 2009 09:48:12 -0500
>>>> +		if (ctd.tcpct_used > 0
>>>> +		 || (tp->cookie_values == NULL
>>>> +		  && (sysctl_tcp_cookie_size > 0
>>>> +		   || ctd.tcpct_cookie_desired > 0
>>>> +		   || ctd.tcpct_s_data_desired > 0))) {
>>> Please fix the conditional coding style, and the alignment of
>>> the lines, it's not right here.
> 
> I think the rather significantly majority style, especially
> for net/... is to use || and && at the end of the line rather
> than the start and it should be used.
> 
> Treewide:
> 
> $ grep -rP --include=*.[ch] "(\|\||\&\&)\s*$" * | wc -l
> 34180
> 
> $ grep -rP --include=*.[ch] "^\s*(\|\||\&\&)" * | wc -l
> 7855
> 
> net: 3859 to 382 (more than 10:1, so it's the one to follow)
> drivers/net: 4610 to 666
> 
Thanks for measuring.

I'll note that during the previous review back at the v4 round, you
(Joe) passed along a formerly private message from Linus expressing his
preference for variable lvalues:

   http://www.spinics.net/lists/netdev/msg111212.html

But my example code in that thread also had both leading && and || -- and
neither David nor Eric nor Ilpo nor you mentioned that as an issue in that
entire thread:

   http://www.spinics.net/lists/netdev/msg111172.html

In the previous plaint about lvalues, there were merely 500+ examples
using the same constant lvalue form as my code -- in arch, drivers, net,
and sound.  For this example, many *thousands* are found everywhere!

Therefore, it's plain as can be that this is just more jumping through
arbitrary and capricious hoops that others are not required to follow.


> Besides, it's the one David wants...
> 
At *thousands* of examples, including in the tcp*.c files themselves, it
really becomes obvious that that may be a personal preference of David,
but is *not* a tree-wide or even a net-wide coding style.

However, a private message to me nearly 2 months ago expressed:

   "As unpalatable as it may be, all the more reason to genuflect as
   required to get the changes into the net-next-2.6 tree so they will
   flow down to future distros."

I followed that advice for a month.  That last patch submitted for
inclusion was v4 on Oct 27th.  Then, as some have noticed, I quit using
the net-next tree for actual development.  I've only sent weekly RFC
versions to solicit more widespread comments from subject matter experts,
and keep the patch offsets in sync with the rapidly changing tree.

As a more recent private comment asked:

   "So your frustration is nothing but normal.  And guess what ? Few
   people accept the challenge, so keep trying !"

So, I'll try again now, with the assurance that this is the final hoop.

^ permalink raw reply

* [PATCH] pktgen: Fix device name compares
From: Eric Dumazet @ 2009-11-23 11:44 UTC (permalink / raw)
  To: David S. Miller; +Cc: Linux Netdev List, Robert Olsson

Commit e6fce5b916cd7f7f7 (pktgen: multiqueue etc.) tried to relax
the pktgen restriction of one device per kernel thread, adding a '@'
tag to device names.

Problem is we dont perform check on full pktgen device name.
This allows adding many time same 'device' to pktgen thread

 pgset "add_device eth0@0"

one session later :

 pgset "add_device eth0@0"

(This doesnt find previous device)

This consumes ~1.5 MBytes of vmalloc memory per round and also triggers
this warning :

[  673.186380] proc_dir_entry 'pktgen/eth0@0' already registered
[  673.186383] Modules linked in: pktgen ixgbe ehci_hcd psmouse mdio mousedev evdev [last unloaded: pktgen]
[  673.186406] Pid: 6219, comm: bash Tainted: G        W  2.6.32-rc7-03302-g41cec6f-dirty #16
[  673.186410] Call Trace:
[  673.186417]  [<ffffffff8104a29b>] warn_slowpath_common+0x7b/0xc0
[  673.186422]  [<ffffffff8104a341>] warn_slowpath_fmt+0x41/0x50
[  673.186426]  [<ffffffff8114e789>] proc_register+0x109/0x210
[  673.186433]  [<ffffffff8100bf2e>] ? apic_timer_interrupt+0xe/0x20
[  673.186438]  [<ffffffff8114e905>] proc_create_data+0x75/0xd0
[  673.186444]  [<ffffffffa006ad38>] pktgen_thread_write+0x568/0x640 [pktgen]
[  673.186449]  [<ffffffffa006a7d0>] ? pktgen_thread_write+0x0/0x640 [pktgen]
[  673.186453]  [<ffffffff81149144>] proc_reg_write+0x84/0xc0
[  673.186458]  [<ffffffff810f5a58>] vfs_write+0xb8/0x180
[  673.186463]  [<ffffffff810f5c11>] sys_write+0x51/0x90
[  673.186468]  [<ffffffff8100b51b>] system_call_fastpath+0x16/0x1b
[  673.186470] ---[ end trace ccbb991b0a8d994d ]---

Solution to this problem is to use a odevname field (includes @ tag and suffix),
instead of using netdevice name.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
 net/core/pktgen.c |   18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index d38470a..1813f08 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -364,6 +364,7 @@ struct pktgen_dev {
 				  * device name (not when the inject is
 				  * started as it used to do.)
 				  */
+	char odevname[32];
 	struct flow_state *flows;
 	unsigned cflows;	/* Concurrent flows (config) */
 	unsigned lflow;		/* Flow length  (config) */
@@ -529,7 +530,7 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
 	seq_printf(seq,
 		   "     frags: %d  delay: %llu  clone_skb: %d  ifname: %s\n",
 		   pkt_dev->nfrags, (unsigned long long) pkt_dev->delay,
-		   pkt_dev->clone_skb, pkt_dev->odev->name);
+		   pkt_dev->clone_skb, pkt_dev->odevname);
 
 	seq_printf(seq, "     flows: %u flowlen: %u\n", pkt_dev->cflows,
 		   pkt_dev->lflow);
@@ -1689,13 +1690,13 @@ static int pktgen_thread_show(struct seq_file *seq, void *v)
 	if_lock(t);
 	list_for_each_entry(pkt_dev, &t->if_list, list)
 		if (pkt_dev->running)
-			seq_printf(seq, "%s ", pkt_dev->odev->name);
+			seq_printf(seq, "%s ", pkt_dev->odevname);
 
 	seq_printf(seq, "\nStopped: ");
 
 	list_for_each_entry(pkt_dev, &t->if_list, list)
 		if (!pkt_dev->running)
-			seq_printf(seq, "%s ", pkt_dev->odev->name);
+			seq_printf(seq, "%s ", pkt_dev->odevname);
 
 	if (t->result[0])
 		seq_printf(seq, "\nResult: %s\n", t->result);
@@ -1995,7 +1996,7 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
 		       "queue_map_min (zero-based) (%d) exceeds valid range "
 		       "[0 - %d] for (%d) queues on %s, resetting\n",
 		       pkt_dev->queue_map_min, (ntxq ?: 1) - 1, ntxq,
-		       pkt_dev->odev->name);
+		       pkt_dev->odevname);
 		pkt_dev->queue_map_min = ntxq - 1;
 	}
 	if (pkt_dev->queue_map_max >= ntxq) {
@@ -2003,7 +2004,7 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
 		       "queue_map_max (zero-based) (%d) exceeds valid range "
 		       "[0 - %d] for (%d) queues on %s, resetting\n",
 		       pkt_dev->queue_map_max, (ntxq ?: 1) - 1, ntxq,
-		       pkt_dev->odev->name);
+		       pkt_dev->odevname);
 		pkt_dev->queue_map_max = ntxq - 1;
 	}
 
@@ -3263,7 +3264,7 @@ static int pktgen_stop_device(struct pktgen_dev *pkt_dev)
 
 	if (!pkt_dev->running) {
 		printk(KERN_WARNING "pktgen: interface: %s is already "
-		       "stopped\n", pkt_dev->odev->name);
+		       "stopped\n", pkt_dev->odevname);
 		return -EINVAL;
 	}
 
@@ -3467,7 +3468,7 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
 	default: /* Drivers are not supposed to return other values! */
 		if (net_ratelimit())
 			pr_info("pktgen: %s xmit error: %d\n",
-				odev->name, ret);
+				pkt_dev->odevname, ret);
 		pkt_dev->errors++;
 		/* fallthru */
 	case NETDEV_TX_LOCKED:
@@ -3576,7 +3577,7 @@ static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t,
 	if_lock(t);
 
 	list_for_each_entry(p, &t->if_list, list)
-		if (strncmp(p->odev->name, ifname, IFNAMSIZ) == 0) {
+		if (strncmp(p->odevname, ifname, IFNAMSIZ) == 0) {
 			pkt_dev = p;
 			break;
 		}
@@ -3632,6 +3633,7 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
 	if (!pkt_dev)
 		return -ENOMEM;
 
+	strcpy(pkt_dev->odevname, ifname);
 	pkt_dev->flows = vmalloc(MAX_CFLOWS * sizeof(struct flow_state));
 	if (pkt_dev->flows == NULL) {
 		kfree(pkt_dev);

^ permalink raw reply related

* Re: Strange CPU load when flushing route cache (kernel 2.6.31.6)
From: Jesper Dangaard Brouer @ 2009-11-23 12:28 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Linux Kernel Network Hackers, Robert Olsson
In-Reply-To: <4B0A63FA.5000804@gmail.com>

On Mon, 2009-11-23 at 11:29 +0100, Eric Dumazet wrote:
> Jesper Dangaard Brouer a écrit :
> > Hi Eric and netdev,
> > 
> > I have observed a strange route cache behaviour when I upgraded some
> > of my production Linux routers (1Gbit/s tg3) to kernel 2.6.31.6 (from
> > kernel 2.6.25.7).
> > 
> > Every time the route cache is flushed I get a CPU spike (in softirq)
> > with a tail.  I have attached some graphs that illustrate the issue
> > (hope vger.kernel.org will allow these attachments...)
> > 
> > 
> > I have done some tuning of the route cache:
> > 
> >  # From /etc/sysctl.conf
> >  #
> >  # Adjusting the route cache flush interval
> >  net/ipv4/route/secret_interval = 1200
> > 
> >  # Limiting the route cache size
> >  # ip_dst_cache slab objects is 256 bytes.
> >  # 2000000 * 256 bytes = 512 MB
> >  net/ipv4/route/max_size = 2000000
> > 
> > Boot parameters: "rhash_entries=262143 vmalloc=256M"
> > 
> > The rhash_entries is for the route cache hash size.  The vmalloc is
> > needed because I have _very_ large iptables rulesets (and is running
> > on a 32-bit kernel, due to old hardware).
> > 
> > Any thoughs on how to avoid these CPU spikes?
> > Or where the issue occurs in the code?
> > 
> 
> Sure, after a flush, we have to rebuild the cache, so extra work is expected.

But the old 2.6.25.7 do NOT show this behavior... That is the real
issue...

> (We receive a packet, notice the cached entry is obsolete, free it, allocate a new one
> and inert it into cache)
> 
> If you dont want these spikes, just dont flush cache :)

I did the cache flushing due to some historical issues, that I think you
did a fix for... Guess I can drop the flushing and see if the garbage
collection can keep up...

> Do you run a 2G/2G User/Kernel split kernel ?

Not sure, how do I check?

I do use a 32-bit kernel (due to the production machines runs an old
32-bit Slackware OS install and some of the machines cannot run 64-bit).

-- 
Med venlig hilsen / Best regards
  Jesper Brouer
  ComX Networks A/S
  Linux Network Kernel Developer
  Cand. Scient Datalog / MSc.CS
  Author of http://adsl-optimizer.dk
  LinkedIn: http://www.linkedin.com/in/brouer

^ permalink raw reply

* [PATCH] pktgen: Fix device name compares
From: robert @ 2009-11-23 14:44 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David S. Miller, Linux Netdev List, Robert Olsson
In-Reply-To: <4B0A75A5.8000106@gmail.com>


Eric Dumazet writes:
 > Commit e6fce5b916cd7f7f7 (pktgen: multiqueue etc.) tried to relax
 > the pktgen restriction of one device per kernel thread, adding a '@'
 > tag to device names.
 > 
 > Problem is we dont perform check on full pktgen device name.
 > This allows adding many time same 'device' to pktgen thread
 > 
 >  pgset "add_device eth0@0"
 > 
 > one session later :
 > 
 >  pgset "add_device eth0@0"
 > 
 > (This doesnt find previous device)

 

 > Solution to this problem is to use a odevname field (includes @ tag and suffix),
 > instead of using netdevice name.


 Ok. So the duplicate test got wrong when the multiqueue stuff was 
 added. 

 Signed-off-by: Robert Olsson <robert.olsson@its.uu.se>

 Cheers
					--ro



 > Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
 > ---
 >  net/core/pktgen.c |   18 ++++++++++--------
 >  1 file changed, 10 insertions(+), 8 deletions(-)
 > 
 > diff --git a/net/core/pktgen.c b/net/core/pktgen.c
 > index d38470a..1813f08 100644
 > --- a/net/core/pktgen.c
 > +++ b/net/core/pktgen.c
 > @@ -364,6 +364,7 @@ struct pktgen_dev {
 >  				  * device name (not when the inject is
 >  				  * started as it used to do.)
 >  				  */
 > +	char odevname[32];
 >  	struct flow_state *flows;
 >  	unsigned cflows;	/* Concurrent flows (config) */
 >  	unsigned lflow;		/* Flow length  (config) */
 > @@ -529,7 +530,7 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
 >  	seq_printf(seq,
 >  		   "     frags: %d  delay: %llu  clone_skb: %d  ifname: %s\n",
 >  		   pkt_dev->nfrags, (unsigned long long) pkt_dev->delay,
 > -		   pkt_dev->clone_skb, pkt_dev->odev->name);
 > +		   pkt_dev->clone_skb, pkt_dev->odevname);
 >  
 >  	seq_printf(seq, "     flows: %u flowlen: %u\n", pkt_dev->cflows,
 >  		   pkt_dev->lflow);
 > @@ -1689,13 +1690,13 @@ static int pktgen_thread_show(struct seq_file *seq, void *v)
 >  	if_lock(t);
 >  	list_for_each_entry(pkt_dev, &t->if_list, list)
 >  		if (pkt_dev->running)
 > -			seq_printf(seq, "%s ", pkt_dev->odev->name);
 > +			seq_printf(seq, "%s ", pkt_dev->odevname);
 >  
 >  	seq_printf(seq, "\nStopped: ");
 >  
 >  	list_for_each_entry(pkt_dev, &t->if_list, list)
 >  		if (!pkt_dev->running)
 > -			seq_printf(seq, "%s ", pkt_dev->odev->name);
 > +			seq_printf(seq, "%s ", pkt_dev->odevname);
 >  
 >  	if (t->result[0])
 >  		seq_printf(seq, "\nResult: %s\n", t->result);
 > @@ -1995,7 +1996,7 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
 >  		       "queue_map_min (zero-based) (%d) exceeds valid range "
 >  		       "[0 - %d] for (%d) queues on %s, resetting\n",
 >  		       pkt_dev->queue_map_min, (ntxq ?: 1) - 1, ntxq,
 > -		       pkt_dev->odev->name);
 > +		       pkt_dev->odevname);
 >  		pkt_dev->queue_map_min = ntxq - 1;
 >  	}
 >  	if (pkt_dev->queue_map_max >= ntxq) {
 > @@ -2003,7 +2004,7 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
 >  		       "queue_map_max (zero-based) (%d) exceeds valid range "
 >  		       "[0 - %d] for (%d) queues on %s, resetting\n",
 >  		       pkt_dev->queue_map_max, (ntxq ?: 1) - 1, ntxq,
 > -		       pkt_dev->odev->name);
 > +		       pkt_dev->odevname);
 >  		pkt_dev->queue_map_max = ntxq - 1;
 >  	}
 >  
 > @@ -3263,7 +3264,7 @@ static int pktgen_stop_device(struct pktgen_dev *pkt_dev)
 >  
 >  	if (!pkt_dev->running) {
 >  		printk(KERN_WARNING "pktgen: interface: %s is already "
 > -		       "stopped\n", pkt_dev->odev->name);
 > +		       "stopped\n", pkt_dev->odevname);
 >  		return -EINVAL;
 >  	}
 >  
 > @@ -3467,7 +3468,7 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
 >  	default: /* Drivers are not supposed to return other values! */
 >  		if (net_ratelimit())
 >  			pr_info("pktgen: %s xmit error: %d\n",
 > -				odev->name, ret);
 > +				pkt_dev->odevname, ret);
 >  		pkt_dev->errors++;
 >  		/* fallthru */
 >  	case NETDEV_TX_LOCKED:
 > @@ -3576,7 +3577,7 @@ static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t,
 >  	if_lock(t);
 >  
 >  	list_for_each_entry(p, &t->if_list, list)
 > -		if (strncmp(p->odev->name, ifname, IFNAMSIZ) == 0) {
 > +		if (strncmp(p->odevname, ifname, IFNAMSIZ) == 0) {
 >  			pkt_dev = p;
 >  			break;
 >  		}
 > @@ -3632,6 +3633,7 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
 >  	if (!pkt_dev)
 >  		return -ENOMEM;
 >  
 > +	strcpy(pkt_dev->odevname, ifname);
 >  	pkt_dev->flows = vmalloc(MAX_CFLOWS * sizeof(struct flow_state));
 >  	if (pkt_dev->flows == NULL) {
 >  		kfree(pkt_dev);

^ permalink raw reply

* netfilter: xt_limit: fix invalid return code in limit_mt_check()
From: Patrick McHardy @ 2009-11-23 12:43 UTC (permalink / raw)
  To: David S. Miller; +Cc: Netfilter Development Mailinglist, Linux Netdev List

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

This patch fixes an invalid return value in the limit match.
Please apply or pull from:

git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-2.6.git master

Thanks!

[-- Attachment #2: 01.diff --]
[-- Type: text/x-patch, Size: 805 bytes --]

commit 8fa539bd911e8a7faa7cd77b5192229c9666d9b8
Author: Patrick McHardy <kaber@trash.net>
Date:   Mon Nov 23 13:37:23 2009 +0100

    netfilter: xt_limit: fix invalid return code in limit_mt_check()
    
    Commit acc738fe (netfilter: xtables: avoid pointer to self) introduced
    an invalid return value in limit_mt_check().
    
    Signed-off-by: Patrick McHardy <kaber@trash.net>

diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index 2e8089e..2773be6 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -112,7 +112,7 @@ static bool limit_mt_check(const struct xt_mtchk_param *par)
 
 	priv = kmalloc(sizeof(*priv), GFP_KERNEL);
 	if (priv == NULL)
-		return -ENOMEM;
+		return false;
 
 	/* For SMP, we only want to use one set of state. */
 	r->master = priv;

^ permalink raw reply related

* Strange CPU load when flushing route cache (kernel 2.6.31.6)
From: robert @ 2009-11-23 15:07 UTC (permalink / raw)
  To: Jesper Dangaard Brouer
  Cc: Eric Dumazet, Linux Kernel Network Hackers, Robert Olsson
In-Reply-To: <1258970332.29747.262.camel@jdb-workstation>


Jesper Dangaard Brouer writes:

 > I have observed a strange route cache behaviour when I upgraded some
 > of my production Linux routers (1Gbit/s tg3) to kernel 2.6.31.6 (from
 > kernel 2.6.25.7).
 > 
 > Every time the route cache is flushed I get a CPU spike (in softirq)
 > with a tail.  I have attached some graphs that illustrate the issue
 > (hope vger.kernel.org will allow these attachments...)


 Nice plots. Yes had the same problem long time. Packets were dropped on
 even moderately loaded machines and the network managers were complaining.

 Also the are some router benchmarks (RFC??) that estimates the forwarding 
 performance to the level when the first packet drop occurs. One can of course 
 discuss such test but it's there...

 IMO is best to have he GC "inlined" with the creation of new flows and avoid 
 periodic tasks in this aspect. 

 Also I tried with something I called "active" garbage collection. The idea 
 was to get hints from TCP-FIN etc when to remove stale entries to take a 
 more pro-active approach. I think this was mentioned in the TRASH-paper. 

 If you only do routing you might try to disable the route cache.

 Cheers
					--ro

^ permalink raw reply


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