Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ coverage.html
/galactic
/galactic-router
/galactic-cni
/galactic-tap-cni
/galactic-ipam
/galactic-bgp
/galactic-route

# Go workspace
go.work
Expand Down
4 changes: 4 additions & 0 deletions Taskfile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ tasks:
-X go.datum.net/galactic/internal/metadata.GitURL={{.GIT_URL}}
cmds:
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-cni ./cmd/galactic-cni
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-tap-cni ./cmd/galactic-tap-cni
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-ipam ./cmd/galactic-ipam
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-bgp ./cmd/galactic-bgp
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-route ./cmd/galactic-route
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-router ./cmd/galactic-router
- go build -ldflags "{{.LDFLAGS}}" -o bin/vmtap-cni ./cmd/vmtap-cni
- GOBIN={{.LOCALBIN}} go install github.com/containernetworking/plugins/plugins/main/host-device@v1.9.1
Expand Down
91 changes: 91 additions & 0 deletions cmd/galactic-bgp/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright 2026 Datum Cloud, Inc.
//
// SPDX-License-Identifier: AGPL-3.0-or-later

package main

import (
"fmt"
"log"
"os"
"strings"

"github.com/containernetworking/cni/pkg/version"
"github.com/spf13/cobra"
"golang.org/x/term"

"go.datum.net/galactic/internal/cnibgp"
"go.datum.net/galactic/internal/metadata"
)

const (
appName = "galactic-bgp"

appDesc = `Galactic BGP CNI Plugin

The BGP/SRv6/eBPF publish plugin in the galactic CNI chain — chained after
galactic-cni/galactic-tap-cni (and, when present, galactic-route) per
conflist order, never run standalone. Has zero kernel-interface
dependency: every address it advertises comes from prevResult, not from a
runtime call into an interface it doesn't own.

Find more information at: https://www.datum.net/docs`
)

func newRootCommand() *cobra.Command {
cmd := &cobra.Command{
Use: appName,
Short: strings.Split(appDesc, "\n")[0],
Long: appDesc,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
cnibgp.InitCNIConfig()
confFile, _ := cmd.Flags().GetString("conf-file")
if confFile != "" {
cnibgp.ConfFile = confFile
}
return nil
},
RunE: func(cmd *cobra.Command, _ []string) error {
if ok, _ := cmd.Flags().GetBool("build-info"); ok {
fmt.Println(metadata.BuildInfo(appName))
return nil
}
if ok, _ := cmd.Flags().GetBool("version"); ok {
fmt.Printf("%s version %s\n", appName, metadata.Version)
return nil
}
if os.Getenv("CNI_COMMAND") == "VERSION" {
return version.All.Encode(os.Stdout)
}

// Real CNI runtimes always pipe the network config JSON on
// stdin and close it. If stdin is an interactive terminal
// instead, no config will ever arrive and skel's blocking
// stdin read would hang forever — print version info instead.
if term.IsTerminal(int(os.Stdin.Fd())) {
fmt.Printf("%s version %s\n", appName, metadata.Version)
fmt.Printf("CNI protocol versions supported: %s\n", strings.Join(version.All.SupportedVersions(), ", "))
return nil
}

// Unlike galactic-cni/galactic-tap-cni, this plugin never enters
// any network namespace at all (it only makes k8s API calls),
// so it needs neither the stdin peek-and-repipe dance nor
// CNI_NETNS_OVERRIDE those two use to detect and handle
// tap-mode's host-netns invocation.
cnibgp.RunPlugin()
return nil
},
}

cmd.PersistentFlags().String("conf-file", cnibgp.ConfFile, "Path to CNI conflist file")
cmd.Flags().Bool("build-info", false, "Print build information and exit")
cmd.Flags().BoolP("version", "V", false, "Print version and exit")
return cmd
}

func main() {
if err := newRootCommand().Execute(); err != nil {
log.Fatalf("error: %v", err)
}
}
42 changes: 8 additions & 34 deletions cmd/galactic-cni/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@
package main

