Since the sk_buff
fields are processed locally it makes more sense to store it in the host order. Fields like sk_buff->vlan_tci
are in host order. Is there a reason for storing some fields sk_buff->protocol
, sk_buff->vlan_proto
in network/big endian format ?
1 Answers
According to http://vger.kernel.org/~davem/skb.html page, protocol
field of sk_buff
IS used by network:
unsigned short protocol,
The 'protocol' field is initialized by routines such as 'eth_type_trans()'. It takes on one of the 'ETH_P_*' values defined in the 'linux/if_ether.h' header file. Even non-ethernet devices use these ethernet protocol type values to indicate what protocol should receive the packet. As long as we always have some ethernet protocol value for each and every protocol, this should not be a problem.
Also, the comment in skbuff.h
says that protocol
is from driver:
340 /**
341 * struct sk_buff - socket buffer
369 * @protocol: Packet protocol from driver
391 * @vlan_proto: vlan encapsulation protocol
392 * @vlan_tci: vlan tag control information
So, for incoming packet protocol
is filled from the Ethernet packet field "TYPE" (ethertype, network endian)
http://en.wikipedia.org/wiki/Ethernet_frame :
Data on Ethernet is transmitted most-significant octet first. Within each octet, however, the least-significant bit is transmitted first. Ethertype (Ethernet II) or length 2 octets
For outgoing packet it is filled by network stack and then used to fill the "TYPE" field.
vlan_proto
is the copy of first protocol
field from ethernet packet, usually 0x8100 when 802.1Q tagging used (http://en.wikipedia.org/wiki/EtherType list it as "VLAN-tagged frame (IEEE 802.1Q)"). And the second protocol field (after VLAN tag), will be used as real protocol
. So, vlan_proto
is also stored as network order because it is from/to network.
TCI (the information to store in vlan_tci
) is also part of network 802.1q packet, it has 2 bytes (octets). But in processing of network fields, it is converted to host format by vlan_untag()
in net/8021q/vlan_core.c:
118 struct sk_buff *vlan_untag(struct sk_buff *skb)
119 {
120 struct vlan_hdr *vhdr;
121 u16 vlan_tci;
135 vhdr = (struct vlan_hdr *) skb->data;
136 vlan_tci = ntohs(vhdr->h_vlan_TCI);
137 __vlan_hwaccel_put_tag(skb, skb->protocol, vlan_tci);
I think it is done to make bit operations on TCI easier. They are needed for getting PCP (3 bit), DEI (1 bit) and VID (12 bit) fields from TCI. There is also several additional flag, VLAN_TAG_PRESENT
stored in vlan_tci
by __vlan_hwaccel_put_tag
There is converting of host TCI to network for outgoing packets, vlan_insert_tag()
from linux/if_vlan.h:
277 * Inserts the VLAN tag into @skb as part of the payload
278 * Returns a VLAN tagged skb. If a new skb is created, @skb is freed.
285 static inline struct sk_buff *vlan_insert_tag(struct sk_buff *skb,
286 __be16 vlan_proto, u16 vlan_tci)
287 {
300 /* first, the ethernet type */
301 veth->h_vlan_proto = vlan_proto;
302
303 /* now, the TCI */
304 veth->h_vlan_TCI = htons(vlan_tci);

- 90,338
- 53
- 357
- 513