Networking

net/ is the largest actively-developed subsystem in the kernel, the one with the strictest process, and the one with the best observability. It is also, for a driver-shaped contribution, one of the more approachable — there are hundreds of NIC drivers and a steady supply of small real work.

The one idea that unlocks it: a packet is a struct sk_buff, and it travels the entire stack as one object. Layers do not copy it. They move pointers into it.


Orient Yourself First

cd ~/kernel/linux

./scripts/get_maintainer.pl --scm --status -f net/core/dev.c
git log --oneline --since="6 months ago" -- net/ | wc -l
git log --oneline --since="6 months ago" -- drivers/net/ | wc -l
git log --since="1 year ago" --format='%cN' -- net/ | sort | uniq -c | sort -rn | head

ls net/
ls Documentation/networking/ | head -30
$EDITOR Documentation/process/maintainer-netdev.rst      # READ THIS BEFORE PATCHING

Predict first: how many commits land in net/ and drivers/net/ in six months? It is a larger number than any other subsystem, and it explains why the process here is stricter than elsewhere.


Why It Matters

BecauseConsequence
It handles millions of packets per second per coreEvery per-packet cost is multiplied enormously
It is entirely driven by external, untrusted inputEvery parsing bug is a remote attack surface
It runs in softirq context on the hot pathCannot sleep, cannot allocate freely, cannot take mutexes
It is programmable at multiple layersXDP, tc-BPF, netfilter, and sockmap all intercept the same packet
Its interfaces are uapiNetlink, sockets, and /proc/net are all frozen contracts

Where the Code Is

   application:  send() / recv()
        ├── net/socket.c            the syscall layer
        ├── net/ipv4/tcp*.c         the protocol
        ├── net/ipv4/ip_output.c    routing and IP
        ├── net/core/dev.c          THE DEVICE LAYER -- the pivot point
        ├── net/sched/              qdiscs: queueing and shaping
        └── drivers/net/            the NIC driver
                └── hardware
AreaWhat lives there
net/core/dev.cThe centre. netif_receive_skb, dev_queue_xmit, NAPI. Read this file.
net/core/skbuff.cThe sk_buff itself: allocation, cloning, splitting
net/ipv4/, net/ipv6/The protocols: TCP, UDP, ICMP, routing
net/socket.c, net/core/sock.cThe socket layer, and the syscall entry points
net/sched/qdiscs and traffic classifiers; also where tc-BPF hooks live
net/netfilter/The hooks, conntrack, and nftables
net/bpf/, net/core/filter.cXDP and BPF program helpers
drivers/net/ethernet/Real NIC drivers. Hundreds of them.
drivers/net/virtio_net.c, veth.cWhat you can actually run in a VM
$EDITOR Documentation/networking/napi.rst
$EDITOR Documentation/networking/scaling.rst
$EDITOR Documentation/networking/skbuff.rst 2>/dev/null || ls Documentation/networking/ | head -40

The Structures

   struct sk_buff           ONE PACKET, from the wire to the socket
     ├── head / data / tail / end   ← four pointers into ONE buffer
     ├── len, data_len              total, and how much is in frags
     ├── protocol, pkt_type
     ├── dev      ──▶ struct net_device
     ├── sk       ──▶ struct sock            (once it reaches a socket)
     ├── network_header, transport_header, mac_header   ← OFFSETS
     ├── cb[48]                     scratch space for the CURRENT layer
     └── skb_shared_info (at the end of the buffer)
           ├── frags[]              page fragments -- the data need not be
           │                        in the linear part at all
           └── frag_list            for GSO/GRO chains

   struct net_device        ONE INTERFACE
     ├── netdev_ops ──▶ ndo_open, ndo_start_xmit, ndo_stop, ...
     ├── ethtool_ops
     ├── _rx[] / _tx[]              per-queue receive and transmit state
     └── napi_list                  the poll contexts

   struct sock              ONE SOCKET (the protocol-independent part)
     ├── sk_receive_queue / sk_write_queue
     ├── sk_prot ──▶ struct proto   tcp_prot, udp_prot, ...
     └── sk_data_ready, sk_write_space   ← the callbacks that wake readers
rg -n "struct sk_buff \{" -A 80 include/linux/skbuff.h | head -90
rg -n "struct net_device_ops \{" -A 40 include/linux/netdevice.h
rg -n "struct sock \{" -A 60 include/net/sock.h | head -70

The Concepts

ChapterAnswers
The sk_buffWhat is a packet, and why is it never copied?
The RX and TX PathsHow does a packet get from the wire to a socket, and back?
Sockets, Filtering, and XDPWho is allowed to intercept it, and where?

Then Lab 13 attaches an XDP program and counts packets before the kernel has built an sk_buff at all.


