Netdev List
 help / color / mirror / Atom feed
* [PATCH 0/5] cnic: Bug fixes.
From: Michael Chan @ 2009-08-15  1:49 UTC (permalink / raw)
  To: davem, James.Bottomley, michaelc; +Cc: netdev, linux-scsi


This patchset fixes a panic on ia64 and some locking issues.
Please review.  Thanks.


^ permalink raw reply

* [PATCH 1/5] cnic: Fix symbol_put_addr() panic on ia64.
From: Michael Chan @ 2009-08-15  1:49 UTC (permalink / raw)
  To: davem, James.Bottomley, michaelc; +Cc: netdev, linux-scsi
In-Reply-To: <1250300987-18407-1-git-send-email-mchan@broadcom.com>

When the cnic driver tries to grab a symbol from bnx2 when bnx2 is
running init code, symbol_get() will succeed but symbol_put_addr()
will hit BUG() a moment later.  module_text_address() fails because
bnx2 is still in init code.

This is fixed by using symbol_put() instead which does the exact
opposite of symbol_get().

Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/cnic.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 4869d77..ecde186 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -2543,7 +2543,7 @@ static struct cnic_dev *init_bnx2_cnic(struct net_device *dev)
 	probe = symbol_get(bnx2_cnic_probe);
 	if (probe) {
 		ethdev = (*probe)(dev);
-		symbol_put_addr(probe);
+		symbol_put(bnx2_cnic_probe);
 	}
 	if (!ethdev)
 		return NULL;
-- 
1.5.6.GIT



^ permalink raw reply related

* [PATCH 2/5] cnic: Refine registration with bnx2.
From: Michael Chan @ 2009-08-15  1:49 UTC (permalink / raw)
  To: davem, James.Bottomley, michaelc; +Cc: netdev, linux-scsi
In-Reply-To: <1250300987-18407-1-git-send-email-mchan@broadcom.com>

Register and unregister with bnx2 during NETDEV_UP and NETDEV_DOWN
events.  This simplifies the sequence of events and allows locking
fixes in the next patch.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/cnic.c |   49 ++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 36 insertions(+), 13 deletions(-)

diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index ecde186..2db81f0 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -2393,21 +2393,45 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
 	return 0;
 }
 
-static int cnic_start_hw(struct cnic_dev *dev)
+static int cnic_register_netdev(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
 	struct cnic_eth_dev *ethdev = cp->ethdev;
 	int err;
 
-	if (test_bit(CNIC_F_CNIC_UP, &dev->flags))
-		return -EALREADY;
+	if (!ethdev)
+		return -ENODEV;
+
+	if (ethdev->drv_state & CNIC_DRV_STATE_REGD)
+		return 0;
 
 	err = ethdev->drv_register_cnic(dev->netdev, cp->cnic_ops, dev);
-	if (err) {
+	if (err)
 		printk(KERN_ERR PFX "%s: register_cnic failed\n",
 		       dev->netdev->name);
-		goto err2;
-	}
+
+	return err;
+}
+
+static void cnic_unregister_netdev(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_eth_dev *ethdev = cp->ethdev;
+
+	if (!ethdev)
+		return;
+
+	ethdev->drv_unregister_cnic(dev->netdev);
+}
+
+static int cnic_start_hw(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_eth_dev *ethdev = cp->ethdev;
+	int err;
+
+	if (test_bit(CNIC_F_CNIC_UP, &dev->flags))
+		return -EALREADY;
 
 	dev->regview = ethdev->io_base;
 	cp->chip_id = ethdev->chip_id;
@@ -2438,18 +2462,13 @@ static int cnic_start_hw(struct cnic_dev *dev)
 	return 0;
 
 err1:
-	ethdev->drv_unregister_cnic(dev->netdev);
 	cp->free_resc(dev);
 	pci_dev_put(dev->pcidev);
-err2:
 	return err;
 }
 
 static void cnic_stop_bnx2_hw(struct cnic_dev *dev)
 {
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-
 	cnic_disable_bnx2_int_sync(dev);
 
 	cnic_reg_wr_ind(dev, BNX2_CP_SCRATCH + 0x20, 0);
@@ -2461,8 +2480,6 @@ static void cnic_stop_bnx2_hw(struct cnic_dev *dev)
 	cnic_setup_5709_context(dev, 0);
 	cnic_free_irq(dev);
 
-	ethdev->drv_unregister_cnic(dev->netdev);
-
 	cnic_free_resc(dev);
 }
 
@@ -2646,6 +2663,10 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
 		else if (event == NETDEV_UNREGISTER)
 			cnic_ulp_exit(dev);
 		else if (event == NETDEV_UP) {
+			if (cnic_register_netdev(dev) != 0) {
+				cnic_put(dev);
+				goto done;
+			}
 			mutex_lock(&cnic_lock);
 			if (!cnic_start_hw(dev))
 				cnic_ulp_start(dev);
@@ -2672,6 +2693,7 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
 			cnic_ulp_stop(dev);
 			cnic_stop_hw(dev);
 			mutex_unlock(&cnic_lock);
+			cnic_unregister_netdev(dev);
 		} else if (event == NETDEV_UNREGISTER) {
 			write_lock(&cnic_dev_lock);
 			list_del_init(&dev->list);
@@ -2703,6 +2725,7 @@ static void cnic_release(void)
 		}
 
 		cnic_ulp_exit(dev);
+		cnic_unregister_netdev(dev);
 		list_del_init(&dev->list);
 		cnic_free_dev(dev);
 	}
-- 
1.5.6.GIT



^ permalink raw reply related

* [PATCH 3/5] bnx2: Use mutex on slow path cnic calls.
From: Michael Chan @ 2009-08-15  1:49 UTC (permalink / raw)
  To: davem, James.Bottomley, michaelc; +Cc: netdev, linux-scsi
In-Reply-To: <1250300987-18407-1-git-send-email-mchan@broadcom.com>

The slow path calls to the cnic driver are sleepable calls so we
cannot use rcu_read_lock().  Use mutex for these slow path calls
instead.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/bnx2.c |   17 +++++++++++------
 drivers/net/bnx2.h |    1 +
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index b70cc99..06b9011 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -399,9 +399,11 @@ static int bnx2_unregister_cnic(struct net_device *dev)
 	struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
 	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
 
+	mutex_lock(&bp->cnic_lock);
 	cp->drv_state = 0;
 	bnapi->cnic_present = 0;
 	rcu_assign_pointer(bp->cnic_ops, NULL);
+	mutex_unlock(&bp->cnic_lock);
 	synchronize_rcu();
 	return 0;
 }
@@ -429,13 +431,13 @@ bnx2_cnic_stop(struct bnx2 *bp)
 	struct cnic_ops *c_ops;
 	struct cnic_ctl_info info;
 
-	rcu_read_lock();
-	c_ops = rcu_dereference(bp->cnic_ops);
+	mutex_lock(&bp->cnic_lock);
+	c_ops = bp->cnic_ops;
 	if (c_ops) {
 		info.cmd = CNIC_CTL_STOP_CMD;
 		c_ops->cnic_ctl(bp->cnic_data, &info);
 	}
-	rcu_read_unlock();
+	mutex_unlock(&bp->cnic_lock);
 }
 
 static void
@@ -444,8 +446,8 @@ bnx2_cnic_start(struct bnx2 *bp)
 	struct cnic_ops *c_ops;
 	struct cnic_ctl_info info;
 
-	rcu_read_lock();
-	c_ops = rcu_dereference(bp->cnic_ops);
+	mutex_lock(&bp->cnic_lock);
+	c_ops = bp->cnic_ops;
 	if (c_ops) {
 		if (!(bp->flags & BNX2_FLAG_USING_MSIX)) {
 			struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
@@ -455,7 +457,7 @@ bnx2_cnic_start(struct bnx2 *bp)
 		info.cmd = CNIC_CTL_START_CMD;
 		c_ops->cnic_ctl(bp->cnic_data, &info);
 	}
-	rcu_read_unlock();
+	mutex_unlock(&bp->cnic_lock);
 }
 
 #else
@@ -7663,6 +7665,9 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
 
 	spin_lock_init(&bp->phy_lock);
 	spin_lock_init(&bp->indirect_lock);
+#ifdef BCM_CNIC
+	mutex_init(&bp->cnic_lock);
+#endif
 	INIT_WORK(&bp->reset_task, bnx2_reset_task);
 
 	dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0);
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index f1edfaa..a4f12fd 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -6902,6 +6902,7 @@ struct bnx2 {
 	u32			idle_chk_status_idx;
 
 #ifdef BCM_CNIC
+	struct mutex		cnic_lock;
 	struct cnic_eth_dev	cnic_eth_dev;
 #endif
 
-- 
1.5.6.GIT



^ permalink raw reply related

* [PATCH 4/5] cnic: Fix locking in start/stop calls.
From: Michael Chan @ 2009-08-15  1:49 UTC (permalink / raw)
  To: davem, James.Bottomley, michaelc; +Cc: netdev, linux-scsi
In-Reply-To: <1250300987-18407-1-git-send-email-mchan@broadcom.com>

The slow path ulp_start and ulp_stop calls to the bnx2i driver
are sleepable calls and therefore should not be protected using
rcu_read_lock.  Fix it by using mutex and setting a bit during
these calls.  cnic_unregister_device() will now wait for the bit
to clear before completing the call.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/cnic.c |   44 ++++++++++++++++++++++++++++----------------
 drivers/net/cnic.h |    1 +
 2 files changed, 29 insertions(+), 16 deletions(-)

diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 2db81f0..4ff618a 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -466,6 +466,7 @@ EXPORT_SYMBOL(cnic_register_driver);
 static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type)
 {
 	struct cnic_local *cp = dev->cnic_priv;
+	int i = 0;
 
 	if (ulp_type >= MAX_CNIC_ULP_TYPE) {
 		printk(KERN_ERR PFX "cnic_unregister_device: Bad type %d\n",
@@ -486,6 +487,15 @@ static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type)
 
 	synchronize_rcu();
 
+	while (test_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[ulp_type]) &&
+	       i < 20) {
+		msleep(100);
+		i++;
+	}
+	if (test_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[ulp_type]))
+		printk(KERN_WARNING PFX "%s: Failed waiting for ULP up call"
+					" to complete.\n", dev->netdev->name);
+
 	return 0;
 }
 EXPORT_SYMBOL(cnic_unregister_driver);
