UDP hijacking is an optional mechanism that encapsulates Homa packets as UDP
datagrams, using IPPROTO_UDP instead of IPPROTO_HOMA as the IP protocol.
It works alongside the existing TCP hijacking feature — only one can be active
at a time on a given socket.
TCP hijacking uses SYN+RST flag combinations that never occur in real TCP
traffic. However, some firewalls (particularly on virtualized environments)
inspect TCP flags and drop packets with these "impossible" flag combinations.
UDP hijacking avoids this issue entirely since UDP has no flags for firewalls
to inspect.
| Feature | TCP hijacking | UDP hijacking |
|---|---|---|
| NIC TSO support | Yes (multi-segment) | No (single-segment) |
| Firewall friendly | No (SYN+RST blocked) | Yes |
| GSO segments/packet | Multiple | 1 (segs_per_gso = 1) |
| IP protocol | IPPROTO_TCP |
IPPROTO_UDP |
| sysctl | hijack_tcp |
hijack_udp |
Because NICs do not perform TSO on UDP packets the same way they do for TCP,
UDP hijacking forces segs_per_gso = 1 (one segment per GSO packet). This
means each Homa data packet is sent individually rather than being batched
into large TSO super-packets.
Enable UDP hijacking at runtime via sysctl:
# Enable UDP hijacking (disable TCP hijacking first if it was on)
sudo sysctl net.homa.hijack_tcp=0
sudo sysctl net.homa.hijack_udp=1To switch back to TCP hijacking:
sudo sysctl net.homa.hijack_udp=0
sudo sysctl net.homa.hijack_tcp=1Note: If both hijack_tcp and hijack_udp are set, TCP hijacking takes
priority (sockets opened while both are set will use TCP).
-
Socket initialization (
homa_hijack_sock_init): When a new Homa socket is created, ifhijack_udpis set the socket'ssk_protocolis set toIPPROTO_UDP. The kernel then transmits packets with a UDP IP protocol. -
Header setup (
homa_udp_hijack_set_hdr): Before transmission, Homa writes UDP-compatible header fields:flagsis set toHOMA_HIJACK_FLAGS(6) — a marker value.urgentis set toHOMA_HIJACK_URGENT(0xb97d) — a second marker.- Bytes 4-5 of the transport header are overwritten with the UDP length.
- Bytes 6-7 are set up for proper UDP checksum offload.
- Because the sequence field (bytes 4-7) is overwritten, the packet offset
is stored in
seg.offsetinstead.
-
GSO geometry: With UDP hijacking,
segs_per_gsois forced to 1 (no multi-segment GSO batching).
-
GRO interception (
homa_udp_hijack_gro_receive): Homa hooks into the UDP GRO pipeline. When a UDP packet arrives, Homa checks:- At least 20 bytes of transport header are available.
flags == HOMA_HIJACK_FLAGSandurgent == HOMA_HIJACK_URGENT.
-
If the packet is identified as a Homa-over-UDP packet, the IP protocol is rewritten to
IPPROTO_HOMAand the packet is handed to Homa's normal GRO handler. Real UDP packets are passed through to the normal UDP stack.
The is_homa_pkt() function in homa_qdisc.c recognizes both TCP-hijacked
and UDP-hijacked packets, ensuring they receive proper Homa qdisc treatment.
| File | Changes |
|---|---|
homa_wire.h |
No new defines needed (reuses HOMA_HIJACK_FLAGS and HOMA_HIJACK_URGENT) |
homa_impl.h |
Added hijack_udp field to struct homa |
homa_hijack.h |
Added homa_udp_hijack_set_hdr(), homa_sock_udp_hijacked(), homa_skb_udp_hijacked(); updated homa_hijack_sock_init() |
homa_hijack.c |
Added homa_udp_hijack_init(), homa_udp_hijack_end(), homa_udp_hijack_gro_receive() |
homa_outgoing.c |
Added segs_per_gso=1 for UDP; added UDP header calls in xmit paths |
homa_plumbing.c |
Added hijack_udp sysctl; added UDP init/end calls |
homa_qdisc.c |
Added IPPROTO_UDP check in is_homa_pkt() |
util/homa_test.cc |
Added udp_ping(), test_udp(), "udp" test command |
util/server.cc |
Added udp_server() function |
util/cp_node.cc |
Added udp_server and udp_client classes, "udp" protocol option |
| Constant | Value | Purpose |
|---|---|---|
HOMA_HIJACK_FLAGS |
6 | Marker in the flags field (shared with TCP hijack) |
HOMA_HIJACK_URGENT |
0xb97d | Marker in the urgent field (shared with TCP hijack) |