Skip to content

Commit 4ab8042

Browse files
authored
IPv6 Support (#127)
1 parent 7aca726 commit 4ab8042

28 files changed

+416
-128
lines changed

Dockerfile

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
FROM golang:1.22-alpine3.20 as builder
1+
FROM golang:1.23-alpine3.20 AS builder
22
WORKDIR /work
33
COPY . .
44
RUN apk add \
55
make \
66
binutils \
7+
coreutils \
78
git \
89
gcc \
910
libpcap-dev \

cmd/config.go

+1
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,5 @@ type Config struct {
3131
GrpcClientCertFile string `required:"false" desc:"the gRPC client certificate file" envconfig:"grpc_client_cert_file"`
3232
GrpcClientKeyFile string `required:"false" desc:"the gRPC client key file" envconfig:"grpc_client_key_file"`
3333
PXEVlanID uint16 `required:"false" default:"4000" desc:"the id of the pxe vlan" envconfig:"pxe_vlan_id"`
34+
AdditionalRouteMapCIDRs []string `required:"false" default:"10.240.0.0/12" desc:"additional route map entries, typically the pod/service CIDRs, one or more CIDR for ipv4 or ipv6, separated by comma" envconfig:"additional_route_map_cidrs"`
3435
}

cmd/internal/core/core.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ type Core struct {
3333

3434
metrics *metrics.Metrics
3535

36-
pxeVlanID uint16
36+
pxeVlanID uint16
37+
additionalRouteMapCIDRs []string
3738
}
3839

3940
type Config struct {
@@ -59,7 +60,8 @@ type Config struct {
5960

6061
Metrics *metrics.Metrics
6162

62-
PXEVlanID uint16
63+
PXEVlanID uint16
64+
AdditionalRouteMapCIDRs []string
6365
}
6466

6567
func New(c Config) *Core {
@@ -82,5 +84,6 @@ func New(c Config) *Core {
8284
eventServiceClient: c.EventServiceClient,
8385
metrics: c.Metrics,
8486
pxeVlanID: c.PXEVlanID,
87+
additionalRouteMapCIDRs: c.AdditionalRouteMapCIDRs,
8588
}
8689
}

cmd/internal/core/reconfigure-switch.go

+13-11
Original file line numberDiff line numberDiff line change
@@ -116,23 +116,22 @@ func (c *Core) reconfigureSwitch(switchName string) (*models.V1SwitchResponse, e
116116

117117
func (c *Core) buildSwitcherConfig(s *models.V1SwitchResponse) (*types.Conf, error) {
118118
asn64, err := strconv.ParseUint(c.asn, 10, 32)
119-
asn := uint32(asn64)
120119
if err != nil {
121120
return nil, err
122121
}
123-
124122
if c.pxeVlanID >= vlan.VlanIDMin && c.pxeVlanID <= vlan.VlanIDMax {
125123
return nil, fmt.Errorf("configured PXE VLAN ID is in the reserved area of %d, %d", vlan.VlanIDMin, vlan.VlanIDMax)
126124
}
127125

128126
switcherConfig := &types.Conf{
129-
Name: s.Name,
130-
LogLevel: mapLogLevel(c.logLevel),
131-
ASN: asn,
132-
Loopback: c.loopbackIP,
133-
MetalCoreCIDR: c.cidr,
134-
AdditionalBridgeVIDs: c.additionalBridgeVIDs,
135-
PXEVlanID: c.pxeVlanID,
127+
Name: s.Name,
128+
LogLevel: mapLogLevel(c.logLevel),
129+
ASN: uint32(asn64), // nolint:gosec
130+
Loopback: c.loopbackIP,
131+
MetalCoreCIDR: c.cidr,
132+
AdditionalBridgeVIDs: c.additionalBridgeVIDs,
133+
PXEVlanID: c.pxeVlanID,
134+
AdditionalRouteMapCIDRs: c.additionalRouteMapCIDRs,
136135
}
137136

138137
p := types.Ports{
@@ -186,7 +185,7 @@ func (c *Core) buildSwitcherConfig(s *models.V1SwitchResponse) (*types.Conf, err
186185
if err != nil {
187186
return nil, err
188187
}
189-
vrf.VNI = uint32(vni64)
188+
vrf.VNI = uint32(vni64) // nolint:gosec
190189
vrf.Neighbors = append(vrf.Neighbors, port)
191190
if nic.Filter != nil {
192191
vrf.Cidrs = nic.Filter.Cidrs
@@ -196,7 +195,10 @@ func (c *Core) buildSwitcherConfig(s *models.V1SwitchResponse) (*types.Conf, err
196195
switcherConfig.Ports = p
197196

198197
c.nos.SanitizeConfig(switcherConfig)
199-
switcherConfig.FillRouteMapsAndIPPrefixLists()
198+
err = switcherConfig.FillRouteMapsAndIPPrefixLists()
199+
if err != nil {
200+
return nil, err
201+
}
200202
m, err := vlan.ReadMapping()
201203
if err != nil {
202204
return nil, err

cmd/internal/core/reconfigure-switch_test.go

+18-14
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,15 @@ import (
1212

1313
func TestBuildSwitcherConfig(t *testing.T) {
1414
c := &Core{
15-
cidr: "10.255.255.2/24",
16-
partitionID: "fra-equ01",
17-
rackID: "rack01",
18-
asn: "420000001",
19-
loopbackIP: "10.0.0.1",
20-
spineUplinks: []string{"swp31", "swp32"},
21-
additionalBridgeVIDs: []string{"201-256", "301-356"},
22-
nos: &cumulus.Cumulus{},
15+
cidr: "10.255.255.2/24",
16+
partitionID: "fra-equ01",
17+
rackID: "rack01",
18+
asn: "420000001",
19+
loopbackIP: "10.0.0.1",
20+
spineUplinks: []string{"swp31", "swp32"},
21+
additionalBridgeVIDs: []string{"201-256", "301-356"},
22+
nos: &cumulus.Cumulus{},
23+
additionalRouteMapCIDRs: []string{"10.240.0.0/12"},
2324
}
2425

2526
n1 := "swp1"
@@ -53,10 +54,11 @@ func TestBuildSwitcherConfig(t *testing.T) {
5354
require.NoError(t, err)
5455
require.NotNil(t, actual)
5556
expected := &types.Conf{
56-
LogLevel: "warnings",
57-
Loopback: "10.0.0.1",
58-
MetalCoreCIDR: "10.255.255.2/24",
59-
ASN: 420000001,
57+
LogLevel: "warnings",
58+
Loopback: "10.0.0.1",
59+
MetalCoreCIDR: "10.255.255.2/24",
60+
ASN: 420000001,
61+
AdditionalRouteMapCIDRs: []string{"10.240.0.0/12"},
6062
Ports: types.Ports{
6163
DownPorts: map[string]bool{},
6264
Underlay: []string{"swp31", "swp32"},
@@ -73,8 +75,9 @@ func TestBuildSwitcherConfig(t *testing.T) {
7375
Filter: types.Filter{
7476
IPPrefixLists: []types.IPPrefixList{
7577
{
76-
Name: "vrf104001-in-prefixes",
77-
Spec: "permit 10.240.0.0/12 le 32",
78+
AddressFamily: "ip",
79+
Name: "vrf104001-in-prefixes",
80+
Spec: "permit 10.240.0.0/12 le 32",
7881
},
7982
},
8083
RouteMaps: []types.RouteMap{
@@ -87,6 +90,7 @@ func TestBuildSwitcherConfig(t *testing.T) {
8790
},
8891
},
8992
Cidrs: []string{"10.240.0.0/12"},
93+
Has4: true,
9094
}},
9195
},
9296
AdditionalBridgeVIDs: []string{"201-256", "301-356"},

cmd/internal/switcher/templates/template_test.go

+12-5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"testing"
99
"text/template"
1010

11+
"github.com/google/go-cmp/cmp"
1112
"github.com/stretchr/testify/require"
1213
"gopkg.in/yaml.v3"
1314

@@ -39,7 +40,8 @@ func TestCumulusFrrTemplate(t *testing.T) {
3940
tt := tests[i]
4041
t.Run(tt, func(t *testing.T) {
4142
c := readConf(t, path.Join("test_data", tt, "conf.yaml"))
42-
c.FillRouteMapsAndIPPrefixLists()
43+
err := c.FillRouteMapsAndIPPrefixLists()
44+
require.NoError(t, err)
4345
tpl := CumulusFrrTemplate("")
4446
verifyTemplate(t, tpl, &c, path.Join("test_data", tt, "cumulus_frr.conf"))
4547
})
@@ -53,7 +55,8 @@ func TestSonicFrrTpl(t *testing.T) {
5355
t.Run(tt, func(t *testing.T) {
5456
c := readConf(t, path.Join("test_data", tt, "conf.yaml"))
5557
c.CapitalizeVrfName()
56-
c.FillRouteMapsAndIPPrefixLists()
58+
err := c.FillRouteMapsAndIPPrefixLists()
59+
require.NoError(t, err)
5760
tpl := SonicFrrTemplate("")
5861
verifyTemplate(t, tpl, &c, path.Join("test_data", tt, "sonic_frr.conf"))
5962
})
@@ -68,22 +71,26 @@ func TestCustomInterfacesTemplate(t *testing.T) {
6871

6972
func TestCustomCumulusFrrTemplate(t *testing.T) {
7073
c := readConf(t, "test_data/dev/conf.yaml")
71-
c.FillRouteMapsAndIPPrefixLists()
74+
err := c.FillRouteMapsAndIPPrefixLists()
75+
require.NoError(t, err)
7276
tpl := CumulusFrrTemplate("test_data/dev/customtpl/frr.tpl")
7377
verifyTemplate(t, tpl, &c, "test_data/dev/customtpl/frr.conf")
7478
}
7579

7680
func TestCustomSonicFrrTemplate(t *testing.T) {
7781
c := readConf(t, "test_data/dev/conf.yaml")
78-
c.FillRouteMapsAndIPPrefixLists()
82+
err := c.FillRouteMapsAndIPPrefixLists()
83+
require.NoError(t, err)
7984
tpl := SonicFrrTemplate("test_data/dev/customtpl/frr.tpl")
8085
verifyTemplate(t, tpl, &c, "test_data/dev/customtpl/frr.conf")
8186
}
8287

8388
func verifyTemplate(t *testing.T, tpl *template.Template, c *types.Conf, expectedFilename string) {
8489
actual := renderToString(t, tpl, c)
8590
expected := readExpected(t, expectedFilename)
86-
require.Equal(t, expected, actual, "Wanted: %s\nGot: %s", expected, actual)
91+
if diff := cmp.Diff(expected, actual); diff != "" {
92+
t.Errorf("%s render differs:%s", expectedFilename, diff)
93+
}
8794
}
8895

8996
func renderToString(t *testing.T, tpl *template.Template, c *types.Conf) string {

cmd/internal/switcher/templates/test_data/dev/conf.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ loglevel: warnings
44
loopback: 10.0.0.10
55
asn: 4200000010
66
metalcorecidr: 10.255.255.2/24
7+
additionalroutemapcidrs:
8+
- "10.240.0.0/12"
9+
- "fd00:10::/64"
710
ports:
811
eth0:
912
addresscidr: 192.168.101.12/24
@@ -36,6 +39,7 @@ ports:
3639
cidrs:
3740
- "100.127.131.0/24"
3841
- "212.17.234.17/32"
42+
- "2001:db8:3::1/128"
3943
additionalbridgevids:
4044
- 201-256
4145
- 301-356

cmd/internal/switcher/templates/test_data/dev/cumulus_frr.conf

+20-1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ router bgp 4200000010
5353
neighbor swp3 route-map fw-swp3-in in
5454
exit-address-family
5555
!
56+
address-family ipv6 unicast
57+
redistribute connected route-map LOOPBACKS
58+
neighbor FIREWALL allowas-in 2
59+
neighbor FIREWALL activate
60+
neighbor swp3 route-map fw-swp3-in in
61+
exit-address-family
62+
!
5663
address-family l2vpn evpn
5764
advertise-all-vni
5865
neighbor FABRIC activate
@@ -93,16 +100,28 @@ router bgp 4200000010 vrf vrf104001
93100
neighbor MACHINE route-map vrf104001-in in
94101
exit-address-family
95102
!
103+
address-family ipv6 unicast
104+
redistribute connected
105+
neighbor MACHINE maximum-prefix 24000
106+
neighbor MACHINE activate
107+
neighbor MACHINE route-map vrf104001-in6 in
108+
exit-address-family
109+
!
96110
address-family l2vpn evpn
97111
advertise ipv4 unicast
112+
advertise ipv6 unicast
98113
exit-address-family
99114
!
100115
# route-maps for vrf104001
116+
ip prefix-list vrf104001-in-prefixes permit 10.240.0.0/12 le 32
101117
ip prefix-list vrf104001-in-prefixes permit 100.127.131.0/24 le 32
102118
ip prefix-list vrf104001-in-prefixes permit 212.17.234.17/32 le 32
103-
ip prefix-list vrf104001-in-prefixes permit 10.240.0.0/12 le 32
119+
ip prefix-list vrf104001-in6-prefixes permit 2001:db8:3::1/128 le 128
120+
ip prefix-list vrf104001-in6-prefixes permit fd00:10::/64 le 128
104121
route-map vrf104001-in permit 10
105122
match ip address prefix-list vrf104001-in-prefixes
123+
route-map vrf104001-in6 permit 10
124+
match ipv6 address prefix-list vrf104001-in6-prefixes
106125
!
107126
line vty
108127
!

cmd/internal/switcher/templates/test_data/dev/customtpl/frr.conf

+6-1
Original file line numberDiff line numberDiff line change
@@ -96,14 +96,19 @@ router bgp 4200000010 vrf vrf104001
9696
!
9797
address-family l2vpn evpn
9898
advertise ipv4 unicast
99+
advertise ipv6 unicast
99100
exit-address-family
100101
!
101102
# route-maps for vrf104001
103+
ip prefix-list vrf104001-in-prefixes permit 10.240.0.0/12 le 32
102104
ip prefix-list vrf104001-in-prefixes permit 100.127.131.0/24 le 32
103105
ip prefix-list vrf104001-in-prefixes permit 212.17.234.17/32 le 32
104-
ip prefix-list vrf104001-in-prefixes permit 10.240.0.0/12 le 32
106+
ip prefix-list vrf104001-in6-prefixes permit 2001:db8:3::1/128 le 128
107+
ip prefix-list vrf104001-in6-prefixes permit fd00:10::/64 le 128
105108
route-map vrf104001-in permit 10
106109
match ip address prefix-list vrf104001-in-prefixes
110+
route-map vrf104001-in6 permit 10
111+
match ipv6 address prefix-list vrf104001-in6-prefixes
107112
!
108113
line vty
109114
!

cmd/internal/switcher/templates/test_data/dev/customtpl/frr.tpl

+1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ router bgp {{ $ASN }} vrf {{ $vrf }}
111111
!
112112
address-family l2vpn evpn
113113
advertise ipv4 unicast
114+
advertise ipv6 unicast
114115
exit-address-family
115116
!
116117
{{- if gt (len $t.IPPrefixLists) 0 }}

cmd/internal/switcher/templates/test_data/dev/sonic_frr.conf

+24-1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ router bgp 4200000010
5858
neighbor swp3 route-map fw-swp3-in in
5959
exit-address-family
6060
!
61+
address-family ipv6 unicast
62+
redistribute connected route-map DENY_MGMT
63+
neighbor FIREWALL allowas-in 2
64+
# see https://docs.frrouting.org/en/latest/bgp.html#clicmd-neighbor-A.B.C.D-activate
65+
# why activate is required
66+
neighbor FIREWALL activate
67+
neighbor swp3 route-map fw-swp3-in in
68+
exit-address-family
69+
!
6170
address-family l2vpn evpn
6271
advertise-all-vni
6372
neighbor FABRIC activate
@@ -99,16 +108,30 @@ router bgp 4200000010 vrf Vrf104001
99108
neighbor MACHINE route-map Vrf104001-in in
100109
exit-address-family
101110
!
111+
address-family ipv6 unicast
112+
redistribute connected
113+
neighbor MACHINE maximum-prefix 24000
114+
# see https://docs.frrouting.org/en/latest/bgp.html#clicmd-neighbor-A.B.C.D-activate
115+
# why activate is required
116+
neighbor MACHINE activate
117+
neighbor MACHINE route-map Vrf104001-in6 in
118+
exit-address-family
119+
!
102120
address-family l2vpn evpn
103121
advertise ipv4 unicast
122+
advertise ipv6 unicast
104123
exit-address-family
105124
!
106125
# route-maps for Vrf104001
126+
ip prefix-list Vrf104001-in-prefixes permit 10.240.0.0/12 le 32
107127
ip prefix-list Vrf104001-in-prefixes permit 100.127.131.0/24 le 32
108128
ip prefix-list Vrf104001-in-prefixes permit 212.17.234.17/32 le 32
109-
ip prefix-list Vrf104001-in-prefixes permit 10.240.0.0/12 le 32
129+
ip prefix-list Vrf104001-in6-prefixes permit 2001:db8:3::1/128 le 128
130+
ip prefix-list Vrf104001-in6-prefixes permit fd00:10::/64 le 128
110131
route-map Vrf104001-in permit 10
111132
match ip address prefix-list Vrf104001-in-prefixes
133+
route-map Vrf104001-in6 permit 10
134+
match ipv6 address prefix-list Vrf104001-in6-prefixes
112135
!
113136
line vty
114137
!

cmd/internal/switcher/templates/test_data/lab/conf.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ loglevel: debugging
44
loopback: 10.0.0.10
55
asn: 4200000010
66
metalcorecidr: 10.255.255.2/24
7+
additionalroutemapcidrs:
8+
- "10.240.0.0/12"
79
ports:
810
eth0:
911
addresscidr: 192.168.0.11

cmd/internal/switcher/templates/test_data/lab/cumulus_frr.conf

+7
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ router bgp 4200000010
5353
neighbor swp3 route-map fw-swp3-in in
5454
exit-address-family
5555
!
56+
address-family ipv6 unicast
57+
redistribute connected route-map LOOPBACKS
58+
neighbor FIREWALL allowas-in 2
59+
neighbor FIREWALL activate
60+
neighbor swp3 route-map fw-swp3-in in
61+
exit-address-family
62+
!
5663
address-family l2vpn evpn
5764
advertise-all-vni
5865
neighbor FABRIC activate

cmd/internal/switcher/templates/test_data/lab/sonic_frr.conf

+9
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ router bgp 4200000010
5858
neighbor swp3 route-map fw-swp3-in in
5959
exit-address-family
6060
!
61+
address-family ipv6 unicast
62+
redistribute connected route-map DENY_MGMT
63+
neighbor FIREWALL allowas-in 2
64+
# see https://docs.frrouting.org/en/latest/bgp.html#clicmd-neighbor-A.B.C.D-activate
65+
# why activate is required
66+
neighbor FIREWALL activate
67+
neighbor swp3 route-map fw-swp3-in in
68+
exit-address-family
69+
!
6170
address-family l2vpn evpn
6271
advertise-all-vni
6372
neighbor FABRIC activate

0 commit comments

Comments
 (0)