@@ -1076,18 +1086,23 @@ static void cnic_ulp_stop(struct cnic_dev *dev)
 	if (cp->cnic_uinfo)
 		cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
 
-	rcu_read_lock();
 	for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) {
 		struct cnic_ulp_ops *ulp_ops;
 
-		ulp_ops = rcu_dereference(cp->ulp_ops[if_type]);
-		if (!ulp_ops)
+		mutex_lock(&cnic_lock);
+		ulp_ops = cp->ulp_ops[if_type];
+		if (!ulp_ops) {
+			mutex_unlock(&cnic_lock);
 			continue;
+		}
+		set_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
+		mutex_unlock(&cnic_lock);
 
 		if (test_and_clear_bit(ULP_F_START, &cp->ulp_flags[if_type]))
 			ulp_ops->cnic_stop(cp->ulp_handle[if_type]);
+
+		clear_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
 	}
-	rcu_read_unlock();
 }
 
 static void cnic_ulp_start(struct cnic_dev *dev)
@@ -1095,18 +1110,23 @@ static void cnic_ulp_start(struct cnic_dev *dev)
 	struct cnic_local *cp = dev->cnic_priv;
 	int if_type;
 
-	rcu_read_lock();
 	for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) {
 		struct cnic_ulp_ops *ulp_ops;
 
-		ulp_ops = rcu_dereference(cp->ulp_ops[if_type]);
-		if (!ulp_ops || !ulp_ops->cnic_start)
+		mutex_lock(&cnic_lock);
+		ulp_ops = cp->ulp_ops[if_type];
+		if (!ulp_ops || !ulp_ops->cnic_start) {
+			mutex_unlock(&cnic_lock);
 			continue;
+		}
+		set_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
+		mutex_unlock(&cnic_lock);
 
 		if (!test_and_set_bit(ULP_F_START, &cp->ulp_flags[if_type]))
 			ulp_ops->cnic_start(cp->ulp_handle[if_type]);
+
+		clear_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
 	}
-	rcu_read_unlock();
 }
 
 static int cnic_ctl(void *data, struct cnic_ctl_info *info)
@@ -1116,22 +1136,18 @@ static int cnic_ctl(void *data, struct cnic_ctl_info *info)
 	switch (info->cmd) {
 	case CNIC_CTL_STOP_CMD:
 		cnic_hold(dev);
-		mutex_lock(&cnic_lock);
 
 		cnic_ulp_stop(dev);
 		cnic_stop_hw(dev);
 
-		mutex_unlock(&cnic_lock);
 		cnic_put(dev);
 		break;
 	case CNIC_CTL_START_CMD:
 		cnic_hold(dev);
-		mutex_lock(&cnic_lock);
 
 		if (!cnic_start_hw(dev))
 			cnic_ulp_start(dev);
 
-		mutex_unlock(&cnic_lock);
 		cnic_put(dev);
 		break;
 	default:
@@ -2667,10 +2683,8 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
 				cnic_put(dev);
 				goto done;
 			}
-			mutex_lock(&cnic_lock);
 			if (!cnic_start_hw(dev))
 				cnic_ulp_start(dev);
-			mutex_unlock(&cnic_lock);
 		}
 
 		rcu_read_lock();
