Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is sk_buff->protocol stored in network endian order?

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 ?

like image 439
Manohar Avatar asked May 08 '14 16:05

Manohar


People also ask

What is Sk_buff structure?

The sk_buff elements are organized as a doubly linked list, in such a way that it is very efficient to move an sk_buff element from the beginning/end of a list to the beginning/end of another list. A queue is defined by struct sk_buff_head, which includes a head and a tail pointer to sk_buff elements.

How does Linux network stack work?

In the Linux operating system, the network stack is useful to communicate the application with the physical network devices. The network stack is divided into multiple layers. There are different network layers. The same different roles are playing their individual role.

Is TCP implemented in kernel?

Therefore, TCP is one of the most com- plicated components in Linux networking stack. In kernel 3.5. 4, it consists of over 21000 lines of code under net/ipv4/ -directory (all tcp*.

What happens as soon as a packet arrives from the network in Linux?

When a packet arrives at the Network Interface Card of the machine, the card receives the packet and the packet is transferred into a rx ring through DMA. The rx ring is a ring in the kernel memory where the network card transfers the incoming packet through DMA.


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);
like image 175
osgx Avatar answered Oct 09 '22 20:10

osgx