All of lore.kernel.org
 help / color / mirror / Atom feed
* VLAN driver question
@ 2013-06-17 19:12 Jim Baxter
  2013-06-18 14:41 ` Ben Hutchings
  0 siblings, 1 reply; 7+ messages in thread
From: Jim Baxter @ 2013-06-17 19:12 UTC (permalink / raw)
  To: netdev

I have a network card that has a single flag to indicate if a received
packet contains a vlan packet.

Can I use this to accelerate the kernels handling of the packet with
something like the following?

/* Handle received VLAN packets */
if ((ndev->features & NETIF_F_HW_VLAN_CTAG_RX) && ebdp &&
					(ebdp->cbd_esc &
					BD_ENET_RX_VLAN)) {
	/* Push and remove the vlan tag */
	struct vlan_hdr *vlan_header;
	u16 vlan_tag;
	vlan_header = (struct vlan_hdr *) skb->data;
	vlan_tag = ntohs(vlan_header->h_vlan_TCI);
	__vlan_hwaccel_put_tag(skb, vlan_tag);
	skb->len -= VLAN_HLEN;
	skb->data += VLAN_HLEN;
	vlan_set_encap_proto(skb, vlan_header);
}

napi_gro_receive(&fep->napi, skb);



Also I cannot find any documentation stating what the difference is
between NETIF_F_HW_VLAN_CTAG_RX and NETIF_F_HW_VLAN_CTAG_FILTER, can
anyone define it?
The FILTER word on NETIF_F_HW_VLAN_CTAG_FILTER suggests it may be
applicable to received packets.

Thank you for your help and comments.
Jim Baxter

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: VLAN driver question
  2013-06-17 19:12 VLAN driver question Jim Baxter
@ 2013-06-18 14:41 ` Ben Hutchings
  2013-06-19 15:57   ` Jim Baxter
  0 siblings, 1 reply; 7+ messages in thread
From: Ben Hutchings @ 2013-06-18 14:41 UTC (permalink / raw)
  To: Jim Baxter; +Cc: netdev

On Mon, 2013-06-17 at 20:12 +0100, Jim Baxter wrote:
> I have a network card that has a single flag to indicate if a received
> packet contains a vlan packet.
> 
> Can I use this to accelerate the kernels handling of the packet with
> something like the following?
>
> /* Handle received VLAN packets */
> if ((ndev->features & NETIF_F_HW_VLAN_CTAG_RX) && ebdp &&
> 					(ebdp->cbd_esc &
> 					BD_ENET_RX_VLAN)) {
> 	/* Push and remove the vlan tag */
> 	struct vlan_hdr *vlan_header;
> 	u16 vlan_tag;
> 	vlan_header = (struct vlan_hdr *) skb->data;
> 	vlan_tag = ntohs(vlan_header->h_vlan_TCI);
> 	__vlan_hwaccel_put_tag(skb, vlan_tag);
> 	skb->len -= VLAN_HLEN;
> 	skb->data += VLAN_HLEN;
> 	vlan_set_encap_proto(skb, vlan_header);

You have to move the Ethernet addresses forward as well.  Imagine this
device is being bridged - the Ethernet header won't be regenerated, so
it has to be immediately before the network header.

> }
> 
> napi_gro_receive(&fep->napi, skb);

I've been meaning to add a core function to do
pull-out-VLAN-tag-and-GRO, although I'm more interested in
napi_gro_frags().  Perhaps you could add the generic wrapper for
napi_gro_receive()?

> Also I cannot find any documentation stating what the difference is
> between NETIF_F_HW_VLAN_CTAG_RX and NETIF_F_HW_VLAN_CTAG_FILTER, can
> anyone define it?
> The FILTER word on NETIF_F_HW_VLAN_CTAG_FILTER suggests it may be
> applicable to received packets.

NETIF_F_HW_VLAN_CTAG_RX means the device will extract VLAN tags so they
aren't received inline.

NETIF_F_HW_VLAN_CTAG_FILTER means the device can filter by VID.  The
driver's ndo_vlan_rx_{add,kill}_vid operations will be called to update
the filter.

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	[flat|nested] 7+ messages in thread

* Re: VLAN driver question
  2013-06-18 14:41 ` Ben Hutchings