@@ -2689,10 +2703,8 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
 		rcu_read_unlock();
 
 		if (event == NETDEV_GOING_DOWN) {
-			mutex_lock(&cnic_lock);
 			cnic_ulp_stop(dev);
 			cnic_stop_hw(dev);
-			mutex_unlock(&cnic_lock);
 			cnic_unregister_netdev(dev);
 		} else if (event == NETDEV_UNREGISTER) {
 			write_lock(&cnic_dev_lock);
diff --git a/drivers/net/cnic.h b/drivers/net/cnic.h
index 5192d4a..a94b302 100644
--- a/drivers/net/cnic.h
+++ b/drivers/net/cnic.h
@@ -176,6 +176,7 @@ struct cnic_local {
 	unsigned long ulp_flags[MAX_CNIC_ULP_TYPE];
 #define ULP_F_INIT	0
 #define ULP_F_START	1
+#define ULP_F_CALL_PENDING	2
 	struct cnic_ulp_ops *ulp_ops[MAX_CNIC_ULP_TYPE];
 
 	/* protected by ulp_lock */
-- 
1.5.6.GIT



^ permalink raw reply related

* Re: Pegasus: Bug / Correction (?)
From: Davide Rizzo @ 2009-08-15  5:57 UTC (permalink / raw)
  To: petkan-nPnTwAqkgEqakBO8gow8eQ
  Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
	petkan-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <e315af7ef85836e3c6dcdf6e1a6f5583.squirrel-nPnTwAqkgEqakBO8gow8eQ@public.gmane.org>

No, I have only ADM8515 to test with.
This is not a general solution to be merged in streamline code, but a
bug report with a (bad) solution that I tested only on ADM8515.
The bug was difficult to report because normal users don't care about
MAC address correctness. I did.
I'm sorry but I don't know enough of USB kernel internals to provide
an elegant, general solution.

2009/8/14  <petkan-nPnTwAqkgEqakBO8gow8eQ@public.gmane.org>:
> Not good - the correction will disable set_address for older controllers.
> Have you tried this code on a different device?
>
>
>                      Petko
>
>
>
>> Bug Correction
>> ADM8515 fails to read central 2 bytes of MAC address
>> This patch solves the problem, but I didn't understand it.
>>
>> Signed-off-by: Davide Rizzo <elpa.rizzo-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> ---
>> diff -urNp linux-2.6.30.4/drivers/net/usb/pegasus.c
>> linux-2.6.30.4.elpa/drivers/net/usb/pegasus.c
>> --- linux-2.6.30.4/drivers/net/usb/pegasus.c  2009-08-13 07:14:57.000000000
>> +0200
>> +++ linux-2.6.30.4.elpa/drivers/net/usb/pegasus.c     2009-08-13
>> 08:39:01.000000000 +0200
>> @@ -425,7 +425,6 @@ fail:
>>  static inline void enable_eprom_write(pegasus_t * pegasus)
>>  {
>>       __u8 tmp;
>> -     int ret;
>>
>>       get_registers(pegasus, EthCtrl2, 1, &tmp);
>>       set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE);
>> @@ -434,7 +433,6 @@ static inline void enable_eprom_write(pe
>>  static inline void disable_eprom_write(pegasus_t * pegasus)
>>  {
>>       __u8 tmp;
>> -     int ret;
>>
>>       get_registers(pegasus, EthCtrl2, 1, &tmp);
>>       set_register(pegasus, EpromCtrl, 0);
>> @@ -486,9 +525,9 @@ static void set_ethernet_addr(pegasus_t
>>  {
>>       __u8 node_id[6];
>>
>> -     if (pegasus->features & PEGASUS_II) {
>> +/*if (pegasus->features & PEGASUS_II) {
>>               get_registers(pegasus, 0x10, sizeof(node_id), node_id);
>> -     } else {
>> +     } else*/ {
>>               get_node_id(pegasus, node_id);
>>               set_registers(pegasus, EthID, sizeof (node_id), node_id);
>>       }
>>
>
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH] Pegasus: Add MAC programmability
From: Davide Rizzo @ 2009-08-15  6:18 UTC (permalink / raw)
  To: petkan-nPnTwAqkgEqakBO8gow8eQ
  Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
	petkan-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <e75fcab5ff0b69446555a633bdb1907d.squirrel-nPnTwAqkgEqakBO8gow8eQ@public.gmane.org>

You're correct.
Because I produce embedded boards with ADM8515 controller, my purpose
was to program eeprom in full, without need to pre-program it before
assemblying the boards.
Writing MAC in eeprom is already protectected by a #ifdef
PEGASUS_WRITE_EEPROM (that should be normally disabled, I agree).
What about protecting the writing of other data with a nested #ifdef
PEGASUS_WRITE_EEPROM_HEADER ? Do you have eeprom datas for other
Pegasus chipsets to include in the source ? Or is there any dedicated
API I don't know about to make this job ?

2009/8/14  <petkan-nPnTwAqkgEqakBO8gow8eQ@public.gmane.org>:
> Why do you have to write def_eeprom[] to the eeprom along with the new MAC
> address?  This may work for 8515 based controllers, but will most likely
> break everything else that antedates it.
>
> The set address function should be much smaller/simpler and not writing to
> the eeprom in general.
>
>
>                  Petko
>
>
>> Added capability to set mac address and to program it into EEPROM
>>
>> Signed-off-by: Davide Rizzo <elpa.rizzo-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> ---
>> diff -urNp linux-2.6.30.4/drivers/net/usb/pegasus.c
>> linux-2.6.30.4.elpa/drivers/net/usb/pegasus.c
>> --- linux-2.6.30.4/drivers/net/usb/pegasus.c  2009-08-13 07:14:57.000000000
>> +0200
>> +++ linux-2.6.30.4.elpa/drivers/net/usb/pegasus.c     2009-08-13
>> 08:39:01.000000000 +0200
>> @@ -469,8 +467,49 @@ fail:
>>               dev_warn(&pegasus->intf->dev, "%s failed\n", __func__);
>>       return -ETIMEDOUT;
>>  }
>> +
>> +/* Got from adm 8515 starter kit */
>> +static const __u16 def_eeprom[] = {
>> +                       0x8515, 0x0170, 0x0082, 0x0409, 0x0000,
>> +     0x07a6, 0x8515, 0x100e, 0x202a, 0x380a, 0x0000, 0x0000, 0x0000,
>> +     0x030e, 0x0041, 0x0044, 0x004d, 0x0074, 0x0065, 0x006b, 0x0000,
>> +     0x001e, 0x0055, 0x0053, 0x0042, 0x0020, 0x0031, 0x0030, 0x002f,
>> +     0x032a, 0x0055, 0x0053, 0x0042, 0x0020, 0x0054, 0x006f, 0x0020,
>> +     0x004c, 0x0041, 0x004e, 0x0020, 0x0043, 0x006f, 0x006e, 0x0076,
>> +     0x0065, 0x0072, 0x0074, 0x0065, 0x0072, 0x0000, 0x0000, 0x0000,
>> +     0x030a, 0x0030, 0x0030, 0x0030, 0x0031, 0x0000, 0x0000, 0x0000,
>> +};
>>  #endif                               /* PEGASUS_WRITE_EEPROM */
>>
>> +static int pegasus_set_mac_address(struct net_device *netdev, void *p)
>> +{
>> +     struct sockaddr *addr = p;
>> +     pegasus_t *pegasus = (pegasus_t *) netdev_priv(netdev);
>> +     int i;
>> +
>> +     if (netif_running(netdev))
>> +             return -EBUSY;
>> +     memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
>> +     dbg("%s: Setting MAC address to ", netdev->name);
>> +     for (i = 0; i < 5; i++)
>> +             dbg("%02X:", netdev->dev_addr[i]);
>> +     dbg("%02X\n", netdev->dev_addr[i]);
>> +     /* Set the IDR registers. */
>> +     set_registers(pegasus, EthID, 6, netdev->dev_addr);
>> +#ifdef PEGASUS_WRITE_EEPROM
>> +     write_eprom_word(pegasus, 0,
>> +             (netdev->dev_addr[1] << 8) + netdev->dev_addr[0]);
>> +     write_eprom_word(pegasus, 1,
>> +             (netdev->dev_addr[3] << 8) + netdev->dev_addr[2]);
>> +     write_eprom_word(pegasus, 2,
>> +             (netdev->dev_addr[5] << 8) + netdev->dev_addr[4]);
>> +     for (i = 0; i < ARRAY_SIZE(def_eeprom); i++)
>> +             write_eprom_word(pegasus, i + 3, def_eeprom[i]);
>> +
>> +#endif                         /* PEGASUS_WRITE_EEPROM */
>> +     return 0;
>> +}
>> +
>>  static inline void get_node_id(pegasus_t * pegasus, __u8 * id)
>>  {
>>       int i;
>> @@ -1492,6 +1531,7 @@ static const struct net_device_ops pegas
>>       .ndo_start_xmit =               pegasus_start_xmit,
>>       .ndo_set_multicast_list =       pegasus_set_multicast,
>>       .ndo_get_stats =                pegasus_netdev_stats,
>> +     .ndo_set_mac_address =  pegasus_set_mac_address,
>>       .ndo_tx_timeout =               pegasus_tx_timeout,
>>       .ndo_change_mtu =               eth_change_mtu,
>>       .ndo_set_mac_address =          eth_mac_addr,
>>
>
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 01/13] TProxy: kick out TIME_WAIT sockets in case a new connection comes in with the same tuple
From: Balazs Scheidler @ 2009-08-15  8:00 UTC (permalink / raw)
  To: netfilter-devel, netdev

Without tproxy redirections an incoming SYN kicks out conflicting
TIME_WAIT sockets, in order to handle clients that reuse ports
within the TIME_WAIT period.

The same mechanism didn't work in case TProxy is involved in finding
the proper socket, as the time_wait processing code looked up the
listening socket assuming that the listener addr/port matches those
of the established connection.

This is not the case with TProxy as the listener addr/port is possibly
changed with the tproxy rule.

Signed-off-by: Balazs Scheidler <bazsi@balabit.hu>
---
 include/net/netfilter/nf_tproxy_core.h |    6 ++++-
 net/netfilter/nf_tproxy_core.c         |   29 +++++++++++++++++++-------
 net/netfilter/xt_TPROXY.c              |   35 ++++++++++++++++++++++++++++---
 net/netfilter/xt_socket.c              |    2 +-
 4 files changed, 58 insertions(+), 14 deletions(-)

diff --git a/include/net/netfilter/nf_tproxy_core.h b/include/net/netfilter/nf_tproxy_core.h
index 208b46f..b3a8942 100644
--- a/include/net/netfilter/nf_tproxy_core.h
+++ b/include/net/netfilter/nf_tproxy_core.h
@@ -8,12 +8,16 @@
 #include <net/inet_sock.h>
 #include <net/tcp.h>
 
+#define NFT_LOOKUP_ANY         0
+#define NFT_LOOKUP_LISTENER    1
+#define NFT_LOOKUP_ESTABLISHED 2
+
 /* look up and get a reference to a matching socket */
 extern struct sock *
 nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
 		      const __be32 saddr, const __be32 daddr,
 		      const __be16 sport, const __be16 dport,
-		      const struct net_device *in, bool listening);
+		      const struct net_device *in, int lookup_type);
 
 static inline void
 nf_tproxy_put_sock(struct sock *sk)
diff --git a/net/netfilter/nf_tproxy_core.c b/net/netfilter/nf_tproxy_core.c
index 5490fc3..8589e5e 100644
--- a/net/netfilter/nf_tproxy_core.c
+++ b/net/netfilter/nf_tproxy_core.c
@@ -22,21 +22,34 @@ struct sock *
 nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
 		      const __be32 saddr, const __be32 daddr,
 		      const __be16 sport, const __be16 dport,
-		      const struct net_device *in, bool listening_only)
+		      const struct net_device *in, int lookup_type)
 {
 	struct sock *sk;
 
 	/* look up socket */
 	switch (protocol) {
 	case IPPROTO_TCP:
-		if (listening_only)
-			sk = __inet_lookup_listener(net, &tcp_hashinfo,
-						    daddr, ntohs(dport),
-						    in->ifindex);
-		else
+		switch (lookup_type) {
+		case NFT_LOOKUP_ANY:
 			sk = __inet_lookup(net, &tcp_hashinfo,
 					   saddr, sport, daddr, dport,
 					   in->ifindex);
+			break;
+		case NFT_LOOKUP_LISTENER:
+			sk = inet_lookup_listener(net, &tcp_hashinfo,
+						    daddr, dport,
+						    in->ifindex);
+			break;
+		case NFT_LOOKUP_ESTABLISHED:
+			sk = inet_lookup_established(net, &tcp_hashinfo,
+						    saddr, sport, daddr, dport,
+						    in->ifindex);
+			break;
+		default:
+			WARN_ON(1);
+			sk = NULL;
+			break;
+		}
 		break;
 	case IPPROTO_UDP:
 		sk = udp4_lib_lookup(net, saddr, sport, daddr, dport,
@@ -47,8 +60,8 @@ nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
 		sk = NULL;
 	}
 
-	pr_debug("tproxy socket lookup: proto %u %08x:%u -> %08x:%u, listener only: %d, sock %p\n",
-		 protocol, ntohl(saddr), ntohs(sport), ntohl(daddr), ntohs(dport), listening_only, sk);
+	pr_debug("tproxy socket lookup: proto %u %08x:%u -> %08x:%u, lookup type: %d, sock %p\n",
+		 protocol, ntohl(saddr), ntohs(sport), ntohl(daddr), ntohs(dport), lookup_type, sk);
 
 	return sk;
 }
diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
index 1340c2f..5592b72 100644
--- a/net/netfilter/xt_TPROXY.c
+++ b/net/netfilter/xt_TPROXY.c
@@ -29,7 +29,7 @@ tproxy_tg(struct sk_buff *skb, const struct xt_target_param *par)
 {
 	const struct iphdr *iph = ip_hdr(skb);
 	const struct xt_tproxy_target_info *tgi = par->targinfo;
-	struct udphdr _hdr, *hp;
+	struct tcphdr _hdr, *hp;
 	struct sock *sk;
 
 	hp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_hdr), &_hdr);
@@ -37,10 +37,37 @@ tproxy_tg(struct sk_buff *skb, const struct xt_target_param *par)
 		return NF_DROP;
 
 	sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), iph->protocol,
