Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH v2] drop_monitor: dont sleep in atomic context
From: David Miller @ 2012-06-04 15:42 UTC (permalink / raw)
  To: nhorman; +Cc: eric.dumazet, netdev
In-Reply-To: <20120604104937.GC20232@hmsreliant.think-freely.org>

From: Neil Horman <nhorman@tuxdriver.com>
Date: Mon, 4 Jun 2012 06:49:37 -0400

> On Mon, Jun 04, 2012 at 12:18:19PM +0200, Eric Dumazet wrote:
>> From: Eric Dumazet <edumazet@google.com>
>> 
>> drop_monitor calls several sleeping functions while in atomic context.
>> 
>>  BUG: sleeping function called from invalid context at mm/slub.c:943
>>  in_atomic(): 1, irqs_disabled(): 0, pid: 2103, name: kworker/0:2
>>  Pid: 2103, comm: kworker/0:2 Not tainted 3.5.0-rc1+ #55
>>  Call Trace:
>>   [<ffffffff810697ca>] __might_sleep+0xca/0xf0
>>   [<ffffffff811345a3>] kmem_cache_alloc_node+0x1b3/0x1c0
>>   [<ffffffff8105578c>] ? queue_delayed_work_on+0x11c/0x130
>>   [<ffffffff815343fb>] __alloc_skb+0x4b/0x230
>>   [<ffffffffa00b0360>] ? reset_per_cpu_data+0x160/0x160 [drop_monitor]
>>   [<ffffffffa00b022f>] reset_per_cpu_data+0x2f/0x160 [drop_monitor]
>>   [<ffffffffa00b03ab>] send_dm_alert+0x4b/0xb0 [drop_monitor]
>>   [<ffffffff810568e0>] process_one_work+0x130/0x4c0
>>   [<ffffffff81058249>] worker_thread+0x159/0x360
>>   [<ffffffff810580f0>] ? manage_workers.isra.27+0x240/0x240
>>   [<ffffffff8105d403>] kthread+0x93/0xa0
>>   [<ffffffff816be6d4>] kernel_thread_helper+0x4/0x10
>>   [<ffffffff8105d370>] ? kthread_freezable_should_stop+0x80/0x80
>>   [<ffffffff816be6d0>] ? gs_change+0xb/0xb
>> 
>> Rework the logic to call the sleeping functions in right context.
>> 
>> Use standard timer/workqueue api to let system chose any cpu to perform
>> the allocation and netlink send.
>> 
>> Also avoid a loop if reset_per_cpu_data() cannot allocate memory :
>> use mod_timer() to wait 1/10 second before next try.
>> 
>> Signed-off-by: Eric Dumazet <edumazet@google.com>
>> Cc: Neil Horman <nhorman@tuxdriver.com>
> Reviewed-by: Neil Horman <nhorman@tuxdriver.com>

Applied and queued up for -stable, thanks.

^ permalink raw reply

* Re: [PATCH] net/ethernet: ks8851_mll mac address configuration support added
From: David Miller @ 2012-06-04 15:43 UTC (permalink / raw)
  To: lamiaposta71; +Cc: netdev, adobriyan, thomas, raffaele.recalcati
In-Reply-To: <1338756223-7207-1-git-send-email-lamiaposta71@gmail.com>

From: Raffaele Recalcati <lamiaposta71@gmail.com>
Date: Sun,  3 Jun 2012 22:43:43 +0200

> From: Raffaele Recalcati <raffaele.recalcati@bticino.it>
> 
> Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>

Applied to net-next, thanks.

^ permalink raw reply

* Re: pull-request: can 2012-06-03
From: David Miller @ 2012-06-04 15:44 UTC (permalink / raw)
  To: mkl; +Cc: netdev, linux-can
In-Reply-To: <1338762120-12695-1-git-send-email-mkl@pengutronix.de>

From: Marc Kleine-Budde <mkl@pengutronix.de>
Date: Mon,  4 Jun 2012 00:21:56 +0200

> git@gitorious.org:linux-can/linux-can.git master

I can't pull from that tree.

[davem@bql net]$ git pull git@gitorious.org:linux-can/linux-can.git master
The authenticity of host 'gitorious.org (87.238.52.168)' can't be established.
RSA key fingerprint is 7e:af:8d:ec:f0:39:5e:ba:52:16:ce:19:fa:d4:b8:7d.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'gitorious.org,87.238.52.168' (RSA) to the list of known hosts.
Permission denied (publickey).
fatal: The remote end hung up unexpectedly

^ permalink raw reply

* Re: [PATCH] net: Remove casts to same type
From: David Miller @ 2012-06-04 15:45 UTC (permalink / raw)
  To: joe; +Cc: netdev
In-Reply-To: <4b3738493b23bc386d3372012faa8cd3672a138d.1338780551.git.joe@perches.com>

From: Joe Perches <joe@perches.com>
Date: Sun,  3 Jun 2012 20:41:40 -0700

> Adding casts of objects to the same type is unnecessary
> and confusing for a human reader.
> 
> For example, this cast:
> 
> 	int y;
> 	int *p = (int *)&y;
> 
> I used the coccinelle script below to find and remove these
> unnecessary casts.  I manually removed the conversions this
> script produces of casts with __force and __user.
> 
> @@
> type T;
> T *p;
> @@
> 
> -	(T *)p
> +	p
> 
> Signed-off-by: Joe Perches <joe@perches.com>

Applied to net-next, thanks Joe.

^ permalink raw reply

* Re: pull-request: can 2012-06-03
From: Marc Kleine-Budde @ 2012-06-04 15:46 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-can
In-Reply-To: <20120604.114443.2116610445330624803.davem@davemloft.net>

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

On 06/04/2012 05:44 PM, David Miller wrote:
> From: Marc Kleine-Budde <mkl@pengutronix.de>
> Date: Mon,  4 Jun 2012 00:21:56 +0200
> 
>> git@gitorious.org:linux-can/linux-can.git master
> 
> I can't pull from that tree.
> 
> [davem@bql net]$ git pull git@gitorious.org:linux-can/linux-can.git master
> The authenticity of host 'gitorious.org (87.238.52.168)' can't be established.
> RSA key fingerprint is 7e:af:8d:ec:f0:39:5e:ba:52:16:ce:19:fa:d4:b8:7d.
> Are you sure you want to continue connecting (yes/no)? yes
> Warning: Permanently added 'gitorious.org,87.238.52.168' (RSA) to the list of known hosts.
> Permission denied (publickey).
> fatal: The remote end hung up unexpectedly

Doh,

git://gitorious.org/linux-can/linux-can.git master

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply

* Re: [PATCH 1/1] net/hyperv: Use wait_event on outstanding sends during device removal
From: David Miller @ 2012-06-04 15:48 UTC (permalink / raw)
  To: haiyangz; +Cc: netdev, kys, olaf, linux-kernel, devel
In-Reply-To: <1338820532-2345-2-git-send-email-haiyangz@microsoft.com>

From: Haiyang Zhang <haiyangz@microsoft.com>
Date: Mon,  4 Jun 2012 07:35:32 -0700

> +	wait_event(net_device->wait_drain,
> +		atomic_read(&net_device->num_outstanding_sends) == 0);

Please indent this properly.  The goal is not to indent using only
TAB characters, the goal is to line things up to the proper column
using TAB and space characters as needed.

You must make the first character on the second line be at the
first column after the openning parenthesis on the previous line.

^ permalink raw reply

* Re: [PATCH (net.git) 1/4] stmmac: remove two useless initialisation
From: David Miller @ 2012-06-04 15:49 UTC (permalink / raw)
  To: peppe.cavallaro; +Cc: netdev
In-Reply-To: <1338824270-9222-2-git-send-email-peppe.cavallaro@st.com>

From: Giuseppe CAVALLARO <peppe.cavallaro@st.com>
Date: Mon,  4 Jun 2012 17:37:47 +0200

> This patch removes two useful initialisation in the
> stmmac_rx and stmmac_tx function.
> In the former, count var was already reset and in the
> stmmac_tx we only need to increment the dirty pointer
> w/o setting the entry var.
> 
> Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>

There are so many problems with this patch I do not know where
to start.

Your subject line says the initializations are "useless" yet
your commit message says they are "useful".

