diff --git a/plugins/vpp/natplugin/descriptor/nat44_address_pool.go b/plugins/vpp/natplugin/descriptor/nat44_address_pool.go index 53f364a34b..e6e68943f1 100644 --- a/plugins/vpp/natplugin/descriptor/nat44_address_pool.go +++ b/plugins/vpp/natplugin/descriptor/nat44_address_pool.go @@ -68,6 +68,7 @@ func NewNAT44AddressPoolDescriptor(nat44GlobalDesc *NAT44GlobalDescriptor, Delete: ctx.Delete, Retrieve: ctx.Retrieve, Dependencies: ctx.Dependencies, + DerivedValues: ctx.DerivedValues, // retrieve global NAT config first (required for deprecated global NAT interface & address API) RetrieveDependencies: []string{NAT44GlobalDescriptorName}, } @@ -151,6 +152,21 @@ func (d *NAT44AddressPoolDescriptor) Dependencies(key string, natAddr *nat.Nat44 } } +// DerivedValues derives: +// - for twiceNAT address pool the pool itself with exposed IP addresses and VRF in derived key +func (d *NAT44AddressPoolDescriptor) DerivedValues(key string, addrPool *nat.Nat44AddressPool) (derValues []kvs.KeyValuePair) { + if addrPool.TwiceNat { + // this derived value may seem as copy of nat44-pool, but nat44-pool key can have 2 forms and in form + // where nat44-pool key is only pool name, there can't be made dependency based on IP address and + // twiceNAT bool => this derived key is needed + derValues = append(derValues, kvs.KeyValuePair{ + Key: nat.DerivedTwiceNATAddressPoolKey(addrPool.FirstIp, addrPool.LastIp, addrPool.VrfId), + Value: addrPool, + }) + } + return derValues +} + // equalNamelessPool determine equality between 2 Nat44AddressPools ignoring Name field func (d *NAT44AddressPoolDescriptor) equalNamelessPool(pool1, pool2 *nat.Nat44AddressPool) bool { return pool1.VrfId == pool2.VrfId && diff --git a/plugins/vpp/natplugin/descriptor/nat44_dnat.go b/plugins/vpp/natplugin/descriptor/nat44_dnat.go index 78aaae8f23..d19c24fe41 100644 --- a/plugins/vpp/natplugin/descriptor/nat44_dnat.go +++ b/plugins/vpp/natplugin/descriptor/nat44_dnat.go @@ -15,12 +15,13 @@ package descriptor import ( + "bytes" + "net" + "strconv" + "github.com/golang/protobuf/proto" "github.com/pkg/errors" "go.ligato.io/cn-infra/v2/logging" - - "strconv" - kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api" vpp_ifdescriptor "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/descriptor" "go.ligato.io/vpp-agent/v3/plugins/vpp/natplugin/descriptor/adapter" @@ -40,8 +41,9 @@ const ( untaggedDNAT = "UNTAGGED-DNAT" // dependency labels - mappingInterfaceDep = "interface-exists" - mappingVrfDep = "vrf-table-exists" + mappingInterfaceDep = "interface-exists" + mappingVrfDep = "vrf-table-exists" + refTwiceNATPoolIPDep = "reference-to-twiceNATPoolIP" ) // A list of non-retriable errors: @@ -49,6 +51,18 @@ var ( // ErrDNAT44WithEmptyLabel is returned when NAT44 DNAT configuration is defined // with empty label ErrDNAT44WithEmptyLabel = errors.New("NAT44 DNAT configuration defined with empty label") + + // ErrDNAT44TwiceNATPoolIPNeedsTwiceNAT is returned when NAT44 DNAT static configuration is defined + // with non-empty twiceNAT pool IP, but twiceNAT is not enabled for given static mapping. + ErrDNAT44TwiceNATPoolIPNeedsTwiceNAT = errors.New("NAT44 DNAT static mapping configuration with " + + "non-empty twiceNAT pool IP have to have also enabled twiceNAT (use enabled, not self-twiceNAT)") + + // ErrDNAT44TwiceNATPoolIPIsNotSupportedForLBStMappings is returned when twiceNAT pool IP is used with + // loadbalanced version of static mapping. This combination is not supported by VPP. + ErrDNAT44TwiceNATPoolIPIsNotSupportedForLBStMappings = errors.New("NAT44 DNAT static mapping's " + + "twiceNAT pool IP feature is not supported(by VPP) when the loadbalanced version of static mapping " + + "is used. Use non-loadbalanced version of static mappings(<=>len(local IP)<=1) or don't use twiceNAT " + + "pool IP feature.") ) // DNAT44Descriptor teaches KVScheduler how to configure Destination NAT44 in VPP. @@ -106,6 +120,27 @@ func (d *DNAT44Descriptor) Validate(key string, dnat *nat.DNat44) error { if dnat.Label == "" { return kvs.NewInvalidValueError(ErrDNAT44WithEmptyLabel, "label") } + + // Static Mapping validation + for _, stMapping := range dnat.StMappings { + // Twice-NAT validation + if stMapping.TwiceNatPoolIp != "" { + if stMapping.TwiceNat != nat.DNat44_StaticMapping_ENABLED { + return kvs.NewInvalidValueError(ErrDNAT44TwiceNATPoolIPNeedsTwiceNAT, + "st_mappings.twice_nat_pool_ip") + } + if len(stMapping.LocalIps) > 1 { + kvs.NewInvalidValueError(ErrDNAT44TwiceNATPoolIPIsNotSupportedForLBStMappings, + "st_mappings.twice_nat_pool_ip") + } + if _, err := ParseIPv4(stMapping.TwiceNatPoolIp); err != nil { + return kvs.NewInvalidValueError(errors.Errorf("NAT44 DNAT static mapping configuration "+ + "has unparsable non-empty twice-NAT pool IPv4 address %s: %v", stMapping.TwiceNatPoolIp, err), + "st_mappings.twice_nat_pool_ip") + } + } + } + return nil } @@ -170,6 +205,11 @@ func (d *DNAT44Descriptor) Update(key string, oldDNAT, newDNAT *nat.DNat44, oldM func (d *DNAT44Descriptor) Retrieve(correlate []adapter.DNAT44KVWithMetadata) ( retrieved []adapter.DNAT44KVWithMetadata, err error, ) { + // TODO when added to dump then implement value retrieval for these new values + // vpp_nat.Nat44AddDelStaticMappingV2.MatchPool + // vpp_nat.Nat44AddDelStaticMappingV2.PoolIPAddress + // (=functionality modeled in NB proto model as DNat44.StaticMapping.twice_nat_pool_ip) + // collect DNATs which are expected to be empty corrEmptyDNATs := make(map[string]*nat.DNat44) for _, kv := range correlate { @@ -253,6 +293,34 @@ func (d *DNAT44Descriptor) Dependencies(key string, dnat *nat.DNat44) (dependenc }) } + // for every twiceNAT pool address reference add one dependency + for _, stMapping := range dnat.StMappings { + if stMapping.TwiceNat == nat.DNat44_StaticMapping_ENABLED && stMapping.TwiceNatPoolIp != "" { + dependencies = append(dependencies, kvs.Dependency{ + Label: refTwiceNATPoolIPDep, + AnyOf: kvs.AnyOfDependency{ + KeyPrefixes: []string{nat.TwiceNATDerivedKeyPrefix}, + KeySelector: func(key string) bool { + firstIP, lastIP, _, isValid := nat.ParseDerivedTwiceNATAddressPoolKey(key) + if isValid { + if lastIP == "" { // single IP address pool + return equivalentTrimmedLowered(firstIP, stMapping.TwiceNatPoolIp) + } + // multiple IP addresses in address pool + fIP := net.ParseIP(firstIP) + lIP := net.ParseIP(lastIP) + tnpIP := net.ParseIP(stMapping.TwiceNatPoolIp) + if fIP != nil && lIP != nil && tnpIP != nil { + return bytes.Compare(fIP, tnpIP) <= 0 && bytes.Compare(tnpIP, lIP) <= 0 + } + } + return false + }, + }, + }) + } + } + return dependencies } @@ -323,7 +391,8 @@ func equivalentStaticMappings(stMapping1, stMapping2 *nat.DNat44_StaticMapping) // attributes compared as usually if stMapping1.Protocol != stMapping2.Protocol || stMapping1.ExternalPort != stMapping2.ExternalPort || stMapping1.ExternalIp != stMapping2.ExternalIp || stMapping1.ExternalInterface != stMapping2.ExternalInterface || - stMapping1.TwiceNat != stMapping2.TwiceNat || stMapping1.SessionAffinity != stMapping1.SessionAffinity { + stMapping1.TwiceNat != stMapping2.TwiceNat || stMapping1.SessionAffinity != stMapping1.SessionAffinity || + !equivalentIPv4(stMapping1.TwiceNatPoolIp, stMapping2.TwiceNatPoolIp) { return false } diff --git a/plugins/vpp/natplugin/vppcalls/vpp1904/nat_vppcalls.go b/plugins/vpp/natplugin/vppcalls/vpp1904/nat_vppcalls.go index 8bf96ebea2..d0c48d2574 100644 --- a/plugins/vpp/natplugin/vppcalls/vpp1904/nat_vppcalls.go +++ b/plugins/vpp/natplugin/vppcalls/vpp1904/nat_vppcalls.go @@ -216,6 +216,11 @@ func (h *NatVppHandler) handleNat44StaticMapping(mapping *nat.DNat44_StaticMappi var ifIdx = NoInterface var exIPAddr net.IP + if mapping.TwiceNatPoolIp != "" { + h.log.Debug("DNAT44 static mapping's twiceNAT pool IP feature " + + "is unsupported in this version of VPP (use 20.09 and newer)") + } + // check tag length limit if err := checkTagLength(dnatLabel); err != nil { return err diff --git a/plugins/vpp/natplugin/vppcalls/vpp1908/nat_vppcalls.go b/plugins/vpp/natplugin/vppcalls/vpp1908/nat_vppcalls.go index fb21f988c8..57511d25aa 100644 --- a/plugins/vpp/natplugin/vppcalls/vpp1908/nat_vppcalls.go +++ b/plugins/vpp/natplugin/vppcalls/vpp1908/nat_vppcalls.go @@ -229,6 +229,11 @@ func (h *NatVppHandler) handleNat44StaticMapping(mapping *nat.DNat44_StaticMappi var ifIdx = NoInterface var exIPAddr natba.IP4Address + if mapping.TwiceNatPoolIp != "" { + h.log.Debug("DNAT44 static mapping's twiceNAT pool IP feature " + + "is unsupported in this version of VPP (use 20.09 and newer)") + } + // check tag length limit if err := checkTagLength(dnatLabel); err != nil { return err diff --git a/plugins/vpp/natplugin/vppcalls/vpp2001/nat_vppcalls.go b/plugins/vpp/natplugin/vppcalls/vpp2001/nat_vppcalls.go index affc13edef..07eb81f358 100644 --- a/plugins/vpp/natplugin/vppcalls/vpp2001/nat_vppcalls.go +++ b/plugins/vpp/natplugin/vppcalls/vpp2001/nat_vppcalls.go @@ -229,6 +229,11 @@ func (h *NatVppHandler) handleNat44StaticMapping(mapping *nat.DNat44_StaticMappi var ifIdx = NoInterface var exIPAddr vpp_nat.IP4Address + if mapping.TwiceNatPoolIp != "" { + h.log.Debug("DNAT44 static mapping's twiceNAT pool IP feature " + + "is unsupported in this version of VPP (use 20.09 and newer)") + } + // check tag length limit if err := checkTagLength(dnatLabel); err != nil { return err diff --git a/plugins/vpp/natplugin/vppcalls/vpp2005/nat_vppcalls.go b/plugins/vpp/natplugin/vppcalls/vpp2005/nat_vppcalls.go index 86ddba3124..d679ca8bc4 100644 --- a/plugins/vpp/natplugin/vppcalls/vpp2005/nat_vppcalls.go +++ b/plugins/vpp/natplugin/vppcalls/vpp2005/nat_vppcalls.go @@ -229,6 +229,11 @@ func (h *NatVppHandler) handleNat44StaticMapping(mapping *nat.DNat44_StaticMappi var ifIdx = NoInterface var exIPAddr vpp_nat.IP4Address + if mapping.TwiceNatPoolIp != "" { + h.log.Debug("DNAT44 static mapping's twiceNAT pool IP feature " + + "is unsupported in this version of VPP (use 20.09 and newer)") + } + // check tag length limit if err := checkTagLength(dnatLabel); err != nil { return err diff --git a/plugins/vpp/natplugin/vppcalls/vpp2009/nat_vppcalls.go b/plugins/vpp/natplugin/vppcalls/vpp2009/nat_vppcalls.go index 236635cc22..5710240898 100644 --- a/plugins/vpp/natplugin/vppcalls/vpp2009/nat_vppcalls.go +++ b/plugins/vpp/natplugin/vppcalls/vpp2009/nat_vppcalls.go @@ -270,7 +270,7 @@ func (h *NatVppHandler) handleNat44StaticMapping(mapping *nat.DNat44_StaticMappi addrOnly = true } - req := &vpp_nat.Nat44AddDelStaticMapping{ + req := &vpp_nat.Nat44AddDelStaticMappingV2{ Tag: dnatLabel, LocalIPAddress: lcIPAddr, ExternalIPAddress: exIPAddr, @@ -291,7 +291,17 @@ func (h *NatVppHandler) handleNat44StaticMapping(mapping *nat.DNat44_StaticMappi req.ExternalPort = uint16(mapping.ExternalPort) } - reply := &vpp_nat.Nat44AddDelStaticMappingReply{} + // Applying(if needed) the override of IP address picking from twice-NAT address pool + if mapping.TwiceNatPoolIp != "" { + req.MatchPool = true + req.PoolIPAddress, err = ipTo4Address(mapping.TwiceNatPoolIp) + if err != nil { + return errors.Errorf("cannot configure static mapping for DNAT %s: unable to parse " + + "twice-NAT pool IP %s: %v", dnatLabel, mapping.TwiceNatPoolIp, err) + } + } + + reply := &vpp_nat.Nat44AddDelStaticMappingV2Reply{} if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err diff --git a/plugins/vpp/natplugin/vppcalls/vpp2009/nat_vppcalls_test.go b/plugins/vpp/natplugin/vppcalls/vpp2009/nat_vppcalls_test.go index 9202355984..8657f7b121 100644 --- a/plugins/vpp/natplugin/vppcalls/vpp2009/nat_vppcalls_test.go +++ b/plugins/vpp/natplugin/vppcalls/vpp2009/nat_vppcalls_test.go @@ -65,7 +65,7 @@ func TestSetNat44ForwardingError(t *testing.T) { defer ctx.TeardownTestCtx() // Incorrect reply object - ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelStaticMappingReply{}) + ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelStaticMappingV2Reply{}) err := natHandler.SetNat44Forwarding(true) Expect(err).Should(HaveOccurred()) @@ -231,7 +231,7 @@ func TestEnableNat44InterfaceOutputError(t *testing.T) { swIfIndexes.Put("if1", &ifaceidx.IfaceMetadata{SwIfIndex: 2}) // Incorrect reply object - ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelStaticMappingReply{}) + ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelStaticMappingV2Reply{}) err := natHandler.EnableNat44Interface("if1", false, true) Expect(err).Should(HaveOccurred()) @@ -441,12 +441,12 @@ func TestAddNat44StaticMapping(t *testing.T) { }, } - ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelStaticMappingReply{}) + ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelStaticMappingV2Reply{}) err := natHandler.AddNat44StaticMapping(mapping, "DNAT 1") Expect(err).ShouldNot(HaveOccurred()) - msg, ok := ctx.MockChannel.Msg.(*vpp_nat.Nat44AddDelStaticMapping) + msg, ok := ctx.MockChannel.Msg.(*vpp_nat.Nat44AddDelStaticMappingV2) Expect(ok).To(BeTrue()) Expect(msg.Tag).To(BeEquivalentTo("DNAT 1")) Expect(msg.VrfID).To(BeEquivalentTo(1)) @@ -478,12 +478,12 @@ func TestAddNat44IdentityMappingWithInterface(t *testing.T) { }, } - ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelStaticMappingReply{}) + ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelStaticMappingV2Reply{}) err := natHandler.AddNat44StaticMapping(mapping, "DNAT 1") Expect(err).ShouldNot(HaveOccurred()) - msg, ok := ctx.MockChannel.Msg.(*vpp_nat.Nat44AddDelStaticMapping) + msg, ok := ctx.MockChannel.Msg.(*vpp_nat.Nat44AddDelStaticMappingV2) Expect(ok).To(BeTrue()) Expect(msg.Tag).To(BeEquivalentTo("DNAT 1")) Expect(msg.IsAdd).To(BeTrue()) @@ -507,7 +507,7 @@ func TestAddNat44StaticMappingRetval(t *testing.T) { ctx, natHandler, _, _ := natTestSetup(t) defer ctx.TeardownTestCtx() - ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelStaticMappingReply{ + ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelStaticMappingV2Reply{ Retval: 1, }) err := natHandler.AddNat44StaticMapping(&nat.DNat44_StaticMapping{}, "") @@ -539,12 +539,12 @@ func TestDelNat44StaticMapping(t *testing.T) { }, } - ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelStaticMappingReply{}) + ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelStaticMappingV2Reply{}) err := natHandler.DelNat44StaticMapping(mapping, "DNAT 1") Expect(err).ShouldNot(HaveOccurred()) - msg, ok := ctx.MockChannel.Msg.(*vpp_nat.Nat44AddDelStaticMapping) + msg, ok := ctx.MockChannel.Msg.(*vpp_nat.Nat44AddDelStaticMappingV2) Expect(ok).To(BeTrue()) Expect(msg.Tag).To(BeEquivalentTo("DNAT 1")) Expect(msg.VrfID).To(BeEquivalentTo(1)) @@ -575,12 +575,12 @@ func TestDelNat44StaticMappingAddrOnly(t *testing.T) { }, } - ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelStaticMappingReply{}) + ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelStaticMappingV2Reply{}) err := natHandler.DelNat44StaticMapping(mapping, "DNAT 1") Expect(err).ShouldNot(HaveOccurred()) - msg, ok := ctx.MockChannel.Msg.(*vpp_nat.Nat44AddDelStaticMapping) + msg, ok := ctx.MockChannel.Msg.(*vpp_nat.Nat44AddDelStaticMappingV2) Expect(ok).To(BeTrue()) Expect(msg.Tag).To(BeEquivalentTo("DNAT 1")) Expect(msg.IsAdd).To(BeFalse()) @@ -777,7 +777,7 @@ func TestAddNat44IdentityMappingError(t *testing.T) { defer ctx.TeardownTestCtx() // Incorrect reply object - ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelStaticMappingReply{}) + ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelStaticMappingV2Reply{}) err := natHandler.AddNat44IdentityMapping(&nat.DNat44_IdentityMapping{}, "") Expect(err).Should(HaveOccurred()) @@ -862,11 +862,11 @@ func TestNat44MappingLongTag(t *testing.T) { } // 1. test - ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelStaticMappingReply{}) + ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelStaticMappingV2Reply{}) ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelLbStaticMappingReply{}) ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelIdentityMappingReply{}) // 2. test - ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelStaticMappingReply{}) + ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelStaticMappingV2Reply{}) ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelLbStaticMappingReply{}) ctx.MockVpp.MockReply(&vpp_nat.Nat44AddDelIdentityMappingReply{}) diff --git a/proto/ligato/vpp/nat/models.go b/proto/ligato/vpp/nat/models.go index 2f618f6bd9..229d01e4c7 100644 --- a/proto/ligato/vpp/nat/models.go +++ b/proto/ligato/vpp/nat/models.go @@ -15,6 +15,8 @@ package vpp_nat import ( + "fmt" + "strconv" "strings" "go.ligato.io/vpp-agent/v3/pkg/models" @@ -108,6 +110,17 @@ const ( // twice-NAT switch twiceNatOn = "on" twiceNatOff = "off" + + // TwiceNATDerivedKeyPrefix is common prefix for (derived) keys each representing twiceNAT address pool + TwiceNATDerivedKeyPrefix = "vpp/nat44/twiceNAT-pool/" + + // twiceNATKeyTemplate is a template for (derived) key + // representing twiceNAT address pool with single IP range. + twiceNATKeyTemplate = TwiceNATDerivedKeyPrefix + "vrf/{vrfID}/addresses/{firstIP}" + + // twiceNATWithMultipeAddressesKeyTemplate is a template for (derived) key + // representing twiceNAT address pool with multiple IP range. + twiceNATWithMultipeAddressesKeyTemplate = TwiceNATDerivedKeyPrefix + "vrf/{vrfID}/addresses/{firstIP}-{lastIP}" ) const ( @@ -182,3 +195,40 @@ func ParseDerivedAddressNAT44Key(key string) (address string, twiceNat bool, isA } return } + +// DerivedTwiceNATAddressPoolKey returns (derived) key representing TwiceNAT address pool configuration. +func DerivedTwiceNATAddressPoolKey(firstIP, lastIP string, vrfID uint32) (key string) { + if lastIP == "" { + key = strings.Replace(twiceNATKeyTemplate, "{vrfID}", fmt.Sprint(vrfID), 1) + key = strings.Replace(key, "{firstIP}", firstIP, 1) + } else { + key = strings.Replace(twiceNATWithMultipeAddressesKeyTemplate, "{vrfID}", fmt.Sprint(vrfID), 1) + key = strings.Replace(key, "{firstIP}", firstIP, 1) + key = strings.Replace(key, "{lastIP}", lastIP, 1) + } + return key +} + +// ParseDerivedTwiceNATAddressPoolKey parses configuration of a twiceNAT address pool from a key +// returned by DerivedTwiceNATAddressPoolKey(). +func ParseDerivedTwiceNATAddressPoolKey(key string) (firstIP, lastIP string, vrfID uint32, isTwiceNatKey bool) { + trim := strings.TrimPrefix(key, TwiceNATDerivedKeyPrefix) + if trim != key && trim != "" { + comps := strings.Split(trim, "/") + if len(comps) == 4 && comps[0] == "vrf" && comps[2] == "addresses" { + vrfID64, err := strconv.ParseUint(comps[1], 10, 32) + if err != nil { + return + } + vrfID = uint32(vrfID64) + addrComps := strings.Split(comps[3], "-") + firstIP = addrComps[0] + if len(addrComps) > 1 { + lastIP = addrComps[1] + } + isTwiceNatKey = true + return + } + } + return +} diff --git a/proto/ligato/vpp/nat/nat.pb.go b/proto/ligato/vpp/nat/nat.pb.go index c339ac0627..7520ccebae 100644 --- a/proto/ligato/vpp/nat/nat.pb.go +++ b/proto/ligato/vpp/nat/nat.pb.go @@ -666,6 +666,14 @@ type DNat44_StaticMapping struct { Protocol DNat44_Protocol `protobuf:"varint,5,opt,name=protocol,proto3,enum=ligato.vpp.nat.DNat44_Protocol" json:"protocol,omitempty"` // Enable/disable (self-)twice NAT. TwiceNat DNat44_StaticMapping_TwiceNatMode `protobuf:"varint,6,opt,name=twice_nat,json=twiceNat,proto3,enum=ligato.vpp.nat.DNat44_StaticMapping_TwiceNatMode" json:"twice_nat,omitempty"` + // IP address from Twice-NAT address pool that should be used as source IP in twice-NAT processing. + // This is override for default behaviour of choosing the first IP address from twice-NAT pool that + // has available at least one free port (NAT is tracking translation sessions and exhausts free ports + // for given IP address). This is needed for example in use cases when multiple twice-NAT + // translations need to use different IP Addresses as source IP addresses. + // This functionality works with VPP 20.09 and newer. It also needs to have twice_nat set to ENABLED. + // It doesn't work for load-balanced static mappings (=local_ips has multiple values). + TwiceNatPoolIp string `protobuf:"bytes,8,opt,name=twice_nat_pool_ip,json=twiceNatPoolIp,proto3" json:"twice_nat_pool_ip,omitempty"` // Session affinity. 0 means disabled, otherwise client IP affinity sticky time in seconds. SessionAffinity uint32 `protobuf:"varint,7,opt,name=session_affinity,json=sessionAffinity,proto3" json:"session_affinity,omitempty"` } @@ -744,6 +752,13 @@ func (x *DNat44_StaticMapping) GetTwiceNat() DNat44_StaticMapping_TwiceNatMode { return DNat44_StaticMapping_DISABLED } +func (x *DNat44_StaticMapping) GetTwiceNatPoolIp() string { + if x != nil { + return x.TwiceNatPoolIp + } + return "" +} + func (x *DNat44_StaticMapping) GetSessionAffinity() uint32 { if x != nil { return x.SessionAffinity @@ -947,7 +962,7 @@ var file_ligato_vpp_nat_nat_proto_rawDesc = []byte{ 0x72, 0x65, 0x73, 0x73, 0x12, 0x15, 0x0a, 0x06, 0x76, 0x72, 0x66, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x72, 0x66, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x77, 0x69, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, - 0x74, 0x77, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x74, 0x22, 0xcc, 0x07, 0x0a, 0x06, 0x44, 0x4e, 0x61, + 0x74, 0x77, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x74, 0x22, 0xf7, 0x07, 0x0a, 0x06, 0x44, 0x4e, 0x61, 0x74, 0x34, 0x34, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x45, 0x0a, 0x0b, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, @@ -958,7 +973,7 @@ var file_ligato_vpp_nat_nat_proto_rawDesc = []byte{ 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x6c, 0x69, 0x67, 0x61, 0x74, 0x6f, 0x2e, 0x76, 0x70, 0x70, 0x2e, 0x6e, 0x61, 0x74, 0x2e, 0x44, 0x4e, 0x61, 0x74, 0x34, 0x34, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0a, 0x69, - 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x1a, 0xba, 0x04, 0x0a, 0x0d, 0x53, 0x74, + 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x1a, 0xe5, 0x04, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x2d, 0x0a, 0x12, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, @@ -980,67 +995,70 @@ var file_ligato_vpp_nat_nat_proto_rawDesc = []byte{ 0x67, 0x61, 0x74, 0x6f, 0x2e, 0x76, 0x70, 0x70, 0x2e, 0x6e, 0x61, 0x74, 0x2e, 0x44, 0x4e, 0x61, 0x74, 0x34, 0x34, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x77, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x08, - 0x74, 0x77, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x66, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x79, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x0f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x41, 0x66, 0x66, 0x69, 0x6e, - 0x69, 0x74, 0x79, 0x1a, 0x7c, 0x0a, 0x07, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x50, 0x12, 0x15, - 0x0a, 0x06, 0x76, 0x72, 0x66, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, - 0x76, 0x72, 0x66, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x69, - 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x70, - 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x12, - 0x20, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x62, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x62, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x79, 0x22, 0x33, 0x0a, 0x0c, 0x54, 0x77, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x74, 0x4d, 0x6f, 0x64, - 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x00, 0x12, - 0x0b, 0x0a, 0x07, 0x45, 0x4e, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, - 0x53, 0x45, 0x4c, 0x46, 0x10, 0x02, 0x1a, 0xb6, 0x01, 0x0a, 0x0f, 0x49, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x15, 0x0a, 0x06, 0x76, 0x72, - 0x66, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x72, 0x66, 0x49, - 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, - 0x1d, 0x0a, 0x0a, 0x69, 0x70, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, - 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, - 0x72, 0x74, 0x12, 0x3b, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x6c, 0x69, 0x67, 0x61, 0x74, 0x6f, 0x2e, 0x76, 0x70, - 0x70, 0x2e, 0x6e, 0x61, 0x74, 0x2e, 0x44, 0x4e, 0x61, 0x74, 0x34, 0x34, 0x2e, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, - 0x26, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x07, 0x0a, 0x03, 0x54, - 0x43, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, 0x01, 0x12, 0x08, 0x0a, - 0x04, 0x49, 0x43, 0x4d, 0x50, 0x10, 0x02, 0x22, 0x8b, 0x01, 0x0a, 0x0e, 0x4e, 0x61, 0x74, 0x34, - 0x34, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, - 0x0a, 0x0a, 0x6e, 0x61, 0x74, 0x5f, 0x69, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x09, 0x6e, 0x61, 0x74, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x12, 0x1f, 0x0a, - 0x0b, 0x6e, 0x61, 0x74, 0x5f, 0x6f, 0x75, 0x74, 0x73, 0x69, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0a, 0x6e, 0x61, 0x74, 0x4f, 0x75, 0x74, 0x73, 0x69, 0x64, 0x65, 0x12, 0x25, - 0x0a, 0x0e, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x46, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x8e, 0x01, 0x0a, 0x10, 0x4e, 0x61, 0x74, 0x34, 0x34, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x15, - 0x0a, 0x06, 0x76, 0x72, 0x66, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, - 0x76, 0x72, 0x66, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x69, - 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x66, 0x69, 0x72, 0x73, 0x74, 0x49, 0x70, - 0x12, 0x17, 0x0a, 0x07, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x6c, 0x61, 0x73, 0x74, 0x49, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x77, 0x69, - 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x77, - 0x69, 0x63, 0x65, 0x4e, 0x61, 0x74, 0x22, 0xa4, 0x01, 0x0a, 0x11, 0x56, 0x69, 0x72, 0x74, 0x75, - 0x61, 0x6c, 0x52, 0x65, 0x61, 0x73, 0x73, 0x65, 0x6d, 0x62, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, - 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x74, - 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x65, - 0x61, 0x73, 0x73, 0x65, 0x6d, 0x62, 0x6c, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x0f, 0x6d, 0x61, 0x78, 0x52, 0x65, 0x61, 0x73, 0x73, 0x65, 0x6d, 0x62, 0x6c, 0x69, 0x65, - 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x46, 0x72, 0x61, - 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x72, 0x6f, 0x70, 0x5f, 0x66, - 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, - 0x64, 0x72, 0x6f, 0x70, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x38, 0x5a, - 0x36, 0x67, 0x6f, 0x2e, 0x6c, 0x69, 0x67, 0x61, 0x74, 0x6f, 0x2e, 0x69, 0x6f, 0x2f, 0x76, 0x70, - 0x70, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x6c, 0x69, 0x67, 0x61, 0x74, 0x6f, 0x2f, 0x76, 0x70, 0x70, 0x2f, 0x6e, 0x61, 0x74, 0x3b, - 0x76, 0x70, 0x70, 0x5f, 0x6e, 0x61, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x77, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x74, 0x12, 0x29, 0x0a, 0x11, 0x74, 0x77, 0x69, 0x63, + 0x65, 0x5f, 0x6e, 0x61, 0x74, 0x5f, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x69, 0x70, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x77, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x74, 0x50, 0x6f, 0x6f, + 0x6c, 0x49, 0x70, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x61, + 0x66, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x41, 0x66, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x79, 0x1a, 0x7c, + 0x0a, 0x07, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x50, 0x12, 0x15, 0x0a, 0x06, 0x76, 0x72, 0x66, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x72, 0x66, 0x49, 0x64, + 0x12, 0x19, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x70, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, + 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x72, + 0x6f, 0x62, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x0b, 0x70, 0x72, 0x6f, 0x62, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x22, 0x33, 0x0a, 0x0c, + 0x54, 0x77, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0c, 0x0a, 0x08, + 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x4e, + 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x45, 0x4c, 0x46, 0x10, + 0x02, 0x1a, 0xb6, 0x01, 0x0a, 0x0f, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x61, + 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x15, 0x0a, 0x06, 0x76, 0x72, 0x66, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x72, 0x66, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x70, + 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x3b, 0x0a, + 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x1f, 0x2e, 0x6c, 0x69, 0x67, 0x61, 0x74, 0x6f, 0x2e, 0x76, 0x70, 0x70, 0x2e, 0x6e, 0x61, 0x74, + 0x2e, 0x44, 0x4e, 0x61, 0x74, 0x34, 0x34, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, + 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, 0x26, 0x0a, 0x08, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x00, 0x12, + 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x43, 0x4d, 0x50, + 0x10, 0x02, 0x22, 0x8b, 0x01, 0x0a, 0x0e, 0x4e, 0x61, 0x74, 0x34, 0x34, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x61, 0x74, + 0x5f, 0x69, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6e, + 0x61, 0x74, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x61, 0x74, 0x5f, + 0x6f, 0x75, 0x74, 0x73, 0x69, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x6e, + 0x61, 0x74, 0x4f, 0x75, 0x74, 0x73, 0x69, 0x64, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x6f, 0x75, 0x74, + 0x70, 0x75, 0x74, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0d, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x22, 0x8e, 0x01, 0x0a, 0x10, 0x4e, 0x61, 0x74, 0x34, 0x34, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x76, 0x72, 0x66, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x72, 0x66, 0x49, 0x64, + 0x12, 0x19, 0x0a, 0x08, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x66, 0x69, 0x72, 0x73, 0x74, 0x49, 0x70, 0x12, 0x17, 0x0a, 0x07, 0x6c, + 0x61, 0x73, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x61, + 0x73, 0x74, 0x49, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x77, 0x69, 0x63, 0x65, 0x5f, 0x6e, 0x61, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x77, 0x69, 0x63, 0x65, 0x4e, 0x61, + 0x74, 0x22, 0xa4, 0x01, 0x0a, 0x11, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x52, 0x65, 0x61, + 0x73, 0x73, 0x65, 0x6d, 0x62, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, + 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, + 0x74, 0x12, 0x29, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x73, 0x65, 0x6d, + 0x62, 0x6c, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x6d, 0x61, 0x78, + 0x52, 0x65, 0x61, 0x73, 0x73, 0x65, 0x6d, 0x62, 0x6c, 0x69, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, + 0x6d, 0x61, 0x78, 0x5f, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x72, 0x6f, 0x70, 0x5f, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x64, 0x72, 0x6f, 0x70, 0x46, + 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x38, 0x5a, 0x36, 0x67, 0x6f, 0x2e, 0x6c, + 0x69, 0x67, 0x61, 0x74, 0x6f, 0x2e, 0x69, 0x6f, 0x2f, 0x76, 0x70, 0x70, 0x2d, 0x61, 0x67, 0x65, + 0x6e, 0x74, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6c, 0x69, 0x67, 0x61, + 0x74, 0x6f, 0x2f, 0x76, 0x70, 0x70, 0x2f, 0x6e, 0x61, 0x74, 0x3b, 0x76, 0x70, 0x70, 0x5f, 0x6e, + 0x61, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/ligato/vpp/nat/nat.proto b/proto/ligato/vpp/nat/nat.proto index e96b37b204..ae3d7631b6 100644 --- a/proto/ligato/vpp/nat/nat.proto +++ b/proto/ligato/vpp/nat/nat.proto @@ -86,6 +86,15 @@ message DNat44 { // Enable/disable (self-)twice NAT. TwiceNatMode twice_nat = 6; + // IP address from Twice-NAT address pool that should be used as source IP in twice-NAT processing. + // This is override for default behaviour of choosing the first IP address from twice-NAT pool that + // has available at least one free port (NAT is tracking translation sessions and exhausts free ports + // for given IP address). This is needed for example in use cases when multiple twice-NAT + // translations need to use different IP Addresses as source IP addresses. + // This functionality works with VPP 20.09 and newer. It also needs to have twice_nat set to ENABLED. + // It doesn't work for load-balanced static mappings (=local_ips has multiple values). + string twice_nat_pool_ip = 8; + // Session affinity. 0 means disabled, otherwise client IP affinity sticky time in seconds. uint32 session_affinity = 7; } diff --git a/tests/integration/vpp/150_nat_test.go b/tests/integration/vpp/150_nat_test.go new file mode 100644 index 0000000000..705b7a6e63 --- /dev/null +++ b/tests/integration/vpp/150_nat_test.go @@ -0,0 +1,154 @@ +// Copyright (c) 2019 Pantheon.tech +// +// 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 ( + "net" + "testing" + + . "github.com/onsi/gomega" + idxmap_mem "go.ligato.io/cn-infra/v2/idxmap/mem" + "go.ligato.io/cn-infra/v2/logging/logrus" + "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/ifaceidx" + _ "go.ligato.io/vpp-agent/v3/plugins/vpp/natplugin" + nat_vppcalls "go.ligato.io/vpp-agent/v3/plugins/vpp/natplugin/vppcalls" + nat "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/nat" + "google.golang.org/protobuf/proto" +) + +const ( + vpp1908 = "19.08" + vpp2001 = "20.01" + vpp2005 = "20.05" + vpp2009 = "20.09" +) + +// TestNat44StaticMapping tests Create/Read/Delete operations for NAT44 static mappings +func TestNat44StaticMapping(t *testing.T) { + ctx := setupVPP(t) + defer ctx.teardownVPP() + + // nat handler + swIfIndexes := ifaceidx.NewIfaceIndex(logrus.DefaultLogger(), "test-sw_if_indexes") + dhcpIndexes := idxmap_mem.NewNamedMapping(logrus.DefaultLogger(), "test-dhcp_indexes", nil) + natHandler := nat_vppcalls.CompatibleNatVppHandler(ctx.vppClient, swIfIndexes, dhcpIndexes, logrus.NewLogger("test")) + Expect(natHandler).ShouldNot(BeNil(), "Handler should be created.") + + // some test constants + const dnatLabel = "DNAT 1" + localIP := net.ParseIP("10.0.0.1").To4() + externalIP := net.ParseIP("10.0.0.2").To4() + startOfIPPool := net.ParseIP("10.0.0.10").To4() + endOfIPPool := net.ParseIP("10.0.0.11").To4() + + // setup twice NAT pool + Expect(natHandler.AddNat44AddressPool(0, startOfIPPool.String(), endOfIPPool.String(), true)).Should(Succeed()) + + tests := []struct { + name string + input *nat.DNat44_StaticMapping + expectedDump *nat.DNat44_StaticMapping + excludeUnsupportedVPPVersions []string + }{ + { + name: "simple NAT44 static mapping", + input: &nat.DNat44_StaticMapping{ + Protocol: nat.DNat44_TCP, + ExternalIp: externalIP.String(), + LocalIps: []*nat.DNat44_StaticMapping_LocalIP{ + { + LocalIp: localIP.String(), + }, + }, + }, + }, + { + name: "NAT44 static mapping with twice nat", + input: &nat.DNat44_StaticMapping{ + Protocol: nat.DNat44_TCP, + ExternalIp: externalIP.String(), + ExternalPort: 80, + LocalIps: []*nat.DNat44_StaticMapping_LocalIP{ + { + LocalIp: localIP.String(), + LocalPort: 8080, + }, + }, + TwiceNat: nat.DNat44_StaticMapping_ENABLED, + }, + }, + { + name: "NAT44 static mapping with twice nat and twice NAT pool IP", + excludeUnsupportedVPPVersions: []string{vpp1908, vpp2001, vpp2005}, + input: &nat.DNat44_StaticMapping{ + Protocol: nat.DNat44_TCP, + ExternalIp: externalIP.String(), + ExternalPort: 80, + LocalIps: []*nat.DNat44_StaticMapping_LocalIP{ + { + LocalIp: localIP.String(), + LocalPort: 8080, + }, + }, + TwiceNat: nat.DNat44_StaticMapping_ENABLED, + TwiceNatPoolIp: endOfIPPool.String(), + }, + expectedDump: &nat.DNat44_StaticMapping{ + // just missing TwiceNatPoolIp (VPP doesnt dump it) + // TODO: fix test when dump will dump currently missing information + Protocol: nat.DNat44_TCP, + ExternalIp: externalIP.String(), + ExternalPort: 80, + LocalIps: []*nat.DNat44_StaticMapping_LocalIP{ + { + LocalIp: localIP.String(), + LocalPort: 8080, + }, + }, + TwiceNat: nat.DNat44_StaticMapping_ENABLED, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + // exclude test testing feature not supported in currently tested VPP version + for _, excludedVPPVersion := range test.excludeUnsupportedVPPVersions { + if ctx.versionInfo.Release() == excludedVPPVersion { + return + } + } + + // Create + Expect(test).ShouldNot(BeNil()) + Expect(natHandler.AddNat44StaticMapping(test.input, dnatLabel)).Should(Succeed()) + + // Read + dnatDump, err := natHandler.DNat44Dump() + t.Logf("received this dnat from dump: %v", dnatDump) + Expect(err).ShouldNot(HaveOccurred()) + expected := test.input + if test.expectedDump != nil { + expected = test.expectedDump + } + Expect(dnatDump).To(HaveLen(1)) + Expect(dnatDump[0].StMappings).To(HaveLen(1)) + Expect(proto.Equal(dnatDump[0].StMappings[0], expected)).To(BeTrue()) + + // Delete + Expect(natHandler.DelNat44StaticMapping(test.input, dnatLabel)).Should(Succeed()) + }) + } +} diff --git a/tests/integration/vpp/integration_test.go b/tests/integration/vpp/integration_test.go index a8542e6382..207ec01d30 100644 --- a/tests/integration/vpp/integration_test.go +++ b/tests/integration/vpp/integration_test.go @@ -65,6 +65,9 @@ const ( } plugins { plugin dpdk_plugin.so { disable } + } + nat { + endpoint-dependent }` )