• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kubeovn / kube-ovn / 18003963110

25 Sep 2025 10:02AM UTC coverage: 21.086% (-0.002%) from 21.088%
18003963110

Pull #5757

github

changluyi
fix gabage u2o openflow

Signed-off-by: clyi <clyi@alauda.io>
Pull Request #5757: fix gabage u2o openflow

0 of 26 new or added lines in 3 files covered. (0.0%)

1 existing line in 1 file now uncovered.

10707 of 50778 relevant lines covered (21.09%)

0.25 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/pkg/ovs/ovs-ofctl.go
1
package ovs
2

3
import (
4
        "fmt"
5
        "net"
6
        "strconv"
7

8
        ovs "github.com/digitalocean/go-openvswitch/ovs"
9
        v1 "k8s.io/api/core/v1"
10
        "k8s.io/klog/v2"
11

12
        kubeovnv1 "github.com/kubeovn/kube-ovn/pkg/apis/kubeovn/v1"
13
        "github.com/kubeovn/kube-ovn/pkg/util"
14
)
15

16
func getOfportByPeer(peer string) (int, error) {
×
17
        // ovs-vsctl find interface options:peer="<peer>"
×
18
        ifaceNames, err := ovsFind("Interface", "name", fmt.Sprintf(`options:peer="%s"`, peer))
×
19
        if err != nil {
×
20
                return -1, fmt.Errorf("failed to find interface with peer %s: %w", peer, err)
×
21
        }
×
22
        if len(ifaceNames) == 0 {
×
23
                return -1, fmt.Errorf("no interface found with peer %s", peer)
×
24
        }
×
25
        if len(ifaceNames) > 1 {
×
26
                // This should not happen for patch ports
×
27
                klog.Warningf("multiple interfaces found with peer %s: %v", peer, ifaceNames)
×
28
        }
×
29
        ifaceName := ifaceNames[0]
×
30

×
31
        ofportStr, err := Get("Interface", ifaceName, "ofport", "", false)
×
32
        if err != nil {
×
33
                return -1, fmt.Errorf("failed to get ofport for interface %s: %w", ifaceName, err)
×
34
        }
×
35

36
        return strconv.Atoi(ofportStr)
×
37
}
38

39
func AddOrUpdateUnderlaySubnetSvcLocalOpenFlow(client *ovs.Client, bridgeName, lbServiceIP, protocol, dstMAC, underlayNic string, lbServicePort uint16) error {
×
40
        isIPv6 := util.CheckProtocol(lbServiceIP) == kubeovnv1.ProtocolIPv6
×
41
        var inPortID, outPortID int
×
42
        var lrpMacAddr net.HardwareAddr
×
43
        var err error
×
44
        var cookie uint64
×
45

×
46
        portInfo, err := client.OpenFlow.DumpPort(bridgeName, underlayNic)
×
47
        if err != nil {
×
48
                klog.Errorf("failed to dump bridge %s port %s: %v", bridgeName, underlayNic, err)
×
49
                return err
×
50
        }
×
51
        inPortID = portInfo.PortID
×
52
        klog.V(3).Infof("underlayNic %s's portID is %d", underlayNic, inPortID)
×
53

×
54
        portInfo, err = client.OpenFlow.DumpPort(bridgeName, "patch-localnet.")
×
55
        if err != nil {
×
56
                klog.Errorf("failed to dump bridge %s port %s: %v", bridgeName, "patch-localnet.", err)
×
57
                return err
×
58
        }
×
59
        outPortID = portInfo.PortID
×
60

×
61
        lrpMacAddr, err = net.ParseMAC(dstMAC)
×
62
        if err != nil {
×
63
                klog.Errorf("failed to parse MAC address %s: %v", dstMAC, err)
×
64
                return err
×
65
        }
×
66

67
        cookie = util.UnderlaySvcLocalOpenFlowCookieV4
×
68
        if isIPv6 {
×
69
                cookie = util.UnderlaySvcLocalOpenFlowCookieV6
×
70
        }
×
71

72
        var protocolType ovs.Protocol
×
73
        switch protocol {
×
74
        case string(v1.ProtocolTCP):
×
75
                protocolType = ovs.ProtocolTCPv4
×
76
                if isIPv6 {
×
77
                        protocolType = ovs.ProtocolTCPv6
×
78
                }
×
79
        case string(v1.ProtocolUDP):
×
80
                protocolType = ovs.ProtocolUDPv4
×
81
                if isIPv6 {
×
82
                        protocolType = ovs.ProtocolUDPv6
×
83
                }
×
84
        default:
×
85
                return fmt.Errorf("unsupported protocol %s", protocol)
×
86
        }
87

88
        flow := &ovs.Flow{
×
89
                Priority: util.UnderlaySvcLocalOpenFlowPriority,
×
90
                Protocol: protocolType,
×
91
                InPort:   inPortID,
×
92
                Actions:  []ovs.Action{ovs.ModDataLinkDestination(lrpMacAddr), ovs.Output(outPortID)},
×
93
                Matches: []ovs.Match{
×
94
                        ovs.NetworkDestination(lbServiceIP),
×
95
                        ovs.TransportDestinationMaskedPort(lbServicePort, 0xffff),
×
96
                },
×
97
                Cookie: cookie,
×
98
        }
×
99

×
100
        klog.Infof("add bridge %s svc local policy openflow rule", bridgeName)
×
101
        err = client.OpenFlow.AddFlow(bridgeName, flow)
×
102
        if err != nil {
×
103
                return err
×
104
        }
×
105

106
        return nil
×
107
}
108

109
func DeleteUnderlaySubnetSvcLocalOpenFlow(client *ovs.Client, bridgeName, lbServiceIP, protocol, underlayNic string, lbServicePort uint16) error {
×
110
        isIPv6 := util.CheckProtocol(lbServiceIP) == kubeovnv1.ProtocolIPv6
×
111
        var inPortID int
×
112
        var cookie uint64
×
113

×
114
        cookie = util.UnderlaySvcLocalOpenFlowCookieV4
×
115
        if isIPv6 {
×
116
                cookie = util.UnderlaySvcLocalOpenFlowCookieV6
×
117
        }
×
118

119
        var protocolType ovs.Protocol
×
120
        switch protocol {
×
121
        case string(v1.ProtocolTCP):
×
122
                protocolType = ovs.ProtocolTCPv4
×
123
                if isIPv6 {
×
124
                        protocolType = ovs.ProtocolTCPv6
×
125
                }
×
126
        case string(v1.ProtocolUDP):
×
127
                protocolType = ovs.ProtocolUDPv4
×
128
                if isIPv6 {
×
129
                        protocolType = ovs.ProtocolUDPv6
×
130
                }
×
131
        default:
×
132
                return fmt.Errorf("unsupported protocol %s", protocol)
×
133
        }
134

135
        portInfo, err := client.OpenFlow.DumpPort(bridgeName, underlayNic)
×
136
        if err != nil {
×
137
                klog.Errorf("failed to dump bridge %s port %s: %v", bridgeName, underlayNic, err)
×
138
                return err
×
139
        }
×
140
        inPortID = portInfo.PortID
×
141
        klog.V(3).Infof("underlayNic %s's portID is %d", underlayNic, inPortID)
×
142

×
143
        match := &ovs.MatchFlow{
×
144
                Protocol: protocolType,
×
145
                InPort:   inPortID,
×
146
                Matches: []ovs.Match{
×
147
                        ovs.NetworkDestination(lbServiceIP),
×
148
                        ovs.TransportDestinationMaskedPort(lbServicePort, 0xffff),
×
149
                },
×
150
                Cookie: cookie,
×
151
        }
×
152

×
153
        oldflows, err := client.OpenFlow.DumpFlowsWithFlowArgs(bridgeName, match)
×
154
        if err != nil {
×
155
                klog.Errorf("failed to dump flows: %v", err)
×
156
                return err
×
157
        }
×
158

159
        if len(oldflows) > 0 {
×
160
                klog.Infof("remove bridge %s old svc local policy openflow rule", bridgeName)
×
161
                err = client.OpenFlow.DelFlows(bridgeName, match)
×
162
                if err != nil {
×
163
                        klog.Errorf("failed to remove old svc local policy openflow rule: %v", err)
×
164
                        return err
×
165
                }
×
166
        }
167
        return nil
×
168
}
169