@ 2013-06-19 15:57   ` Jim Baxter
  2013-06-19 16:33     ` Ben Hutchings
  0 siblings, 1 reply; 7+ messages in thread
From: Jim Baxter @ 2013-06-19 15:57 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: netdev

Thank you Ben, that is very helpful.

On 18/06/13 15:41, Ben Hutchings wrote:
> On Mon, 2013-06-17 at 20:12 +0100, Jim Baxter wrote:
>> I have a network card that has a single flag to indicate if a received
>> packet contains a vlan packet.
>>
>> Can I use this to accelerate the kernels handling of the packet with
>> something like the following?
>>
>> /* Handle received VLAN packets */
>> if ((ndev->features & NETIF_F_HW_VLAN_CTAG_RX) && ebdp &&
>> 					(ebdp->cbd_esc &
>> 					BD_ENET_RX_VLAN)) {
>> 	/* Push and remove the vlan tag */
>> 	struct vlan_hdr *vlan_header;
>> 	u16 vlan_tag;
>> 	vlan_header = (struct vlan_hdr *) skb->data;
>> 	vlan_tag = ntohs(vlan_header->h_vlan_TCI);
>> 	__vlan_hwaccel_put_tag(skb, vlan_tag);
>> 	skb->len -= VLAN_HLEN;
>> 	skb->data += VLAN_HLEN;
>> 	vlan_set_encap_proto(skb, vlan_header);
> 
> You have to move the Ethernet addresses forward as well.  Imagine this
> device is being bridged - the Ethernet header won't be regenerated, so
> it has to be immediately before the network header.
> 
Unless I have misunderstood, the Ethernet header is already copied
across to the skb by the Driver I am editing with the lines:
	skb_reserve(skb, NET_IP_ALIGN);
	skb_put(skb, pkt_len - 4);	/* Make room */
	skb_copy_to_linear_data(skb, data, pkt_len - 4);
	skb->protocol = eth_type_trans(skb, ndev);


Thinking about it though I should actually use the flag from the driver
to create an skb of the size (pkt_len - 4 - VLAN_HLEN) and extract the
vlan header from data so it is not copied to the skb, does this sound
sensible?

>> }
>>
>> napi_gro_receive(&fep->napi, skb);
> 
> I've been meaning to add a core function to do
> pull-out-VLAN-tag-and-GRO, although I'm more interested in
> napi_gro_frags().  Perhaps you could add the generic wrapper for
> napi_gro_receive()?
>
>> Also I cannot find any documentation stating what the difference is
>> between NETIF_F_HW_VLAN_CTAG_RX and NETIF_F_HW_VLAN_CTAG_FILTER, can
>> anyone define it?
>> The FILTER word on NETIF_F_HW_VLAN_CTAG_FILTER suggests it may be
>> applicable to received packets.
> 
> NETIF_F_HW_VLAN_CTAG_RX means the device will extract VLAN tags so they
> aren't received inline.
> 
> NETIF_F_HW_VLAN_CTAG_FILTER means the device can filter by VID.  The
> driver's ndo_vlan_rx_{add,kill}_vid operations will be called to update
> the filter.
> 
> Ben.
> 
Jim

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: VLAN driver question
  2013-06-19 15:57   ` Jim Baxter
@ 2013-06-19 16:33     ` Ben Hutchings
  2013-06-20 19:05       ` Jim Baxter
  0 siblings, 1 reply; 7+ messages in thread
From: Ben Hutchings @ 2013-06-19 16:33 UTC (permalink / raw)
  To: Jim Baxter; +Cc: netdev

On Wed, 2013-06-19 at 16:57 +0100, Jim Baxter wrote:
> Thank you Ben, that is very helpful.
> 
> On 18/06/13 15:41, Ben Hutchings wrote:
> > On Mon, 2013-06-17 at 20:12 +0100, Jim Baxter wrote:
> >> I have a network card that has a single flag to indicate if a received
> >> packet contains a vlan packet.
> >>
> >> Can I use this to accelerate the kernels handling of the packet with
> >> something like the following?
> >>
> >> /* Handle received VLAN packets */
> >> if ((ndev->features & NETIF_F_HW_VLAN_CTAG_RX) && ebdp &&
> >> 					(ebdp->cbd_esc &
> >> 					BD_ENET_RX_VLAN)) {
> >> 	/* Push and remove the vlan tag */
> >> 	struct vlan_hdr *vlan_header;
> >> 	u16 vlan_tag;
> >> 	vlan_header = (struct vlan_hdr *) skb->data;
> >> 	vlan_tag = ntohs(vlan_header->h_vlan_TCI);
> >> 	__vlan_hwaccel_put_tag(skb, vlan_tag);
> >> 	skb->len -= VLAN_HLEN;
> >> 	skb->data += VLAN_HLEN;
> >> 	vlan_set_encap_proto(skb, vlan_header);
> > 
> > You have to move the Ethernet addresses forward as well.  Imagine this
> > device is being bridged - the Ethernet header won't be regenerated, so
> > it has to be immediately before the network header.
> > 
> Unless I have misunderstood, the Ethernet header is already copied
> across to the skb by the Driver I am editing with the lines:
> 	skb_reserve(skb, NET_IP_ALIGN);
> 	skb_put(skb, pkt_len - 4);	/* Make room */
> 	skb_copy_to_linear_data(skb, data, pkt_len - 4);
> 	skb->protocol = eth_type_trans(skb, ndev);

Right, but the copy and ether_type_trans() result in an skb like this:

-14 -8  -2   0   2    4
|dst|src|8100|vid|type|payload...|
             ^

After extracting the VLAN tag the skb looks like:

-18 -12 -6   -4  -2   0
|dst|src|8100|vid|type|payload...|
                      ^

If this packet is bridged, the 14 bytes before skb->data will be treated
as the Ethernet header:

0 2   8    10  12   14
|x|src|8100|vid|type|payload...|
^

Then with the VLAN tag inserted;

0 2   8    10  12   14  16   18
|x|src|8100|vid|8100|vid|type|payload...|

> Thinking about it though I should actually use the flag from the driver
> to create an skb of the size (pkt_len - 4 - VLAN_HLEN) and extract the
> vlan header from data so it is not copied to the skb, does this sound
> sensible?
[...]

That would also work.

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	[flat|nested] 7+ messages in thread

* Re: VLAN driver question
  2013-06-19 16:33     ` Ben Hutchings
