Skip to content

Commit b13eba1

Browse files
authored
Merge pull request #186 from zvfvrv/srv6-dev
Support SRv6
2 parents ec6e2b9 + 38bc167 commit b13eba1

29 files changed

+3183
-11
lines changed

Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ load-images:
6464
test-install-calicovpp:
6565
kubectl apply -k yaml/overlays/test-vagrant
6666

67+
# Allows to simply run calico-vpp from release images in a test cluster with SRv6 configured
68+
.PHONY: test-install-calicovpp-srv6
69+
test-install-calicovpp-srv6:
70+
kubectl kustomize yaml/overlays/test-vagrant-srv6 | kubectl apply -f -
71+
6772
# Allows to run calico-vpp in a test cluster with locally-built binaries for dev / debug
6873
.PHONY: test-install-calicovpp-dev
6974
test-install-calicovpp-dev:
@@ -77,6 +82,10 @@ test-install-calicovpp-v6:
7782
test-install-calicovpp-dev-v6:
7883
kubectl apply -k yaml/overlays/test-vagrant-v6-mounts
7984

85+
.PHONY: test-install-calicovpp-dev-srv6
86+
test-install-calicovpp-dev-srv6:
87+
kubectl kustomize yaml/overlays/test-vagrant-srv6-mounts | kubectl apply -f -
88+
8089
.PHONY: run-tests
8190
run-tests:
8291
test/scripts/test.sh up iperf v4

calico-vpp-agent/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@ dev: build gobgp
4040
docker build -t calicovpp/agent:$(TAG) .
4141

4242
proto:
43-
$(MAKE) -C proto $@
43+
$(MAKE) -C proto $@

calico-vpp-agent/config/config.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ const (
5959
IpsecNbAsyncCryptoThEnvVar = "CALICOVPP_IPSEC_NB_ASYNC_CRYPTO_THREAD"
6060
LogLevelEnvVar = "CALICO_LOG_LEVEL"
6161
ServicePrefixEnvVar = "SERVICE_PREFIX"
62+
EnableSRv6EnvVar = "CALICOVPP_SRV6_ENABLED"
63+
SRv6LocalsidPoolEnvVar = "CALICOVPP_SR_LS_POOL"
64+
SRv6PolicyPoolEnvVar = "CALICOVPP_SR_POLICY_POOL"
6265

6366
MemifSocketName = "@vpp/memif"
6467
DefaultVXLANVni = 4096
@@ -80,6 +83,7 @@ var (
8083
EnableServices = true
8184
EnablePolicies = true
8285
EnableIPSec = false
86+
EnableSRv6 = false
8387
IpsecAddressCount = 1
8488
CrossIpsecTunnels = false
8589
IPSecIkev2Psk = ""
@@ -93,6 +97,8 @@ var (
9397
HostMtu int = 0
9498
PodMtu int = 0
9599
IpsecNbAsyncCryptoThread int = 0
100+
SRv6policyIPPool = ""
101+
SRv6localSidIPPool = ""
96102

97103
felixConfigReceived = false
98104
felixConfigChan = make(chan struct{})
@@ -126,6 +132,7 @@ func PrintAgentConfig(log *logrus.Logger) {
126132
log.Infof("Config:HostMtu %d", HostMtu)
127133
log.Infof("Config:PodMtu %d", PodMtu)
128134
log.Infof("Config:IpsecNbAsyncCryptoThread %d", IpsecNbAsyncCryptoThread)
135+
log.Infof("Config:EnableSRv6 %t", EnableSRv6)
129136
}
130137

131138
var supportedEnvVars map[string]bool
@@ -290,6 +297,22 @@ func LoadConfig(log *logrus.Logger) (err error) {
290297
}
291298
}
292299

300+
if conf := getEnvValue(EnableSRv6EnvVar); conf != "" {
301+
enableSRv6, err := strconv.ParseBool(conf)
302+
if err != nil {
303+
return fmt.Errorf("Invalid %s configuration: %s parses to %v err %v", EnableSRv6EnvVar, conf, enableSRv6, err)
304+
}
305+
EnableSRv6 = enableSRv6
306+
}
307+
308+
if conf := getEnvValue(SRv6PolicyPoolEnvVar); conf != "" {
309+
SRv6policyIPPool = conf
310+
}
311+
312+
if conf := getEnvValue(SRv6LocalsidPoolEnvVar); conf != "" {
313+
SRv6localSidIPPool = conf
314+
}
315+
293316
psk := getEnvValue(IPSecIkev2PskEnvVar)
294317
if EnableIPSec && psk == "" {
295318
return errors.New("IKEv2 PSK not configured: nothing found in CALICOVPP_IPSEC_IKEV2_PSK environment variable")

calico-vpp-agent/routing/common/common.go

Lines changed: 133 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ import (
2828
oldv3 "github.com/projectcalico/libcalico-go/lib/apis/v3"
2929
calicocli "github.com/projectcalico/libcalico-go/lib/client"
3030
calicov3cli "github.com/projectcalico/libcalico-go/lib/clientv3"
31+
"github.com/projectcalico/vpp-dataplane/calico-vpp-agent/config"
3132
"github.com/projectcalico/vpp-dataplane/vpplink"
33+
"github.com/projectcalico/vpp-dataplane/vpplink/types"
34+
"google.golang.org/protobuf/types/known/anypb"
3235
)
3336

3437
const (
@@ -39,7 +42,9 @@ const (
3942

4043
var (
4144
BgpFamilyUnicastIPv4 = bgpapi.Family{Afi: bgpapi.Family_AFI_IP, Safi: bgpapi.Family_SAFI_UNICAST}
45+
BgpFamilySRv6IPv4 = bgpapi.Family{Afi: bgpapi.Family_AFI_IP, Safi: bgpapi.Family_SAFI_SR_POLICY}
4246
BgpFamilyUnicastIPv6 = bgpapi.Family{Afi: bgpapi.Family_AFI_IP6, Safi: bgpapi.Family_SAFI_UNICAST}
47+
BgpFamilySRv6IPv6 = bgpapi.Family{Afi: bgpapi.Family_AFI_IP6, Safi: bgpapi.Family_SAFI_SR_POLICY}
4348
)
4449

4550
// Data managed by the routing server and
@@ -115,9 +120,17 @@ func MakePath(prefix string, isWithdrawal bool, nodeIpv4 net.IP, nodeIpv6 net.IP
115120

116121
if v4 {
117122
family = &BgpFamilyUnicastIPv4
118-
nhAttr, err := ptypes.MarshalAny(&bgpapi.NextHopAttribute{
119-
NextHop: nodeIpv4.String(),
120-
})
123+
var nhAttr *anypb.Any
124+
125+
if config.EnableSRv6 {
126+
nhAttr, err = ptypes.MarshalAny(&bgpapi.NextHopAttribute{
127+
NextHop: nodeIpv6.String(),
128+
})
129+
} else {
130+
nhAttr, err = ptypes.MarshalAny(&bgpapi.NextHopAttribute{
131+
NextHop: nodeIpv4.String(),
132+
})
133+
}
121134
if err != nil {
122135
return nil, err
123136
}
@@ -147,6 +160,111 @@ func MakePath(prefix string, isWithdrawal bool, nodeIpv4 net.IP, nodeIpv6 net.IP
147160
}, nil
148161
}
149162

163+
func MakePathSRv6Tunnel(localSid net.IP, bSid net.IP, nodeIpv6 net.IP, trafficType int, isWithdrawal bool) (*bgpapi.Path, error) {
164+
originAttr, err := ptypes.MarshalAny(&bgpapi.OriginAttribute{Origin: 0})
165+
if err != nil {
166+
return nil, err
167+
}
168+
attrs := []*any.Any{originAttr}
169+
170+
var family *bgpapi.Family
171+
var nodeIP = nodeIpv6
172+
var epbs = &bgpapi.SRv6EndPointBehavior{}
173+
family = &BgpFamilySRv6IPv6
174+
if trafficType == 4 {
175+
epbs.Behavior = bgpapi.SRv6Behavior_END_DT4
176+
} else {
177+
epbs.Behavior = bgpapi.SRv6Behavior_END_DT6
178+
}
179+
180+
nlrisr, err := ptypes.MarshalAny(&bgpapi.SRPolicyNLRI{
181+
Length: 192,
182+
Endpoint: nodeIP,
183+
})
184+
185+
if err != nil {
186+
return nil, err
187+
}
188+
nhAttr, err := ptypes.MarshalAny(&bgpapi.NextHopAttribute{
189+
NextHop: nodeIP.String(),
190+
})
191+
if err != nil {
192+
return nil, err
193+
}
194+
attrs = append(attrs, nhAttr)
195+
196+
sid, err := ptypes.MarshalAny(&bgpapi.SRBindingSID{
197+
SFlag: true,
198+
IFlag: false,
199+
Sid: bSid,
200+
})
201+
202+
if err != nil {
203+
return nil, err
204+
}
205+
bsid, err := ptypes.MarshalAny(&bgpapi.TunnelEncapSubTLVSRBindingSID{
206+
Bsid: sid,
207+
})
208+
if err != nil {
209+
return nil, err
210+
}
211+
212+
segment, err := ptypes.MarshalAny(&bgpapi.SegmentTypeB{
213+
Flags: &bgpapi.SegmentFlags{SFlag: true},
214+
Sid: localSid,
215+
EndpointBehaviorStructure: epbs,
216+
})
217+
if err != nil {
218+
return nil, err
219+
}
220+
seglist, err := ptypes.MarshalAny(&bgpapi.TunnelEncapSubTLVSRSegmentList{
221+
Weight: &bgpapi.SRWeight{
222+
Flags: 0,
223+
Weight: 12,
224+
},
225+
Segments: []*any.Any{segment},
226+
})
227+
if err != nil {
228+
return nil, err
229+
}
230+
pref, err := ptypes.MarshalAny(&bgpapi.TunnelEncapSubTLVSRPreference{
231+
Flags: 0,
232+
Preference: 11,
233+
})
234+
if err != nil {
235+
return nil, err
236+
}
237+
238+
pri, err := ptypes.MarshalAny(&bgpapi.TunnelEncapSubTLVSRPriority{
239+
Priority: 10,
240+
})
241+
if err != nil {
242+
return nil, err
243+
}
244+
// Tunnel Encapsulation attribute for SR Policy
245+
tun, err := ptypes.MarshalAny(&bgpapi.TunnelEncapAttribute{
246+
Tlvs: []*bgpapi.TunnelEncapTLV{
247+
{
248+
Type: 15,
249+
Tlvs: []*anypb.Any{bsid, seglist, pref, pri},
250+
},
251+
},
252+
})
253+
if err != nil {
254+
return nil, err
255+
}
256+
attrs = append(attrs, tun)
257+
258+
return &bgpapi.Path{
259+
Nlri: nlrisr,
260+
IsWithdraw: isWithdrawal,
261+
Pattrs: attrs,
262+
Age: ptypes.TimestampNow(),
263+
Family: family,
264+
}, nil
265+
266+
}
267+
150268
type ChangeType int
151269

152270
const (
@@ -181,6 +299,8 @@ const (
181299
RescanState ConnectivityEventType = "RescanState"
182300
ConnectivtyAdded ConnectivityEventType = "ConnectivtyAdded"
183301
ConnectivtyDeleted ConnectivityEventType = "ConnectivtyDeleted"
302+
SRv6PolicyAdded ConnectivityEventType = "SRv6PolicyAdded"
303+
SRv6PolicyDeleted ConnectivityEventType = "SRv6PolicyDeleted"
184304
)
185305

186306
type ConnectivityEvent struct {
@@ -194,8 +314,18 @@ type NodeConnectivity struct {
194314
Dst net.IPNet
195315
NextHop net.IP
196316
ResolvedProvider string
317+
Custom interface{}
197318
}
198319

199320
func (cn *NodeConnectivity) String() string {
200321
return fmt.Sprintf("%s-%s", cn.Dst.String(), cn.NextHop.String())
201322
}
323+
324+
type SRv6Tunnel struct {
325+
Dst net.IP
326+
Bsid net.IP
327+
Policy *types.SrPolicy
328+
Sid net.IP
329+
Behavior uint8
330+
Priority uint32
331+
}

calico-vpp-agent/routing/connectivity/connectivity.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const (
3232
VXLAN = "vxlan"
3333
IPIP = "ipip"
3434
WIREGUARD = "wireguard"
35+
SRv6 = "srv6"
3536
)
3637

3738
type ConnectivityProviderData struct {

calico-vpp-agent/routing/connectivity/connectivity_server.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"net"
2020

2121
calicov3 "github.com/projectcalico/api/pkg/apis/projectcalico/v3"
22+
"github.com/projectcalico/vpp-dataplane/calico-vpp-agent/config"
2223
"github.com/projectcalico/vpp-dataplane/calico-vpp-agent/routing/common"
2324
"github.com/projectcalico/vpp-dataplane/calico-vpp-agent/routing/watchers"
2425
"github.com/sirupsen/logrus"
@@ -72,6 +73,7 @@ func NewConnectivityServer(routingData *common.RoutingData,
7273
server.providers[IPSEC] = NewIPsecProvider(providerData)
7374
server.providers[VXLAN] = NewVXLanProvider(providerData)
7475
server.providers[WIREGUARD] = NewWireguardProvider(providerData)
76+
server.providers[SRv6] = NewSRv6Provider(providerData)
7577

7678
server.TunnelChangeChan = providerData.tunnelChangeChan
7779

@@ -182,13 +184,29 @@ func (s *ConnectivityServer) ServeConnectivity() error {
182184
s.log.Infof("VXLAN/IPIPMode Changed")
183185
s.updateAllIPConnectivity()
184186
}
187+
case common.SRv6PolicyAdded:
188+
new := evt.New.(*common.NodeConnectivity)
189+
190+
err := s.updateSRv6Policy(new, false /* isWithdraw */)
191+
if err != nil {
192+
s.log.Errorf("Error while adding SRv6 Policy %s", err)
193+
}
194+
case common.SRv6PolicyDeleted:
195+
old := evt.Old.(*common.NodeConnectivity)
196+
err := s.updateSRv6Policy(old, true /* isWithdraw */)
197+
if err != nil {
198+
s.log.Errorf("Error while deleting SRv6 Policy %s", err)
199+
}
185200
}
186201
}
187202
return nil
188203
}
189204

190205
func (s *ConnectivityServer) getProviderType(cn *common.NodeConnectivity) string {
191206
ipPool := s.ipam.GetPrefixIPPool(&cn.Dst)
207+
if config.EnableSRv6 {
208+
return SRv6
209+
}
192210
if ipPool == nil {
193211
return FLAT
194212
}
@@ -259,3 +277,14 @@ func (s *ConnectivityServer) updateIPConnectivity(cn *common.NodeConnectivity, I
259277
}
260278
}
261279
}
280+
281+
func (s *ConnectivityServer) updateSRv6Policy(cn *common.NodeConnectivity, IsWithdraw bool) (err error) {
282+
s.log.Infof("updateSRv6Policy")
283+
providerType := SRv6
284+
if IsWithdraw {
285+
err = s.providers[providerType].DelConnectivity(cn)
286+
} else {
287+
err = s.providers[providerType].AddConnectivity(cn)
288+
}
289+
return err
290+
}

0 commit comments

Comments
 (0)