How to Read It

 1. Documentation/networking/napi.rst -- the receive model, in ten minutes.

 2. struct sk_buff, and specifically the FOUR POINTERS. Draw them. Nothing
    else in this subsystem makes sense until you have.

 3. ONE PATH, receive:
      driver's NAPI poll ──▶ napi_gro_receive ──▶ netif_receive_skb
        ──▶ ip_rcv ──▶ netfilter hooks ──▶ ip_local_deliver
        ──▶ tcp_v4_rcv ──▶ the socket's receive queue ──▶ wake the reader

 4. THE SECOND PATH, transmit, which is NOT a mirror image:
      tcp_sendmsg ──▶ ip_queue_xmit ──▶ dev_queue_xmit ──▶ qdisc
        ──▶ ndo_start_xmit ──▶ the NIC

 5. net/core/dev.c is the pivot. Everything above it is protocol;
    everything below is device.

Observing It

Networking has the best observability in the kernel, and one feature in particular is disproportionately useful.

# Interface and queue state
ip -s link; ip -s -s link show dev eth0
ethtool -S eth0 2>/dev/null | head -30       # driver-level counters
cat /proc/net/softnet_stat                   # per-CPU: processed, dropped, time_squeeze
cat /proc/net/snmp /proc/net/netstat | head

# Sockets
ss -tinm 2>/dev/null | head -20              # per-socket TCP internals

# Tracepoints
ls /sys/kernel/tracing/events/net/ /sys/kernel/tracing/events/tcp/ /sys/kernel/tracing/events/skb/

# THE ONE TO KNOW: every dropped packet, WITH A REASON
sudo bpftrace -e 'tracepoint:skb:kfree_skb { @[args.reason] = count(); }'
rg -n "SKB_DROP_REASON_" include/net/dropreason-core.h | head -30

Tip: kfree_skb carries a drop reason — an enum naming why the packet was discarded: checksum failure, no socket, netfilter drop, queue full, and dozens more. Before this existed, "the packet vanished" was a day of work. Now it is one command. It is the single highest-value thing in this chapter.


The Process Here Is Different

netdev is the strictest subsystem in the kernel about process, and violating its rules is the most common way a good patch gets bounced.

$EDITOR Documentation/process/maintainer-netdev.rst
RuleDetail
Say which tree in the subject[PATCH net] for fixes to the current release; [PATCH net-next] for features. Not optional.
net-next closes during the merge windowCheck git describe and the list before sending a feature
Patchwork is authoritativeYour patch's state there is how the maintainers track it
Reverse Christmas treeLocal variable declarations sorted longest-line-first. Networking only, and enforced.
A different block-comment stylenet/ opens block comments differently from the rest of the tree. Match the file.
Fixes need Fixes:Rigorously enforced; stable backports depend on it
No cover letter for a single patchAnd a required one for a series

What a Good First Contribution Looks Like

TargetWhy it is plausible
A driver fix in drivers/net/ethernet/<vendor>/Hundreds of drivers, many lightly maintained, real bugs
Adding drop reasonsConverting a bare kfree_skb() to kfree_skb_reason() with the right enum is small, mechanical, and genuinely valuable
Selftests in tools/testing/selftests/net/Large, active, and always wanting more coverage
Documentation in Documentation/networking/Big and uneven
A syzbot networking bugSteady supply, with reproducers
An ethtool counter or a tracepointAdditive, low risk, useful
veth/netdevsim/virtio_net workTestable entirely in a VM, with no hardware

Tip: The drop-reason conversion is an unusually good first contribution: the change is mechanical, the correct enum value requires you to actually understand the code path, reviewers can verify it easily, and every one makes a real debugging session shorter for someone. Find candidates with:

rg -n "\bkfree_skb\(" net/ drivers/net/ | wc -l
rg -n "\bkfree_skb\(" net/ipv4/ | head -20

Common Misconceptions

MisconceptionReality
"Each layer copies the packet"Nothing copies. Layers move skb->data and record header offsets.
"An interrupt per packet"Under load, NAPI switches to polling — the interrupt is disabled and a softirq drains the ring
"The receive path runs in my process"It runs in softirq context, on whichever CPU took the interrupt. Your process is woken at the end.
"The TX path is RX in reverse"It is not. Different queueing, different locking, different context.
"skb->len is the data in the buffer"len is the total; data_len is how much lives in page frags. The linear part may be nearly empty.
"XDP is just a faster BPF hook"It runs before an sk_buff exists. That is the entire performance argument, and the entire limitation.
"Dropped packets are a mystery"kfree_skb has a reason enum. One command.
"ping measures the network"It measures the network plus two scheduling delays plus two softirq latencies

Validation / Self-check

  1. What is a sk_buff and why does the stack never copy the packet?
  2. Name the four pointers in an sk_buff and what each delimits.
  3. What is the difference between skb->len and skb->data_len?
  4. Which file is the pivot between protocol and device, and what are the two functions to read in it?
  5. What is NAPI and what problem does it solve? What changes under load?
  6. In what context does the receive path run, and what does that forbid?
  7. Why is the transmit path not a mirror image of receive?
  8. What is kfree_skb's drop reason, and why is it the most valuable observability feature here?
  9. Give four rules netdev enforces that other subsystems do not.
  10. Name four plausible first contributions here, and say which needs no hardware.
  11. Where does XDP run relative to sk_buff allocation, and what does that buy and cost?
  12. What does /proc/net/softnet_stat's time_squeeze column mean?

Next: The sk_buff — the one structure everything here is about.