@ 2013-06-20 19:05       ` Jim Baxter
  2013-06-21 15:42         ` Ben Hutchings
  0 siblings, 1 reply; 7+ messages in thread
From: Jim Baxter @ 2013-06-20 19:05 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: netdev

On 19/06/13 17:33, Ben Hutchings wrote:
> On Wed, 2013-06-19 at 16:57 +0100, Jim Baxter wrote:
>> Thank you Ben, that is very helpful.
>>
>> On 18/06/13 15:41, Ben Hutchings wrote:
>>> On Mon, 2013-06-17 at 20:12 +0100, Jim Baxter wrote:
>>>> I have a network card that has a single flag to indicate if a received
>>>> packet contains a vlan packet.
>>>>
>>>> Can I use this to accelerate the kernels handling of the packet with
>>>> something like the following?
>>>>
>>>> /* Handle received VLAN packets */
>>>> if ((ndev->features & NETIF_F_HW_VLAN_CTAG_RX) && ebdp &&
>>>> 					(ebdp->cbd_esc &
>>>> 					BD_ENET_RX_VLAN)) {
>>>> 	/* Push and remove the vlan tag */
>>>> 	struct vlan_hdr *vlan_header;
>>>> 	u16 vlan_tag;
>>>> 	vlan_header = (struct vlan_hdr *) skb->data;
>>>> 	vlan_tag = ntohs(vlan_header->h_vlan_TCI);
>>>> 	__vlan_hwaccel_put_tag(skb, vlan_tag);
>>>> 	skb->len -= VLAN_HLEN;
>>>> 	skb->data += VLAN_HLEN;
>>>> 	vlan_set_encap_proto(skb, vlan_header);
>>>
>>> You have to move the Ethernet addresses forward as well.  Imagine this
>>> device is being bridged - the Ethernet header won't be regenerated, so
>>> it has to be immediately before the network header.
>>>
>> Unless I have misunderstood, the Ethernet header is already copied
>> across to the skb by the Driver I am editing with the lines:
>> 	skb_reserve(skb, NET_IP_ALIGN);
>> 	skb_put(skb, pkt_len - 4);	/* Make room */
>> 	skb_copy_to_linear_data(skb, data, pkt_len - 4);
>> 	skb->protocol = eth_type_trans(skb, ndev);
> 
> Right, but the copy and ether_type_trans() result in an skb like this:
> 
> -14 -8  -2   0   2    4
> |dst|src|8100|vid|type|payload...|
>              ^
> 
> After extracting the VLAN tag the skb looks like:
> 
> -18 -12 -6   -4  -2   0
> |dst|src|8100|vid|type|payload...|
>                       ^
> 
> If this packet is bridged, the 14 bytes before skb->data will be treated
> as the Ethernet header:
> 
> 0 2   8    10  12   14
> |x|src|8100|vid|type|payload...|
> ^
> 
> Then with the VLAN tag inserted;
> 
> 0 2   8    10  12   14  16   18
> |x|src|8100|vid|8100|vid|type|payload...|
> 
>> Thinking about it though I should actually use the flag from the driver
>> to create an skb of the size (pkt_len - 4 - VLAN_HLEN) and extract the
>> vlan header from data so it is not copied to the skb, does this sound
>> sensible?
> [...]
> 
> That would also work.
> 
> Ben.
> 

Thank you for that information, I have decided to extract the data
before copying the data into the skb->data structure.

This is the put of the packet showing my removal of the data correctly,
however the network is not receiving any data on the VLAN.

- data buffer from the Network card
ff ff ff ff ff ff 00 26 b9 d4 19 01 81 00 00 0a 08 06 00 01 08 00 06 04
00 01 00 26 b9 d4

- skb->data after I have only copied data to it and removed the vlan 4
octet header using skb_copy_to_linear_data and
skb_copy_to_linear_data_offset.
ff ff ff ff ff ff 00 26 b9 d4 19 01 08 06 00 01 08 00 06 04 00 01 00 26
b9 d4 19 01 c0 a8

- skb-data after eth_type_trans()
00 01 08 00 06 04 00 01 00 26 b9 d4 19 01 c0 a8 01 67 00 00 00 00 00 00
c0 a8 01 64 00 00

After this point I send the packet into the network stack with:
	__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);

	napi_gro_receive(&fep->napi, skb);