-				   iph->saddr, tgi->laddr ? tgi->laddr : iph->daddr,
-				   hp->source, tgi->lport ? tgi->lport : hp->dest,
-				   par->in, true);
-
+				   iph->saddr, iph->daddr,
+				   hp->source, hp->dest,
+				   par->in, NFT_LOOKUP_ESTABLISHED);
+
+	/* udp has no TCP_TIME_WAIT state, so we never enter here */
+	if (sk && sk->sk_state == TCP_TIME_WAIT &&
+	    hp->syn && !hp->rst && !hp->ack && !hp->fin) {
+		struct sock *sk2;
+
+		/* Hm.. we got a SYN to a TIME_WAIT socket, let's see if
+		 * there's a listener on the redirected port
+		 */
+		sk2 = nf_tproxy_get_sock_v4(dev_net(skb->dev), iph->protocol,
+					   iph->saddr, tgi->laddr ? tgi->laddr : iph->daddr,
+					   hp->source, tgi->lport ? tgi->lport : hp->dest,
+					   par->in, NFT_LOOKUP_LISTENER);
+		if (sk2) {
+
+			/* yeah, there's one, let's kill the TIME_WAIT
+			 * socket and redirect to the listener
+			 */
+			inet_twsk_deschedule(inet_twsk(sk), &tcp_death_row);
+			inet_twsk_put(inet_twsk(sk));
+			sk = sk2;
+		}
+	} else if (!sk) {
+		sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), iph->protocol,
+					   iph->saddr, tgi->laddr ? tgi->laddr : iph->daddr,
+					   hp->source, tgi->lport ? tgi->lport : hp->dest,
+					   par->in, NFT_LOOKUP_LISTENER);
+	}
 	/* NOTE: assign_sock consumes our sk reference */
 	if (sk && nf_tproxy_assign_sock(skb, sk)) {
 		/* This should be in a separate target, but we don't do multiple
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c
index ebf00ad..12a7140 100644
--- a/net/netfilter/xt_socket.c
+++ b/net/netfilter/xt_socket.c
@@ -142,7 +142,7 @@ socket_match(const struct sk_buff *skb, const struct xt_match_param *par,
 #endif
 
 	sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), protocol,
-				   saddr, daddr, sport, dport, par->in, false);
+				   saddr, daddr, sport, dport, par->in, NFT_LOOKUP_ANY);
 	if (sk != NULL) {
 		bool wildcard;
 		bool transparent = true;
-- 
1.6.0.4


^ permalink raw reply related

* Re: [PATCH v3 3/6] vbus: add a "vbus-proxy" bus model for vbus_driver objects
From: Ingo Molnar @ 2009-08-15 10:32 UTC (permalink / raw)
  To: Gregory Haskins, kvm, Avi Kivity; +Cc: alacrityvm-devel, linux-kernel, netdev
In-Reply-To: <20090814154308.26116.46980.stgit@dev.haskins.net>


* Gregory Haskins <ghaskins@novell.com> wrote:

> This will generally be used for hypervisors to publish any host-side
> virtual devices up to a guest.  The guest will have the opportunity
> to consume any devices present on the vbus-proxy as if they were
> platform devices, similar to existing buses like PCI.
> 
> Signed-off-by: Gregory Haskins <ghaskins@novell.com>
> ---
> 
>  MAINTAINERS                 |    6 ++
>  arch/x86/Kconfig            |    2 +
>  drivers/Makefile            |    1 
>  drivers/vbus/Kconfig        |   14 ++++
>  drivers/vbus/Makefile       |    3 +
>  drivers/vbus/bus-proxy.c    |  152 +++++++++++++++++++++++++++++++++++++++++++
>  include/linux/vbus_driver.h |   73 +++++++++++++++++++++
>  7 files changed, 251 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/vbus/Kconfig
>  create mode 100644 drivers/vbus/Makefile
>  create mode 100644 drivers/vbus/bus-proxy.c
>  create mode 100644 include/linux/vbus_driver.h

Is there a consensus on this with the KVM folks? (i've added the KVM 
list to the Cc:)

	Ingo

^ permalink raw reply

* [PATCH 02/13] TProxy: add lookup type checks for UDP in nf_tproxy_get_sock_v4()
From: Balazs Scheidler @ 2009-08-15 12:01 UTC (permalink / raw)
  To: netfilter-devel, netdev

Also, inline this function as the lookup_type is always a literal
and inlineing removes branches performed at runtime.

Signed-off-by: Balazs Scheidler <bazsi@balabit.hu>
---
 include/net/netfilter/nf_tproxy_core.h |  116 +++++++++++++++++++++++++++++++-
 net/netfilter/nf_tproxy_core.c         |   48 -------------
 2 files changed, 114 insertions(+), 50 deletions(-)

diff --git a/include/net/netfilter/nf_tproxy_core.h b/include/net/netfilter/nf_tproxy_core.h
index b3a8942..4064f35 100644
--- a/include/net/netfilter/nf_tproxy_core.h
+++ b/include/net/netfilter/nf_tproxy_core.h
@@ -13,11 +13,123 @@
 #define NFT_LOOKUP_ESTABLISHED 2
 
 /* look up and get a reference to a matching socket */
-extern struct sock *
+
+
+/* This function is used by the 'TPROXY' target and the 'socket'
+ * match. The following lookups are supported:
+ *
+ * Explicit TProxy target rule
+ * ===========================
+ *
+ * This is used when the user wants to intercept a connection matching
+ * an explicit iptables rule. In this case the sockets are assumed
+ * matching in preference order:
+ *
+ *   - match: if there's a fully established connection matching the
+ *     _packet_ tuple, it is returned, assuming the redirection
+ *     already took place and we process a packet belonging to an
+ *     established connection
+ *
+ *   - match: if there's a listening socket matching the redirection
+ *     (e.g. on-port & on-ip of the connection), it is returned,
+ *     regardless if it was bound to 0.0.0.0 or an explicit
+ *     address. The reasoning is that if there's an explicit rule, it
+ *     does not really matter if the listener is bound to an interface
+ *     or to 0. The user already stated that he wants redirection
+ *     (since he added the rule).
+ *
+ * "socket" match based redirection (no specific rule)
+ * ===================================================
+ * 
+ * There are connections with dynamic endpoints (e.g. FTP data
+ * connection) that the user is unable to add explicit rules
+ * for. These are taken care of by a generic "socket" rule. It is
+ * assumed that the proxy application is trusted to open such
+ * connections without explicit iptables rule (except of course the
+ * generic 'socket' rule). In this case the following sockets are
+ * matched in preference order:
+ *
+ *   - match: if there's a fully established connection matching the
+ *     _packet_ tuple
+ * 
+ *   - match: if there's a non-zero bound listener (possibly with a
+ *     non-local address) We don't accept zero-bound listeners, since
+ *     then local services could intercept traffic going through the
+ *     box.
+ *
+ * Please note that there's an overlap between what a TPROXY target
+ * and a socket match will match. Normally if you have both rules the
+ * "socket" match will be the first one, effectively all packets
+ * belonging to established connections going through that one.
+ */
+static inline struct sock *
 nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
 		      const __be32 saddr, const __be32 daddr,
 		      const __be16 sport, const __be16 dport,
-		      const struct net_device *in, int lookup_type);
+		      const struct net_device *in, int lookup_type)
+{
+	struct sock *sk;
+
+	/* look up socket */
+	switch (protocol) {
+	case IPPROTO_TCP:
+		switch (lookup_type) {
+		case NFT_LOOKUP_ANY:
+			sk = __inet_lookup(net, &tcp_hashinfo,
+					   saddr, sport, daddr, dport,
+					   in->ifindex);
+			break;
+		case NFT_LOOKUP_LISTENER:
+			sk = inet_lookup_listener(net, &tcp_hashinfo,
+						    daddr, dport,
+						    in->ifindex);
+
+                        /* NOTE: we return listeners even if bound to
+                         * 0.0.0.0, those are filtered out in
+                         * xt_socket, since xt_TPROXY needs 0 bound
+                         * listeners too */
+
+			break;
+		case NFT_LOOKUP_ESTABLISHED:
+			sk = inet_lookup_established(net, &tcp_hashinfo,
+						    saddr, sport, daddr, dport,
+						    in->ifindex);
+			break;
+		default:
+			WARN_ON(1);
+			sk = NULL;
+			break;
+		}
+		break;
+	case IPPROTO_UDP:
+		sk = udp4_lib_lookup(net, saddr, sport, daddr, dport,
+				     in->ifindex);
+                if (sk && lookup_type != NFT_LOOKUP_ANY) {
+                        int connected = (sk->sk_state == TCP_ESTABLISHED);
+                        int wildcard = (inet_sk(sk)->rcv_saddr == 0);
+                        
+                        /* NOTE: we return listeners even if bound to
+                         * 0.0.0.0, those are filtered out in
+                         * xt_socket, since xt_TPROXY needs 0 bound
+                         * listeners too */
+                        if ((lookup_type == NFT_LOOKUP_ESTABLISHED && (!connected || wildcard)) ||
+			    (lookup_type == NFT_LOOKUP_LISTENER && connected)) {
+				sock_put(sk);
+				sk = NULL;
+                        }
+		}
+		break;
+	default:
+		WARN_ON(1);
+		sk = NULL;
+	}
+
+	pr_debug("tproxy socket lookup: proto %u %08x:%u -> %08x:%u, lookup type: %d, sock %p\n",
+		 protocol, ntohl(saddr), ntohs(sport), ntohl(daddr), ntohs(dport), lookup_type, sk);
+
+	return sk;
+}
+
 
 static inline void
 nf_tproxy_put_sock(struct sock *sk)
diff --git a/net/netfilter/nf_tproxy_core.c b/net/netfilter/nf_tproxy_core.c
index 8589e5e..db65563 100644
--- a/net/netfilter/nf_tproxy_core.c
+++ b/net/netfilter/nf_tproxy_core.c
@@ -18,54 +18,6 @@
 #include <net/udp.h>
 #include <net/netfilter/nf_tproxy_core.h>
 
-struct sock *
-nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
-		      const __be32 saddr, const __be32 daddr,
-		      const __be16 sport, const __be16 dport,
-		      const struct net_device *in, int lookup_type)
-{
-	struct sock *sk;
-
-	/* look up socket */
-	switch (protocol) {
-	case IPPROTO_TCP:
-		switch (lookup_type) {
-		case NFT_LOOKUP_ANY:
-			sk = __inet_lookup(net, &tcp_hashinfo,
-					   saddr, sport, daddr, dport,
-					   in->ifindex);
-			break;
-		case NFT_LOOKUP_LISTENER:
-			sk = inet_lookup_listener(net, &tcp_hashinfo,
-						    daddr, dport,
-						    in->ifindex);
-			break;
-		case NFT_LOOKUP_ESTABLISHED:
-			sk = inet_lookup_established(net, &tcp_hashinfo,
-						    saddr, sport, daddr, dport,
-						    in->ifindex);
-			break;
-		default:
-			WARN_ON(1);
-			sk = NULL;
-			break;
-		}
-		break;
-	case IPPROTO_UDP:
-		sk = udp4_lib_lookup(net, saddr, sport, daddr, dport,
-				     in->ifindex);
-		break;
-	default:
-		WARN_ON(1);
-		sk = NULL;
-	}
-
-	pr_debug("tproxy socket lookup: proto %u %08x:%u -> %08x:%u, lookup type: %d, sock %p\n",
-		 protocol, ntohl(saddr), ntohs(sport), ntohl(daddr), ntohs(dport), lookup_type, sk);
-
-	return sk;
-}
-EXPORT_SYMBOL_GPL(nf_tproxy_get_sock_v4);
 
 static void
 nf_tproxy_destructor(struct sk_buff *skb)
-- 
1.6.0.4


^ permalink raw reply related

* Re: [PATCH] WAN: bit and/or confusion
From: Roel Kluin @ 2009-08-15 13:41 UTC (permalink / raw)
  To: Andrew Morton; +Cc: David Miller, romieu, netdev
In-Reply-To: <20090814165852.7338461e.akpm@linux-foundation.org>

Fix the tests that check whether Frame* bits are not set

Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
---
> we need
> 
> 	else if (!(skb->data[pkt_len] & FrameCrc))

