6

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 ?

osgx
  • 90,338
  • 53
  • 357
  • 513
Manohar
  • 3,865
  • 11
  • 41
  • 56

1 Answers1

8

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);
osgx
  • 90,338
  • 53
  • 357
  • 513