import (
"encoding/json"
"errors"
"fmt"
"io"
"log"
"os"
"strings"
Expand Down Expand Up @@ -108,27 +106,14 @@ func newRootCommand() *cobra.Command {
return nil
}

// Read stdin once so we can inspect the CNI config before the
// library runs its netns validation. We pipe the buffered bytes
// back as os.Stdin so the CNI library can still read them.
stdinData, _ := io.ReadAll(os.Stdin)
r, w, _ := os.Pipe()
go func() {
_, _ = w.Write(stdinData)
_ = w.Close()
}()
oldStdin := os.Stdin
os.Stdin = r

// Tap mode never enters a network namespace — all operations are
// host-side. Set the override so the CNI library skips its same-
// netns rejection check, which would otherwise reject kraftlet
// workloads that pass the host netns.
if isTapMode(stdinData) {
_ = os.Setenv("CNI_NETNS_OVERRIDE", "true")
}

defer func() { os.Stdin = oldStdin }()
// galactic-cni is veth-only: it always moves an interface into
// the container's own netns, so it always needs the CNI
// library's normal same-netns rejection check — unlike
// galactic-tap-cni (which unconditionally sets
// CNI_NETNS_OVERRIDE, since tap workloads never enter a netns
// at all), there is no stdin-peeking tap-mode detection here
// anymore. Interface kind is which binary you invoke now, not a
// config field this process branches on.
cni.RunPlugin()
return nil
},
Expand All @@ -142,17 +127,6 @@ func newRootCommand() *cobra.Command {
return cmd
}

// isTapMode returns true when the CNI config requests tap interface type.
// Only a minimal JSON parse is needed — full validation happens later in
// parseConf inside cmdAdd.
func isTapMode(stdinData []byte) bool {
var cfg struct {
InterfaceType string `json:"interface_type"`
}
_ = json.Unmarshal(stdinData, &cfg)
return cfg.InterfaceType == "tap"
}

