Skip to content

Commit 12c4711

Browse files
authored
Merge pull request #168 from River-sh/bugfix/fix_raven0_broadcast
fix mac address for vxlan
2 parents d1255b1 + d70eb16 commit 12c4711

File tree

4 files changed

+67
-14
lines changed

4 files changed

+67
-14
lines changed

cmd/agent/app/config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ type TunnelConfig struct {
3838
VPNDriver string
3939
VPNPort string
4040
RouteDriver string
41+
MACPrefix string
4142
ForwardNodeIP bool
4243
NATTraversal bool
4344
KeepAliveInterval int

cmd/agent/app/options/options.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import (
55
"fmt"
66
"net"
77
"os"
8+
"regexp"
89
"strconv"
10+
"strings"
911

1012
"github.com/spf13/pflag"
1113
v1 "k8s.io/api/core/v1"
@@ -35,6 +37,7 @@ const (
3537
DefaultTunnelMetricsPort = 10265
3638
DefaultProxyMetricsPort = 10266
3739
DefaultHealthyProbeAddr = 10275
40+
DefaultMACPrefix = "aa:0f"
3841
)
3942

4043
// AgentOptions has the information that required by the raven agent
@@ -52,6 +55,7 @@ type TunnelOptions struct {
5255
VPNDriver string
5356
VPNPort string
5457
RouteDriver string
58+
MACPrefix string
5559
ForwardNodeIP bool
5660
NATTraversal bool
5761
KeepAliveInterval int
@@ -77,6 +81,15 @@ func (o *AgentOptions) Validate() error {
7781
return errors.New("currently only supports libreswan and wireguard VPN drivers")
7882
}
7983
}
84+
if o.MACPrefix != "" {
85+
reg := regexp.MustCompile(`^[0-9a-fA-F]+$`)
86+
strs := strings.Split(o.MACPrefix, ":")
87+
for i := range strs {
88+
if !reg.MatchString(strings.ToLower(strs[i])) {
89+
return fmt.Errorf("mac prefix %s is nonstandard", o.MACPrefix)
90+
}
91+
}
92+
}
8093
return nil
8194
}
8295

@@ -95,6 +108,7 @@ func (o *AgentOptions) AddFlags(fs *pflag.FlagSet) {
95108
fs.BoolVar(&o.ForwardNodeIP, "forward-node-ip", o.ForwardNodeIP, `Forward node IP or not. (default "false")`)
96109
fs.IntVar(&o.KeepAliveInterval, "keep-alive-interval", o.KeepAliveInterval, `Interval for sending keepalive packets in the VPN tunnel, (default "0", closed)`)
97110
fs.IntVar(&o.KeepAliveTimeout, "keep-alive-timeout", o.KeepAliveTimeout, `Timeout for sending keepalive packets in the VPN tunnel, (default "0", closed)`)
111+
fs.StringVar(&o.MACPrefix, "customized-mac-prefix", o.MACPrefix, `Customized MAC address prefix for vxlan link, (default "aa:0f")`)
98112

99113
fs.StringVar(&o.ProxyMetricsAddress, "proxy-metric-bind-addr", o.ProxyMetricsAddress, `Binding address of proxy metrics. (default ":10266")`)
100114
fs.StringVar(&o.InternalSecureAddress, "proxy-internal-secure-addr", o.InternalSecureAddress, `Binding secure address of proxy server. (default ":10263")`)
@@ -145,6 +159,7 @@ func (o *AgentOptions) Config() (*config.Config, error) {
145159
VPNPort: port,
146160
VPNDriver: o.VPNDriver,
147161
RouteDriver: o.RouteDriver,
162+
MACPrefix: o.MACPrefix,
148163
ForwardNodeIP: o.ForwardNodeIP,
149164
NATTraversal: o.NATTraversal,
150165
KeepAliveInterval: o.KeepAliveInterval,
@@ -171,6 +186,9 @@ func (o *AgentOptions) Config() (*config.Config, error) {
171186
if c.Tunnel.VPNPort == "" {
172187
c.Tunnel.VPNPort = vpndriver.DefaultVPNPort
173188
}
189+
if c.Tunnel.MACPrefix == "" {
190+
c.Tunnel.MACPrefix = DefaultMACPrefix
191+
}
174192
if c.Proxy.ProxyClientCertDir == "" {
175193
c.Proxy.ProxyClientCertDir = utils.RavenProxyClientCertDir
176194
}

pkg/networkengine/routedriver/vxlan/vxlan.go

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"math"
2323
"net"
2424
"os"
25+
"strings"
2526
"syscall"
2627

2728
"github.com/vdobler/ht/errorlist"
@@ -67,6 +68,7 @@ func init() {
6768
type vxlan struct {
6869
vxlanIface netlink.Link
6970
nodeName types.NodeName
71+
macPrefix string
7072

7173
iptables iptablesutil.IPTablesInterface
7274
ipset ipsetutil.IPSetInterface
@@ -137,7 +139,10 @@ func (vx *vxlan) Apply(network *types.Network, vpnDriverMTUFn func() (int, error
137139

138140
if vx.isGatewayRole(network) {
139141
desiredRoutes = vx.calRouteOnGateway(network)
140-
desiredFDBs = vx.calFDBOnGateway(network)
142+
desiredFDBs, err = vx.calFDBOnGateway(network)
143+
if err != nil {
144+
return fmt.Errorf("error calculate gateway fdb: %s", err)
145+
}
141146

142147
err = vx.deleteChainRuleOnNode(iptablesutil.MangleTable, iptablesutil.RavenMarkChain, nonGatewayChainRuleSpec)
143148
if err != nil {
@@ -149,8 +154,10 @@ func (vx *vxlan) Apply(network *types.Network, vpnDriverMTUFn func() (int, error
149154
}
150155
} else {
151156
desiredRoutes = vx.calRouteOnNonGateway(network)
152-
desiredFDBs = vx.calFDBOnNonGateway(network)
153-
157+
desiredFDBs, err = vx.calFDBOnNonGateway(network)
158+
if err != nil {
159+
return fmt.Errorf("error calculate non gateway fdb: %s", err)
160+
}
154161
err = vx.deleteChainRuleOnNode(iptablesutil.MangleTable, iptablesutil.RavenMarkChain, gatewayChainRuleSpec)
155162
if err != nil {
156163
return fmt.Errorf("error deleting gateway chain rule: %s", err)
@@ -218,7 +225,8 @@ func (vx *vxlan) nodeInfo(network *types.Network) *v1beta1.NodeInfo {
218225

219226
func New(cfg *config.Config) (routedriver.Driver, error) {
220227
return &vxlan{
221-
nodeName: types.NodeName(cfg.NodeName),
228+
nodeName: types.NodeName(cfg.NodeName),
229+
macPrefix: cfg.Tunnel.MACPrefix,
222230
}, nil
223231
}
224232

@@ -274,13 +282,17 @@ func (vx *vxlan) ensureVxlanLink(network *types.Network, vpnDriverMTUFn func() (
274282
VxlanId: vxlanID,
275283
Age: 300,
276284
Port: vxlanPort,
277-
Learning: true,
285+
Learning: false,
278286
}
279287
if !vx.isGatewayRole(network) {
280288
vxlanLink.Group = net.ParseIP(network.LocalEndpoint.PrivateIP)
281289
}
282290

283291
localIP := net.ParseIP(vx.nodeInfo(network).PrivateIP)
292+
vxlanLink.HardwareAddr, err = vx.ipAddrToHardwareAddr(localIP)
293+
if err != nil {
294+
return fmt.Errorf("error convert vxlan ip to mac address: %s", err)
295+
}
284296
nl, err := ensureVxlanLink(vxlanLink, vxlanIP(localIP))
285297
if err != nil {
286298
return fmt.Errorf("error ensuring vxlan link: %s", err)
@@ -383,31 +395,39 @@ func (vx *vxlan) calRulesOnNode() map[string]*netlink.Rule {
383395
// calFDBOnGateway calculates and returns the desired FDB entries on gateway node.
384396
// The FDB entries format are equivalent to the following `bridge fdb append` command:
385397
//
386-
// bridge fdb append 00:00:00:00:00:00 dev raven0 dst {non_gateway_nodeN_private_ip} self permanent
387-
func (vx *vxlan) calFDBOnGateway(network *types.Network) map[string]*netlink.Neigh {
398+
// bridge fdb append fixed mac address dev raven0 dst {non_gateway_nodeN_private_ip} self permanent
399+
func (vx *vxlan) calFDBOnGateway(network *types.Network) (map[string]*netlink.Neigh, error) {
388400
fdbs := make(map[string]*netlink.Neigh)
389401
for k, v := range network.LocalNodeInfo {
390402
if vx.nodeName == k {
391403
continue
392404
}
405+
HardwareAddr, err := vx.ipAddrToHardwareAddr(net.ParseIP(v.PrivateIP))
406+
if err != nil {
407+
return nil, fmt.Errorf("convert ip address %s to hardware address error %s", v.PrivateIP, err.Error())
408+
}
393409
fdbs[v.PrivateIP] = &netlink.Neigh{
394410
LinkIndex: vx.vxlanIface.Attrs().Index,
395411
State: netlink.NUD_PERMANENT | netlink.NUD_NOARP,
396412
Type: netlink.NDA_DST,
397413
Family: syscall.AF_BRIDGE,
398414
Flags: netlink.NTF_SELF,
399415
IP: net.ParseIP(v.PrivateIP),
400-
HardwareAddr: networkutil.AllZeroMAC,
416+
HardwareAddr: HardwareAddr,
401417
}
402418
}
403-
return fdbs
419+
return fdbs, nil
404420
}
405421

406422
// calFDBOnNonGateway calculates and returns the desired FDB entries on non-gateway node.
407423
// The FDB entries format are equivalent to the following `bridge fdb append` command:
408424
//
409-
// bridge fdb append 00:00:00:00:00:00 dev raven0 dst {gateway_node_private_ip} self permanent
410-
func (vx *vxlan) calFDBOnNonGateway(network *types.Network) map[string]*netlink.Neigh {
425+
// bridge fdb append fixed mac address dev raven0 dst {gateway_node_private_ip} self permanent
426+
func (vx *vxlan) calFDBOnNonGateway(network *types.Network) (map[string]*netlink.Neigh, error) {
427+
HardwareAddr, err := vx.ipAddrToHardwareAddr(net.ParseIP(network.LocalEndpoint.PrivateIP))
428+
if err != nil {
429+
return nil, fmt.Errorf("convert ip address %s to hardware address error %s", network.LocalEndpoint.PrivateIP, err.Error())
430+
}
411431
return map[string]*netlink.Neigh{
412432
network.LocalEndpoint.PrivateIP: {
413433
LinkIndex: vx.vxlanIface.Attrs().Index,
@@ -416,9 +436,9 @@ func (vx *vxlan) calFDBOnNonGateway(network *types.Network) map[string]*netlink.
416436
Family: syscall.AF_BRIDGE,
417437
Flags: netlink.NTF_SELF,
418438
IP: net.ParseIP(network.LocalEndpoint.PrivateIP),
419-
HardwareAddr: networkutil.AllZeroMAC,
439+
HardwareAddr: HardwareAddr,
420440
},
421-
}
441+
}, nil
422442
}
423443

424444
// calIPSetOnNonGateway calculates and returns the desired ip set entries on non-gateway node.
@@ -522,3 +542,16 @@ func (vx *vxlan) isGatewayRole(network *types.Network) bool {
522542
network.LocalEndpoint != nil &&
523543
network.LocalEndpoint.NodeName == vx.nodeName
524544
}
545+
546+
func (vx *vxlan) ipAddrToHardwareAddr(ip net.IP) (net.HardwareAddr, error) {
547+
macSlice := []string{vx.macPrefix}
548+
for _, ipSlice := range vxlanIP(ip).To4() {
549+
macSlice = append(macSlice, fmt.Sprintf("%02x", ipSlice))
550+
}
551+
macStr := strings.Join(macSlice, ":")
552+
macAddr, err := net.ParseMAC(macStr)
553+
if err != nil {
554+
return nil, fmt.Errorf("parse MAC %s error %s", macStr, err.Error())
555+
}
556+
return macAddr, nil
557+
}

pkg/networkengine/routedriver/vxlan/vxlan_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,8 @@ func TestVxlan_Apply(t *testing.T) {
440440
for _, v := range testcases {
441441
t.Run(v.name, func(t *testing.T) {
442442
vx := vxlan{
443-
nodeName: v.nodeName,
443+
nodeName: v.nodeName,
444+
macPrefix: "aa:0f",
444445
}
445446
a := assert.New(t)
446447
a.NoError(vx.Init())

0 commit comments

Comments
 (0)