Am I missing a kernel call or doing something wrong to cause the packet
to be rejected in the kernel?

Thank you for any help,
Jim

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: VLAN driver question
  2013-06-20 19:05       ` Jim Baxter
@ 2013-06-21 15:42         ` Ben Hutchings
  2013-06-21 17:02           ` Jim Baxter
  0 siblings, 1 reply; 7+ messages in thread
From: Ben Hutchings @ 2013-06-21 15:42 UTC (permalink / raw)
  To: Jim Baxter; +Cc: netdev

On Thu, 2013-06-20 at 20:05 +0100, Jim Baxter wrote:
[...]
> Thank you for that information, I have decided to extract the data
> before copying the data into the skb->data structure.
> 
> This is the put of the packet showing my removal of the data correctly,
> however the network is not receiving any data on the VLAN.
> 
> - data buffer from the Network card
> ff ff ff ff ff ff 00 26 b9 d4 19 01 81 00 00 0a 08 06 00 01 08 00 06 04
> 00 01 00 26 b9 d4
> 
> - skb->data after I have only copied data to it and removed the vlan 4
> octet header using skb_copy_to_linear_data and
> skb_copy_to_linear_data_offset.
> ff ff ff ff ff ff 00 26 b9 d4 19 01 08 06 00 01 08 00 06 04 00 01 00 26
> b9 d4 19 01 c0 a8
> 
> - skb-data after eth_type_trans()
> 00 01 08 00 06 04 00 01 00 26 b9 d4 19 01 c0 a8 01 67 00 00 00 00 00 00
> c0 a8 01 64 00 00
> 
> After this point I send the packet into the network stack with:
> 	__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
> 
> 	napi_gro_receive(&fep->napi, skb);
> 
> Am I missing a kernel call or doing something wrong to cause the packet
> to be rejected in the kernel?

That looks about right to me, but perhaps vlan_tag has the wrong byte
order?  __vlan_hwaccel_put_tag() expects it in host byte order.

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	[flat|nested] 7+ messages in thread

* Re: VLAN driver question
  2013-06-21 15:42         ` Ben Hutchings
