Netdev List
 help / color / mirror / Atom feed
* Re: sky2 rx length errors
From: Stephen Hemminger @ 2009-09-20 18:05 UTC (permalink / raw)
  To: Andrew Morton; +Cc: Grozdan, linux-kernel, Stephen Hemminger, netdev
In-Reply-To: <20090919233536.f5fb700c.akpm@linux-foundation.org>

On Sat, 19 Sep 2009 23:35:36 -0700
Andrew Morton <akpm@linux-foundation.org> wrote:

> (added cc's from the MAINTAINERS file)
> 
> On Fri, 18 Sep 2009 15:41:45 +0200 Grozdan <neutrino8@gmail.com> wrote:
> 
> > Hi,
> > 
> > I have a Marvell onboard NIC (88E8053) and I've been noticing for a
> > while now a bit weird behavior with the sky2 driver. This mostly
> > occurs with newer kernels (2.6.30, 2.6.31) and my older distro kernel
> > (2.6.27.21) does not seem to have the same problem. Basically, the
> > sky2 driver will randomly and unpredictably spew rx length error
> > messages and reboot itself. I also noticed in dmesg that this mostly
> > occurs after "martian destination" messages. After this message, sky2
> > starts spewing messages as shown below and then reboots itself. It is
> > not really a big problem for me, but since I'm virtually always logged
> > in in IRC, the client always loses connection, waits for a few minutes
> > to get a response from the server and then relogs me again. I do not
> > think it's a HW problem as the Marvell NIC otherwise works perfectly
> > and I've checked my cable modem too which operates without a problem.
> > Any ideas?
> > 
> > PS: please cc me as I'm not subscribed to the mailing list
> > 
> > sky2 driver version 1.23
> > sky2 0000:05:00.0: PCI INT A -> GSI 36 (level, low) -> IRQ 36
> > sky2 0000:05:00.0: setting latency timer to 64
> > sky2 0000:05:00.0: PCI: Disallowing DAC for device
> > sky2 0000:05:00.0: Yukon-2 EC chip revision 2
> > sky2 0000:05:00.0: irq 53 for MSI/MSI-X
> > sky2 0000:05:00.0: No interrupt generated using MSI, switching to INTx mode.
> > sky2 eth0: addr 00:11:d8:a1:5b:0e
> > sky2 eth0: enabling interface
> > sky2 eth0: Link is up at 100 Mbps, full duplex, flow control rx
> > .....
> > .....
> > martian destination 0.0.0.0 from 172.23.204.1, dev eth0
> > sky2 eth0: rx length error: status 0x4420100 length 598
> > sky2 eth0: rx length error: status 0x5ea0100 length 598

This error status occurs if the length reported by the PHY does not
match the len reported by the DMA engine.  The error status is:
   0x4420100 = length 1090 + broadcast packet...

No idea what is on your network, but perhaps there is some MTU confusion?
Since martian destination seems related, knowing more about that packet
might help.

^ permalink raw reply

* Re: SO_TIMESTAMPING fix and design decisions
From: Peter P Waskiewicz Jr @ 2009-09-20 17:48 UTC (permalink / raw)
  To: Christopher Zimmermann; +Cc: netdev@vger.kernel.org
In-Reply-To: <20090920095242.5cd42f1a@pundit>

On Sun, 2009-09-20 at 00:52 -0700, Christopher Zimmermann wrote:
> On Sat, 19 Sep 2009 15:09:21 -0700
> Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com> wrote:
> 
> > > hardware timestamps only work for the Intel igb driver. I have 
> > > access to two test machines with NICs supported by this driver.
> > 
> > Intel's 82599, supported by ixgbe, also has the same IEEE 1588
> > timestamping support in hardware.  We haven't implemented the support
> > yet in ixgbe, but the hardware is there and does work.  If you were
> > curious of the interface, the datasheet for the hardware is available on
> > our SourceForge site (e1000.sf.net).
> 
> hi! thanks for the reply.
> 
> I already got the documentation for the 82576 cards I have access to. I 
> won't be able to afford another pair.
> 
> What do you think about my idea to expose the relevant registers to 
> userspace? I believe it would not be too difficult for userspace to 
> configure the timestamps this way and would allow way more flexibility. 
> Of course I would #DEFINE the constants used to set the registers.

The patch seems reasonable, but I haven't played with the igb
timestamping very much.  However, what impact will this have on the
existing ptpd userspace daemon?

-PJ


^ permalink raw reply

* Re: [PATCH] atm: dereference of he_dev->rbps_virt in he_init_group()
From: Roel Kluin @ 2009-09-20 17:11 UTC (permalink / raw)
  To: Joe Perches; +Cc: David Miller, chas, linux-atm-general, netdev, akpm
In-Reply-To: <1253384847.2638.4.camel@Joe-Laptop.home>

he_dev->rbps_virt or he_dev->rbpl_virt allocation may fail, s
them. Make sure that he_init_group() cleans up after errors.

Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
---

> It looks as if it'd be clearer to not use variable ret and
> simply return -ENOMEM after the out_destroy_rbps_pool label.

Ok, thanks.

Again build, sparse and checkpatch tested.

diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index 2de6406..29e66d6 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -790,11 +790,15 @@ he_init_group(struct he_dev *he_dev, int group)
 	he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev,
 		CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys);
 	if (he_dev->rbps_base == NULL) {
-		hprintk("failed to alloc rbps\n");
-		return -ENOMEM;
+		hprintk("failed to alloc rbps_base\n");
+		goto out_destroy_rbps_pool;
 	}
 	memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp));
 	he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL);
+	if (he_dev->rbps_virt == NULL) {
+		hprintk("failed to alloc rbps_virt\n");
+		goto out_free_rbps_base;
+	}
 
 	for (i = 0; i < CONFIG_RBPS_SIZE; ++i) {
 		dma_addr_t dma_handle;
@@ -802,7 +806,7 @@ he_init_group(struct he_dev *he_dev, int group)
 
 		cpuaddr = pci_pool_alloc(he_dev->rbps_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
 		if (cpuaddr == NULL)
-			return -ENOMEM;
+			goto out_free_rbps_virt;
 
 		he_dev->rbps_virt[i].virt = cpuaddr;
 		he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF);
@@ -827,17 +831,21 @@ he_init_group(struct he_dev *he_dev, int group)
 			CONFIG_RBPL_BUFSIZE, 8, 0);
 	if (he_dev->rbpl_pool == NULL) {
 		hprintk("unable to create rbpl pool\n");
-		return -ENOMEM;
+		goto out_free_rbps_virt;
 	}
 
 	he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev,
 		CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys);
 	if (he_dev->rbpl_base == NULL) {
-		hprintk("failed to alloc rbpl\n");
-		return -ENOMEM;
+		hprintk("failed to alloc rbpl_base\n");
+		goto out_destroy_rbpl_pool;
 	}
 	memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp));
 	he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL);
+	if (he_dev->rbpl_virt == NULL) {
+		hprintk("failed to alloc rbpl_virt\n");
+		goto out_free_rbpl_base;
+	}
 
 	for (i = 0; i < CONFIG_RBPL_SIZE; ++i) {
 		dma_addr_t dma_handle;
@@ -845,7 +853,7 @@ he_init_group(struct he_dev *he_dev, int group)
 
 		cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
 		if (cpuaddr == NULL)
-			return -ENOMEM;
+			goto out_free_rbpl_virt;
 
 		he_dev->rbpl_virt[i].virt = cpuaddr;
 		he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF);
@@ -870,7 +878,7 @@ he_init_group(struct he_dev *he_dev, int group)
 		CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys);
 	if (he_dev->rbrq_base == NULL) {
 		hprintk("failed to allocate rbrq\n");
-		return -ENOMEM;
+		goto out_free_rbpl_virt;
 	}
 	memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq));
 
@@ -894,7 +902,7 @@ he_init_group(struct he_dev *he_dev, int group)
 		CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys);
 	if (he_dev->tbrq_base == NULL) {
 		hprintk("failed to allocate tbrq\n");
-		return -ENOMEM;
+		goto out_free_rbpq_base;
 	}
 	memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq));
 
@@ -906,6 +914,39 @@ he_init_group(struct he_dev *he_dev, int group)
 	he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16));
 
 	return 0;
+
+out_free_rbpq_base:
+	pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE *
+			sizeof(struct he_rbrq), he_dev->rbrq_base,
+			he_dev->rbrq_phys);
+	i = CONFIG_RBPL_SIZE;
+out_free_rbpl_virt:
+	while (--i)
+		pci_pool_free(he_dev->rbps_pool, he_dev->rbpl_virt[i].virt,
+				he_dev->rbps_base[i].phys);
+	kfree(he_dev->rbpl_virt);
+
+out_free_rbpl_base:
+	pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE *
+			sizeof(struct he_rbp), he_dev->rbpl_base,
+			he_dev->rbpl_phys);
+out_destroy_rbpl_pool:
+	pci_pool_destroy(he_dev->rbpl_pool);
+
+	i = CONFIG_RBPL_SIZE;
+out_free_rbps_virt:
+	while (--i)
+		pci_pool_free(he_dev->rbpl_pool, he_dev->rbps_virt[i].virt,
+				he_dev->rbpl_base[i].phys);
+	kfree(he_dev->rbps_virt);
+
+out_free_rbps_base:
+	pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE *
+			sizeof(struct he_rbp), he_dev->rbps_base,
+			he_dev->rbps_phys);
+out_destroy_rbps_pool:
+	pci_pool_destroy(he_dev->rbps_pool);
+	return -ENOMEM;
 }
 
 static int __devinit

^ permalink raw reply related

* [PATCH] ax25: Fix SIOCAX25GETINFO ioctl
From: Eric Dumazet @ 2009-09-20 16:32 UTC (permalink / raw)
  To: Jan Rafaj, David S. Miller; +Cc: Linux Netdev List
In-Reply-To: <alpine.LNX.2.00.0909201226001.29572@cedric.unob.cz>

Jan Rafaj a écrit :
> 
> Hello Eric,
> 
> Your commit 31e6d363abcd0d05766c82f1a9c905a4c974a199 introduces (among
> other things):
> 
> diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
> index 61b35b9..da0f64f 100644
> --- a/net/ax25/af_ax25.c
> +++ b/net/ax25/af_ax25.c
> @@ -1780,8 +1781,8 @@ static int ax25_ioctl(struct socket *sock,
> unsigned int cmd, unsigned long arg)
>                 ax25_info.idletimer =
> ax25_display_timer(&ax25->idletimer) / (60 * HZ);
>                 ax25_info.n2count   = ax25->n2count;
>                 ax25_info.state     = ax25->state;
> -               ax25_info.rcv_q     = atomic_read(&sk->sk_rmem_alloc);
> -               ax25_info.snd_q     = atomic_read(&sk->sk_wmem_alloc);
> +               ax25_info.rcv_q     = sk_wmem_alloc_get(sk);
> +               ax25_info.snd_q     = sk_rmem_alloc_get(sk);
>                 ax25_info.vs        = ax25->vs;
>                 ax25_info.vr        = ax25->vr;
>                 ax25_info.va        = ax25->va;
> 
> I believe there is a typo, correctly this should be:
> 
>                 ax25_info.idletimer = ax25_display_timer(&ax25->idletimer)
> / (60 * HZ);
>                 ax25_info.n2count   = ax25->n2count;
>                 ax25_info.state     = ax25->state;
> -               ax25_info.rcv_q     = atomic_read(&sk->sk_rmem_alloc);
> -               ax25_info.snd_q     = atomic_read(&sk->sk_wmem_alloc);
> +               ax25_info.rcv_q     = sk_rmem_alloc_get(sk);
> +               ax25_info.snd_q     = sk_wmem_alloc_get(sk);
>                 ax25_info.vs        = ax25->vs;
>                 ax25_info.vr        = ax25->vr;
>                 ax25_info.va        = ax25->va;
> 
> If this is not fixed in the master, then fix, please.
> 
> Being a total kernel newbie, I've checked it against Greg K-H's 2.6.31.y
> git tree (but I'm quite unsure whether this is the real HEAD of
> latest [most up to date] development master branch), so if you know where
> I should be looking instead, I'll be grateful for any kicking into the
> right direction... (I somehow feel this should probably be the main
> Linus's syndication tree linux/kernel/git/torvalds/linux-2.6.git - feel
> free to correct me on this one please).
> 
> Thanks,
> 
> Jan
> 
> ---
> Jan Rafaj
> University of Defence in Brno
> 