> vfr is "valid frame".  0 is invalid.
> 
> rab is "receive message aborted".  The data sheet doesn't actually say
> if the bit is active-high or active-low (grr).  

Maybe someone could test this?

diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index 8face5d..b686050 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -663,9 +663,9 @@ static inline void dscc4_rx_skb(struct dscc4_dev_priv *dpriv,
 	} else {
 		if (skb->data[pkt_len] & FrameRdo)
 			dev->stats.rx_fifo_errors++;
-		else if (!(skb->data[pkt_len] | ~FrameCrc))
+		else if (!(skb->data[pkt_len] & FrameCrc))
 			dev->stats.rx_crc_errors++;
-		else if (!(skb->data[pkt_len] | ~(FrameVfr | FrameRab)))
+		else if (!(skb->data[pkt_len] & (FrameVfr | FrameRab)))
 			dev->stats.rx_length_errors++;
 		else
 			dev->stats.rx_errors++;


^ permalink raw reply related

* Re: [PATCH] WAN: bit and/or confusion
From: Francois Romieu @ 2009-08-15 14:13 UTC (permalink / raw)
  To: Roel Kluin; +Cc: Andrew Morton, David Miller, netdev
In-Reply-To: <4A86BAF3.5060609@gmail.com>

Roel Kluin <roel.kluin@gmail.com> :
[...]
> Maybe someone could test this?

I may undust a pair of card and a split box but do not hold your breath.

-- 
Ueimor

^ permalink raw reply

* [PATCH] lib/vsprintf.c: Add "%pI6c" - print pointer as compressed ipv6 address
From: Joe Perches @ 2009-08-15 15:24 UTC (permalink / raw)
  To: David Miller; +Cc: jens, chuck.lever, brian.haley, netdev
In-Reply-To: <20090814.131218.139318801.davem@davemloft.net>

On Fri, 2009-08-14 at 13:12 -0700, David Miller wrote:
> I'd say that kernel log messages are OK to tinker with, whereas procfs
> and sysfs file contents are not.

Here's a patch to start that tinkering with log messages

Add functions to format and print a compressed ipv6 address
Does longest 0 match "::" compression
Added an #include <net/addrconf.h>
Changed currently unused "%pi4" to use leading 0s (001.002.003.004)
Changed code to not modify "spec"

'I' [46] for IPv4/IPv6 addresses printed in the usual way
    IPv4 uses dot-separated decimal without leading 0's (1.2.3.4)
    IPv6 uses colon separated network-order 16 bit hex with leading 0's
'i' [46] for 'raw' IPv4/IPv6 addresses
    IPv6 omits the colons (01020304...0f)
    IPv4 uses dot-separated decimal with leading 0's (010.123.045.006)
'I6c' for IPv6 addresses printed as specified by
    http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt

Signed-off-by: Joe Perches <joe@perches.com>
---
 lib/vsprintf.c |  205 +++++++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 158 insertions(+), 47 deletions(-)

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 756ccaf..9b79536 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -25,6 +25,7 @@
 #include <linux/kallsyms.h>
 #include <linux/uaccess.h>
 #include <linux/ioport.h>
+#include <net/addrconf.h>
 
 #include <asm/page.h>		/* for PAGE_SIZE */
 #include <asm/div64.h>
@@ -630,60 +631,162 @@ static char *resource_string(char *buf, char *end, struct resource *res,
 }
 
 static char *mac_address_string(char *buf, char *end, u8 *addr,
-				struct printf_spec spec)
+				struct printf_spec spec, const char *fmt)
 {
-	char mac_addr[6 * 3]; /* (6 * 2 hex digits), 5 colons and trailing zero */
+	char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")];
 	char *p = mac_addr;
 	int i;
 
 	for (i = 0; i < 6; i++) {
 		p = pack_hex_byte(p, addr[i]);
-		if (!(spec.flags & SPECIAL) && i != 5)
+		if (fmt[0] == 'M' && i != 5)
 			*p++ = ':';
 	}
 	*p = '\0';
-	spec.flags &= ~SPECIAL;
 
 	return string(buf, end, mac_addr, spec);
 }
 
-static char *ip6_addr_string(char *buf, char *end, u8 *addr,
-				struct printf_spec spec)
+static char *ip4_string(char *p, const u8 *addr, bool leading_zeros)
 {
-	char ip6_addr[8 * 5]; /* (8 * 4 hex digits), 7 colons and trailing zero */
-	char *p = ip6_addr;
 	int i;
 
+	for (i = 0; i < 4; i++) {
+		char temp[3];	/* hold each IP quad in reverse order */
+		int digits = put_dec_trunc(temp, addr[i]) - temp;
+		if (leading_zeros) {
+			if (digits < 3)
+				*p++ = '0';
+			if (digits < 2)
+				*p++ = '0';
+		}
+		/* reverse the digits in the quad */
+		while (digits--)
+			*p++ = temp[digits];
+		if (i < 3)
+			*p++ = '.';
+	}
+
+	*p = '\0';
+	return p;
+}
+
+static char *ip6_compressed_string(char *p, const struct in6_addr *addr)
+{
+	int i;
+	int j;
+	int range;
+	unsigned char zerolength[8];
+	int longest = 0;
+	int colonpos = -1;
+	u16 word;
+	u8 hi;
+	u8 lo;
+	bool printhi;
+	bool needcolon = false;
+	bool useIPv4 = ipv6_addr_v4mapped(addr) || ipv6_addr_is_isatap(addr);
+
+	memset(zerolength, 0, sizeof(zerolength));
+
+	if (useIPv4)
+		range = 6;
+	else
+		range = 8;
+
+	/* find position of longest 0 run */
+	for (i = 0; i < range; i++) {
+		for (j = i; j < range; j++) {
+			if (addr->s6_addr16[j] != 0)
+				break;
+			zerolength[i]++;
+		}
+	}
+	for (i = 0; i < range; i++) {
+		if (zerolength[i] > longest) {
+			longest = zerolength[i];
+			colonpos = i;
+		}
+	}
+	if (colonpos != -1 && zerolength[colonpos] < 2)
+		colonpos = -1;
+
+	for (i = 0; i < range; i++) {
+		if (i == colonpos) {
+			if (needcolon || i == 0)
+				*p++ = ':';
+			*p++ = ':';
+			needcolon = false;
+			while (i + 1 < range && addr->s6_addr16[i + 1] == 0) {
+				i++;	/* skip successive 0s */
+			}
+			continue;
+		}
+		if (needcolon) {
+			*p++ = ':';
+			needcolon = false;
+		}
+		/* hex u16 without leading 0s */
+		word = ntohs(addr->s6_addr16[i]);
+		hi = word >> 8;
+		lo = word & 0xff;
+		printhi = false;
+		if (hi) {
+			if (hi > 0x0f)
+				p = pack_hex_byte(p, hi);
+			else
+				*p++ = hex_asc_lo(hi);
+			printhi = true;
+		}
+		if (printhi || lo > 0x0f)
+			p = pack_hex_byte(p, lo);
+		else
+			*p++ = hex_asc_lo(lo);
+		needcolon = true;
+	}
+
+	if (useIPv4) {
+		if (needcolon)
+			*p++ = ':';
+		p = ip4_string(p, &addr->s6_addr[12], false);
+	}
+
+	*p = '\0';
+	return p;
+}
+
+static char *ip6_string(char *p, const struct in6_addr *addr, const char *fmt)
+{
+	int i;
 	for (i = 0; i < 8; i++) {
-		p = pack_hex_byte(p, addr[2 * i]);
-		p = pack_hex_byte(p, addr[2 * i + 1]);
-		if (!(spec.flags & SPECIAL) && i != 7)
+		p = pack_hex_byte(p, addr->s6_addr[2 * i]);
+		p = pack_hex_byte(p, addr->s6_addr[2 * i + 1]);
+		if (fmt[0] == 'I' && i != 7)
 			*p++ = ':';
 	}
+
 	*p = '\0';
-	spec.flags &= ~SPECIAL;
+	return p;
+}
+
+static char *ip6_addr_string(char *buf, char *end, const u8 *addr,
+			     struct printf_spec spec, const char *fmt)
+{
+	char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
+
+	if (fmt[0] == 'I' && fmt[2] == 'c')
+		ip6_compressed_string(ip6_addr, (const struct in6_addr *)addr);
+	else
+		ip6_string(ip6_addr, (const struct in6_addr *)addr, fmt);
 
 	return string(buf, end, ip6_addr, spec);
 }
 
-static char *ip4_addr_string(char *buf, char *end, u8 *addr,
-				struct printf_spec spec)
+static char *ip4_addr_string(char *buf, char *end, const u8 *addr,
+			     struct printf_spec spec, const char *fmt)
 {
-	char ip4_addr[4 * 4]; /* (4 * 3 decimal digits), 3 dots and trailing zero */
-	char temp[3];	/* hold each IP quad in reverse order */
-	char *p = ip4_addr;
-	int i, digits;
+	char ip4_addr[sizeof("255.255.255.255")];
 
-	for (i = 0; i < 4; i++) {
-		digits = put_dec_trunc(temp, addr[i]) - temp;
-		/* reverse the digits in the quad */
-		while (digits--)
-			*p++ = temp[digits];
-		if (i != 3)
-			*p++ = '.';
-	}
-	*p = '\0';
-	spec.flags &= ~SPECIAL;
+	ip4_string(ip4_addr, addr, fmt[0] == 'i');
 
 	return string(buf, end, ip4_addr, spec);
 }
@@ -702,11 +805,15 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr,
  *       addresses (not the name nor the flags)
  * - 'M' For a 6-byte MAC address, it prints the address in the
  *       usual colon-separated hex notation
- * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way (dot-separated
- *       decimal for v4 and colon separated network-order 16 bit hex for v6)
- * - 'i' [46] for 'raw' IPv4/IPv6 addresses, IPv6 omits the colons, IPv4 is
- *       currently the same
- *
+ * - 'm' For a 6-byte MAC address, it prints the hex address without colons
+ * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way
+ *       IPv4 uses dot-separated decimal without leading 0's (1.2.3.4)
+ *       IPv6 uses colon separated network-order 16 bit hex with leading 0's
+ * - 'i' [46] for 'raw' IPv4/IPv6 addresses
+ *       IPv6 omits the colons (01020304...0f)
+ *       IPv4 uses dot-separated decimal with leading 0's (010.123.045.006)
+ * - 'I6c' for IPv6 addresses printed as specified by
+ *       http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt
  * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
  * function pointers are really function descriptors, which contain a
  * pointer to the real address.
