packet

package
v0.6.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 31, 2026 License: Apache-2.0 Imports: 3 Imported by: 0

Documentation

Overview

Package packet builds the Ethernet, 802.1Q, IPv4, UDP and TCP headers Wireblast transmits.

The design goal is a hot path that allocates nothing and recomputes nothing it does not have to. A Template is built once per queue; changing a flow rewrites only the fields that differ and repairs the checksums incrementally (RFC 1624), never by rescanning the header.

Everything here is pure: no sockets, no system calls, no globals. The layout is computed from an offset rather than hardcoded constants, so an IPv6 builder can be added later without disturbing the mutators.

Index

Constants

View Source
const (
	ProtoTCP = 6
	ProtoUDP = 17
)

IP protocol numbers Wireblast generates.

View Source
const (
	EtherTypeIPv4 = 0x0800
	EtherTypeIPv6 = 0x86DD
	EtherTypeVLAN = 0x8100
)

EtherTypes used by the builders.

View Source
const (
	EthHeaderLen  = 14
	VLANTagLen    = 4
	IPv4HeaderLen = 20
	IPv6HeaderLen = 40
	UDPHeaderLen  = 8
	TCPHeaderLen  = 20
)

Header sizes, in bytes.

Variables

This section is empty.

Functions

func Checksum

func Checksum(b []byte) uint16

Checksum computes the 16-bit one's-complement checksum of b, as used by IPv4, UDP and TCP. An odd-length buffer is padded with a zero byte.

func PseudoHeaderSum

func PseudoHeaderSum(srcIP, dstIP [4]byte, proto uint8, l4Len int) uint32

PseudoHeaderSum returns the unfolded partial sum of the IPv4 pseudo-header used by UDP and TCP: source address, destination address, protocol number and L4 length.

func PseudoHeaderSum6 added in v0.2.0

func PseudoHeaderSum6(srcIP, dstIP [16]byte, nextHdr uint8, l4Len int) uint32

PseudoHeaderSum6 returns the unfolded partial sum of the IPv6 pseudo-header used by UDP and TCP (RFC 8200 section 8.1): the 128-bit source and destination addresses, a 32-bit upper-layer packet length, and the next-header value (the three bytes before it are zero and contribute nothing).

func ReplaceU16

func ReplaceU16(csum, old, new uint16) uint16

ReplaceU16 returns the checksum csum updated for a 16-bit header field whose value changed from old to new, without rescanning the packet.

This is RFC 1624 equation 3, HC' = ~(~HC + ~m + m'), which is correct even when the intermediate sum would otherwise produce the negative-zero result that the naive RFC 1141 formula gets wrong.

func ReplaceU32

func ReplaceU32(csum uint16, old, new [4]byte) uint16

ReplaceU32 returns csum updated for a 32-bit field (an IPv4 address, say) that changed from old to new. It is two 16-bit replacements.

Types

type Layout

type Layout struct {
	HasVLAN bool
	HasIP   bool
	Is6     bool // IPv6 rather than IPv4

	L3Off int // start of the IP header (or of the raw payload)
	L4Off int // start of the UDP/TCP header

	SrcIPOff   int
	DstIPOff   int
	IPCksumOff int
	IPLenOff   int

	SrcPortOff int
	DstPortOff int
	L4LenOff   int // UDP length field; -1 for TCP
	L4CksumOff int // -1 when there is no L4 checksum to maintain

	HeaderLen int   // total header bytes before the payload
	Proto     uint8 // 0 for raw Ethernet
}

Layout records where each mutable field sits in a built frame. Offsets shift by VLANTagLen when a tag is present, which is why nothing downstream hardcodes them.

type Spec

type Spec struct {
	SrcMAC, DstMAC [6]byte
	VLAN           uint16 // 0 means untagged
	PCP            uint8  // 802.1p priority, 0-7

	SrcIP, DstIP     netip.Addr // IPv4; ignored when EtherType is set
	Proto            uint8      // ProtoUDP or ProtoTCP
	SrcPort, DstPort uint16
	TTL              uint8

	// EtherType, when non-zero, builds a raw Ethernet frame with this type
	// and no IP headers at all.
	EtherType uint16

	FrameLen    int // bytes written for each packet
	Cap         int // buffer capacity; >= FrameLen, for later SetFrameLen calls
	PayloadByte byte
}

Spec describes the frame to build. FrameLen and Cap are in bytes actually written to the wire, i.e. excluding the FCS the NIC appends.

type Template

type Template struct {
	// contains filtered or unexported fields
}

Template is a prebuilt frame plus the bookkeeping needed to change a flow field and repair the checksums without rescanning the packet.

A Template is owned by exactly one transmit goroutine. It is not safe for concurrent use, and does not need to be: each queue builds its own.

func Build

func Build(s Spec) (*Template, error)

Build constructs a Template from a Spec.

func (*Template) Bytes

func (t *Template) Bytes() []byte

Bytes returns the current frame. The slice aliases the Template's buffer and is only valid until the next mutation; do not retain it.

func (*Template) Layout

func (t *Template) Layout() Layout

Layout returns where each mutable field lives.

func (*Template) Len

func (t *Template) Len() int

Len returns the current frame length in bytes written (excluding the FCS).

func (*Template) SetDstIP

func (t *Template) SetDstIP(ip netip.Addr)

SetDstIP changes the destination address, repairing the same checksums.

func (*Template) SetDstPort

func (t *Template) SetDstPort(p uint16)

SetDstPort changes the L4 destination port.

func (*Template) SetFrameLen

func (t *Template) SetFrameLen(n int) error

SetFrameLen changes how many bytes the next packet occupies, updating the IPv4 total length and the UDP length. This is how IMIX varies frame size without rebuilding anything.

For UDP the update is incremental and cheap. For TCP the length is part of the checksummed pseudo-header and changes which payload bytes are covered, so the L4 checksum is recomputed in full — TCP modes are fixed-size, so that never happens on a hot path.

func (*Template) SetSrcIP

func (t *Template) SetSrcIP(ip netip.Addr)

SetSrcIP changes the source address, repairing the IPv4 header checksum (IPv6 has none) and, wherever an L4 checksum is maintained, its pseudo-header part. It is a no-op for a non-IP template. The address family must match the one the template was built for.

func (*Template) SetSrcPort

func (t *Template) SetSrcPort(p uint16)

SetSrcPort changes the L4 source port. The IPv4 header checksum does not cover ports, so only the L4 checksum needs repairing — and for UDP, whose checksum is left at zero, not even that.

func (*Template) WriteTo

func (t *Template) WriteTo(dst []byte) int

WriteTo copies the current frame into dst and returns how many bytes it wrote. dst must be at least Len() bytes. This is the only per-packet copy on the transmit path, and it allocates nothing.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL