-
Notifications
You must be signed in to change notification settings - Fork 443
/
ovs.go
148 lines (131 loc) · 4.82 KB
/
ovs.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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package daemon
import (
"fmt"
"strings"
"time"
goping "github.com/oilbeater/go-ping"
"k8s.io/klog/v2"
"github.com/kubeovn/kube-ovn/pkg/ovs"
"github.com/kubeovn/kube-ovn/pkg/util"
)
const gatewayCheckMaxRetry = 200
func pingGateway(gw, src string, verbose bool) error {
pinger, err := goping.NewPinger(gw)
if err != nil {
return fmt.Errorf("failed to init pinger: %v", err)
}
pinger.SetPrivileged(true)
// CNITimeoutSec = 220, cannot exceed
pinger.Count = gatewayCheckMaxRetry
pinger.Timeout = gatewayCheckMaxRetry * time.Second
pinger.Interval = time.Second
var success bool
pinger.OnRecv = func(p *goping.Packet) {
success = true
pinger.Stop()
}
pinger.Run()
cniConnectivityResult.WithLabelValues(nodeName).Add(float64(pinger.PacketsSent))
if !success {
return fmt.Errorf("%s network not ready after %d ping %s", src, gatewayCheckMaxRetry, gw)
}
if verbose {
klog.Infof("%s network ready after %d ping, gw %s", src, pinger.PacketsSent, gw)
}
return nil
}
func configureGlobalMirror(portName string, mtu int) error {
raw, err := ovs.Exec(ovs.MayExist, "add-port", "br-int", portName, "--",
"set", "interface", portName, "type=internal", "--",
"clear", "bridge", "br-int", "mirrors", "--",
"--id=@mirror0", "get", "port", portName, "--",
"--id=@m", "create", "mirror", fmt.Sprintf("name=%s", util.MirrorDefaultName), "select_all=true", "output_port=@mirror0", "--",
"add", "bridge", "br-int", "mirrors", "@m")
if err != nil {
klog.Errorf("failed to configure mirror nic %s %q", portName, raw)
return fmt.Errorf(raw)
}
return configureMirrorLink(portName, mtu)
}
func configureEmptyMirror(portName string, mtu int) error {
raw, err := ovs.Exec(ovs.MayExist, "add-port", "br-int", portName, "--",
"set", "interface", portName, "type=internal", "--",
"clear", "bridge", "br-int", "mirrors", "--",
"--id=@mirror0", "get", "port", portName, "--",
"--id=@m", "create", "mirror", fmt.Sprintf("name=%s", util.MirrorDefaultName), "output_port=@mirror0", "--",
"add", "bridge", "br-int", "mirrors", "@m")
if err != nil {
klog.Errorf("failed to configure mirror nic %s %q", portName, raw)
return fmt.Errorf(raw)
}
return configureMirrorLink(portName, mtu)
}
func configExternalBridge(provider, bridge, nic string) error {
brExists, err := ovs.BridgeExists(bridge)
if err != nil {
return fmt.Errorf("failed to check OVS bridge existence: %v", err)
}
output, err := ovs.Exec(ovs.MayExist, "add-br", bridge,
"--", "set", "bridge", bridge, "external_ids:vendor="+util.CniTypeName)
if err != nil {
return fmt.Errorf("failed to create OVS bridge %s, %v: %q", bridge, err, output)
}
if !brExists {
// assign a new generated mac address only when the bridge is newly created
output, err = ovs.Exec("set", "bridge", bridge, fmt.Sprintf(`other-config:hwaddr="%s"`, util.GenerateMac()))
if err != nil {
return fmt.Errorf("failed to set hwaddr of OVS bridge %s, %v: %q", bridge, err, output)
}
}
if output, err = ovs.Exec("list-ports", bridge); err != nil {
return fmt.Errorf("failed to list ports of OVS bridge %s, %v: %q", bridge, err, output)
}
if output != "" {
for _, port := range strings.Split(output, "\n") {
if port != nic {
ok, err := ovs.ValidatePortVendor(port)
if err != nil {
return fmt.Errorf("failed to check vendor of port %s: %v", port, err)
}
if ok {
if err = removeProviderNic(port, bridge); err != nil {
return fmt.Errorf("failed to remove port %s from OVS bridge %s: %v", port, bridge, err)
}
}
}
}
}
if output, err = ovs.Exec(ovs.IfExists, "get", "open", ".", "external-ids:ovn-bridge-mappings"); err != nil {
return fmt.Errorf("failed to get ovn-bridge-mappings, %v", err)
}
bridgeMappings := fmt.Sprintf("%s:%s", provider, bridge)
if util.IsStringIn(bridgeMappings, strings.Split(output, ",")) {
return nil
}
if output != "" {
bridgeMappings = fmt.Sprintf("%s,%s", output, bridgeMappings)
}
if output, err = ovs.Exec("set", "open", ".", "external-ids:ovn-bridge-mappings="+bridgeMappings); err != nil {
return fmt.Errorf("failed to set ovn-bridge-mappings, %v: %q", err, output)
}
return nil
}
func initProviderChassisMac(provider string) error {
output, err := ovs.Exec(ovs.IfExists, "get", "open", ".", "external-ids:ovn-chassis-mac-mappings")
if err != nil {
return fmt.Errorf("failed to get ovn-bridge-mappings, %v", err)
}
for _, macMap := range strings.Split(output, ",") {
if len(macMap) == len(provider)+18 && strings.Contains(output, provider) {
return nil
}
}
macMappings := fmt.Sprintf("%s:%s", provider, util.GenerateMac())
if output != "" {
macMappings = fmt.Sprintf("%s,%s", output, macMappings)
}
if output, err = ovs.Exec("set", "open", ".", "external-ids:ovn-chassis-mac-mappings="+macMappings); err != nil {
return fmt.Errorf("failed to set ovn-chassis-mac-mappings, %v: %q", err, output)
}
return nil
}