This is a cleanup, and does not fix any bugs, and is therefore
absolutely not appropriate for the 'net' tree.

I'm tossing this entire series, you need to be more careful
with your submissions.

^ permalink raw reply

* Re: [PATCH 0/1] net/hyperv: Use wait_event on outstanding sends during device removal
From: David Miller @ 2012-06-04 15:51 UTC (permalink / raw)
  To: haiyangz; +Cc: netdev, kys, olaf, linux-kernel, devel
In-Reply-To: <1338820532-2345-1-git-send-email-haiyangz@microsoft.com>

From: Haiyang Zhang <haiyangz@microsoft.com>
Date: Mon,  4 Jun 2012 07:35:31 -0700

> This patch is targeting net-next tree (when it's available for check in).
> 
> Haiyang Zhang (1):
>   net/hyperv: Use wait_event on outstanding sends during device removal

Why in the world are you doing this?

This patch you are already asking me to apply to the 'net' tree, and
changes already will automatically propagate from 'net' to
'net-next' the next time I merge those trees.

So you never need to submit bug fixes twice, once for 'net' and
once for 'net-next' so please do not do it.

^ permalink raw reply

* [PATCH (net.git)] net: icplus: fix interrupt mask
From: Giuseppe CAVALLARO @ 2012-06-04 15:51 UTC (permalink / raw)
  To: netdev; +Cc: Giuseppe Cavallaro

This patch fixes the interrupt mask for IC101 A/G devices
and now enables the link/speed/duplex interrupts.
This is done by setting the "INTR pin used" bit and cleaning
all the other bits in the Register 17.

Reported-by: Stuart Menefy <stuart.menefy@st.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/phy/icplus.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
index 5ac46f5..47f8e89 100644
--- a/drivers/net/phy/icplus.c
+++ b/drivers/net/phy/icplus.c
@@ -41,6 +41,8 @@ MODULE_LICENSE("GPL");
 #define IP1001_APS_ON			11	/* IP1001 APS Mode  bit */
 #define IP101A_G_APS_ON			2	/* IP101A/G APS Mode bit */
 #define IP101A_G_IRQ_CONF_STATUS	0x11	/* Conf Info IRQ & Status Reg */
+#define	IP101A_G_IRQ_PIN_USED		(1<<15) /* INTR pin used */
+#define	IP101A_G_IRQ_DEFAULT		IP101A_G_IRQ_PIN_USED
 
 static int ip175c_config_init(struct phy_device *phydev)
 {
@@ -136,6 +138,11 @@ static int ip1001_config_init(struct phy_device *phydev)
 	if (c < 0)
 		return c;
 
+	/* INTR pin used: speed/link/duplex will cause an interrupt */
+	c = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, IP101A_G_IRQ_DEFAULT);
+	if (c < 0)
+		return c;
+
 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
 		/* Additional delay (2ns) used to adjust RX clock phase
 		 * at RGMII interface */
-- 
1.7.4.4

^ permalink raw reply related

* Re: pull-request: can 2012-06-03
From: David Miller @ 2012-06-04 15:51 UTC (permalink / raw)
  To: mkl; +Cc: netdev, linux-can
In-Reply-To: <4FCCD86F.40007@pengutronix.de>

From: Marc Kleine-Budde <mkl@pengutronix.de>
Date: Mon, 04 Jun 2012 17:46:55 +0200

> On 06/04/2012 05:44 PM, David Miller wrote:
>> From: Marc Kleine-Budde <mkl@pengutronix.de>
>> Date: Mon,  4 Jun 2012 00:21:56 +0200
>> 
>>> git@gitorious.org:linux-can/linux-can.git master
>> 
>> I can't pull from that tree.
>> 
>> [davem@bql net]$ git pull git@gitorious.org:linux-can/linux-can.git master
>> The authenticity of host 'gitorious.org (87.238.52.168)' can't be established.
>> RSA key fingerprint is 7e:af:8d:ec:f0:39:5e:ba:52:16:ce:19:fa:d4:b8:7d.
>> Are you sure you want to continue connecting (yes/no)? yes
>> Warning: Permanently added 'gitorious.org,87.238.52.168' (RSA) to the list of known hosts.
>> Permission denied (publickey).
>> fatal: The remote end hung up unexpectedly
> 
> Doh,
> 
> git://gitorious.org/linux-can/linux-can.git master

Pulled, thanks.

^ permalink raw reply

* Re: pull-request: can-next 2012-06-04
From: Marc Kleine-Budde @ 2012-06-04 15:52 UTC (permalink / raw)
  To: davem; +Cc: Linux Netdev List, linux-can@vger.kernel.org
In-Reply-To: <4FCBEAAB.90708@pengutronix.de>

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

On 06/04/2012 12:52 AM, Marc Kleine-Budde wrote:
> Hello David,
> 
> here are the first patches for net-next, they add power management
> support for the flexcan driver and clarify the documentation with
> respect to error messages.
> 
> regards, Marc
> 
> ---
> 
> The following changes since commit 31a67102f4762df5544bc2dfb34a931233d2a5b2:
> 
>   Fix blocking allocations called very early during bootup (2012-05-21 12:52:42 -0700)
> 
> are available in the git repository at:
>   git@gitorious.org:linux-can/linux-can-next.git master

That should be:

git://gitorious.org/linux-can/linux-can-next.git master

Sorry for the noise,
Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply

* Re: [PATCH] net: Remove casts to same type
From: Joe Perches @ 2012-06-04 15:52 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20120604.114533.1720204611284591292.davem@davemloft.net>

On Mon, 2012-06-04 at 11:45 -0400, David Miller wrote:
> From: Joe Perches <joe@perches.com>
> > Adding casts of objects to the same type is unnecessary
> > and confusing for a human reader.
[]
> > I used the coccinelle script below to find and remove these
> > unnecessary casts.  I manually removed the conversions this
> > script produces of casts with __force and __user.
> > 
> > @@
> > type T;
> > T *p;
> > @@
> > 
> > -	(T *)p
> > +	p
> Applied to net-next, thanks Joe.

Do you want the same thing for drivers/net?

It's pretty big and might be better broken into
commits by maintainer/directory.

^ permalink raw reply

* Re: [PATCH] net: Remove casts to same type
From: David Miller @ 2012-06-04 15:53 UTC (permalink / raw)
  To: joe; +Cc: netdev
In-Reply-To: <1338825128.8574.15.camel@joe2Laptop>

From: Joe Perches <joe@perches.com>
Date: Mon, 04 Jun 2012 08:52:08 -0700

> On Mon, 2012-06-04 at 11:45 -0400, David Miller wrote:
>> From: Joe Perches <joe@perches.com>
>> > Adding casts of objects to the same type is unnecessary
>> > and confusing for a human reader.
> []
>> > I used the coccinelle script below to find and remove these
>> > unnecessary casts.  I manually removed the conversions this
>> > script produces of casts with __force and __user.
>> > 
>> > @@
>> > type T;
>> > T *p;
>> > @@
>> > 
>> > -	(T *)p
>> > +	p
>> Applied to net-next, thanks Joe.
> 
> Do you want the same thing for drivers/net?
> 
> It's pretty big and might be better broken into
> commits by maintainer/directory.

I don't see any value beyond perhaps splitting it into
drivers/net/ethernet, drivers/net/wireless, and "rest".

^ permalink raw reply

* Re: [PATCH RFC] c_can_pci: generic module for c_can on PCI
From: Alan Cox @ 2012-06-04 15:56 UTC (permalink / raw)
  To: Federico Vaga
  Cc: Wolfgang Grandegger, Marc Kleine-Budde, Giancarlo Asnaghi,
	Alan Cox, Alessandro Rubini, linux-can, netdev, linux-kernel
In-Reply-To: <1338816766-7089-2-git-send-email-federico.vaga@gmail.com>

> +enum c_can_pci_reg_align {
> +	C_CAN_REG_ALIGN_16,
> +	C_CAN_REG_ALIGN_32,
> +};

Anythign wrong with 

bool aligned32;

> +
> +struct c_can_pci_data {
> +	unsigned int reg_align;	/* Set the register alignment in the memory */

Not the enum .. indeed

> +static u16 c_can_pci_read_reg_aligned_to_16bit(struct c_can_priv *priv,
> +						void *reg)

I'm a bit worried this function name might be too short ;)


> +	dev_info(&pdev->dev, "%s device registered (regs=%p, irq=%d)\n",
> +		 KBUILD_MODNAME, priv->regs, dev->irq);

dev_dbg

> +	 * do not call pci_disable_device on sta2x11 because it
> +	 * break all other Bus masters on this EP
> +	 */
> +	if(pdev->vendor == PCI_VENDOR_ID_STMICRO &&
> +	   pdev->device == PCI_DEVICE_ID_STMICRO_CAN)
> +		goto out;

Is that the disabling or the dropping it into D3. We have a PCI quirk
flag for the latter. See "quirk_no_ata_d3". That will also avoid any
accidents elsewhere. Right now the quirk has "ata" in the name but the
ata is just historically because we had to quirk various disk controllers.

^ permalink raw reply

* Re: [PATCH (net.git) 1/4] stmmac: remove two useless initialisation
From: Giuseppe CAVALLARO @ 2012-06-04 15:58 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20120604.114940.813410325113851773.davem@davemloft.net>

On 6/4/2012 5:49 PM, David Miller wrote:
> From: Giuseppe CAVALLARO <peppe.cavallaro@st.com>
> Date: Mon,  4 Jun 2012 17:37:47 +0200
> 
>> This patch removes two useful initialisation in the
>> stmmac_rx and stmmac_tx function.
>> In the former, count var was already reset and in the
>> stmmac_tx we only need to increment the dirty pointer
>> w/o setting the entry var.
>>
>> Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
> 
> There are so many problems with this patch I do not know where
> to start.
> 
> Your subject line says the initializations are "useless" yet
> your commit message says they are "useful".

Sorry, I meant "useless".

> This is a cleanup, and does not fix any bugs, and is therefore
> absolutely not appropriate for the 'net' tree.

Yes this is not a fix but a cleanup.

I've not clear where I have to post this patch.
Do you mean, w/o net.git entry in the patch subject?
Can you tell me what I have to do? So will resend all the patches again
but I'll be more careful on all.

> I'm tossing this entire series, you need to be more careful
> with your submissions.

ok, thanks a lot.

peppe

> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 

^ permalink raw reply

* Re: [PATCH (net.git) 1/4] stmmac: remove two useless initialisation
From: David Miller @ 2012-06-04 16:01 UTC (permalink / raw)
  To: peppe.cavallaro; +Cc: netdev
In-Reply-To: <4FCCDB1A.1080307@st.com>

From: Giuseppe CAVALLARO <peppe.cavallaro@st.com>
Date: Mon, 04 Jun 2012 17:58:18 +0200

> I've not clear where I have to post this patch.

This is mind boggling that you can't figure this out.

If I tell you it's not appropriate for net, that means
it obviously must go to net-next

^ permalink raw reply

* Re: [PATCH (net.git)] net: icplus: fix interrupt mask
From: David Miller @ 2012-06-04 16:03 UTC (permalink / raw)
  To: peppe.cavallaro; +Cc: netdev
In-Reply-To: <1338825078-31856-1-git-send-email-peppe.cavallaro@st.com>

From: Giuseppe CAVALLARO <peppe.cavallaro@st.com>
Date: Mon,  4 Jun 2012 17:51:18 +0200

> This patch fixes the interrupt mask for IC101 A/G devices
> and now enables the link/speed/duplex interrupts.
> This is done by setting the "INTR pin used" bit and cleaning
> all the other bits in the Register 17.
> 
> Reported-by: Stuart Menefy <stuart.menefy@st.com>
> Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>

Applied.

^ permalink raw reply

* Re: [PATCH] net: Remove casts to same type
From: Ben Hutchings @ 2012-06-04 16:04 UTC (permalink / raw)
  To: Joe Perches; +Cc: David S. Miller, netdev
In-Reply-To: <4b3738493b23bc386d3372012faa8cd3672a138d.1338780551.git.joe@perches.com>

On Sun, 2012-06-03 at 20:41 -0700, Joe Perches wrote:
> Adding casts of objects to the same type is unnecessary
> and confusing for a human reader.
> 
> For example, this cast:
> 
> 	int y;
> 	int *p = (int *)&y;
> 
> I used the coccinelle script below to find and remove these
> unnecessary casts.  I manually removed the conversions this
> script produces of casts with __force and __user.
[...]
> diff --git a/net/9p/client.c b/net/9p/client.c
> index a170893..5cbea90 100644
> --- a/net/9p/client.c
> +++ b/net/9p/client.c
> @@ -1548,7 +1548,7 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
>  			kernel_buf = 1;
>  			indata = data;
>  		} else
> -			indata = (char *)udata;
> +			indata = udata;
>  		/*
>  		 * response header len is 11
>  		 * PDU Header(7) + IO Size (4)
[...]

This one is casting char __user * to char *.  We need a cast to let
sparse know this is deliberate, though presumably we need __force as
well.

Ben.

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

^ permalink raw reply

* [PATCH iproute2 0/3] CAN Filter/Classifier
From: Rostislav Lisovy @ 2012-06-04 16:09 UTC (permalink / raw)
  To: netdev; +Cc: linux-can, lartc, pisa, sojkam1, Rostislav Lisovy

This classifier classifies CAN frames (AF_CAN) according to their
identifiers. This functionality can not be easily achieved with
existing classifiers, such as u32. This classifier can be used
with any available qdisc and it is able to classify both SFF
or EFF frames.

The filtering rules for EFF frames are stored in an array, which
is traversed during classification. A bitmap is used to store SFF
rules -- one bit for each ID.

More info about the project:
http://rtime.felk.cvut.cz/can/socketcan-qdisc-final.pdf


Rostislav Lisovy (3):
  Add missing can.h
  CAN Filter/Classifier -- Source code
  CAN Filter/Classifier -- Documentation

 include/linux/can.h     |  112 ++++++++++++++++++++++
 include/linux/pkt_cls.h |   10 ++
 man/man8/tc-can.8       |   97 +++++++++++++++++++
 tc/Makefile             |    1 +
 tc/f_can.c              |  238 +++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 458 insertions(+)
 create mode 100644 include/linux/can.h
 create mode 100644 man/man8/tc-can.8
 create mode 100644 tc/f_can.c

-- 
1.7.9.5


^ permalink raw reply

* [PATCH iproute2 1/3] Add missing can.h
From: Rostislav Lisovy @ 2012-06-04 16:09 UTC (permalink / raw)
  To: netdev; +Cc: linux-can, lartc, pisa, sojkam1, Rostislav Lisovy
In-Reply-To: <1338826149-11604-1-git-send-email-lisovy@gmail.com>

This header file is slightly modified version copied from
Linux kernel v. 3.3. It contains defines necessary for working
with AF_CAN packets.

Signed-off-by: Rostislav Lisovy <lisovy@gmail.com>
---
 include/linux/can.h |  112 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 112 insertions(+)
 create mode 100644 include/linux/can.h

diff --git a/include/linux/can.h b/include/linux/can.h
new file mode 100644
index 0000000..08d1610
--- /dev/null
+++ b/include/linux/can.h
@@ -0,0 +1,112 @@
+/*
+ * linux/can.h
+ *
+ * Definitions for CAN network layer (socket addr / CAN frame / CAN filter)
+ *
+ * Authors: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
+ *          Urs Thuermann   <urs.thuermann@volkswagen.de>
+ * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
+ * All rights reserved.
+ *
+ */
+
+#ifndef CAN_H
+#define CAN_H
+
+#include <linux/types.h>
+#include <linux/socket.h>
+
+/* controller area network (CAN) kernel definitions */
+
+/* special address description flags for the CAN_ID */
+#define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */
+#define CAN_RTR_FLAG 0x40000000U /* remote transmission request */
+#define CAN_ERR_FLAG 0x20000000U /* error frame */
+
+/* valid bits in CAN ID for frame formats */
+#define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */
+#define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */
+#define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */
+
+/*
+ * Controller Area Network Identifier structure
+ *
+ * bit 0-28	: CAN identifier (11/29 bit)
+ * bit 29	: error frame flag (0 = data frame, 1 = error frame)
+ * bit 30	: remote transmission request flag (1 = rtr frame)
+ * bit 31	: frame format flag (0 = standard 11 bit, 1 = extended 29 bit)
+ */
+typedef __u32 canid_t;
+
+#define CAN_SFF_ID_BITS		11
+#define CAN_EFF_ID_BITS		29
+
+/*
+ * Controller Area Network Error Frame Mask structure
+ *
+ * bit 0-28	: error class mask (see include/linux/can/error.h)
+ * bit 29-31	: set to zero
+ */
+typedef __u32 can_err_mask_t;
+
+/**
+ * struct can_frame - basic CAN frame structure
+ * @can_id:  the CAN ID of the frame and CAN_*_FLAG flags, see above.
+ * @can_dlc: the data length field of the CAN frame
+ * @data:    the CAN frame payload.
+ */
+struct can_frame {
+	canid_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */
+	__u8    can_dlc; /* data length code: 0 .. 8 */
+	__u8    data[8] __attribute__((aligned(8)));
+};
+
+/* particular protocols of the protocol family PF_CAN */
+#define CAN_RAW		1 /* RAW sockets */
+#define CAN_BCM		2 /* Broadcast Manager */
+#define CAN_TP16	3 /* VAG Transport Protocol v1.6 */
+#define CAN_TP20	4 /* VAG Transport Protocol v2.0 */
+#define CAN_MCNET	5 /* Bosch MCNet */
+#define CAN_ISOTP	6 /* ISO 15765-2 Transport Protocol */
+#define CAN_NPROTO	7
+
+#define SOL_CAN_BASE 100
+
+/**
+ * struct sockaddr_can - the sockaddr structure for CAN sockets
+ * @can_family:  address family number AF_CAN.
+ * @can_ifindex: CAN network interface index.
+ * @can_addr:    protocol specific address information
+ */
+struct sockaddr_can {
+	__kernel_sa_family_t can_family;
+	int         can_ifindex;
+	union {
+		/* transport protocol class address information (e.g. ISOTP) */
+		struct { canid_t rx_id, tx_id; } tp;
+
+		/* reserved for future CAN protocols address information */
+	} can_addr;
+};
+
+/**
+ * struct can_filter - CAN ID based filter in can_register().
+ * @can_id:   relevant bits of CAN ID which are not masked out.
+ * @can_mask: CAN mask (see description)
+ *
+ * Description:
+ * A filter matches, when
+ *
+ *          <received_can_id> & mask == can_id & mask
+ *
+ * The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can
+ * filter for error frames (CAN_ERR_FLAG bit set in mask).
+ */
+struct can_filter {
+	canid_t can_id;
+	canid_t can_mask;
+};
+
+#define CAN_INV_FILTER 0x20000000U /* to be set in can_filter.can_id */
+
+#endif /* CAN_H */
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH iproute2 2/3] CAN Filter/Classifier -- Source code
From: Rostislav Lisovy @ 2012-06-04 16:09 UTC (permalink / raw)
  To: netdev; +Cc: linux-can, lartc, pisa, sojkam1, Rostislav Lisovy