Oops, Jan you are absolutely right, this part of the patch was wrong.

Dont worry, David will push your patch to netdev tree, then to Linus.

Thanks

[PATCH] ax25: Fix SIOCAX25GETINFO ioctl

rcv_q & snd_q initializations were reversed in commit
31e6d363abcd0d05766c82f1a9c905a4c974a199
(net: correct off-by-one write allocations reports)

Signed-off-by: Jan Rafaj <jr+netfilter-devel@cedric.unob.cz>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index da0f64f..d6b1b05 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -1781,8 +1781,8 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 		ax25_info.idletimer = ax25_display_timer(&ax25->idletimer) / (60 * HZ);
 		ax25_info.n2count   = ax25->n2count;
 		ax25_info.state     = ax25->state;
-		ax25_info.rcv_q     = sk_wmem_alloc_get(sk);
-		ax25_info.snd_q     = sk_rmem_alloc_get(sk);
+		ax25_info.rcv_q     = sk_rmem_alloc_get(sk);
+		ax25_info.snd_q     = sk_wmem_alloc_get(sk);
 		ax25_info.vs        = ax25->vs;
 		ax25_info.vr        = ax25->vr;
 		ax25_info.va        = ax25->va;

^ permalink raw reply related

* Re: [PATCH 1/2] pktgen: check for link down
From: Jesper Dangaard Brouer @ 2009-09-20 15:26 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: David Miller, Robert Olsson, Jesper Dangaard Brouer, netdev
In-Reply-To: <20090919221844.114e2e23@nehalam>


Thanks for fixing this.

Acked-by: Jesper Dangaard Brouer <hawk@comx.dk>


On Sat, 19 Sep 2009, Stephen Hemminger wrote:

> If cable is pulled, pktgen shouldn't continue slamming packets into the
> device.
>
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
>
> --- a/net/core/pktgen.c	2009-09-19 11:20:55.546463176 -0700
> +++ b/net/core/pktgen.c	2009-09-19 11:22:44.810509240 -0700
> @@ -1959,7 +1959,7 @@ static int pktgen_setup_dev(struct pktge
> 	if (odev->type != ARPHRD_ETHER) {
> 		printk(KERN_ERR "pktgen: not an ethernet device: \"%s\"\n", ifname);
> 		err = -EINVAL;
> -	} else if (!netif_running(odev)) {
> +	} else if (!netif_running(odev) || !netif_carrier_ok(odev)) {
> 		printk(KERN_ERR "pktgen: device is down: \"%s\"\n", ifname);
> 		err = -ENETDOWN;
> 	} else {
> @@ -3410,7 +3410,7 @@ static void pktgen_xmit(struct pktgen_de
> 	/* Did we saturate the queue already? */
> 	if (netif_tx_queue_stopped(txq) || netif_tx_queue_frozen(txq)) {
> 		/* If device is down, then all queues are permnantly frozen */
> -		if (netif_running(odev))
> +		if (netif_running(odev) && netif_carrier_ok(odev))
> 			idle(pkt_dev);
> 		else
> 			pktgen_stop_device(pkt_dev);

Hilsen
   Jesper Brouer

--
-------------------------------------------------------------------
MSc. Master of Computer Science
Dept. of Computer Science, University of Copenhagen
Author of http://www.adsl-optimizer.dk
-------------------------------------------------------------------

^ permalink raw reply

* Re: [iproute2] tc action mirred    question
From: jamal @ 2009-09-20 13:33 UTC (permalink / raw)
  To: Xiaofei Wu; +Cc: linux netdev
In-Reply-To: <908876.76571.qm@web111609.mail.gq1.yahoo.com>

On Sun, 2009-09-20 at 02:58 -0700, Xiaofei Wu wrote:

> When the link A-B is not available, 

How do you detect this? Is it a path that is broken or a link?

> Could iproute2 'tc' do this?


you could use iproute2 'ip' which supports multi-nexthops, example
off top of my head (for exact syntax run "ip route help")
----
ip route add blah/24 nexthop via a.b.c.d dev wlan0 \
	    nexthop via e.f.g.h dev wlan1 
----

You will probably need to help it by flushing route cache.
You may need to worry about loops on mirroring when the route flipping
happens and need to optimize for that. Please experiment.

cheers,
jamal



^ permalink raw reply

* Pozyskaj nowych klientów, zwieksz przychody, obniż koszty [Paweł Boratyński]
From: pb3 @ 2009-09-20 11:55 UTC (permalink / raw)
  To: netdev

Witam,
reprezentuję firmę JSystems (www.jsystems.pl). Nasza firma stworzyła profesjonalny informatyczny system marketingowy, automatyzujący proces poszukiwania nowych klientów i jednocześnie znacznie obniżający koszty tego procesu. Czy mogę Państwu przesłać ofertę dotyczącą tego produktu?

Pozdrawiam

Sales Representative
Paweł Boratyński
22 405 38 45

^ permalink raw reply

* Re: [iproute2] tc action mirred    question
From: Xiaofei Wu @ 2009-09-20  9:58 UTC (permalink / raw)
  To: hadi; +Cc: linux netdev
In-Reply-To: <1253104099.4584.9.camel@dogo.mojatatu.com>

Hi,

I come across another problem.

network topology:
 M
  |
 A
/  \
B  D
\  /
 C

node M  < ---- > node C
common path: M-A-B-C
the other path: M-A-D-C

With your help I can mirror the outgoing packets(node A wlan0) to wlan1(node A), then transmit it to D. D will route them to C.

There will be another problem.

When the link A-B is not available, there is no packect going out to mirror, node M could not get to node C. (if B is broken, A use ARP to ask the MAC of B's IP addr, but no reply)

So I want to forward the incoming packets( node M -> A(eth0) ) to wlan0(node A) and wlan1(node A) at the same time, route them separately. In this case, if one path is unavailable, it will not influence the other path.

Could iproute2 'tc' do this?


regards,
wu

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 


^ permalink raw reply

* Re: [AX25] kernel panic
From: f8arr @ 2009-09-20  9:09 UTC (permalink / raw)
  To: Bernard Pidoux
  Cc: Jarek Poplawski, Ralf Baechle DL5RB, Linux Netdev List,
	linux-hams
In-Reply-To: <4AB5EAE5.6070605@upmc.fr>

hi Bernard,

My problem wasn't exactly the same has your.
But !

Doing a boot with the kernel option "nosmp" wasn't suffisant... it 
seemed to load the smp and then, while reading the boot option, 
unsetting them... but it was too late. (I saw that looking the dmesg).

My solution has been to compile a kernel without smp to be sure that 
nothing goes up... and it worked !

Regards
f8arr

Bernard Pidoux a écrit :
> Hi,
>
> Here are the first events noticed since I turned on 
> CONFIG_DEBUG_OBJECTS_TIMERS option.
>
> First a kernel BUG, second a kernel panic.
>
> Best regards,
>
> Bernard Pidoux
>
>
>
>
>

^ permalink raw reply

* Re: [AX25] kernel panic
From: Bernard Pidoux @ 2009-09-20  8:42 UTC (permalink / raw)
  To: Jarek Poplawski; +Cc: Ralf Baechle DL5RB, Linux Netdev List, linux-hams
In-Reply-To: <20090911120557.GA12175@linux-mips.org>

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

Hi,

Here are the first events noticed since I turned on 
CONFIG_DEBUG_OBJECTS_TIMERS option.

First a kernel BUG, second a kernel panic.

Best regards,

Bernard Pidoux






[-- Attachment #2: kernel_bug --]
[-- Type: text/plain, Size: 4116 bytes --]

------------[ cut here ]------------
kernel BUG at kernel/timer.c:913!
invalid opcode: 0000 [#1] 
last sysfs file: /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
CPU 0 
Modules linked in: netconsole netrom mkiss rose ax25 nfsd exportfs nfs lockd nfs_acl auth_rpcgss sunrpc af_packet ipv6 binfmt_misc loop ext3 jbd cpufreq_ondemand cpufreq_conservative cpufreq_powersave acpi_cpufreq freq_table snd_via82xx snd_ac97_codec ac97_bus snd_mpu401_uart snd_rawmidi snd_seq_dummy snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device snd_pcm_oss snd_pcm snd_timer snd_page_alloc snd_mixer_oss snd soundcore shpchp pci_hotplug i2c_viapro i2c_core via_agp floppy 8139cp 8139too mii sg sr_mod processor rtc_cmos button thermal evdev pata_via ata_generic ide_pci_generic pata_acpi sata_via libata sd_mod scsi_mod crc_t10dif
Pid: 24497, comm: astropulse_5.06 Not tainted 2.6.31-nosmp #3 MS-7258
RIP: 0010:[<ffffffff81061412>]  [<ffffffff81061412>] cascade+0xb2/0xc0
RSP: 0000:ffffffff8155be00  EFLAGS: 00010082
RAX: 0000000000000000 RBX: ffff880050c4c218 RCX: 0000000104445204
RDX: ffffffff8132b3d0 RSI: ffff880050c4c218 RDI: ffffffff81673540
RBP: ffffffff8155be40 R08: 0000000000000004 R09: ffffffff81568bc0
R10: ffffffff8155be28 R11: 0000000000000001 R12: ffffffff81673540
R13: ffffffff8155be00 R14: 0000000000000012 R15: 0000000000000001
FS:  00000000016e2860(0063) GS:ffffffff81558000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fe3eb15029c CR3: 000000007ecff000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff4ff0 DR7: 0000000000000400
Process astropulse_5.06 (pid: 24497, threadinfo ffff88005807a000, task ffff880049588000)
Stack:
 ffff8800445748e0 ffff88007e86ab98 ffffffff8155be88 000000008c85481d
<0> 0000000000000000 ffffffff81673540 ffffffff8155be70 0000000000000081
<0> ffffffff8155bec0 ffffffff81061613 ffffffff81675150 ffffffff81674d50
Call Trace:
 <IRQ> 
 [<ffffffff81061613>] run_timer_softirq+0xf3/0x250
 [<ffffffff8102d0db>] ? lapic_next_event+0x2b/0x50
 [<ffffffff8107fc42>] ? clockevents_program_event+0x62/0xc0
 [<ffffffff8105b242>] __do_softirq+0xe2/0x1d0
 [<ffffffff8101414a>] call_softirq+0x1a/0x30
 [<ffffffff810162c5>] do_softirq+0x75/0xc0
 [<ffffffff8105ac45>] irq_exit+0x65/0x80
 [<ffffffff8102ddb5>] smp_apic_timer_interrupt+0x65/0xb0
 [<ffffffff81013c73>] apic_timer_interrupt+0x13/0x20
 <EOI> 
Code: 45 fe ff ff 4c 39 eb 48 8b 13 75 dd 48 8b 55 d8 65 48 33 14 25 28 00 00 00 44 89 f0 75 11 48 83 c4 20 5b 41 5c 41 5d 41 5e c9 c3 <0f> 0b eb fe e8 c5 29 ff ff 0f 1f 44 00 00 55 48 89 e5 48 83 ec 
RIP  [<ffffffff81061412>] cascade+0xb2/0xc0
 RSP <ffffffff8155be00>
---[ end trace 2efb8d4aaedbf503 ]---
Kernel panic - not syncing: Fatal exception in interrupt
Pid: 24497, comm: astropulse_5.06 Tainted: G      D    2.6.31-nosmp #3
Call Trace:
 <IRQ>  [<ffffffff813d5e52>] panic+0xb2/0x180
 [<ffffffff8132f8ff>] ? __kfree_skb+0x6f/0xe0
 [<ffffffff810549bd>] ? console_unblank+0x8d/0xd0
 [<ffffffff812bdcee>] ? unblank_screen+0x1e/0x40
 [<ffffffff81053a36>] ? oops_exit+0x36/0x60
 [<ffffffff81017947>] oops_end+0xe7/0x100
 [<ffffffff810179bd>] ? oops_begin+0x5d/0x80
 [<ffffffff81017b52>] die+0x62/0xa0
 [<ffffffff81014e86>] do_trap+0x166/0x190
 [<ffffffff8107715d>] ? notify_die+0x3d/0x60
 [<ffffffff810153a5>] do_invalid_op+0xa5/0xd0
 [<ffffffff81061412>] ? cascade+0xb2/0xc0
 [<ffffffff8104dcde>] ? wake_up_state+0x1e/0x40
 [<ffffffff81013ddb>] invalid_op+0x1b/0x20
 [<ffffffff8132b3d0>] ? sock_def_write_space+0x0/0xb0
 [<ffffffff81061412>] ? cascade+0xb2/0xc0
 [<ffffffff81061613>] run_timer_softirq+0xf3/0x250
 [<ffffffff8102d0db>] ? lapic_next_event+0x2b/0x50
 [<ffffffff8107fc42>] ? clockevents_program_event+0x62/0xc0
 [<ffffffff8105b242>] __do_softirq+0xe2/0x1d0
 [<ffffffff8101414a>] call_softirq+0x1a/0x30
 [<ffffffff810162c5>] do_softirq+0x75/0xc0
 [<ffffffff8105ac45>] irq_exit+0x65/0x80
 [<ffffffff8102ddb5>] smp_apic_timer_interrupt+0x65/0xb0
 [<ffffffff81013c73>] apic_timer_interrupt+0x13/0x20
 <EOI> 
Rebooting in 60 seconds..[root@f6bvp-9 bernard]# 


^ permalink raw reply

* Re: SO_TIMESTAMPING fix and design decisions
From: Christopher Zimmermann @ 2009-09-20  7:52 UTC (permalink / raw)
  To: Peter P Waskiewicz Jr, netdev@vger.kernel.org
In-Reply-To: <1253398161.14869.2.camel@localhost.localdomain>

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

On Sat, 19 Sep 2009 15:09:21 -0700
Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com> wrote:

> > hardware timestamps only work for the Intel igb driver. I have 
> > access to two test machines with NICs supported by this driver.
> 
> Intel's 82599, supported by ixgbe, also has the same IEEE 1588
> timestamping support in hardware.  We haven't implemented the support
> yet in ixgbe, but the hardware is there and does work.  If you were
> curious of the interface, the datasheet for the hardware is available on
> our SourceForge site (e1000.sf.net).

hi! thanks for the reply.

I already got the documentation for the 82576 cards I have access to. I 
won't be able to afford another pair.

What do you think about my idea to expose the relevant registers to 
userspace? I believe it would not be too difficult for userspace to 
configure the timestamps this way and would allow way more flexibility. 
Of course I would #DEFINE the constants used to set the registers.

Christopher Zimmermann

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: [PATCH] netdev: stats on multiqueue possible bug
From: Eric Dumazet @ 2009-09-20  7:24 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: David Miller, netdev
In-Reply-To: <20090919222608.5fdf80b8@nehalam>

Stephen Hemminger a écrit :
> Dave, I think you were trying to optimize something here that
> doesn't need optimization.
> 
> If transmit stats (all) wrap to zero, then the stats would not
> be set correctly. Move local variable into loop as well.
> 
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> 
> --- a/net/core/dev.c	2009-09-19 15:19:13.902495560 -0700
> +++ b/net/core/dev.c	2009-09-19 15:48:21.126458728 -0700
> @@ -5079,19 +5079,19 @@ const struct net_device_stats *dev_get_s
>  		unsigned long tx_bytes = 0, tx_packets = 0, tx_dropped = 0;
>  		struct net_device_stats *stats = &dev->stats;
>  		unsigned int i;
> -		struct netdev_queue *txq;
>  
>  		for (i = 0; i < dev->num_tx_queues; i++) {
> -			txq = netdev_get_tx_queue(dev, i);
> +			const struct netdev_queue *txq
> +				 = netdev_get_tx_queue(dev, i);
>  			tx_bytes   += txq->tx_bytes;
>  			tx_packets += txq->tx_packets;
>  			tx_dropped += txq->tx_dropped;
>  		}
> -		if (tx_bytes || tx_packets || tx_dropped) {
> -			stats->tx_bytes   = tx_bytes;
> -			stats->tx_packets = tx_packets;
> -			stats->tx_dropped = tx_dropped;
> -		}
> +
> +		stats->tx_bytes   = tx_bytes;
> +		stats->tx_packets = tx_packets;
> +		stats->tx_dropped = tx_dropped;
> +
>  		return stats;
>  	}
>  }

Most devices dont update txq->tx_bytes/tx_packets/tx_dropped yet, but
still update their device->stats

Your patch makes these devices clearing their stats.

In the case all stats wrap to zero, we'll give old values. If you think this is 
a bug, you should find another way to fix it :)

^ permalink raw reply

* Re: sky2 rx length errors
From: Andrew Morton @ 2009-09-20  6:35 UTC (permalink / raw)
  To: Grozdan; +Cc: linux-kernel, Stephen Hemminger, netdev
In-Reply-To: <c5bd819b0909180641n7c353b80tc15b9c9fe02d5c95@mail.gmail.com>

(added cc's from the MAINTAINERS file)

On Fri, 18 Sep 2009 15:41:45 +0200 Grozdan <neutrino8@gmail.com> wrote:

> Hi,
> 
> I have a Marvell onboard NIC (88E8053) and I've been noticing for a
> while now a bit weird behavior with the sky2 driver. This mostly
> occurs with newer kernels (2.6.30, 2.6.31) and my older distro kernel
> (2.6.27.21) does not seem to have the same problem. Basically, the
> sky2 driver will randomly and unpredictably spew rx length error
> messages and reboot itself. I also noticed in dmesg that this mostly
> occurs after "martian destination" messages. After this message, sky2
> starts spewing messages as shown below and then reboots itself. It is
> not really a big problem for me, but since I'm virtually always logged
> in in IRC, the client always loses connection, waits for a few minutes
> to get a response from the server and then relogs me again. I do not
> think it's a HW problem as the Marvell NIC otherwise works perfectly
> and I've checked my cable modem too which operates without a problem.
> Any ideas?
> 
> PS: please cc me as I'm not subscribed to the mailing list
> 
> sky2 driver version 1.23
> sky2 0000:05:00.0: PCI INT A -> GSI 36 (level, low) -> IRQ 36
> sky2 0000:05:00.0: setting latency timer to 64
> sky2 0000:05:00.0: PCI: Disallowing DAC for device
> sky2 0000:05:00.0: Yukon-2 EC chip revision 2
> sky2 0000:05:00.0: irq 53 for MSI/MSI-X
> sky2 0000:05:00.0: No interrupt generated using MSI, switching to INTx mode.
> sky2 eth0: addr 00:11:d8:a1:5b:0e
> sky2 eth0: enabling interface
> sky2 eth0: Link is up at 100 Mbps, full duplex, flow control rx
> .....
> .....
> martian destination 0.0.0.0 from 172.23.204.1, dev eth0
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x5ea0100 length 598
> sky2 eth0: rx length error: status 0x5ea0100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x5ea0100 length 598
> sky2 eth0: rx length error: status 0x5ea0100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598
> sky2 eth0: rx length error: status 0x4420100 length 598


^ permalink raw reply

* [PATCH] netdev: stats on multiqueue possible bug
From: Stephen Hemminger @ 2009-09-20  5:26 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

Dave, I think you were trying to optimize something here that
doesn't need optimization.

If transmit stats (all) wrap to zero, then the stats would not
be set correctly. Move local variable into loop as well.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

--- a/net/core/dev.c	2009-09-19 15:19:13.902495560 -0700
+++ b/net/core/dev.c	2009-09-19 15:48:21.126458728 -0700
@@ -5079,19 +5079,19 @@ const struct net_device_stats *dev_get_s
 		unsigned long tx_bytes = 0, tx_packets = 0, tx_dropped = 0;
 		struct net_device_stats *stats = &dev->stats;
 		unsigned int i;
-		struct netdev_queue *txq;
 
 		for (i = 0; i < dev->num_tx_queues; i++) {
-			txq = netdev_get_tx_queue(dev, i);
+			const struct netdev_queue *txq
+				 = netdev_get_tx_queue(dev, i);
 			tx_bytes   += txq->tx_bytes;
 			tx_packets += txq->tx_packets;
 			tx_dropped += txq->tx_dropped;
 		}
-		if (tx_bytes || tx_packets || tx_dropped) {
-			stats->tx_bytes   = tx_bytes;
-			stats->tx_packets = tx_packets;
-			stats->tx_dropped = tx_dropped;
-		}
+
+		stats->tx_bytes   = tx_bytes;
+		stats->tx_packets = tx_packets;
+		stats->tx_dropped = tx_dropped;
+
 		return stats;
 	}
 }

^ permalink raw reply

* [PATCH 2/2] pktgen: nmi watchdog keep alive
From: Stephen Hemminger @ 2009-09-20  5:21 UTC (permalink / raw)
  To: David Miller, Robert Olsson; +Cc: netdev

If pktgen gets really busy it takes up all the CPU,
and can starve the NMI thread and cause system reset.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

--- a/net/core/pktgen.c	2009-09-19 11:28:53.762463050 -0700
+++ b/net/core/pktgen.c	2009-09-19 11:30:36.534459968 -0700
@@ -136,6 +136,7 @@
 #include <linux/delay.h>
 #include <linux/timer.h>
 #include <linux/list.h>
+#include <linux/nmi.h>
 #include <linux/init.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
@@ -3369,6 +3370,7 @@ static void idle(struct pktgen_dev *pkt_
 {
 	ktime_t idle_start = ktime_now();
 
+	touch_nmi_watchdog();
 	if (need_resched())
 		schedule();
 	else

^ permalink raw reply

* [PATCH 1/2] pktgen: check for link down
From: Stephen Hemminger @ 2009-09-20  5:18 UTC (permalink / raw)
  To: David Miller, Robert Olsson, Jesper Dangaard Brouer; +Cc: netdev

If cable is pulled, pktgen shouldn't continue slamming packets into the
device.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

--- a/net/core/pktgen.c	2009-09-19 11:20:55.546463176 -0700
+++ b/net/core/pktgen.c	2009-09-19 11:22:44.810509240 -0700
@@ -1959,7 +1959,7 @@ static int pktgen_setup_dev(struct pktge
 	if (odev->type != ARPHRD_ETHER) {
 		printk(KERN_ERR "pktgen: not an ethernet device: \"%s\"\n", ifname);
 		err = -EINVAL;
-	} else if (!netif_running(odev)) {
+	} else if (!netif_running(odev) || !netif_carrier_ok(odev)) {
 		printk(KERN_ERR "pktgen: device is down: \"%s\"\n", ifname);
 		err = -ENETDOWN;
 	} else {
@@ -3410,7 +3410,7 @@ static void pktgen_xmit(struct pktgen_de
 	/* Did we saturate the queue already? */
 	if (netif_tx_queue_stopped(txq) || netif_tx_queue_frozen(txq)) {
 		/* If device is down, then all queues are permnantly frozen */
-		if (netif_running(odev))
+		if (netif_running(odev) && netif_carrier_ok(odev))
 			idle(pkt_dev);
 		else
 			pktgen_stop_device(pkt_dev);

^ permalink raw reply

* Re: SO_TIMESTAMPING fix and design decisions
From: Peter P Waskiewicz Jr @ 2009-09-19 22:09 UTC (permalink / raw)
  To: Christopher Zimmermann; +Cc: netdev@vger.kernel.org
In-Reply-To: <20090919192549.0735c93a@pundit>

On Sat, 2009-09-19 at 10:25 -0700, Christopher Zimmermann wrote:
> Hi, 
> 
> I'm currently working on the SO_TIMESTAMPING feature which is currently 
> pretty much broken. The current status is the following:
> 
> -tx software timestamps don't work because of a race condition. See 
> commit cd4d8fdad1f1320.
> -rx software timestamps do work. But they are nothing new.
> SO_TIMESTAMP[NS] has been available for years.
> 
> hardware timestamps only work for the Intel igb driver. I have access to 
> two test machines with NICs supported by this driver.
> 

Intel's 82599, supported by ixgbe, also has the same IEEE 1588
timestamping support in hardware.  We haven't implemented the support
yet in ixgbe, but the hardware is there and does work.  If you were
curious of the interface, the datasheet for the hardware is available on
our SourceForge site (e1000.sf.net).

Cheers,
-PJ


^ permalink raw reply

* [PATCH RESEND] kaweth: Fix memory leak in kaweth_control()
From: Kevin Cernekee @ 2009-09-19 21:18 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-usb-u79uwXL29TY76Z2rM5mHXA, Oliver Neukum,
	Greg Kroah-Hartman

kaweth_control() never frees the buffer that it allocates for the USB
control message.  Test case:

while :; do ifconfig eth2 down ; ifconfig eth2 up ; done

This is a tiny buffer so it is a slow leak.  If you want to speed up the
process, you can change the allocation size to e.g. 16384 bytes, and it
will consume several megabytes within a few minutes.

Signed-off-by: Kevin Cernekee <cernekee-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Acked-by: Oliver Neukum <oliver-GvhC2dPhHPQdnm+yROfE0A@public.gmane.org>
---
 drivers/net/usb/kaweth.c |   18 +++++++++++-------
 1 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
index e2a39b9..e391ef9 100644
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -263,6 +263,7 @@ static int kaweth_control(struct kaweth_device *kaweth,
 			  int timeout)
 {
 	struct usb_ctrlrequest *dr;
+	int retval;
 
 	dbg("kaweth_control()");
 
@@ -278,18 +279,21 @@ static int kaweth_control(struct kaweth_device *kaweth,
 		return -ENOMEM;
 	}
 
-	dr->bRequestType= requesttype;
+	dr->bRequestType = requesttype;
 	dr->bRequest = request;
 	dr->wValue = cpu_to_le16(value);
 	dr->wIndex = cpu_to_le16(index);
 	dr->wLength = cpu_to_le16(size);
 
-	return kaweth_internal_control_msg(kaweth->dev,
-					pipe,
-					dr,
-					data,
-					size,
-					timeout);
+	retval = kaweth_internal_control_msg(kaweth->dev,
+					     pipe,
+					     dr,
+					     data,
+					     size,
+					     timeout);
+
+	kfree(dr);
+	return retval;
 }
 
 /****************************************************************
-- 
1.6.3.1

--
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 related

* Re: [iproute2 PATCH] Add 'ip tuntap' support.
From: David Woodhouse @ 2009-09-19 19:55 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <20090919125222.5f4718f1@s6510>

On Sat, 2009-09-19 at 12:52 -0700, Stephen Hemminger wrote:
> 
> I added it, but:
>   * cleaned up whitespace

Thanks.

>   * use if_tun.h from sanitized 2.6.30

Hm, what's the difference, other than the lack of IFF_TUN_EXCL?

>   * ifdef IFF_TUN_EXCL flag, so can build with older code
>    (currently iproute is releasing for 2.6.30)

IFF_TUN_EXCL is harmless (ignored) on older kernels -- when I looked at
compatibility I decided to just set it anyway. Sorry, perhaps I should
have mentioned that in the commit comment... but I'd completely
forgotten about it.

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse@intel.com                              Intel Corporation


^ permalink raw reply

* Re: [iproute2 PATCH] Add 'ip tuntap' support.
From: Stephen Hemminger @ 2009-09-19 19:52 UTC (permalink / raw)
  To: David Woodhouse; +Cc: netdev
In-Reply-To: <1253378923.6317.11.camel@macbook.infradead.org>

On Sat, 19 Sep 2009 09:48:43 -0700
David Woodhouse <dwmw2@infradead.org> wrote:

> This patch provides support for 'ip tuntap', allowing creation and
> deletion of persistent tun/tap devices.
> 
> diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h
> new file mode 100644
> index 0000000..915ba57
> --- /dev/null
> +++ b/include/linux/if_tun.h
> @@ -0,0 +1,88 @@
> +/*
> + *  Universal TUN/TAP device driver.
> + *  Copyright (C) 1999-2000 Maxim Krasnyansky <max_mk@yahoo.com>
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation; either version 2 of the License, or
> + *  (at your option) any later version.
> + *
> + *  This program is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + *  GNU General Public License for more details.
> + */
> +
> +#ifndef __IF_TUN_H
> +#define __IF_TUN_H
> +
> +#include <linux/types.h>
> +#include <linux/if_ether.h>
> +
> +/* Read queue size */
> +#define TUN_READQ_SIZE	500
> +
> +/* TUN device flags */
> +#define TUN_TUN_DEV 	0x0001	
> +#define TUN_TAP_DEV	0x0002
> +#define TUN_TYPE_MASK   0x000f
> +
> +#define TUN_FASYNC	0x0010
> +#define TUN_NOCHECKSUM	0x0020
> +#define TUN_NO_PI	0x0040
> +#define TUN_ONE_QUEUE	0x0080
> +#define TUN_PERSIST 	0x0100	
> +#define TUN_VNET_HDR 	0x0200
> +
> +/* Ioctl defines */
> +#define TUNSETNOCSUM  _IOW('T', 200, int) 
> +#define TUNSETDEBUG   _IOW('T', 201, int) 
> +#define TUNSETIFF     _IOW('T', 202, int) 
> +#define TUNSETPERSIST _IOW('T', 203, int) 
> +#define TUNSETOWNER   _IOW('T', 204, int)
> +#define TUNSETLINK    _IOW('T', 205, int)
> +#define TUNSETGROUP   _IOW('T', 206, int)
> +#define TUNGETFEATURES _IOR('T', 207, unsigned int)
> +#define TUNSETOFFLOAD  _IOW('T', 208, unsigned int)
> +#define TUNSETTXFILTER _IOW('T', 209, unsigned int)
> +#define TUNGETIFF      _IOR('T', 210, unsigned int)
> +#define TUNGETSNDBUF   _IOR('T', 211, int)
> +#define TUNSETSNDBUF   _IOW('T', 212, int)
> +
> +/* TUNSETIFF ifr flags */
> +#define IFF_TUN		0x0001
> +#define IFF_TAP		0x0002
> +#define IFF_NO_PI	0x1000
> +#define IFF_ONE_QUEUE	0x2000
> +#define IFF_VNET_HDR	0x4000
> +#define IFF_TUN_EXCL	0x8000
> +
> +/* Features for GSO (TUNSETOFFLOAD). */
> +#define TUN_F_CSUM	0x01	/* You can hand me unchecksummed packets. */
> +#define TUN_F_TSO4	0x02	/* I can handle TSO for IPv4 packets */
> +#define TUN_F_TSO6	0x04	/* I can handle TSO for IPv6 packets */
> +#define TUN_F_TSO_ECN	0x08	/* I can handle TSO with ECN bits. */
> +
> +/* Protocol info prepended to the packets (when IFF_NO_PI is not set) */
> +#define TUN_PKT_STRIP	0x0001
> +struct tun_pi {
> +	__u16  flags;
> +	__be16 proto;
> +};
> +
> +/*
> + * Filter spec (used for SETXXFILTER ioctls)
> + * This stuff is applicable only to the TAP (Ethernet) devices.
> + * If the count is zero the filter is disabled and the driver accepts
> + * all packets (promisc mode).
> + * If the filter is enabled in order to accept broadcast packets
> + * broadcast addr must be explicitly included in the addr list.
> + */
> +#define TUN_FLT_ALLMULTI 0x0001 /* Accept all multicast packets */
> +struct tun_filter {
> +	__u16  flags; /* TUN_FLT_ flags see above */
> +	__u16  count; /* Number of addresses */
> +	__u8   addr[0][ETH_ALEN];
> +};
> +
> +#endif /* __IF_TUN_H */
> diff --git a/ip/Makefile b/ip/Makefile
> index 3c185cf..fd16fe9 100644
> --- a/ip/Makefile
> +++ b/ip/Makefile
> @@ -1,6 +1,6 @@
>  IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o \
>      rtm_map.o iptunnel.o ip6tunnel.o tunnel.o ipneigh.o ipntable.o iplink.o \
> -    ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o \
> +    ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o iptuntap.o \
>      ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \
>      iplink_vlan.o link_veth.o link_gre.o iplink_can.o
>  
> diff --git a/ip/ip.c b/ip/ip.c
> index 2bd54b2..d846a76 100644
> --- a/ip/ip.c
> +++ b/ip/ip.c
> @@ -47,7 +47,7 @@ static void usage(void)
>  "Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }\n"
>  "       ip [ -force ] -batch filename\n"
>  "where  OBJECT := { link | addr | addrlabel | route | rule | neigh | ntable |\n"
> -"                   tunnel | maddr | mroute | monitor | xfrm }\n"
> +"                   tunnel | tuntap | maddr | mroute | monitor | xfrm }\n"
>  "       OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
>  "                    -f[amily] { inet | inet6 | ipx | dnet | link } |\n"
>  "                    -o[neline] | -t[imestamp] | -b[atch] [filename] }\n");
> @@ -75,6 +75,8 @@ static const struct cmd {
>  	{ "link",	do_iplink },
>  	{ "tunnel",	do_iptunnel },
>  	{ "tunl",	do_iptunnel },
> +	{ "tuntap",	do_iptuntap },
> +	{ "tap",	do_iptuntap },
>  	{ "monitor",	do_ipmonitor },
>  	{ "xfrm",	do_xfrm },
>  	{ "mroute",	do_multiroute },
> diff --git a/ip/ip_common.h b/ip/ip_common.h
> index 273065f..c857667 100644
> --- a/ip/ip_common.h
> +++ b/ip/ip_common.h
> @@ -32,6 +32,7 @@ extern int do_ipneigh(int argc, char **argv);
>  extern int do_ipntable(int argc, char **argv);
>  extern int do_iptunnel(int argc, char **argv);
>  extern int do_ip6tunnel(int argc, char **argv);
> +extern int do_iptuntap(int argc, char **argv);
>  extern int do_iplink(int argc, char **argv);
>  extern int do_ipmonitor(int argc, char **argv);
>  extern int do_multiaddr(int argc, char **argv);
> diff --git a/ip/iptuntap.c b/ip/iptuntap.c
> new file mode 100644
> index 0000000..f7f64bc
> --- /dev/null
> +++ b/ip/iptuntap.c
> @@ -0,0 +1,321 @@
> +/*
> + * iptunnel.c	       "ip tuntap"
> + *
> + *		This program is free software; you can redistribute it and/or
> + *		modify it under the terms of the GNU General Public License
> + *		as published by the Free Software Foundation; either version
> + *		2 of the License, or (at your option) any later version.
> + *
> + * Authors:	David Woodhouse <David.Woodhouse@intel.com>
> + *
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <sys/types.h>
> +#include <sys/socket.h>
> +#include <arpa/inet.h>
> +#include <sys/ioctl.h>
> +#include <linux/if.h>
> +#include <linux/if_tun.h>
> +#include <pwd.h>
> +#include <grp.h>
> +#include <fcntl.h>
> +#include <dirent.h>
> +#include <errno.h>
> +
> +#include "rt_names.h"
> +#include "utils.h"
> +#include "ip_common.h"
> +
> +#define TUNDEV "/dev/net/tun"
> +
> +static void usage(void) __attribute__((noreturn));
> +
> +static void usage(void)
> +{
> +	fprintf(stderr, "Usage: ip tuntap { add | del } [ dev PHYS_DEV ] \n");
> +	fprintf(stderr, "          [ mode { tun | tap } ] [ user USER ] [ group GROUP ]\n");
> +	fprintf(stderr, "          [ one_queue ] [ pi ] [ vnet_hdr ]\n");
> +	fprintf(stderr, "\n");
> +	fprintf(stderr, "Where: USER  := { STRING | NUMBER }\n");
> +	fprintf(stderr, "       GROUP := { STRING | NUMBER }\n");
> +	exit(-1);
> +}
> +
> +static int tap_add_ioctl(struct ifreq *ifr, uid_t uid, gid_t gid)
> +{
> +	int fd = open(TUNDEV, O_RDWR);
> +	int ret = -1;
> +
> +	ifr->ifr_flags |= IFF_TUN_EXCL;
> +
> +	fd = open(TUNDEV, O_RDWR);
> +	if (fd < 0) {
> +		perror("open");
> +		return -1;
> +	}
> +	if (ioctl(fd, TUNSETIFF, ifr)) {
> +		perror("ioctl(TUNSETIFF)");
> +		goto out;
> +	}
> +	if (uid != -1 && ioctl(fd, TUNSETOWNER, uid)) {
> +		perror("ioctl(TUNSETOWNER)");
> +		goto out;
> +	}
> +	if (gid != -1 && ioctl(fd, TUNSETGROUP, gid)) {
> +		perror("ioctl(TUNSETGROUP)");
> +		goto out;
> +	}
> +	if (ioctl(fd, TUNSETPERSIST, 1)) {
> +		perror("ioctl(TUNSETPERSIST)");
> +		goto out;
> +	}
> +	ret = 0;
> + out:
> +	close(fd);
> +	return ret;
> +}
> +
> +static int tap_del_ioctl(struct ifreq *ifr)
> +{
> +	int fd = open(TUNDEV, O_RDWR);
> +	int ret = -1;
> +
> +	if (fd < 0) {
> +		perror("open");
> +		return -1;
> +	}
> +	if (ioctl(fd, TUNSETIFF, ifr)) {
> +		perror("ioctl(TUNSETIFF)");
> +		goto out;
> +	}
> +	if (ioctl(fd, TUNSETPERSIST, 0)) {
> +		perror("ioctl(TUNSETPERSIST)");
> +		goto out;
> +	}
> +	ret = 0;
> + out:
> +	close(fd);
> +	return ret;
> +	
> +}
> +static int parse_args(int argc, char **argv, struct ifreq *ifr, uid_t *uid, gid_t *gid)
> +{
> +	int count = 0;
> +
> +	memset(ifr, 0, sizeof(*ifr));
> +
> +	ifr->ifr_flags |= IFF_NO_PI;
> +
> +	while (argc > 0) {
> +		if (matches(*argv, "mode") == 0) {
> +			NEXT_ARG();
> +			if (matches(*argv, "tun") == 0) {
> +				if (ifr->ifr_flags & IFF_TAP) {
> +					fprintf(stderr,"You managed to ask for more than one tunnel mode.\n");
> +					exit(-1);
> +				}
> +				ifr->ifr_flags |= IFF_TUN;
> +			} else if (matches(*argv, "tap") == 0) {
> +				if (ifr->ifr_flags & IFF_TUN) {
> +					fprintf(stderr,"You managed to ask for more than one tunnel mode.\n");
> +					exit(-1);
> +				}
> +				ifr->ifr_flags |= IFF_TAP;
> +			} else {
> +				fprintf(stderr,"Cannot guess tunnel mode.\n");
> +				exit(-1);
> +			}
> +		} else if (uid && matches(*argv, "user") == 0) {
> +			char *end;
> +			unsigned long user;
> +
> +			NEXT_ARG();
> +			if (**argv && ((user = strtol(*argv, &end, 10)), !*end))
> +				*uid = user;
> +			else {
> +				struct passwd *pw = getpwnam(*argv);
> +				if (!pw) {
> +					fprintf(stderr, "invalid user \"%s\"\n", *argv);
> +					exit(-1);
> +				}
> +				*uid = pw->pw_uid;
> +			}
> +		} else if (gid && matches(*argv, "group") == 0) {
> +			char *end;
> +			unsigned long group;
> +
> +			NEXT_ARG();
> +			
> +			if (**argv && ((group = strtol(*argv, &end, 10)), !*end))
> +				*gid = group;
> +			else {
> +				struct group *gr = getgrnam(*argv);
> +				if (!gr) {
> +					fprintf(stderr, "invalid group \"%s\"\n", *argv);
> +					exit(-1);
> +				}
> +				*gid = gr->gr_gid;
> +			}
> +		} else if (matches(*argv, "pi") == 0) {
> +			ifr->ifr_flags &= ~IFF_NO_PI;
> +		} else if (matches(*argv, "one_queue") == 0) {
> +			ifr->ifr_flags |= IFF_ONE_QUEUE;
> +		} else if (matches(*argv, "vnet_hdr") == 0) {
> +			ifr->ifr_flags |= IFF_VNET_HDR;
> +		} else if (matches(*argv, "dev") == 0) {
> +			NEXT_ARG();
> +			strncpy(ifr->ifr_name, *argv, IFNAMSIZ-1);
> +		} else {
> +			if (matches(*argv, "name") == 0) {
> +				NEXT_ARG();
> +			} else if (matches(*argv, "help") == 0)
> +				usage();
> +			if (ifr->ifr_name[0])
> +				duparg2("name", *argv);
> +			strncpy(ifr->ifr_name, *argv, IFNAMSIZ);
> +		}
> +		count++;
> +		argc--; argv++;
> +	}
> +
> +	return 0;
> +}
> +
> +
> +static int do_add(int argc, char **argv)
> +{
> +	struct ifreq ifr;
> +	uid_t uid = -1;
> +	gid_t gid = -1;
> +
> +	if (parse_args(argc, argv, &ifr, &uid, &gid) < 0)
> +		return -1;
> +
> +	if (!(ifr.ifr_flags & TUN_TYPE_MASK)) {
> +		fprintf(stderr, "You failed to specify a tunnel mode\n");
> +		return -1;
> +	}
> +	return tap_add_ioctl(&ifr, uid, gid);
> +}
> +
> +static int do_del(int argc, char **argv)
> +{
> +	struct ifreq ifr;
> +
> +	if (parse_args(argc, argv, &ifr, NULL, NULL) < 0)
> +		return -1;
> +
> +	return tap_del_ioctl(&ifr);
> +}
> +
> +static int read_prop(char *dev, char *prop, long *value)
> +{
> +	char fname[IFNAMSIZ+25], buf[80], *endp;
> +	ssize_t len;
> +	int fd;
> +	long result;
> +
> +	sprintf(fname, "/sys/class/net/%s/%s", dev, prop);
> +	fd = open(fname, O_RDONLY);
> +	if (fd < 0) {
> +		if (strcmp(prop, "tun_flags"))
> +			fprintf(stderr, "open %s: %s\n", fname,
> +				strerror(errno));
> +		return -1;
> +	}
> +	len = read(fd, buf, sizeof(buf)-1);
> +	close(fd);
> +	if (len < 0) {
> +		fprintf(stderr, "read %s: %s", fname, strerror(errno));
> +		return -1;
> +	}
> +
> +	buf[len] = 0;
> +	result = strtol(buf, &endp, 0);
> +	if (*endp != '\n') {
> +		fprintf(stderr, "Failed to parse %s\n", fname);
> +		return -1;
> +	}
> +	*value = result;
> +	return 0;
> +}
> +
> +static void print_flags(long flags)
> +{
> +	if (flags & IFF_TUN)
> +		printf(" tun");
> +
> +	if (flags & IFF_TAP)
> +		printf(" tap");
> +
> +	if (!(flags & IFF_NO_PI))
> +		printf(" pi");
> +
> +	if (flags & IFF_ONE_QUEUE)
> +		printf(" one_queue");
> +
> +	if (flags & IFF_VNET_HDR)
> +		printf(" vnet_hdr");
> +
> +	flags &= ~(IFF_TUN|IFF_TAP|IFF_NO_PI|IFF_ONE_QUEUE|IFF_VNET_HDR);
> +	if (flags)
> +		printf(" UNKNOWN_FLAGS:%lx", flags);
> +}
> +
> +static int do_show(int argc, char **argv)
> +{
> +	DIR *dir;
> +	struct dirent *d;
> +	long flags, owner = -1, group = -1;
> +
> +	dir = opendir("/sys/class/net");
> +	if (!dir) {
> +		perror("opendir");
> +		return -1;
> +	}
> +	while ((d = readdir(dir))) {
> +		if (d->d_name[0] == '.' &&
> +		    (d->d_name[1] == 0 || d->d_name[1] == '.'))
> +			continue;
> +
> +		if (read_prop(d->d_name, "tun_flags", &flags))
> +			continue;
> +
> +		read_prop(d->d_name, "owner", &owner);
> +		read_prop(d->d_name, "group", &group);
> +		
> +		printf("%s:", d->d_name);
> +		print_flags(flags);
> +		if (owner != -1)
> +			printf(" user %ld", owner);
> +		if (group != -1)
> +			printf(" group %ld", group);
> +		printf("\n");
> +	}
> +	return 0;
> +}
> +
> +int do_iptuntap(int argc, char **argv)
> +{
> +	if (argc > 0) {
> +		if (matches(*argv, "add") == 0)
> +			return do_add(argc-1, argv+1);
> +		if (matches(*argv, "del") == 0)
> +			return do_del(argc-1, argv+1);
> +		if (matches(*argv, "show") == 0 ||
> +                    matches(*argv, "lst") == 0 ||
> +                    matches(*argv, "list") == 0)
> +                        return do_show(argc-1, argv+1);
> +		if (matches(*argv, "help") == 0)
> +			usage();
> +	} else
> +		return do_show(0, NULL);
> +
> +	fprintf(stderr, "Command \"%s\" is unknown, try \"ip tuntap help\".\n",
> +		*argv);
> +	exit(-1);
> +}
> 

I added it, but:
  * cleaned up whitespace
  * use if_tun.h from sanitized 2.6.30
  * ifdef IFF_TUN_EXCL flag, so can build with older code
   (currently iproute is releasing for 2.6.30)

^ permalink raw reply

* [PATCH 2/5] drivers/net: remove duplicate structure field initialization
From: Julia Lawall @ 2009-09-19 19:48 UTC (permalink / raw)
  To: netdev, linux-kernel, kernel-janitors

From: Julia Lawall <julia@diku.dk>

The definitions of vnet_ops and ehea_netdev_ops have initializations of a
local function and eth_change_mtu for their respective ndo_change_mtu
fields.  This change uses only the local function.

The semantic match that finds this problem is as follows:
(http://coccinelle.lip6.fr/)

// <smpl>
@r@
identifier I, s, fld;
position p0,p;
expression E;
@@

struct I s =@p0 { ... .fld@p = E, ...};

@s@
identifier I, s, r.fld;
position r.p0,p;
expression E;
@@

struct I s =@p0 { ... .fld@p = E, ...};

@script:python@
p0 << r.p0;
fld << r.fld;
ps << s.p;
pr << r.p;
@@

if int(ps[0].line)!=int(pr[0].line) or int(ps[0].column)!=int(pr[0].column):
  cocci.print_main(fld,p0)
// </smpl>

Signed-off-by: Julia Lawall <julia@diku.dk>

---
 drivers/net/ehea/ehea_main.c |    1 -
 drivers/net/sunvnet.c        |    1 -
 2 files changed, 2 deletions(-)

diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c
index f1e5e45..bc74db0 100644
--- a/drivers/net/sunvnet.c
+++ b/drivers/net/sunvnet.c
@@ -1016,7 +1016,6 @@ static const struct net_device_ops vnet_ops = {
 	.ndo_open		= vnet_open,
 	.ndo_stop		= vnet_close,
 	.ndo_set_multicast_list	= vnet_set_rx_mode,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_set_mac_address	= vnet_set_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_tx_timeout		= vnet_tx_timeout,
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 977c3d3..41bd7ae 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -3083,7 +3083,6 @@ static const struct net_device_ops ehea_netdev_ops = {
 	.ndo_poll_controller	= ehea_netpoll,
 #endif
 	.ndo_get_stats		= ehea_get_stats,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_set_mac_address	= ehea_set_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_multicast_list	= ehea_set_multicast_list,

^ permalink raw reply related

* Re: [PATCH] atm: dereference of he_dev->rbps_virt in he_init_group()
From: Joe Perches @ 2009-09-19 18:27 UTC (permalink / raw)
  To: Roel Kluin; +Cc: David Miller, chas, linux-atm-general, netdev, akpm
In-Reply-To: <4AB51FE7.7030509@gmail.com>

On Sat, 2009-09-19 at 20:16 +0200, Roel Kluin wrote:
> +	int i, ret;
> +		ret = -ENOMEM;
> +		ret = -ENOMEM;
> +			ret = -ENOMEM;
> +		ret = -ENOMEM;
> +		ret = -ENOMEM;
> +		ret = -ENOMEM;
> +		ret = -ENOMEM;
> +		ret = -ENOMEM;
> +out_destroy_rbps_pool:
> +	pci_pool_destroy(he_dev->rbps_pool);
> +	return ret;

It looks as if it'd be clearer to not use variable ret and
simply return -ENOMEM after the out_destroy_rbps_pool label.



^ permalink raw reply

* [PATCH] atm: dereference of he_dev->rbps_virt in he_init_group()
From: Roel Kluin @ 2009-09-19 18:16 UTC (permalink / raw)
  To: David Miller; +Cc: chas, linux-atm-general, netdev, akpm
In-Reply-To: <20090911.125135.148893888.davem@davemloft.net>

he_dev->rbps_virt or he_dev->rbpl_virt allocation may fail, s
them. Make sure that he_init_group() cleans up after errors.

Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
---
Found with sed: http://kernelnewbies.org/roelkluin

This version was build, sparse and checkpatch tested.

diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index 2de6406..00fd67e 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -777,7 +777,7 @@ he_init_cs_block_rcm(struct he_dev *he_dev)
 static int __devinit
 he_init_group(struct he_dev *he_dev, int group)
 {
-	int i;
+	int i, ret;
 
 	/* small buffer pool */
 	he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev,
@@ -790,19 +790,27 @@ he_init_group(struct he_dev *he_dev, int group)
 	he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev,
 		CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys);
 	if (he_dev->rbps_base == NULL) {
-		hprintk("failed to alloc rbps\n");
-		return -ENOMEM;
+		hprintk("failed to alloc rbps_base\n");
+		ret = -ENOMEM;
+		goto out_destroy_rbps_pool;
 	}
 	memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp));
 	he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL);
+	if (he_dev->rbps_virt == NULL) {
+		hprintk("failed to alloc rbps_virt\n");
+		ret = -ENOMEM;
+		goto out_free_rbps_base;
+	}
 
 	for (i = 0; i < CONFIG_RBPS_SIZE; ++i) {
 		dma_addr_t dma_handle;
 		void *cpuaddr;
 
 		cpuaddr = pci_pool_alloc(he_dev->rbps_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
-		if (cpuaddr == NULL)
-			return -ENOMEM;
+		if (cpuaddr == NULL) {
+			ret = -ENOMEM;
+			goto out_free_rbps_virt;
+		}
 
 		he_dev->rbps_virt[i].virt = cpuaddr;
 		he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF);
@@ -827,25 +835,34 @@ he_init_group(struct he_dev *he_dev, int group)
 			CONFIG_RBPL_BUFSIZE, 8, 0);
 	if (he_dev->rbpl_pool == NULL) {
 		hprintk("unable to create rbpl pool\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto out_free_rbps_virt;
 	}
 
 	he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev,
 		CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys);
 	if (he_dev->rbpl_base == NULL) {
-		hprintk("failed to alloc rbpl\n");
-		return -ENOMEM;
+		hprintk("failed to alloc rbpl_base\n");
+		ret = -ENOMEM;
+		goto out_destroy_rbpl_pool;
 	}
 	memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp));
 	he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL);
+	if (he_dev->rbpl_virt == NULL) {
+		hprintk("failed to alloc rbpl_virt\n");
+		ret = -ENOMEM;
+		goto out_free_rbpl_base;
+	}
 
 	for (i = 0; i < CONFIG_RBPL_SIZE; ++i) {
 		dma_addr_t dma_handle;
 		void *cpuaddr;
 
 		cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
-		if (cpuaddr == NULL)
-			return -ENOMEM;
+		if (cpuaddr == NULL) {
+			ret = -ENOMEM;
+			goto out_free_rbpl_virt;
+		}
 
 		he_dev->rbpl_virt[i].virt = cpuaddr;
 		he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF);
@@ -870,7 +887,8 @@ he_init_group(struct he_dev *he_dev, int group)
 		CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys);
 	if (he_dev->rbrq_base == NULL) {
 		hprintk("failed to allocate rbrq\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto out_free_rbpl_virt;
 	}
 	memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq));
 
@@ -894,7 +912,8 @@ he_init_group(struct he_dev *he_dev, int group)
 		CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys);
 	if (he_dev->tbrq_base == NULL) {
 		hprintk("failed to allocate tbrq\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto out_free_rbpq_base;
 	}
 	memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq));
 
@@ -906,6 +925,39 @@ he_init_group(struct he_dev *he_dev, int group)
 	he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16));
 
 	return 0;
+
+out_free_rbpq_base:
+	pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE *
+			sizeof(struct he_rbrq), he_dev->rbrq_base,
+			he_dev->rbrq_phys);
+	i = CONFIG_RBPL_SIZE;
+out_free_rbpl_virt:
+	while (--i)
+		pci_pool_free(he_dev->rbps_pool, he_dev->rbpl_virt[i].virt,
+				he_dev->rbps_base[i].phys);
+	kfree(he_dev->rbpl_virt);
+
+out_free_rbpl_base:
+	pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE *
+			sizeof(struct he_rbp), he_dev->rbpl_base,
+			he_dev->rbpl_phys);
+out_destroy_rbpl_pool:
+	pci_pool_destroy(he_dev->rbpl_pool);
+
+	i = CONFIG_RBPL_SIZE;
+out_free_rbps_virt:
+	while (--i)
+		pci_pool_free(he_dev->rbpl_pool, he_dev->rbps_virt[i].virt,
+				he_dev->rbpl_base[i].phys);
+	kfree(he_dev->rbps_virt);
+
+out_free_rbps_base:
+	pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE *
+			sizeof(struct he_rbp), he_dev->rbps_base,
+			he_dev->rbps_phys);
+out_destroy_rbps_pool:
+	pci_pool_destroy(he_dev->rbps_pool);
+	return ret;
 }
 
 static int __devinit

