Claude Code Plugins

Community-maintained marketplace

Feedback

ebpf-cnf-scaffold

@cassamajor/xcnf
1
0

Scaffold new eBPF-based Cloud Native Network Function (CNF) projects with proper directory structure, boilerplate C kernel code, Go userspace application, bpf2go generation, and build configuration following established patterns. Use when creating new CNF examples or starting fresh eBPF projects.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name ebpf-cnf-scaffold
description Scaffold new eBPF-based Cloud Native Network Function (CNF) projects with proper directory structure, boilerplate C kernel code, Go userspace application, bpf2go generation, and build configuration following established patterns. Use when creating new CNF examples or starting fresh eBPF projects.

eBPF CNF Scaffold Skill

This skill scaffolds complete eBPF-based CNF projects following the established patterns in this repository.

What This Skill Does

Creates a new eBPF CNF project with:

  1. Proper directory structure (examples/{name}/)
  2. eBPF kernel program in Restricted C (bytecode/{name}.c)
  3. Go userspace application (main.go)
  4. bpf2go code generation setup (bytecode/gen.go)
  5. Go module initialization
  6. README with build/run instructions
  7. Optional Dockerfile for containerization

When to Use

  • Creating a new CNF from scratch
  • Adding a new example to the examples/ directory
  • Starting a new eBPF networking project
  • Need a working template that follows repository conventions

Project Structure Created

examples/{name}/
├── main.go                 # Go userspace application
├── bytecode/
│   ├── gen.go             # bpf2go generation directive
│   ├── {name}.c           # eBPF kernel program (Restricted C)
│   ├── {name}_bpfel.go    # Generated (after go generate)
│   └── {name}_bpfeb.go    # Generated (after go generate)
├── go.mod                 # Go module file
├── README.md              # Build and run instructions
└── Dockerfile             # Optional containerization

Information to Gather

Before scaffolding, ask the user:

  1. CNF Name: What to name the CNF (lowercase, hyphens only)
  2. Hook Type: Which eBPF hook to use (XDP, TC/tcx, netkit, kprobe, tracepoint)
  3. Functionality: Brief description of what the CNF should do
  4. Maps Needed: Does it need eBPF maps? (hash, array, ringbuf, etc.)
  5. Dockerfile: Should a Dockerfile be included?

Boilerplate Components

1. eBPF Program Template (bytecode/{name}.c)

//go:build ignore

#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>

// Add appropriate headers based on hook type
// XDP: <linux/if_ether.h>, <linux/ip.h>
// TC/tcx: <linux/pkt_cls.h>
// netkit: <linux/if_link.h>

char _license[] SEC("license") = "GPL";

SEC("{hook_section}")
int {function_name}(struct {ctx_type} *ctx) {
    // TODO: Implement CNF logic
    return {return_value};
}

2. Go Generation File (bytecode/gen.go)

package bytecode

//go:generate go tool bpf2go -type {types} {CapitalizedName} {name}.c -- -O2 -Wall -Werror

3. Go Userspace Application (main.go)

package main

import (
    "log"
    "os"
    "os/signal"
    "syscall"

    "{module}/bytecode"
    "github.com/cilium/ebpf"
    "github.com/cilium/ebpf/link"
)

func main() {
    // Load eBPF objects
    spec, err := bytecode.Load{Name}()
    if err != nil {
        log.Fatalf("loading eBPF spec: %v", err)
    }

    objs := &bytecode.{Name}Objects{}
    if err := spec.LoadAndAssign(objs, nil); err != nil {
        log.Fatalf("loading eBPF objects: %v", err)
    }
    defer objs.Close()

    // TODO: Attach program to hook
    // TODO: Read from maps/ringbufs if needed

    log.Println("{Name} CNF is running...")

    // Wait for signal
    sig := make(chan os.Signal, 1)
    signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
    <-sig

    log.Println("Shutting down...")
}

4. README Template

# {Name} CNF

{Description}

## Build

Compile the eBPF program:
```shell
go generate ./bytecode
```

Build the userspace application:
```shell
go build -o {name}
```

## Run

```shell
sudo ./{name}
```

## Test

```shell
sudo -E go test .
```

Hook-Specific Configuration

XDP

  • Section: SEC("xdp")
  • Context: struct xdp_md *ctx
  • Return values: XDP_PASS, XDP_DROP, XDP_TX, XDP_REDIRECT, XDP_ABORTED
  • Attach: link.AttachXDP()

TC/tcx (Kernel 6.6+)

  • Section: SEC("tc") or SEC("tcx/ingress") / SEC("tcx/egress")
  • Context: struct __sk_buff *skb
  • Return values: TC_ACT_OK, TC_ACT_SHOT, TC_ACT_REDIRECT, TC_ACT_PIPE
  • Attach: link.AttachTCX() for tcx, link.AttachTC() for legacy

netkit (BPF-programmable network device)

  • Section: SEC("netkit/primary") and SEC("netkit/peer")
  • Context: struct __sk_buff *skb
  • Return values: NETKIT_PASS, NETKIT_DROP, NETKIT_REDIRECT
  • Attach: link.AttachNetkit() with ebpf.AttachNetkitPrimary or ebpf.AttachNetkitPeer
  • Note: Requires two programs (primary and peer) for bidirectional processing

kprobe/kretprobe

  • Section: SEC("kprobe/function_name") or SEC("kretprobe/function_name")
  • Context: struct pt_regs *ctx
  • Return value: 0
  • Attach: link.Kprobe() or link.Kretprobe()

tracepoint

  • Section: SEC("tracepoint/category/name")
  • Context: Custom struct based on tracepoint
  • Return value: 0
  • Attach: link.Tracepoint()

Go Module Initialization

After creating the structure, initialize the Go module:

cd examples/{name}
go mod init github.com/{username}/xcnf/examples/{name}
go get -tool github.com/cilium/ebpf/cmd/bpf2go
go mod tidy

Post-Scaffold Instructions

After scaffolding, remind the user to:

  1. Enter the Linux VM (if using OrbStack):

    orb
    
  2. Generate eBPF bytecode:

    cd examples/{name}
    go generate ./bytecode
    
  3. Implement the CNF logic in:

    • bytecode/{name}.c - kernel-space processing
    • main.go - userspace control and data handling
  4. Build and test:

    go build -o {name}
    sudo ./{name}
    

Best Practices

  • Use meaningful variable names that describe the CNF's purpose
  • Add TODO comments for areas that need implementation
  • Include bounds checking for all packet data access
  • Use appropriate helper functions (bpf_printk for debugging)
  • Follow the existing patterns in the repository
  • Add proper error handling in Go code
  • Use defer for cleanup (Close(), link cleanup)

Example Usage

User: "Create a new CNF called 'rate-limiter' that uses XDP to rate limit incoming packets"