In-Reply-To: <1338826149-11604-1-git-send-email-lisovy@gmail.com>

This classifier classifies CAN frames (AF_CAN) according to their
identifiers. This functionality can not be easily achieved with
existing classifiers, such as u32. This classifier can be used
with any available qdisc and it is able to classify both SFF
or EFF frames.

The filtering rules for EFF frames are stored in an array, which
is traversed during classification. A bitmap is used to store SFF
rules -- one bit for each ID.

More info about the project:
http://rtime.felk.cvut.cz/can/socketcan-qdisc-final.pdf

Signed-off-by: Rostislav Lisovy <lisovy@gmail.com>
---
 include/linux/pkt_cls.h |   10 ++
 tc/Makefile             |    1 +
 tc/f_can.c              |  238 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 249 insertions(+)
 create mode 100644 tc/f_can.c

diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h
index defbde2..83f9241 100644
--- a/include/linux/pkt_cls.h
+++ b/include/linux/pkt_cls.h
@@ -375,6 +375,16 @@ enum {
 
 #define TCA_BASIC_MAX (__TCA_BASIC_MAX - 1)
 
+/* CAN filter */
+
+enum {
+	TCA_CANFLTR_UNSPEC,
+	TCA_CANFLTR_CLASSID,
+	TCA_CANFLTR_RULES,
+	__TCA_CANFLTR_MAX
+};
+
+#define TCA_CANFLTR_MAX (__TCA_CANFLTR_MAX - 1)
 
 /* Cgroup classifier */
 
diff --git a/tc/Makefile b/tc/Makefile
index 64d93ad..1281568 100644
--- a/tc/Makefile
+++ b/tc/Makefile
@@ -22,6 +22,7 @@ TCMODULES += f_u32.o
 TCMODULES += f_route.o
 TCMODULES += f_fw.o
 TCMODULES += f_basic.o
+TCMODULES += f_can.o
 TCMODULES += f_flow.o
 TCMODULES += f_cgroup.o
 TCMODULES += q_dsmark.o
diff --git a/tc/f_can.c b/tc/f_can.c
new file mode 100644
index 0000000..208625f
--- /dev/null
+++ b/tc/f_can.c
@@ -0,0 +1,238 @@
+/*
+ * f_can.c  Filter for CAN packets
+ *
+ *		This program is free software; you can distribute 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.
+ *
+ * Idea:       Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
+ * Copyright:  (c) 2011 Czech Technical University in Prague
+ *             (c) 2011 Volkswagen Group Research
+ * Authors:    Michal Sojka <sojkam1@fel.cvut.cz>
+ *             Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *             Rostislav Lisovy <lisovy@gmail.cz>
+ * Funded by:  Volkswagen Group Research
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <linux/if.h>
+#include <limits.h>
+#include <inttypes.h>
+#include "utils.h"
+#include "tc_util.h"
+#include "linux/can.h"
+
+#define RULES_SIZE		128 /* Maximum number of rules sent via the
+				netlink message during creation/configuration */
+
+
+static void canfltr_explain(void)
+{
+	fprintf(stderr, "Usage: ... can [ MATCHSPEC ] [ flowid FLOWID ]\n"
+			"\n"
+			"Where: MATCHSPEC := { sffid FILTERID | effid FILTERID |\n"
+			"                   MATCHSPEC ... }\n"
+			"       FILTERID := CANID[:MASK]\n"
+			"\n"
+			"NOTE: CLASSID, CANID, MASK is parsed as hexadecimal input.\n");
+}
+
+static int canfltr_parse_opt(struct filter_util *qu, char *handle,
+			 int argc, char **argv, struct nlmsghdr *n)
+{
+	struct tcmsg *t = NLMSG_DATA(n);
+	struct rtattr *tail;
+	struct can_filter canfltr_rules[RULES_SIZE];
+	int rules_count = 0;
+	long h = 0;
+	canid_t can_id;
+	canid_t can_mask;
+
+	if (!argc)
+		return 0;
+
+	if (handle) {
+		h = strtol(handle, NULL, 0);
+		if (h == LONG_MIN || h == LONG_MAX) {
+			fprintf(stderr, "Illegal handle \"%s\", must be numeric.\n",
+				handle);
+			return -1;
+		}
+	}
+
+	t->tcm_handle = h;
+
+	tail = NLMSG_TAIL(n);
+	addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0);
+
+	while (argc > 0) {
+		if (matches(*argv, "sffid") == 0) {
+			/* parse SFF CAN ID optionally with mask */
+			if (rules_count >= RULES_SIZE) {
+				fprintf(stderr, "Too much rules on input. "
+					"Maximum number of rules is: %d\n",
+					RULES_SIZE);
+				return -1;
+			}
+
+			NEXT_ARG();
+
+			if (sscanf(*argv, "%"SCNx32 ":" "%"SCNx32,
+				&can_id, &can_mask) != 2) {
+				if (sscanf(*argv, "%"SCNx32, &can_id) != 1) {
+					fprintf(stderr, "Improperly formed CAN "
+						"ID & mask '%s'\n", *argv);
+					return -1;
+				} else
+					can_mask = CAN_SFF_MASK;
+			}
+
+			/* we do not support extra handling for RTR frames
+			due to the bitmap approach */
+			if (can_id & ~CAN_SFF_MASK) {
+				fprintf(stderr, "ID 0x%lx exceeded standard CAN ID range.\n",
+					(unsigned long)can_id);
+				return -1;
+			}
+
+			canfltr_rules[rules_count].can_id = can_id;
+			canfltr_rules[rules_count].can_mask =
+				(can_mask & CAN_SFF_MASK);
+			rules_count++;
+
+		} else if (matches(*argv, "effid") == 0) {
+			/* parse EFF CAN ID optionally with mask */
+			if (rules_count >= RULES_SIZE) {
+				fprintf(stderr, "Too much rules on input. "
+					"Maximum number of rules is: %d\n",
+					RULES_SIZE);
+				return -1;
+			}
+
+			NEXT_ARG();
+
+			if (sscanf(*argv, "%"SCNx32 ":" "%"SCNx32, &can_id, &can_mask) != 2) {
+				if (sscanf(*argv, "%"SCNx32, &can_id) != 1) {
+					fprintf(stderr, "Improperly formed CAN ID & mask '%s'\n", *argv);
+					return -1;
+				} else
+					can_mask = CAN_EFF_MASK;
+			}
+
+			if (can_id & ~CAN_EFF_MASK) {
+				fprintf(stderr, "ID 0x%lx exceeded extended CAN ID range.",
+					(unsigned long)can_id);
+				return -1;
+			}
+
+			canfltr_rules[rules_count].can_id =
+				can_id | CAN_EFF_FLAG;
+			canfltr_rules[rules_count].can_mask =
+				(can_mask & CAN_EFF_MASK) | CAN_EFF_FLAG;
+			rules_count++;
+
+		} else if (matches(*argv, "classid") == 0 || strcmp(*argv, "flowid") == 0) {
+			unsigned handle;
+			NEXT_ARG();
+			if (get_tc_classid(&handle, *argv)) {
+				fprintf(stderr, "Illegal \"classid\"\n");
+				return -1;
+			}
+			addattr_l(n, MAX_MSG, TCA_CANFLTR_CLASSID, &handle, 4);
+
+		} else if (strcmp(*argv, "help") == 0) {
+			canfltr_explain();
+			return -1;
+
+		} else {
+			fprintf(stderr, "What is \"%s\"?\n", *argv);
+			canfltr_explain();
+			return -1;
+		}
+		argc--; argv++;
+	}
+
+	addattr_l(n, MAX_MSG, TCA_CANFLTR_RULES, &canfltr_rules,
+		sizeof(struct can_filter) * rules_count);
+
+	tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail;
+	return 0;
+}
+
+/* When "tc filter show dev XY" is executed, function canfltr_walk() (in
+ * kernel) is called (which calls canfltr_dump() for each instance of a
+ * filter) which sends information about each instance of a filter to
+ * userspace -- to this function which parses the message and prints it.
+ */
+static int canfltr_print_opt(struct filter_util *qu, FILE *f,
+			struct rtattr *opt, __u32 handle)
+{
+	struct rtattr *tb[TCA_CANFLTR_MAX+1];
+	struct can_filter *canfltr_rules = NULL;
+	int rules_count = 0;
+	int i;
+
+	if (opt == NULL)
+		return 0;
+
+	parse_rtattr_nested(tb, TCA_CANFLTR_MAX, opt);
+
+	if (handle)
+		fprintf(f, "handle 0x%x ", handle);
+
+
+	if (tb[TCA_BASIC_CLASSID]) {
+		SPRINT_BUF(b1); /* allocates buffer b1 */
+		fprintf(f, "flowid %s ",
+			sprint_tc_classid(*(__u32 *)RTA_DATA(tb[TCA_BASIC_CLASSID]), b1));
+	}
+
+	if (tb[TCA_CANFLTR_RULES]) {
+		if (RTA_PAYLOAD(tb[TCA_CANFLTR_RULES]) < sizeof(struct can_filter))
+			return -1;
+
+		canfltr_rules = RTA_DATA(tb[TCA_CANFLTR_RULES]);
+		rules_count = (RTA_PAYLOAD(tb[TCA_CANFLTR_RULES]) /
+			sizeof(struct can_filter));
+
+		for (i = 0; i < rules_count; i++) {
+			struct can_filter *pcfltr = &canfltr_rules[i];
+
+			if (pcfltr->can_id & CAN_EFF_FLAG) {
+				if (pcfltr->can_mask == (CAN_EFF_FLAG|CAN_EFF_MASK))
+					fprintf(f, "effid 0x%"PRIX32" ",
+						pcfltr->can_id & CAN_EFF_MASK);
+				else
+					fprintf(f, "effid 0x%"PRIX32":0x%"PRIX32" ",
+						pcfltr->can_id & CAN_EFF_MASK,
+						pcfltr->can_mask & CAN_EFF_MASK);
+			} else {
+				if (pcfltr->can_mask == CAN_SFF_MASK)
+					fprintf(f, "sffid 0x%"PRIX32" ",
+						pcfltr->can_id);
+				else
+					fprintf(f, "sffid 0x%"PRIX32":0x%"PRIX32" ",
+						pcfltr->can_id,
+						pcfltr->can_mask);
+			}
+		}
+	}
+
+	return 0;
+}
+
+struct filter_util can_filter_util = {
+	.id = "can",
+	.parse_fopt = canfltr_parse_opt,
+	.print_fopt = canfltr_print_opt,
+};
+
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH iproute2 3/3] CAN Filter/Classifier -- Documentation
From: Rostislav Lisovy @ 2012-06-04 16:09 UTC (permalink / raw)
  To: netdev; +Cc: linux-can, lartc, pisa, sojkam1, Rostislav Lisovy