func main() {
if err := newRootCommand().Execute(); err != nil {
log.Fatalf("error: %v", err)
Expand Down
79 changes: 79 additions & 0 deletions cmd/galactic-ipam/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright 2026 Datum Cloud, Inc.
//
// SPDX-License-Identifier: AGPL-3.0-or-later

package main

import (
"fmt"
"log"
"os"
"strings"

"github.com/containernetworking/cni/pkg/version"
"github.com/spf13/cobra"
"golang.org/x/term"

"go.datum.net/galactic/internal/cniipam"
"go.datum.net/galactic/internal/metadata"
)

const (
appName = "galactic-ipam"

appDesc = `Galactic IPAM CNI Plugin

The delegated CNI IPAM plugin in the galactic CNI chain — invoked by
galactic-cni/galactic-tap-cni's own "ipam" block via the CNI IPAM
delegation protocol (github.com/containernetworking/cni/pkg/ipam), never
run directly from a conflist. Has no Kubernetes dependency at all:
allocation state persists in on-disk marker files under this node's own
filesystem.

Find more information at: https://www.datum.net/docs`
)

func newRootCommand() *cobra.Command {
cmd := &cobra.Command{
Use: appName,
Short: strings.Split(appDesc, "\n")[0],
Long: appDesc,
RunE: func(cmd *cobra.Command, _ []string) error {
if ok, _ := cmd.Flags().GetBool("build-info"); ok {
fmt.Println(metadata.BuildInfo(appName))
return nil
}
if ok, _ := cmd.Flags().GetBool("version"); ok {
fmt.Printf("%s version %s\n", appName, metadata.Version)
return nil
}
if os.Getenv("CNI_COMMAND") == "VERSION" {
return version.All.Encode(os.Stdout)
}

// Real CNI runtimes (via IPAM delegation's ExecAdd/ExecDel/
// ExecCheck) always pipe the netconf JSON on stdin and close
// it. If stdin is an interactive terminal instead, no config
// will ever arrive and skel's blocking stdin read would hang
// forever — print version info instead.
if term.IsTerminal(int(os.Stdin.Fd())) {
fmt.Printf("%s version %s\n", appName, metadata.Version)
fmt.Printf("CNI protocol versions supported: %s\n", strings.Join(version.All.SupportedVersions(), ", "))
return nil
}

cniipam.RunPlugin()
return nil
},
}

cmd.Flags().Bool("build-info", false, "Print build information and exit")
cmd.Flags().BoolP("version", "V", false, "Print version and exit")
return cmd
}

func main() {
if err := newRootCommand().Execute(); err != nil {
log.Fatalf("error: %v", err)
}
}
126 changes: 126 additions & 0 deletions cmd/galactic-route/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// Copyright 2026 Datum Cloud, Inc.
//
// SPDX-License-Identifier: AGPL-3.0-or-later

package main

import (
"encoding/json"
"fmt"
"io"
"log"
"os"
"strings"

"github.com/containernetworking/cni/pkg/version"
"github.com/spf13/cobra"
"golang.org/x/term"

"go.datum.net/galactic/internal/cniroute"
"go.datum.net/galactic/internal/metadata"
)

const (
appName = "galactic-route"

appDesc = `Galactic Route CNI Plugin

The termination-route plugin in the galactic CNI chain — chained after
galactic-cni/galactic-tap-cni and before galactic-bgp per conflist order,
never run standalone, and optional (only present for attachments with
terminations to install). Has no Kubernetes dependency at all: it only
installs kernel routes into the VRF routing table the master plugin
already created.

Find more information at: https://www.datum.net/docs`
)

func newRootCommand() *cobra.Command {
cmd := &cobra.Command{
Use: appName,
Short: strings.Split(appDesc, "\n")[0],
Long: appDesc,
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
cniroute.InitCNIConfig()
confFile, _ := cmd.Flags().GetString("conf-file")
if confFile != "" {
cniroute.ConfFile = confFile
}
return nil
},
RunE: func(cmd *cobra.Command, _ []string) error {
if ok, _ := cmd.Flags().GetBool("build-info"); ok {
fmt.Println(metadata.BuildInfo(appName))
return nil
}
if ok, _ := cmd.Flags().GetBool("version"); ok {
fmt.Printf("%s version %s\n", appName, metadata.Version)
return nil
}
if os.Getenv("CNI_COMMAND") == "VERSION" {
return version.All.Encode(os.Stdout)
}

// Real CNI runtimes always pipe the network config JSON on
// stdin and close it. If stdin is an interactive terminal
// instead, no config will ever arrive and skel's blocking
// stdin read would hang forever — print version info instead.
if term.IsTerminal(int(os.Stdin.Fd())) {
fmt.Printf("%s version %s\n", appName, metadata.Version)
fmt.Printf("CNI protocol versions supported: %s\n", strings.Join(version.All.SupportedVersions(), ", "))
return nil
}

// Unlike galactic-cni/galactic-tap-cni, this plugin never talks
// to the API server. It does, however, run natively in whatever
// netns CNI_NETNS points at rather than entering it — for a
// veth-mode attachment CNI_NETNS is the container's netns, which
// differs from this process's own ambient (host) netns, so the
// CNI library's same-netns rejection check never fires. For a
// tap-mode attachment, though, CNI_NETNS is deliberately set to
// the host's own root netns (there's no per-VM netns to enter),
// which does equal this process's ambient netns — so the same
// peek-and-repipe dance and CNI_NETNS_OVERRIDE galactic-cni uses
// for tap mode are needed here too, or the library rejects every
// tap-mode ADD/DEL after the route is already installed.
stdinData, _ := io.ReadAll(os.Stdin)
r, w, _ := os.Pipe()
go func() {
_, _ = w.Write(stdinData)
_ = w.Close()
}()
oldStdin := os.Stdin
os.Stdin = r
defer func() { os.Stdin = oldStdin }()

if isTapMode(stdinData) {
_ = os.Setenv("CNI_NETNS_OVERRIDE", "true")
}

cniroute.RunPlugin()
return nil
},
}

cmd.PersistentFlags().String("conf-file", cniroute.ConfFile, "Path to CNI conflist file")
cmd.Flags().Bool("build-info", false, "Print build information and exit")
cmd.Flags().BoolP("version", "V", false, "Print version and exit")
return cmd
}

// isTapMode returns true when the CNI config requests tap interface type.
// Only a minimal JSON parse is needed — full validation happens later in
// parseConf inside cmdAdd/cmdDel.
func isTapMode(stdinData []byte) bool {
var cfg struct {
InterfaceType string `json:"interface_type"`
}
_ = json.Unmarshal(stdinData, &cfg)
return cfg.InterfaceType == "tap"
}

func main() {
if err := newRootCommand().Execute(); err != nil {
log.Fatalf("error: %v", err)
}
}
Loading
Loading