dnsquery

package
v0.0.4 Latest Latest
Warning

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

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

Documentation

Index

Constants

View Source
const (
	// MaxName is the key width shared with the domain interning in
	// pkg/bpf/egressfilter, so a question this decoder accepts is a question a
	// policy could have named.
	MaxName = 128

	// EventSize is the minimum number of bytes DecodeQueryEvent needs.
	EventSize = offName + MaxName // 140
)

Byte layout of `struct dns_query_event` in _cprog/maps.h. Little-endian, in the natural C field order with no internal padding:

off  size  field
  0     8  cgroup_id  __u64
  8     4  name_len   __u32  (offset of whatever follows the name, so it
                              counts the terminating zero byte)
 12   128  name       __u8[128] (wire format, lowercased, zero padded)

The kernel never writes the terminating zero: it is the zero padding, which is why the decodable name is name_len-1 bytes long.

View Source
const (
	StatRingbufFull    = 0
	StatNameUnreadable = 1
)

Stat indices in the BPF `stats` per-CPU array, mirroring enum dns_query_stat in _cprog/maps.h.

View Source
const DefaultStatsInterval = 30 * time.Second

DefaultStatsInterval is how often the kernel-side loss counters are read.

View Source
const SourceName = "dnsquery"

SourceName is the name this source reports to the collector. It is also the label used for its drop metrics.

Variables

View Source
var (
	// ErrTruncated means the kernel handed over fewer bytes than the layout
	// requires; the Go and C sides disagree, or the record is damaged.
	ErrTruncated = errors.New("dnsquery: truncated kernel event")
	// ErrBadName means name_len or the label sequence itself is invalid.
	ErrBadName = errors.New("dnsquery: malformed question name")
)
View Source
var ErrNotLoaded = errors.New("dnsquery: bpf objects not loaded")

ErrNotLoaded is returned by map-touching methods on an Observer built without kernel objects.

View Source
var StatNames = [statCount]string{
	StatRingbufFull:    "ringbuf_full",
	StatNameUnreadable: "name_unreadable",
}

StatNames labels each stat index for metrics and logs.

Functions

func DecodeQueryEvent

func DecodeQueryEvent(b []byte) (runtimeevent.Event, error)

DecodeQueryEvent converts one kernel record into a normalized event.

Time is left zero: the record carries no timestamp, so the source stamps it. Count is 1 — every record is exactly one observed question, unlike the poll sources, which aggregate.

Types

type Observer

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

Observer owns the loaded question observer: one program, one ring buffer, and one cgroup-id gate shared by every cgroup it is attached to.

A single instance is deliberate. cgroup_skb programs attach per cgroup, so observing N pods means N links, but sharing one object keeps one ring buffer and one reader goroutine instead of N of each.

func New

func New() (*Observer, error)

func (*Observer) AddCgids

func (o *Observer) AddCgids(cgids []uint64) error

AddCgids admits cgroup ids to the kernel-side gate. A question from a cgroup absent from this map produces no record at all, which is what keeps an unselected pod free of observation cost.

func (*Observer) Attach

func (o *Observer) Attach(cgroupPath string) (link.Link, error)

Attach hooks the program onto one container cgroup's egress path. The returned link must be closed to detach.

func (*Observer) Close

func (o *Observer) Close() error

func (*Observer) DeleteCgids

func (o *Observer) DeleteCgids(cgids []uint64) error

DeleteCgids revokes cgroup ids. A key that is already gone is not an error: pod deletion and policy deletion can both revoke the same cgroup.

func (*Observer) ReadStats

func (o *Observer) ReadStats() ([statCount]uint64, error)

ReadStats returns the cumulative loss counters, summed across CPUs. They are never reset: the caller reports deltas.

func (*Observer) Reader

func (o *Observer) Reader() (*ringbuf.Reader, error)

Reader opens a reader over the event ring buffer.

type Option

type Option func(*Source)

func WithClock

func WithClock(f func() time.Time) Option

WithClock overrides the event timestamp source.

func WithLossFunc

func WithLossFunc(f runtimeevent.LossFunc) Option

WithLossFunc reports kernel-side loss deltas, normally to a metrics counter.

func WithStatsInterval

func WithStatsInterval(d time.Duration) Option

WithStatsInterval overrides the loss-counter poll period.

type Source

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

Source drains the question ring buffer into the collector.

func NewSource

func NewSource(log logr.Logger, o *Observer, opts ...Option) *Source

NewSource builds the question source over an already-loaded observer.

func (*Source) Name

func (s *Source) Name() string

func (*Source) Run

func (s *Source) Run(ctx context.Context, out chan<- runtimeevent.Event) error

Run drains the ring buffer until ctx is cancelled.

A record the decoder rejects is counted and dropped rather than fatal: the kernel and the Go layout would have to disagree for that to happen, and returning would lose every subsequent question too.

Jump to

Keyboard shortcuts

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