From a52954c903b9d977aeed9af769c90dc39ff8165f Mon Sep 17 00:00:00 2001 From: Rastislav Szabo Date: Mon, 22 Jun 2020 13:13:48 +0200 Subject: [PATCH] feat: Add IPIP & IPSec point-to-multipoint support (#1669) * IPIP & IPSec point-to-multipoint support Signed-off-by: Rastislav Szabo * Add workaround for ipip tunnel mode Signed-off-by: Rastislav Szabo * Add TEIB support Signed-off-by: Rastislav Szabo --- plugins/vpp/binapi/vpp2005/teib/teib.ba.go | 212 +++++++++++++ plugins/vpp/binapi/vpp2005/vpp2005.go | 3 + plugins/vpp/ifplugin/descriptor/interface.go | 12 +- .../vppcalls/vpp2005/ipip_vppcalls.go | 75 +++-- .../vppcalls/vpp2005/dump_vppcalls.go | 14 + .../vppcalls/vpp2005/ipsec_vppcalls.go | 14 + .../l3plugin/descriptor/adapter/teibentry.go | 233 ++++++++++++++ plugins/vpp/l3plugin/descriptor/teib_entry.go | 139 ++++++++ plugins/vpp/l3plugin/l3plugin.go | 3 + plugins/vpp/l3plugin/vppcalls/l3_vppcalls.go | 20 ++ .../vppcalls/vpp1904/vppcalls_handlers.go | 17 + .../vppcalls/vpp1908/vppcalls_handlers.go | 32 +- .../vppcalls/vpp2001/vppcalls_handlers.go | 32 +- .../vppcalls/vpp2005/teib_vppcalls.go | 89 ++++++ .../vppcalls/vpp2005/vppcalls_handlers.go | 21 ++ proto/ligato/vpp/interfaces/interface.pb.go | 297 +++++++++--------- proto/ligato/vpp/interfaces/interface.proto | 3 +- proto/ligato/vpp/ipsec/ipsec.pb.go | 133 ++++---- proto/ligato/vpp/ipsec/ipsec.proto | 3 + proto/ligato/vpp/ipsec/models.go | 3 +- proto/ligato/vpp/l3/models.go | 8 + proto/ligato/vpp/l3/teib.pb.go | 112 +++++++ proto/ligato/vpp/l3/teib.proto | 20 ++ tests/e2e/070_ipsec_test.go | 148 +++++++++ tests/e2e/e2e_test.go | 2 +- tests/integration/vpp/120_ipip_test.go | 96 +++--- tests/integration/vpp/130_ipsec_test.go | 69 +++- tests/integration/vpp/140_teib_test.go | 149 +++++++++ 28 files changed, 1656 insertions(+), 303 deletions(-) create mode 100644 plugins/vpp/binapi/vpp2005/teib/teib.ba.go create mode 100644 plugins/vpp/l3plugin/descriptor/adapter/teibentry.go create mode 100644 plugins/vpp/l3plugin/descriptor/teib_entry.go create mode 100644 plugins/vpp/l3plugin/vppcalls/vpp2005/teib_vppcalls.go create mode 100644 proto/ligato/vpp/l3/teib.pb.go create mode 100644 proto/ligato/vpp/l3/teib.proto create mode 100644 tests/integration/vpp/140_teib_test.go diff --git a/plugins/vpp/binapi/vpp2005/teib/teib.ba.go b/plugins/vpp/binapi/vpp2005/teib/teib.ba.go new file mode 100644 index 0000000000..abf35bd610 --- /dev/null +++ b/plugins/vpp/binapi/vpp2005/teib/teib.ba.go @@ -0,0 +1,212 @@ +// Code generated by GoVPP's binapi-generator. DO NOT EDIT. +// source: /usr/share/vpp/api/core/teib.api.json + +/* +Package teib is a generated VPP binary API for 'teib' module. + +It consists of: + 10 enums + 6 aliases + 7 types + 1 union + 4 messages + 2 services +*/ +package teib + +import ( + "bytes" + "context" + "io" + "strconv" + + api "git.fd.io/govpp.git/api" + struc "github.com/lunixbochs/struc" + + interface_types "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2005/interface_types" + ip_types "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2005/ip_types" +) + +const ( + // ModuleName is the name of this module. + ModuleName = "teib" + // APIVersion is the API version of this module. + APIVersion = "1.0.0" + // VersionCrc is the CRC of this module. + VersionCrc = 0xaac93c17 +) + +type AddressFamily = ip_types.AddressFamily + +type IfStatusFlags = interface_types.IfStatusFlags + +type IfType = interface_types.IfType + +type IPDscp = ip_types.IPDscp + +type IPEcn = ip_types.IPEcn + +type IPProto = ip_types.IPProto + +type LinkDuplex = interface_types.LinkDuplex + +type MtuProto = interface_types.MtuProto + +type RxMode = interface_types.RxMode + +type SubIfFlags = interface_types.SubIfFlags + +type AddressWithPrefix = ip_types.AddressWithPrefix + +type InterfaceIndex = interface_types.InterfaceIndex + +type IP4Address = ip_types.IP4Address + +type IP4AddressWithPrefix = ip_types.IP4AddressWithPrefix + +type IP6Address = ip_types.IP6Address + +type IP6AddressWithPrefix = ip_types.IP6AddressWithPrefix + +type Address = ip_types.Address + +type IP4Prefix = ip_types.IP4Prefix + +type IP6Prefix = ip_types.IP6Prefix + +type Mprefix = ip_types.Mprefix + +type Prefix = ip_types.Prefix + +type PrefixMatcher = ip_types.PrefixMatcher + +// TeibEntry represents VPP binary API type 'teib_entry'. +type TeibEntry struct { + SwIfIndex InterfaceIndex + Peer Address + Nh Address + NhTableID uint32 +} + +func (*TeibEntry) GetTypeName() string { return "teib_entry" } + +type AddressUnion = ip_types.AddressUnion + +// TeibDetails represents VPP binary API message 'teib_details'. +type TeibDetails struct { + Entry TeibEntry +} + +func (m *TeibDetails) Reset() { *m = TeibDetails{} } +func (*TeibDetails) GetMessageName() string { return "teib_details" } +func (*TeibDetails) GetCrcString() string { return "e3b6a503" } +func (*TeibDetails) GetMessageType() api.MessageType { return api.ReplyMessage } + +// TeibDump represents VPP binary API message 'teib_dump'. +type TeibDump struct{} + +func (m *TeibDump) Reset() { *m = TeibDump{} } +func (*TeibDump) GetMessageName() string { return "teib_dump" } +func (*TeibDump) GetCrcString() string { return "51077d14" } +func (*TeibDump) GetMessageType() api.MessageType { return api.RequestMessage } + +// TeibEntryAddDel represents VPP binary API message 'teib_entry_add_del'. +type TeibEntryAddDel struct { + IsAdd uint8 + Entry TeibEntry +} + +func (m *TeibEntryAddDel) Reset() { *m = TeibEntryAddDel{} } +func (*TeibEntryAddDel) GetMessageName() string { return "teib_entry_add_del" } +func (*TeibEntryAddDel) GetCrcString() string { return "5aa0a538" } +func (*TeibEntryAddDel) GetMessageType() api.MessageType { return api.RequestMessage } + +// TeibEntryAddDelReply represents VPP binary API message 'teib_entry_add_del_reply'. +type TeibEntryAddDelReply struct { + Retval int32 +} + +func (m *TeibEntryAddDelReply) Reset() { *m = TeibEntryAddDelReply{} } +func (*TeibEntryAddDelReply) GetMessageName() string { return "teib_entry_add_del_reply" } +func (*TeibEntryAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*TeibEntryAddDelReply) GetMessageType() api.MessageType { return api.ReplyMessage } + +func init() { + api.RegisterMessage((*TeibDetails)(nil), "teib.TeibDetails") + api.RegisterMessage((*TeibDump)(nil), "teib.TeibDump") + api.RegisterMessage((*TeibEntryAddDel)(nil), "teib.TeibEntryAddDel") + api.RegisterMessage((*TeibEntryAddDelReply)(nil), "teib.TeibEntryAddDelReply") +} + +// Messages returns list of all messages in this module. +func AllMessages() []api.Message { + return []api.Message{ + (*TeibDetails)(nil), + (*TeibDump)(nil), + (*TeibEntryAddDel)(nil), + (*TeibEntryAddDelReply)(nil), + } +} + +// RPCService represents RPC service API for teib module. +type RPCService interface { + DumpTeib(ctx context.Context, in *TeibDump) (RPCService_DumpTeibClient, error) + TeibEntryAddDel(ctx context.Context, in *TeibEntryAddDel) (*TeibEntryAddDelReply, error) +} + +type serviceClient struct { + ch api.Channel +} + +func NewServiceClient(ch api.Channel) RPCService { + return &serviceClient{ch} +} + +func (c *serviceClient) DumpTeib(ctx context.Context, in *TeibDump) (RPCService_DumpTeibClient, error) { + stream := c.ch.SendMultiRequest(in) + x := &serviceClient_DumpTeibClient{stream} + return x, nil +} + +type RPCService_DumpTeibClient interface { + Recv() (*TeibDetails, error) +} + +type serviceClient_DumpTeibClient struct { + api.MultiRequestCtx +} + +func (c *serviceClient_DumpTeibClient) Recv() (*TeibDetails, error) { + m := new(TeibDetails) + stop, err := c.MultiRequestCtx.ReceiveReply(m) + if err != nil { + return nil, err + } + if stop { + return nil, io.EOF + } + return m, nil +} + +func (c *serviceClient) TeibEntryAddDel(ctx context.Context, in *TeibEntryAddDel) (*TeibEntryAddDelReply, error) { + out := new(TeibEntryAddDelReply) + err := c.ch.SendRequest(in).ReceiveReply(out) + if err != nil { + return nil, err + } + return out, nil +} + +// 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.GoVppAPIPackageIsVersion1 // please upgrade the GoVPP api package + +// Reference imports to suppress errors if they are not otherwise used. +var _ = api.RegisterMessage +var _ = bytes.NewBuffer +var _ = context.Background +var _ = io.Copy +var _ = strconv.Itoa +var _ = struc.Pack diff --git a/plugins/vpp/binapi/vpp2005/vpp2005.go b/plugins/vpp/binapi/vpp2005/vpp2005.go index 37da146518..77b9d48cb2 100644 --- a/plugins/vpp/binapi/vpp2005/vpp2005.go +++ b/plugins/vpp/binapi/vpp2005/vpp2005.go @@ -41,6 +41,7 @@ import ( "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2005/sr" "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2005/stn" "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2005/tapv2" + "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2005/teib" "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2005/vmxnet3" "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2005/vpe" "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2005/vxlan" @@ -66,6 +67,7 @@ func init() { span.AllMessages, sr.AllMessages, tapv2.AllMessages, + teib.AllMessages, vpe.AllMessages, vxlan.AllMessages, vxlan_gpe.AllMessages, @@ -110,6 +112,7 @@ func init() { //go:generate binapigen --input-file=$VPP_API_DIR/core/span.api.json //go:generate binapigen --input-file=$VPP_API_DIR/core/sr.api.json //go:generate binapigen --input-file=$VPP_API_DIR/core/tapv2.api.json +//go:generate binapigen --input-file=$VPP_API_DIR/core/teib.api.json //go:generate binapigen --input-file=$VPP_API_DIR/core/vpe.api.json //go:generate binapigen --input-file=$VPP_API_DIR/core/vxlan.api.json //go:generate binapigen --input-file=$VPP_API_DIR/core/vxlan_gpe.api.json diff --git a/plugins/vpp/ifplugin/descriptor/interface.go b/plugins/vpp/ifplugin/descriptor/interface.go index 8c37891afa..5a25b85739 100644 --- a/plugins/vpp/ifplugin/descriptor/interface.go +++ b/plugins/vpp/ifplugin/descriptor/interface.go @@ -578,11 +578,13 @@ func (d *InterfaceDescriptor) Validate(key string, intf *interfaces.Interface) e return kvs.NewInvalidValueError(ErrIpipSrcAddrBad, "link.ipip.src_addr") } - if intf.GetIpip().DstAddr == "" { - return kvs.NewInvalidValueError(ErrIpipDstAddrMissing, "link.ipip.dst_addr") - } - if net.ParseIP(intf.GetIpip().DstAddr) == nil { - return kvs.NewInvalidValueError(ErrIpipDstAddrBad, "link.ipip.dst_addr") + if intf.GetIpip().TunnelMode == interfaces.IPIPLink_POINT_TO_POINT { + if intf.GetIpip().DstAddr == "" { + return kvs.NewInvalidValueError(ErrIpipDstAddrMissing, "link.ipip.dst_addr") + } + if net.ParseIP(intf.GetIpip().DstAddr) == nil { + return kvs.NewInvalidValueError(ErrIpipDstAddrBad, "link.ipip.dst_addr") + } } } diff --git a/plugins/vpp/ifplugin/vppcalls/vpp2005/ipip_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/vpp2005/ipip_vppcalls.go index b9e0b212af..f7c25bfe7e 100644 --- a/plugins/vpp/ifplugin/vppcalls/vpp2005/ipip_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/vpp2005/ipip_vppcalls.go @@ -39,53 +39,65 @@ func (h *InterfaceVppHandler) AddIpipTunnel(ifName string, vrf uint32, ipipLink if ipipLink == nil { return 0, errors.New("missing IPIP tunnel information") } - srcAddr := net.ParseIP(ipipLink.SrcAddr) + var srcAddr, dstAddr net.IP + var isSrcIPv6, isDstIPv6 bool + + srcAddr = net.ParseIP(ipipLink.SrcAddr) if srcAddr == nil { err := errors.New("bad source address for IPIP tunnel") return 0, err } - dstAddr := net.ParseIP(ipipLink.DstAddr) - if dstAddr == nil { - err := errors.New("bad destination address for IPIP tunnel") - return 0, err - } - - var isSrcIPv6, isDstIPv6 bool if srcAddr.To4() == nil { isSrcIPv6 = true } - if dstAddr.To4() == nil { - isDstIPv6 = true + + if ipipLink.TunnelMode == interfaces.IPIPLink_POINT_TO_POINT { + dstAddr = net.ParseIP(ipipLink.DstAddr) + if dstAddr == nil { + err := errors.New("bad destination address for IPIP tunnel") + return 0, err + } + if dstAddr.To4() == nil { + isDstIPv6 = true + } } - if !isSrcIPv6 && !isDstIPv6 { + if !isSrcIPv6 && (dstAddr == nil || !isDstIPv6) { var src, dst [4]uint8 copy(src[:], srcAddr.To4()) - copy(dst[:], dstAddr.To4()) req.Tunnel.Src = ip_types.Address{ Af: ip_types.ADDRESS_IP4, Un: ip_types.AddressUnionIP4(src), } - req.Tunnel.Dst = ip_types.Address{ - Af: ip_types.ADDRESS_IP4, - Un: ip_types.AddressUnionIP4(dst), + if dstAddr != nil { + copy(dst[:], dstAddr.To4()) + req.Tunnel.Dst = ip_types.Address{ + Af: ip_types.ADDRESS_IP4, + Un: ip_types.AddressUnionIP4(dst), + } } - } else if isSrcIPv6 && isDstIPv6 { + } else if isSrcIPv6 && (dstAddr == nil || isDstIPv6) { var src, dst [16]uint8 copy(src[:], srcAddr.To16()) - copy(dst[:], dstAddr.To16()) req.Tunnel.Src = ip_types.Address{ Af: ip_types.ADDRESS_IP6, Un: ip_types.AddressUnionIP6(src), } - req.Tunnel.Dst = ip_types.Address{ - Af: ip_types.ADDRESS_IP6, - Un: ip_types.AddressUnionIP6(dst), + if dstAddr != nil { + copy(dst[:], dstAddr.To16()) + req.Tunnel.Dst = ip_types.Address{ + Af: ip_types.ADDRESS_IP6, + Un: ip_types.AddressUnionIP6(dst), + } } } else { return 0, errors.New("source and destination addresses must be both either IPv4 or IPv6") } + if ipipLink.TunnelMode == interfaces.IPIPLink_POINT_TO_MULTIPOINT { + req.Tunnel.Mode = ipip.TUNNEL_API_MODE_MP + } + reply := &ipip.IpipAddTunnelReply{} if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { @@ -131,13 +143,28 @@ func (h *InterfaceVppHandler) dumpIpipDetails(ifc map[uint32]*vppcalls.Interface if ipipDetails.Tunnel.Src.Af == ip_types.ADDRESS_IP6 { srcAddrArr := ipipDetails.Tunnel.Src.Un.GetIP6() ipipLink.SrcAddr = net.IP(srcAddrArr[:]).To16().String() - dstAddrArr := ipipDetails.Tunnel.Dst.Un.GetIP6() - ipipLink.DstAddr = net.IP(dstAddrArr[:]).To16().String() + if ipipDetails.Tunnel.Mode == ipip.TUNNEL_API_MODE_P2P { + dstAddrArr := ipipDetails.Tunnel.Dst.Un.GetIP6() + ipipLink.DstAddr = net.IP(dstAddrArr[:]).To16().String() + } } else { srcAddrArr := ipipDetails.Tunnel.Src.Un.GetIP4() ipipLink.SrcAddr = net.IP(srcAddrArr[:4]).To4().String() - dstAddrArr := ipipDetails.Tunnel.Dst.Un.GetIP4() - ipipLink.DstAddr = net.IP(dstAddrArr[:4]).To4().String() + if ipipDetails.Tunnel.Mode == ipip.TUNNEL_API_MODE_P2P { + dstAddrArr := ipipDetails.Tunnel.Dst.Un.GetIP4() + ipipLink.DstAddr = net.IP(dstAddrArr[:4]).To4().String() + } + } + + if ipipDetails.Tunnel.Mode == ipip.TUNNEL_API_MODE_MP { + ipipLink.TunnelMode = interfaces.IPIPLink_POINT_TO_MULTIPOINT + } + + // TODO: temporary fix since VPP does not dump the tunnel mode properly. + // If dst address is empty, this must be a multipoint tunnel. + if ipipLink.DstAddr == "0.0.0.0" { + ipipLink.TunnelMode = interfaces.IPIPLink_POINT_TO_MULTIPOINT + ipipLink.DstAddr = "" } ifc[uint32(ipipDetails.Tunnel.SwIfIndex)].Interface.Link = &interfaces.Interface_Ipip{Ipip: ipipLink} diff --git a/plugins/vpp/ipsecplugin/vppcalls/vpp2005/dump_vppcalls.go b/plugins/vpp/ipsecplugin/vppcalls/vpp2005/dump_vppcalls.go index c461881ed0..62383e20c9 100644 --- a/plugins/vpp/ipsecplugin/vppcalls/vpp2005/dump_vppcalls.go +++ b/plugins/vpp/ipsecplugin/vppcalls/vpp2005/dump_vppcalls.go @@ -195,6 +195,20 @@ func (h *IPSecVppHandler) DumpTunnelProtections() (tpList []*ipsec.TunnelProtect } tp.SaIn = append(tp.SaIn, tpDetails.Tun.SaIn...) tpList = append(tpList, tp) + + if tpDetails.Tun.Nh.Af == ip_types.ADDRESS_IP6 { + nhAddrArr := tpDetails.Tun.Nh.Un.GetIP6() + nhAddr := net.IP(nhAddrArr[:]).To16() + if !nhAddr.IsUnspecified() { + tp.NextHopAddr = nhAddr.String() + } + } else { + nhAddrArr := tpDetails.Tun.Nh.Un.GetIP4() + nhAddr := net.IP(nhAddrArr[:4]).To4() + if !nhAddr.IsUnspecified() { + tp.NextHopAddr = nhAddr.String() + } + } } return } diff --git a/plugins/vpp/ipsecplugin/vppcalls/vpp2005/ipsec_vppcalls.go b/plugins/vpp/ipsecplugin/vppcalls/vpp2005/ipsec_vppcalls.go index 407a805531..526bf1b9d4 100644 --- a/plugins/vpp/ipsecplugin/vppcalls/vpp2005/ipsec_vppcalls.go +++ b/plugins/vpp/ipsecplugin/vppcalls/vpp2005/ipsec_vppcalls.go @@ -292,6 +292,13 @@ func (h *IPSecVppHandler) tunProtectAddUpdateEntry(tp *ipsec.TunnelProtection, s SaIn: tp.SaIn, NSaIn: uint8(len(tp.SaIn)), }} + if tp.NextHopAddr != "" { + nh, err := IPToAddress(tp.NextHopAddr) + if err != nil { + return err + } + req.Tunnel.Nh = nh + } reply := &vpp_ipsec.IpsecTunnelProtectUpdateReply{} if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err @@ -303,6 +310,13 @@ func (h *IPSecVppHandler) tunProtectDelEntry(tp *ipsec.TunnelProtection, swIfInd req := &vpp_ipsec.IpsecTunnelProtectDel{ SwIfIndex: vpp_ipsec.InterfaceIndex(swIfIndex), } + if tp.NextHopAddr != "" { + nh, err := IPToAddress(tp.NextHopAddr) + if err != nil { + return err + } + req.Nh = nh + } reply := &vpp_ipsec.IpsecTunnelProtectDelReply{} if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err diff --git a/plugins/vpp/l3plugin/descriptor/adapter/teibentry.go b/plugins/vpp/l3plugin/descriptor/adapter/teibentry.go new file mode 100644 index 0000000000..95b49b8c9c --- /dev/null +++ b/plugins/vpp/l3plugin/descriptor/adapter/teibentry.go @@ -0,0 +1,233 @@ +// Code generated by adapter-generator. DO NOT EDIT. + +package adapter + +import ( + "github.com/golang/protobuf/proto" + . "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api" + "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3" +) + +////////// type-safe key-value pair with metadata ////////// + +type TeibEntryKVWithMetadata struct { + Key string + Value *vpp_l3.TeibEntry + Metadata interface{} + Origin ValueOrigin +} + +////////// type-safe Descriptor structure ////////// + +type TeibEntryDescriptor struct { + Name string + KeySelector KeySelector + ValueTypeName string + KeyLabel func(key string) string + ValueComparator func(key string, oldValue, newValue *vpp_l3.TeibEntry) bool + NBKeyPrefix string + WithMetadata bool + MetadataMapFactory MetadataMapFactory + Validate func(key string, value *vpp_l3.TeibEntry) error + Create func(key string, value *vpp_l3.TeibEntry) (metadata interface{}, err error) + Delete func(key string, value *vpp_l3.TeibEntry, metadata interface{}) error + Update func(key string, oldValue, newValue *vpp_l3.TeibEntry, oldMetadata interface{}) (newMetadata interface{}, err error) + UpdateWithRecreate func(key string, oldValue, newValue *vpp_l3.TeibEntry, metadata interface{}) bool + Retrieve func(correlate []TeibEntryKVWithMetadata) ([]TeibEntryKVWithMetadata, error) + IsRetriableFailure func(err error) bool + DerivedValues func(key string, value *vpp_l3.TeibEntry) []KeyValuePair + Dependencies func(key string, value *vpp_l3.TeibEntry) []Dependency + RetrieveDependencies []string /* descriptor name */ +} + +////////// Descriptor adapter ////////// + +type TeibEntryDescriptorAdapter struct { + descriptor *TeibEntryDescriptor +} + +func NewTeibEntryDescriptor(typedDescriptor *TeibEntryDescriptor) *KVDescriptor { + adapter := &TeibEntryDescriptorAdapter{descriptor: typedDescriptor} + descriptor := &KVDescriptor{ + Name: typedDescriptor.Name, + KeySelector: typedDescriptor.KeySelector, + ValueTypeName: typedDescriptor.ValueTypeName, + KeyLabel: typedDescriptor.KeyLabel, + NBKeyPrefix: typedDescriptor.NBKeyPrefix, + WithMetadata: typedDescriptor.WithMetadata, + MetadataMapFactory: typedDescriptor.MetadataMapFactory, + IsRetriableFailure: typedDescriptor.IsRetriableFailure, + RetrieveDependencies: typedDescriptor.RetrieveDependencies, + } + if typedDescriptor.ValueComparator != nil { + descriptor.ValueComparator = adapter.ValueComparator + } + if typedDescriptor.Validate != nil { + descriptor.Validate = adapter.Validate + } + if typedDescriptor.Create != nil { + descriptor.Create = adapter.Create + } + if typedDescriptor.Delete != nil { + descriptor.Delete = adapter.Delete + } + if typedDescriptor.Update != nil { + descriptor.Update = adapter.Update + } + if typedDescriptor.UpdateWithRecreate != nil { + descriptor.UpdateWithRecreate = adapter.UpdateWithRecreate + } + if typedDescriptor.Retrieve != nil { + descriptor.Retrieve = adapter.Retrieve + } + if typedDescriptor.Dependencies != nil { + descriptor.Dependencies = adapter.Dependencies + } + if typedDescriptor.DerivedValues != nil { + descriptor.DerivedValues = adapter.DerivedValues + } + return descriptor +} + +func (da *TeibEntryDescriptorAdapter) ValueComparator(key string, oldValue, newValue proto.Message) bool { + typedOldValue, err1 := castTeibEntryValue(key, oldValue) + typedNewValue, err2 := castTeibEntryValue(key, newValue) + if err1 != nil || err2 != nil { + return false + } + return da.descriptor.ValueComparator(key, typedOldValue, typedNewValue) +} + +func (da *TeibEntryDescriptorAdapter) Validate(key string, value proto.Message) (err error) { + typedValue, err := castTeibEntryValue(key, value) + if err != nil { + return err + } + return da.descriptor.Validate(key, typedValue) +} + +func (da *TeibEntryDescriptorAdapter) Create(key string, value proto.Message) (metadata Metadata, err error) { + typedValue, err := castTeibEntryValue(key, value) + if err != nil { + return nil, err + } + return da.descriptor.Create(key, typedValue) +} + +func (da *TeibEntryDescriptorAdapter) Update(key string, oldValue, newValue proto.Message, oldMetadata Metadata) (newMetadata Metadata, err error) { + oldTypedValue, err := castTeibEntryValue(key, oldValue) + if err != nil { + return nil, err + } + newTypedValue, err := castTeibEntryValue(key, newValue) + if err != nil { + return nil, err + } + typedOldMetadata, err := castTeibEntryMetadata(key, oldMetadata) + if err != nil { + return nil, err + } + return da.descriptor.Update(key, oldTypedValue, newTypedValue, typedOldMetadata) +} + +func (da *TeibEntryDescriptorAdapter) Delete(key string, value proto.Message, metadata Metadata) error { + typedValue, err := castTeibEntryValue(key, value) + if err != nil { + return err + } + typedMetadata, err := castTeibEntryMetadata(key, metadata) + if err != nil { + return err + } + return da.descriptor.Delete(key, typedValue, typedMetadata) +} + +func (da *TeibEntryDescriptorAdapter) UpdateWithRecreate(key string, oldValue, newValue proto.Message, metadata Metadata) bool { + oldTypedValue, err := castTeibEntryValue(key, oldValue) + if err != nil { + return true + } + newTypedValue, err := castTeibEntryValue(key, newValue) + if err != nil { + return true + } + typedMetadata, err := castTeibEntryMetadata(key, metadata) + if err != nil { + return true + } + return da.descriptor.UpdateWithRecreate(key, oldTypedValue, newTypedValue, typedMetadata) +} + +func (da *TeibEntryDescriptorAdapter) Retrieve(correlate []KVWithMetadata) ([]KVWithMetadata, error) { + var correlateWithType []TeibEntryKVWithMetadata + for _, kvpair := range correlate { + typedValue, err := castTeibEntryValue(kvpair.Key, kvpair.Value) + if err != nil { + continue + } + typedMetadata, err := castTeibEntryMetadata(kvpair.Key, kvpair.Metadata) + if err != nil { + continue + } + correlateWithType = append(correlateWithType, + TeibEntryKVWithMetadata{ + Key: kvpair.Key, + Value: typedValue, + Metadata: typedMetadata, + Origin: kvpair.Origin, + }) + } + + typedValues, err := da.descriptor.Retrieve(correlateWithType) + if err != nil { + return nil, err + } + var values []KVWithMetadata + for _, typedKVWithMetadata := range typedValues { + kvWithMetadata := KVWithMetadata{ + Key: typedKVWithMetadata.Key, + Metadata: typedKVWithMetadata.Metadata, + Origin: typedKVWithMetadata.Origin, + } + kvWithMetadata.Value = typedKVWithMetadata.Value + values = append(values, kvWithMetadata) + } + return values, err +} + +func (da *TeibEntryDescriptorAdapter) DerivedValues(key string, value proto.Message) []KeyValuePair { + typedValue, err := castTeibEntryValue(key, value) + if err != nil { + return nil + } + return da.descriptor.DerivedValues(key, typedValue) +} + +func (da *TeibEntryDescriptorAdapter) Dependencies(key string, value proto.Message) []Dependency { + typedValue, err := castTeibEntryValue(key, value) + if err != nil { + return nil + } + return da.descriptor.Dependencies(key, typedValue) +} + +////////// Helper methods ////////// + +func castTeibEntryValue(key string, value proto.Message) (*vpp_l3.TeibEntry, error) { + typedValue, ok := value.(*vpp_l3.TeibEntry) + if !ok { + return nil, ErrInvalidValueType(key, value) + } + return typedValue, nil +} + +func castTeibEntryMetadata(key string, metadata Metadata) (interface{}, error) { + if metadata == nil { + return nil, nil + } + typedMetadata, ok := metadata.(interface{}) + if !ok { + return nil, ErrInvalidMetadataType(key) + } + return typedMetadata, nil +} diff --git a/plugins/vpp/l3plugin/descriptor/teib_entry.go b/plugins/vpp/l3plugin/descriptor/teib_entry.go new file mode 100644 index 0000000000..aff24b4536 --- /dev/null +++ b/plugins/vpp/l3plugin/descriptor/teib_entry.go @@ -0,0 +1,139 @@ +// Copyright (c) 2020 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package descriptor + +import ( + "context" + "fmt" + + "go.ligato.io/cn-infra/v2/logging" + "go.ligato.io/cn-infra/v2/utils/addrs" + + "go.ligato.io/vpp-agent/v3/pkg/models" + kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api" + ifdescriptor "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/descriptor" + "go.ligato.io/vpp-agent/v3/plugins/vpp/l3plugin/descriptor/adapter" + "go.ligato.io/vpp-agent/v3/plugins/vpp/l3plugin/vppcalls" + interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces" + l3 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3" +) + +const ( + // TeibDescriptorName is the name of the descriptor. + TeibDescriptorName = "vpp-teib" + + // dependency labels + teibEntryInterfaceDep = "interface-exists" + teibEntryVrfTableDep = "vrf-table-exists" +) + +// TeibDescriptor instructs KVScheduler how to configure VPP TEIB entries. +type TeibDescriptor struct { + log logging.Logger + teibHandler vppcalls.TeibVppAPI + scheduler kvs.KVScheduler +} + +// NewTeibDescriptor creates a new instance of the TeibDescriptor. +func NewTeibDescriptor(scheduler kvs.KVScheduler, + teibHandler vppcalls.TeibVppAPI, log logging.PluginLogger) *kvs.KVDescriptor { + + ctx := &TeibDescriptor{ + scheduler: scheduler, + teibHandler: teibHandler, + log: log.NewLogger("teib-descriptor"), + } + + typedDescr := &adapter.TeibEntryDescriptor{ + Name: TeibDescriptorName, + NBKeyPrefix: l3.ModelTeib.KeyPrefix(), + ValueTypeName: l3.ModelTeib.ProtoName(), + KeySelector: l3.ModelTeib.IsKeyValid, + KeyLabel: l3.ModelTeib.StripKeyPrefix, + Validate: ctx.Validate, + Create: ctx.Create, + Delete: ctx.Delete, + Retrieve: ctx.Retrieve, + Dependencies: ctx.Dependencies, + RetrieveDependencies: []string{ifdescriptor.InterfaceDescriptorName}, + } + return adapter.NewTeibEntryDescriptor(typedDescr) +} + +// Validate validates VPP TEIB entry configuration. +func (d *TeibDescriptor) Validate(key string, entry *l3.TeibEntry) (err error) { + if entry.Interface == "" { + return kvs.NewInvalidValueError(fmt.Errorf("no interface defined"), "interface") + } + if entry.PeerAddr == "" { + return kvs.NewInvalidValueError(fmt.Errorf("no peer address defined"), "peer_addr") + } + if entry.NextHopAddr == "" { + return kvs.NewInvalidValueError(fmt.Errorf("no next hop address defined"), "next_hop_addr") + } + return nil +} + +// Create adds a VPP TEIB entry. +func (d *TeibDescriptor) Create(key string, entry *l3.TeibEntry) (interface{}, error) { + return nil, d.teibHandler.VppAddTeibEntry(context.Background(), entry) +} + +// Delete removes a VPP TEIB entry. +func (d *TeibDescriptor) Delete(key string, entry *l3.TeibEntry, metadata interface{}) error { + return d.teibHandler.VppDelTeibEntry(context.Background(), entry) +} + +// Retrieve returns all TEIB entries. +func (d *TeibDescriptor) Retrieve(correlate []adapter.TeibEntryKVWithMetadata) ( + retrieved []adapter.TeibEntryKVWithMetadata, err error, +) { + entries, err := d.teibHandler.DumpTeib() + if err != nil { + return nil, err + } + for _, entry := range entries { + retrieved = append(retrieved, adapter.TeibEntryKVWithMetadata{ + Key: models.Key(entry), + Value: entry, + Origin: kvs.UnknownOrigin, + }) + } + return +} + +// Dependencies lists dependencies for a VPP TEIB entry. +func (d *TeibDescriptor) Dependencies(key string, entry *l3.TeibEntry) (deps []kvs.Dependency) { + + // the referenced interface must exist + deps = append(deps, kvs.Dependency{ + Label: teibEntryInterfaceDep, + Key: interfaces.InterfaceKey(entry.Interface), + }) + + // non-zero VRF must exists + if entry.VrfId != 0 { + var protocol l3.VrfTable_Protocol + _, isIPv6, _ := addrs.ParseIPWithPrefix(entry.NextHopAddr) + if isIPv6 { + protocol = l3.VrfTable_IPV6 + } + deps = append(deps, kvs.Dependency{ + Label: teibEntryVrfTableDep, + Key: l3.VrfTableKey(entry.VrfId, protocol), + }) + } + return deps +} diff --git a/plugins/vpp/l3plugin/l3plugin.go b/plugins/vpp/l3plugin/l3plugin.go index f6c7d14785..3e42fb65fc 100644 --- a/plugins/vpp/l3plugin/l3plugin.go +++ b/plugins/vpp/l3plugin/l3plugin.go @@ -20,6 +20,7 @@ //go:generate descriptor-adapter --descriptor-name VrfTable --value-type *vpp_l3.VrfTable --meta-type *vrfidx.VRFMetadata --import "go.ligato.io/vpp-agent/v3/plugins/vpp/l3plugin/vrfidx" --import "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3" --output-dir "descriptor" //go:generate descriptor-adapter --descriptor-name DHCPProxy --value-type *vpp_l3.DHCPProxy --import "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3" --output-dir "descriptor" //go:generate descriptor-adapter --descriptor-name L3XC --value-type *vpp_l3.L3XConnect --import "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3" --output-dir "descriptor" +//go:generate descriptor-adapter --descriptor-name TeibEntry --value-type *vpp_l3.TeibEntry --import "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3" --output-dir "descriptor" package l3plugin @@ -100,6 +101,7 @@ func (p *L3Plugin) Init() (err error) { ipScanNeighborDescriptor := descriptor.NewIPScanNeighborDescriptor(p.KVScheduler, p.l3Handler, p.Log) dhcpProxyDescriptor := descriptor.NewDHCPProxyDescriptor(p.KVScheduler, p.l3Handler, p.Log) l3xcDescriptor := descriptor.NewL3XCDescriptor(p.l3Handler, p.IfPlugin.GetInterfaceIndex(), p.Log) + teibDescriptor := descriptor.NewTeibDescriptor(p.KVScheduler, p.l3Handler, p.Log) err = p.Deps.KVScheduler.RegisterKVDescriptor( routeDescriptor, @@ -109,6 +111,7 @@ func (p *L3Plugin) Init() (err error) { ipScanNeighborDescriptor, dhcpProxyDescriptor, l3xcDescriptor, + teibDescriptor, ) if err != nil { return err diff --git a/plugins/vpp/l3plugin/vppcalls/l3_vppcalls.go b/plugins/vpp/l3plugin/vppcalls/l3_vppcalls.go index 05828058e5..10b351c536 100644 --- a/plugins/vpp/l3plugin/vppcalls/l3_vppcalls.go +++ b/plugins/vpp/l3plugin/vppcalls/l3_vppcalls.go @@ -32,6 +32,9 @@ import ( var ( // ErrIPNeighborNotImplemented is used for IPScanNeighAPI handlers that are missing implementation. ErrIPNeighborNotImplemented = errors.New("ip neighbor config not implemented") + + // ErrTeibUnsupported error is returned if TEIB is not supported on given VPP version. + ErrTeibUnsupported = errors.New("TEIB is not supported") ) // L3VppAPI groups L3 Vpp APIs. @@ -43,6 +46,7 @@ type L3VppAPI interface { VrfTableVppAPI DHCPProxyAPI L3XCVppAPI + TeibVppAPI } // ArpDetails holds info about ARP entry as a proto model @@ -212,6 +216,22 @@ type IPNeighVppAPI interface { DefaultIPScanNeighbor() *l3.IPScanNeighbor } +// TeibVppAPI provides methods for managing VPP tunnel information base. +type TeibVppAPI interface { + TeibVppRead + + // VppAddTeibEntry adds a new TEIB entry. + VppAddTeibEntry(ctx context.Context, entry *l3.TeibEntry) error + // VppDelTeibEntry removes an existing TEIB entry. + VppDelTeibEntry(ctx context.Context, entry *l3.TeibEntry) error +} + +// TeibVppRead provides read methods VPP tunnel information base. +type TeibVppRead interface { + // DumpTeib dumps TEIB entries from VPP and fills them into the provided TEIB entry map. + DumpTeib() ([]*l3.TeibEntry, error) +} + // Path represents FIB path entry. type Path struct { SwIfIndex uint32 diff --git a/plugins/vpp/l3plugin/vppcalls/vpp1904/vppcalls_handlers.go b/plugins/vpp/l3plugin/vppcalls/vpp1904/vppcalls_handlers.go index 0b6f55ceb9..36386d9765 100644 --- a/plugins/vpp/l3plugin/vppcalls/vpp1904/vppcalls_handlers.go +++ b/plugins/vpp/l3plugin/vppcalls/vpp1904/vppcalls_handlers.go @@ -35,6 +35,7 @@ import ( "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/ifaceidx" "go.ligato.io/vpp-agent/v3/plugins/vpp/l3plugin/vppcalls" "go.ligato.io/vpp-agent/v3/plugins/vpp/l3plugin/vrfidx" + l3 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3" ) var ( @@ -58,6 +59,7 @@ type L3VppHandler struct { *VrfTableHandler *DHCPProxyHandler *L3XCHandlerUnsupported + *TeibHandlerUnsupported } func NewL3VppHandler( @@ -80,6 +82,7 @@ func NewL3VppHandler( VrfTableHandler: NewVrfTableVppHandler(ch, log), DHCPProxyHandler: NewDHCPProxyHandler(ch, log), L3XCHandlerUnsupported: &L3XCHandlerUnsupported{}, + TeibHandlerUnsupported: &TeibHandlerUnsupported{}, } } @@ -214,6 +217,20 @@ func (l L3XCHandlerUnsupported) DeleteL3XC(ctx context.Context, index uint32, ip return ErrUnsupported } +type TeibHandlerUnsupported struct{} + +func (h *TeibHandlerUnsupported) VppAddTeibEntry(ctx context.Context, entry *l3.TeibEntry) error { + return fmt.Errorf("%w in VPP %s", vppcalls.ErrTeibUnsupported, vpp1904.Version) +} + +func (h *TeibHandlerUnsupported) VppDelTeibEntry(ctx context.Context, entry *l3.TeibEntry) error { + return fmt.Errorf("%w in VPP %s", vppcalls.ErrTeibUnsupported, vpp1904.Version) +} + +func (h *TeibHandlerUnsupported) DumpTeib() ([]*l3.TeibEntry, error) { + return nil, fmt.Errorf("%w in VPP %s", vppcalls.ErrTeibUnsupported, vpp1904.Version) +} + func ipToAddress(ipstr string) (addr ip.Address, err error) { netIP := net.ParseIP(ipstr) if netIP == nil { diff --git a/plugins/vpp/l3plugin/vppcalls/vpp1908/vppcalls_handlers.go b/plugins/vpp/l3plugin/vppcalls/vpp1908/vppcalls_handlers.go index 3b5b90de1c..819dd933e0 100644 --- a/plugins/vpp/l3plugin/vppcalls/vpp1908/vppcalls_handlers.go +++ b/plugins/vpp/l3plugin/vppcalls/vpp1908/vppcalls_handlers.go @@ -15,6 +15,7 @@ package vpp1908 import ( + "context" "fmt" "net" @@ -34,6 +35,7 @@ import ( "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/ifaceidx" "go.ligato.io/vpp-agent/v3/plugins/vpp/l3plugin/vppcalls" "go.ligato.io/vpp-agent/v3/plugins/vpp/l3plugin/vrfidx" + l3 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3" ) func init() { @@ -53,6 +55,7 @@ type L3VppHandler struct { *VrfTableHandler *DHCPProxyHandler *L3XCHandler + *TeibHandlerUnsupported } func NewL3VppHandler( @@ -68,13 +71,14 @@ func NewL3VppHandler( return nil } return &L3VppHandler{ - ArpVppHandler: NewArpVppHandler(ch, ifIdx, log), - ProxyArpVppHandler: NewProxyArpVppHandler(ch, ifIdx, log), - RouteHandler: NewRouteVppHandler(ch, ifIdx, vrfIdx, addrAlloc, log), - IPNeighHandler: NewIPNeighVppHandler(ch, log), - VrfTableHandler: NewVrfTableVppHandler(ch, log), - DHCPProxyHandler: NewDHCPProxyHandler(ch, log), - L3XCHandler: NewL3XCHandler(c, ifIdx, log), + ArpVppHandler: NewArpVppHandler(ch, ifIdx, log), + ProxyArpVppHandler: NewProxyArpVppHandler(ch, ifIdx, log), + RouteHandler: NewRouteVppHandler(ch, ifIdx, vrfIdx, addrAlloc, log), + IPNeighHandler: NewIPNeighVppHandler(ch, log), + VrfTableHandler: NewVrfTableVppHandler(ch, log), + DHCPProxyHandler: NewDHCPProxyHandler(ch, log), + L3XCHandler: NewL3XCHandler(c, ifIdx, log), + TeibHandlerUnsupported: &TeibHandlerUnsupported{}, } } @@ -221,6 +225,20 @@ func NewL3XCHandler(c vpp.Client, ifIndexes ifaceidx.IfaceMetadataIndex, log log return h } +type TeibHandlerUnsupported struct{} + +func (h *TeibHandlerUnsupported) VppAddTeibEntry(ctx context.Context, entry *l3.TeibEntry) error { + return fmt.Errorf("%w in VPP %s", vppcalls.ErrTeibUnsupported, vpp1908.Version) +} + +func (h *TeibHandlerUnsupported) VppDelTeibEntry(ctx context.Context, entry *l3.TeibEntry) error { + return fmt.Errorf("%w in VPP %s", vppcalls.ErrTeibUnsupported, vpp1908.Version) +} + +func (h *TeibHandlerUnsupported) DumpTeib() ([]*l3.TeibEntry, error) { + return nil, fmt.Errorf("%w in VPP %s", vppcalls.ErrTeibUnsupported, vpp1908.Version) +} + func ipToAddress(ipstr string) (addr ip.Address, err error) { netIP := net.ParseIP(ipstr) if netIP == nil { diff --git a/plugins/vpp/l3plugin/vppcalls/vpp2001/vppcalls_handlers.go b/plugins/vpp/l3plugin/vppcalls/vpp2001/vppcalls_handlers.go index a5401ff83a..92866cbb35 100644 --- a/plugins/vpp/l3plugin/vppcalls/vpp2001/vppcalls_handlers.go +++ b/plugins/vpp/l3plugin/vppcalls/vpp2001/vppcalls_handlers.go @@ -15,6 +15,7 @@ package vpp2001 import ( + "context" "fmt" "net" @@ -36,6 +37,7 @@ import ( "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/ifaceidx" "go.ligato.io/vpp-agent/v3/plugins/vpp/l3plugin/vppcalls" "go.ligato.io/vpp-agent/v3/plugins/vpp/l3plugin/vrfidx" + l3 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3" ) func init() { @@ -56,6 +58,7 @@ type L3VppHandler struct { *VrfTableHandler *DHCPProxyHandler *L3XCHandler + *TeibHandlerUnsupported } func NewL3VppHandler( @@ -71,13 +74,14 @@ func NewL3VppHandler( return nil } return &L3VppHandler{ - ArpVppHandler: NewArpVppHandler(ch, ifIdx, log), - ProxyArpVppHandler: NewProxyArpVppHandler(ch, ifIdx, log), - RouteHandler: NewRouteVppHandler(ch, ifIdx, vrfIdx, addrAlloc, log), - IPNeighHandler: NewIPNeighVppHandler(ch, log), - VrfTableHandler: NewVrfTableVppHandler(ch, log), - DHCPProxyHandler: NewDHCPProxyHandler(ch, log), - L3XCHandler: NewL3XCHandler(c, ifIdx, log), + ArpVppHandler: NewArpVppHandler(ch, ifIdx, log), + ProxyArpVppHandler: NewProxyArpVppHandler(ch, ifIdx, log), + RouteHandler: NewRouteVppHandler(ch, ifIdx, vrfIdx, addrAlloc, log), + IPNeighHandler: NewIPNeighVppHandler(ch, log), + VrfTableHandler: NewVrfTableVppHandler(ch, log), + DHCPProxyHandler: NewDHCPProxyHandler(ch, log), + L3XCHandler: NewL3XCHandler(c, ifIdx, log), + TeibHandlerUnsupported: &TeibHandlerUnsupported{}, } } @@ -222,6 +226,20 @@ func NewL3XCHandler(c vpp.Client, ifIndexes ifaceidx.IfaceMetadataIndex, log log return h } +type TeibHandlerUnsupported struct{} + +func (h *TeibHandlerUnsupported) VppAddTeibEntry(ctx context.Context, entry *l3.TeibEntry) error { + return fmt.Errorf("%w in VPP %s", vppcalls.ErrTeibUnsupported, vpp2001.Version) +} + +func (h *TeibHandlerUnsupported) VppDelTeibEntry(ctx context.Context, entry *l3.TeibEntry) error { + return fmt.Errorf("%w in VPP %s", vppcalls.ErrTeibUnsupported, vpp2001.Version) +} + +func (h *TeibHandlerUnsupported) DumpTeib() ([]*l3.TeibEntry, error) { + return nil, fmt.Errorf("%w in VPP %s", vppcalls.ErrTeibUnsupported, vpp2001.Version) +} + func ipToAddress(ipstr string) (addr vpp_ip.Address, err error) { netIP := net.ParseIP(ipstr) if netIP == nil { diff --git a/plugins/vpp/l3plugin/vppcalls/vpp2005/teib_vppcalls.go b/plugins/vpp/l3plugin/vppcalls/vpp2005/teib_vppcalls.go new file mode 100644 index 0000000000..46c1f0a63f --- /dev/null +++ b/plugins/vpp/l3plugin/vppcalls/vpp2005/teib_vppcalls.go @@ -0,0 +1,89 @@ +package vpp2005 + +import ( + "context" + "fmt" + "net" + + "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2005/ip_types" + "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2005/teib" + l3 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3" +) + +// VppAddTeibEntry adds a new TEIB entry. +func (h *TeibHandler) VppAddTeibEntry(ctx context.Context, entry *l3.TeibEntry) error { + return h.vppAddDelTeibEntry(entry, false) +} + +// VppDelTeibEntry removes an existing TEIB entry. +func (h *TeibHandler) VppDelTeibEntry(ctx context.Context, entry *l3.TeibEntry) error { + return h.vppAddDelTeibEntry(entry, true) +} + +func (h *TeibHandler) vppAddDelTeibEntry(entry *l3.TeibEntry, delete bool) error { + peer, err := ipToAddress(entry.PeerAddr) + if err != nil { + return err + } + nh, err := ipToAddress(entry.NextHopAddr) + if err != nil { + return err + } + + meta, found := h.ifIndexes.LookupByName(entry.Interface) + if !found { + return fmt.Errorf("interface %s not found", entry.Interface) + } + + req := &teib.TeibEntryAddDel{ + Entry: teib.TeibEntry{ + SwIfIndex: teib.InterfaceIndex(meta.SwIfIndex), + Peer: peer, + Nh: nh, + NhTableID: entry.VrfId, + }, + } + if !delete { + req.IsAdd = 1 + } + + reply := &teib.TeibEntryAddDelReply{} + return h.callsChannel.SendRequest(req).ReceiveReply(reply) +} + +// DumpTeib dumps TEIB entries from VPP and fills them into the provided TEIB entry map. +func (h *TeibHandler) DumpTeib() (entries []*l3.TeibEntry, err error) { + reqCtx := h.callsChannel.SendMultiRequest(&teib.TeibDump{}) + for { + teibDetails := &teib.TeibDetails{} + stop, err := reqCtx.ReceiveReply(teibDetails) + if stop { + break + } + if err != nil { + return nil, err + } + entry := &l3.TeibEntry{ + PeerAddr: ipAddrToStr(teibDetails.Entry.Peer), + NextHopAddr: ipAddrToStr(teibDetails.Entry.Nh), + VrfId: teibDetails.Entry.NhTableID, + } + if ifName, _, exists := h.ifIndexes.LookupBySwIfIndex(uint32(teibDetails.Entry.SwIfIndex)); !exists { + h.log.Warnf("TEIB dump: interface name for index %d not found", teibDetails.Entry.SwIfIndex) + } else { + entry.Interface = ifName + } + entries = append(entries, entry) + } + return +} + +func ipAddrToStr(addr ip_types.Address) string { + if addr.Af == ip_types.ADDRESS_IP6 { + ip6Addr := addr.Un.GetIP6() + return net.IP(ip6Addr[:]).To16().String() + } else { + ip4Addr := addr.Un.GetIP4() + return net.IP(ip4Addr[:4]).To4().String() + } +} diff --git a/plugins/vpp/l3plugin/vppcalls/vpp2005/vppcalls_handlers.go b/plugins/vpp/l3plugin/vppcalls/vpp2005/vppcalls_handlers.go index 48d898f0a7..4ef39da92d 100644 --- a/plugins/vpp/l3plugin/vppcalls/vpp2005/vppcalls_handlers.go +++ b/plugins/vpp/l3plugin/vppcalls/vpp2005/vppcalls_handlers.go @@ -56,6 +56,7 @@ type L3VppHandler struct { *VrfTableHandler *DHCPProxyHandler *L3XCHandler + *TeibHandler } func NewL3VppHandler( @@ -78,6 +79,7 @@ func NewL3VppHandler( VrfTableHandler: NewVrfTableVppHandler(ch, log), DHCPProxyHandler: NewDHCPProxyHandler(ch, log), L3XCHandler: NewL3XCHandler(c, ifIdx, log), + TeibHandler: NewTeibVppHandler(ch, ifIdx, log), } } @@ -123,6 +125,13 @@ type VrfTableHandler struct { log logging.Logger } +// TeibHandler is accessor for TEIB-related vppcalls methods +type TeibHandler struct { + callsChannel govppapi.Channel + ifIndexes ifaceidx.IfaceMetadataIndex + log logging.Logger +} + // NewArpVppHandler creates new instance of IPsec vppcalls handler func NewArpVppHandler(callsChan govppapi.Channel, ifIndexes ifaceidx.IfaceMetadataIndex, log logging.Logger) *ArpVppHandler { if log == nil { @@ -196,6 +205,18 @@ func NewDHCPProxyHandler(callsChan govppapi.Channel, log logging.Logger) *DHCPPr } } +// NewTeibVppHandler creates new instance of TEIB vppcalls handler +func NewTeibVppHandler(callsChan govppapi.Channel, ifIndexes ifaceidx.IfaceMetadataIndex, log logging.Logger) *TeibHandler { + if log == nil { + log = logrus.NewLogger("teib-handler") + } + return &TeibHandler{ + callsChannel: callsChan, + ifIndexes: ifIndexes, + log: log, + } +} + type L3XCHandler struct { l3xc l3xc.RPCService ifIndexes ifaceidx.IfaceMetadataIndex diff --git a/proto/ligato/vpp/interfaces/interface.pb.go b/proto/ligato/vpp/interfaces/interface.pb.go index aff38ac386..7bd297f6d6 100644 --- a/proto/ligato/vpp/interfaces/interface.pb.go +++ b/proto/ligato/vpp/interfaces/interface.pb.go @@ -377,14 +377,18 @@ type IPIPLink_Mode int32 const ( // point-to-point tunnel IPIPLink_POINT_TO_POINT IPIPLink_Mode = 0 + // point-to multipoint tunnel (supported starting from VPP 20.05) + IPIPLink_POINT_TO_MULTIPOINT IPIPLink_Mode = 1 ) var IPIPLink_Mode_name = map[int32]string{ 0: "POINT_TO_POINT", + 1: "POINT_TO_MULTIPOINT", } var IPIPLink_Mode_value = map[string]int32{ - "POINT_TO_POINT": 0, + "POINT_TO_POINT": 0, + "POINT_TO_MULTIPOINT": 1, } func (x IPIPLink_Mode) String() string { @@ -1916,149 +1920,150 @@ func init() { } var fileDescriptor_8b053108eedee97b = []byte{ - // 2302 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x58, 0xdd, 0x72, 0xdb, 0xc6, - 0x15, 0x16, 0x48, 0x4a, 0x04, 0x0f, 0x7f, 0x04, 0xef, 0x24, 0x19, 0x44, 0x89, 0x1b, 0x95, 0x71, - 0x1a, 0x4d, 0x9a, 0xc8, 0x15, 0xd5, 0xfc, 0xb4, 0xe9, 0x34, 0x01, 0x45, 0x48, 0x66, 0x4c, 0x83, - 0x08, 0x08, 0x3a, 0x71, 0x27, 0x1d, 0x0c, 0x44, 0x2c, 0x29, 0x54, 0x20, 0x00, 0x03, 0x4b, 0x99, - 0xca, 0x4b, 0xb4, 0xef, 0xd0, 0x57, 0xe8, 0x7b, 0x74, 0xf2, 0x06, 0x7d, 0x80, 0x5e, 0x77, 0xda, - 0x5e, 0x75, 0xce, 0xee, 0x82, 0xa2, 0x12, 0x4b, 0xf2, 0xf4, 0x46, 0xda, 0xfd, 0xf6, 0x7c, 0xbb, - 0x07, 0x67, 0xcf, 0xdf, 0x12, 0xde, 0x8b, 0xc2, 0x99, 0xcf, 0x92, 0x87, 0x17, 0x69, 0xfa, 0x30, - 0x8c, 0x19, 0xcd, 0xa6, 0xfe, 0x84, 0xe6, 0x57, 0xc3, 0xfd, 0x34, 0x4b, 0x58, 0x42, 0x5e, 0x17, - 0x62, 0xfb, 0x17, 0x69, 0xba, 0x7f, 0x25, 0xb6, 0xf3, 0xf6, 0x3a, 0x3b, 0xcd, 0xe9, 0x44, 0xfc, - 0x15, 0xa4, 0xf6, 0x0f, 0x4d, 0xa8, 0xf5, 0x0b, 0x61, 0x42, 0xa0, 0x12, 0xfb, 0x73, 0xaa, 0x2b, - 0xbb, 0xca, 0x5e, 0xcd, 0xe1, 0x63, 0xf2, 0x1b, 0xa8, 0xb0, 0xcb, 0x94, 0xea, 0xa5, 0x5d, 0x65, - 0xaf, 0xd5, 0x79, 0x6f, 0xff, 0xa5, 0xa7, 0xec, 0xaf, 0xf6, 0xd8, 0x77, 0x2f, 0x53, 0xea, 0x70, - 0x0a, 0xd1, 0xa1, 0x4a, 0x63, 0xff, 0x34, 0xa2, 0x81, 0x5e, 0xde, 0x55, 0xf6, 0x54, 0xa7, 0x98, - 0x92, 0x9f, 0x43, 0x23, 0x3d, 0xbb, 0xcc, 0x3d, 0x3f, 0x08, 0x32, 0x9a, 0xe7, 0x7a, 0x85, 0x1f, - 0x58, 0x47, 0xcc, 0x10, 0x10, 0x8a, 0x84, 0x69, 0x21, 0x40, 0x73, 0x7d, 0x73, 0xb7, 0x8c, 0x22, - 0x61, 0x6a, 0x14, 0x10, 0xd1, 0xa0, 0x7c, 0x91, 0x4d, 0xf5, 0xad, 0x5d, 0x65, 0xaf, 0xe9, 0xe0, - 0x90, 0xfc, 0x02, 0xb6, 0x73, 0xca, 0xbc, 0xe0, 0x6c, 0x92, 0x7a, 0x93, 0x28, 0xa4, 0x31, 0xd3, - 0xab, 0xfc, 0xe4, 0x66, 0x4e, 0x59, 0xef, 0x6c, 0x92, 0x1e, 0x71, 0x10, 0x99, 0x73, 0xb6, 0xd0, - 0x55, 0xc1, 0x9c, 0xb3, 0x05, 0x79, 0x0c, 0xb0, 0x88, 0xe3, 0xc5, 0xfc, 0x94, 0x66, 0x34, 0xd0, - 0x6b, 0xbb, 0xca, 0x5e, 0xbd, 0xf3, 0xcb, 0x3b, 0x3f, 0x76, 0xbc, 0xa2, 0x38, 0x6b, 0x74, 0xd2, - 0x05, 0x35, 0x5b, 0x7a, 0xf3, 0x24, 0xa0, 0xb9, 0xde, 0xd8, 0x2d, 0xef, 0xd5, 0x3b, 0xef, 0xdf, - 0xb9, 0x95, 0xb3, 0x7c, 0x92, 0x04, 0xd4, 0xa9, 0x66, 0xfc, 0x7f, 0x4e, 0xbe, 0x86, 0x66, 0xb6, - 0xf4, 0xd2, 0xc8, 0x9f, 0xd0, 0x39, 0x8d, 0x59, 0xae, 0x37, 0xf9, 0x46, 0x1f, 0xbe, 0xc2, 0x46, - 0x76, 0x41, 0x72, 0x1a, 0xd9, 0xd5, 0x24, 0x27, 0x9f, 0x42, 0x39, 0x5f, 0x9c, 0xea, 0x01, 0xff, - 0xb8, 0x77, 0x6f, 0xd8, 0x68, 0xb4, 0x38, 0x5d, 0xed, 0xf5, 0x68, 0xc3, 0x41, 0x06, 0xf9, 0x0c, - 0x36, 0xe7, 0x74, 0x1e, 0x4e, 0x75, 0xca, 0xa9, 0xbb, 0x37, 0x50, 0x9f, 0xa0, 0xcc, 0x20, 0x8c, - 0xcf, 0x1f, 0x6d, 0x38, 0x82, 0x40, 0x0c, 0x50, 0xfd, 0x69, 0xea, 0x4f, 0xce, 0x29, 0xd3, 0xa7, - 0xb7, 0x9e, 0x6b, 0x48, 0x31, 0xc9, 0x5f, 0xd1, 0x48, 0x07, 0xca, 0xcc, 0x4f, 0xf5, 0x19, 0x67, - 0xff, 0xec, 0x06, 0xb6, 0xeb, 0xa7, 0x92, 0x88, 0xc2, 0xa8, 0xf0, 0xc5, 0x32, 0xf2, 0x63, 0xfd, - 0xec, 0x56, 0x85, 0x9f, 0xa2, 0x4c, 0xa1, 0x30, 0x27, 0x90, 0xdf, 0xc1, 0x26, 0x8f, 0x0f, 0x3d, - 0xbc, 0x95, 0xd9, 0xb7, 0x47, 0x74, 0x82, 0xcc, 0x6e, 0x49, 0x57, 0x90, 0xcd, 0x49, 0xe4, 0x0b, - 0x50, 0x2f, 0xe6, 0x4b, 0x2f, 0xa6, 0xec, 0x50, 0xff, 0x13, 0xdf, 0xa0, 0x7d, 0xd3, 0xd1, 0xf3, - 0xa5, 0x45, 0xd9, 0xa1, 0x3c, 0xbc, 0x7a, 0x21, 0xa6, 0xe4, 0x63, 0xa8, 0x9c, 0x26, 0x71, 0xa0, - 0x9f, 0x73, 0xf2, 0x3b, 0x37, 0x90, 0xbb, 0x49, 0x1c, 0x48, 0x26, 0x17, 0x47, 0x1b, 0xcd, 0x32, - 0xaa, 0x47, 0xb7, 0xda, 0xe8, 0x24, 0xa3, 0x85, 0x8d, 0x66, 0x19, 0xc5, 0xa3, 0x66, 0x2c, 0x5d, - 0xe8, 0xf3, 0x5b, 0x8f, 0x3a, 0x61, 0xe9, 0xa2, 0x38, 0x0a, 0xc5, 0x91, 0x16, 0xa6, 0x61, 0xaa, - 0xc7, 0xb7, 0xd2, 0xfa, 0x76, 0xdf, 0x2e, 0x68, 0x28, 0xbe, 0xf3, 0x19, 0xc0, 0x55, 0xb0, 0x90, - 0x0f, 0xe0, 0xde, 0x4a, 0xd8, 0x7b, 0x11, 0xb2, 0x33, 0x2f, 0x4c, 0x65, 0xd6, 0xd9, 0x5e, 0x2d, - 0x7c, 0x13, 0xb2, 0xb3, 0x7e, 0xba, 0xf3, 0x77, 0x05, 0xb6, 0x44, 0x70, 0x90, 0xd7, 0x60, 0xf3, - 0xf9, 0x82, 0x2e, 0x44, 0x82, 0x6a, 0x3a, 0x62, 0x42, 0xbe, 0x84, 0x0a, 0x86, 0x9a, 0xcc, 0x50, - 0x1f, 0xbe, 0x62, 0xa4, 0xc9, 0x44, 0x85, 0x4c, 0xcc, 0x35, 0x01, 0x9d, 0xfa, 0x8b, 0x88, 0xf1, - 0xa0, 0x95, 0xd9, 0xaa, 0x2e, 0x31, 0x94, 0x6e, 0x7f, 0x05, 0x15, 0x24, 0x90, 0x3a, 0x54, 0xc7, - 0xd6, 0x63, 0x6b, 0xf8, 0x8d, 0xa5, 0x6d, 0xe0, 0xc4, 0x1e, 0x0e, 0x06, 0x7d, 0xeb, 0x44, 0x53, - 0x08, 0x66, 0x52, 0xcb, 0x35, 0x1d, 0x67, 0x6c, 0xbb, 0x5a, 0x89, 0x34, 0x40, 0x35, 0x7a, 0x86, - 0xed, 0xf6, 0x9f, 0x9a, 0x5a, 0x19, 0x25, 0x7b, 0xe6, 0xb1, 0x31, 0x1e, 0xb8, 0x5a, 0x65, 0xe7, - 0x3b, 0xa8, 0xaf, 0x05, 0xe9, 0x0d, 0x5f, 0xf5, 0x06, 0x6c, 0xbd, 0x48, 0xb2, 0x73, 0x9a, 0xf1, - 0xef, 0x6a, 0x3a, 0x72, 0x46, 0xde, 0x81, 0xfa, 0xdc, 0x0f, 0x63, 0x8f, 0x9d, 0x65, 0xd4, 0x2f, - 0x12, 0x2b, 0x20, 0xe4, 0x72, 0xa4, 0xfd, 0x2f, 0x45, 0xaa, 0x4a, 0xa0, 0x35, 0xb6, 0x7a, 0xe6, - 0x71, 0xdf, 0x32, 0x7b, 0x9e, 0xfb, 0xcc, 0x36, 0xb5, 0x0d, 0x72, 0x0f, 0x9a, 0xa3, 0x71, 0xd7, - 0xe3, 0x8a, 0x1e, 0x1b, 0x47, 0xa6, 0xa6, 0x90, 0xd7, 0xe1, 0xde, 0x68, 0x78, 0xec, 0x7e, 0x63, - 0x38, 0xa6, 0x37, 0x18, 0x0e, 0xed, 0xae, 0x71, 0xf4, 0x58, 0x2b, 0x11, 0x15, 0x2a, 0x3d, 0xbb, - 0xf7, 0x58, 0x2b, 0x93, 0x1a, 0x6c, 0x3e, 0x31, 0x9f, 0xf4, 0x8f, 0xb5, 0x0a, 0xa9, 0x42, 0xd9, - 0x35, 0x6c, 0x6d, 0x13, 0x3f, 0xd6, 0x38, 0xf6, 0x6c, 0xe3, 0xe8, 0xb1, 0xe9, 0x6a, 0x5b, 0x44, - 0x83, 0xc6, 0xd3, 0x6f, 0x07, 0x86, 0xe5, 0xb9, 0x63, 0xcb, 0x32, 0x07, 0x5a, 0x95, 0xbc, 0x06, - 0x8d, 0xbe, 0x3d, 0x32, 0x8f, 0x0a, 0x44, 0xdd, 0x29, 0xa9, 0xfc, 0xac, 0xa7, 0x4f, 0xbe, 0xb5, - 0x4c, 0xf7, 0x70, 0x4d, 0x85, 0x1a, 0x6a, 0xda, 0x1d, 0x5a, 0xbd, 0x35, 0x0c, 0x48, 0x0b, 0xe0, - 0xc4, 0x31, 0x0b, 0x7a, 0x9d, 0x6c, 0x43, 0xfd, 0xc4, 0xb5, 0xc7, 0x05, 0xd0, 0x40, 0x00, 0xbd, - 0xac, 0x00, 0x9a, 0xdd, 0x2d, 0xa8, 0x44, 0x61, 0x7c, 0xde, 0xfe, 0x6f, 0x09, 0x1a, 0xeb, 0x59, - 0x0c, 0x4d, 0x96, 0xfa, 0x19, 0x8d, 0x99, 0xb7, 0x56, 0xdd, 0x40, 0x40, 0x16, 0xd6, 0xb8, 0xd7, - 0x61, 0x2b, 0x5f, 0x9c, 0x7a, 0x61, 0x20, 0x6d, 0xbd, 0x99, 0x2f, 0x4e, 0xfb, 0x01, 0x79, 0x06, - 0x4d, 0xe6, 0xcf, 0xbc, 0xec, 0x85, 0x97, 0xa4, 0x2c, 0x4c, 0x62, 0x6e, 0xec, 0x56, 0xe7, 0xe3, - 0x57, 0xc8, 0x9c, 0xfb, 0xae, 0x3f, 0x73, 0xe8, 0x8b, 0x2c, 0x64, 0x74, 0xc8, 0xb9, 0xb9, 0x53, - 0x67, 0xfe, 0xcc, 0x79, 0x21, 0x66, 0xe4, 0x3e, 0x40, 0xba, 0xc8, 0xcf, 0xbc, 0x20, 0x61, 0x07, - 0xcf, 0x79, 0xf9, 0x53, 0x9d, 0x1a, 0x22, 0x3d, 0x04, 0xb0, 0x10, 0x33, 0x7f, 0x76, 0xa0, 0x6f, - 0x72, 0x75, 0xf8, 0x58, 0x62, 0x1d, 0x59, 0xee, 0xf8, 0xb8, 0xfd, 0x67, 0x05, 0xee, 0xfd, 0xe4, - 0x24, 0x74, 0xbd, 0x5e, 0x7f, 0x64, 0x74, 0x07, 0x66, 0x4f, 0xdb, 0xc0, 0xeb, 0xb3, 0xc7, 0xa3, - 0x47, 0x07, 0x9a, 0x52, 0x0c, 0x3b, 0xe2, 0x7a, 0xed, 0xa1, 0x7d, 0xa0, 0x95, 0xe5, 0xa8, 0xa3, - 0x55, 0xd0, 0xa2, 0xae, 0x63, 0x58, 0xa3, 0x81, 0xe1, 0x9a, 0x07, 0x07, 0xda, 0xe6, 0x75, 0xa0, - 0xa3, 0x6d, 0x5d, 0x03, 0x3a, 0x07, 0x5a, 0xf5, 0x3a, 0xd0, 0xd1, 0xd4, 0xf6, 0x3f, 0x4a, 0x50, - 0x5b, 0xd5, 0x01, 0xf2, 0x7b, 0x19, 0x9a, 0x0a, 0x37, 0xdc, 0x07, 0x77, 0xd5, 0x0d, 0x31, 0xe2, - 0x75, 0x50, 0x04, 0xe6, 0x1b, 0xb0, 0x35, 0xf7, 0x73, 0x26, 0x83, 0x40, 0x75, 0xe4, 0x8c, 0xb4, - 0xa0, 0x14, 0x0a, 0xdf, 0x6f, 0x3a, 0xa5, 0x30, 0x20, 0xef, 0xc3, 0x76, 0x9e, 0x60, 0xb5, 0xf0, - 0xa6, 0x61, 0x44, 0xf9, 0x2d, 0x8b, 0x96, 0xa2, 0x25, 0xe0, 0x63, 0x89, 0xe2, 0x86, 0x39, 0x9d, - 0x64, 0x94, 0x71, 0xd3, 0xd6, 0x1c, 0x39, 0x23, 0x6f, 0x41, 0x2d, 0x0b, 0xe3, 0x99, 0x97, 0x87, - 0xdf, 0x53, 0x69, 0x61, 0x15, 0x81, 0x51, 0xf8, 0x3d, 0xf7, 0x9f, 0xd3, 0xc5, 0x74, 0x4a, 0x33, - 0xb1, 0x5c, 0xe5, 0xcb, 0x20, 0x20, 0x2e, 0x80, 0xec, 0xa5, 0xc7, 0xe3, 0x36, 0x97, 0x4d, 0x85, - 0x9a, 0x2d, 0xbf, 0xe6, 0x73, 0x5c, 0x64, 0xab, 0xc5, 0x9a, 0x58, 0x64, 0x72, 0xb1, 0xdd, 0x91, - 0xd6, 0xe2, 0xe9, 0xad, 0x01, 0xaa, 0xe9, 0x3e, 0x32, 0x1d, 0xcb, 0x74, 0xb5, 0x0d, 0xb2, 0x05, - 0xa5, 0xbe, 0xad, 0x29, 0x68, 0x62, 0x7b, 0x6c, 0xb9, 0x5e, 0xdf, 0xfa, 0xca, 0x3c, 0x72, 0xb5, - 0x52, 0xfb, 0x9f, 0x25, 0xa8, 0xad, 0x2a, 0x17, 0x2a, 0x97, 0x67, 0x93, 0x55, 0x27, 0x25, 0x9d, - 0x3b, 0xcf, 0x26, 0x45, 0x23, 0xf5, 0x0e, 0xd4, 0x83, 0x9c, 0xad, 0x04, 0x4a, 0x42, 0x20, 0xc8, - 0x59, 0x21, 0x80, 0x6d, 0x54, 0x1c, 0x4a, 0x6b, 0xe2, 0x90, 0xbc, 0x0d, 0xb5, 0xf9, 0x22, 0x62, - 0xe1, 0xc4, 0xcf, 0x99, 0x34, 0xe4, 0x15, 0x40, 0x3e, 0x81, 0xf2, 0x2c, 0xa5, 0xdc, 0x80, 0xf5, - 0xce, 0x83, 0xbb, 0x4a, 0xeb, 0xfe, 0x49, 0x4a, 0x1d, 0x24, 0xec, 0xfc, 0x4d, 0x81, 0xf2, 0x49, - 0x4a, 0xc9, 0x2e, 0x66, 0xdb, 0x89, 0x9f, 0x7a, 0x17, 0xd9, 0x14, 0x63, 0x4e, 0xa4, 0x3d, 0xe0, - 0xd8, 0xd3, 0x6c, 0xda, 0x0f, 0x48, 0x1f, 0x54, 0xde, 0x9e, 0x4e, 0x92, 0x48, 0x66, 0xf5, 0x8f, - 0x5e, 0xe5, 0x98, 0x7d, 0x5b, 0x92, 0x9c, 0x15, 0xbd, 0xfd, 0x25, 0xa8, 0x05, 0x7a, 0x3d, 0x77, - 0x57, 0xa1, 0xdc, 0xb7, 0x7f, 0xad, 0x29, 0x62, 0xf0, 0x89, 0xc8, 0xd8, 0x2b, 0xf3, 0x97, 0x11, - 0xb6, 0x46, 0x8f, 0xb4, 0x4a, 0xfb, 0x8f, 0xd0, 0x58, 0xef, 0x4d, 0xc8, 0x03, 0x68, 0x9c, 0x25, - 0x39, 0xf3, 0xc2, 0xe9, 0x5a, 0x3a, 0xc1, 0x36, 0xc0, 0x01, 0xc4, 0xfb, 0x53, 0x9e, 0x52, 0xde, - 0x87, 0xed, 0x28, 0x8c, 0x17, 0x4b, 0x6f, 0xa5, 0xac, 0xb4, 0x7c, 0x8b, 0xc3, 0xab, 0x44, 0xd1, - 0xfe, 0x41, 0x81, 0xaa, 0xec, 0x5e, 0xb0, 0x61, 0xbe, 0xa0, 0x59, 0x8e, 0xa9, 0x46, 0x18, 0xa5, - 0x98, 0xa2, 0xcd, 0xae, 0x1d, 0x2a, 0x6f, 0xf1, 0xfa, 0x81, 0x2c, 0xf1, 0xe6, 0xe1, 0x24, 0x4b, - 0x72, 0x9a, 0x5d, 0x84, 0x13, 0x51, 0xc6, 0x6a, 0x4e, 0x8b, 0x25, 0x4f, 0xd6, 0x50, 0xdc, 0x2a, - 0x5b, 0x7a, 0x57, 0xde, 0x5e, 0x11, 0xe6, 0xcf, 0x96, 0x4e, 0xe1, 0xef, 0xbb, 0xd0, 0x60, 0xeb, - 0x12, 0x22, 0x0b, 0x01, 0xbb, 0x92, 0xb8, 0x0f, 0x20, 0x5a, 0x79, 0x6f, 0x96, 0x27, 0x3c, 0x5e, - 0x54, 0xa7, 0x26, 0x90, 0x93, 0x3c, 0x69, 0xff, 0xa7, 0x0c, 0xb5, 0x55, 0x87, 0x84, 0xfe, 0x45, - 0xf3, 0x58, 0x46, 0x30, 0x0e, 0xd1, 0x25, 0xfd, 0x98, 0x85, 0x5e, 0x46, 0xd3, 0xc8, 0xbf, 0x2c, - 0x6a, 0x18, 0x42, 0x0e, 0x47, 0xc8, 0x9b, 0xa0, 0x46, 0xc9, 0xc4, 0x8f, 0xb0, 0x2d, 0x10, 0xfe, - 0x57, 0xe5, 0xf3, 0x7e, 0xca, 0x63, 0x8d, 0xce, 0x13, 0x46, 0x71, 0x4d, 0x04, 0xb1, 0x2a, 0x00, - 0xb1, 0x28, 0x78, 0x79, 0x1a, 0x16, 0x61, 0xcc, 0x81, 0x51, 0x1a, 0xa2, 0xd2, 0x92, 0x89, 0xab, - 0x22, 0x8a, 0xe5, 0x5e, 0xb8, 0xfc, 0x5b, 0x80, 0x49, 0x76, 0x99, 0xb2, 0xc4, 0xf3, 0xa3, 0x19, - 0x8f, 0xe2, 0x56, 0xe7, 0xad, 0x6b, 0x6e, 0xc7, 0xdf, 0x4d, 0x47, 0x5c, 0xc6, 0x88, 0x66, 0x4e, - 0x6d, 0x52, 0x0c, 0xc9, 0x1e, 0x68, 0xe2, 0x5c, 0xb9, 0xc3, 0x39, 0xbd, 0xe4, 0xa1, 0x8e, 0xd7, - 0x8d, 0xb8, 0x20, 0x3d, 0xa6, 0x97, 0xd8, 0xf9, 0x48, 0x25, 0xd6, 0x44, 0x41, 0x74, 0x3e, 0x62, - 0xe1, 0x4a, 0xf6, 0x53, 0xa8, 0xa1, 0xf7, 0xcc, 0xb8, 0x42, 0x75, 0xae, 0xd0, 0xce, 0x4f, 0x15, - 0x42, 0x57, 0x9a, 0xa1, 0x3e, 0x6a, 0x28, 0x47, 0xf8, 0x0c, 0x92, 0xe6, 0xe3, 0x74, 0x3c, 0xa2, - 0xc1, 0x8f, 0x68, 0x0a, 0x2b, 0x22, 0x8a, 0x07, 0xec, 0x81, 0x56, 0xd8, 0x72, 0x25, 0xd8, 0x14, - 0x6a, 0x4b, 0x93, 0xae, 0x49, 0xca, 0x0b, 0x5f, 0x04, 0xa9, 0x47, 0xe3, 0x89, 0x9f, 0xea, 0x2d, - 0x7e, 0x6d, 0x2d, 0x81, 0x8f, 0x83, 0xd4, 0x44, 0xb4, 0x1d, 0x40, 0x7d, 0xad, 0xb7, 0xc5, 0xab, - 0x96, 0x44, 0x1a, 0x25, 0x33, 0xe9, 0x04, 0xd2, 0x79, 0xcc, 0x28, 0x99, 0xe1, 0x55, 0x67, 0xcb, - 0xe7, 0xc2, 0xd1, 0x44, 0x0a, 0xaa, 0x66, 0xcb, 0xe7, 0xdc, 0xcb, 0xde, 0x04, 0x95, 0x15, 0x4b, - 0xc2, 0x4b, 0xab, 0x4c, 0x2c, 0xa1, 0x87, 0xa9, 0x45, 0x17, 0x2c, 0xab, 0x81, 0xb2, 0xaa, 0x06, - 0x9f, 0xc9, 0xaa, 0x23, 0xca, 0xf5, 0x83, 0x3b, 0x9a, 0xe8, 0xfd, 0xb5, 0x7a, 0xf3, 0x39, 0x94, - 0xa2, 0x53, 0x7e, 0x56, 0xeb, 0xc6, 0xd7, 0xdf, 0x8a, 0x37, 0x48, 0xfc, 0xa0, 0xeb, 0x47, 0x7e, - 0x3c, 0xa1, 0x4e, 0x29, 0x3a, 0x25, 0xdf, 0xc1, 0x3d, 0x6c, 0xc6, 0x69, 0x70, 0x15, 0xf3, 0xc5, - 0xf3, 0xef, 0xe1, 0x5d, 0x7b, 0x75, 0x39, 0x71, 0x95, 0x15, 0x1c, 0xed, 0xf4, 0x3a, 0x90, 0xef, - 0x44, 0xb0, 0xfd, 0x23, 0xa1, 0x97, 0x3e, 0xd7, 0xef, 0x03, 0x84, 0xb9, 0x97, 0xfa, 0x79, 0x1e, - 0x5e, 0x50, 0x69, 0xee, 0x5a, 0x98, 0xdb, 0x02, 0x40, 0xcf, 0x08, 0x73, 0x2f, 0x4a, 0xe2, 0x99, - 0xc7, 0xc2, 0x39, 0x4d, 0x16, 0x4c, 0x46, 0x5f, 0x33, 0xcc, 0x07, 0x49, 0x3c, 0x73, 0x05, 0xd8, - 0x7e, 0x06, 0x15, 0x5e, 0x92, 0xae, 0xa5, 0xcc, 0x6d, 0xa8, 0x3b, 0xc3, 0xb1, 0xd5, 0xf3, 0x9c, - 0x61, 0xb7, 0x6f, 0x69, 0x0a, 0x76, 0x93, 0xc6, 0x11, 0x76, 0xb8, 0x1e, 0x36, 0x8d, 0x63, 0x5b, - 0x2b, 0x61, 0xda, 0xfc, 0x76, 0xe8, 0x68, 0x65, 0xec, 0x10, 0xbb, 0xce, 0xd0, 0xe8, 0x1d, 0x19, - 0x23, 0x57, 0xab, 0x60, 0x97, 0x31, 0x30, 0x8e, 0x6c, 0x6d, 0xb3, 0xfd, 0x05, 0xd4, 0xd7, 0x2c, - 0x87, 0x65, 0x6e, 0xd0, 0x11, 0xf9, 0x78, 0x70, 0x28, 0xf3, 0xf1, 0xa0, 0x73, 0xa8, 0x95, 0x70, - 0xc5, 0xc1, 0x9d, 0xb6, 0xa0, 0xd4, 0x3d, 0xd2, 0x2a, 0xf8, 0xdf, 0xe8, 0x6a, 0x9b, 0xed, 0x7f, - 0x2b, 0x50, 0x95, 0x6f, 0x19, 0xd2, 0x83, 0x3a, 0x5b, 0xc4, 0x31, 0x8d, 0x3c, 0xfe, 0x23, 0x85, - 0xe8, 0x33, 0xde, 0xbd, 0xfd, 0x01, 0x24, 0x3a, 0x7f, 0x10, 0x3c, 0xde, 0x29, 0xbf, 0x09, 0x6a, - 0x51, 0x43, 0x65, 0x66, 0xad, 0xca, 0x02, 0x8a, 0x4b, 0x45, 0xf5, 0x94, 0xf9, 0xb4, 0x2a, 0x4b, - 0x27, 0xa6, 0xc9, 0x64, 0xc1, 0x68, 0xe6, 0x4d, 0x43, 0xde, 0x3b, 0xca, 0x44, 0xca, 0xb1, 0xe3, - 0x10, 0x1b, 0xc8, 0xfb, 0x00, 0x39, 0xcd, 0x31, 0x81, 0xe3, 0xba, 0x48, 0xa3, 0x35, 0x89, 0xf4, - 0x83, 0xf6, 0xaf, 0x5e, 0xf6, 0xa6, 0x40, 0x7b, 0x1c, 0x0a, 0x33, 0xb8, 0x66, 0x57, 0x2b, 0x11, - 0x80, 0x2d, 0xd3, 0x19, 0xd9, 0x86, 0xa5, 0x95, 0xdb, 0x7f, 0x29, 0x81, 0x5a, 0xbc, 0xc8, 0xae, - 0x69, 0xad, 0xdc, 0xac, 0x75, 0xe9, 0xba, 0xd6, 0xd7, 0x6a, 0x7b, 0xf9, 0xc7, 0xb5, 0x1d, 0x9b, - 0x4c, 0xba, 0xfa, 0x16, 0x3e, 0xc6, 0xef, 0xe4, 0x01, 0x5f, 0xd4, 0x6b, 0x59, 0x0e, 0x38, 0x26, - 0xea, 0xf5, 0x09, 0x88, 0xea, 0xed, 0xc5, 0x74, 0xc9, 0x78, 0xde, 0x6d, 0x75, 0xf6, 0xee, 0x78, - 0x50, 0xee, 0x5b, 0x74, 0xc9, 0x2c, 0x0c, 0xbd, 0x1a, 0xe7, 0xe2, 0xb4, 0x7d, 0x00, 0x6a, 0x01, - 0xaf, 0x3f, 0x99, 0x36, 0xa4, 0x97, 0x28, 0x45, 0xd5, 0x2e, 0x15, 0x55, 0xbb, 0xdc, 0xfe, 0xab, - 0x02, 0x6a, 0xf1, 0xda, 0x24, 0xe6, 0xca, 0x1d, 0xd6, 0xda, 0xce, 0x07, 0x77, 0xbc, 0x51, 0x45, - 0x02, 0x90, 0xfe, 0xc0, 0xbd, 0xfe, 0xff, 0xf2, 0x87, 0xf6, 0x8e, 0x8c, 0x19, 0x02, 0x2d, 0x7b, - 0xd8, 0xb7, 0x5c, 0xcf, 0x1d, 0x7a, 0x7c, 0xa0, 0x6d, 0x74, 0x8f, 0xff, 0xd0, 0x9b, 0x25, 0x85, - 0x1e, 0x21, 0xff, 0x35, 0xee, 0x23, 0x7f, 0x46, 0x63, 0xf6, 0xf0, 0xe2, 0xf0, 0x21, 0x6f, 0x56, - 0x1e, 0xbe, 0xf4, 0x57, 0xbe, 0xcf, 0x2f, 0xd2, 0x74, 0x2d, 0x9d, 0x9c, 0x6e, 0x71, 0xd9, 0xc3, - 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0x40, 0x23, 0x42, 0x87, 0x14, 0x14, 0x00, 0x00, + // 2314 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x58, 0xdd, 0x72, 0xe3, 0xb6, + 0x15, 0x36, 0x25, 0xd9, 0xa2, 0x8e, 0x7e, 0xcc, 0x45, 0x93, 0x94, 0x71, 0xb2, 0x8d, 0xab, 0x6c, + 0x1a, 0x4f, 0x9a, 0x78, 0x6b, 0xb9, 0xf9, 0x69, 0xd3, 0x69, 0x42, 0x59, 0xb4, 0x57, 0x59, 0x99, + 0x62, 0x28, 0x6a, 0x93, 0x74, 0xd2, 0xe1, 0xd0, 0x22, 0x24, 0xb3, 0x4b, 0x91, 0x5c, 0x12, 0xf2, + 0xca, 0x79, 0x89, 0xf6, 0x61, 0x7a, 0xd9, 0x77, 0xe8, 0xe4, 0x0d, 0xfa, 0x00, 0xbd, 0xee, 0xb4, + 0xbd, 0xea, 0x1c, 0x00, 0x94, 0xe5, 0x64, 0x6d, 0xef, 0xf4, 0xc6, 0x06, 0x3e, 0x9c, 0x0f, 0x38, + 0x3c, 0x38, 0x7f, 0x10, 0xbc, 0x13, 0x85, 0x33, 0x9f, 0x25, 0x0f, 0x2f, 0xd2, 0xf4, 0x61, 0x18, + 0x33, 0x9a, 0x4d, 0xfd, 0x09, 0xcd, 0xaf, 0x86, 0xfb, 0x69, 0x96, 0xb0, 0x84, 0xbc, 0x2a, 0xc4, + 0xf6, 0x2f, 0xd2, 0x74, 0xff, 0x4a, 0x6c, 0xe7, 0xcd, 0x75, 0x76, 0x9a, 0xd3, 0x89, 0xf8, 0x2b, + 0x48, 0xed, 0xef, 0x9b, 0x50, 0xeb, 0x17, 0xc2, 0x84, 0x40, 0x25, 0xf6, 0xe7, 0x54, 0x57, 0x76, + 0x95, 0xbd, 0x9a, 0xc3, 0xc7, 0xe4, 0x37, 0x50, 0x61, 0x97, 0x29, 0xd5, 0x4b, 0xbb, 0xca, 0x5e, + 0xab, 0xf3, 0xce, 0xfe, 0x0b, 0x4f, 0xd9, 0x5f, 0xed, 0xb1, 0xef, 0x5e, 0xa6, 0xd4, 0xe1, 0x14, + 0xa2, 0x43, 0x95, 0xc6, 0xfe, 0x59, 0x44, 0x03, 0xbd, 0xbc, 0xab, 0xec, 0xa9, 0x4e, 0x31, 0x25, + 0x3f, 0x87, 0x46, 0x7a, 0x7e, 0x99, 0x7b, 0x7e, 0x10, 0x64, 0x34, 0xcf, 0xf5, 0x0a, 0x3f, 0xb0, + 0x8e, 0x98, 0x21, 0x20, 0x14, 0x09, 0xd3, 0x42, 0x80, 0xe6, 0xfa, 0xe6, 0x6e, 0x19, 0x45, 0xc2, + 0xd4, 0x28, 0x20, 0xa2, 0x41, 0xf9, 0x22, 0x9b, 0xea, 0x5b, 0xbb, 0xca, 0x5e, 0xd3, 0xc1, 0x21, + 0xf9, 0x05, 0x6c, 0xe7, 0x94, 0x79, 0xc1, 0xf9, 0x24, 0xf5, 0x26, 0x51, 0x48, 0x63, 0xa6, 0x57, + 0xf9, 0xc9, 0xcd, 0x9c, 0xb2, 0xde, 0xf9, 0x24, 0x3d, 0xe2, 0x20, 0x32, 0xe7, 0x6c, 0xa1, 0xab, + 0x82, 0x39, 0x67, 0x0b, 0xf2, 0x18, 0x60, 0x11, 0xc7, 0x8b, 0xf9, 0x19, 0xcd, 0x68, 0xa0, 0xd7, + 0x76, 0x95, 0xbd, 0x7a, 0xe7, 0x97, 0x77, 0x7e, 0xec, 0x78, 0x45, 0x71, 0xd6, 0xe8, 0xa4, 0x0b, + 0x6a, 0xb6, 0xf4, 0xe6, 0x49, 0x40, 0x73, 0xbd, 0xb1, 0x5b, 0xde, 0xab, 0x77, 0xde, 0xbd, 0x73, + 0x2b, 0x67, 0x79, 0x9a, 0x04, 0xd4, 0xa9, 0x66, 0xfc, 0x7f, 0x4e, 0xbe, 0x84, 0x66, 0xb6, 0xf4, + 0xd2, 0xc8, 0x9f, 0xd0, 0x39, 0x8d, 0x59, 0xae, 0x37, 0xf9, 0x46, 0xef, 0xbf, 0xc4, 0x46, 0x76, + 0x41, 0x72, 0x1a, 0xd9, 0xd5, 0x24, 0x27, 0x1f, 0x43, 0x39, 0x5f, 0x9c, 0xe9, 0x01, 0xff, 0xb8, + 0xb7, 0x6f, 0xd8, 0x68, 0xb4, 0x38, 0x5b, 0xed, 0xf5, 0x68, 0xc3, 0x41, 0x06, 0xf9, 0x04, 0x36, + 0xe7, 0x74, 0x1e, 0x4e, 0x75, 0xca, 0xa9, 0xbb, 0x37, 0x50, 0x4f, 0x51, 0x66, 0x10, 0xc6, 0x4f, + 0x1f, 0x6d, 0x38, 0x82, 0x40, 0x0c, 0x50, 0xfd, 0x69, 0xea, 0x4f, 0x9e, 0x52, 0xa6, 0x4f, 0x6f, + 0x3d, 0xd7, 0x90, 0x62, 0x92, 0xbf, 0xa2, 0x91, 0x0e, 0x94, 0x99, 0x9f, 0xea, 0x33, 0xce, 0xfe, + 0xd9, 0x0d, 0x6c, 0xd7, 0x4f, 0x25, 0x11, 0x85, 0x51, 0xe1, 0x8b, 0x65, 0xe4, 0xc7, 0xfa, 0xf9, + 0xad, 0x0a, 0x3f, 0x41, 0x99, 0x42, 0x61, 0x4e, 0x20, 0xbf, 0x83, 0x4d, 0x1e, 0x1f, 0x7a, 0x78, + 0x2b, 0xb3, 0x6f, 0x8f, 0xe8, 0x04, 0x99, 0xdd, 0x92, 0xae, 0x20, 0x9b, 0x93, 0xc8, 0x67, 0xa0, + 0x5e, 0xcc, 0x97, 0x5e, 0x4c, 0xd9, 0xa1, 0xfe, 0x27, 0xbe, 0x41, 0xfb, 0xa6, 0xa3, 0xe7, 0x4b, + 0x8b, 0xb2, 0x43, 0x79, 0x78, 0xf5, 0x42, 0x4c, 0xc9, 0x87, 0x50, 0x39, 0x4b, 0xe2, 0x40, 0x7f, + 0xca, 0xc9, 0x6f, 0xdd, 0x40, 0xee, 0x26, 0x71, 0x20, 0x99, 0x5c, 0x1c, 0x6d, 0x34, 0xcb, 0xa8, + 0x1e, 0xdd, 0x6a, 0xa3, 0x93, 0x8c, 0x16, 0x36, 0x9a, 0x65, 0x14, 0x8f, 0x9a, 0xb1, 0x74, 0xa1, + 0xcf, 0x6f, 0x3d, 0xea, 0x84, 0xa5, 0x8b, 0xe2, 0x28, 0x14, 0x47, 0x5a, 0x98, 0x86, 0xa9, 0x1e, + 0xdf, 0x4a, 0xeb, 0xdb, 0x7d, 0xbb, 0xa0, 0xa1, 0xf8, 0xce, 0x27, 0x00, 0x57, 0xc1, 0x42, 0xde, + 0x83, 0x7b, 0x2b, 0x61, 0xef, 0x79, 0xc8, 0xce, 0xbd, 0x30, 0x95, 0x59, 0x67, 0x7b, 0xb5, 0xf0, + 0x55, 0xc8, 0xce, 0xfb, 0xe9, 0xce, 0xdf, 0x15, 0xd8, 0x12, 0xc1, 0x41, 0x5e, 0x81, 0xcd, 0x67, + 0x0b, 0xba, 0x10, 0x09, 0xaa, 0xe9, 0x88, 0x09, 0xf9, 0x1c, 0x2a, 0x18, 0x6a, 0x32, 0x43, 0xbd, + 0xff, 0x92, 0x91, 0x26, 0x13, 0x15, 0x32, 0x31, 0xd7, 0x04, 0x74, 0xea, 0x2f, 0x22, 0xc6, 0x83, + 0x56, 0x66, 0xab, 0xba, 0xc4, 0x50, 0xba, 0xfd, 0x05, 0x54, 0x90, 0x40, 0xea, 0x50, 0x1d, 0x5b, + 0x8f, 0xad, 0xe1, 0x57, 0x96, 0xb6, 0x81, 0x13, 0x7b, 0x38, 0x18, 0xf4, 0xad, 0x13, 0x4d, 0x21, + 0x98, 0x49, 0x2d, 0xd7, 0x74, 0x9c, 0xb1, 0xed, 0x6a, 0x25, 0xd2, 0x00, 0xd5, 0xe8, 0x19, 0xb6, + 0xdb, 0x7f, 0x62, 0x6a, 0x65, 0x94, 0xec, 0x99, 0xc7, 0xc6, 0x78, 0xe0, 0x6a, 0x95, 0x9d, 0x6f, + 0xa1, 0xbe, 0x16, 0xa4, 0x37, 0x7c, 0xd5, 0x6b, 0xb0, 0xf5, 0x3c, 0xc9, 0x9e, 0xd2, 0x8c, 0x7f, + 0x57, 0xd3, 0x91, 0x33, 0xf2, 0x16, 0xd4, 0xe7, 0x7e, 0x18, 0x7b, 0xec, 0x3c, 0xa3, 0x7e, 0x91, + 0x58, 0x01, 0x21, 0x97, 0x23, 0xed, 0x7f, 0x29, 0x52, 0x55, 0x02, 0xad, 0xb1, 0xd5, 0x33, 0x8f, + 0xfb, 0x96, 0xd9, 0xf3, 0xdc, 0x6f, 0x6c, 0x53, 0xdb, 0x20, 0xf7, 0xa0, 0x39, 0x1a, 0x77, 0x3d, + 0xae, 0xe8, 0xb1, 0x71, 0x64, 0x6a, 0x0a, 0x79, 0x15, 0xee, 0x8d, 0x86, 0xc7, 0xee, 0x57, 0x86, + 0x63, 0x7a, 0x83, 0xe1, 0xd0, 0xee, 0x1a, 0x47, 0x8f, 0xb5, 0x12, 0x51, 0xa1, 0xd2, 0xb3, 0x7b, + 0x8f, 0xb5, 0x32, 0xa9, 0xc1, 0xe6, 0xa9, 0x79, 0xda, 0x3f, 0xd6, 0x2a, 0xa4, 0x0a, 0x65, 0xd7, + 0xb0, 0xb5, 0x4d, 0xfc, 0x58, 0xe3, 0xd8, 0xb3, 0x8d, 0xa3, 0xc7, 0xa6, 0xab, 0x6d, 0x11, 0x0d, + 0x1a, 0x4f, 0xbe, 0x1e, 0x18, 0x96, 0xe7, 0x8e, 0x2d, 0xcb, 0x1c, 0x68, 0x55, 0xf2, 0x0a, 0x34, + 0xfa, 0xf6, 0xc8, 0x3c, 0x2a, 0x10, 0x75, 0xa7, 0xa4, 0xf2, 0xb3, 0x9e, 0x9c, 0x7e, 0x6d, 0x99, + 0xee, 0xe1, 0x9a, 0x0a, 0x35, 0xd4, 0xb4, 0x3b, 0xb4, 0x7a, 0x6b, 0x18, 0x90, 0x16, 0xc0, 0x89, + 0x63, 0x16, 0xf4, 0x3a, 0xd9, 0x86, 0xfa, 0x89, 0x6b, 0x8f, 0x0b, 0xa0, 0x81, 0x00, 0x7a, 0x59, + 0x01, 0x34, 0xbb, 0x5b, 0x50, 0x89, 0xc2, 0xf8, 0x69, 0xfb, 0xbf, 0x25, 0x68, 0xac, 0x67, 0x31, + 0x34, 0x59, 0xea, 0x67, 0x34, 0x66, 0xde, 0x5a, 0x75, 0x03, 0x01, 0x59, 0x58, 0xe3, 0x5e, 0x85, + 0xad, 0x7c, 0x71, 0xe6, 0x85, 0x81, 0xb4, 0xf5, 0x66, 0xbe, 0x38, 0xeb, 0x07, 0xe4, 0x1b, 0x68, + 0x32, 0x7f, 0xe6, 0x65, 0xcf, 0xbd, 0x24, 0x65, 0x61, 0x12, 0x73, 0x63, 0xb7, 0x3a, 0x1f, 0xbe, + 0x44, 0xe6, 0xdc, 0x77, 0xfd, 0x99, 0x43, 0x9f, 0x67, 0x21, 0xa3, 0x43, 0xce, 0xcd, 0x9d, 0x3a, + 0xf3, 0x67, 0xce, 0x73, 0x31, 0x23, 0xf7, 0x01, 0xd2, 0x45, 0x7e, 0xee, 0x05, 0x09, 0x3b, 0x78, + 0xc6, 0xcb, 0x9f, 0xea, 0xd4, 0x10, 0xe9, 0x21, 0x80, 0x85, 0x98, 0xf9, 0xb3, 0x03, 0x7d, 0x93, + 0xab, 0xc3, 0xc7, 0x12, 0xeb, 0xc8, 0x72, 0xc7, 0xc7, 0xed, 0x3f, 0x2b, 0x70, 0xef, 0x47, 0x27, + 0xa1, 0xeb, 0xf5, 0xfa, 0x23, 0xa3, 0x3b, 0x30, 0x7b, 0xda, 0x06, 0x5e, 0x9f, 0x3d, 0x1e, 0x3d, + 0x3a, 0xd0, 0x94, 0x62, 0xd8, 0x11, 0xd7, 0x6b, 0x0f, 0xed, 0x03, 0xad, 0x2c, 0x47, 0x1d, 0xad, + 0x82, 0x16, 0x75, 0x1d, 0xc3, 0x1a, 0x0d, 0x0c, 0xd7, 0x3c, 0x38, 0xd0, 0x36, 0xaf, 0x03, 0x1d, + 0x6d, 0xeb, 0x1a, 0xd0, 0x39, 0xd0, 0xaa, 0xd7, 0x81, 0x8e, 0xa6, 0xb6, 0xff, 0x51, 0x82, 0xda, + 0xaa, 0x0e, 0x90, 0xdf, 0xcb, 0xd0, 0x54, 0xb8, 0xe1, 0xde, 0xbb, 0xab, 0x6e, 0x88, 0x11, 0xaf, + 0x83, 0x22, 0x30, 0x5f, 0x83, 0xad, 0xb9, 0x9f, 0x33, 0x19, 0x04, 0xaa, 0x23, 0x67, 0xa4, 0x05, + 0xa5, 0x50, 0xf8, 0x7e, 0xd3, 0x29, 0x85, 0x01, 0x79, 0x17, 0xb6, 0xf3, 0x04, 0xab, 0x85, 0x37, + 0x0d, 0x23, 0xca, 0x6f, 0x59, 0xb4, 0x14, 0x2d, 0x01, 0x1f, 0x4b, 0x14, 0x37, 0xcc, 0xe9, 0x24, + 0xa3, 0x8c, 0x9b, 0xb6, 0xe6, 0xc8, 0x19, 0x79, 0x03, 0x6a, 0x59, 0x18, 0xcf, 0xbc, 0x3c, 0xfc, + 0x8e, 0x4a, 0x0b, 0xab, 0x08, 0x8c, 0xc2, 0xef, 0xb8, 0xff, 0x9c, 0x2d, 0xa6, 0x53, 0x9a, 0x89, + 0xe5, 0x2a, 0x5f, 0x06, 0x01, 0x71, 0x01, 0x64, 0x2f, 0x3d, 0x1e, 0xb7, 0xb9, 0x6c, 0x2a, 0xd4, + 0x6c, 0xf9, 0x25, 0x9f, 0xe3, 0x22, 0x5b, 0x2d, 0xd6, 0xc4, 0x22, 0x93, 0x8b, 0xed, 0x8e, 0xb4, + 0x16, 0x4f, 0x6f, 0x0d, 0x50, 0x4d, 0xf7, 0x91, 0xe9, 0x58, 0xa6, 0xab, 0x6d, 0x90, 0x2d, 0x28, + 0xf5, 0x6d, 0x4d, 0x41, 0x13, 0xdb, 0x63, 0xcb, 0xf5, 0xfa, 0xd6, 0x17, 0xe6, 0x91, 0xab, 0x95, + 0xda, 0xff, 0x2c, 0x41, 0x6d, 0x55, 0xb9, 0x50, 0xb9, 0x3c, 0x9b, 0xac, 0x3a, 0x29, 0xe9, 0xdc, + 0x79, 0x36, 0x29, 0x1a, 0xa9, 0xb7, 0xa0, 0x1e, 0xe4, 0x6c, 0x25, 0x50, 0x12, 0x02, 0x41, 0xce, + 0x0a, 0x01, 0x6c, 0xa3, 0xe2, 0x50, 0x5a, 0x13, 0x87, 0xe4, 0x4d, 0xa8, 0xcd, 0x17, 0x11, 0x0b, + 0x27, 0x7e, 0xce, 0xa4, 0x21, 0xaf, 0x00, 0xf2, 0x11, 0x94, 0x67, 0x29, 0xe5, 0x06, 0xac, 0x77, + 0x1e, 0xdc, 0x55, 0x5a, 0xf7, 0x4f, 0x52, 0xea, 0x20, 0x61, 0xe7, 0xaf, 0x0a, 0x94, 0x4f, 0x52, + 0x4a, 0x76, 0x31, 0xdb, 0x4e, 0xfc, 0xd4, 0xbb, 0xc8, 0xa6, 0x18, 0x73, 0x22, 0xed, 0x01, 0xc7, + 0x9e, 0x64, 0xd3, 0x7e, 0x40, 0xfa, 0xa0, 0xf2, 0xf6, 0x74, 0x92, 0x44, 0x32, 0xab, 0x7f, 0xf0, + 0x32, 0xc7, 0xec, 0xdb, 0x92, 0xe4, 0xac, 0xe8, 0xed, 0xcf, 0x41, 0x2d, 0xd0, 0xeb, 0xb9, 0xbb, + 0x0a, 0xe5, 0xbe, 0xfd, 0x6b, 0x4d, 0x11, 0x83, 0x8f, 0x44, 0xc6, 0x5e, 0x99, 0xbf, 0x8c, 0xb0, + 0x35, 0x7a, 0xa4, 0x55, 0xda, 0x7f, 0x84, 0xc6, 0x7a, 0x6f, 0x42, 0x1e, 0x40, 0xe3, 0x3c, 0xc9, + 0x99, 0x17, 0x4e, 0xd7, 0xd2, 0x09, 0xb6, 0x01, 0x0e, 0x20, 0xde, 0x9f, 0xf2, 0x94, 0xf2, 0x2e, + 0x6c, 0x47, 0x61, 0xbc, 0x58, 0x7a, 0x2b, 0x65, 0xa5, 0xe5, 0x5b, 0x1c, 0x5e, 0x25, 0x8a, 0xf6, + 0xf7, 0x0a, 0x54, 0x65, 0xf7, 0x82, 0x0d, 0xf3, 0x05, 0xcd, 0x72, 0x4c, 0x35, 0xc2, 0x28, 0xc5, + 0x14, 0x6d, 0x76, 0xed, 0x50, 0x79, 0x8b, 0xd7, 0x0f, 0x64, 0x89, 0x37, 0x0f, 0x27, 0x59, 0x92, + 0xd3, 0xec, 0x22, 0x9c, 0x88, 0x32, 0x56, 0x73, 0x5a, 0x2c, 0x39, 0x5d, 0x43, 0x71, 0xab, 0x6c, + 0xe9, 0x5d, 0x79, 0x7b, 0x45, 0x98, 0x3f, 0x5b, 0x3a, 0x85, 0xbf, 0xef, 0x42, 0x83, 0xad, 0x4b, + 0x88, 0x2c, 0x04, 0xec, 0x4a, 0xe2, 0x3e, 0x80, 0x68, 0xe5, 0xbd, 0x59, 0x9e, 0xf0, 0x78, 0x51, + 0x9d, 0x9a, 0x40, 0x4e, 0xf2, 0xa4, 0xfd, 0x9f, 0x32, 0xd4, 0x56, 0x1d, 0x12, 0xfa, 0x17, 0xcd, + 0x63, 0x19, 0xc1, 0x38, 0x44, 0x97, 0xf4, 0x63, 0x16, 0x7a, 0x19, 0x4d, 0x23, 0xff, 0xb2, 0xa8, + 0x61, 0x08, 0x39, 0x1c, 0x21, 0xaf, 0x83, 0x1a, 0x25, 0x13, 0x3f, 0xc2, 0xb6, 0x40, 0xf8, 0x5f, + 0x95, 0xcf, 0xfb, 0x29, 0x8f, 0x35, 0x3a, 0x4f, 0x18, 0xc5, 0x35, 0x11, 0xc4, 0xaa, 0x00, 0xc4, + 0xa2, 0xe0, 0xe5, 0x69, 0x58, 0x84, 0x31, 0x07, 0x46, 0x69, 0x88, 0x4a, 0x4b, 0x26, 0xae, 0x8a, + 0x28, 0x96, 0x7b, 0xe1, 0xf2, 0x6f, 0x01, 0x26, 0xd9, 0x65, 0xca, 0x12, 0xcf, 0x8f, 0x66, 0x3c, + 0x8a, 0x5b, 0x9d, 0x37, 0xae, 0xb9, 0x1d, 0x7f, 0x37, 0x1d, 0x71, 0x19, 0x23, 0x9a, 0x39, 0xb5, + 0x49, 0x31, 0x24, 0x7b, 0xa0, 0x89, 0x73, 0xe5, 0x0e, 0x4f, 0xe9, 0x25, 0x0f, 0x75, 0xbc, 0x6e, + 0xc4, 0x05, 0xe9, 0x31, 0xbd, 0xc4, 0xce, 0x47, 0x2a, 0xb1, 0x26, 0x0a, 0xa2, 0xf3, 0x11, 0x0b, + 0x57, 0xb2, 0x1f, 0x43, 0x0d, 0xbd, 0x67, 0xc6, 0x15, 0xaa, 0x73, 0x85, 0x76, 0x7e, 0xac, 0x10, + 0xba, 0xd2, 0x0c, 0xf5, 0x51, 0x43, 0x39, 0xc2, 0x67, 0x90, 0x34, 0x1f, 0xa7, 0xe3, 0x11, 0x0d, + 0x7e, 0x44, 0x53, 0x58, 0x11, 0x51, 0x3c, 0x60, 0x0f, 0xb4, 0xc2, 0x96, 0x2b, 0xc1, 0xa6, 0x50, + 0x5b, 0x9a, 0x74, 0x4d, 0x52, 0x5e, 0xf8, 0x22, 0x48, 0x3d, 0x1a, 0x4f, 0xfc, 0x54, 0x6f, 0xf1, + 0x6b, 0x6b, 0x09, 0x7c, 0x1c, 0xa4, 0x26, 0xa2, 0xed, 0x00, 0xea, 0x6b, 0xbd, 0x2d, 0x5e, 0xb5, + 0x24, 0xd2, 0x28, 0x99, 0x49, 0x27, 0x90, 0xce, 0x63, 0x46, 0xc9, 0x0c, 0xaf, 0x3a, 0x5b, 0x3e, + 0x13, 0x8e, 0x26, 0x52, 0x50, 0x35, 0x5b, 0x3e, 0xe3, 0x5e, 0xf6, 0x3a, 0xa8, 0xac, 0x58, 0x12, + 0x5e, 0x5a, 0x65, 0x62, 0x09, 0x3d, 0x4c, 0x2d, 0xba, 0x60, 0x59, 0x0d, 0x94, 0x55, 0x35, 0xf8, + 0x44, 0x56, 0x1d, 0x51, 0xae, 0x1f, 0xdc, 0xd1, 0x44, 0xef, 0xaf, 0xd5, 0x9b, 0x4f, 0xa1, 0x14, + 0x9d, 0xf1, 0xb3, 0x5a, 0x37, 0xbe, 0xfe, 0x56, 0xbc, 0x41, 0xe2, 0x07, 0x5d, 0x3f, 0xf2, 0xe3, + 0x09, 0x75, 0x4a, 0xd1, 0x19, 0xf9, 0x16, 0xee, 0x61, 0x33, 0x4e, 0x83, 0xab, 0x98, 0x2f, 0x9e, + 0x7f, 0x0f, 0xef, 0xda, 0xab, 0xcb, 0x89, 0xab, 0xac, 0xe0, 0x68, 0x67, 0xd7, 0x81, 0x7c, 0x27, + 0x82, 0xed, 0x1f, 0x08, 0xbd, 0xf0, 0xb9, 0x7e, 0x1f, 0x20, 0xcc, 0xbd, 0xd4, 0xcf, 0xf3, 0xf0, + 0x82, 0x4a, 0x73, 0xd7, 0xc2, 0xdc, 0x16, 0x00, 0x7a, 0x46, 0x98, 0x7b, 0x51, 0x12, 0xcf, 0x3c, + 0x16, 0xce, 0x69, 0xb2, 0x60, 0x32, 0xfa, 0x9a, 0x61, 0x3e, 0x48, 0xe2, 0x99, 0x2b, 0xc0, 0xf6, + 0x37, 0x50, 0xe1, 0x25, 0xe9, 0x5a, 0xca, 0xdc, 0x86, 0xba, 0x33, 0x1c, 0x5b, 0x3d, 0xcf, 0x19, + 0x76, 0xfb, 0x96, 0xa6, 0x60, 0x37, 0x69, 0x1c, 0x61, 0x87, 0xeb, 0x61, 0xd3, 0x38, 0xb6, 0xb5, + 0x12, 0xa6, 0xcd, 0xaf, 0x87, 0x8e, 0x56, 0xc6, 0x0e, 0xb1, 0xeb, 0x0c, 0x8d, 0xde, 0x91, 0x31, + 0x72, 0xb5, 0x0a, 0x76, 0x19, 0x03, 0xe3, 0xc8, 0xd6, 0x36, 0xdb, 0x9f, 0x41, 0x7d, 0xcd, 0x72, + 0x58, 0xe6, 0x06, 0x1d, 0x91, 0x8f, 0x07, 0x87, 0x32, 0x1f, 0x0f, 0x3a, 0x87, 0x5a, 0x09, 0x57, + 0x1c, 0xdc, 0x69, 0x0b, 0x4a, 0xdd, 0x23, 0xad, 0x82, 0xff, 0x8d, 0xae, 0xb6, 0xd9, 0xfe, 0xb7, + 0x02, 0x55, 0xf9, 0x96, 0x21, 0x3d, 0xa8, 0xb3, 0x45, 0x1c, 0xd3, 0xc8, 0xe3, 0x3f, 0x52, 0x88, + 0x3e, 0xe3, 0xed, 0xdb, 0x1f, 0x40, 0xa2, 0xf3, 0x07, 0xc1, 0xe3, 0x9d, 0xf2, 0xeb, 0xa0, 0x16, + 0x35, 0x54, 0x66, 0xd6, 0xaa, 0x2c, 0xa0, 0xb8, 0x54, 0x54, 0x4f, 0x99, 0x4f, 0xab, 0xb2, 0x74, + 0x62, 0x9a, 0x4c, 0x16, 0x8c, 0x66, 0xde, 0x34, 0xe4, 0xbd, 0xa3, 0x4c, 0xa4, 0x1c, 0x3b, 0x0e, + 0xb1, 0x81, 0xbc, 0x0f, 0x90, 0xd3, 0x1c, 0x13, 0x38, 0xae, 0x8b, 0x34, 0x5a, 0x93, 0x48, 0x3f, + 0x68, 0xff, 0xea, 0x45, 0x6f, 0x0a, 0xb4, 0xc7, 0xa1, 0x30, 0x83, 0x6b, 0x76, 0xb5, 0x12, 0x01, + 0xd8, 0x32, 0x9d, 0x91, 0x6d, 0x58, 0x5a, 0xb9, 0xfd, 0x97, 0x12, 0xa8, 0xc5, 0x8b, 0xec, 0x9a, + 0xd6, 0xca, 0xcd, 0x5a, 0x97, 0xae, 0x6b, 0x7d, 0xad, 0xb6, 0x97, 0x7f, 0x58, 0xdb, 0xb1, 0xc9, + 0xa4, 0xab, 0x6f, 0xe1, 0x63, 0xfc, 0x4e, 0x1e, 0xf0, 0x45, 0xbd, 0x96, 0xe5, 0x80, 0x63, 0xa2, + 0x5e, 0x9f, 0x80, 0xa8, 0xde, 0x5e, 0x4c, 0x97, 0x8c, 0xe7, 0xdd, 0x56, 0x67, 0xef, 0x8e, 0x07, + 0xe5, 0xbe, 0x45, 0x97, 0xcc, 0xc2, 0xd0, 0xab, 0x71, 0x2e, 0x4e, 0xdb, 0x07, 0xa0, 0x16, 0xf0, + 0xfa, 0x93, 0x69, 0x43, 0x7a, 0x89, 0x52, 0x54, 0xed, 0x52, 0x51, 0xb5, 0xcb, 0xed, 0xbf, 0x29, + 0xa0, 0x16, 0xaf, 0x4d, 0x62, 0xae, 0xdc, 0x61, 0xad, 0xed, 0x7c, 0x70, 0xc7, 0x1b, 0x55, 0x24, + 0x00, 0xe9, 0x0f, 0xdc, 0xeb, 0xff, 0x2f, 0x7f, 0x68, 0x1f, 0xca, 0x98, 0x21, 0xd0, 0xb2, 0x87, + 0x7d, 0xcb, 0xf5, 0xdc, 0xa1, 0xc7, 0x07, 0xda, 0x06, 0xf9, 0x29, 0xfc, 0x64, 0x85, 0x9d, 0x8e, + 0x07, 0x6e, 0x5f, 0x2c, 0x28, 0xdd, 0xe3, 0x3f, 0xf4, 0x66, 0x49, 0xa1, 0x60, 0xc8, 0x7f, 0xa6, + 0xfb, 0xc0, 0x9f, 0xd1, 0x98, 0x3d, 0xbc, 0x38, 0x7c, 0xc8, 0xbb, 0x98, 0x87, 0x2f, 0xfc, 0xf9, + 0xef, 0xd3, 0x8b, 0x34, 0x5d, 0xcb, 0x33, 0x67, 0x5b, 0x5c, 0xf6, 0xf0, 0x7f, 0x01, 0x00, 0x00, + 0xff, 0xff, 0xbe, 0x40, 0x6a, 0x8c, 0x2d, 0x14, 0x00, 0x00, } diff --git a/proto/ligato/vpp/interfaces/interface.proto b/proto/ligato/vpp/interfaces/interface.proto index bec95a364f..6f8685d11e 100644 --- a/proto/ligato/vpp/interfaces/interface.proto +++ b/proto/ligato/vpp/interfaces/interface.proto @@ -347,7 +347,8 @@ message IPIPLink { enum Mode { // point-to-point tunnel POINT_TO_POINT = 0; - // note: point-to multipoint support will be added in VPP 20.04 + // point-to multipoint tunnel (supported starting from VPP 20.05) + POINT_TO_MULTIPOINT = 1; }; // Mode of the IPIP tunnel Mode tunnel_mode = 1; diff --git a/proto/ligato/vpp/ipsec/ipsec.pb.go b/proto/ligato/vpp/ipsec/ipsec.pb.go index f0819c92a9..8c3e08e047 100644 --- a/proto/ligato/vpp/ipsec/ipsec.pb.go +++ b/proto/ligato/vpp/ipsec/ipsec.pb.go @@ -539,7 +539,9 @@ type TunnelProtection struct { // Outbound security associations identified by SA index. SaOut []uint32 `protobuf:"varint,2,rep,packed,name=sa_out,json=saOut,proto3" json:"sa_out,omitempty"` // Inbound security associations identified by SA index. - SaIn []uint32 `protobuf:"varint,3,rep,packed,name=sa_in,json=saIn,proto3" json:"sa_in,omitempty"` + SaIn []uint32 `protobuf:"varint,3,rep,packed,name=sa_in,json=saIn,proto3" json:"sa_in,omitempty"` + // (Optional) Next hop IP address, used for multipoint tunnels. + NextHopAddr string `protobuf:"bytes,4,opt,name=next_hop_addr,json=nextHopAddr,proto3" json:"next_hop_addr,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -591,6 +593,13 @@ func (m *TunnelProtection) GetSaIn() []uint32 { return nil } +func (m *TunnelProtection) GetNextHopAddr() string { + if m != nil { + return m.NextHopAddr + } + return "" +} + func init() { proto.RegisterEnum("ligato.vpp.ipsec.CryptoAlg", CryptoAlg_name, CryptoAlg_value) proto.RegisterEnum("ligato.vpp.ipsec.IntegAlg", IntegAlg_name, IntegAlg_value) @@ -606,64 +615,66 @@ func init() { func init() { proto.RegisterFile("ligato/vpp/ipsec/ipsec.proto", fileDescriptor_3aa20672189bf205) } var fileDescriptor_3aa20672189bf205 = []byte{ - // 938 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xed, 0x6e, 0xdb, 0x36, - 0x14, 0x8d, 0xbf, 0x64, 0xf9, 0xba, 0x72, 0x34, 0x76, 0x1f, 0x5a, 0xda, 0xa1, 0x46, 0x7e, 0x0c, - 0x46, 0x80, 0x39, 0x88, 0xd3, 0x74, 0x4d, 0xb3, 0x3f, 0x8a, 0x2d, 0x34, 0xc1, 0xd6, 0xd8, 0xa0, - 0xbc, 0x01, 0xdd, 0x06, 0x08, 0x8c, 0xcc, 0x19, 0xc2, 0x5c, 0x91, 0x10, 0xe9, 0x60, 0x7e, 0x97, - 0x3d, 0xd4, 0xde, 0x61, 0xc0, 0x9e, 0x63, 0xe0, 0xa5, 0xed, 0xc8, 0x69, 0x07, 0x0c, 0xfd, 0x13, - 0xf0, 0x1e, 0x9e, 0x7b, 0xe8, 0x13, 0x9e, 0x4b, 0xc1, 0xd3, 0x45, 0x36, 0x67, 0x5a, 0x1c, 0xdf, - 0x49, 0x79, 0x9c, 0x49, 0xc5, 0x53, 0xfb, 0xb7, 0x2f, 0x0b, 0xa1, 0x05, 0xf1, 0xed, 0x6e, 0xff, - 0x4e, 0xca, 0x3e, 0xe2, 0x87, 0xff, 0x38, 0xf0, 0x79, 0xcc, 0xd3, 0x65, 0x91, 0xe9, 0xd5, 0x44, - 0x2c, 0xb2, 0x74, 0x35, 0x62, 0x9a, 0xdd, 0x32, 0xc5, 0xc9, 0xa7, 0xd0, 0xc8, 0xf2, 0x19, 0xff, - 0x23, 0xa8, 0x74, 0x2b, 0x3d, 0x8f, 0xda, 0x82, 0x50, 0x80, 0x2c, 0xd7, 0xbc, 0xf8, 0x8d, 0xa5, - 0x5c, 0x05, 0xd5, 0x6e, 0xad, 0xd7, 0x1e, 0x0c, 0xfa, 0x0f, 0x75, 0xfb, 0x1f, 0xd6, 0xec, 0x5f, - 0x6f, 0x5a, 0x69, 0x49, 0x85, 0xfc, 0x02, 0x1d, 0x89, 0xbc, 0x84, 0xe7, 0xba, 0xc8, 0xb8, 0x0a, - 0x6a, 0xa8, 0xfb, 0xfc, 0x7f, 0xeb, 0xda, 0x32, 0xca, 0x75, 0xb1, 0xa2, 0x9e, 0xdc, 0x16, 0x19, - 0x57, 0x07, 0xcf, 0xa0, 0xb5, 0x3d, 0x95, 0x10, 0xa8, 0xe7, 0xec, 0x1d, 0x47, 0x4b, 0x2d, 0x8a, - 0xeb, 0x83, 0xbf, 0xeb, 0xd0, 0x2e, 0xf5, 0x93, 0x2f, 0xc1, 0x55, 0x2c, 0x29, 0x5b, 0x6f, 0x2a, - 0x76, 0x8d, 0xe6, 0x0f, 0xc0, 0x95, 0x45, 0x26, 0xcc, 0x0f, 0x08, 0xaa, 0xdd, 0x4a, 0xaf, 0x41, - 0xb7, 0x35, 0x79, 0x06, 0xed, 0x4c, 0x25, 0x62, 0xa9, 0x6f, 0xc5, 0x32, 0x9f, 0x05, 0xb5, 0x6e, - 0xa5, 0xe7, 0x52, 0xc8, 0xd4, 0x78, 0x8d, 0x90, 0x23, 0xf8, 0xa4, 0xe0, 0xef, 0x84, 0xe6, 0x09, - 0x9b, 0xcd, 0x8a, 0x44, 0x69, 0x56, 0xe8, 0xa0, 0x8e, 0x3f, 0x64, 0xdf, 0x6e, 0x84, 0xb3, 0x59, - 0x11, 0x1b, 0x98, 0xf4, 0xc0, 0xdf, 0xe5, 0x0a, 0x19, 0x34, 0x90, 0xda, 0x29, 0x53, 0x85, 0x34, - 0xcc, 0x85, 0x48, 0xd9, 0xa2, 0x2c, 0xea, 0x58, 0x26, 0xe2, 0xf7, 0x9a, 0x5f, 0xc3, 0xfe, 0x0e, - 0x53, 0xc8, 0xa0, 0x89, 0x44, 0xaf, 0x44, 0x14, 0xd2, 0x9a, 0x14, 0x5a, 0xa4, 0x62, 0x11, 0xb8, - 0xe8, 0x7f, 0x5b, 0x97, 0x3c, 0x48, 0x51, 0xe8, 0xf5, 0x71, 0x2d, 0x24, 0xad, 0x3d, 0x4c, 0x44, - 0xa1, 0x1f, 0x7a, 0x58, 0x73, 0x85, 0x0c, 0x00, 0xa9, 0x9d, 0x32, 0xb5, 0xec, 0xa1, 0x24, 0xda, - 0xb6, 0x4c, 0xc4, 0xef, 0x35, 0xb7, 0x1e, 0xee, 0x25, 0x1f, 0x21, 0xd1, 0x2b, 0x11, 0x85, 0x24, - 0x31, 0x38, 0x2c, 0xd5, 0x99, 0xc8, 0x03, 0xaf, 0x5b, 0xe9, 0x75, 0x06, 0x17, 0x1f, 0x93, 0xa4, - 0x7e, 0x88, 0x12, 0x74, 0x2d, 0x75, 0x78, 0x01, 0x8e, 0x45, 0x08, 0x80, 0x73, 0xf9, 0x76, 0x12, - 0xc6, 0xb1, 0xbf, 0x47, 0xda, 0xd0, 0x1c, 0x5d, 0xc7, 0xc3, 0x90, 0x8e, 0xfc, 0x8a, 0x29, 0x68, - 0x14, 0x8f, 0x7f, 0xf8, 0x29, 0xf2, 0xab, 0xa6, 0x98, 0xd0, 0xf1, 0x34, 0x1a, 0x4e, 0xfd, 0xda, - 0xe1, 0x9f, 0x75, 0x78, 0xbc, 0x39, 0x32, 0x54, 0x4a, 0xa4, 0x19, 0x43, 0xa9, 0x0f, 0x4f, 0x99, - 0x0f, 0x35, 0x25, 0x33, 0xcc, 0x98, 0x47, 0xcd, 0x92, 0x8c, 0x4b, 0xb7, 0x52, 0x43, 0x4f, 0xa7, - 0xff, 0xed, 0xa9, 0x74, 0x40, 0xff, 0x7a, 0x12, 0xf3, 0x74, 0xb2, 0x6e, 0x2d, 0x5d, 0xe5, 0x2b, - 0x80, 0xb4, 0x58, 0x49, 0x2d, 0x12, 0xb6, 0x98, 0x63, 0x0e, 0x3b, 0x83, 0x27, 0xef, 0x4b, 0x0e, - 0x91, 0x13, 0x2e, 0xe6, 0xb4, 0x95, 0x6e, 0x96, 0xe4, 0xab, 0x6d, 0xef, 0xef, 0x7c, 0xb5, 0x0e, - 0xe6, 0x7a, 0xfb, 0x7b, 0xbe, 0x22, 0xdf, 0x42, 0xcb, 0x4c, 0xf7, 0x1c, 0x95, 0x1d, 0x54, 0x3e, - 0x78, 0x5f, 0xd9, 0x4c, 0xe5, 0xdc, 0x08, 0xbb, 0xd9, 0x7a, 0x45, 0x9e, 0x6c, 0x1a, 0x8d, 0xac, - 0x0d, 0xa7, 0xdd, 0x34, 0xaa, 0x5f, 0x40, 0x73, 0xa9, 0x78, 0xc2, 0x55, 0x8e, 0xb1, 0x74, 0xa9, - 0xb3, 0x54, 0x3c, 0x52, 0xb9, 0x09, 0x85, 0xd9, 0x60, 0xb9, 0xce, 0x92, 0x82, 0xcb, 0x05, 0x5b, - 0x61, 0x24, 0x5d, 0xea, 0x2d, 0x15, 0x0f, 0x73, 0x9d, 0x51, 0x04, 0x0d, 0x4f, 0x2f, 0xf3, 0x9c, - 0x2f, 0x12, 0x55, 0xa4, 0x38, 0x05, 0x98, 0xc7, 0x16, 0xf5, 0x2c, 0x1c, 0x17, 0xa9, 0x19, 0x82, - 0x12, 0x6f, 0xa6, 0xb4, 0xe5, 0xb5, 0xcb, 0xbc, 0x91, 0xd2, 0xc8, 0xeb, 0x81, 0xcf, 0x73, 0x76, - 0xbb, 0xe0, 0xc9, 0x72, 0x26, 0x13, 0x9e, 0xa7, 0xcc, 0xa6, 0xd1, 0xa5, 0x1d, 0x8b, 0xff, 0x38, - 0x93, 0x91, 0x41, 0x0f, 0xbb, 0xe0, 0xed, 0x5c, 0x03, 0x71, 0xa0, 0x1a, 0x5e, 0xf9, 0x7b, 0xa4, - 0x09, 0xb5, 0x28, 0x9e, 0xf8, 0x95, 0xc3, 0x5f, 0xc1, 0x9f, 0xa2, 0xb8, 0xa1, 0x70, 0x9b, 0xb2, - 0xa7, 0xf6, 0xbf, 0x81, 0x2f, 0xd7, 0xfa, 0xc5, 0xba, 0x07, 0xc8, 0x67, 0xe0, 0x28, 0x66, 0xde, - 0x1b, 0x7c, 0x84, 0x3d, 0xda, 0x50, 0x6c, 0xbc, 0xd4, 0xe4, 0x31, 0x34, 0xf0, 0xf5, 0xc2, 0x27, - 0xd4, 0xa3, 0x75, 0xf3, 0x74, 0x1d, 0xfd, 0x55, 0x81, 0xd6, 0xf6, 0x22, 0xc9, 0x3e, 0xb4, 0x6f, - 0xc6, 0x37, 0x51, 0x32, 0xa4, 0x6f, 0x27, 0xd3, 0xb1, 0xbf, 0x67, 0x80, 0x30, 0x8a, 0x93, 0xe1, - 0xe5, 0x30, 0x39, 0x19, 0xbc, 0xf4, 0x2b, 0x3b, 0xc0, 0xf9, 0xc0, 0xaf, 0x96, 0x81, 0xc1, 0xd9, - 0x0b, 0xbf, 0xb6, 0x05, 0xa6, 0x14, 0x5b, 0xea, 0x3b, 0xc0, 0xf9, 0xc0, 0x6f, 0x94, 0x01, 0xd3, - 0xe2, 0x6c, 0x80, 0xd7, 0xc3, 0x37, 0xd8, 0xd2, 0xdc, 0x01, 0xce, 0x07, 0xbe, 0x5b, 0x06, 0x4c, - 0x4b, 0x0b, 0x67, 0xcb, 0x1e, 0xeb, 0x03, 0x79, 0x04, 0xee, 0x28, 0x8a, 0x4f, 0xb1, 0x6a, 0x1f, - 0xdd, 0x81, 0xbb, 0x09, 0x10, 0xe9, 0x00, 0xa0, 0xa1, 0xeb, 0x9b, 0x69, 0xf4, 0xda, 0xdf, 0x33, - 0xe3, 0xf9, 0x66, 0x74, 0x96, 0x9c, 0xbf, 0xb0, 0x13, 0x19, 0x5f, 0x85, 0x27, 0xa6, 0xa8, 0x1a, - 0x62, 0x7c, 0x15, 0x1a, 0x71, 0x53, 0xa3, 0x8b, 0x4d, 0xbd, 0x75, 0x61, 0x80, 0xd3, 0x97, 0xcf, - 0xef, 0x5d, 0x18, 0xe0, 0xec, 0x64, 0x60, 0x5d, 0x5c, 0x7e, 0xf7, 0xf3, 0xab, 0xb9, 0xd8, 0x84, - 0x39, 0xc3, 0x0f, 0xed, 0x37, 0x6c, 0xce, 0x73, 0x7d, 0x7c, 0x77, 0x7a, 0x8c, 0xc3, 0x75, 0xfc, - 0xf0, 0x13, 0x7c, 0x71, 0x27, 0x65, 0x82, 0xab, 0x5b, 0x07, 0x19, 0xa7, 0xff, 0x06, 0x00, 0x00, - 0xff, 0xff, 0x4c, 0x93, 0x85, 0x5e, 0xa7, 0x07, 0x00, 0x00, + // 962 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xdf, 0x6e, 0xdb, 0xb6, + 0x17, 0x8e, 0xff, 0xc9, 0xf2, 0x71, 0xe5, 0xea, 0xc7, 0xfe, 0xb6, 0x69, 0x69, 0x87, 0x1a, 0xbe, + 0x18, 0x8c, 0x02, 0x73, 0x10, 0xa7, 0xe9, 0x9a, 0x66, 0x37, 0x8a, 0x2d, 0x34, 0xc1, 0xd6, 0xd8, + 0xa0, 0xbc, 0x01, 0xdd, 0x2e, 0x04, 0x46, 0xe6, 0x3c, 0x61, 0xae, 0x48, 0x88, 0x74, 0x50, 0xdf, + 0xed, 0x41, 0xf6, 0x50, 0x7b, 0x87, 0x01, 0x7b, 0x8e, 0x81, 0x87, 0xb6, 0x23, 0xa7, 0x1d, 0x30, + 0xec, 0xc6, 0xe0, 0xf9, 0xf8, 0x9d, 0x8f, 0xfa, 0xcc, 0x73, 0x0e, 0xe1, 0xc9, 0x32, 0x5b, 0x30, + 0x2d, 0x8e, 0x6e, 0xa5, 0x3c, 0xca, 0xa4, 0xe2, 0xa9, 0xfd, 0x1d, 0xc8, 0x42, 0x68, 0x41, 0x7c, + 0xbb, 0x3b, 0xb8, 0x95, 0x72, 0x80, 0x78, 0xef, 0x2f, 0x07, 0x3e, 0x8d, 0x79, 0xba, 0x2a, 0x32, + 0xbd, 0x9e, 0x8a, 0x65, 0x96, 0xae, 0xc7, 0x4c, 0xb3, 0x1b, 0xa6, 0x38, 0xf9, 0x3f, 0x34, 0xb2, + 0x7c, 0xce, 0xdf, 0x07, 0x95, 0x6e, 0xa5, 0xef, 0x51, 0x1b, 0x10, 0x0a, 0x90, 0xe5, 0x9a, 0x17, + 0x3f, 0xb3, 0x94, 0xab, 0xa0, 0xda, 0xad, 0xf5, 0xdb, 0xc3, 0xe1, 0xe0, 0xbe, 0xee, 0xe0, 0xe3, + 0x9a, 0x83, 0xab, 0x6d, 0x2a, 0x2d, 0xa9, 0x90, 0x9f, 0xa0, 0x23, 0x91, 0x97, 0xf0, 0x5c, 0x17, + 0x19, 0x57, 0x41, 0x0d, 0x75, 0x9f, 0xff, 0x6b, 0x5d, 0x1b, 0x46, 0xb9, 0x2e, 0xd6, 0xd4, 0x93, + 0xbb, 0x20, 0xe3, 0xea, 0xf0, 0x29, 0xb4, 0x76, 0xa7, 0x12, 0x02, 0xf5, 0x9c, 0xbd, 0xe3, 0x68, + 0xa9, 0x45, 0x71, 0x7d, 0xf8, 0x67, 0x1d, 0xda, 0xa5, 0x7c, 0xf2, 0x39, 0xb8, 0x8a, 0x25, 0x65, + 0xeb, 0x4d, 0xc5, 0xae, 0xd0, 0xfc, 0x21, 0xb8, 0xb2, 0xc8, 0x84, 0xf9, 0x80, 0xa0, 0xda, 0xad, + 0xf4, 0x1b, 0x74, 0x17, 0x93, 0xa7, 0xd0, 0xce, 0x54, 0x22, 0x56, 0xfa, 0x46, 0xac, 0xf2, 0x79, + 0x50, 0xeb, 0x56, 0xfa, 0x2e, 0x85, 0x4c, 0x4d, 0x36, 0x08, 0x79, 0x06, 0xff, 0x2b, 0xf8, 0x3b, + 0xa1, 0x79, 0xc2, 0xe6, 0xf3, 0x22, 0x51, 0x9a, 0x15, 0x3a, 0xa8, 0xe3, 0x87, 0x3c, 0xb4, 0x1b, + 0xe1, 0x7c, 0x5e, 0xc4, 0x06, 0x26, 0x7d, 0xf0, 0xf7, 0xb9, 0x42, 0x06, 0x0d, 0xa4, 0x76, 0xca, + 0x54, 0x21, 0x0d, 0x73, 0x29, 0x52, 0xb6, 0x2c, 0x8b, 0x3a, 0x96, 0x89, 0xf8, 0x9d, 0xe6, 0x97, + 0xf0, 0x70, 0x8f, 0x29, 0x64, 0xd0, 0x44, 0xa2, 0x57, 0x22, 0x0a, 0x69, 0x4d, 0x0a, 0x2d, 0x52, + 0xb1, 0x0c, 0x5c, 0xf4, 0xbf, 0x8b, 0x4b, 0x1e, 0xa4, 0x28, 0xf4, 0xe6, 0xb8, 0x16, 0x92, 0x36, + 0x1e, 0xa6, 0xa2, 0xd0, 0xf7, 0x3d, 0x6c, 0xb8, 0x42, 0x06, 0x80, 0xd4, 0x4e, 0x99, 0x5a, 0xf6, + 0x50, 0x12, 0x6d, 0x5b, 0x26, 0xe2, 0x77, 0x9a, 0x3b, 0x0f, 0x77, 0x92, 0x0f, 0x90, 0xe8, 0x95, + 0x88, 0x42, 0x92, 0x18, 0x1c, 0x96, 0xea, 0x4c, 0xe4, 0x81, 0xd7, 0xad, 0xf4, 0x3b, 0xc3, 0xf3, + 0xff, 0x52, 0x49, 0x83, 0x10, 0x25, 0xe8, 0x46, 0xaa, 0x77, 0x0e, 0x8e, 0x45, 0x08, 0x80, 0x73, + 0xf1, 0x76, 0x1a, 0xc6, 0xb1, 0x7f, 0x40, 0xda, 0xd0, 0x1c, 0x5f, 0xc5, 0xa3, 0x90, 0x8e, 0xfd, + 0x8a, 0x09, 0x68, 0x14, 0x4f, 0xbe, 0xfb, 0x21, 0xf2, 0xab, 0x26, 0x98, 0xd2, 0xc9, 0x2c, 0x1a, + 0xcd, 0xfc, 0x5a, 0xef, 0xf7, 0x3a, 0x3c, 0xda, 0x1e, 0x19, 0x2a, 0x25, 0xd2, 0x8c, 0xa1, 0xd4, + 0xc7, 0xbb, 0xcc, 0x87, 0x9a, 0x92, 0x19, 0xd6, 0x98, 0x47, 0xcd, 0x92, 0x4c, 0x4a, 0xb7, 0x52, + 0x43, 0x4f, 0x27, 0xff, 0xec, 0xa9, 0x74, 0xc0, 0xe0, 0x6a, 0x1a, 0xf3, 0x74, 0xba, 0x49, 0x2d, + 0x5d, 0xe5, 0x2b, 0x80, 0xb4, 0x58, 0x4b, 0x2d, 0x12, 0xb6, 0x5c, 0x60, 0x1d, 0x76, 0x86, 0x8f, + 0x3f, 0x94, 0x1c, 0x21, 0x27, 0x5c, 0x2e, 0x68, 0x2b, 0xdd, 0x2e, 0xc9, 0x17, 0xbb, 0xdc, 0x5f, + 0xf9, 0x7a, 0x53, 0x98, 0x9b, 0xed, 0x6f, 0xf9, 0x9a, 0x7c, 0x0d, 0x2d, 0xd3, 0xdd, 0x0b, 0x54, + 0x76, 0x50, 0xf9, 0xf0, 0x43, 0x65, 0xd3, 0x95, 0x0b, 0x23, 0xec, 0x66, 0x9b, 0x15, 0x79, 0xbc, + 0x4d, 0x34, 0xb2, 0xb6, 0x38, 0xed, 0xa6, 0x51, 0xfd, 0x0c, 0x9a, 0x2b, 0xc5, 0x13, 0xae, 0x72, + 0x2c, 0x4b, 0x97, 0x3a, 0x2b, 0xc5, 0x23, 0x95, 0x9b, 0xa2, 0x30, 0x1b, 0x2c, 0xd7, 0x59, 0x52, + 0x70, 0xb9, 0x64, 0x6b, 0x2c, 0x49, 0x97, 0x7a, 0x2b, 0xc5, 0xc3, 0x5c, 0x67, 0x14, 0x41, 0xc3, + 0xd3, 0xab, 0x3c, 0xe7, 0xcb, 0x44, 0x15, 0x29, 0x76, 0x01, 0xd6, 0x63, 0x8b, 0x7a, 0x16, 0x8e, + 0x8b, 0xd4, 0x34, 0x41, 0x89, 0x37, 0x57, 0xda, 0xf2, 0xda, 0x65, 0xde, 0x58, 0x69, 0xe4, 0xf5, + 0xc1, 0xe7, 0x39, 0xbb, 0x59, 0xf2, 0x64, 0x35, 0x97, 0x09, 0xcf, 0x53, 0x66, 0xab, 0xd1, 0xa5, + 0x1d, 0x8b, 0x7f, 0x3f, 0x97, 0x91, 0x41, 0x7b, 0x5d, 0xf0, 0xf6, 0xae, 0x81, 0x38, 0x50, 0x0d, + 0x2f, 0xfd, 0x03, 0xd2, 0x84, 0x5a, 0x14, 0x4f, 0xfd, 0x4a, 0xef, 0xb7, 0x0a, 0xf8, 0x33, 0x54, + 0x37, 0x1c, 0x6e, 0xcb, 0xec, 0x89, 0xfd, 0x3b, 0x70, 0x74, 0x6d, 0x46, 0xd6, 0x1d, 0x40, 0x3e, + 0x01, 0x47, 0x31, 0x33, 0x70, 0x70, 0x0a, 0x7b, 0xb4, 0xa1, 0xd8, 0x64, 0xa5, 0xc9, 0x23, 0x68, + 0xe0, 0xf8, 0xc2, 0x19, 0xea, 0xd1, 0xba, 0x99, 0x5d, 0xa4, 0x07, 0x5e, 0xce, 0xdf, 0xeb, 0xe4, + 0x17, 0x21, 0xad, 0x21, 0x3b, 0x77, 0xda, 0x06, 0xbc, 0x14, 0xd2, 0xd8, 0x79, 0xf6, 0x47, 0x05, + 0x5a, 0xbb, 0xdb, 0x26, 0x0f, 0xa1, 0x7d, 0x3d, 0xb9, 0x8e, 0x92, 0x11, 0x7d, 0x3b, 0x9d, 0x4d, + 0xfc, 0x03, 0x03, 0x84, 0x51, 0x9c, 0x8c, 0x2e, 0x46, 0xc9, 0xf1, 0xf0, 0xa5, 0x5f, 0xd9, 0x03, + 0xce, 0x86, 0x7e, 0xb5, 0x0c, 0x0c, 0x4f, 0x5f, 0xf8, 0xb5, 0x1d, 0x30, 0xa3, 0x98, 0x52, 0xdf, + 0x03, 0xce, 0x86, 0x7e, 0xa3, 0x0c, 0x98, 0x14, 0x67, 0x0b, 0xbc, 0x1e, 0xbd, 0xc1, 0x94, 0xe6, + 0x1e, 0x70, 0x36, 0xf4, 0xdd, 0x32, 0x60, 0x52, 0x5a, 0xd8, 0x80, 0xf6, 0x58, 0x1f, 0xc8, 0x03, + 0x70, 0xc7, 0x51, 0x7c, 0x82, 0x51, 0xfb, 0xd9, 0x2d, 0xb8, 0xdb, 0x2a, 0x23, 0x1d, 0x00, 0x34, + 0x74, 0x75, 0x3d, 0x8b, 0x5e, 0xfb, 0x07, 0xa6, 0x87, 0xdf, 0x8c, 0x4f, 0x93, 0xb3, 0x17, 0xb6, + 0x6d, 0xe3, 0xcb, 0xf0, 0xd8, 0x04, 0x55, 0x43, 0x8c, 0x2f, 0x43, 0x23, 0x6e, 0x62, 0x74, 0xb1, + 0x8d, 0x77, 0x2e, 0x0c, 0x70, 0xf2, 0xf2, 0xf9, 0x9d, 0x0b, 0x03, 0x9c, 0x1e, 0x0f, 0xad, 0x8b, + 0x8b, 0x6f, 0x7e, 0x7c, 0xb5, 0x10, 0xdb, 0x8a, 0xcf, 0xf0, 0x35, 0xfe, 0x8a, 0x2d, 0x78, 0xae, + 0x8f, 0x6e, 0x4f, 0x8e, 0xb0, 0x03, 0x8f, 0xee, 0xbf, 0xd3, 0xe7, 0xb7, 0x52, 0x26, 0xb8, 0xba, + 0x71, 0x90, 0x71, 0xf2, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x42, 0xa2, 0x13, 0x48, 0xcc, 0x07, + 0x00, 0x00, } diff --git a/proto/ligato/vpp/ipsec/ipsec.proto b/proto/ligato/vpp/ipsec/ipsec.proto index 1fcdb20590..b220044b88 100644 --- a/proto/ligato/vpp/ipsec/ipsec.proto +++ b/proto/ligato/vpp/ipsec/ipsec.proto @@ -106,4 +106,7 @@ message TunnelProtection { // Inbound security associations identified by SA index. repeated uint32 sa_in = 3; + + // (Optional) Next hop IP address, used for multipoint tunnels. + string next_hop_addr = 4; } \ No newline at end of file diff --git a/proto/ligato/vpp/ipsec/models.go b/proto/ligato/vpp/ipsec/models.go index 07cc7ce4a2..96d2ce1406 100644 --- a/proto/ligato/vpp/ipsec/models.go +++ b/proto/ligato/vpp/ipsec/models.go @@ -42,7 +42,8 @@ var ( Version: "v2", Type: "tun-protect", }, models.WithNameTemplate( - `{{.Interface}}`, + `{{.Interface}}`+ + `{{if .NextHopAddr}}/nh/{{.NextHopAddr}}{{end}}`, )) ) diff --git a/proto/ligato/vpp/l3/models.go b/proto/ligato/vpp/l3/models.go index a394b97821..231f1883e6 100644 --- a/proto/ligato/vpp/l3/models.go +++ b/proto/ligato/vpp/l3/models.go @@ -80,6 +80,14 @@ var ( }, models.WithNameTemplate( `{{.Interface}}/protocol/{{.Protocol}}`, )) + + ModelTeib = models.Register(&TeibEntry{}, models.Spec{ + Module: ModuleName, + Type: "teib", + Version: "v2", + }, models.WithNameTemplate( + `{{.Interface}}/peer/{{.PeerAddr}}`, + )) ) // ProxyARPKey returns key for global proxy arp diff --git a/proto/ligato/vpp/l3/teib.pb.go b/proto/ligato/vpp/l3/teib.pb.go new file mode 100644 index 0000000000..32b4645315 --- /dev/null +++ b/proto/ligato/vpp/l3/teib.pb.go @@ -0,0 +1,112 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: ligato/vpp/l3/teib.proto + +package vpp_l3 + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +// TeibEntry represents an tunnel endpoint information base entry. +type TeibEntry struct { + // Interface references a tunnel interface this TEIB entry is linked to. + Interface string `protobuf:"bytes,1,opt,name=interface,proto3" json:"interface,omitempty"` + // IP address of the peer. + PeerAddr string `protobuf:"bytes,2,opt,name=peer_addr,json=peerAddr,proto3" json:"peer_addr,omitempty"` + // Next hop IP address. + NextHopAddr string `protobuf:"bytes,3,opt,name=next_hop_addr,json=nextHopAddr,proto3" json:"next_hop_addr,omitempty"` + // VRF ID used to reach the next hop. + VrfId uint32 `protobuf:"varint,4,opt,name=vrf_id,json=vrfId,proto3" json:"vrf_id,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *TeibEntry) Reset() { *m = TeibEntry{} } +func (m *TeibEntry) String() string { return proto.CompactTextString(m) } +func (*TeibEntry) ProtoMessage() {} +func (*TeibEntry) Descriptor() ([]byte, []int) { + return fileDescriptor_43413ef30fbb968b, []int{0} +} + +func (m *TeibEntry) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_TeibEntry.Unmarshal(m, b) +} +func (m *TeibEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_TeibEntry.Marshal(b, m, deterministic) +} +func (m *TeibEntry) XXX_Merge(src proto.Message) { + xxx_messageInfo_TeibEntry.Merge(m, src) +} +func (m *TeibEntry) XXX_Size() int { + return xxx_messageInfo_TeibEntry.Size(m) +} +func (m *TeibEntry) XXX_DiscardUnknown() { + xxx_messageInfo_TeibEntry.DiscardUnknown(m) +} + +var xxx_messageInfo_TeibEntry proto.InternalMessageInfo + +func (m *TeibEntry) GetInterface() string { + if m != nil { + return m.Interface + } + return "" +} + +func (m *TeibEntry) GetPeerAddr() string { + if m != nil { + return m.PeerAddr + } + return "" +} + +func (m *TeibEntry) GetNextHopAddr() string { + if m != nil { + return m.NextHopAddr + } + return "" +} + +func (m *TeibEntry) GetVrfId() uint32 { + if m != nil { + return m.VrfId + } + return 0 +} + +func init() { + proto.RegisterType((*TeibEntry)(nil), "ligato.vpp.l3.TeibEntry") +} + +func init() { proto.RegisterFile("ligato/vpp/l3/teib.proto", fileDescriptor_43413ef30fbb968b) } + +var fileDescriptor_43413ef30fbb968b = []byte{ + // 204 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x8f, 0x3d, 0x4b, 0x04, 0x31, + 0x14, 0x45, 0x89, 0x1f, 0x8b, 0x89, 0x4c, 0x13, 0x10, 0x02, 0x5a, 0x2c, 0x5b, 0x6d, 0x63, 0x52, + 0x44, 0x6c, 0xac, 0x14, 0x04, 0x6d, 0x17, 0x2b, 0x9b, 0x90, 0x31, 0x6f, 0xc6, 0x40, 0x48, 0x1e, + 0x8f, 0x10, 0xb4, 0xf4, 0x9f, 0xcb, 0x64, 0x04, 0xd9, 0xf6, 0x9e, 0x53, 0x9c, 0x2b, 0x54, 0x8a, + 0xb3, 0xaf, 0xc5, 0x34, 0x44, 0x93, 0xac, 0xa9, 0x10, 0x47, 0x8d, 0x54, 0x6a, 0x91, 0xc3, 0x4a, + 0x74, 0x43, 0xd4, 0xc9, 0xee, 0x7e, 0x98, 0xe0, 0x6f, 0x10, 0xc7, 0xe7, 0x5c, 0xe9, 0x5b, 0xde, + 0x08, 0x1e, 0x73, 0x05, 0x9a, 0xfc, 0x07, 0x28, 0xb6, 0x65, 0x7b, 0x7e, 0xf8, 0x1f, 0xe4, 0xb5, + 0xe0, 0x08, 0x40, 0xce, 0x87, 0x40, 0xea, 0xa4, 0xd3, 0x8b, 0x65, 0x78, 0x0c, 0x81, 0xe4, 0x4e, + 0x0c, 0x19, 0xbe, 0xaa, 0xfb, 0x2c, 0xb8, 0x0a, 0xa7, 0x5d, 0xb8, 0x5c, 0xc6, 0x97, 0x82, 0xdd, + 0xb9, 0x12, 0x9b, 0x46, 0x93, 0x8b, 0x41, 0x9d, 0x6d, 0xd9, 0x7e, 0x38, 0x9c, 0x37, 0x9a, 0x5e, + 0xc3, 0xd3, 0xfd, 0xfb, 0xdd, 0x5c, 0xf4, 0x5f, 0x57, 0xec, 0xd1, 0xb7, 0x7e, 0x86, 0x5c, 0x4d, + 0xb3, 0xa6, 0x57, 0x9b, 0xa3, 0x3b, 0x0f, 0x0d, 0xd1, 0x25, 0x3b, 0x6e, 0x3a, 0xb3, 0xbf, 0x01, + 0x00, 0x00, 0xff, 0xff, 0x65, 0xf5, 0xe1, 0xfd, 0xed, 0x00, 0x00, 0x00, +} diff --git a/proto/ligato/vpp/l3/teib.proto b/proto/ligato/vpp/l3/teib.proto new file mode 100644 index 0000000000..67fb5ea05c --- /dev/null +++ b/proto/ligato/vpp/l3/teib.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; + +package ligato.vpp.l3; + +option go_package = "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3;vpp_l3"; + +// TeibEntry represents an tunnel endpoint information base entry. +message TeibEntry { + // Interface references a tunnel interface this TEIB entry is linked to. + string interface = 1; + + // IP address of the peer. + string peer_addr = 2; + + // Next hop IP address. + string next_hop_addr = 3; + + // VRF ID used to reach the next hop. + uint32 vrf_id = 4; +} diff --git a/tests/e2e/070_ipsec_test.go b/tests/e2e/070_ipsec_test.go index 7d38ead110..b8982c3e1d 100644 --- a/tests/e2e/070_ipsec_test.go +++ b/tests/e2e/070_ipsec_test.go @@ -23,6 +23,7 @@ import ( "go.ligato.io/vpp-agent/v3/proto/ligato/kvscheduler" vpp_interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces" vpp_ipsec "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/ipsec" + vpp_l3 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3" ) func TestIPSec(t *testing.T) { @@ -168,3 +169,150 @@ func TestIPSec(t *testing.T) { Eventually(ctx.getValueStateClb(ipipTun)).Should(Equal(kvscheduler.ValueState_NONEXISTENT), "IPIP tunnel was not removed") } + +func TestIPSecMultiPoint(t *testing.T) { + ctx := setupE2E(t) + defer ctx.teardownE2E() + + if ctx.vppRelease < "20.05" { + t.Skipf("IPSec MP: skipped for VPP < 20.05 (%s)", ctx.vppRelease) + } + + const ( + msName = "microservice1" + tunnelIfName = "ipsec-tunnel" + ) + + ipipTun := &vpp_interfaces.Interface{ + Name: tunnelIfName, + Enabled: true, + Type: vpp_interfaces.Interface_IPIP_TUNNEL, + + Link: &vpp_interfaces.Interface_Ipip{ + Ipip: &vpp_interfaces.IPIPLink{ + SrcAddr: "1.2.3.4", + TunnelMode: vpp_interfaces.IPIPLink_POINT_TO_MULTIPOINT, + }, + }, + IpAddresses: []string{"192.168.0.1/24"}, + } + saOut1 := &vpp_ipsec.SecurityAssociation{ + Index: 10, + Spi: 123, + Protocol: vpp_ipsec.SecurityAssociation_ESP, + CryptoAlg: vpp_ipsec.CryptoAlg_AES_CBC_128, + CryptoKey: "d9a4ec50aed76f1bf80bc915d8fcfe1c", + IntegAlg: vpp_ipsec.IntegAlg_SHA1_96, + IntegKey: "bf9b150aaf5c2a87d79898b11eabd055e70abdbe", + EnableUdpEncap: true, + } + saIn1 := &vpp_ipsec.SecurityAssociation{ + Index: 20, + Spi: 456, + Protocol: vpp_ipsec.SecurityAssociation_ESP, + CryptoAlg: vpp_ipsec.CryptoAlg_AES_CBC_128, + CryptoKey: "d9a4ec50aed76f1bf80bc915d8fcfe1c", + IntegAlg: vpp_ipsec.IntegAlg_SHA1_96, + IntegKey: "bf9b150aaf5c2a87d79898b11eabd055e70abdbe", + EnableUdpEncap: true, + } + saOut2 := &vpp_ipsec.SecurityAssociation{ + Index: 30, + Spi: 789, + Protocol: vpp_ipsec.SecurityAssociation_ESP, + CryptoAlg: vpp_ipsec.CryptoAlg_AES_CBC_128, + CryptoKey: "d9a4ec50aed76f1bf80bc915d8fcfe1c", + IntegAlg: vpp_ipsec.IntegAlg_SHA1_96, + IntegKey: "bf9b150aaf5c2a87d79898b11eabd055e70abdbe", + EnableUdpEncap: true, + } + saIn2 := &vpp_ipsec.SecurityAssociation{ + Index: 40, + Spi: 111, + Protocol: vpp_ipsec.SecurityAssociation_ESP, + CryptoAlg: vpp_ipsec.CryptoAlg_AES_CBC_128, + CryptoKey: "d9a4ec50aed76f1bf80bc915d8fcfe1c", + IntegAlg: vpp_ipsec.IntegAlg_SHA1_96, + IntegKey: "bf9b150aaf5c2a87d79898b11eabd055e70abdbe", + EnableUdpEncap: true, + } + tp1 := &vpp_ipsec.TunnelProtection{ + Interface: tunnelIfName, + SaOut: []uint32{saOut1.Index}, + SaIn: []uint32{saIn1.Index}, + NextHopAddr: "192.168.0.2", + } + tp2 := &vpp_ipsec.TunnelProtection{ + Interface: tunnelIfName, + SaOut: []uint32{saOut2.Index}, + SaIn: []uint32{saIn2.Index}, + NextHopAddr: "192.168.0.3", + } + teib1 := &vpp_l3.TeibEntry{ + Interface: tunnelIfName, + PeerAddr: tp1.NextHopAddr, + NextHopAddr: "8.8.8.8", + } + teib2 := &vpp_l3.TeibEntry{ + Interface: tunnelIfName, + PeerAddr: tp2.NextHopAddr, + NextHopAddr: "8.8.8.9", + } + + ctx.startMicroservice(msName) + req := ctx.grpcClient.ChangeRequest() + err := req.Update( + ipipTun, + saOut1, saIn1, saOut2, saIn2, + tp1, tp2, + teib1, teib2, + ).Send(context.Background()) + Expect(err).ToNot(HaveOccurred(), "Sending change request failed with err") + + Eventually(ctx.getValueStateClb(ipipTun)).Should(Equal(kvscheduler.ValueState_CONFIGURED), + "IPIP tunnel is not configured") + Eventually(ctx.getValueStateClb(saOut1)).Should(Equal(kvscheduler.ValueState_CONFIGURED), + "OUT SA 1 is not configured") + Eventually(ctx.getValueStateClb(saIn1)).Should(Equal(kvscheduler.ValueState_CONFIGURED), + "IN SA 1 is not configured") + Eventually(ctx.getValueStateClb(saOut2)).Should(Equal(kvscheduler.ValueState_CONFIGURED), + "OUT SA 2 is not configured") + Eventually(ctx.getValueStateClb(saIn2)).Should(Equal(kvscheduler.ValueState_CONFIGURED), + "IN SA 2 is not configured") + Eventually(ctx.getValueStateClb(tp1)).Should(Equal(kvscheduler.ValueState_CONFIGURED), + "tunnel protection 1 is not configured") + Eventually(ctx.getValueStateClb(tp2)).Should(Equal(kvscheduler.ValueState_CONFIGURED), + "tunnel protection 2 is not configured") + Eventually(ctx.getValueStateClb(teib1)).Should(Equal(kvscheduler.ValueState_CONFIGURED), + "TEIB 1 is not configured") + Eventually(ctx.getValueStateClb(teib2)).Should(Equal(kvscheduler.ValueState_CONFIGURED), + "TEIB 2 is not configured") + + req3 := ctx.grpcClient.ChangeRequest() + err = req3.Delete( + ipipTun, + saOut1, saIn1, saOut2, saIn2, + tp1, tp2, + teib1, teib2, + ).Send(context.Background()) + Expect(err).ToNot(HaveOccurred(), "Sending change request failed with err") + + Eventually(ctx.getValueStateClb(teib1)).Should(Equal(kvscheduler.ValueState_NONEXISTENT), + "TEIB 1 was not removed") + Eventually(ctx.getValueStateClb(teib2)).Should(Equal(kvscheduler.ValueState_NONEXISTENT), + "TEIB 2 was not removed") + Eventually(ctx.getValueStateClb(saOut1)).Should(Equal(kvscheduler.ValueState_NONEXISTENT), + "OUT SA 1 was not removed") + Eventually(ctx.getValueStateClb(saIn1)).Should(Equal(kvscheduler.ValueState_NONEXISTENT), + "IN SA 1 was not removed") + Eventually(ctx.getValueStateClb(saOut2)).Should(Equal(kvscheduler.ValueState_NONEXISTENT), + "OUT SA 2 was not removed") + Eventually(ctx.getValueStateClb(saIn2)).Should(Equal(kvscheduler.ValueState_NONEXISTENT), + "IN SA 2 was not removed") + Eventually(ctx.getValueStateClb(tp2)).Should(Equal(kvscheduler.ValueState_NONEXISTENT), + "tunnel protection 2 was not removed") + Eventually(ctx.getValueStateClb(tp1)).Should(Equal(kvscheduler.ValueState_NONEXISTENT), + "tunnel protection 1 was not removed") + Eventually(ctx.getValueStateClb(ipipTun)).Should(Equal(kvscheduler.ValueState_NONEXISTENT), + "IPIP tunnel was not removed") +} diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 3084a37272..3b3bff3bb3 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -208,7 +208,7 @@ func setupE2E(t *testing.T) *TestCtx { version = strings.SplitN(version, " ", 3)[1] testCtx.vppVersion = version if len(version) > 5 { - testCtx.vppRelease = version[1:5] + testCtx.vppRelease = version[1:6] } t.Logf("VPP version: %v", testCtx.vppVersion) } diff --git a/tests/integration/vpp/120_ipip_test.go b/tests/integration/vpp/120_ipip_test.go index ce50dd1ae9..524fa8b57a 100644 --- a/tests/integration/vpp/120_ipip_test.go +++ b/tests/integration/vpp/120_ipip_test.go @@ -30,11 +30,15 @@ func TestIPIP(t *testing.T) { ctx := setupVPP(t) defer ctx.teardownVPP() - dumpAPIOk := true + p2mpSupported := true // determines point-to-multipoint support + release := ctx.versionInfo.Release() if release < "20.01" { t.Skipf("IPIP: skipped for VPP < 20.01 (%s)", release) } + if release < "20.05" { + p2mpSupported = false // point-to-multipoint support comes in VPP 20.05 + } h := ifplugin_vppcalls.CompatibleInterfaceVppHandler(ctx.vppClient, logrus.NewLogger("test")) @@ -75,6 +79,22 @@ func TestIPIP(t *testing.T) { }, shouldFail: true, }, + { + name: "Create p2p IPIP tunnel with missing dst address", + ipip: &interfaces.IPIPLink{ + SrcAddr: "20.30.40.50", + TunnelMode: interfaces.IPIPLink_POINT_TO_POINT, + }, + shouldFail: true, + }, + { + name: "Create p2mp IPIP tunnel (dst address not specified)", + ipip: &interfaces.IPIPLink{ + SrcAddr: "20.30.40.50", + TunnelMode: interfaces.IPIPLink_POINT_TO_MULTIPOINT, + }, + shouldFail: false, + }, { name: "Create 2 IPIP tunnels (IPv4)", ipip: &interfaces.IPIPLink{ @@ -102,6 +122,9 @@ func TestIPIP(t *testing.T) { } for i, test := range tests { t.Run(test.name, func(t *testing.T) { + if !p2mpSupported && test.ipip.TunnelMode == interfaces.IPIPLink_POINT_TO_MULTIPOINT { + t.Skipf("IPIP: p2mp skipped for VPP < 20.05 (%s)", release) + } ifName := fmt.Sprintf("ipip%d", i) ifIdx, err := h.AddIpipTunnel(ifName, 0, test.ipip) @@ -136,35 +159,34 @@ func TestIPIP(t *testing.T) { } } - if dumpAPIOk { - ifaces, err := h.DumpInterfaces(ctx.Ctx) - if err != nil { - t.Fatalf("dumping interfaces failed: %v", err) - } - iface, ok := ifaces[ifIdx] + ifaces, err := h.DumpInterfaces(ctx.Ctx) + if err != nil { + t.Fatalf("dumping interfaces failed: %v", err) + } + iface, ok := ifaces[ifIdx] + if !ok { + t.Fatalf("IPIP interface was not found in dump") + } + if test.ipip2 != nil { + _, ok := ifaces[ifIdx2] if !ok { - t.Fatalf("IPIP interface was not found in dump") - } - if test.ipip2 != nil { - _, ok := ifaces[ifIdx2] - if !ok { - t.Fatalf("IPIP interface2 was not found in dump") - } + t.Fatalf("IPIP interface2 was not found in dump") } + } - if iface.Interface.GetType() != interfaces.Interface_IPIP_TUNNEL { - t.Fatalf("Interface is not an IPIP tunnel") - } + if iface.Interface.GetType() != interfaces.Interface_IPIP_TUNNEL { + t.Fatalf("Interface is not an IPIP tunnel") + } - ipip := iface.Interface.GetIpip() - if test.ipip.SrcAddr != ipip.SrcAddr { - t.Fatalf("expected source address <%s>, got: <%s>", test.ipip.SrcAddr, ipip.SrcAddr) - } - if test.ipip.DstAddr != ipip.DstAddr { - t.Fatalf("expected destination address <%s>, got: <%s>", test.ipip.DstAddr, ipip.DstAddr) - } - } else { - t.Logf("IPIP: DumpInterfaces skipped because of a broken API in VPP %s", ctx.versionInfo.Version) + ipip := iface.Interface.GetIpip() + if test.ipip.TunnelMode != ipip.TunnelMode { + t.Fatalf("expected tunnel mode <%v>, got: <%v>", test.ipip.TunnelMode, ipip.TunnelMode) + } + if test.ipip.SrcAddr != ipip.SrcAddr { + t.Fatalf("expected source address <%s>, got: <%s>", test.ipip.SrcAddr, ipip.SrcAddr) + } + if test.ipip.DstAddr != ipip.DstAddr { + t.Fatalf("expected destination address <%s>, got: <%s>", test.ipip.DstAddr, ipip.DstAddr) } err = h.DelIpipTunnel(ifName, ifIdx) @@ -178,19 +200,17 @@ func TestIPIP(t *testing.T) { } } - if dumpAPIOk { - ifaces, err := h.DumpInterfaces(ctx.Ctx) - if err != nil { - t.Fatalf("dumping interfaces failed: %v", err) - } + ifaces, err = h.DumpInterfaces(ctx.Ctx) + if err != nil { + t.Fatalf("dumping interfaces failed: %v", err) + } - if _, ok := ifaces[ifIdx]; ok { - t.Fatalf("IPIP interface was found in dump after removing") - } - if test.ipip2 != nil { - if _, ok := ifaces[ifIdx2]; ok { - t.Fatalf("IPIP interface2 was found in dump after removing") - } + if _, ok := ifaces[ifIdx]; ok { + t.Fatalf("IPIP interface was found in dump after removing") + } + if test.ipip2 != nil { + if _, ok := ifaces[ifIdx2]; ok { + t.Fatalf("IPIP interface2 was found in dump after removing") } } }) diff --git a/tests/integration/vpp/130_ipsec_test.go b/tests/integration/vpp/130_ipsec_test.go index be13aacd5e..f82a8d0a85 100644 --- a/tests/integration/vpp/130_ipsec_test.go +++ b/tests/integration/vpp/130_ipsec_test.go @@ -34,14 +34,16 @@ func TestIPSec(t *testing.T) { ctx := setupVPP(t) defer ctx.teardownVPP() - dumpAPIOk := true + p2mpSupported := true // determines point-to-multipoint support + saDumpAPIOk := true // determines if SA dump API is working + release := ctx.versionInfo.Release() if release < "20.01" { t.Skipf("IPSec: skipped for VPP < 20.01 (%s)", release) } - if release < "20.04" { - // tunnel protection dump broken in VPP 20.01 - dumpAPIOk = false + if release < "20.05" { + saDumpAPIOk = false // tunnel protection SA dump broken in VPP 20.01 + p2mpSupported = false // point-to-multipoint support comes in VPP 20.05 } ifIndexes := ifaceidx.NewIfaceIndex(logrus.NewLogger("test"), "test-ifidx") @@ -53,6 +55,7 @@ func TestIPSec(t *testing.T) { ipip *interfaces.IPIPLink saOut *ipsec.SecurityAssociation saIn *ipsec.SecurityAssociation + tp *ipsec.TunnelProtection }{ { name: "Create IPSec tunnel (IPv4)", @@ -80,6 +83,10 @@ func TestIPSec(t *testing.T) { IntegKey: "bf9b150aaf5c2a87d79898b11eabd055e70abdbe", EnableUdpEncap: true, }, + tp: &ipsec.TunnelProtection{ + SaOut: []uint32{10}, + SaIn: []uint32{20}, + }, }, { name: "Create IPSec tunnel (IPv6)", @@ -105,10 +112,49 @@ func TestIPSec(t *testing.T) { IntegAlg: ipsec.IntegAlg_SHA1_96, IntegKey: "bf9b150aaf5c2a87d79898b11eabd055e70abdbe", }, + tp: &ipsec.TunnelProtection{ + SaOut: []uint32{1}, + SaIn: []uint32{2}, + }, + }, + { + name: "Create multipoint IPSec tunnel", + ipip: &interfaces.IPIPLink{ + SrcAddr: "20.30.40.50", + TunnelMode: interfaces.IPIPLink_POINT_TO_MULTIPOINT, + }, + saOut: &ipsec.SecurityAssociation{ + Index: 100, + Spi: 123, + Protocol: ipsec.SecurityAssociation_ESP, + CryptoAlg: ipsec.CryptoAlg_AES_CBC_128, + CryptoKey: "d9a4ec50aed76f1bf80bc915d8fcfe1c", + IntegAlg: ipsec.IntegAlg_SHA1_96, + IntegKey: "bf9b150aaf5c2a87d79898b11eabd055e70abdbe", + EnableUdpEncap: true, + }, + saIn: &ipsec.SecurityAssociation{ + Index: 101, + Spi: 456, + Protocol: ipsec.SecurityAssociation_ESP, + CryptoAlg: ipsec.CryptoAlg_AES_CBC_128, + CryptoKey: "d9a4ec50aed76f1bf80bc915d8fcfe1c", + IntegAlg: ipsec.IntegAlg_SHA1_96, + IntegKey: "bf9b150aaf5c2a87d79898b11eabd055e70abdbe", + EnableUdpEncap: true, + }, + tp: &ipsec.TunnelProtection{ + SaOut: []uint32{100}, + SaIn: []uint32{101}, + NextHopAddr: "4.5.6.7", + }, }, } for i, test := range tests { t.Run(test.name, func(t *testing.T) { + if !p2mpSupported && test.ipip.TunnelMode == interfaces.IPIPLink_POINT_TO_MULTIPOINT { + t.Skipf("IPIP: p2mp skipped for VPP < 20.05 (%s)", release) + } // create IPIP tunnel + SAs + tunnel protection ifName := fmt.Sprintf("ipip%d", i) ifIdx, err := ifHandler.AddIpipTunnel(ifName, 0, test.ipip) @@ -127,12 +173,8 @@ func TestIPSec(t *testing.T) { if err != nil { t.Fatalf("IPSec SA add failed: %v", err) } - tunnelProtect := &ipsec.TunnelProtection{ - Interface: ifName, - SaOut: []uint32{test.saOut.Index}, - SaIn: []uint32{test.saIn.Index}, - } - err = ipsecHandler.AddTunnelProtection(tunnelProtect) + test.tp.Interface = ifName + err = ipsecHandler.AddTunnelProtection(test.tp) if err != nil { t.Fatalf("add tunnel protection failed: %v\n", err) } @@ -160,7 +202,7 @@ func TestIPSec(t *testing.T) { if tpList[0].Interface != ifName { t.Fatalf("Invalid interface name in tunnel protections: %s", tpList[0].Interface) } - if dumpAPIOk { + if saDumpAPIOk { if tpList[0].SaIn[0] != test.saIn.Index || tpList[0].SaOut[0] != test.saOut.Index { t.Fatalf("tunnel protection SA mismatch (%d != %d || %d != %d)", tpList[0].SaIn[0], test.saIn.Index, tpList[0].SaOut[0], test.saOut.Index) @@ -168,9 +210,12 @@ func TestIPSec(t *testing.T) { } else { t.Logf("IPIP: SA index check skipped because of a broken API in VPP %s", ctx.versionInfo.Version) } + if tpList[0].NextHopAddr != test.tp.NextHopAddr { + t.Fatalf("tunnel protection next hop mismatch (%v != %v)", tpList[0].NextHopAddr, test.tp.NextHopAddr) + } // delete tunnel protection, SAs and IPIP tunnel - err = ipsecHandler.DeleteTunnelProtection(tunnelProtect) + err = ipsecHandler.DeleteTunnelProtection(test.tp) if err != nil { t.Fatalf("delete tunnel protection failed: %v\n", err) } diff --git a/tests/integration/vpp/140_teib_test.go b/tests/integration/vpp/140_teib_test.go new file mode 100644 index 0000000000..cd1124f224 --- /dev/null +++ b/tests/integration/vpp/140_teib_test.go @@ -0,0 +1,149 @@ +// Copyright (c) 2020 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vpp + +import ( + "testing" + + "go.ligato.io/cn-infra/v2/logging/logrus" + + netalloc_mock "go.ligato.io/vpp-agent/v3/plugins/netalloc/mock" + "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/ifaceidx" + ifplugin_vppcalls "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/vppcalls" + l3plugin_vppcalls "go.ligato.io/vpp-agent/v3/plugins/vpp/l3plugin/vppcalls" + "go.ligato.io/vpp-agent/v3/plugins/vpp/l3plugin/vrfidx" + l3 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3" + + _ "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin" +) + +func TestTeib(t *testing.T) { + ctx := setupVPP(t) + defer ctx.teardownVPP() + + release := ctx.versionInfo.Release() + if release < "20.05" { + t.Skipf("TEIB: skipped for VPP < 20.05 (%s)", release) + } + + ifIndexes := ifaceidx.NewIfaceIndex(logrus.NewLogger("test-if"), "test-if") + vrfIndexes := vrfidx.NewVRFIndex(logrus.NewLogger("test-vrf"), "test-vrf") + l3Handler := l3plugin_vppcalls.CompatibleL3VppHandler(ctx.vppClient, ifIndexes, vrfIndexes, + netalloc_mock.NewMockNetAlloc(), logrus.NewLogger("test-l3")) + + ifHandler := ifplugin_vppcalls.CompatibleInterfaceVppHandler(ctx.vppClient, logrus.NewLogger("test-if")) + + tests := []struct { + name string + teib *l3.TeibEntry + shouldFail bool + }{ + { + name: "Create TEIB entry (IPv4)", + teib: &l3.TeibEntry{ + Interface: "if0", + PeerAddr: "20.30.40.50", + NextHopAddr: "50.40.30.20", + }, + shouldFail: false, + }, + { + name: "Create TEIB entry (IPv6)", + teib: &l3.TeibEntry{ + Interface: "if1", + PeerAddr: "2001:db8:0:1:1:1:1:1", + NextHopAddr: "2002:db8:0:1:1:1:1:1", + }, + shouldFail: false, + }, + { + name: "Create TEIB entry with no peer IP", + teib: &l3.TeibEntry{ + Interface: "if2", + NextHopAddr: "50.40.30.20", + }, + shouldFail: true, + }, + { + name: "Create TEIB entry with no next hop IP", + teib: &l3.TeibEntry{ + Interface: "if3", + PeerAddr: "20.30.40.50", + }, + shouldFail: true, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + ifIdx, err := ifHandler.AddLoopbackInterface(test.teib.Interface) + if err != nil { + t.Fatalf("creating interface failed: %v", err) + } + ifIndexes.Put(test.teib.Interface, &ifaceidx.IfaceMetadata{SwIfIndex: ifIdx}) + + err = l3Handler.VppAddTeibEntry(nil, test.teib) + if err != nil { + if test.shouldFail { + return + } + t.Fatalf("create TEIB entry failed: %v\n", err) + } else { + if test.shouldFail { + t.Fatal("create TEIB entry must fail, but it's not") + } + } + + entries, err := l3Handler.DumpTeib() + if err != nil { + t.Fatalf("dump TEIB entries failed: %v\n", err) + } + if len(entries) == 0 { + t.Fatalf("no TEIB entries dumped") + } + + if entries[0].VrfId != test.teib.VrfId { + t.Fatalf("expected VrfId <%v>, got: <%v>", test.teib.VrfId, entries[0].VrfId) + } + if entries[0].Interface != test.teib.Interface { + t.Fatalf("expected Interface <%v>, got: <%v>", test.teib.Interface, entries[0].Interface) + } + if entries[0].PeerAddr != test.teib.PeerAddr { + t.Fatalf("expected PeerAddr <%s>, got: <%s>", test.teib.PeerAddr, entries[0].PeerAddr) + } + if entries[0].NextHopAddr != test.teib.NextHopAddr { + t.Fatalf("expected NextHopAddr <%s>, got: <%s>", test.teib.NextHopAddr, entries[0].NextHopAddr) + } + + err = l3Handler.VppDelTeibEntry(nil, test.teib) + if err != nil { + t.Fatalf("delete TEIB entry failed: %v\n", err) + } + + entries, err = l3Handler.DumpTeib() + if err != nil { + t.Fatalf("dump TEIB entries failed: %v\n", err) + } + if len(entries) != 0 { + t.Fatalf("%d TEIB entries dumped after delete", len(entries)) + } + + err = ifHandler.DeleteLoopbackInterface(test.teib.Interface, ifIdx) + if err != nil { + t.Fatalf("delete interface failed: %v", err) + } + ifIndexes.Delete(test.teib.Interface) + }) + } +}