How to understand the function of pskb_may_pull()?

Alberto Leiva ydahhrk at gmail.com
Wed Jan 7 10:35:22 EST 2015


I think in theory whatever random driver for whatever random hardware
might create this situation. It's not illegal. Anyone can create a
driver outside of the kernel tree, after all. In practice, of course,
this is not the case, because anyone can tell it creates a significant
amount of overhead when the inevitable pskb_may_pull() come into play,
but you don't know what constrictive environments a driver out there
might be operating on.

As I understand it, paging skbs is a technique meant to ease the work
of drivers.
A driver might choose to page "too much" data.
The kernel is prepared for this situation ('Be conservative in what
you do, be liberal in what you accept from others' -
http://en.wikipedia.org/wiki/Robustness_principle).
That's all there is to it, I think.

PS: From your sorta definition, you seem to be assuming
pskb_may_pull() is only used to ensure the IP header is not paged. I
understand this might not be the case, but just to make things clear:
pskb_may_pull() can be used to copy *any* amount of bytes from the
paged part to the head room of the packet (it's not tied to the IP
header's length). For example, you could use it to also guarantee a
TCP header by doing this:
if (!pskb_may_pull(skb, sizeof(struct iphdr) + sizeof(struct tcphdr)))
        goto inhdr_error;


On Wed, Jan 7, 2015 at 2:28 AM, lx <lxlenovostar at gmail.com> wrote:
> hi all:
>       The job of pskb_may_pull is to make sure that the area pointed to by
> skb->data contains a block of
> data at least as big as the IP header, since each IP packet (fragments
> included) must include a complete IP
> header.When we receive a packet , the kernel will call the pkb_may_pull(),
> it looks like the following in line 395:
>
> 373 /*
> 374  *  Main IP Receive routine.
> 375  */
> 376 int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct
> packet_type *pt, struct net_device *orig_dev)
> 377 {
> 378     const struct iphdr *iph;
> 379     u32 len;
> 380
> 381     /* When the interface is in promisc. mode, drop all the crap
> 382      * that it receives, do not try to analyse it.
> 383      */
> 384     if (skb->pkt_type == PACKET_OTHERHOST)
> 385         goto drop;
> 386
> 387
> 388     IP_UPD_PO_STATS_BH(dev_net(dev), IPSTATS_MIB_IN, skb->len);
> 389
> 390     if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
> 391         IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
> 392         goto out;
> 393     }
> 394
> 395     if (!pskb_may_pull(skb, sizeof(struct iphdr)))
> 396         goto inhdr_error;
> 397
> 398     iph = ip_hdr(skb);
> 399
>
> And the definition of pkb_may_pull() looks like the following:
>
> 1708 static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len)
> 1709 {
> 1710     if (likely(len <= skb_headlen(skb)))
> 1711         return 1;
> 1712     if (unlikely(len > skb->len))
> 1713         return 0;
> 1714     return __pskb_pull_tail(skb, len - skb_headlen(skb)) != NULL;
> 1715 }
>
> I just want to know which situation make the skb->data contains a block of
> data less than the IP header?
> I think this packet can't send by kernel at all.
> Thank you.
>
> _______________________________________________
> Kernelnewbies mailing list
> Kernelnewbies at kernelnewbies.org
> http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
>



More information about the Kernelnewbies mailing list