netdev
[Top] [All Lists]

Re: Some questions about skbuff's

To: "netdev@xxxxxxxxxxx" <netdev@xxxxxxxxxxx>
Subject: Re: Some questions about skbuff's
From: Laurence <laudney@xxxxxxxx>
Date: Wed, 20 Feb 2002 12:8:37 +0800
Organization: SJTU
Reply-to: laudney@xxxxxxxx
Sender: owner-netdev@xxxxxxxxxxx
>Ok, i will try to express the problem crealy.
>I have seen many examples with skbuff's and when a tcp packet arrives in the 
>code appears...
>skb->h.raw = skb->nh.raw + skb->nh.iph->ihl*4;
>skb->data = (unsigned char *)skb->h.raw +(skb->h.th->doff <<2);
>skb->len -= skb->nh.iph->ihl*4 + (skb->h.th->doff <<2);
>and after these lines skb->data points to payload of the packet and skb->len 
>contains length 
>of packet payload.
>My problem is that i don't understand those lines, you can explain me? and if 
>packet would be 
>UDP or ICMP how can i put skb->data pointing to payload?
>
>Thanks You

Yeh, PaCoRRo, this time your question is clear enough!!

Let me quote part of struct sk_buff{} first:

struct sk_buff {
..
/* Transport Layer header */
union
{
struct tcphdr *th;
..
unsigned char *raw;
} h;

/* Network Layer header */
union
{
struct iphdr *iph;
..
unsigned char *raw;
} nh;

..
}

When yuo get a TCP packet, you have IP header + TCP header + data.
skb->nh.raw points to the very beginning of this packet, ie. the very
beginning of the IP header (since IP header is at the very front).

skb->nh.iph->ihl is "IP header length" expressed in units of 32 bits,
or 4 chars' length (since one char is one byte long).
Thus, skb->nh.iph->ihl*4 is the legnth of the IP header expressed in
bytes.
Look, since skb->h.raw and skb->nh.raw are "unsigned char *" pointers,
the conversion above is necessary.

So, "skb->h.raw = skb->nh.raw + skb->nh.iph->ihl*4;" makes skb->h.raw
points to the very start of TCP header.

skb->h.th->doff can be considered the length of TCP header expressed
in units of 32 bits, or 4 chars' length (just like above). 
skb->h.th->doff<<2 equals skb->h.th->doff*4 in effects, but much faster.

Therefore, "skb->data = (unsigned char *)skb->h.raw +(skb->h.th->doff <<2);"
makes skb->data points to the very start of data.

"skb->len -= skb->nh.iph->ihl*4 + (skb->h.th->doff <<2);" subtracts
IP and TCP header length from skb->len. From then on, skb->len represents
the length of "pure data".

If you receive UDP packets, simply change everything associated with
TCP above (like TCP header, TCP header len) into UDP related. But, ICMP
is different, since ICMP is a netowork-layer protocol.

A ICMP packet encapsulated in IP header is like this:

IP header + ICMP packet.

A ICMP packet is like this:
8-bit type   +   8-bit code     + 16-bit checksum     + various content

It has no "len". So, simply do the following:

skb->data = (unsigned char *)skb->nh.raw + skb->nh.iph->ihl*4;
skb->len -= skb->nh.iph->ihl*4



-- Laudney



<Prev in Thread] Current Thread [Next in Thread>