^ permalink raw reply related

* SO_TIMESTAMPING fix and design decisions
From: Christopher Zimmermann @ 2009-09-19 17:25 UTC (permalink / raw)
  To: netdev


[-- Attachment #1.1: Type: text/plain, Size: 3049 bytes --]

Hi, 

I'm currently working on the SO_TIMESTAMPING feature which is currently 
pretty much broken. The current status is the following:

-tx software timestamps don't work because of a race condition. See 
commit cd4d8fdad1f1320.
-rx software timestamps do work. But they are nothing new.
SO_TIMESTAMP[NS] has been available for years.

hardware timestamps only work for the Intel igb driver. I have access to 
two test machines with NICs supported by this driver.

-tx hardware timestamps do work. I still have to check what happens when 
there is high load of packets requesting timestamping.
-rx hardware timestamps work only for special PTP (Precision Time 
Protocol) packets. There exists a HWTSTAMP_FILTER_ALL option to 
timestamp all packets, but it doesn't work and it will not work. This is 
due to a problem in the hardware design. The Intel hardware is tuned for 
PTP (and so is the ioctl interface).


Right now I'm trying to fix the software tx timestamps. I see several 
ways to fix it:

-Do skb_get() before calling ops->ndo_start_xmit(). This breaks the 
wireless stack, because it is incompatible with pskb_expand_head().

-Do skb_clone() and skb_set_owner_w() before calling 
ops->ndo_start_xmit(). If the driver promises to do timestamping 
(shtx->in_progress==1), then this clone will be abandoned. -> Software 
timestamps only as fallback.

-Do skb_clone() and skb_set_owner_w() before calling 
ops->ndo_start_xmit(). Use this to send the software timestamp 
regardless of what the driver is doing. This results in software 
timestamps being always generated. Not only as fallback. The drawback is 
that userspace will eventually have to parse two timestamping messages 
(only if requested). This is not a big deal.

I chose the last option since it is easiest to implement without much 
interaction with the driver. Patch is attached. Any comments or ideas 
for a better implementation are welcome.
Currently the tx timestamp is returned with the whole packet, including 
all transport layer headers. I would like to return only the payload, 
since this would make the interface easier for userspace. There is 
nothing like a "payload" pointer in the sk_buff. How can I solve this? 
Add such a pointer?


To fix the hardware rx timestamps my idea is to change the ioctl 
interface, so that it allows userspace to fine tune the relevant 
hardware registers of the intel controler. This would allow hardware 
timestamps to be used in other scenarios than just for PTP.
I don't know any application which already uses this interface right 
now. But if there is one it would be easy to fix.
In case there appear some other controlers with timestamping support 
they will either need their own custom interface (if they are similarly 
limited) or they can just go without the ioctl interface and do hardware 
timestamping of all received packages if they are not so limited.

Could this be a way to go or what would you suggest?


Regards, 

Christopher Zimmermann

[-- Attachment #1.2: patch --]
[-- Type: application/octet-stream, Size: 4924 bytes --]

commit fe7b307ab374a495feba8c951fb7da2518a4e422
Author: Christopher Zimmermann <madroach@zakweb.de>
Date:   Sat Sep 19 19:21:28 2009 +0200

    net: Implement timestamping
    
    Avoid the skb_clone, skb_hold and software fallback problems by
    returning two seperate messages to userspace. One for software and one
    for hardware timestamp.

diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index d2639c4..1bdce95 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -4435,7 +4435,7 @@ static void igb_tx_hwtstamp(struct igb_adapter *adapter, struct sk_buff *skb)
 			shhwtstamps.hwtstamp = ns_to_ktime(ns);
 			shhwtstamps.syststamp =
 				timecompare_transform(&adapter->compare, ns);
-			skb_tstamp_tx(skb, &shhwtstamps);
+			skb_tstamp_hw_tx(skb, &shhwtstamps);
 		}
 	}
 }
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index df7b23a..315a4c4 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1868,7 +1868,7 @@ static inline ktime_t net_invalid_timestamp(void)
 }
 
 /**
- * skb_tstamp_tx - queue clone of skb with send time stamps
+ * skb_tstamp_tx - queue clone of skb with hardware send time stamps
  * @orig_skb:	the original outgoing packet
  * @hwtstamps:	hardware time stamps, may be NULL if not available
  *
@@ -1878,9 +1878,21 @@ static inline ktime_t net_invalid_timestamp(void)
  * generates a software time stamp (otherwise), then queues the clone
  * to the error queue of the socket.  Errors are silently ignored.
  */
