VPP load-balancer dataplane integration: state, sync, and global conf

This commit wires maglevd through to VPP's LB plugin end-to-end, using
locally-generated GoVPP bindings for the newer v2 API messages.

VPP binapi (vendored)
- New package internal/vpp/binapi/ containing lb, lb_types, ip_types, and
  interface_types, generated from a local VPP build (~/src/vpp) via a new
  'make vpp-binapi' target. GoVPP v0.12.0 upstream lacks the v2 messages we
  need (lb_conf_get, lb_add_del_vip_v2, lb_add_del_as_v2, lb_as_v2_dump,
  lb_as_set_weight), so we commit the generated output in-tree.
- All generated files go through our loggedChannel wrapper; every VPP API
  send/receive is recorded at DEBUG via slog (vpp-api-send / vpp-api-recv /
  vpp-api-send-multi / vpp-api-recv-multi) so the full wire-level trail is
  auditable. NewAPIChannel is unexported — callers must use c.apiChannel().

Read path: GetLBState{All,VIP}
- GetLBStateAll returns a full snapshot (global conf + every VIP with its
  attached application servers).
- GetLBStateVIP looks up a single VIP by (prefix, protocol, port) and
  returns (nil, nil) when the VIP doesn't exist in VPP. This is the
  efficient path for targeted updates on a busy LB.
- Helpers factored out: getLBConf, dumpAllVIPs, dumpASesForVIP, lookupVIP,
  vipFromDetails.

Write path: SyncLBState{All,VIP}
- SyncLBStateAll reconciles every configured frontend with VPP: creates
  missing VIPs, removes stale ones (with AS flush), and reconciles AS
  membership and weights within VIPs that exist on both sides.
- SyncLBStateVIP targets a single frontend by name. Never removes VIPs.
  Returns ErrFrontendNotFound (wrapped with the name) when the frontend
  isn't in config, so callers can use errors.Is.
- Shared reconcileVIP helper does the per-VIP AS diff; removeVIP is used
  only by the full-sync pass.
- LbAddDelVipV2 requests always set NewFlowsTableLength=1024. The .api
  default=1024 annotation is only applied by VAT/CLI parsers, not wire-
  level marshalling — sending 0 caused VPP to vec_validate with mask
  0xFFFFFFFF and OOM-panic.
- Pool semantics: backends in the primary (first) pool of a frontend get
  their configured weight; backends in secondary pools get weight 0. All
  backends are installed so higher layers can flip weights on failover
  without add/remove churn.
- Every individual change emits a DEBUG slog (vpp-lbsync-vip-add/del,
  vpp-lbsync-as-add/del, vpp-lbsync-as-weight). Start/done INFO logs
  carry a scope=all|vip label plus aggregate counts.

Global conf push: SetLBConf
- New SetLBConf(cfg) sends lb_conf with ipv4-src, ipv6-src, sticky-buckets,
  and flow-timeout. Called automatically on VPP (re)connect and after
  every config reload (via doReloadConfig). Results are cached on the
  Client so redundant pushes are silently skipped — only actual changes
  produce a vpp-lb-conf-set INFO log line.

Periodic drift reconciliation
- vpp.Client.lbSyncLoop runs in a goroutine tied to each VPP connection's
  lifetime. Its first tick is immediate (startup and post-reconnect
  sync quickly); subsequent ticks fire every vpp.lb.sync-interval from
  config (default 30s). Purpose: catch drift if something/someone
  modifies VPP state by hand. The loop uses a ConfigSource interface
  (satisfied by checker.Checker via its new Config() accessor) to avoid
  an import cycle with the checker package.

Config schema additions (maglev.vpp.lb)
- sync-interval: positive Go duration, default 30s.
- ipv4-src-address: REQUIRED. Used as the outer source for GRE4 encap
  to application servers. Missing this is a hard semantic error —
  maglevd --check exits 2 and the daemon refuses to start. VPP GRE
  needs a source address and every VIP we program uses GRE, so there
  is no meaningful config without it.
- ipv6-src-address: REQUIRED. Same treatment as ipv4-src-address.
- sticky-buckets-per-core: default 65536, must be a power of 2.
- flow-timeout: default 40s, must be a whole number of seconds in [1s, 120s].
- VPP validation runs at the end of convert() so structural errors in
  healthchecks/backends/frontends surface first — operators fix those,
  then get the VPP-specific requirements.

gRPC API
- New GetVPPLBState RPC returning VPPLBState: global conf + VIPs with
  ASes. Mirrors the read-path but strips fields irrelevant to our
  GRE-only deployment (srv_type, dscp, target_port).
- New SyncVPPLBState RPC with optional frontend_name. Unset → full sync
  (may remove stale VIPs). Set → single-VIP sync (never removes).
  Returns codes.NotFound for unknown frontends, codes.Unavailable when
  VPP integration is disabled or disconnected.

maglevc (CLI)
- New 'show vpp lbstate' command displaying the LB plugin state. VPP-only
  fields the dataplane irrelevant to GRE are suppressed. Per-AS lines use
  a key-value format ("address X  weight Y  flow-table-buckets Z")
  instead of a tabwriter column, which avoids the ANSI-color alignment
  issue we hit with mixed label/data rows.
- New 'sync vpp lbstate [<name>]' command. Without a name, triggers a
  full reconciliation; with a name, targets one frontend.
- Previous 'show vpp lb' renamed to 'show vpp lbstate' for consistency
  with the new sync command.

Test fixtures
- validConfig and all ad-hoc config_test.go fixtures that reach the end
  of convert() now include the two required vpp.lb src addresses.
- tests/01-maglevd/maglevd-lab/maglev.yaml gains a vpp.lb section so the
  robot integration tests can still load the config.
- cmd/maglevc/tree_test.go gains expected paths for the new commands.

Docs
- config-guide.md: new 'vpp' section in the basic structure, detailed
  vpp.lb field reference, noting ipv4/ipv6 src addresses as REQUIRED
  (hard error) with no defaults; example config updated.
