VIDEOS 》 Linux Kernel sk_buff data-structure - Episode-11 to Episode-18

Watch Linux Kernel sk_buff data-structure - Episode-1 to Episode-10 Videos HERE.

You can check fragmented packets as suggested in the video by tapping RX path in net/core/dev.c :: __netif_receive_skb_core() API as shown below:

static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc)


//thelinuxchannel - start
	if(skb_shinfo(skb)->nr_frags) {  printk("skb - is fragmented !\n"); }
//thelinuxchannel - end



For more details refer Linux Source:

skb_clone - duplicate an sk_buff - http://elixir.free-electrons.com/linux/latest/source/net/core/skbuff.c#L1016
skb_copy - create private copy of an sk_buff - http://elixir.free-electrons.com/linux/latest/source/net/core/skbuff.c#L1094

And here is the copy paste of skb_clone() and skb_copy() APIs (/net/core/skbuff.c) from the Kernel-source version 4.13 for quick reference:

 *	skb_clone	-	duplicate an sk_buff
 *	@skb: buffer to clone
 *	@gfp_mask: allocation priority
 *	Duplicate an &sk_buff. The new one is not owned by a socket. Both
 *	copies share the same packet data but not structure. The new
 *	buffer has a reference count of 1. If the allocation fails the
 *	function returns %NULL otherwise the new buffer is returned.
 *	If this function is called from an interrupt gfp_mask() must be

struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
	struct sk_buff_fclones *fclones = container_of(skb,
						       struct sk_buff_fclones,
	struct sk_buff *n;

	if (skb_orphan_frags(skb, gfp_mask))
		return NULL;

	if (skb->fclone == SKB_FCLONE_ORIG &&
	    refcount_read(&fclones->fclone_ref) == 1) {
		n = &fclones->skb2;
		refcount_set(&fclones->fclone_ref, 2);
	} else {
		if (skb_pfmemalloc(skb))
			gfp_mask |= __GFP_MEMALLOC;

		n = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
		if (!n)
			return NULL;

		kmemcheck_annotate_bitfield(n, flags1);

	return __skb_clone(n, skb);


 *	skb_copy	-	create private copy of an sk_buff
 *	@skb: buffer to copy
 *	@gfp_mask: allocation priority
 *	Make a copy of both an &sk_buff and its data. This is used when the
 *	caller wishes to modify the data and needs a private copy of the
 *	data to alter. Returns %NULL on failure or the pointer to the buffer
 *	on success. The returned buffer has a reference count of 1.
 *	As by-product this function converts non-linear &sk_buff to linear
 *	one, so that &sk_buff becomes completely private and caller is allowed
 *	to modify all the data of returned buffer. This means that this
 *	function is not recommended for use in circumstances when only
 *	header is going to be modified. Use pskb_copy() instead.

struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask)
	int headerlen = skb_headroom(skb);
	unsigned int size = skb_end_offset(skb) + skb->data_len;
	struct sk_buff *n = __alloc_skb(size, gfp_mask,
					skb_alloc_rx_flag(skb), NUMA_NO_NODE);

	if (!n)
		return NULL;

	/* Set the data pointer */
	skb_reserve(n, headerlen);
	/* Set the tail pointer and length */
	skb_put(n, skb->len);

	if (skb_copy_bits(skb, -headerlen, n->head, headerlen + skb->len))

	copy_skb_header(n, skb);
	return n;

skb_headroom - bytes at buffer head - http://elixir.free-electrons.com/linux/latest/source/include/linux/skbuff.h#L2023
skb_tailroom - bytes at buffer end - http://elixir.free-electrons.com/linux/latest/source/include/linux/skbuff.h#L2034

And here is the copy paste of skb_headroom() and skb_tailroom() APIs (/include/linux/skbuff.h) from the Kernel-source version 4.13 for quick reference:

 *	skb_headroom - bytes at buffer head
 *	@skb: buffer to check
 *	Return the number of bytes of free space at the head of an &sk_buff.
static inline unsigned int skb_headroom(const struct sk_buff *skb)
	return skb->data - skb->head;

 *	skb_tailroom - bytes at buffer end
 *	@skb: buffer to check
 *	Return the number of bytes of free space at the tail of an sk_buff
static inline int skb_tailroom(const struct sk_buff *skb)
	return skb_is_nonlinear(skb) ? 0 : skb->end - skb->tail;

skb_put - add data to a buffer - http://elixir.free-electrons.com/linux/latest/source/net/core/skbuff.c#L1443

And here is the copy paste of skb_put() API (/net/core/skbuff.c) from the Kernel-source version 4.13 for quick reference:

 *	skb_put - add data to a buffer
 *	@skb: buffer to use
 *	@len: amount of data to add
 *	This function extends the used data area of the buffer. If this would
 *	exceed the total buffer size the kernel will panic. A pointer to the
 *	first byte of the extra data is returned.
void *skb_put(struct sk_buff *skb, unsigned int len)
	void *tmp = skb_tail_pointer(skb);
	skb->tail += len;
	skb->len  += len;
	if (unlikely(skb->tail > skb->end))
		skb_over_panic(skb, len, __builtin_return_address(0));
	return tmp;

Suggested Topics:

Video Episodes :: Linux Kernel programming

Join The Linux Channel :: Facebook Group ↗

Visit The Linux Channel :: on Youtube ↗

Join a course:

💎 Linux, Kernel, Networking and Device Drivers: PDF Brochure
💎 PhD or equivalent (or Post Doctoral) looking for assistance: Details
💎 ... or unlimited life-time mentorship: Details

💗 Help shape the future: Sponsor/Donate

Recommended Topics:
Featured Video:
Watch on Youtube - [89/0] 205 VLOG - Choose the right harddisk for your NAS ↗

Trending Video:
Watch on Youtube - [9795/0] Linux Kernel Networking Sub-system - episode3 net/core, net/sched, net/socket.c APIs ↗

Recommended Video:
Watch on Youtube - [461/0] 0x17d Linux Kernel Programming | Tracking changes in Kernel Source code | The Linux Channel ↗