Open-Source Wikis

/

Cilium

/

How to contribute

/

Patterns and conventions

cilium/cilium

Patterns and conventions

This page documents the recurring patterns a contributor should expect when reading or writing Cilium Go code.

Hive cells everywhere

New agent functionality is added by writing a cell.Cell:

var Cell = cell.Module(
    "feature-foo",
    "Implements feature foo",
    cell.Provide(newFooManager),
    cell.Invoke(registerFooHooks),
    cell.Config(defaultConfig),
)
  • cell.Provide — supply types other cells can In from. Constructors return (T, error) or (T, hive.Lifecycle) etc.
  • cell.Invoke — run side-effecting initialisation that depends on already-provided types.
  • cell.Config — register a struct that maps to CLI flags via option.Flag* tags.
  • cell.Module — group related cells with a stable name, used by hive print-objects and the metric labels.

Lifecycle hooks (OnStart / OnStop) are registered through cell.Lifecycle so that the agent can stop cleanly. Avoid global state — every dependency should flow through the cell graph.

See pkg/hive/ and the dozens of cell.go files under pkg/ for examples.

Configuration

Configuration originates from CLI flags / Helm values / ConfigMap and is mapped into typed Config structs:

  • Cell-local config: a struct with Flags(flags *pflag.FlagSet) registered through cell.Config.
  • Global agent config: pkg/option/config.go holds the historical DaemonConfig plus its RegisterOptions method. New options should go into a cell-local config when possible, falling back to DaemonConfig only when truly cross-cutting.

Helm values are defined in install/kubernetes/cilium/values.yaml and rendered into a ConfigMap, then mapped onto the agent flags.

Logging

  • Use log/slog via pkg/logging/. Each subsystem keeps its own logger in a package-level log variable initialised from logging.DefaultSlogLogger.With(logfields.LogSubsys, "<name>").
  • Field constants live in pkg/logging/logfields/. Reuse them rather than hardcoding strings (logfields.EndpointID, logfields.IPAddr, logfields.Identity, ...).
  • Log levels: slog.LevelDebug for verbose internal flows, Info for one-shot events that an operator should see, Warn for recoverable problems, Error only for failures that are visible to users.

Error handling

  • Wrap errors with fmt.Errorf("…: %w", err) so callers can errors.Is/As.
  • Reserve sentinel errors for cases callers must distinguish (errors.New("…"), exported as ErrFoo).
  • For control-plane reconciliation, return the error and let the upper layer (controller, hive lifecycle, statedb reconciler) retry; do not block in the inner loop.

Concurrency

  • Prefer statedb tables (vendor/.../statedb, pkg/datapath/tables/, etc.) over ad-hoc maps protected by mutexes for shared state.
  • Where a mutex is required, use pkg/lock/ (lock.Mutex, lock.RWMutex) for context-aware deadlock checking under -tags lockdebug.
  • Long-running goroutines must take a context.Context from the cell lifecycle so they can be cancelled on shutdown.
  • Use pkg/controller/ for periodic reconciliation loops that need backoff and metrics.

REST API conventions

The agent's REST API is defined in OpenAPI at api/v1/openapi.yaml and generated into api/v1/server/ and api/v1/client/ via make generate-api. The handlers live in daemon/cmd/ and are wired via Hive cells.

The Hubble gRPC API is defined in .proto files under api/v1/observer/, api/v1/relay/, and api/v1/peer/.

CRDs

Cilium CRDs live in pkg/k8s/apis/cilium.io/v2/ (and v2alpha1 for alpha). After modifying a Go type, run:

make generate-k8s-api

This regenerates deepcopy methods, OpenAPI schemas, the YAML CRD manifests under pkg/k8s/apis/cilium.io/client/crds/, and the docs table in Documentation/crdlist.rst.

File naming

  • One package per directory; the package name matches the directory name.

  • Tests sit next to source: foo.go + foo_test.go.

  • Build tags: //go:build linux, //go:build privileged, etc. Cilium runs on Linux only; non-Linux files are stub implementations that satisfy the compiler.

  • License header on every source file:

    // SPDX-License-Identifier: Apache-2.0
    // Copyright Authors of Cilium

    enforced by make checkpatch and CI.

BPF C conventions

  • Programs live in bpf/bpf_*.c; helpers live in bpf/lib/*.h.
  • All map declarations go through BPF_MAP_* macros in bpf/include/bpf/.
  • Programs include node_config.h (host-specific) and ep_config.h (endpoint-specific) generated by the agent at compile time.
  • Tail-calls are dispatched through indices defined in bpf/include/bpf/section.h.
  • Verifier complexity is a constant battle: prefer small inline functions, bounded loops, and __always_inline to keep the verifier happy.

Style summary

  • Run gofmt, goimports, and golangci-lint.
  • Keep PRs focused — split large changes into a series of commits, each independently reviewable.
  • Add tests for new behaviour; if you can't, explain why in the PR.
  • Keep the public surface (pkg/ exported identifiers) stable across patch releases.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Patterns and conventions – Cilium wiki | Factory