kedge/internal/cni/plugin.go
Tyler King 6058e62348 Initial commit: Kedge network automation platform
Go-based network automation with YANG models, gRPC, Ansible,
Terraform, and Kubernetes integration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 12:09:30 -05:00

93 lines
2.9 KiB
Go

package cni
import (
"fmt"
"github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/types"
current "github.com/containernetworking/cni/pkg/types/100"
)
// CmdAdd is called by the container runtime when a pod is created.
// It creates the net1 interface in the pod's network namespace and programs
// routes for both overlay (WireGuard) and underlay (VLAN bridge) subnets.
func CmdAdd(args *skel.CmdArgs) error {
conf, err := ParseNetConf(args.StdinData)
if err != nil {
return fmt.Errorf("failed to parse config: %w", err)
}
// Load mesh topology for current node state.
topo, err := loadMeshTopology(conf.MeshConfig)
if err != nil {
return fmt.Errorf("failed to load mesh topology: %w", err)
}
// Create veth pair and move one end into the pod's network namespace.
hostVeth, podVeth, err := createVethPair(args.Netns, args.IfName)
if err != nil {
return fmt.Errorf("failed to create veth pair: %w", err)
}
// Attach host-side veth to appropriate backend interfaces.
if err := attachOverlayRoutes(hostVeth, conf.OverlayRoutes, topo); err != nil {
return fmt.Errorf("failed to attach overlay routes: %w", err)
}
if err := attachUnderlayRoutes(hostVeth, conf.UnderlayRoutes, topo); err != nil {
return fmt.Errorf("failed to attach underlay routes: %w", err)
}
// Program routes inside the pod's network namespace.
if err := programPodRoutes(args.Netns, podVeth, conf.OverlayRoutes, conf.UnderlayRoutes); err != nil {
return fmt.Errorf("failed to program pod routes: %w", err)
}
// Apply SVID-based network policy.
if err := applySVIDPolicy(args, conf, topo); err != nil {
return fmt.Errorf("failed to apply SVID policy: %w", err)
}
// Build and return CNI result.
result := &current.Result{
CNIVersion: conf.CNIVersion,
Interfaces: []*current.Interface{
{Name: hostVeth, Sandbox: ""},
{Name: podVeth, Sandbox: args.Netns},
},
}
return types.PrintResult(result, conf.CNIVersion)
}
// CmdDel is called when a pod is deleted.
// Tears down the net1 interface and cleans up routes and bridge/tunnel attachments.
func CmdDel(args *skel.CmdArgs) error {
conf, err := ParseNetConf(args.StdinData)
if err != nil {
return fmt.Errorf("failed to parse config: %w", err)
}
if err := teardownInterface(args.Netns, args.IfName); err != nil {
return fmt.Errorf("failed to teardown interface: %w", err)
}
_ = conf // Routes are cleaned up with the interface
return nil
}
// CmdCheck verifies the net1 interface exists and routes are correct.
func CmdCheck(args *skel.CmdArgs) error {
conf, err := ParseNetConf(args.StdinData)
if err != nil {
return fmt.Errorf("failed to parse config: %w", err)
}
if err := verifyInterface(args.Netns, args.IfName); err != nil {
return fmt.Errorf("interface check failed: %w", err)
}
if err := verifyRoutes(args.Netns, conf.OverlayRoutes, conf.UnderlayRoutes); err != nil {
return fmt.Errorf("route check failed: %w", err)
}
return nil
}