In-Reply-To: <1338826149-11604-1-git-send-email-lisovy@gmail.com>

Manpage describing usage of CAN Filter.

Signed-off-by: Rostislav Lisovy <lisovy@gmail.com>
---
 man/man8/tc-can.8 |   97 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 97 insertions(+)
 create mode 100644 man/man8/tc-can.8

diff --git a/man/man8/tc-can.8 b/man/man8/tc-can.8
new file mode 100644
index 0000000..54ee96a
--- /dev/null
+++ b/man/man8/tc-can.8
@@ -0,0 +1,97 @@
+.TH CAN 8 "8 May 2012" "iproute2" "Linux"
+.SH NAME
+CAN \- Controller Area Network classifier
+.SH SYNOPSIS
+.B tc filter ... dev
+DEV
+.B parent
+CLASSID
+.B [ prio
+PRIORITY
+.B ] [ protocol can ] [ handle 
+HANDLE
+.B ] can [ 
+MATCHSPEC
+.B ] [ flowid 
+FLOWID
+.B ]
+
+.B CLASSID := major:minor
+.br
+.B FLOWID := major:minor
+.br
+.B MATCHSPEC := { sffid 
+FILTERID
+.B | effid 
+FILTERID
+.B | MATCHSPEC ... }
+.br
+.B FILTERID := canid[:mask]
+
+.BR CLASSID ,
+.BR FLOWID ,
+.BR canid
+and
+.B mask
+are parsed as hexadecimal input.
+
+
+.SH DESCRIPTION
+The CAN classifier may be used with any available
+.B qdisc
+on Controller Area Network (CAN) frames passed through AF_CAN
+networking subsystem. The classifier classifies CAN frames according
+to their identifiers. It can be used on CAN frames with both SFF or
+EFF identifiers.
+
+It is possible to add CAN classifier to any qdisc configured on any networking
+device, however it will ignore non-CAN packets.
+
+
+.SH CLASSIFICATION
+The filtering rules for EFF frames are stored in an array, which is traversed
+during classification. This means that the worst-case time needed for
+classification of EFF frames increases with the number of configured rules.
+
+The filter implements an optimization for matching SFF frames using a bitmap
+with one bit for every ID. With this optimization, the classification time
+for SFF frames is nearly constant independently of the number of rules.
+
+.SH EXAMPLE
+This example shows how to set
+.B prio qdisc
+with
+.B CAN
+classifier.
+
+.nf
+tc qdisc add dev can0 root handle 1: prio
+
+tc filter add dev can0 parent 1:0 prio 1 handle 0xa \\
+    can sffid 0x7ff:0xf flowid 1:1
+tc filter add dev can0 parent 1:0 prio 2 handle 0xb \\
+    can sffid 0xC0:0x7ff effid 0x80:0x7ff flowid 1:2
+tc filter add dev can0 parent 1:0 prio 3 \\
+    can sffid 0x80:0x7ff flowid 1:2
+tc filter add dev can0 parent 1:0 prio 4 \\
+    can sffid 0x0:0x0 effid 0x0:0x0 flowid 1:3
+.fi
+
+
+.SH BUGS
+The maximum number or rules passed from
+.BR tc(8)
+utility to CAN classifier is fixed. The limit is set at compilation time
+(default is 128).
+
+
+.SH SEE ALSO
+.BR tc(8)
+
+
+.SH AUTHORS
+Michal Sojka <sojkam1@fel.cvut.cz>, Pavel Pisa <pisa@cmp.felk.cvut.cz>,
+Rostislav Lisovy <lisovy@gmail.cz>.
+
+This manpage maintained by Rostislav Lisovy <lisovy@gmail.com>
+
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 1/2] can: Add constants containing length of CAN identifiers
From: Rostislav Lisovy @ 2012-06-04 16:09 UTC (permalink / raw)
  To: netdev; +Cc: linux-can, lartc, pisa, sojkam1, Rostislav Lisovy

