VIDEOS 》 Linux Kernel sk_buff data-structure - Episode-1 to Episode-10

Watch Linux Kernel sk_buff data-structure - Episode-11 to Episode-18 Videos HERE.

skb_pull - remove data from the start of a buffer -

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

 *	skb_pull - remove data from the start of a buffer
 *	@skb: buffer to use
 *	@len: amount of data to remove
 *	This function removes data from the start of a buffer, returning
 *	the memory to the headroom. A pointer to the next data in the buffer
 *	is returned. Once the data has been pulled future pushes will overwrite
 *	the old data.
void *skb_pull(struct sk_buff *skb, unsigned int len)
	return skb_pull_inline(skb, len);

Which points to skb_pull_inline() as you can see above, and if we trace, we get the implementation in /include/linux/skbuff.h. skb_pull_inline() internally calls __skb_pull() wrapper API which has the real implementation of the same. And just above the same you can also see the skb_pull() function prototype.

void *skb_pull(struct sk_buff *skb, unsigned int len);
static inline void *__skb_pull(struct sk_buff *skb, unsigned int len)
	skb->len -= len;
	BUG_ON(skb->len < skb->data_len);
	return skb->data += len;

static inline void *skb_pull_inline(struct sk_buff *skb, unsigned int len)
	return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len);

skb_trim - remove end from a buffer -

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

 *	skb_trim - remove end from a buffer
 *	@skb: buffer to alter
 *	@len: new length
 *	Cut the length of a buffer down by removing data from the tail. If
 *	the buffer is already under the length specified it is not modified.
 *	The skb must be linear.
void skb_trim(struct sk_buff *skb, unsigned int len)
	if (skb->len > len)
		__skb_trim(skb, len);

Which points to __skb_trim() wrapper API as you can see above, and if we trace, we get the implementation in /include/linux/skbuff.h. __skb_trim() internally calls __skb_set_length() API which has most of the core implementation of the same. And just below the same you can also see the skb_trim() function prototype.