170
func AddOrUpdateU2OKeepSrcMac(client *ovs.Client, bridgeName, podIP, podMac, chassisMac, subnetName string) error {
×
171
        var localnetPatchPortID int
×
172
        var podMacAddr net.HardwareAddr
×
173
        var err error
×
174
        var matchs []ovs.Match
×
175
        var protocolType ovs.Protocol
×
176
        isIPv6 := util.CheckProtocol(podIP) == kubeovnv1.ProtocolIPv6
×
177

×
178
        peer := fmt.Sprintf("patch-br-int-to-localnet.%s", subnetName)
×
179
        localnetPatchPortID, err = getOfportByPeer(peer)
×
180
        if err != nil {
×
181
                klog.Errorf("failed to get ofport for peer %s: %v", peer, err)
×
182
                return err
×
183
        }
×
184

185
        podMacAddr, err = net.ParseMAC(podMac)
×
186
        if err != nil {
×
187
                klog.Errorf("failed to parse MAC address %s: %v", podMac, err)
×
188
                return err
×
189
        }
×
190

191
        if isIPv6 {
×
192
                protocolType = ovs.ProtocolIPv6
×
193
                matchs = []ovs.Match{
×
194
                        ovs.IPv6Source(podIP),
×
195
                        ovs.DataLinkSource(chassisMac),
×
196
                }
×
197
        } else {
×
198
                protocolType = ovs.ProtocolIPv4
×
199
                matchs = []ovs.Match{
×
200
                        ovs.NetworkSource(podIP),
×
201
                        ovs.DataLinkSource(chassisMac),
×
202
                }
×
203
        }
×
204

205
        matchFlow := &ovs.MatchFlow{
×
206
                InPort:   localnetPatchPortID,
×
207
                Protocol: protocolType,
×
208
                Matches:  matchs,
×
209
        }
×
210

×
211
        flows, err := client.OpenFlow.DumpFlowsWithFlowArgs(bridgeName, matchFlow)
×
212
        if err != nil {
×
213
                klog.Errorf("failed to dump flows from bridge %s: %v", bridgeName, err)
×
214
                return err
×
215
        }
×
216

NEW
217
        expectedAction := fmt.Sprintf("mod_dl_src:%s", podMac)
×
NEW
218
        for _, flow := range flows {
×
NEW
219
                if flow.Priority != util.U2OKeepSrcMacPriority || flow.InPort != localnetPatchPortID {
×
NEW
220
                        continue
×
221
                }
222

NEW
223
                for _, action := range flow.Actions {
×
NEW
224
                        if actionText, _ := action.MarshalText(); string(actionText) == expectedAction {
×
NEW
225
                                klog.V(3).Infof("flow already exists in bridge %s for in_port=%d, ip_src=%s, dl_src=%s, actions=mod_dl_src:%s",
×
NEW
226
                                        bridgeName, localnetPatchPortID, podIP, chassisMac, podMac)
×
NEW
227
                                return nil
×
NEW
228
                        }
×
229
                }
230
        }
231

232
        flow := &ovs.Flow{
×
233
                Priority: util.U2OKeepSrcMacPriority,
×
234
                InPort:   localnetPatchPortID,
×
235
                Protocol: protocolType,
×
236
                Actions: []ovs.Action{
×
237
                        ovs.ModDataLinkSource(podMacAddr),
×
238
                        ovs.Normal(),
×
239
                },
×
240
                Matches: matchs,
×
241
        }
×
242

×
243
        klog.V(3).Infof("adding flow to bridge %s: in_port=%d, ip_src=%s, dl_src=%s, actions=mod_dl_src:%s,normal",
×
244
                bridgeName, localnetPatchPortID, podIP, chassisMac, podMac)
×
245

×
246
        return client.OpenFlow.AddFlow(bridgeName, flow)
×
247
}
248

249
func DeleteU2OKeepSrcMac(client *ovs.Client, bridgeName, podIP, chassisMac, subnetName string) error {
×
250
        var localnetPatchPortID int
×
251
        var err error
×
252
        var matchs []ovs.Match
×
253
        var protocolType ovs.Protocol
×
254
        isIPv6 := util.CheckProtocol(podIP) == kubeovnv1.ProtocolIPv6
×
255

×
256
        peer := fmt.Sprintf("patch-br-int-to-localnet.%s", subnetName)
×
257
        localnetPatchPortID, err = getOfportByPeer(peer)
×
258
        if err != nil {
×
259
                klog.Errorf("failed to get ofport for peer %s: %v", peer, err)
×
260
                return err
×
261
        }
×
262

263
        if isIPv6 {
×
264
                protocolType = ovs.ProtocolIPv6
×
265
                matchs = []ovs.Match{
×
266
                        ovs.IPv6Source(podIP),
×
267
                        ovs.DataLinkSource(chassisMac),
×
268
                }
×
269
        } else {
×
270
                protocolType = ovs.ProtocolIPv4
×
271
                matchs = []ovs.Match{
×
272
                        ovs.NetworkSource(podIP),
×
273
                        ovs.DataLinkSource(chassisMac),
×
274
                }
×
275
        }
×
276

277
        matchFlow := &ovs.MatchFlow{
×
278
                InPort:   localnetPatchPortID,
×
279
                Protocol: protocolType,
×
280
                Matches:  matchs,
×
281
        }
×
282

×
283
        klog.Infof("deleting flow from bridge %s: in_port=%d, ip_src=%s, dl_src=%s",
×
284
                bridgeName, localnetPatchPortID, podIP, chassisMac)
×
285

×
286
        return client.OpenFlow.DelFlows(bridgeName, matchFlow)
×
287
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc