Skip to content

Commit 5979579

Browse files
rewensetrewenset
rewenset
authored and
rewenset
committed
feat: Add VRF field to proxy ARP range
test-e2e
1 parent dfd2d53 commit 5979579

17 files changed

+668
-187
lines changed

plugins/vpp/l3plugin/descriptor/proxy_arp.go

+107-62
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2018 Cisco and/or its affiliates.
1+
// Copyright (c) 2020 Cisco and/or its affiliates.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -32,6 +32,21 @@ import (
3232
const (
3333
// ProxyArpDescriptorName is the name of the descriptor.
3434
ProxyArpDescriptorName = "vpp-proxy-arp"
35+
36+
// Dependency labels:
37+
vrfTableProxyARPDep = "vrf-table-exists"
38+
)
39+
40+
// Validation errors:
41+
var (
42+
// ErrMissingIP returned when one of IP fields in ProxyARP range is not set.
43+
ErrMissingIP = errors.New("missing IP address")
44+
// ErrIPWithMask returned when one of IP fields in ProxyARP range is set with a subnet mask.
45+
ErrIPWithMask = errors.New("only one IP must be defined (e.g. \"192.0.2.1\"), not a subnet")
46+
// ErrInvalidIP returned when one of IP fields in ProxyARP range can not be parsed.
47+
ErrInvalidIP = errors.New("invalid IP address")
48+
// ErrIPv6NotSupported returned when one of IP fields in ProxyARP range is defined as IPv6.
49+
ErrIPv6NotSupported = errors.New("IP address must be IPv4, not IPv6")
3550
)
3651

3752
// ProxyArpDescriptor teaches KVScheduler how to configure VPP proxy ARPs.
@@ -57,19 +72,73 @@ func NewProxyArpDescriptor(scheduler kvs.KVScheduler,
5772
ValueTypeName: l3.ModelProxyARP.ProtoName(),
5873
KeySelector: l3.ModelProxyARP.IsKeyValid,
5974
ValueComparator: ctx.EquivalentProxyArps,
75+
Validate: ctx.Validate,
6076
Create: ctx.Create,
6177
Update: ctx.Update,
6278
Delete: ctx.Delete,
6379
Retrieve: ctx.Retrieve,
80+
Dependencies: ctx.Dependencies,
6481
DerivedValues: ctx.DerivedValues,
6582
RetrieveDependencies: []string{ifdescriptor.InterfaceDescriptorName},
6683
}
6784
return adapter.NewProxyARPDescriptor(typedDescr)
6885
}
6986

70-
// DerivedValues derives l3.ProxyARP_Interface for every interface..
87+
// Validate validates ProxyARP setup.
88+
func (d *ProxyArpDescriptor) Validate(key string, proxyArp *l3.ProxyARP) error {
89+
for _, r := range proxyArp.Ranges {
90+
if r.FirstIpAddr == "" {
91+
return kvs.NewInvalidValueError(ErrMissingIP, "ranges.first_ip_addr")
92+
}
93+
if r.LastIpAddr == "" {
94+
return kvs.NewInvalidValueError(ErrMissingIP, "ranges.last_ip_addr")
95+
}
96+
97+
if strings.Contains(r.FirstIpAddr, "/") {
98+
return kvs.NewInvalidValueError(ErrIPWithMask, "ranges.first_ip_addr")
99+
}
100+
if strings.Contains(r.LastIpAddr, "/") {
101+
return kvs.NewInvalidValueError(ErrIPWithMask, "ranges.last_ip_addr")
102+
}
103+
104+
firstIP := net.ParseIP(r.FirstIpAddr)
105+
if firstIP == nil {
106+
return kvs.NewInvalidValueError(ErrInvalidIP, "ranges.first_ip_addr")
107+
}
108+
lastIP := net.ParseIP(r.LastIpAddr)
109+
if lastIP == nil {
110+
return kvs.NewInvalidValueError(ErrInvalidIP, "ranges.last_ip_addr")
111+
}
112+
113+
if firstIP.To4() == nil {
114+
return kvs.NewInvalidValueError(ErrIPv6NotSupported, "ranges.first_ip_addr")
115+
}
116+
if lastIP.To4() == nil {
117+
return kvs.NewInvalidValueError(ErrIPv6NotSupported, "ranges.last_ip_addr")
118+
}
119+
}
120+
return nil
121+
}
122+
123+
// Dependencies lists dependencies for a VPP Proxy ARP.
124+
func (d *ProxyArpDescriptor) Dependencies(key string, proxyArp *l3.ProxyARP) []kvs.Dependency {
125+
var dependencies []kvs.Dependency
126+
127+
for _, r := range proxyArp.Ranges {
128+
if r.VrfId == 0 {
129+
continue
130+
}
131+
dependencies = append(dependencies, kvs.Dependency{
132+
Label: vrfTableProxyARPDep,
133+
Key: l3.VrfTableKey(r.VrfId, l3.VrfTable_IPV4),
134+
})
135+
}
136+
137+
return dependencies
138+
}
139+
140+
// DerivedValues derives l3.ProxyARP_Interface for every interface.
71141
func (d *ProxyArpDescriptor) DerivedValues(key string, proxyArp *l3.ProxyARP) (derValues []kvs.KeyValuePair) {
72-
// IP addresses
73142
for _, iface := range proxyArp.Interfaces {
74143
derValues = append(derValues, kvs.KeyValuePair{
75144
Key: l3.ProxyARPInterfaceKey(iface.Name),
@@ -90,16 +159,12 @@ func (d *ProxyArpDescriptor) EquivalentProxyArps(key string, oldValue, newValue
90159

91160
// Create adds VPP Proxy ARP.
92161
func (d *ProxyArpDescriptor) Create(key string, value *l3.ProxyARP) (metadata interface{}, err error) {
93-
for _, proxyArpRange := range value.Ranges {
94-
// Prune addresses
95-
firstIP := pruneIP(proxyArpRange.FirstIpAddr)
96-
lastIP := pruneIP(proxyArpRange.LastIpAddr)
97-
// Convert to byte representation
98-
bFirstIP := net.ParseIP(firstIP).To4()
99-
bLastIP := net.ParseIP(lastIP).To4()
100-
// Call VPP API to configure IP range for proxy ARP
101-
if err := d.proxyArpHandler.AddProxyArpRange(bFirstIP, bLastIP); err != nil {
102-
return nil, errors.Errorf("failed to add proxy ARP address range %s - %s: %v", firstIP, lastIP, err)
162+
for _, r := range value.Ranges {
163+
firstIP := net.ParseIP(r.FirstIpAddr).To4()
164+
lastIP := net.ParseIP(r.LastIpAddr).To4()
165+
166+
if err := d.proxyArpHandler.AddProxyArpRange(firstIP, lastIP, r.VrfId); err != nil {
167+
return nil, errors.Errorf("failed to add proxy ARP address range %s - %s (VRF: %d): %v", firstIP, lastIP, r.VrfId, err)
103168
}
104169
}
105170
return nil, nil
@@ -108,30 +173,22 @@ func (d *ProxyArpDescriptor) Create(key string, value *l3.ProxyARP) (metadata in
108173
// Update modifies VPP Proxy ARP.
109174
func (d *ProxyArpDescriptor) Update(key string, oldValue, newValue *l3.ProxyARP, oldMetadata interface{}) (newMetadata interface{}, err error) {
110175
toAdd, toDelete := calculateRngDiff(newValue.Ranges, oldValue.Ranges)
111-
// Remove old ranges
112-
for _, proxyArpRange := range toDelete {
113-
// Prune addresses
114-
firstIP := pruneIP(proxyArpRange.FirstIpAddr)
115-
lastIP := pruneIP(proxyArpRange.LastIpAddr)
116-
// Convert to byte representation
117-
bFirstIP := net.ParseIP(firstIP).To4()
118-
bLastIP := net.ParseIP(lastIP).To4()
119-
// Call VPP API to configure IP range for proxy ARP
120-
if err := d.proxyArpHandler.DeleteProxyArpRange(bFirstIP, bLastIP); err != nil {
121-
return nil, errors.Errorf("failed to delete proxy ARP address range %s - %s: %v", firstIP, lastIP, err)
122-
}
123-
}
124-
// Add new ranges
125-
for _, proxyArpRange := range toAdd {
126-
// Prune addresses
127-
firstIP := pruneIP(proxyArpRange.FirstIpAddr)
128-
lastIP := pruneIP(proxyArpRange.LastIpAddr)
129-
// Convert to byte representation
130-
bFirstIP := net.ParseIP(firstIP).To4()
131-
bLastIP := net.ParseIP(lastIP).To4()
132-
// Call VPP API to configure IP range for proxy ARP
133-
if err := d.proxyArpHandler.AddProxyArpRange(bFirstIP, bLastIP); err != nil {
134-
return nil, errors.Errorf("failed to add proxy ARP address range %s - %s: %v", firstIP, lastIP, err)
176+
177+
for _, r := range toDelete {
178+
firstIP := net.ParseIP(r.FirstIpAddr).To4()
179+
lastIP := net.ParseIP(r.LastIpAddr).To4()
180+
181+
if err := d.proxyArpHandler.DeleteProxyArpRange(firstIP, lastIP, r.VrfId); err != nil {
182+
return nil, errors.Errorf("failed to delete proxy ARP address range %s - %s (VRF: %d): %v", firstIP, lastIP, r.VrfId, err)
183+
}
184+
}
185+
186+
for _, r := range toAdd {
187+
firstIP := net.ParseIP(r.FirstIpAddr).To4()
188+
lastIP := net.ParseIP(r.LastIpAddr).To4()
189+
190+
if err := d.proxyArpHandler.AddProxyArpRange(firstIP, lastIP, r.VrfId); err != nil {
191+
return nil, errors.Errorf("failed to add proxy ARP address range %s - %s (VRF: %d): %v", firstIP, lastIP, r.VrfId, err)
135192
}
136193
}
137194

@@ -140,16 +197,12 @@ func (d *ProxyArpDescriptor) Update(key string, oldValue, newValue *l3.ProxyARP,
140197

141198
// Delete deletes VPP Proxy ARP.
142199
func (d *ProxyArpDescriptor) Delete(key string, value *l3.ProxyARP, metadata interface{}) error {
143-
for _, proxyArpRange := range value.Ranges {
144-
// Prune addresses
145-
firstIP := pruneIP(proxyArpRange.FirstIpAddr)
146-
lastIP := pruneIP(proxyArpRange.LastIpAddr)
147-
// Convert to byte representation
148-
bFirstIP := net.ParseIP(firstIP).To4()
149-
bLastIP := net.ParseIP(lastIP).To4()
150-
// Call VPP API to configure IP range for proxy ARP
151-
if err := d.proxyArpHandler.DeleteProxyArpRange(bFirstIP, bLastIP); err != nil {
152-
return errors.Errorf("failed to delete proxy ARP address range %s - %s: %v", firstIP, lastIP, err)
200+
for _, r := range value.Ranges {
201+
firstIP := net.ParseIP(r.FirstIpAddr).To4()
202+
lastIP := net.ParseIP(r.LastIpAddr).To4()
203+
204+
if err := d.proxyArpHandler.DeleteProxyArpRange(firstIP, lastIP, r.VrfId); err != nil {
205+
return errors.Errorf("failed to delete proxy ARP address range %s - %s (VRF: %d): %v", firstIP, lastIP, r.VrfId, err)
153206
}
154207
}
155208
return nil
@@ -186,23 +239,14 @@ func (d *ProxyArpDescriptor) Retrieve(correlate []adapter.ProxyARPKVWithMetadata
186239
return retrieved, nil
187240
}
188241

189-
// Remove IP mask if set
190-
func pruneIP(ip string) string {
191-
ipParts := strings.Split(ip, "/")
192-
switch len(ipParts) {
193-
case 1, 2:
194-
return ipParts[0]
195-
}
196-
return ip
197-
}
198-
199-
// Calculate difference between old and new ranges
242+
// calculateRngDiff calculates difference between old and new ranges.
200243
func calculateRngDiff(newRngs, oldRngs []*l3.ProxyARP_Range) (toAdd, toDelete []*l3.ProxyARP_Range) {
201-
// Find missing ranges
244+
// Find missing ranges.
202245
for _, newRng := range newRngs {
203246
var found bool
204247
for _, oldRng := range oldRngs {
205-
if newRng.FirstIpAddr == oldRng.FirstIpAddr &&
248+
if newRng.VrfId == oldRng.VrfId &&
249+
newRng.FirstIpAddr == oldRng.FirstIpAddr &&
206250
newRng.LastIpAddr == oldRng.LastIpAddr {
207251
found = true
208252
break
@@ -212,11 +256,12 @@ func calculateRngDiff(newRngs, oldRngs []*l3.ProxyARP_Range) (toAdd, toDelete []
212256
toAdd = append(toAdd, newRng)
213257
}
214258
}
215-
// Find obsolete interfaces
259+
// Find obsolete ranges.
216260
for _, oldRng := range oldRngs {
217261
var found bool
218262
for _, newRng := range newRngs {
219-
if oldRng.FirstIpAddr == newRng.FirstIpAddr &&
263+
if oldRng.VrfId == newRng.VrfId &&
264+
oldRng.FirstIpAddr == newRng.FirstIpAddr &&
220265
oldRng.LastIpAddr == newRng.LastIpAddr {
221266
found = true
222267
break

plugins/vpp/l3plugin/vppcalls/l3_vppcalls.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,9 @@ type ProxyArpVppAPI interface {
122122
// DisableProxyArpInterface disables interface for proxy ARP
123123
DisableProxyArpInterface(ifName string) error
124124
// AddProxyArpRange adds new IP range for proxy ARP
125-
AddProxyArpRange(firstIP, lastIP []byte) error
125+
AddProxyArpRange(firstIP, lastIP []byte, vrfID uint32) error
126126
// DeleteProxyArpRange removes proxy ARP IP range
127-
DeleteProxyArpRange(firstIP, lastIP []byte) error
127+
DeleteProxyArpRange(firstIP, lastIP []byte, vrfID uint32) error
128128
}
129129

130130
// ProxyArpVppRead provides read methods for proxy ARPs

plugins/vpp/l3plugin/vppcalls/vpp1904/proxyarp_dump.go

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ func (h *ProxyArpVppHandler) DumpProxyArpRanges() (pArpRngs []*vppcalls.ProxyArp
4141
Range: &l3.ProxyARP_Range{
4242
FirstIpAddr: net.IP(proxyArpDetails.Proxy.Low[:]).To4().String(),
4343
LastIpAddr: net.IP(proxyArpDetails.Proxy.Hi[:]).To4().String(),
44+
VrfId: proxyArpDetails.Proxy.TableID,
4445
},
4546
})
4647
}

plugins/vpp/l3plugin/vppcalls/vpp1904/proxyarp_vppcalls.go

+25-8
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
package vpp1904
1616

1717
import (
18+
"fmt"
19+
"net"
20+
1821
"github.com/pkg/errors"
1922
"go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp1904/ip"
2023
)
@@ -30,13 +33,13 @@ func (h *ProxyArpVppHandler) DisableProxyArpInterface(ifName string) error {
3033
}
3134

3235
// AddProxyArpRange implements proxy arp handler.
33-
func (h *ProxyArpVppHandler) AddProxyArpRange(firstIP, lastIP []byte) error {
34-
return h.vppAddDelProxyArpRange(firstIP, lastIP, true)
36+
func (h *ProxyArpVppHandler) AddProxyArpRange(firstIP, lastIP []byte, vrfID uint32) error {
37+
return h.vppAddDelProxyArpRange(firstIP, lastIP, vrfID, true)
3538
}
3639

3740
// DeleteProxyArpRange implements proxy arp handler.
38-
func (h *ProxyArpVppHandler) DeleteProxyArpRange(firstIP, lastIP []byte) error {
39-
return h.vppAddDelProxyArpRange(firstIP, lastIP, false)
41+
func (h *ProxyArpVppHandler) DeleteProxyArpRange(firstIP, lastIP []byte, vrfID uint32) error {
42+
return h.vppAddDelProxyArpRange(firstIP, lastIP, vrfID, false)
4043
}
4144

4245
// vppAddDelProxyArpInterface adds or removes proxy ARP interface entry according to provided input
@@ -61,10 +64,24 @@ func (h *ProxyArpVppHandler) vppAddDelProxyArpInterface(ifName string, enable bo
6164
return nil
6265
}
6366

64-
// vppAddDelProxyArpRange adds or removes proxy ARP range according to provided input
65-
func (h *ProxyArpVppHandler) vppAddDelProxyArpRange(firstIP, lastIP []byte, isAdd bool) error {
67+
// vppAddDelProxyArpRange adds or removes proxy ARP range according to provided input.
68+
func (h *ProxyArpVppHandler) vppAddDelProxyArpRange(firstIP, lastIP []byte, vrf uint32, isAdd bool) error {
69+
validateIPBytes := func(b []byte) error {
70+
ip := net.IP(b)
71+
if ip.To4() == nil {
72+
return fmt.Errorf("IP bytes %v are not valid IPv4 address", b)
73+
}
74+
return nil
75+
}
76+
if err := validateIPBytes(firstIP); err != nil {
77+
return fmt.Errorf("bad first IP: %v", err)
78+
}
79+
if err := validateIPBytes(lastIP); err != nil {
80+
return fmt.Errorf("bad last IP: %v", err)
81+
}
82+
6683
proxy := ip.ProxyArp{
67-
TableID: 0, // TODO: add support for VRF
84+
TableID: vrf,
6885
}
6986
copy(proxy.Low[:], firstIP)
7087
copy(proxy.Hi[:], lastIP)
@@ -79,7 +96,7 @@ func (h *ProxyArpVppHandler) vppAddDelProxyArpRange(firstIP, lastIP []byte, isAd
7996
return err
8097
}
8198

82-
h.log.Debugf("proxy arp range: %v - %v added: %v", req.Proxy.Low, req.Proxy.Hi, isAdd)
99+
h.log.Debugf("proxy arp range: %v - %v (vrf: %d) added: %v", proxy.Low, proxy.Hi, proxy.TableID, isAdd)
83100

84101
return nil
85102
}

0 commit comments

Comments
 (0)