@@ -726,20 +833,24 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 		return symbol_string(buf, end, ptr, spec, *fmt);
 	case 'R':
 		return resource_string(buf, end, ptr, spec);
-	case 'm':
-		spec.flags |= SPECIAL;
-		/* Fallthrough */
-	case 'M':
-		return mac_address_string(buf, end, ptr, spec);
-	case 'i':
-		spec.flags |= SPECIAL;
-		/* Fallthrough */
-	case 'I':
-		if (fmt[1] == '6')
-			return ip6_addr_string(buf, end, ptr, spec);
-		if (fmt[1] == '4')
-			return ip4_addr_string(buf, end, ptr, spec);
-		spec.flags &= ~SPECIAL;
+	case 'M':			/* Colon separated: 00:01:02:03:04:05 */
+	case 'm':			/* Contiguous: 000102030405 */
+		return mac_address_string(buf, end, ptr, spec, fmt);
+	case 'I':			/* Formatted IP supported
+					 * 4:	1.2.3.4
+					 * 6:	0001:0203:...:0708
+					 * 6c:	1::708 or 1::1.2.3.4
+					 */
+	case 'i':			/* Contiguous:
+					 * 4:	001.002.003.004
+					 * 6:   000102...0f
+					 */
+		switch (fmt[1]) {
+		case '6':
+			return ip6_addr_string(buf, end, ptr, spec, fmt);
+		case '4':
+			return ip4_addr_string(buf, end, ptr, spec, fmt);
+		}
 		break;
 	}
 	spec.flags |= SMALL;
-- 
1.6.3.1.10.g659a0.dirty




^ permalink raw reply related

* question about drivers/atm/firestream.c
From: Julia Lawall @ 2009-08-15 17:08 UTC (permalink / raw)
  To: chas, linux-atm-general, netdev

In the file drivers/atm/firestream.c in the function fs_open, there is the 
following code:

       if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC)
                set_bit(ATM_VF_ADDR, &atm_vcc->flags);

Should ATM_VPI_UNSPEC and ATM_VCI_UNSPEC be exchanged?  They have the same 
value, but the code looks a bit odd this way nonetheless.

thanks,
julia

^ permalink raw reply

* Re: [PATCH] WAN: bit and/or confusion
From: Krzysztof Halasa @ 2009-08-15 18:46 UTC (permalink / raw)
  To: Roel Kluin; +Cc: Andrew Morton, David Miller, romieu, netdev
In-Reply-To: <4A86BAF3.5060609@gmail.com>

Roel Kluin <roel.kluin@gmail.com> writes:

> +++ b/drivers/net/wan/dscc4.c
> @@ -663,9 +663,9 @@ static inline void dscc4_rx_skb(struct dscc4_dev_priv *dpriv,
>  	} else {
>  		if (skb->data[pkt_len] & FrameRdo)
>  			dev->stats.rx_fifo_errors++;
> -		else if (!(skb->data[pkt_len] | ~FrameCrc))
> +		else if (!(skb->data[pkt_len] & FrameCrc))
>  			dev->stats.rx_crc_errors++;

This looks like a correct fix.

> -		else if (!(skb->data[pkt_len] | ~(FrameVfr | FrameRab)))
> +		else if (!(skb->data[pkt_len] & (FrameVfr | FrameRab)))
>  			dev->stats.rx_length_errors++;

This test requires both FrameVfr and FrameRab to be true (zero). Perhaps
it should be:

> +		else if ((skb->data[pkt_len] & (FrameVfr | FrameRab)) != FrameVfr | FrameRab)

>  		else
>  			dev->stats.rx_errors++;

rx_errors is incremented only on remaining errors. I think most drivers
increment rx_errors on all RX errors, and simultaneously rx_*_errors
when needed.


Perhaps something like the following should be better?

		u8 status = ~skb->data[pkt_len];

		if (status == 0)
			looks_good...;
		else {
			if (status & FrameRab)
				...
			if (status & FrameVfr)
				...
			etc.
			rx_errors++;
		}

I don't have the hardware and can't test (donations of such hw welcome).
-- 
Krzysztof Halasa

^ permalink raw reply

* Re: [PATCH v3 3/6] vbus: add a "vbus-proxy" bus model for vbus_driver objects
From: Anthony Liguori @ 2009-08-15 19:15 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Gregory Haskins, kvm, Avi Kivity, alacrityvm-devel, linux-kernel,
	netdev, Michael S. Tsirkin
In-Reply-To: <20090815103243.GA26749@elte.hu>

Ingo Molnar wrote:
> * Gregory Haskins <ghaskins@novell.com> wrote:
>
>   
>> This will generally be used for hypervisors to publish any host-side
>> virtual devices up to a guest.  The guest will have the opportunity
>> to consume any devices present on the vbus-proxy as if they were
>> platform devices, similar to existing buses like PCI.
>>
>> Signed-off-by: Gregory Haskins <ghaskins@novell.com>
>> ---
>>
>>  MAINTAINERS                 |    6 ++
>>  arch/x86/Kconfig            |    2 +
>>  drivers/Makefile            |    1 
>>  drivers/vbus/Kconfig        |   14 ++++
>>  drivers/vbus/Makefile       |    3 +
>>  drivers/vbus/bus-proxy.c    |  152 +++++++++++++++++++++++++++++++++++++++++++
>>  include/linux/vbus_driver.h |   73 +++++++++++++++++++++
>>  7 files changed, 251 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/vbus/Kconfig
>>  create mode 100644 drivers/vbus/Makefile
>>  create mode 100644 drivers/vbus/bus-proxy.c
>>  create mode 100644 include/linux/vbus_driver.h
>>     
>
> Is there a consensus on this with the KVM folks? (i've added the KVM 
> list to the Cc:)
>   

I'll let Avi comment about it from a KVM perspective but from a QEMU 
perspective, I don't think we want to support two paravirtual IO 
frameworks.  I'd like to see them converge.  Since there's an install 
base of guests today with virtio drivers, there really ought to be a 
compelling reason to change the virtio ABI in a non-backwards compatible 
way.  This means convergence really ought to be adding features to virtio.

On paper, I don't think vbus really has any features over virtio.  vbus 
does things in different ways (paravirtual bus vs. pci for discovery) 
but I think we're happy with how virtio does things today.

I think the reason vbus gets better performance for networking today is 
that vbus' backends are in the kernel while virtio's backends are 
currently in userspace.  Since Michael has a functioning in-kernel 
backend for virtio-net now, I suspect we're weeks (maybe days) away from 
performance results.  My expectation is that vhost + virtio-net will be 
as good as venet + vbus.  If that's the case, then I don't see any 
reason to adopt vbus unless Greg things there are other compelling 
features over virtio.

Regards,

Anthony Liguori

> 	Ingo
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" 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] Update Neighbor Cache when IPv6 RA is received on a router
From: David Ward @ 2009-08-16  0:19 UTC (permalink / raw)
  To: netdev; +Cc: David Ward

When processing a received IPv6 Router Advertisement, the kernel
creates or updates an IPv6 Neighbor Cache entry for the sender --
but presently this does not occur if IPv6 forwarding is enabled
(net.ipv6.conf.*.forwarding = 1), or if IPv6 Router Advertisements
are not accepted (net.ipv6.conf.*.accept_ra = 0), because in these
cases processing of the Router Advertisement has already halted.

This patch allows the Neighbor Cache to be updated in these cases,
while still avoiding any modification to routes or link parameters.

This continues to satisfy RFC 4861, since any entry created in the
Neighbor Cache as the result of a received Router Advertisement is
still placed in the STALE state.

Signed-off-by: David Ward <david.ward@ll.mit.edu>
---
 net/ipv6/ndisc.c |   14 ++++++++------
 1 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 1ba42bd..44b4c87 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1151,10 +1151,6 @@ static void ndisc_router_discovery(struct sk_buff *skb)
 			   skb->dev->name);
 		return;
 	}
-	if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) {
-		in6_dev_put(in6_dev);
-		return;
-	}
 
 	if (!ndisc_parse_options(opt, optlen, &ndopts)) {
 		in6_dev_put(in6_dev);
@@ -1163,6 +1159,10 @@ static void ndisc_router_discovery(struct sk_buff *skb)
 		return;
 	}
 
+	/* skip route and link configuration on routers */
+	if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra)
+		goto skip_linkparms;
+
 #ifdef CONFIG_IPV6_NDISC_NODETYPE
 	/* skip link-specific parameters from interior routers */
 	if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT)
@@ -1283,9 +1283,7 @@ skip_defrtr:
 		}
 	}
 
-#ifdef CONFIG_IPV6_NDISC_NODETYPE
 skip_linkparms:
-#endif
 
 	/*
 	 *	Process options.
@@ -1312,6 +1310,10 @@ skip_linkparms:
 			     NEIGH_UPDATE_F_ISROUTER);
 	}
 
+	/* skip route and link configuration on routers */
+	if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra)
+		goto out;
+
 #ifdef CONFIG_IPV6_ROUTE_INFO
 	if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) {
 		struct nd_opt_hdr *p;
-- 
1.6.0.4


^ permalink raw reply related

* Re: [PATCH 0/5] cnic: Bug fixes.
From: David Miller @ 2009-08-16  1:51 UTC (permalink / raw)
  To: mchan; +Cc: James.Bottomley, michaelc, netdev, linux-scsi
In-Reply-To: <1250300987-18407-1-git-send-email-mchan@broadcom.com>

From: "Michael Chan" <mchan@broadcom.com>
Date: Fri, 14 Aug 2009 18:49:42 -0700

> This patchset fixes a panic on ia64 and some locking issues.
> Please review.  Thanks.

Looks fine to me, applied to net-2.6

^ permalink raw reply

* Re: [net-2.6 PATCH 1/2] e1000e: WoL does not work on 82577/82578 with manageability enabled
From: David Miller @ 2009-08-16  1:53 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: netdev, gospo, bruce.w.allan
In-Reply-To: <20090815003524.2335.3107.stgit@localhost.localdomain>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Fri, 14 Aug 2009 17:35:33 -0700

> From: Bruce Allan <bruce.w.allan@intel.com>
> 
> With manageability (Intel AMT) enabled via BIOS, PHY wakeup does not get
> configured on newer parts which use PHY wakeup vs. MAC wakeup which causes
> WoL to not work.  The driver should configure PHY wakeup whether or not
> manageability is enabled.
> 
> Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Applied.

^ permalink raw reply

* Re: [net-2.6 PATCH 2/2] e1000e: fix use of pci_enable_pcie_error_reporting
From: David Miller @ 2009-08-16  1:53 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: netdev, gospo, dfeng
In-Reply-To: <20090815003551.2335.26888.stgit@localhost.localdomain>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Fri, 14 Aug 2009 17:35:52 -0700

> From: Xiaotian Feng <dfeng@redhat.com>
> 
> commit 111b9dc5 introduces pcie aer support for e1000e, but it is not
> reasonable to disable it in e1000_remove but enable it in e1000_resume.
> This patch enables aer support in e1000_probe.
> 
> Signed-off-by: Xiaotian Feng <dfeng@redhat.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Applied.

^ permalink raw reply

* Re: [PATCH] Update Neighbor Cache when IPv6 RA is received on a router
From: Mark Smith @ 2009-08-16  2:30 UTC (permalink / raw)
  To: David Ward; +Cc: netdev
In-Reply-To: <1250381994-21329-1-git-send-email-david.ward@ll.mit.edu>

Hi David,

On Sat, 15 Aug 2009 20:19:54 -0400
David Ward <david.ward@ll.mit.edu> wrote:

> When processing a received IPv6 Router Advertisement, the kernel
> creates or updates an IPv6 Neighbor Cache entry for the sender --
> but presently this does not occur if IPv6 forwarding is enabled
> (net.ipv6.conf.*.forwarding = 1), or if IPv6 Router Advertisements
> are not accepted (net.ipv6.conf.*.accept_ra = 0), because in these
> cases processing of the Router Advertisement has already halted.
> 
> This patch allows the Neighbor Cache to be updated in these cases,
> while still avoiding any modification to routes or link parameters.
> 

I'm a bit confused what benefit this has. Is the intent to avoid a
Neighbor Solicitation being triggered when a recent RA has already
provided the router's link local address, therefore reducing by a small
mount ND traffic?

> This continues to satisfy RFC 4861, since any entry created in the
> Neighbor Cache as the result of a received Router Advertisement is
> still placed in the STALE state.
> 
> Signed-off-by: David Ward <david.ward@ll.mit.edu>
> ---
>  net/ipv6/ndisc.c |   14 ++++++++------
>  1 files changed, 8 insertions(+), 6 deletions(-)
> 
> diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
> index 1ba42bd..44b4c87 100644
> --- a/net/ipv6/ndisc.c
> +++ b/net/ipv6/ndisc.c
> @@ -1151,10 +1151,6 @@ static void ndisc_router_discovery(struct sk_buff *skb)
>  			   skb->dev->name);
>  		return;
>  	}
> -	if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) {
> -		in6_dev_put(in6_dev);
> -		return;
> -	}
>  
>  	if (!ndisc_parse_options(opt, optlen, &ndopts)) {
>  		in6_dev_put(in6_dev);
> @@ -1163,6 +1159,10 @@ static void ndisc_router_discovery(struct sk_buff *skb)
>  		return;
>  	}
>  
> +	/* skip route and link configuration on routers */
> +	if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra)
> +		goto skip_linkparms;
> +
>  #ifdef CONFIG_IPV6_NDISC_NODETYPE
>  	/* skip link-specific parameters from interior routers */
>  	if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT)
> @@ -1283,9 +1283,7 @@ skip_defrtr:
>  		}
>  	}
>  
> -#ifdef CONFIG_IPV6_NDISC_NODETYPE
>  skip_linkparms:
> -#endif
>  
>  	/*
>  	 *	Process options.
> @@ -1312,6 +1310,10 @@ skip_linkparms:
>  			     NEIGH_UPDATE_F_ISROUTER);
>  	}
>  
> +	/* skip route and link configuration on routers */
> +	if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra)
> +		goto out;
> +
>  #ifdef CONFIG_IPV6_ROUTE_INFO
>  	if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) {
>  		struct nd_opt_hdr *p;
> -- 
> 1.6.0.4
> 
> --
> 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

* Very strange issues with ethernet wake on lan
From: Maxim Levitsky @ 2009-08-16  3:42 UTC (permalink / raw)
  To: netdev@vger.kernel.org
  Cc: linux-pm@lists.linux-foundation.org, Rafael J. Wysocki

Hi,

I have recently put back the davicom dm9009 ethernet card into my
computer.

Some long time ago, I have written its suspend/resume routines.
Now I see that few things have changed, like I need to enable wake in
sysfs or better patch the code to do so, some nice helpers like
pci_prepare_to_sleep have arrived, etc.


I narrowed the strange issue down to following situation:

I reload dmfe.ko (and networkmanager is disabled)
I don't ifup the device, thus pretty much no hardware initialization
takes place (but this appears not to matter anyway)

I then suspend the system, and WOL doesn't work (I have patched the
driver to enable WOL automaticly)

I then, suspend again. WOL works, and continues to work as long as I
don't reload the driver. If I do, same situation repeats.

Also, after a boot, WOL works, so a reload cycle triggers that issue.

And most importantly, if I don't do a

pci_set_power_state(pci_dev, pci_choose_state (pci_dev, state));

in .suspend, then WOL always works.

and I have even tried to set state manually to PCI_D3hot or PCI_D3cold, 

I also tried to use pci_save_state


I also have 2 copies of this card, and both have this issue.
I also tried 2 pci slots.

Kernel is vanilla 2.6.31-rc5


Any ideas?

Best regards,
	Maxim Levitsky


^ permalink raw reply

* [RFC PATCH] lib/vsprintf.c: Add struct sockaddr * "%pN<foo>" output
From: Joe Perches @ 2009-08-16  4:10 UTC (permalink / raw)
  To: chuck.lever; +Cc: jens, brian.haley, David Miller, netdev
In-Reply-To: <1250349894.4620.5.camel@Joe-Laptop.home>

Hi Chuck.

Here's a tentative patch that adds that facility you wanted in
this thread.
http://kerneltrap.org/mailarchive/linux-netdev/2008/11/25/4231684

This patch is on top of this patch:
http://marc.info/?l=linux-netdev&m=125034992003220&w=2

I'm not sure it's great or even useful, but just for discussion.

Use style:
* - 'N' For network socket (sockaddr) pointers
*       if sa_family is IPv4, output is %pI4; if IPv6, output is %pI6c
*       May be used with any combination of additional specifiers below
*       'p' decimal socket port number for IPv[46]: ":12345"
*       'f' decimal flowinfo for IPv6: "/123456789"
*       's' decimal scope_id number for IPv6: "%1234567890"
*       so %pNp will print if IPv4 "1.2.3.4:1234", if IPv6: "1::c0a8:a:1234"

I think using ":" as the separator for the port number, while common,
and already frequently used in kernel source (see bullet 2 in):
http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt
"Section 6: Notes on Combining IPv6 Addresses with Port Numbers".
is not good for readability.

Perhaps this style should be changed to the "[ipv6]:port" described
in the draft above.

cheers, Joe

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 9b79536..b3cbc38 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -791,6 +791,90 @@ static char *ip4_addr_string(char *buf, char *end, const u8 *addr,
 	return string(buf, end, ip4_addr, spec);
 }
 