-extern void skb_tstamp_tx(struct sk_buff *orig_skb,
+extern void skb_tstamp_hw_tx(struct sk_buff *orig_skb,
 			struct skb_shared_hwtstamps *hwtstamps);
 
+/**
+ * skb_tstamp_tx - queue clone of skb with software generated send time stamps
+ * @orig_skb:	the original outgoing packet
+ *
+ * If the skb has a socket associated, then this function clones the
+ * skb (thus sharing the actual data and optional structures), generates a
+ * software time stamp, then queues the clone to the error queue of the socket.
+ * Errors are silently ignored.
+ */
+extern void skb_tstamp_tx(struct sk_buff *skb);
+			
+
 extern __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len);
 extern __sum16 __skb_checksum_complete(struct sk_buff *skb);
 
diff --git a/net/core/dev.c b/net/core/dev.c
index 560c8c9..c04d3dd 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1701,6 +1701,16 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
 {
 	const struct net_device_ops *ops = dev->netdev_ops;
 	int rc;
+	struct sk_buff *skb_tstamp = NULL;
+
+	if (unlikely(skb_tx(skb)->software && skb->sk)) {
+		skb_tstamp = skb_clone(skb, 0);
+
+		/* TODO: Is a sock_hold() needed here?
+		 * skb_set_owner_w doesn't do it. */
+		if (likely(skb_tstamp))
+		    	skb_set_owner_w(skb_tstamp, skb->sk);
+	}
 
 	if (likely(!skb->next)) {
 		if (!list_empty(&ptype_all))
@@ -1721,8 +1731,11 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
 			skb_dst_drop(skb);
 
 		rc = ops->ndo_start_xmit(skb, dev);
-		if (rc == NETDEV_TX_OK)
+		if (rc == NETDEV_TX_OK) {
+			if (unlikely(skb_tstamp))
+				skb_tstamp_tx(skb_tstamp);
 			txq_trans_update(txq);
+		}
 		/*
 		 * TODO: if skb_orphan() was called by
 		 * dev->hard_start_xmit() (for example, the unmodified
@@ -1752,6 +1765,8 @@ gso:
 			skb->next = nskb;
 			return rc;
 		}
+		if (unlikely(skb_tstamp))
+			skb_tstamp_tx(skb_tstamp);
 		txq_trans_update(txq);
 		if (unlikely(netif_tx_queue_stopped(txq) && skb->next))
 			return NETDEV_TX_BUSY;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 80a9616..1517a5e 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2967,7 +2967,7 @@ int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer)
 }
 EXPORT_SYMBOL_GPL(skb_cow_data);
 
-void skb_tstamp_tx(struct sk_buff *orig_skb,
+void skb_tstamp_hw_tx(struct sk_buff *orig_skb,
 		struct skb_shared_hwtstamps *hwtstamps)
 {
 	struct sock *sk = orig_skb->sk;
@@ -2982,17 +2982,9 @@ void skb_tstamp_tx(struct sk_buff *orig_skb,
 	if (!skb)
 		return;
 
-	if (hwtstamps) {
+	if (hwtstamps)
 		*skb_hwtstamps(skb) =
 			*hwtstamps;
-	} else {
-		/*
-		 * no hardware time stamps available,
-		 * so keep the skb_shared_tx and only
-		 * store software time stamp
-		 */
-		skb->tstamp = ktime_get_real();
-	}
 
 	serr = SKB_EXT_ERR(skb);
 	memset(serr, 0, sizeof(*serr));
@@ -3002,6 +2994,23 @@ void skb_tstamp_tx(struct sk_buff *orig_skb,
 	if (err)
 		kfree_skb(skb);
 }
+EXPORT_SYMBOL_GPL(skb_tstamp_hw_tx);
+
+void skb_tstamp_tx(struct sk_buff *skb)
+{
+	struct sock_exterr_skb *serr;
+	int err;
+
+	skb->tstamp = ktime_get_real();
+
+	serr = SKB_EXT_ERR(skb);
+	memset(serr, 0, sizeof(*serr));
+	serr->ee.ee_errno = ENOMSG;
+	serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
+	err = sock_queue_err_skb(skb->sk, skb);
+	if (err)
+		kfree_skb(skb);
+}
 EXPORT_SYMBOL_GPL(skb_tstamp_tx);
 
 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply related

* [iproute2 PATCH] Add 'ip tuntap' support.
From: David Woodhouse @ 2009-09-19 16:48 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev

This patch provides support for 'ip tuntap', allowing creation and
deletion of persistent tun/tap devices.

diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h
new file mode 100644
index 0000000..915ba57
--- /dev/null
+++ b/include/linux/if_tun.h
@@ -0,0 +1,88 @@
+/*
+ *  Universal TUN/TAP device driver.
+ *  Copyright (C) 1999-2000 Maxim Krasnyansky <max_mk@yahoo.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ */
+
+#ifndef __IF_TUN_H
+#define __IF_TUN_H
+
+#include <linux/types.h>
+#include <linux/if_ether.h>
+
+/* Read queue size */
+#define TUN_READQ_SIZE	500
+
+/* TUN device flags */
+#define TUN_TUN_DEV 	0x0001	
+#define TUN_TAP_DEV	0x0002
+#define TUN_TYPE_MASK   0x000f
+
+#define TUN_FASYNC	0x0010
+#define TUN_NOCHECKSUM	0x0020
+#define TUN_NO_PI	0x0040
+#define TUN_ONE_QUEUE	0x0080
+#define TUN_PERSIST 	0x0100	
+#define TUN_VNET_HDR 	0x0200
+
+/* Ioctl defines */
+#define TUNSETNOCSUM  _IOW('T', 200, int) 
+#define TUNSETDEBUG   _IOW('T', 201, int) 
+#define TUNSETIFF     _IOW('T', 202, int) 
+#define TUNSETPERSIST _IOW('T', 203, int) 
+#define TUNSETOWNER   _IOW('T', 204, int)
+#define TUNSETLINK    _IOW('T', 205, int)
+#define TUNSETGROUP   _IOW('T', 206, int)
+#define TUNGETFEATURES _IOR('T', 207, unsigned int)
+#define TUNSETOFFLOAD  _IOW('T', 208, unsigned int)
+#define TUNSETTXFILTER _IOW('T', 209, unsigned int)
+#define TUNGETIFF      _IOR('T', 210, unsigned int)
+#define TUNGETSNDBUF   _IOR('T', 211, int)
+#define TUNSETSNDBUF   _IOW('T', 212, int)
+
+/* TUNSETIFF ifr flags */
+#define IFF_TUN		0x0001
+#define IFF_TAP		0x0002
+#define IFF_NO_PI	0x1000
+#define IFF_ONE_QUEUE	0x2000
+#define IFF_VNET_HDR	0x4000
+#define IFF_TUN_EXCL	0x8000
+
+/* Features for GSO (TUNSETOFFLOAD). */
+#define TUN_F_CSUM	0x01	/* You can hand me unchecksummed packets. */
+#define TUN_F_TSO4	0x02	/* I can handle TSO for IPv4 packets */
+#define TUN_F_TSO6	0x04	/* I can handle TSO for IPv6 packets */
+#define TUN_F_TSO_ECN	0x08	/* I can handle TSO with ECN bits. */
+
+/* Protocol info prepended to the packets (when IFF_NO_PI is not set) */
+#define TUN_PKT_STRIP	0x0001
+struct tun_pi {
+	__u16  flags;
+	__be16 proto;
+};
+
+/*
+ * Filter spec (used for SETXXFILTER ioctls)
+ * This stuff is applicable only to the TAP (Ethernet) devices.
+ * If the count is zero the filter is disabled and the driver accepts
+ * all packets (promisc mode).
+ * If the filter is enabled in order to accept broadcast packets
+ * broadcast addr must be explicitly included in the addr list.
+ */
+#define TUN_FLT_ALLMULTI 0x0001 /* Accept all multicast packets */
+struct tun_filter {
+	__u16  flags; /* TUN_FLT_ flags see above */
+	__u16  count; /* Number of addresses */
+	__u8   addr[0][ETH_ALEN];
+};
+
+#endif /* __IF_TUN_H */
diff --git a/ip/Makefile b/ip/Makefile
index 3c185cf..fd16fe9 100644
--- a/ip/Makefile
+++ b/ip/Makefile
@@ -1,6 +1,6 @@
 IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o \
     rtm_map.o iptunnel.o ip6tunnel.o tunnel.o ipneigh.o ipntable.o iplink.o \
-    ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o \
+    ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o iptuntap.o \
     ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \
     iplink_vlan.o link_veth.o link_gre.o iplink_can.o
 
diff --git a/ip/ip.c b/ip/ip.c
index 2bd54b2..d846a76 100644
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -47,7 +47,7 @@ static void usage(void)
 "Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }\n"
 "       ip [ -force ] -batch filename\n"
 "where  OBJECT := { link | addr | addrlabel | route | rule | neigh | ntable |\n"
-"                   tunnel | maddr | mroute | monitor | xfrm }\n"
+"                   tunnel | tuntap | maddr | mroute | monitor | xfrm }\n"
 "       OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
 "                    -f[amily] { inet | inet6 | ipx | dnet | link } |\n"
 "                    -o[neline] | -t[imestamp] | -b[atch] [filename] }\n");