@ 2013-06-21 17:02           ` Jim Baxter
  0 siblings, 0 replies; 7+ messages in thread
From: Jim Baxter @ 2013-06-21 17:02 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: netdev

On 21/06/13 16:42, Ben Hutchings wrote:
> On Thu, 2013-06-20 at 20:05 +0100, Jim Baxter wrote:
> [...]
>> Thank you for that information, I have decided to extract the data
>> before copying the data into the skb->data structure.
>>
>> This is the put of the packet showing my removal of the data correctly,
>> however the network is not receiving any data on the VLAN.
>>
>> - data buffer from the Network card
>> ff ff ff ff ff ff 00 26 b9 d4 19 01 81 00 00 0a 08 06 00 01 08 00 06 04
>> 00 01 00 26 b9 d4
>>
>> - skb->data after I have only copied data to it and removed the vlan 4
>> octet header using skb_copy_to_linear_data and
>> skb_copy_to_linear_data_offset.
>> ff ff ff ff ff ff 00 26 b9 d4 19 01 08 06 00 01 08 00 06 04 00 01 00 26
>> b9 d4 19 01 c0 a8
>>
>> - skb-data after eth_type_trans()
>> 00 01 08 00 06 04 00 01 00 26 b9 d4 19 01 c0 a8 01 67 00 00 00 00 00 00
>> c0 a8 01 64 00 00
>>
>> After this point I send the packet into the network stack with:
>> 	__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
>>
>> 	napi_gro_receive(&fep->napi, skb);
>>
>> Am I missing a kernel call or doing something wrong to cause the packet
>> to be rejected in the kernel?
> 
> That looks about right to me, but perhaps vlan_tag has the wrong byte
> order?  __vlan_hwaccel_put_tag() expects it in host byte order.
> 
> Ben.
> 

Hi, Thank you, I have got it working. The problem was that when I had
changed the code to remove the VLAN before putting the data into the
skb, I was not moving the pointer past the TPID.

It now all works with ping, ssh and scp'ing small files but when I scp a
large file it stalls. I suspect it is because it is not processing
packets that are at the MTU of 1518 bytes (1522 bytes with the VLAN
header) in size.

Jim

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2013-06-21 17:02 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-06-17 19:12 VLAN driver question Jim Baxter
2013-06-18 14:41 ` Ben Hutchings
2013-06-19 15:57   ` Jim Baxter
2013-06-19 16:33     ` Ben Hutchings
2013-06-20 19:05       ` Jim Baxter
2013-06-21 15:42         ` Ben Hutchings
2013-06-21 17:02           ` Jim Baxter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.