- user-guide.md: documented 'show vpp info', 'show vpp lbstate',
  'sync vpp lbstate [<name>]', new --vpp-api-addr and --vpp-stats-addr
  flags, the vpp-lb-conf-set log line, and corrected the pause/resume
  description to reflect that pause cancels the probe goroutine.
- debian/maglev.yaml: example config gains a vpp.lb block with src
  addresses and commented optional overrides.
This commit is contained in:
2026-04-12 10:58:39 +02:00
parent 3227263d68
commit d3c5c86037
24 changed files with 4900 additions and 161 deletions

View File

@@ -0,0 +1,304 @@
// Code generated by GoVPP's binapi-generator. DO NOT EDIT.
// Package interface_types contains generated bindings for API file interface_types.api.
//
// Contents:
// - 1 alias
// - 7 enums
package interface_types
import (
"strconv"
api "go.fd.io/govpp/api"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the GoVPP api package it is being compiled against.
// A compilation error at this line likely means your copy of the
// GoVPP api package needs to be updated.
const _ = api.GoVppAPIPackageIsVersion2
const (
APIFile = "interface_types"
APIVersion = "1.0.0"
VersionCrc = 0x7f2ba79a
)
// Direction defines enum 'direction'.
type Direction uint8
const (
RX Direction = 0
TX Direction = 1
)
var (
Direction_name = map[uint8]string{
0: "RX",
1: "TX",
}
Direction_value = map[string]uint8{
"RX": 0,
"TX": 1,
}
)
func (x Direction) String() string {
s, ok := Direction_name[uint8(x)]
if ok {
return s
}
return "Direction(" + strconv.Itoa(int(x)) + ")"
}
// IfStatusFlags defines enum 'if_status_flags'.
type IfStatusFlags uint32
const (
IF_STATUS_API_FLAG_ADMIN_UP IfStatusFlags = 1
IF_STATUS_API_FLAG_LINK_UP IfStatusFlags = 2
)
var (
IfStatusFlags_name = map[uint32]string{
1: "IF_STATUS_API_FLAG_ADMIN_UP",
2: "IF_STATUS_API_FLAG_LINK_UP",
}
IfStatusFlags_value = map[string]uint32{
"IF_STATUS_API_FLAG_ADMIN_UP": 1,
"IF_STATUS_API_FLAG_LINK_UP": 2,
}
)
func (x IfStatusFlags) String() string {
s, ok := IfStatusFlags_name[uint32(x)]
if ok {
return s
}
str := func(n uint32) string {
s, ok := IfStatusFlags_name[uint32(n)]
if ok {
return s
}
return "IfStatusFlags(" + strconv.Itoa(int(n)) + ")"
}
for i := uint32(0); i <= 32; i++ {
val := uint32(x)
if val&(1<<i) != 0 {
if s != "" {
s += "|"
}
s += str(1 << i)
}
}
if s == "" {
return str(uint32(x))
}
return s
}
// IfType defines enum 'if_type'.
type IfType uint32
const (
IF_API_TYPE_HARDWARE IfType = 0
IF_API_TYPE_SUB IfType = 1
IF_API_TYPE_P2P IfType = 2
IF_API_TYPE_PIPE IfType = 3
)
var (
IfType_name = map[uint32]string{
0: "IF_API_TYPE_HARDWARE",
1: "IF_API_TYPE_SUB",
2: "IF_API_TYPE_P2P",
3: "IF_API_TYPE_PIPE",
}
IfType_value = map[string]uint32{
"IF_API_TYPE_HARDWARE": 0,
"IF_API_TYPE_SUB": 1,
"IF_API_TYPE_P2P": 2,
"IF_API_TYPE_PIPE": 3,
}
)
func (x IfType) String() string {
s, ok := IfType_name[uint32(x)]
if ok {
return s
}
return "IfType(" + strconv.Itoa(int(x)) + ")"
}
// LinkDuplex defines enum 'link_duplex'.
type LinkDuplex uint32
const (
LINK_DUPLEX_API_UNKNOWN LinkDuplex = 0
LINK_DUPLEX_API_HALF LinkDuplex = 1
LINK_DUPLEX_API_FULL LinkDuplex = 2
)
var (
LinkDuplex_name = map[uint32]string{
0: "LINK_DUPLEX_API_UNKNOWN",
1: "LINK_DUPLEX_API_HALF",
2: "LINK_DUPLEX_API_FULL",
}
LinkDuplex_value = map[string]uint32{
"LINK_DUPLEX_API_UNKNOWN": 0,
"LINK_DUPLEX_API_HALF": 1,
"LINK_DUPLEX_API_FULL": 2,
}
)
func (x LinkDuplex) String() string {
s, ok := LinkDuplex_name[uint32(x)]
if ok {
return s
}
return "LinkDuplex(" + strconv.Itoa(int(x)) + ")"
}
// MtuProto defines enum 'mtu_proto'.
type MtuProto uint32
const (
MTU_PROTO_API_L3 MtuProto = 0
MTU_PROTO_API_IP4 MtuProto = 1
MTU_PROTO_API_IP6 MtuProto = 2
MTU_PROTO_API_MPLS MtuProto = 3
)
var (
MtuProto_name = map[uint32]string{
0: "MTU_PROTO_API_L3",
1: "MTU_PROTO_API_IP4",
2: "MTU_PROTO_API_IP6",
3: "MTU_PROTO_API_MPLS",
}
MtuProto_value = map[string]uint32{
"MTU_PROTO_API_L3": 0,
"MTU_PROTO_API_IP4": 1,
"MTU_PROTO_API_IP6": 2,
"MTU_PROTO_API_MPLS": 3,
}
)
func (x MtuProto) String() string {
s, ok := MtuProto_name[uint32(x)]
if ok {
return s
}
return "MtuProto(" + strconv.Itoa(int(x)) + ")"
}
// RxMode defines enum 'rx_mode'.
type RxMode uint32
const (
RX_MODE_API_UNKNOWN RxMode = 0
RX_MODE_API_POLLING RxMode = 1
RX_MODE_API_INTERRUPT RxMode = 2
RX_MODE_API_ADAPTIVE RxMode = 3
RX_MODE_API_DEFAULT RxMode = 4
)
var (
RxMode_name = map[uint32]string{
0: "RX_MODE_API_UNKNOWN",
1: "RX_MODE_API_POLLING",
2: "RX_MODE_API_INTERRUPT",
3: "RX_MODE_API_ADAPTIVE",
4: "RX_MODE_API_DEFAULT",
}
RxMode_value = map[string]uint32{
"RX_MODE_API_UNKNOWN": 0,
"RX_MODE_API_POLLING": 1,
"RX_MODE_API_INTERRUPT": 2,
"RX_MODE_API_ADAPTIVE": 3,
"RX_MODE_API_DEFAULT": 4,
}
)
func (x RxMode) String() string {
s, ok := RxMode_name[uint32(x)]
if ok {
return s
}
return "RxMode(" + strconv.Itoa(int(x)) + ")"
}
// SubIfFlags defines enum 'sub_if_flags'.
type SubIfFlags uint32
const (
SUB_IF_API_FLAG_NO_TAGS SubIfFlags = 1
SUB_IF_API_FLAG_ONE_TAG SubIfFlags = 2
SUB_IF_API_FLAG_TWO_TAGS SubIfFlags = 4
SUB_IF_API_FLAG_DOT1AD SubIfFlags = 8
SUB_IF_API_FLAG_EXACT_MATCH SubIfFlags = 16
SUB_IF_API_FLAG_DEFAULT SubIfFlags = 32
SUB_IF_API_FLAG_OUTER_VLAN_ID_ANY SubIfFlags = 64
SUB_IF_API_FLAG_INNER_VLAN_ID_ANY SubIfFlags = 128
SUB_IF_API_FLAG_MASK_VNET SubIfFlags = 254
SUB_IF_API_FLAG_DOT1AH SubIfFlags = 256
)
var (
SubIfFlags_name = map[uint32]string{
1: "SUB_IF_API_FLAG_NO_TAGS",
2: "SUB_IF_API_FLAG_ONE_TAG",
4: "SUB_IF_API_FLAG_TWO_TAGS",
8: "SUB_IF_API_FLAG_DOT1AD",
16: "SUB_IF_API_FLAG_EXACT_MATCH",
32: "SUB_IF_API_FLAG_DEFAULT",
64: "SUB_IF_API_FLAG_OUTER_VLAN_ID_ANY",
128: "SUB_IF_API_FLAG_INNER_VLAN_ID_ANY",
254: "SUB_IF_API_FLAG_MASK_VNET",
256: "SUB_IF_API_FLAG_DOT1AH",
}
SubIfFlags_value = map[string]uint32{
"SUB_IF_API_FLAG_NO_TAGS": 1,
"SUB_IF_API_FLAG_ONE_TAG": 2,
"SUB_IF_API_FLAG_TWO_TAGS": 4,
"SUB_IF_API_FLAG_DOT1AD": 8,
"SUB_IF_API_FLAG_EXACT_MATCH": 16,
"SUB_IF_API_FLAG_DEFAULT": 32,
"SUB_IF_API_FLAG_OUTER_VLAN_ID_ANY": 64,
"SUB_IF_API_FLAG_INNER_VLAN_ID_ANY": 128,
"SUB_IF_API_FLAG_MASK_VNET": 254,
"SUB_IF_API_FLAG_DOT1AH": 256,
}
)
func (x SubIfFlags) String() string {
s, ok := SubIfFlags_name[uint32(x)]
if ok {
return s
}
str := func(n uint32) string {
s, ok := SubIfFlags_name[uint32(n)]
if ok {
return s
}
return "SubIfFlags(" + strconv.Itoa(int(n)) + ")"
}
for i := uint32(0); i <= 32; i++ {
val := uint32(x)
if val&(1<<i) != 0 {
if s != "" {
s += "|"
}
s += str(1 << i)
}
}
if s == "" {
return str(uint32(x))
}
return s
}
// InterfaceIndex defines alias 'interface_index'.
type InterfaceIndex uint32

View File

@@ -0,0 +1,717 @@
// Code generated by GoVPP's binapi-generator. DO NOT EDIT.
// Package ip_types contains generated bindings for API file ip_types.api.
//
// Contents:
// - 5 aliases
// - 5 enums
// - 8 structs
// - 1 union
package ip_types
import (
"fmt"
"net"
"strconv"
"strings"
api "go.fd.io/govpp/api"
codec "go.fd.io/govpp/codec"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the GoVPP api package it is being compiled against.
// A compilation error at this line likely means your copy of the
// GoVPP api package needs to be updated.
const _ = api.GoVppAPIPackageIsVersion2
const (
APIFile = "ip_types"
APIVersion = "3.0.0"
VersionCrc = 0xfee023ed
)
// AddressFamily defines enum 'address_family'.
type AddressFamily uint8
const (
ADDRESS_IP4 AddressFamily = 0
ADDRESS_IP6 AddressFamily = 1
)
var (
AddressFamily_name = map[uint8]string{
0: "ADDRESS_IP4",
1: "ADDRESS_IP6",
}
AddressFamily_value = map[string]uint8{
"ADDRESS_IP4": 0,
"ADDRESS_IP6": 1,
}
)
func (x AddressFamily) String() string {
s, ok := AddressFamily_name[uint8(x)]
if ok {
return s
}
return "AddressFamily(" + strconv.Itoa(int(x)) + ")"
}
// IPDscp defines enum 'ip_dscp'.
type IPDscp uint8
const (
IP_API_DSCP_CS0 IPDscp = 0
IP_API_DSCP_CS1 IPDscp = 8
IP_API_DSCP_AF11 IPDscp = 10
IP_API_DSCP_AF12 IPDscp = 12
IP_API_DSCP_AF13 IPDscp = 14
IP_API_DSCP_CS2 IPDscp = 16
IP_API_DSCP_AF21 IPDscp = 18
IP_API_DSCP_AF22 IPDscp = 20
IP_API_DSCP_AF23 IPDscp = 22
IP_API_DSCP_CS3 IPDscp = 24
IP_API_DSCP_AF31 IPDscp = 26
IP_API_DSCP_AF32 IPDscp = 28
IP_API_DSCP_AF33 IPDscp = 30
IP_API_DSCP_CS4 IPDscp = 32
IP_API_DSCP_AF41 IPDscp = 34
IP_API_DSCP_AF42 IPDscp = 36
IP_API_DSCP_AF43 IPDscp = 38
IP_API_DSCP_CS5 IPDscp = 40
IP_API_DSCP_EF IPDscp = 46
IP_API_DSCP_CS6 IPDscp = 48
IP_API_DSCP_CS7 IPDscp = 50
)
var (
IPDscp_name = map[uint8]string{
0: "IP_API_DSCP_CS0",
8: "IP_API_DSCP_CS1",
10: "IP_API_DSCP_AF11",
12: "IP_API_DSCP_AF12",
14: "IP_API_DSCP_AF13",
16: "IP_API_DSCP_CS2",
18: "IP_API_DSCP_AF21",
20: "IP_API_DSCP_AF22",
22: "IP_API_DSCP_AF23",
24: "IP_API_DSCP_CS3",
26: "IP_API_DSCP_AF31",
28: "IP_API_DSCP_AF32",
30: "IP_API_DSCP_AF33",
32: "IP_API_DSCP_CS4",
34: "IP_API_DSCP_AF41",
36: "IP_API_DSCP_AF42",
38: "IP_API_DSCP_AF43",
40: "IP_API_DSCP_CS5",
46: "IP_API_DSCP_EF",
48: "IP_API_DSCP_CS6",
50: "IP_API_DSCP_CS7",
}
IPDscp_value = map[string]uint8{
"IP_API_DSCP_CS0": 0,
"IP_API_DSCP_CS1": 8,
"IP_API_DSCP_AF11": 10,
"IP_API_DSCP_AF12": 12,
"IP_API_DSCP_AF13": 14,
"IP_API_DSCP_CS2": 16,
"IP_API_DSCP_AF21": 18,
"IP_API_DSCP_AF22": 20,
"IP_API_DSCP_AF23": 22,
"IP_API_DSCP_CS3": 24,
"IP_API_DSCP_AF31": 26,
"IP_API_DSCP_AF32": 28,
"IP_API_DSCP_AF33": 30,
"IP_API_DSCP_CS4": 32,
"IP_API_DSCP_AF41": 34,
"IP_API_DSCP_AF42": 36,
"IP_API_DSCP_AF43": 38,
"IP_API_DSCP_CS5": 40,
"IP_API_DSCP_EF": 46,
"IP_API_DSCP_CS6": 48,
"IP_API_DSCP_CS7": 50,
}
)
func (x IPDscp) String() string {
s, ok := IPDscp_name[uint8(x)]
if ok {
return s
}
return "IPDscp(" + strconv.Itoa(int(x)) + ")"
}
// IPEcn defines enum 'ip_ecn'.
type IPEcn uint8
const (
IP_API_ECN_NONE IPEcn = 0
IP_API_ECN_ECT0 IPEcn = 1
IP_API_ECN_ECT1 IPEcn = 2
IP_API_ECN_CE IPEcn = 3
)
var (
IPEcn_name = map[uint8]string{
0: "IP_API_ECN_NONE",
1: "IP_API_ECN_ECT0",
2: "IP_API_ECN_ECT1",
3: "IP_API_ECN_CE",
}
IPEcn_value = map[string]uint8{
"IP_API_ECN_NONE": 0,
"IP_API_ECN_ECT0": 1,
"IP_API_ECN_ECT1": 2,
"IP_API_ECN_CE": 3,
}
)
func (x IPEcn) String() string {
s, ok := IPEcn_name[uint8(x)]
if ok {
return s
}
return "IPEcn(" + strconv.Itoa(int(x)) + ")"
}
// IPFeatureLocation defines enum 'ip_feature_location'.
type IPFeatureLocation uint8
const (
IP_API_FEATURE_INPUT IPFeatureLocation = 0
IP_API_FEATURE_OUTPUT IPFeatureLocation = 1
IP_API_FEATURE_LOCAL IPFeatureLocation = 2
IP_API_FEATURE_PUNT IPFeatureLocation = 3
IP_API_FEATURE_DROP IPFeatureLocation = 4
)
var (
IPFeatureLocation_name = map[uint8]string{
0: "IP_API_FEATURE_INPUT",
1: "IP_API_FEATURE_OUTPUT",
2: "IP_API_FEATURE_LOCAL",
3: "IP_API_FEATURE_PUNT",
4: "IP_API_FEATURE_DROP",
}
IPFeatureLocation_value = map[string]uint8{
"IP_API_FEATURE_INPUT": 0,
"IP_API_FEATURE_OUTPUT": 1,
"IP_API_FEATURE_LOCAL": 2,
"IP_API_FEATURE_PUNT": 3,
"IP_API_FEATURE_DROP": 4,
}
)
func (x IPFeatureLocation) String() string {
s, ok := IPFeatureLocation_name[uint8(x)]
if ok {
return s
}
return "IPFeatureLocation(" + strconv.Itoa(int(x)) + ")"
}
// IPProto defines enum 'ip_proto'.
type IPProto uint8
const (
IP_API_PROTO_HOPOPT IPProto = 0
IP_API_PROTO_ICMP IPProto = 1
IP_API_PROTO_IGMP IPProto = 2
IP_API_PROTO_TCP IPProto = 6
IP_API_PROTO_UDP IPProto = 17
IP_API_PROTO_GRE IPProto = 47
IP_API_PROTO_ESP IPProto = 50
IP_API_PROTO_AH IPProto = 51
IP_API_PROTO_ICMP6 IPProto = 58
IP_API_PROTO_EIGRP IPProto = 88
IP_API_PROTO_OSPF IPProto = 89
IP_API_PROTO_SCTP IPProto = 132
IP_API_PROTO_RESERVED IPProto = 255
)
var (
IPProto_name = map[uint8]string{
0: "IP_API_PROTO_HOPOPT",
1: "IP_API_PROTO_ICMP",
2: "IP_API_PROTO_IGMP",
6: "IP_API_PROTO_TCP",
17: "IP_API_PROTO_UDP",
47: "IP_API_PROTO_GRE",
50: "IP_API_PROTO_ESP",
51: "IP_API_PROTO_AH",
58: "IP_API_PROTO_ICMP6",
88: "IP_API_PROTO_EIGRP",
89: "IP_API_PROTO_OSPF",
132: "IP_API_PROTO_SCTP",
255: "IP_API_PROTO_RESERVED",
}
IPProto_value = map[string]uint8{
"IP_API_PROTO_HOPOPT": 0,
"IP_API_PROTO_ICMP": 1,
"IP_API_PROTO_IGMP": 2,
"IP_API_PROTO_TCP": 6,
"IP_API_PROTO_UDP": 17,
"IP_API_PROTO_GRE": 47,
"IP_API_PROTO_ESP": 50,
"IP_API_PROTO_AH": 51,
"IP_API_PROTO_ICMP6": 58,
"IP_API_PROTO_EIGRP": 88,
"IP_API_PROTO_OSPF": 89,
"IP_API_PROTO_SCTP": 132,
"IP_API_PROTO_RESERVED": 255,
}
)
func (x IPProto) String() string {
s, ok := IPProto_name[uint8(x)]
if ok {
return s
}
return "IPProto(" + strconv.Itoa(int(x)) + ")"
}
// AddressWithPrefix defines alias 'address_with_prefix'.
type AddressWithPrefix Prefix
func NewAddressWithPrefix(network net.IPNet) AddressWithPrefix {
prefix := NewPrefix(network)
return AddressWithPrefix(prefix)
}
func ParseAddressWithPrefix(s string) (AddressWithPrefix, error) {
prefix, err := ParsePrefix(s)
if err != nil {
return AddressWithPrefix{}, err
}
return AddressWithPrefix(prefix), nil
}
func (x AddressWithPrefix) ToIPNet() *net.IPNet {
return Prefix(x).ToIPNet()
}
func (x AddressWithPrefix) String() string {
return Prefix(x).String()
}
func (x *AddressWithPrefix) MarshalText() ([]byte, error) {
return []byte(x.String()), nil
}
func (x *AddressWithPrefix) UnmarshalText(text []byte) error {
prefix, err := ParseAddressWithPrefix(string(text))
if err != nil {
return err
}
*x = prefix
return nil
}
// IP4Address defines alias 'ip4_address'.
type IP4Address [4]uint8
func NewIP4Address(ip net.IP) IP4Address {
var ipaddr IP4Address
copy(ipaddr[:], ip.To4())
return ipaddr
}
func ParseIP4Address(s string) (IP4Address, error) {
ip := net.ParseIP(s).To4()
if ip == nil {
return IP4Address{}, fmt.Errorf("invalid IP4 address: %s", s)
}
var ipaddr IP4Address
copy(ipaddr[:], ip.To4())
return ipaddr, nil
}
func (x IP4Address) ToIP() net.IP {
return net.IP(x[:]).To4()
}
func (x IP4Address) String() string {
return x.ToIP().String()
}
func (x *IP4Address) MarshalText() ([]byte, error) {
return []byte(x.String()), nil
}
func (x *IP4Address) UnmarshalText(text []byte) error {
ipaddr, err := ParseIP4Address(string(text))
if err != nil {
return err
}
*x = ipaddr
return nil
}
// IP4AddressWithPrefix defines alias 'ip4_address_with_prefix'.
type IP4AddressWithPrefix IP4Prefix
// IP6Address defines alias 'ip6_address'.
type IP6Address [16]uint8
func NewIP6Address(ip net.IP) IP6Address {
var ipaddr IP6Address
copy(ipaddr[:], ip.To16())
return ipaddr
}
func ParseIP6Address(s string) (IP6Address, error) {
ip := net.ParseIP(s).To16()
if ip == nil {
return IP6Address{}, fmt.Errorf("invalid IP6 address: %s", s)
}
var ipaddr IP6Address
copy(ipaddr[:], ip.To16())
return ipaddr, nil
}
func (x IP6Address) ToIP() net.IP {
return net.IP(x[:]).To16()
}
func (x IP6Address) String() string {
return x.ToIP().String()
}
func (x *IP6Address) MarshalText() ([]byte, error) {
return []byte(x.String()), nil
}
func (x *IP6Address) UnmarshalText(text []byte) error {
ipaddr, err := ParseIP6Address(string(text))
if err != nil {
return err
}
*x = ipaddr
return nil
}
// IP6AddressWithPrefix defines alias 'ip6_address_with_prefix'.
type IP6AddressWithPrefix IP6Prefix
// Address defines type 'address'.
type Address struct {
Af AddressFamily `binapi:"address_family,name=af" json:"af,omitempty"`
Un AddressUnion `binapi:"address_union,name=un" json:"un,omitempty"`
}
func NewAddress(ip net.IP) Address {
var addr Address
if ip.To4() == nil {
addr.Af = ADDRESS_IP6
var ip6 IP6Address
copy(ip6[:], ip.To16())
addr.Un.SetIP6(ip6)
} else {
addr.Af = ADDRESS_IP4
var ip4 IP4Address
copy(ip4[:], ip.To4())
addr.Un.SetIP4(ip4)
}
return addr
}
func ParseAddress(s string) (Address, error) {
ip := net.ParseIP(s)
if ip == nil {
return Address{}, fmt.Errorf("invalid IP address: %s", s)
}
return NewAddress(ip), nil
}
func (x Address) ToIP() net.IP {
if x.Af == ADDRESS_IP6 {
ip6 := x.Un.GetIP6()
return net.IP(ip6[:]).To16()
} else {
ip4 := x.Un.GetIP4()
return net.IP(ip4[:]).To4()
}
}
func (x Address) String() string {
return x.ToIP().String()
}
func (x *Address) MarshalText() ([]byte, error) {
return []byte(x.String()), nil
}
func (x *Address) UnmarshalText(text []byte) error {
addr, err := ParseAddress(string(text))
if err != nil {
return err
}
*x = addr
return nil
}
// IP4AddressAndMask defines type 'ip4_address_and_mask'.
type IP4AddressAndMask struct {
Addr IP4Address `binapi:"ip4_address,name=addr" json:"addr,omitempty"`
Mask IP4Address `binapi:"ip4_address,name=mask" json:"mask,omitempty"`
}
// IP4Prefix defines type 'ip4_prefix'.
type IP4Prefix struct {
Address IP4Address `binapi:"ip4_address,name=address" json:"address,omitempty"`
Len uint8 `binapi:"u8,name=len" json:"len,omitempty"`
}
func NewIP4Prefix(network net.IPNet) IP4Prefix {
var prefix IP4Prefix
maskSize, _ := network.Mask.Size()
prefix.Len = byte(maskSize)
prefix.Address = NewIP4Address(network.IP)
return prefix
}
func ParseIP4Prefix(s string) (prefix IP4Prefix, err error) {
hasPrefix := strings.Contains(s, "/")
if hasPrefix {
ip, network, err := net.ParseCIDR(s)
if err != nil {
return IP4Prefix{}, fmt.Errorf("invalid IP4 %s: %s", s, err)
}
maskSize, _ := network.Mask.Size()
prefix.Len = byte(maskSize)
prefix.Address, err = ParseIP4Address(ip.String())
if err != nil {
return IP4Prefix{}, fmt.Errorf("invalid IP4 %s: %s", s, err)
}
} else {
ip := net.ParseIP(s)
defaultMaskSize, _ := net.CIDRMask(32, 32).Size()
if ip.To4() == nil {
defaultMaskSize, _ = net.CIDRMask(128, 128).Size()
}
prefix.Len = byte(defaultMaskSize)
prefix.Address, err = ParseIP4Address(ip.String())
if err != nil {
return IP4Prefix{}, fmt.Errorf("invalid IP4 %s: %s", s, err)
}
}
return prefix, nil
}
func (x IP4Prefix) ToIPNet() *net.IPNet {
mask := net.CIDRMask(int(x.Len), 32)
ipnet := &net.IPNet{IP: x.Address.ToIP(), Mask: mask}
return ipnet
}
func (x IP4Prefix) String() string {
ip := x.Address.String()
return ip + "/" + strconv.Itoa(int(x.Len))
}
func (x *IP4Prefix) MarshalText() ([]byte, error) {
return []byte(x.String()), nil
}
func (x *IP4Prefix) UnmarshalText(text []byte) error {
prefix, err := ParseIP4Prefix(string(text))
if err != nil {
return err
}
*x = prefix
return nil
}
// IP6AddressAndMask defines type 'ip6_address_and_mask'.
type IP6AddressAndMask struct {
Addr IP6Address `binapi:"ip6_address,name=addr" json:"addr,omitempty"`
Mask IP6Address `binapi:"ip6_address,name=mask" json:"mask,omitempty"`
}
// IP6Prefix defines type 'ip6_prefix'.
type IP6Prefix struct {
Address IP6Address `binapi:"ip6_address,name=address" json:"address,omitempty"`
Len uint8 `binapi:"u8,name=len" json:"len,omitempty"`
}
func NewIP6Prefix(network net.IPNet) IP6Prefix {
var prefix IP6Prefix
maskSize, _ := network.Mask.Size()
prefix.Len = byte(maskSize)
prefix.Address = NewIP6Address(network.IP)
return prefix
}
func ParseIP6Prefix(s string) (prefix IP6Prefix, err error) {
hasPrefix := strings.Contains(s, "/")
if hasPrefix {
ip, network, err := net.ParseCIDR(s)
if err != nil {
return IP6Prefix{}, fmt.Errorf("invalid IP6 %s: %s", s, err)
}
maskSize, _ := network.Mask.Size()
prefix.Len = byte(maskSize)
prefix.Address, err = ParseIP6Address(ip.String())
if err != nil {
return IP6Prefix{}, fmt.Errorf("invalid IP6 %s: %s", s, err)
}
} else {
ip := net.ParseIP(s)
defaultMaskSize, _ := net.CIDRMask(32, 32).Size()
if ip.To4() == nil {
defaultMaskSize, _ = net.CIDRMask(128, 128).Size()
}
prefix.Len = byte(defaultMaskSize)
prefix.Address, err = ParseIP6Address(ip.String())
if err != nil {
return IP6Prefix{}, fmt.Errorf("invalid IP6 %s: %s", s, err)
}
}
return prefix, nil
}
func (x IP6Prefix) ToIPNet() *net.IPNet {
mask := net.CIDRMask(int(x.Len), 128)
ipnet := &net.IPNet{IP: x.Address.ToIP(), Mask: mask}
return ipnet
}
func (x IP6Prefix) String() string {
ip := x.Address.String()
return ip + "/" + strconv.Itoa(int(x.Len))
}
func (x *IP6Prefix) MarshalText() ([]byte, error) {
return []byte(x.String()), nil
}
func (x *IP6Prefix) UnmarshalText(text []byte) error {
prefix, err := ParseIP6Prefix(string(text))
if err != nil {
return err
}
*x = prefix
return nil
}
// Mprefix defines type 'mprefix'.
type Mprefix struct {
Af AddressFamily `binapi:"address_family,name=af" json:"af,omitempty"`
GrpAddressLength uint16 `binapi:"u16,name=grp_address_length" json:"grp_address_length,omitempty"`
GrpAddress AddressUnion `binapi:"address_union,name=grp_address" json:"grp_address,omitempty"`
SrcAddress AddressUnion `binapi:"address_union,name=src_address" json:"src_address,omitempty"`
}
// Prefix defines type 'prefix'.
type Prefix struct {
Address Address `binapi:"address,name=address" json:"address,omitempty"`
Len uint8 `binapi:"u8,name=len" json:"len,omitempty"`
}
func NewPrefix(network net.IPNet) Prefix {
var prefix Prefix
maskSize, _ := network.Mask.Size()
prefix.Len = byte(maskSize)
prefix.Address = NewAddress(network.IP)
return prefix
}
func ParsePrefix(ip string) (prefix Prefix, err error) {
hasPrefix := strings.Contains(ip, "/")
if hasPrefix {
netIP, network, err := net.ParseCIDR(ip)
if err != nil {
return Prefix{}, fmt.Errorf("invalid IP %s: %s", ip, err)
}
maskSize, _ := network.Mask.Size()
prefix.Len = byte(maskSize)
prefix.Address, err = ParseAddress(netIP.String())
if err != nil {
return Prefix{}, fmt.Errorf("invalid IP %s: %s", ip, err)
}
} else {
netIP := net.ParseIP(ip)
defaultMaskSize, _ := net.CIDRMask(32, 32).Size()
if netIP.To4() == nil {
defaultMaskSize, _ = net.CIDRMask(128, 128).Size()
}
prefix.Len = byte(defaultMaskSize)
prefix.Address, err = ParseAddress(netIP.String())
if err != nil {
return Prefix{}, fmt.Errorf("invalid IP %s: %s", ip, err)
}
}
return prefix, nil
}
func (x Prefix) ToIPNet() *net.IPNet {
var mask net.IPMask
if x.Address.Af == ADDRESS_IP4 {
mask = net.CIDRMask(int(x.Len), 32)
} else {
mask = net.CIDRMask(int(x.Len), 128)
}
ipnet := &net.IPNet{IP: x.Address.ToIP(), Mask: mask}
return ipnet
}
func (x Prefix) String() string {
ip := x.Address.String()
return ip + "/" + strconv.Itoa(int(x.Len))
}
func (x *Prefix) MarshalText() ([]byte, error) {
return []byte(x.String()), nil
}
func (x *Prefix) UnmarshalText(text []byte) error {
prefix, err := ParsePrefix(string(text))
if err != nil {
return err
}
*x = prefix
return nil
}
// PrefixMatcher defines type 'prefix_matcher'.
type PrefixMatcher struct {
Le uint8 `binapi:"u8,name=le" json:"le,omitempty"`
Ge uint8 `binapi:"u8,name=ge" json:"ge,omitempty"`
}
// AddressUnion defines union 'address_union'.
type AddressUnion struct {
// AddressUnion can be one of:
// - IP4 *IP4Address
// - IP6 *IP6Address
XXX_UnionData [16]byte
}
func AddressUnionIP4(a IP4Address) (u AddressUnion) {
u.SetIP4(a)
return
}
func (u *AddressUnion) SetIP4(a IP4Address) {
buf := codec.NewBuffer(u.XXX_UnionData[:])
buf.EncodeBytes(a[:], 4)
}
func (u *AddressUnion) GetIP4() (a IP4Address) {
buf := codec.NewBuffer(u.XXX_UnionData[:])
copy(a[:], buf.DecodeBytes(4))
return
}
func AddressUnionIP6(a IP6Address) (u AddressUnion) {
u.SetIP6(a)
return
}
func (u *AddressUnion) SetIP6(a IP6Address) {
buf := codec.NewBuffer(u.XXX_UnionData[:])
buf.EncodeBytes(a[:], 16)
}
func (u *AddressUnion) GetIP6() (a IP6Address) {
buf := codec.NewBuffer(u.XXX_UnionData[:])
copy(a[:], buf.DecodeBytes(16))
return
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,211 @@
// Code generated by GoVPP's binapi-generator. DO NOT EDIT.
// Package lb_types contains generated bindings for API file lb_types.api.
//
// Contents:
// - 5 enums
// - 1 struct
package lb_types
import (
"strconv"
ip_types "git.ipng.ch/ipng/vpp-maglev/internal/vpp/binapi/ip_types"
api "go.fd.io/govpp/api"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the GoVPP api package it is being compiled against.
// A compilation error at this line likely means your copy of the
// GoVPP api package needs to be updated.
const _ = api.GoVppAPIPackageIsVersion2
const (
APIFile = "lb_types"
APIVersion = "1.0.0"
VersionCrc = 0xba19340c
)
// LbEncapType defines enum 'lb_encap_type'.
type LbEncapType uint32
const (
LB_API_ENCAP_TYPE_GRE4 LbEncapType = 0
LB_API_ENCAP_TYPE_GRE6 LbEncapType = 1
LB_API_ENCAP_TYPE_L3DSR LbEncapType = 2
LB_API_ENCAP_TYPE_NAT4 LbEncapType = 3
LB_API_ENCAP_TYPE_NAT6 LbEncapType = 4
LB_API_ENCAP_N_TYPES LbEncapType = 5
)
var (
LbEncapType_name = map[uint32]string{
0: "LB_API_ENCAP_TYPE_GRE4",
1: "LB_API_ENCAP_TYPE_GRE6",
2: "LB_API_ENCAP_TYPE_L3DSR",
3: "LB_API_ENCAP_TYPE_NAT4",
4: "LB_API_ENCAP_TYPE_NAT6",
5: "LB_API_ENCAP_N_TYPES",
}
LbEncapType_value = map[string]uint32{
"LB_API_ENCAP_TYPE_GRE4": 0,
"LB_API_ENCAP_TYPE_GRE6": 1,
"LB_API_ENCAP_TYPE_L3DSR": 2,
"LB_API_ENCAP_TYPE_NAT4": 3,
"LB_API_ENCAP_TYPE_NAT6": 4,
"LB_API_ENCAP_N_TYPES": 5,
}
)
func (x LbEncapType) String() string {
s, ok := LbEncapType_name[uint32(x)]
if ok {
return s
}
return "LbEncapType(" + strconv.Itoa(int(x)) + ")"
}
// LbLkpTypeT defines enum 'lb_lkp_type_t'.
type LbLkpTypeT uint32
const (
LB_API_LKP_SAME_IP_PORT LbLkpTypeT = 0
LB_API_LKP_DIFF_IP_PORT LbLkpTypeT = 1
LB_API_LKP_ALL_PORT_IP LbLkpTypeT = 2
LB_API_LKP_N_TYPES LbLkpTypeT = 3
)
var (
LbLkpTypeT_name = map[uint32]string{
0: "LB_API_LKP_SAME_IP_PORT",
1: "LB_API_LKP_DIFF_IP_PORT",
2: "LB_API_LKP_ALL_PORT_IP",
3: "LB_API_LKP_N_TYPES",
}
LbLkpTypeT_value = map[string]uint32{
"LB_API_LKP_SAME_IP_PORT": 0,
"LB_API_LKP_DIFF_IP_PORT": 1,
"LB_API_LKP_ALL_PORT_IP": 2,
"LB_API_LKP_N_TYPES": 3,
}
)
func (x LbLkpTypeT) String() string {
s, ok := LbLkpTypeT_name[uint32(x)]
if ok {
return s
}
return "LbLkpTypeT(" + strconv.Itoa(int(x)) + ")"
}
// LbNatProtocol defines enum 'lb_nat_protocol'.
type LbNatProtocol uint32
const (
LB_API_NAT_PROTOCOL_UDP LbNatProtocol = 6
LB_API_NAT_PROTOCOL_TCP LbNatProtocol = 23
LB_API_NAT_PROTOCOL_ANY LbNatProtocol = 4294967295
)
var (
LbNatProtocol_name = map[uint32]string{
6: "LB_API_NAT_PROTOCOL_UDP",
23: "LB_API_NAT_PROTOCOL_TCP",
4294967295: "LB_API_NAT_PROTOCOL_ANY",
}
LbNatProtocol_value = map[string]uint32{
"LB_API_NAT_PROTOCOL_UDP": 6,
"LB_API_NAT_PROTOCOL_TCP": 23,
"LB_API_NAT_PROTOCOL_ANY": 4294967295,
}
)
func (x LbNatProtocol) String() string {
s, ok := LbNatProtocol_name[uint32(x)]
if ok {
return s
}
return "LbNatProtocol(" + strconv.Itoa(int(x)) + ")"
}
// LbSrvType defines enum 'lb_srv_type'.
type LbSrvType uint32
const (
LB_API_SRV_TYPE_CLUSTERIP LbSrvType = 0
LB_API_SRV_TYPE_NODEPORT LbSrvType = 1
LB_API_SRV_N_TYPES LbSrvType = 2
)
var (
LbSrvType_name = map[uint32]string{
0: "LB_API_SRV_TYPE_CLUSTERIP",
1: "LB_API_SRV_TYPE_NODEPORT",
2: "LB_API_SRV_N_TYPES",
}
LbSrvType_value = map[string]uint32{
"LB_API_SRV_TYPE_CLUSTERIP": 0,
"LB_API_SRV_TYPE_NODEPORT": 1,
"LB_API_SRV_N_TYPES": 2,
}
)
func (x LbSrvType) String() string {
s, ok := LbSrvType_name[uint32(x)]
if ok {
return s
}
return "LbSrvType(" + strconv.Itoa(int(x)) + ")"
}
// LbVipType defines enum 'lb_vip_type'.
type LbVipType uint32
const (
LB_API_VIP_TYPE_IP6_GRE6 LbVipType = 0
LB_API_VIP_TYPE_IP6_GRE4 LbVipType = 1
LB_API_VIP_TYPE_IP4_GRE6 LbVipType = 2
LB_API_VIP_TYPE_IP4_GRE4 LbVipType = 3
LB_API_VIP_TYPE_IP4_L3DSR LbVipType = 4
LB_API_VIP_TYPE_IP4_NAT4 LbVipType = 5
LB_API_VIP_TYPE_IP6_NAT6 LbVipType = 6
LB_API_VIP_N_TYPES LbVipType = 7
)
var (
LbVipType_name = map[uint32]string{
0: "LB_API_VIP_TYPE_IP6_GRE6",
1: "LB_API_VIP_TYPE_IP6_GRE4",
2: "LB_API_VIP_TYPE_IP4_GRE6",
3: "LB_API_VIP_TYPE_IP4_GRE4",
4: "LB_API_VIP_TYPE_IP4_L3DSR",
5: "LB_API_VIP_TYPE_IP4_NAT4",
6: "LB_API_VIP_TYPE_IP6_NAT6",
7: "LB_API_VIP_N_TYPES",
}
LbVipType_value = map[string]uint32{
"LB_API_VIP_TYPE_IP6_GRE6": 0,
"LB_API_VIP_TYPE_IP6_GRE4": 1,
"LB_API_VIP_TYPE_IP4_GRE6": 2,
"LB_API_VIP_TYPE_IP4_GRE4": 3,
"LB_API_VIP_TYPE_IP4_L3DSR": 4,
"LB_API_VIP_TYPE_IP4_NAT4": 5,
"LB_API_VIP_TYPE_IP6_NAT6": 6,
"LB_API_VIP_N_TYPES": 7,
}
)
func (x LbVipType) String() string {
s, ok := LbVipType_name[uint32(x)]
if ok {
return s
}
return "LbVipType(" + strconv.Itoa(int(x)) + ")"
}
// LbVip defines type 'lb_vip'.
type LbVip struct {
Pfx ip_types.AddressWithPrefix `binapi:"address_with_prefix,name=pfx" json:"pfx,omitempty"`
Protocol ip_types.IPProto `binapi:"ip_proto,name=protocol" json:"protocol,omitempty"`
Port uint16 `binapi:"u16,name=port" json:"port,omitempty"`
}