-
Notifications
You must be signed in to change notification settings - Fork 2
handlers
Pre-Alpha. This page describes behavior that may change.
Handlers are the callbacks a plugin registers with the SDK to react to engine-initiated events. They cover the whole plugin lifecycle: the stage-2 config delivery, the stage-4 registry share, runtime BGP events, command dispatch, NLRI codec requests, config reload, OPEN validation, and shutdown. Every handler is registered with an On* method on *sdk.Plugin before you call Run().
The full list is in pkg/plugin/sdk/sdk_callbacks.go. This page covers the ones you will touch first.
Register every handler you need before calling Run(). The order of registration does not matter, but the fact that they are all registered before Run() does: the SDK wires them into the event loop at startup and handlers registered afterwards are ignored.
p := sdk.NewWithConn("my-plugin", conn)
// Startup
p.OnConfigure(func(sections []sdk.ConfigSection) error { ... })
p.OnShareRegistry(func(commands []sdk.RegistryCommand) { ... })
// Runtime
p.OnEvent(func(event string) error { ... })
p.OnExecuteCommand(func(serial, command string, args []string, peer string) (string, string, error) { ... })
p.OnConfigVerify(func(sections []sdk.ConfigSection) error { ... })
p.OnConfigApply(func(diffs []sdk.ConfigDiffSection) error { ... })
p.OnValidateOpen(func(input *sdk.ValidateOpenInput) *sdk.ValidateOpenOutput { ... })
// NLRI codecs
p.OnEncodeNLRI(func(family string, args []string) (string, error) { ... })
p.OnDecodeNLRI(func(family, hex string) (string, error) { ... })
p.OnDecodeCapability(func(code uint8, hex string) (string, error) { ... })
// Lifecycle
p.OnStarted(func(ctx context.Context) error { ... })
p.OnBye(func(reason string) { ... })
p.Run(ctx, sdk.Registration{ ... })Stage 2. The engine delivers the plugin's config sections. Each section is a {Root, Data} pair where Data is the JSON encoding of the subtree under Root.
p.OnConfigure(func(sections []sdk.ConfigSection) error {
for _, s := range sections {
var cfg MyConfig
if err := json.Unmarshal([]byte(s.Data), &cfg); err != nil {
return fmt.Errorf("parse config: %w", err)
}
// Store cfg for later use.
}
return nil
})Return nil to accept the config. Return an error to reject it: that aborts startup, and the engine logs the failure.
Stage 4. The engine hands you the command registry from every other loaded plugin. The handler is informational: use the registry to route command dispatches or to know which commands are available to DispatchCommand.
p.OnShareRegistry(func(commands []sdk.RegistryCommand) {
for _, cmd := range commands {
// cmd.Name, cmd.Plugin, cmd.Encoding
}
})A post-stage-5 hook. Safe to call engine methods here (EmitEvent, DispatchCommand, SubscribeEvents, UpdateRoute). Runs on the plugin's goroutine, so do not block it forever.
p.OnStarted(func(ctx context.Context) error {
return p.EmitEvent(ctx, "my-plugin", "ready", "", "", `{"ok":true}`)
})The BGP event delivery path. The engine delivers each subscribed event as a JSON string, and you handle it.
p.OnEvent(func(event string) error {
// event is the full JSON envelope:
// {"type":"bgp","bgp":{"peer":{"address":"10.0.0.1"},"message":{"type":"update"},...}}
return nil
})Event delivery is synchronous. The handler must return quickly. If you need to do real work, push the event onto a queue and process it on a worker goroutine.
The CLI and API dispatch path. When a user runs a command that your plugin declared in its Registration, the engine delivers it through execute-command.
p.OnExecuteCommand(func(serial, command string, args []string, peer string) (string, string, error) {
switch command {
case "my-plugin status":
return "done", `{"status":"running","uptime":3600}`, nil
case "my-plugin check":
if len(args) < 1 {
return "error", "usage: my-plugin check <target>", nil
}
result := performCheck(args[0])
return "done", result, nil
default:
return "error", "unknown command: " + command, nil
}
})The return tuple is (status, data, error). status is a short string (done, error, or a custom status). data is the structured result, typically JSON. If error is non-nil, the SDK sends an error response and the status and data values are ignored.
The reload path. When the operator reloads the config, every plugin with a Verify handler gets the candidate config first, before anything is applied. If any plugin returns an error, the reload is rejected and nothing is applied.
p.OnConfigVerify(func(sections []sdk.ConfigSection) error {
// Read-only check. Return nil to accept, error to reject.
return nil
})
p.OnConfigApply(func(diffs []sdk.ConfigDiffSection) error {
// Apply the diff. The plugin's current state must match the new config after this returns.
return nil
})ConfigDiffSection carries added, removed, and changed paths, so you can react minimally instead of re-parsing the full tree.
Called when a peer sends an OPEN message. The plugin can accept, reject, or modify the session parameters before the FSM moves to OpenConfirm. The Role plugin uses this hook to enforce RFC 9234 role compatibility; the Hostname and Software Version plugins use it to surface the peer's identity to subscribers.
p.OnValidateOpen(func(in *sdk.ValidateOpenInput) *sdk.ValidateOpenOutput {
// Inspect in.Capabilities, in.RouterID, in.ASN, in.Peer.
return &sdk.ValidateOpenOutput{Accept: true}
})OnEncodeNLRI, OnDecodeNLRI, and OnDecodeCapability let a plugin provide encode and decode functions for a custom address family or capability. These are the hooks every bgp-nlri-* plugin uses.
p.OnEncodeNLRI(func(family string, args []string) (string, error) {
// Return hex-encoded NLRI bytes.
})
p.OnDecodeNLRI(func(family, hex string) (string, error) {
// Return JSON-encoded parsed NLRI.
})The engine is shutting the plugin down. The reason string tells you why. Use this to flush state, close files, or release external resources.
p.OnBye(func(reason string) {
log.Printf("plugin shutting down: %s", reason)
})- Go plugins for the overall SDK surface.
-
YANG schema for the schema that defines
ConfigSection. -
Commands for declaring commands that
OnExecuteCommandhandles. - In-tree handlers reference for the long version.
Adapted from main/docs/plugin-development/handlers.md.
Unreviewed draft. This wiki was authored in bulk and has not been reviewed. File corrections on the issue tracker.
- Overview
- YANG Model
- Editor Workflow
- Archive and Rollback
- System
- Interfaces
- VRRP
- BFD
- FIB
- OSPF
- IS-IS
- MPLS / LDP / RSVP-TE
- RSVP-TE
- SRv6
- Static Routes
- Policy Routing
- Firewall
- Traffic Control
- Class of Service
- L2TP/PPP
- PPPoE
- VPP Data Plane
- RPKI
- IPsec VPN
- TACACS+ AAA
- RADIUS AAA
- AS112 DNS
- Authorization
- Fleet
- BGP
- Starting and Stopping
- Show Commands
- Monitoring
- Flow Export
- DDoS Mitigation
- Anomaly Detection
- Health Checks
- Audit Trail
- Production Diagnostics
- Logging
- Operational Reports
- Healthcheck
- Self-Update
- Zero-Touch Provisioning
- MRT Analysis
- Upgrade and Restart
- Storage
- Policy
- Core
- Resilience
- Validation
- Capabilities
- Address Families
- Protocol
- Subsystems
- Infrastructure
- Route Server at an IXP
- Transit Edge with RPKI
- Public Looking Glass
- ExaBGP Migration Walkthrough
- FlowSpec Injection
- Chaos-Tested Peering
- AS Path Topology