+static char *u32_dec_val(char *p, u32 val)
+{
+	char temp[9];
+	int digits;
+	u32 hi_val = val / 100000;
+	char *pos;
+	pos = put_dec_trunc(temp, val%100000);
+	if (hi_val)
+		pos = put_dec_trunc(pos, hi_val);
+	digits = pos - temp;
+	/* reverse the digits in temp */
+	while (digits--)
+		*p++ = temp[digits];
+	return p;
+}
+
+static char *socket_addr_string(char *buf, char *end,
+				const struct sockaddr *sa,
+				struct printf_spec spec, const char *fmt)
+{
+	char addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255") +
+		  sizeof(":12345") +
+		  sizeof("%1234567890") +
+		  sizeof("/123456789")];
+	char *p;
+	struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
+	struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
+
+	switch (sa->sa_family) {
+	case AF_INET:
+		p = ip4_string(addr, (const u8 *)&sa4->sin_addr.s_addr, false);
+		break;
+	case AF_INET6:
+		p = ip6_compressed_string(addr, &sa6->sin6_addr);
+		break;
+	default: {
+		struct printf_spec num_spec = {
+			.base = 16,
+			.precision = -1,
+			.field_width = 2 * sizeof(void *),
+			.flags = SPECIAL | SMALL | ZEROPAD,
+		};
+
+		p = strcpy(addr, "Bad socket address: ")
+			+ sizeof("Bad socket address: ");
+		p = number(p, addr + sizeof(addr), (unsigned long)sa, num_spec);
+		break;
+	}
+	}
+
+	while (isalpha(*++fmt)) {
+		switch (*fmt) {
+		case 'p':
+			*p++ = ':';
+			switch (sa->sa_family) {
+			case AF_INET:
+				p = u32_dec_val(p,ntohs(sa4->sin_port));
+				break;
+			case AF_INET6:
+				p = u32_dec_val(p,ntohs(sa6->sin6_port));
+				break;
+			}
+			break;
+		case 's':
+			*p++ = '%';
+			switch (sa->sa_family) {
+			case AF_INET6:
+				p = u32_dec_val(p, sa6->sin6_scope_id);
+			}
+			break;
+		case 'f':
+			*p++ = '/';
+			switch (sa->sa_family) {
+			case AF_INET6:
+				p = u32_dec_val(p, ntohl(sa6->sin6_flowinfo &
+							 IPV6_FLOWINFO_MASK));
+			}
+			break;
+		}
+	}
+	*p = '\0';
+	return string(buf, end, addr, spec);
+}
+
 /*
  * Show a '%p' thing.  A kernel extension is that the '%p' is followed
  * by an extra set of alphanumeric characters that are extended format
@@ -814,6 +898,13 @@ static char *ip4_addr_string(char *buf, char *end, const u8 *addr,
  *       IPv4 uses dot-separated decimal with leading 0's (010.123.045.006)
  * - 'I6c' for IPv6 addresses printed as specified by
  *       http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt
+ * - 'N' For network socket (sockaddr) pointers
+ *       if sa_family is IPv4, output is %pI4; if IPv6, output is %pI6c
+ *       May be used with any combination of additional specifiers below
+ *       'p' decimal socket port number for IPv[46]: ":12345"
+ *       'f' decimal flowinfo for IPv6: "/123456789"
+ *       's' decimal scope_id number for IPv6: "%1234567890"
+ *       so %pNp will print if IPv4 "1.2.3.4:1234", if IPv6: "1::c0a8:a:1234"
  * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
  * function pointers are really function descriptors, which contain a
  * pointer to the real address.
@@ -852,7 +943,10 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 			return ip4_addr_string(buf, end, ptr, spec, fmt);
 		}
 		break;
+	case 'N':
+		return socket_addr_string(buf, end, ptr, spec, fmt);
 	}
+
 	spec.flags |= SMALL;
 	if (spec.field_width == -1) {
 		spec.field_width = 2*sizeof(void *);



^ permalink raw reply related

* Re: [PATCH] Update Neighbor Cache when IPv6 RA is received on a router
From: David Ward @ 2009-08-16  5:47 UTC (permalink / raw)
  To: Mark Smith; +Cc: netdev
In-Reply-To: <20090816120027.3d510139.lk-netdev@lk-netdev.nosense.org>

Mark, thank you very much for your response.

On 08/15/2009 10:30 PM, Mark Smith wrote:
> Hi David,
>
> On Sat, 15 Aug 2009 20:19:54 -0400
> David Ward <david.ward@ll.mit.edu> wrote:
>
>> When processing a received IPv6 Router Advertisement, the kernel
>> creates or updates an IPv6 Neighbor Cache entry for the sender --
>> but presently this does not occur if IPv6 forwarding is enabled
>> (net.ipv6.conf.*.forwarding = 1), or if IPv6 Router Advertisements
>> are not accepted (net.ipv6.conf.*.accept_ra = 0), because in these
>> cases processing of the Router Advertisement has already halted.
>>
>> This patch allows the Neighbor Cache to be updated in these cases,
>> while still avoiding any modification to routes or link parameters.
>>
>
> I'm a bit confused what benefit this has.

I apologize for not making that clear. It allows routers to utilize the 
Neighbor Cache to keep track of neighboring routers, which are learned 
about through the periodic Router Advertisements. By doing so, 
applications communicating through upper layers can make use of the 
Neighbor Cache, for example, as a basis for initiating dynamic peering 
between neighboring routers. Non-routers are already able to keep track 
of their neighboring routers in the Neighbor Cache; this simply allows 
routers to do the same.

This cannot be achieved through Neighbor Advertisements, because they 
are usually sent in response to a direct Neighbor Solicitation, while 
Router Advertisements are periodically multicast to the all-nodes group.

> Is the intent to avoid a Neighbor Solicitation being triggered when a
> recent RA has already provided the router's link local address,
> therefore reducing by a small mount ND traffic?

No. This patch does not preclude the need to send a Neighbor 
Solicitation to another router to determine reachability. That would 
violate RFC 4861, which states that a Router Advertisement "MUST NOT be 
treated as a reachability confirmation".

In the dynamic router peering scenario, the Neighbor Cache entry could 
be used to learn that the neighboring router exists and is a potential 
peer -- but reachability must still be determined before a peering 
session could actually be attempted.

>> This continues to satisfy RFC 4861, since any entry created in the
>> Neighbor Cache as the result of a received Router Advertisement is
>> still placed in the STALE state.
>>
>> Signed-off-by: David Ward <david.ward@ll.mit.edu>
>> ---
>>  net/ipv6/ndisc.c |   14 ++++++++------
>>  1 files changed, 8 insertions(+), 6 deletions(-)
>>
>> diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
>> index 1ba42bd..44b4c87 100644
>> --- a/net/ipv6/ndisc.c
>> +++ b/net/ipv6/ndisc.c
>> @@ -1151,10 +1151,6 @@ static void ndisc_router_discovery(struct
>> sk_buff *skb)
>>                 skb->dev->name);
>>          return;
>>      }
>> -    if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) {
>> -        in6_dev_put(in6_dev);
>> -        return;
>> -    }
>>
>>      if (!ndisc_parse_options(opt, optlen, &ndopts)) {
>>          in6_dev_put(in6_dev);
>> @@ -1163,6 +1159,10 @@ static void ndisc_router_discovery(struct
>> sk_buff *skb)
>>          return;
>>      }
>>
>> +    /* skip route and link configuration on routers */
>> +    if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra)
>> +        goto skip_linkparms;
>> +
>>  #ifdef CONFIG_IPV6_NDISC_NODETYPE
>>      /* skip link-specific parameters from interior routers */
>>      if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT)
>> @@ -1283,9 +1283,7 @@ skip_defrtr:
>>          }
>>      }
>>
>> -#ifdef CONFIG_IPV6_NDISC_NODETYPE
>>  skip_linkparms:
>> -#endif
>>
>>      /*
>>       *    Process options.
>> @@ -1312,6 +1310,10 @@ skip_linkparms:
>>                   NEIGH_UPDATE_F_ISROUTER);
>>      }
>>
>> +    /* skip route and link configuration on routers */
>> +    if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra)
>> +        goto out;
>> +
>>  #ifdef CONFIG_IPV6_ROUTE_INFO
>>      if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) {
>>          struct nd_opt_hdr *p;
>> --
>> 1.6.0.4

^ permalink raw reply

* Re: [PATCHv3 2/2] vhost_net: a kernel-level virtio server
From: Michael S. Tsirkin @ 2009-08-16  6:51 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: virtualization, netdev, kvm, linux-kernel, mingo, linux-mm, akpm,
	hpa, gregory.haskins
In-Reply-To: <200908141340.36176.arnd@arndb.de>

On Fri, Aug 14, 2009 at 01:40:36PM +0200, Arnd Bergmann wrote:
> On Thursday 13 August 2009, Michael S. Tsirkin wrote:
> > What it is: vhost net is a character device that can be used to reduce
> > the number of system calls involved in virtio networking.
> > Existing virtio net code is used in the guest without modification.
> 
> AFAICT, you have addressed all my comments, mostly by convincing me
> that you got it right anyway ;-).
> 
> I hope this gets into 2.6.32, good work!
> 
> > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> 
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> 
> One idea though:
> 
> > +	/* Parameter checking */
> > +	if (sock->sk->sk_type != SOCK_RAW) {
> > +		r = -ESOCKTNOSUPPORT;
> > +		goto done;
> > +	}
> > +
> > +	r = sock->ops->getname(sock, (struct sockaddr *)&uaddr.sa,
> > +			       &uaddr_len, 0);
> > +	if (r)
> > +		goto done;
> > +
> > +	if (uaddr.sa.sll_family != AF_PACKET) {
> > +		r = -EPFNOSUPPORT;
> > +		goto done;
> > +	}
> 
> You currently limit the scope of the driver by only allowing raw packet
> sockets to be passed into the network driver. In qemu, we currently support
> some very similar transports:
> 
> * raw packet (not in a release yet)
> * tcp connection
> * UDP multicast
> * tap character device
> * VDE with Unix local sockets
> 
> My primary interest right now is the tap support, but I think it would
> be interesting in general to allow different file descriptor types
> in vhost_net_set_socket. AFAICT, there are two major differences
> that we need to handle for this:
> 
> * most of the transports are sockets, tap uses a character device.
>   This could be dealt with by having both a struct socket * in
>   struct vhost_net *and* a struct file *, or by always keeping the
>   struct file and calling vfs_readv/vfs_writev for the data transport
>   in both cases.

I am concerned that character devices might have weird side effects with
read/write operations and that calling them from kernel thread the way I
do might have security implications. Can't point at anything specific
though at the moment.
I wonder - can we expose the underlying socket used by tap, or will that
create complex lifetime issues?

> * Each transport has a slightly different header, we have
>   - raw ethernet frames (raw, udp multicast, tap)
>   - 32-bit length + raw frames, possibly fragmented (tcp)
>   - 80-bit header + raw frames, possibly fragmented (tap with vnet_hdr)
>   To handle these three cases, we need either different ioctl numbers
>   so that vhost_net can choose the right one, or a flags field in
>   VHOST_NET_SET_SOCKET, like
> 
>   #define VHOST_NET_RAW		1
>   #define VHOST_NET_LEN_HDR	2
>   #define VHOST_NET_VNET_HDR	4
> 
>   struct vhost_net_socket {
> 	unsigned int flags;
> 	int fd;
>   };
>   #define VHOST_NET_SET_SOCKET _IOW(VHOST_VIRTIO, 0x30, struct vhost_net_socket)

It seems we can query the socket to find out the type, or use the
features ioctl.

> If both of those are addressed, we can treat vhost_net as a generic
> way to do network handling in the kernel independent of the qemu
> model (raw, tap, ...) for it. 
> 
> Your qemu patch would have to work differently, so instead of 
> 
> qemu -net nic,vhost=eth0
> 
> you would do the same as today with the raw packet socket extension
> 
> qemu -net nic -net raw,ifname=eth0 
> 
> Qemu could then automatically try to use vhost_net, if it's available
> in the kernel, or just fall back on software vlan otherwise.
> Does that make sense?
> 
> 	Arnd <>

I agree, long term it should be enabled automatically when possible.

-- 
MST

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ 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