static inline void __skb_set_length(struct sk_buff *skb, unsigned int len)
	if (unlikely(skb_is_nonlinear(skb))) {
	skb->len = len;
	skb_set_tail_pointer(skb, len);

static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
	__skb_set_length(skb, len);

void skb_trim(struct sk_buff *skb, unsigned int len);

skb_push - add data to the start of a buffer -

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

 *	skb_push - add data to the start of a buffer
 *	@skb: buffer to use
 *	@len: amount of data to add
 *	This function extends the used data area of the buffer at the buffer
 *	start. If this would exceed the total buffer headroom the kernel will
 *	panic. A pointer to the first byte of the extra data is returned.
void *skb_push(struct sk_buff *skb, unsigned int len)
	skb->data -= len;
	skb->len  += len;
	if (unlikely(skb->data<skb->head))
		skb_under_panic(skb, len, __builtin_return_address(0));
	return skb->data;

struct sk_buff data-structure -
Routines having to do with the struct sk_buff -
Linux Kernel Networking subsystem -

And here is the copy paste of struct sk_buff data-structure (/include/linux/skbuff.h) from the Kernel-source version 4.13 for quick reference:

 *	struct sk_buff - socket buffer
 *	@next: Next buffer in list
 *	@prev: Previous buffer in list
 *	@tstamp: Time we arrived/left
 *	@rbnode: RB tree node, alternative to next/prev for netem/tcp
 *	@sk: Socket we are owned by
 *	@dev: Device we arrived on/are leaving by
 *	@cb: Control buffer. Free for use by every layer. Put private vars here
 *	@_skb_refdst: destination entry (with norefcount bit)
 *	@sp: the security path, used for xfrm
 *	@len: Length of actual data
 *	@data_len: Data length
 *	@mac_len: Length of link layer header
 *	@hdr_len: writable header length of cloned skb
 *	@csum: Checksum (must include start/offset pair)
 *	@csum_start: Offset from skb->head where checksumming should start
 *	@csum_offset: Offset from csum_start where checksum should be stored
 *	@priority: Packet queueing priority
 *	@ignore_df: allow local fragmentation
 *	@cloned: Head may be cloned (check refcnt to be sure)
 *	@ip_summed: Driver fed us an IP checksum
 *	@nohdr: Payload reference only, must not modify header
 *	@pkt_type: Packet class
 *	@fclone: skbuff clone status
 *	@ipvs_property: skbuff is owned by ipvs
 *	@tc_skip_classify: do not classify packet. set by IFB device
 *	@tc_at_ingress: used within tc_classify to distinguish in/egress
 *	@tc_redirected: packet was redirected by a tc action
 *	@tc_from_ingress: if tc_redirected, tc_at_ingress at time of redirect
 *	@peeked: this packet has been seen already, so stats have been
 *		done for it, don't do them again
 *	@nf_trace: netfilter packet trace flag
 *	@protocol: Packet protocol from driver
 *	@destructor: Destruct function
 *	@_nfct: Associated connection, if any (with nfctinfo bits)
 *	@nf_bridge: Saved data about a bridged frame - see br_netfilter.c
 *	@skb_iif: ifindex of device we arrived on
 *	@tc_index: Traffic control index
 *	@hash: the packet hash
 *	@queue_mapping: Queue mapping for multiqueue devices
 *	@xmit_more: More SKBs are pending for this queue
 *	@ndisc_nodetype: router type (from link layer)
 *	@ooo_okay: allow the mapping of a socket to a queue to be changed
 *	@l4_hash: indicate hash is a canonical 4-tuple hash over transport
 *		ports.
 *	@sw_hash: indicates hash was computed in software stack
 *	@wifi_acked_valid: wifi_acked was set
 *	@wifi_acked: whether frame was acked on wifi or not
 *	@no_fcs:  Request NIC to treat last 4 bytes as Ethernet FCS
 *	@csum_not_inet: use CRC32c to resolve CHECKSUM_PARTIAL
 *	@dst_pending_confirm: need to confirm neighbour
 *	@napi_id: id of the NAPI struct this skb came from
 *	@secmark: security marking
 *	@mark: Generic packet mark
 *	@vlan_proto: vlan encapsulation protocol
 *	@vlan_tci: vlan tag control information
 *	@inner_protocol: Protocol (encapsulation)
 *	@inner_transport_header: Inner transport layer header (encapsulation)
 *	@inner_network_header: Network layer header (encapsulation)
 *	@inner_mac_header: Link layer header (encapsulation)
 *	@transport_header: Transport layer header
 *	@network_header: Network layer header
 *	@mac_header: Link layer header
 *	@tail: Tail pointer
 *	@end: End pointer
 *	@head: Head of buffer
 *	@data: Data head pointer
 *	@truesize: Buffer size
 *	@users: User count - see {datagram,tcp}.c

struct sk_buff {
	union {
		struct {
			/* These two members must be first. */
			struct sk_buff		*next;
			struct sk_buff		*prev;

			union {
				ktime_t		tstamp;
				u64		skb_mstamp;
		struct rb_node	rbnode; /* used in netem & tcp stack */
	struct sock		*sk;

	union {
		struct net_device	*dev;
		/* Some protocols might use this space to store information,
		 * while device pointer would be NULL.
		 * UDP receive path is one user.
		unsigned long		dev_scratch;
	 * This is the control buffer. It is free to use for every
	 * layer. Please put your private variables there. If you
	 * want to keep them across layers you have to do a skb_clone()
	 * first. This is owned by whoever has the skb queued ATM.
	char			cb[48] __aligned(8);

	unsigned long		_skb_refdst;
	void			(*destructor)(struct sk_buff *skb);
	struct	sec_path	*sp;
	unsigned long		 _nfct;
	struct nf_bridge_info	*nf_bridge;
	unsigned int		len,
	__u16			mac_len,

	/* Following fields are _not_ copied in __copy_skb_header()
	 * Note that queue_mapping is here mostly to fill a hole.
	__u16			queue_mapping;

/* if you move cloned around you also must adapt those constants */
#define CLONED_MASK	(1 << 7)
#define CLONED_MASK	1
#define CLONED_OFFSET()		offsetof(struct sk_buff, __cloned_offset)

	__u8			__cloned_offset[0];
	__u8			cloned:1,
				__unused:1; /* one bit hole */

	/* fields enclosed in headers_start/headers_end are copied
	 * using a single memcpy() in __copy_skb_header()
	/* private: */
	__u32			headers_start[0];
	/* public: */

/* if you move pkt_type around you also must adapt those constants */
#define PKT_TYPE_MAX	(7 << 5)
#define PKT_TYPE_MAX	7
#define PKT_TYPE_OFFSET()	offsetof(struct sk_buff, __pkt_type_offset)

	__u8			__pkt_type_offset[0];
	__u8			pkt_type:3;
	__u8			pfmemalloc:1;
	__u8			ignore_df:1;

	__u8			nf_trace:1;
	__u8			ip_summed:2;
	__u8			ooo_okay:1;
	__u8			l4_hash:1;
	__u8			sw_hash:1;
	__u8			wifi_acked_valid:1;
	__u8			wifi_acked:1;

	__u8			no_fcs:1;
	/* Indicates the inner headers are valid in the skbuff. */
	__u8			encapsulation:1;
	__u8			encap_hdr_csum:1;
	__u8			csum_valid:1;
	__u8			csum_complete_sw:1;
	__u8			csum_level:2;
	__u8			csum_not_inet:1;

	__u8			dst_pending_confirm:1;
	__u8			ndisc_nodetype:2;
	__u8			ipvs_property:1;
	__u8			inner_protocol_type:1;
	__u8			remcsum_offload:1;
	__u8			offload_fwd_mark:1;
	__u8			tc_skip_classify:1;
	__u8			tc_at_ingress:1;
	__u8			tc_redirected:1;
	__u8			tc_from_ingress:1;

	__u16			tc_index;	/* traffic control index */

	union {
		__wsum		csum;
		struct {
			__u16	csum_start;
			__u16	csum_offset;
	__u32			priority;
	int			skb_iif;
	__u32			hash;
	__be16			vlan_proto;
	__u16			vlan_tci;
#if defined(CONFIG_NET_RX_BUSY_POLL) || defined(CONFIG_XPS)
	union {
		unsigned int	napi_id;
		unsigned int	sender_cpu;
	__u32		secmark;

	union {
		__u32		mark;
		__u32		reserved_tailroom;

	union {
		__be16		inner_protocol;
		__u8		inner_ipproto;

	__u16			inner_transport_header;
	__u16			inner_network_header;
	__u16			inner_mac_header;

	__be16			protocol;
	__u16			transport_header;
	__u16			network_header;
	__u16			mac_header;

	/* private: */
	__u32			headers_end[0];
	/* public: */

	/* These elements must be at the end, see alloc_skb() for details.  */
	sk_buff_data_t		tail;
	sk_buff_data_t		end;
	unsigned char		*head,
	unsigned int		truesize;
	refcount_t		users;

This is a complete reshoot of my earlier episode (i.e: Linux Kernel sk_buff data-structure - part1 - Introduction):

And here is my old episode of the same:

Suggested Topics:

Video Episodes :: Linux Kernel programming

Linux Kernel Compilation ↗
Thursday' 09-Jul-2020

Linux Kernel - Containers and Namespaces ↗
Thursday' 09-Jul-2020

Linux Kernel FileSystems Subsystem ↗
Thursday' 09-Jul-2020

Linux Kernel Architecture ↗
Thursday' 09-Jul-2020

Linux ioctl() API interface ↗
Thursday' 09-Jul-2020
Watch detailed videos and read topics on Linux Kernel Programming and Linux ioctl() API interface

Linux Kernel Programming - Device Drivers ↗
Thursday' 09-Jul-2020
Watch detailed videos and read topics on Linux Kernel Programming - Device Drivers

Linux Operating System - User-space Processes ↗
Thursday' 09-Jul-2020

Linux Kernel Programming ↗
Thursday' 09-Jul-2020

Linux Kernel /proc Interface ↗
Thursday' 09-Jul-2020

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

Tópicos recomendados:
Featured Video:
Assista no Youtube - [97//0] B.E and M.E Final Year Projects - Execute your project ↗

Roadmap - How to become Linux Kernel Developer - Device Drivers Programmer and a Systems Software Expert ↗
Thursday' 09-Jul-2020
Many viewers and even sometimes my students ask me how I can become a kernel programmer or just device driver developer and so on. So I shot this video (and an add-on video) where I summarized steps and a roadmap to become a full-fledged Linux Kernel Developer.

Compiling a C Compiler with a C Compilter | Compile gcc with gcc ↗
Thursday' 09-Jul-2020
The fundamental aspect of a programming language compiler is to translate code written from language to other. But most commonly compilers will compile code written in high-level human friendly language such as C, C++, Java, etc. to native CPU architecture specific (machine understandable) binary code which is nothing but sequence of CPU instructions. Hence if we see that way we should able to compile gcc Compiler source code with a gcc Compiler binary.

AT&T Archives: The UNIX Operating System ↗
Thursday' 09-Jul-2020

CEO, CTO Talk ↗
Thursday' 09-Jul-2020

Arduino UNO - RO Water Purifier Controller ↗
Thursday' 09-Jul-2020
Here is a Youtube VLOG of my DIY RO Water Purifier Controller done via Arduino UNO. I want the Arduino UNO to control the RO pump, so that it pumps for a specific duration and stops automatically. This is done via Opto-isolated 4 Channel 5V 10A Relay Board meant for Arduino UNO, Raspberry Pi or similar SoC boards which offers GPIO pins. To this relay I have connected the RO water purifier booster pump which works at 24V DC connected via 220V AC to 24V DC power supply adaptar. I have also connected a small active 5V buzzer to notify the progress and completion as it fills the tank/canister.

CYRIL INGÉNIERIE - CoreFreq Linux CPU monitoring software ↗
Thursday' 09-Jul-2020

Nmap Network Scanning ↗
Thursday' 09-Jul-2020

Programming Language Performance and Overheads ↗
Thursday' 09-Jul-2020
A detailed Youtube video series of various programming language performance and overheads - a big picture

Telnet installation and remote access ↗
Thursday' 09-Jul-2020

Linux Kernel Network Programming - Transport Layer L4 TCP/UDP Registration - Protocol APIs ↗
Thursday' 09-Jul-2020

Trending Video:
Assista no Youtube - [1782//0] Linux Kernel sk_buff data-structure -part3 - skbuff Kernel Architecture ↗

Online Course - Linux TUN/TAP virtual network interfaces ↗
Thursday' 09-Jul-2020

Recommended Video:
Assista no Youtube - [8054//0] 352 Linux user-space - Shared Memory IPC - Live Demo and Example ↗