Skip to content

Commit

Permalink
feat: added dependency for NAT44 static mapping that is referencing I…
Browse files Browse the repository at this point in the history
…P from twiceNAT address pool

Signed-off-by: Filip Gschwandtner <filip.gschwandtner@pantheon.tech>
  • Loading branch information
fgschwan committed Sep 16, 2020
1 parent aaeb5b2 commit 0d43513
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 2 deletions.
16 changes: 16 additions & 0 deletions plugins/vpp/natplugin/descriptor/nat44_address_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -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},
}
Expand Down Expand Up @@ -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 &&
Expand Down
35 changes: 33 additions & 2 deletions plugins/vpp/natplugin/descriptor/nat44_dnat.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
package descriptor

import (
"bytes"
"net"
"strconv"

"github.com/golang/protobuf/proto"
Expand All @@ -39,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:
Expand Down Expand Up @@ -270,6 +273,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
}

Expand Down
50 changes: 50 additions & 0 deletions proto/ligato/vpp/nat/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
package vpp_nat

import (
"fmt"
"strconv"
"strings"

"go.ligato.io/vpp-agent/v3/pkg/models"
Expand Down Expand Up @@ -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 (
Expand Down Expand Up @@ -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
}

0 comments on commit 0d43513

Please sign in to comment.