The necessary information might be determined out of the CAN_*_MASK,
however it is undesirable to misuse masks for such purpose.

Signed-off-by: Rostislav Lisovy <lisovy@gmail.com>
---
 include/linux/can.h |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/linux/can.h b/include/linux/can.h
index 9a19bcb..08d1610 100644
--- a/include/linux/can.h
+++ b/include/linux/can.h
@@ -38,6 +38,9 @@
  */
 typedef __u32 canid_t;
 
+#define CAN_SFF_ID_BITS		11
+#define CAN_EFF_ID_BITS		29
+
 /*
  * Controller Area Network Error Frame Mask structure
  *
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 2/2] net/sched: CAN Filter/Classifier
From: Rostislav Lisovy @ 2012-06-04 16:09 UTC (permalink / raw)
  To: netdev; +Cc: linux-can, lartc, pisa, sojkam1, Rostislav Lisovy
In-Reply-To: <1338826176-11646-1-git-send-email-lisovy@gmail.com>

This classifier classifies CAN frames (AF_CAN) according to their
identifiers. This functionality can not be easily achieved with
existing classifiers, such as u32. This classifier can be used
with any available qdisc and it is able to classify both SFF
or EFF frames.

The filtering rules for EFF frames are stored in an array, which
is traversed during classification. A bitmap is used to store SFF
rules -- one bit for each ID.

More info about the project:
http://rtime.felk.cvut.cz/can/socketcan-qdisc-final.pdf

Signed-off-by: Rostislav Lisovy <lisovy@gmail.com>
---
 net/sched/Kconfig   |   10 +
 net/sched/Makefile  |    1 +
 net/sched/cls_can.c |  572 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 583 insertions(+)
 create mode 100644 net/sched/cls_can.c

diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index e7a8976..aeb3c29 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -323,6 +323,16 @@ config NET_CLS_BASIC
 	  To compile this code as a module, choose M here: the
 	  module will be called cls_basic.
 
+config NET_CLS_CAN
+	tristate "Controller Area Network classifier (CAN)"
+	select NET_CLS
+	---help---
+	  Say Y here if you want to be able to classify CAN frames according
+	  to their CAN identifiers (can_id).
+
+	  To compile this code as a module, choose M here: the
+	  module will be called cls_can.
+
 config NET_CLS_TCINDEX
 	tristate "Traffic-Control Index (TCINDEX)"
 	select NET_CLS
diff --git a/net/sched/Makefile b/net/sched/Makefile
index 5940a19..0217341 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_NET_CLS_RSVP)	+= cls_rsvp.o
 obj-$(CONFIG_NET_CLS_TCINDEX)	+= cls_tcindex.o
 obj-$(CONFIG_NET_CLS_RSVP6)	+= cls_rsvp6.o
 obj-$(CONFIG_NET_CLS_BASIC)	+= cls_basic.o
+obj-$(CONFIG_NET_CLS_CAN)	+= cls_can.o
 obj-$(CONFIG_NET_CLS_FLOW)	+= cls_flow.o
 obj-$(CONFIG_NET_CLS_CGROUP)	+= cls_cgroup.o
 obj-$(CONFIG_NET_EMATCH)	+= ematch.o
diff --git a/net/sched/cls_can.c b/net/sched/cls_can.c
new file mode 100644
index 0000000..659be45
--- /dev/null
+++ b/net/sched/cls_can.c
@@ -0,0 +1,572 @@
+/*
+ * cls_can.c  -- Controller Area Network classifier.
+ * Makes decisions according to Controller Area Network identifiers (can_id).
+ *
+ *             This program is free software; you can distribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; version 2 of
+ *             the License.
+ *
+ * Idea:       Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
+ * Copyright:  (c) 2011 Czech Technical University in Prague
+ *             (c) 2011 Volkswagen Group Research
+ * Authors:    Michal Sojka <sojkam1@fel.cvut.cz>
+ *             Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *             Rostislav Lisovy <lisovy@gmail.cz>
+ * Funded by:  Volkswagen Group Research
+ *
+ * Some function descriptions are heavily inspired by article "Linux Network
+ * Traffic Control -- Implementation Overview" by Werner Almesberger
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/rtnetlink.h>
+#include <linux/skbuff.h>
+#include <net/netlink.h>
+#include <net/act_api.h>
+#include <net/pkt_cls.h>
+#include <linux/bitmap.h>
+#include <linux/spinlock.h>
+#include <linux/rcupdate.h>
+#include <linux/can.h>
+
+/* Definition of Netlink message parts */
+enum {
+	TCA_CANFLTR_UNSPEC,
+	TCA_CANFLTR_CLASSID,
+	TCA_CANFLTR_RULES,	/* Array of can_filter structs; We are able
+				to determine the length after receiving */
+	__TCA_CANFLTR_MAX
+};
+#define TCA_CANFLTR_MAX (__TCA_CANFLTR_MAX - 1)
+
+static const struct nla_policy canfltr_policy[TCA_CANFLTR_MAX + 1] = {
+	[TCA_CANFLTR_CLASSID]    = { .type = NLA_U32 }, /* Be aware of possible
+						problems with 64bit kernel and
+						32bit userspace etc. */
+	[TCA_CANFLTR_RULES]      = { .type = NLA_NESTED }
+};
+
+struct canfltr_rules {
+	struct can_filter *rules_raw;	/* Raw rules copied from netlink
+					message; Used for sending information
+					to userspace (when 'tc filter show' is
+					invoked) AND when matching EFF frames*/
+	DECLARE_BITMAP(match_sff, (1 << CAN_SFF_ID_BITS)); /* For each SFF CAN
+					ID (11 bit) there is one record in this
+					bitfield */
+	int rules_count;
+	int eff_rules_count;
+	int sff_rules_count;
+
+	struct rcu_head rcu;
+};
+
+struct canfltr_head {
+	u32 hgenerator;
+	struct list_head flist;
+};
+
+struct canfltr_state {
+	u32 handle;
+	struct canfltr_rules *rules;	/* All rules necessary for
+					classification */
+	struct tcf_result res;		/* Class ID (flow id) the instance
+					of a filter is bound to */
+	struct list_head link;
+};
+
+/*
+ * ----------------------------------------------------------------------------
+ */
+
+static void canfltr_sff_match_add(struct canfltr_rules *rls,
+				u32 can_id, u32 can_mask)
+{
+	int i;
+
+	/* Limit can_mask and can_id to SFF range to
+	protect against write after end of array */
+	can_mask &= CAN_SFF_MASK;
+	can_id &= can_mask;
+
+	/* single frame */
+	if (can_mask == CAN_SFF_MASK) {
+		set_bit(can_id, rls->match_sff);
+		return;
+	}
+
+	/* all frames */
+	if (can_mask == 0) {
+		bitmap_fill(rls->match_sff, (1 << CAN_SFF_ID_BITS));
+		return;
+	}
+
+	/* individual frame filter */
+	/* Add record (set bit to 1) for each ID that
+	conforms particular rule */
+	for (i = 0; i < (1 << CAN_SFF_ID_BITS); i++) {
+		if ((i & can_mask) == can_id)
+			set_bit(i, rls->match_sff);
+	}
+}
+
+/**
+ * canfltr_get_id() - Extracts Can ID out of the sk_buff structure.
+ */
+static canid_t canfltr_get_id(struct sk_buff *skb)
+{
+	/* Can ID is inside of data field */
+	struct can_frame *cf = (struct can_frame *)skb->data;
+
+	return cf->can_id;
+}
+
+/**
+ * canfltr_classify() - Performs the classification.
+ *
+ * @skb: Socket buffer
+ * @tp:
+ * @res: Is used for setting Class ID as a result of classification
+ *
+ * Iterates over all instances of filter, checking for CAN ID match.
+ *
+ * Returns value relevant for policing. Used return values:
+ *   TC_POLICE_OK if succesfully classified (without regard to policing rules)
+ *   TC_POLICE_UNSPEC if no matching rule was found
+ */
+static int canfltr_classify(struct sk_buff *skb, const struct tcf_proto *tp,
+			  struct tcf_result *res)
+{
+	struct canfltr_head *head = (struct canfltr_head *)tp->root;
+	struct canfltr_state *f;
+	struct canfltr_rules *r;
+	canid_t can_id;
+	int i;
+
+	can_id = canfltr_get_id(skb);
+
+	rcu_read_lock();
+	list_for_each_entry(f, &head->flist, link) {
+		bool match = false;
+		r = rcu_dereference(f->rules);
+
+
+		if (can_id & CAN_EFF_FLAG) {
+			can_id &= CAN_EFF_MASK;
+
+			for (i = 0; i < r->eff_rules_count; i++) {
+				if (!(((r->rules_raw[i].can_id ^ can_id) &
+				r->rules_raw[i].can_mask) & CAN_EFF_MASK)) {
+					match = true;
+					break;
+				}
+			}
+		} else { /* SFF */
+			can_id &= CAN_SFF_MASK;
+			match = test_bit(can_id, r->match_sff);
+		}
+
+		if (match) {
+			*res = f->res;
+			rcu_read_unlock();
+			return TC_POLICE_OK;
+		}
+	}
+
+	rcu_read_unlock();
+	return TC_POLICE_UNSPEC;
+}
+
+/**
+ * canfltr_get() - Looks up a filter element by its handle and returns the
+ * internal filter ID (i.e. pointer)
+ */
+static unsigned long canfltr_get(struct tcf_proto *tp, u32 handle)
+{
+	struct canfltr_head *head = (struct canfltr_head *)tp->root;
+	struct canfltr_state *f;
+
+	if (head == NULL)
+		return 0UL;
+
+	list_for_each_entry(f, &head->flist, link) {
+		if (f->handle == handle)
+			return (unsigned long) f;
+	}
+
+	return 0UL;
+}
+
+/**
+ * canfltr_put() - Is invoked when a filter element previously referenced
+ * with get() is no longer used
+ */
+static void canfltr_put(struct tcf_proto *tp, unsigned long f)
+{
+}
+
+/**
+ * canfltr_gen_handle() - Generate handle for newly created filter
+ *
+ * This code is heavily inspired by handle generator in cls_basic.c
+ */
+static unsigned int canfltr_gen_handle(struct tcf_proto *tp)
+{
+	struct canfltr_head *head = (struct canfltr_head *)tp->root;
+	unsigned int i = 0x80000000;
+
+	do {
+		if (++head->hgenerator == 0x7FFFFFFF)
+			head->hgenerator = 1;
+	} while (--i > 0 && canfltr_get(tp, head->hgenerator));
+
+	if (i == 0)
+		return 0;
+
+	return head->hgenerator;
+}
+
+static void canfltr_rules_free_rcu(struct rcu_head *rcu)
+{
+	kfree(container_of(rcu, struct canfltr_rules, rcu));
+}
+
+static int canfltr_set_parms(struct tcf_proto *tp, struct canfltr_state *f,
+				unsigned long base, struct nlattr **tb,
+				struct nlattr *est)
+{
+	struct can_filter *canfltr_nl_rules;
+	struct canfltr_rules *rules_tmp;
+	int err;
+	int i;
+
+	rules_tmp = kzalloc(sizeof(*rules_tmp), GFP_KERNEL);
+	if (!rules_tmp)
+		return -ENOBUFS;
+
+	err = -EINVAL;
+	if (tb[TCA_CANFLTR_CLASSID] == NULL)
+		goto errout;
+
+	if (tb[TCA_CANFLTR_RULES]) {
+		canfltr_nl_rules = nla_data(tb[TCA_CANFLTR_RULES]);
+		rules_tmp->sff_rules_count = 0;
+		rules_tmp->eff_rules_count = 0;
+		rules_tmp->rules_count = (nla_len(tb[TCA_CANFLTR_RULES]) /
+			sizeof(struct can_filter));
+
+		rules_tmp->rules_raw = kzalloc(sizeof(struct can_filter) *
+			rules_tmp->rules_count, GFP_KERNEL);
+		err = -ENOMEM;
+		if (rules_tmp->rules_raw == NULL)
+			goto errout;
+
+		/* We need two for() loops for copying rules into
+		two contiguous areas in rules_raw */
+
+		/* Process EFF frame rules*/
+		for (i = 0; i < rules_tmp->rules_count; i++) {
+			if ((canfltr_nl_rules[i].can_id & CAN_EFF_FLAG) &&
+			    (canfltr_nl_rules[i].can_mask & CAN_EFF_FLAG)) {
+				memcpy(rules_tmp->rules_raw +
+					rules_tmp->eff_rules_count,
+					&canfltr_nl_rules[i],
+					sizeof(struct can_filter));
+				rules_tmp->eff_rules_count++;
+			} else {
+				continue;
+			}
+		}
+
+		/* Process SFF frame rules */
+		for (i = 0; i < rules_tmp->rules_count; i++) {
+			if ((canfltr_nl_rules[i].can_id & CAN_EFF_FLAG) &&
+			    (canfltr_nl_rules[i].can_mask & CAN_EFF_FLAG)) {
+				continue;
+			} else {
+				memcpy(rules_tmp->rules_raw +
+					rules_tmp->eff_rules_count +
+					rules_tmp->sff_rules_count,
+					&canfltr_nl_rules[i],
+					sizeof(struct can_filter));
+				rules_tmp->sff_rules_count++;
+				canfltr_sff_match_add(rules_tmp,
+					canfltr_nl_rules[i].can_id,
+					canfltr_nl_rules[i].can_mask);
+			}
+		}
+	}
+
+
+	/* Setting parameters for newly created filter */
+	if (f->rules == NULL) {
+		rcu_assign_pointer(f->rules, rules_tmp);
+	} else { /* Changing existing filter */
+		struct canfltr_rules *rules_old;
+
+		rules_old = xchg(&f->rules, rules_tmp);
+		call_rcu(&rules_old->rcu, canfltr_rules_free_rcu);
+	}
+
+	return 0;
+
+errout:
+	kfree(rules_tmp);
+	return err;
+}
+
+/**
+ * canfltr_change() - Called for changing properties of an existing filter or
+ * after addition of a new filter to a class (by calling bind_tcf which binds
+ * an instance of a filter to the class).
+ *
+ * @tp:     Structure representing instance of a filter.
+ *          Part of a linked list of all filters.
+ * @base:
+ * @handle:
+ * @tca:    Messages passed through the Netlink from userspace.
+ * @arg:
+ */
+static int canfltr_change(struct tcf_proto *tp, unsigned long base, u32 handle,
+			  struct nlattr **tca, unsigned long *arg)
+{
+	struct canfltr_head *head = (struct canfltr_head *)tp->root;
+	struct canfltr_state *f = (struct canfltr_state *)*arg;
+	struct nlattr *tb[TCA_CANFLTR_MAX + 1];
+	int err;
+
+	if (tca[TCA_OPTIONS] == NULL)
+		return -EINVAL;
+
+	/* Parses a stream of attributes and stores a pointer to each
+	attribute in the tb array accessible via the attribute type.
+	Policy may be set to NULL if no validation is required.*/
+	err = nla_parse_nested(tb, TCA_CANFLTR_MAX, tca[TCA_OPTIONS],
+		canfltr_policy);
+	if (err < 0)
+		return err;
+	/* Change existing filter (remove all settings and add
+	them thereafter as if filter was newly created) */
+	if (f != NULL) {
+		if (handle && f->handle != handle)
+			return -EINVAL;
+
+		return canfltr_set_parms(tp, f, base, tb, tca[TCA_RATE]);
+	}
+
+	/* Create new filter */
+	err = -ENOBUFS;
+	f = kzalloc(sizeof(*f), GFP_KERNEL);
+	if (f == NULL)
+		goto errout;
+
+	if (tb[TCA_CANFLTR_CLASSID]) {
+		f->res.classid = nla_get_u32(tb[TCA_U32_CLASSID]);
+		tcf_bind_filter(tp, &f->res, base);
+	}
+
+	err = -EINVAL;
+	if (handle) /* handle passed from userspace */
+		f->handle = handle;
+	else {
+		f->handle = canfltr_gen_handle(tp);
+		if (f->handle == 0)
+			goto errout;
+	}
+
+	/* Configure filter */
+	err = canfltr_set_parms(tp, f, base, tb, tca[TCA_RATE]);
+	if (err < 0)
+		goto errout;
+
+	/* Add newly created filter to list of all filters */
+	tcf_tree_lock(tp);
+	list_add(&f->link, &head->flist);
+	tcf_tree_unlock(tp);
+	*arg = (unsigned long) f;
+
+	return 0;
+
+errout:
+	if (*arg == 0UL && f)
+		kfree(f);
+
+	return err;
+}
+
+
+static void canfltr_delete_filter(struct tcf_proto *tp,
+				struct canfltr_state *f)
+{
+	tcf_unbind_filter(tp, &f->res);
+
+	rcu_barrier();
+	kfree(f->rules->rules_raw);
+	kfree(f->rules);
+	kfree(f);
+}
+
+/**
+ * canfltr_destroy() - Remove whole filter.
+ */
+static void canfltr_destroy(struct tcf_proto *tp)
+{
+	struct canfltr_head *head = tp->root;
+	struct canfltr_state *f, *n;
+
+	list_for_each_entry_safe(f, n, &head->flist, link) {
+		list_del(&f->link);
+		canfltr_delete_filter(tp, f);
+	}
+	kfree(head);
+}
+
+/**
+ * canfltr_delete() - Delete one instance of a filter.
+ */
+static int canfltr_delete(struct tcf_proto *tp, unsigned long arg)
+{
+	struct canfltr_head *head = (struct canfltr_head *)tp->root;
+	struct canfltr_state *t;
+	struct canfltr_state *f = (struct canfltr_state *)arg;
+
+	rcu_barrier(); /* Wait for completion of call_rcu()'s */
+
+	list_for_each_entry(t, &head->flist, link)
+		if (t == f) {
+			tcf_tree_lock(tp);
+			list_del(&t->link);
+			tcf_tree_unlock(tp);
+			canfltr_delete_filter(tp, t);
+			return 0;
+		}
+
+	return -ENOENT;
+}
+
+
+/**
+ * canfltr_init() - Initialize filter
+ */
+static int canfltr_init(struct tcf_proto *tp)
+{
+	struct canfltr_head *head;
+
+	if ((tp->protocol != htons(ETH_P_ALL)) &&
+	    (tp->protocol != htons(ETH_P_CAN)))
+		return -1;
+
+	/* Work only on CAN frames */
+	if (tp->protocol == htons(ETH_P_ALL))
+		tp->protocol = htons(ETH_P_CAN);
+
+	head = kzalloc(sizeof(*head), GFP_KERNEL);
+	if (head == NULL)
+		return -ENOBUFS;
+
+	INIT_LIST_HEAD(&head->flist);
+	tp->root = head;
+
+	return 0;
+}
+
+/**
+ * canfltr_walk() - Iterates over all elements of a filter and invokes a
+ * callback function for each of them. This is used to obtain diagnostic data.
+ */
+static void canfltr_walk(struct tcf_proto *tp, struct tcf_walker *arg)
+{
+	struct canfltr_head *head = (struct canfltr_head *) tp->root;
+	struct canfltr_state *f;
+
+	list_for_each_entry(f, &head->flist, link) {
+		if (arg->count < arg->skip)
+			goto skip;
+
+		if (arg->fn(tp, (unsigned long) f, arg) < 0) {
+			arg->stop = 1;
+			break;
+		}
+skip:
+		arg->count++;
+	}
+}
+
+/**
+ * canfltr_dump() - Returns diagnostic data for a filter or one of its elements.
+ */
+static int canfltr_dump(struct tcf_proto *tp, unsigned long fh,
+			struct sk_buff *skb, struct tcmsg *t)
+{
+	struct canfltr_state *f = (struct canfltr_state *) fh;
+	struct nlattr *nest;
+	struct canfltr_rules *r;
+
+	if (f == NULL)
+		return skb->len;
+
+	rcu_read_lock();
+	r = rcu_dereference(f->rules);
+	t->tcm_handle = f->handle;
+
+	nest = nla_nest_start(skb, TCA_OPTIONS);
+	if (nest == NULL)
+		goto nla_put_failure;
+
+	if (f->res.classid &&
+	    nla_put_u32(skb, TCA_CANFLTR_CLASSID, f->res.classid))
+		goto nla_put_failure;
+
+	if (nla_put(skb, TCA_CANFLTR_RULES, r->rules_count *
+	    sizeof(struct can_filter), r->rules_raw))
+		goto nla_put_failure;
+
+	nla_nest_end(skb, nest);
+
+	rcu_read_unlock();
+	return skb->len;
+
+nla_put_failure:
+	nla_nest_cancel(skb, nest);
+	rcu_read_unlock();
+	return -1;
+}
+
+
+static struct tcf_proto_ops cls_canfltr_ops __read_mostly = {
+	.kind           =       "can",
+	.classify       =       canfltr_classify,
+	.init           =       canfltr_init,
+	.destroy        =       canfltr_destroy,
+	.get            =       canfltr_get,
+	.put            =       canfltr_put,
+	.change         =       canfltr_change,
+	.delete         =       canfltr_delete,
+	.walk           =       canfltr_walk,
+	.dump           =       canfltr_dump,
+	.owner          =       THIS_MODULE,
+};
+
+static int __init init_canfltr(void)
+{
+	pr_debug("canfltr: CAN filter loaded\n");
+	return register_tcf_proto_ops(&cls_canfltr_ops);
+}
+
+static void __exit exit_canfltr(void)
+{
+	pr_debug("canfltr: CAN filter removed\n");
+	unregister_tcf_proto_ops(&cls_canfltr_ops);
+}
+
+module_init(init_canfltr);
+module_exit(exit_canfltr);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Rostislav Lisovy <lisovy@gmail.cz>");
+MODULE_DESCRIPTION("Controller Area Network classifier");
-- 
1.7.9.5


