-
Notifications
You must be signed in to change notification settings - Fork 333
/
helper_linux.go
117 lines (105 loc) · 3.67 KB
/
helper_linux.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// +build linux
package node
import (
"fmt"
"net"
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/config"
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/util"
"github.com/pkg/errors"
"github.com/vishvananda/netlink"
kapi "k8s.io/api/core/v1"
"k8s.io/klog/v2"
)
// getDefaultGatewayInterfaceDetails returns the interface name on
// which the default gateway (for route to 0.0.0.0) is configured.
// It also returns the default gateways themselves.
func getDefaultGatewayInterfaceDetails() (string, []net.IP, error) {
var intfName string
var gatewayIPs []net.IP
if config.IPv4Mode {
intfIPv4Name, gw, err := getDefaultGatewayInterfaceByFamily(netlink.FAMILY_V4)
if err != nil {
return "", gatewayIPs, err
}
intfName = intfIPv4Name
gatewayIPs = append(gatewayIPs, gw)
}
if config.IPv6Mode {
intfIPv6Name, gw, err := getDefaultGatewayInterfaceByFamily(netlink.FAMILY_V6)
if err != nil {
return "", gatewayIPs, err
}
// validate that both IP Families use the same interface for the gateway
if intfName == "" {
intfName = intfIPv6Name
} else if intfName != intfIPv6Name {
return "", nil, fmt.Errorf("multiple gateway interfaces detected: %s %s", intfName, intfIPv6Name)
}
gatewayIPs = append(gatewayIPs, gw)
}
if len(gatewayIPs) == 0 {
return "", nil, fmt.Errorf("failed to get default gateway interface")
}
return intfName, gatewayIPs, nil
}
func getDefaultGatewayInterfaceByFamily(family int) (string, net.IP, error) {
// filter the default route to obtain the gateway
filter := &netlink.Route{Dst: nil}
routes, err := netlink.RouteListFiltered(family, filter, netlink.RT_FILTER_DST)
if err != nil {
return "", nil, errors.Wrapf(err, "failed to get routing table in node")
}
// use the first valid default gateway
for _, r := range routes {
// no multipath
if len(r.MultiPath) == 0 {
intfLink, err := netlink.LinkByIndex(r.LinkIndex)
if err != nil {
klog.Warningf("Failed to get interface link for route %v : %v", r, err)
continue
}
if r.Gw == nil {
klog.Warningf("Failed to get gateway for route %v : %v", r, err)
continue
}
netlink.AddrList(intfLink, family)
klog.Infof("Found default gateway interface %s %s", intfLink.Attrs().Name, r.Gw.String())
return intfLink.Attrs().Name, r.Gw, nil
}
// multipath, use the first valid entry
// TODO: revisit for full multipath support
// xref: https://github.com/vishvananda/netlink/blob/6ffafa9fc19b848776f4fd608c4ad09509aaacb4/route.go#L137-L145
for _, nh := range r.MultiPath {
intfLink, err := netlink.LinkByIndex(nh.LinkIndex)
if err != nil {
klog.Warningf("Failed to get interface link for route %v : %v", nh, err)
continue
}
if nh.Gw == nil {
klog.Warningf("Failed to get gateway for multipath route %v : %v", nh, err)
continue
}
klog.Infof("Found default gateway interface %s %s", intfLink.Attrs().Name, nh.Gw.String())
return intfLink.Attrs().Name, nh.Gw, nil
}
}
return "", net.IP{}, fmt.Errorf("failed to get default gateway interface")
}
func getIntfName(gatewayIntf string) (string, error) {
// The given (or autodetected) interface is an OVS bridge and this could be
// created by us using util.NicToBridge() or it was pre-created by the user.
// Is intfName a port of gatewayIntf?
intfName, err := util.GetNicName(gatewayIntf)
if err != nil {
return "", err
}
_, stderr, err := util.RunOVSVsctl("get", "interface", intfName, "ofport")
if err != nil {
return "", fmt.Errorf("failed to get ofport of %s, stderr: %q, error: %v",
intfName, stderr, err)
}
return intfName, nil
}
func deleteConntrack(ip string, port int32, protocol kapi.Protocol) error {
return util.DeleteConntrack(ip, port, protocol)
}