@@ -75,6 +75,8 @@ static const struct cmd {
 	{ "link",	do_iplink },
 	{ "tunnel",	do_iptunnel },
 	{ "tunl",	do_iptunnel },
+	{ "tuntap",	do_iptuntap },
+	{ "tap",	do_iptuntap },
 	{ "monitor",	do_ipmonitor },
 	{ "xfrm",	do_xfrm },
 	{ "mroute",	do_multiroute },
diff --git a/ip/ip_common.h b/ip/ip_common.h
index 273065f..c857667 100644
--- a/ip/ip_common.h
+++ b/ip/ip_common.h
@@ -32,6 +32,7 @@ extern int do_ipneigh(int argc, char **argv);
 extern int do_ipntable(int argc, char **argv);
 extern int do_iptunnel(int argc, char **argv);
 extern int do_ip6tunnel(int argc, char **argv);
+extern int do_iptuntap(int argc, char **argv);
 extern int do_iplink(int argc, char **argv);
 extern int do_ipmonitor(int argc, char **argv);
 extern int do_multiaddr(int argc, char **argv);
diff --git a/ip/iptuntap.c b/ip/iptuntap.c
new file mode 100644
index 0000000..f7f64bc
--- /dev/null
+++ b/ip/iptuntap.c
@@ -0,0 +1,321 @@
+/*
+ * iptunnel.c	       "ip tuntap"
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ * Authors:	David Woodhouse <David.Woodhouse@intel.com>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#include <pwd.h>
+#include <grp.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+
+#include "rt_names.h"
+#include "utils.h"
+#include "ip_common.h"
+
+#define TUNDEV "/dev/net/tun"
+
+static void usage(void) __attribute__((noreturn));
+
+static void usage(void)
+{
+	fprintf(stderr, "Usage: ip tuntap { add | del } [ dev PHYS_DEV ] \n");
+	fprintf(stderr, "          [ mode { tun | tap } ] [ user USER ] [ group GROUP ]\n");
+	fprintf(stderr, "          [ one_queue ] [ pi ] [ vnet_hdr ]\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "Where: USER  := { STRING | NUMBER }\n");
+	fprintf(stderr, "       GROUP := { STRING | NUMBER }\n");
+	exit(-1);
+}
+
+static int tap_add_ioctl(struct ifreq *ifr, uid_t uid, gid_t gid)
+{
+	int fd = open(TUNDEV, O_RDWR);
+	int ret = -1;
+
+	ifr->ifr_flags |= IFF_TUN_EXCL;
+
+	fd = open(TUNDEV, O_RDWR);
+	if (fd < 0) {
+		perror("open");
+		return -1;
+	}
+	if (ioctl(fd, TUNSETIFF, ifr)) {
+		perror("ioctl(TUNSETIFF)");
+		goto out;
+	}
+	if (uid != -1 && ioctl(fd, TUNSETOWNER, uid)) {
+		perror("ioctl(TUNSETOWNER)");
+		goto out;
+	}
+	if (gid != -1 && ioctl(fd, TUNSETGROUP, gid)) {
+		perror("ioctl(TUNSETGROUP)");
+		goto out;
+	}
+	if (ioctl(fd, TUNSETPERSIST, 1)) {
+		perror("ioctl(TUNSETPERSIST)");
+		goto out;
+	}
+	ret = 0;
+ out:
+	close(fd);
+	return ret;
+}
+
+static int tap_del_ioctl(struct ifreq *ifr)
+{
+	int fd = open(TUNDEV, O_RDWR);
+	int ret = -1;
+
+	if (fd < 0) {
+		perror("open");
+		return -1;
+	}
+	if (ioctl(fd, TUNSETIFF, ifr)) {
+		perror("ioctl(TUNSETIFF)");
+		goto out;
+	}
+	if (ioctl(fd, TUNSETPERSIST, 0)) {
+		perror("ioctl(TUNSETPERSIST)");
+		goto out;
+	}
+	ret = 0;
+ out:
+	close(fd);
+	return ret;
+	
+}
+static int parse_args(int argc, char **argv, struct ifreq *ifr, uid_t *uid, gid_t *gid)
+{
+	int count = 0;
+
+	memset(ifr, 0, sizeof(*ifr));
+
+	ifr->ifr_flags |= IFF_NO_PI;
+
+	while (argc > 0) {
+		if (matches(*argv, "mode") == 0) {
+			NEXT_ARG();
+			if (matches(*argv, "tun") == 0) {
+				if (ifr->ifr_flags & IFF_TAP) {
+					fprintf(stderr,"You managed to ask for more than one tunnel mode.\n");
+					exit(-1);
+				}
+				ifr->ifr_flags |= IFF_TUN;
+			} else if (matches(*argv, "tap") == 0) {
+				if (ifr->ifr_flags & IFF_TUN) {
+					fprintf(stderr,"You managed to ask for more than one tunnel mode.\n");
+					exit(-1);
+				}
+				ifr->ifr_flags |= IFF_TAP;
+			} else {
+				fprintf(stderr,"Cannot guess tunnel mode.\n");
+				exit(-1);
+			}
+		} else if (uid && matches(*argv, "user") == 0) {
+			char *end;
+			unsigned long user;
+
+			NEXT_ARG();
+			if (**argv && ((user = strtol(*argv, &end, 10)), !*end))
+				*uid = user;
+			else {
+				struct passwd *pw = getpwnam(*argv);
+				if (!pw) {
+					fprintf(stderr, "invalid user \"%s\"\n", *argv);
+					exit(-1);
+				}
+				*uid = pw->pw_uid;
+			}
+		} else if (gid && matches(*argv, "group") == 0) {
+			char *end;
+			unsigned long group;
+
+			NEXT_ARG();
+			
+			if (**argv && ((group = strtol(*argv, &end, 10)), !*end))
+				*gid = group;
+			else {
+				struct group *gr = getgrnam(*argv);
+				if (!gr) {
+					fprintf(stderr, "invalid group \"%s\"\n", *argv);
+					exit(-1);
+				}
+				*gid = gr->gr_gid;
+			}
+		} else if (matches(*argv, "pi") == 0) {
+			ifr->ifr_flags &= ~IFF_NO_PI;
+		} else if (matches(*argv, "one_queue") == 0) {
+			ifr->ifr_flags |= IFF_ONE_QUEUE;
+		} else if (matches(*argv, "vnet_hdr") == 0) {
+			ifr->ifr_flags |= IFF_VNET_HDR;
+		} else if (matches(*argv, "dev") == 0) {
+			NEXT_ARG();
+			strncpy(ifr->ifr_name, *argv, IFNAMSIZ-1);
+		} else {
+			if (matches(*argv, "name") == 0) {
+				NEXT_ARG();
+			} else if (matches(*argv, "help") == 0)
+				usage();
+			if (ifr->ifr_name[0])
+				duparg2("name", *argv);
+			strncpy(ifr->ifr_name, *argv, IFNAMSIZ);
+		}
+		count++;
+		argc--; argv++;
+	}
+
+	return 0;
+}
+
+
+static int do_add(int argc, char **argv)
+{
+	struct ifreq ifr;
+	uid_t uid = -1;
+	gid_t gid = -1;
+
+	if (parse_args(argc, argv, &ifr, &uid, &gid) < 0)
+		return -1;
+
+	if (!(ifr.ifr_flags & TUN_TYPE_MASK)) {
+		fprintf(stderr, "You failed to specify a tunnel mode\n");
+		return -1;
+	}
+	return tap_add_ioctl(&ifr, uid, gid);
+}
+
+static int do_del(int argc, char **argv)
+{
+	struct ifreq ifr;
+
+	if (parse_args(argc, argv, &ifr, NULL, NULL) < 0)
+		return -1;
+
+	return tap_del_ioctl(&ifr);
+}
+
+static int read_prop(char *dev, char *prop, long *value)
+{
+	char fname[IFNAMSIZ+25], buf[80], *endp;
+	ssize_t len;
+	int fd;
+	long result;
+
+	sprintf(fname, "/sys/class/net/%s/%s", dev, prop);
+	fd = open(fname, O_RDONLY);
+	if (fd < 0) {
+		if (strcmp(prop, "tun_flags"))
+			fprintf(stderr, "open %s: %s\n", fname,
+				strerror(errno));
+		return -1;
+	}
+	len = read(fd, buf, sizeof(buf)-1);
+	close(fd);
+	if (len < 0) {
+		fprintf(stderr, "read %s: %s", fname, strerror(errno));
+		return -1;
+	}
+
+	buf[len] = 0;
+	result = strtol(buf, &endp, 0);
+	if (*endp != '\n') {
+		fprintf(stderr, "Failed to parse %s\n", fname);
+		return -1;
+	}
+	*value = result;
+	return 0;
+}
+
+static void print_flags(long flags)
+{
+	if (flags & IFF_TUN)
+		printf(" tun");
+
+	if (flags & IFF_TAP)
+		printf(" tap");
+
+	if (!(flags & IFF_NO_PI))
+		printf(" pi");
+
+	if (flags & IFF_ONE_QUEUE)
+		printf(" one_queue");
+
+	if (flags & IFF_VNET_HDR)
+		printf(" vnet_hdr");
+
+	flags &= ~(IFF_TUN|IFF_TAP|IFF_NO_PI|IFF_ONE_QUEUE|IFF_VNET_HDR);
+	if (flags)
+		printf(" UNKNOWN_FLAGS:%lx", flags);
+}
+
+static int do_show(int argc, char **argv)
+{
+	DIR *dir;
+	struct dirent *d;
+	long flags, owner = -1, group = -1;
+
+	dir = opendir("/sys/class/net");
+	if (!dir) {
+		perror("opendir");
+		return -1;
+	}
+	while ((d = readdir(dir))) {
+		if (d->d_name[0] == '.' &&
+		    (d->d_name[1] == 0 || d->d_name[1] == '.'))
+			continue;
+
+		if (read_prop(d->d_name, "tun_flags", &flags))
+			continue;
+
+		read_prop(d->d_name, "owner", &owner);
+		read_prop(d->d_name, "group", &group);
+		
+		printf("%s:", d->d_name);
+		print_flags(flags);
+		if (owner != -1)
+			printf(" user %ld", owner);
+		if (group != -1)
+			printf(" group %ld", group);
+		printf("\n");
+	}
+	return 0;
+}
+
+int do_iptuntap(int argc, char **argv)
+{
+	if (argc > 0) {
+		if (matches(*argv, "add") == 0)
+			return do_add(argc-1, argv+1);
+		if (matches(*argv, "del") == 0)
+			return do_del(argc-1, argv+1);
+		if (matches(*argv, "show") == 0 ||
+                    matches(*argv, "lst") == 0 ||
+                    matches(*argv, "list") == 0)
+                        return do_show(argc-1, argv+1);
+		if (matches(*argv, "help") == 0)
+			usage();
+	} else
+		return do_show(0, NULL);
+
+	fprintf(stderr, "Command \"%s\" is unknown, try \"ip tuntap help\".\n",
+		*argv);
+	exit(-1);
+}

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse@intel.com                              Intel Corporation


^ permalink raw reply related


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