^ permalink raw reply related

* RE: [PATCH 1/1] net/hyperv: Use wait_event on outstanding sends during device removal
From: Haiyang Zhang @ 2012-06-04 16:14 UTC (permalink / raw)
  To: David Miller
  Cc: netdev@vger.kernel.org, KY Srinivasan, olaf@aepfle.de,
	linux-kernel@vger.kernel.org, devel@linuxdriverproject.org
In-Reply-To: <20120604.114803.742884170282591530.davem@davemloft.net>



> -----Original Message-----
> From: David Miller [mailto:davem@davemloft.net]
> Sent: Monday, June 04, 2012 11:48 AM
> To: Haiyang Zhang
> Cc: netdev@vger.kernel.org; KY Srinivasan; olaf@aepfle.de; linux-
> kernel@vger.kernel.org; devel@linuxdriverproject.org
> Subject: Re: [PATCH 1/1] net/hyperv: Use wait_event on outstanding sends
> during device removal
> 
> From: Haiyang Zhang <haiyangz@microsoft.com>
> Date: Mon,  4 Jun 2012 07:35:32 -0700
> 
> > +	wait_event(net_device->wait_drain,
> > +		atomic_read(&net_device->num_outstanding_sends) == 0);
> 
> Please indent this properly.  The goal is not to indent using only
> TAB characters, the goal is to line things up to the proper column
> using TAB and space characters as needed.
> 
> You must make the first character on the second line be at the
> first column after the openning parenthesis on the previous line.

Will do.

Thanks,
- Haiyang 

^ 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