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

kubeovn / kube-ovn / 12292860294

12 Dec 2024 08:48AM UTC coverage: 22.084% (+0.2%) from 21.903%
12292860294

Pull #4774

github

zhangzujian
fix format

Signed-off-by: zhangzujian <zhangzujian.7@gmail.com>
Pull Request #4774: add anp/banp unit test

16 of 20 new or added lines in 2 files covered. (80.0%)

2 existing lines in 1 file now uncovered.

10267 of 46491 relevant lines covered (22.08%)

0.26 hits per line

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

61.61
/pkg/ovs/ovn-nb-bfd.go
1
package ovs
2

3
import (
4
        "context"
5
        "fmt"
6
        "time"
7

8
        "github.com/ovn-org/libovsdb/cache"
9
        "github.com/ovn-org/libovsdb/model"
10
        "k8s.io/klog/v2"
11

12
        "github.com/kubeovn/kube-ovn/pkg/ovsdb/ovnnb"
13
        "github.com/kubeovn/kube-ovn/pkg/util"
14
)
15

16
func (c *OVNNbClient) ListBFDs(lrpName, dstIP string) ([]ovnnb.BFD, error) {
1✔
17
        ctx, cancel := context.WithTimeout(context.Background(), c.Timeout)
1✔
18
        defer cancel()
1✔
19

1✔
20
        bfdList := make([]ovnnb.BFD, 0)
1✔
21
        if err := c.ovsDbClient.WhereCache(func(bfd *ovnnb.BFD) bool {
2✔
22
                if bfd.LogicalPort != lrpName {
2✔
23
                        return false
1✔
24
                }
1✔
25
                return dstIP == "" || bfd.DstIP == dstIP
1✔
26
        }).List(ctx, &bfdList); err != nil {
×
27
                err := fmt.Errorf("failed to list BFD with logical_port=%s and dst_ip=%s: %w", lrpName, dstIP, err)
×
28
                klog.Error(err)
×
29
                return nil, err
×
30
        }
×
31

32
        return bfdList, nil
1✔
33
}
34

35
func (c *OVNNbClient) ListDownBFDs(dstIP string) ([]ovnnb.BFD, error) {
1✔
36
        ctx, cancel := context.WithTimeout(context.Background(), c.Timeout)
1✔
37
        defer cancel()
1✔
38

1✔
39
        bfdList := make([]ovnnb.BFD, 0)
1✔
40
        if err := c.ovsDbClient.WhereCache(func(bfd *ovnnb.BFD) bool {
2✔
41
                if bfd.DstIP == dstIP && (*bfd.Status == ovnnb.BFDStatusDown || *bfd.Status == ovnnb.BFDStatusAdminDown) {
2✔
42
                        return true
1✔
43
                }
1✔
44
                return false
1✔
45
        }).List(ctx, &bfdList); err != nil {
×
46
                err := fmt.Errorf("failed to list down BFDs: %w", err)
×
47
                klog.Error(err)
×
48
                return nil, err
×
49
        }
×
50

51
        return bfdList, nil
1✔
52
}
53

54
func (c *OVNNbClient) ListUpBFDs(dstIP string) ([]ovnnb.BFD, error) {
1✔
55
        ctx, cancel := context.WithTimeout(context.Background(), c.Timeout)
1✔
56
        defer cancel()
1✔
57

1✔
58
        bfdList := make([]ovnnb.BFD, 0)
1✔
59
        if err := c.ovsDbClient.WhereCache(func(bfd *ovnnb.BFD) bool {
2✔
60
                return bfd.DstIP == dstIP && *bfd.Status == ovnnb.BFDStatusUp
1✔
61
        }).List(ctx, &bfdList); err != nil {
1✔
62
                err := fmt.Errorf("failed to list up BFDs: %w", err)
×
63
                klog.Error(err)
×
64
                return nil, err
×
65
        }
×
66

67
        return bfdList, nil
1✔
68
}
69

70
func (c *OVNNbClient) CreateBFD(lrpName, dstIP string, minRx, minTx, detectMult int, externalIDs map[string]string) (*ovnnb.BFD, error) {
1✔
71
        bfdList, err := c.ListBFDs(lrpName, dstIP)
1✔
72
        if err != nil {
1✔
73
                klog.Error(err)
×
74
                return nil, err
×
75
        }
×
76
        if len(bfdList) != 0 {
2✔
77
                return &bfdList[0], nil
1✔
78
        }
1✔
79

80
        bfd := &ovnnb.BFD{
1✔
81
                LogicalPort: lrpName,
1✔
82
                DstIP:       dstIP,
1✔
83
                MinRx:       &minRx,
1✔
84
                MinTx:       &minTx,
1✔
85
                DetectMult:  &detectMult,
1✔
86
                ExternalIDs: externalIDs,
1✔
87
        }
1✔
88
        ops, err := c.Create(bfd)
1✔
89
        if err != nil {
1✔
90
                err := fmt.Errorf("failed to generate operations for BFD creation with logical_port=%s and dst_ip=%s: %w", lrpName, dstIP, err)
×
91
                klog.Error(err)
×
92
                return nil, err
×
93
        }
×
94
        if err = c.Transact("bfd-add", ops); err != nil {
2✔
95
                err := fmt.Errorf("failed to create BFD with logical_port=%s and dst_ip=%s: %w", lrpName, dstIP, err)
1✔
96
                klog.Error(err)
1✔
97
                return nil, err
1✔
98
        }
1✔
99

100
        if bfdList, err = c.ListBFDs(lrpName, dstIP); err != nil {
1✔
101
                err := fmt.Errorf("failed to list BFDs: %w", err)
×
102
                klog.Error(err)
×
103
                return nil, err
×
104
        }
×
105
        if len(bfdList) == 0 {
1✔
106
                return nil, fmt.Errorf("BFD with logical_port=%s and dst_ip=%s not found", lrpName, dstIP)
×
107
        }
×
108
        return &bfdList[0], nil
1✔
109
}
110

111
// UpdateBFD update BFD
112
func (c *OVNNbClient) UpdateBFD(bfd *ovnnb.BFD, fields ...interface{}) error {
1✔
113
        op, err := c.ovsDbClient.Where(bfd).Update(bfd, fields...)
1✔
114
        if err != nil {
2✔
115
                err := fmt.Errorf("failed to generate bfd update operations for lrp %s with fields %v: %w", bfd.LogicalPort, fields, err)
1✔
116
                klog.Error(err)
1✔
117
                return err
1✔
118
        }
1✔
119
        if err = c.Transact("bfd-update", op); err != nil {
1✔
120
                err := fmt.Errorf("failed to update bfd %s for lrp %s: %w", bfd.UUID, bfd.LogicalPort, err)
×
121
                klog.Error(err)
×
122
                return err
×
123
        }
×
124
        return nil
1✔
125
}
126

127
func (c *OVNNbClient) DeleteBFD(uuid string) error {
1✔
128
        ops, err := c.Where(&ovnnb.BFD{UUID: uuid}).Delete()
1✔
129
        if err != nil {
1✔
130
                err := fmt.Errorf("failed to generate operations for BFD deletion with UUID %s: %w", uuid, err)
×
131
                klog.Error(err)
×
132
                return err
×
133
        }
×
134
        if err = c.Transact("bfd-del", ops); err != nil {
1✔
135
                err = fmt.Errorf("failed to delete BFD with with UUID %s: %w", uuid, err)
×
136
                klog.Error(err)
×
137
                return err
×
138
        }
×
139
        return nil
1✔
140
}
141

142
func (c *OVNNbClient) DeleteBFDByDstIP(lrpName, dstIP string) error {
1✔
143
        bfdList, err := c.ListBFDs(lrpName, dstIP)
1✔
144
        if err != nil {
1✔
145
                klog.Error(err)
×
146
                return err
×
147
        }
×
148
        if len(bfdList) == 0 {
2✔
149
                return nil
1✔
150
        }
1✔
151
        for _, bfd := range bfdList {
2✔
152
                ops, err := c.Where(&bfd).Delete()
1✔
153
                if err != nil {
1✔
154
                        err := fmt.Errorf("failed to generate operations for BFD deletion with UUID %s: %w", bfd.UUID, err)
×
155
                        klog.Error(err)
×
156
                        return err
×
157
                }
×
158
                klog.Infof("delete lrp %s BFD dst ip %s", lrpName, bfd.DstIP)
1✔
159
                if err = c.Transact("bfd-del", ops); err != nil {
1✔
160
                        err := fmt.Errorf("failed to delete BFD with with UUID %s: %w", bfd.UUID, err)
×
161
                        klog.Error(err)
×
162
                        return err
×
163
                }
×
164
        }
165
        return nil
1✔
166
}
167

168
// MonitorBFD will add a handler
169
// to NB libovsdb cache to update the BFD priority.
170
// This function should only be called once.
171
func (c *OVNNbClient) MonitorBFD() {
1✔
172
        c.ovsDbClient.Cache().AddEventHandler(&cache.EventHandlerFuncs{
1✔
173
                AddFunc: func(table string, model model.Model) {
2✔
174
                        c.bfdAddL3HAHandler(table, model)
1✔
175
                },
1✔
176
                UpdateFunc: func(table string, oldModel, newModel model.Model) {
1✔
177
                        c.bfdUpdateL3HAHandler(table, oldModel, newModel)
1✔
178
                },
1✔
179
                DeleteFunc: func(table string, model model.Model) {
1✔
180
                        c.bfdDelL3HAHandler(table, model)
1✔
181
                },
1✔
182
        })
183
}
184

185
func (c *OVNNbClient) isLrpBfdUp(lrpName, dstIP string) (bool, error) {
1✔
186
        bfdList, err := c.ListBFDs(lrpName, dstIP)
1✔
187
        if err != nil {
1✔
188
                klog.Errorf("failed to list bfd for lrp %s, %v", lrpName, err)
×
189
                return false, err
×
190
        }
×
191
        if len(bfdList) == 0 {
2✔
192
                klog.Errorf("no bfd for lrp %s", lrpName)
1✔
193
                // no bfd, means no need to handle
1✔
194
                return true, nil
1✔
195
        }
1✔
196
        bfd := bfdList[0]
1✔
197
        if bfd.Status == nil {
2✔
198
                err := fmt.Errorf("lrp %s bfd status is nil", lrpName)
1✔
199
                klog.Error(err)
1✔
200
                return false, err
1✔
201
        } else if *bfd.Status == ovnnb.BFDStatusUp {
3✔
202
                klog.Infof("lrp %s bfd dst ip %s status is up", lrpName, bfd.DstIP)
1✔
203
                return true, nil
1✔
204
        }
1✔
205
        // bfd status is still down
206
        err = fmt.Errorf("lrp %s bfd dst ip %s status is down", lrpName, bfd.DstIP)
1✔
207
        klog.Error(err)
1✔
208
        return false, err
1✔
209
}
210

211
func (c *OVNNbClient) bfdAddL3HAHandler(table string, model model.Model) {
1✔
212
        if table != ovnnb.BFDTable {
2✔
213
                return
1✔
214
        }
1✔
215

216
        bfd := model.(*ovnnb.BFD)
1✔
217
        if bfd.ExternalIDs[ExternalIDVpcEgressGateway] != "" {
1✔
218
                return
×
219
        }
×
220

221
        klog.Infof("lrp %s add BFD to dst ip %s", bfd.LogicalPort, bfd.DstIP)
1✔
222
        needRecheck := false
1✔
223
        if bfd.Status == nil {
2✔
224
                needRecheck = true
1✔
225
        } else if *bfd.Status != ovnnb.BFDStatusUp {
3✔
226
                needRecheck = true
1✔
227
        }
1✔
228
        if !needRecheck {
2✔
229
                return
1✔
230
        }
1✔
231
        // bfd status should be up in 15 seconds
232
        for try := 1; try < 4; try++ {
2✔
233
                time.Sleep(5 * time.Second)
1✔
234
                klog.Warningf("the %d time check bfd status for lrp %s dst ip %s", try, bfd.LogicalPort, bfd.DstIP)
1✔
235
                if ok, err := c.isLrpBfdUp(bfd.LogicalPort, bfd.DstIP); err != nil {
2✔
236
                        klog.Errorf("failed to check bfd status for lrp %s dst ip %s, %v", bfd.LogicalPort, bfd.DstIP, err)
1✔
237
                        continue
1✔
UNCOV
238
                } else if ok {
×
UNCOV
239
                        break
×
240
                }
241
        }
242
}
243

244
func (c *OVNNbClient) bfdUpdateL3HAHandler(table string, oldModel, newModel model.Model) {
1✔
245
        if table != ovnnb.BFDTable {
2✔
246
                return
1✔
247
        }
1✔
248

249
        oldBfd := oldModel.(*ovnnb.BFD)
1✔
250
        newBfd := newModel.(*ovnnb.BFD)
1✔
251

1✔
252
        if newBfd.ExternalIDs[ExternalIDVpcEgressGateway] != "" {
1✔
253
                return
×
254
        }
×
255
        if oldBfd.Status == nil || newBfd.Status == nil {
2✔
256
                return
1✔
257
        }
1✔
258
        klog.Infof("lrp %s BFD to dst ip %s status changed from %s to %s", newBfd.LogicalPort, newBfd.DstIP, *oldBfd.Status, *newBfd.Status)
1✔
259

1✔
260
        if *oldBfd.Status == *newBfd.Status {
2✔
261
                return
1✔
262
        }
1✔
263
        lrpName := newBfd.LogicalPort
1✔
264
        dstIP := newBfd.DstIP
1✔
265
        if *oldBfd.Status == ovnnb.BFDStatusAdminDown && *newBfd.Status == ovnnb.BFDStatusDown {
2✔
266
                // bfd status should be up in 15 seconds
1✔
267
                for try := 1; try <= 3; try++ {
2✔
268
                        time.Sleep(5 * time.Second)
1✔
269
                        klog.Warningf("the %d time check bfd status for lrp %s dst ip %s", try, lrpName, dstIP)
1✔
270
                        if ok, err := c.isLrpBfdUp(lrpName, dstIP); err != nil {
2✔
271
                                klog.Errorf("failed to check bfd status for lrp %s dst ip %s, %v", lrpName, dstIP, err)
1✔
272
                                continue
1✔
273
                        } else if ok {
×
274
                                break
×
275
                        }
276
                }
277
        }
278

279
        if *oldBfd.Status == ovnnb.BFDStatusDown && *newBfd.Status == ovnnb.BFDStatusUp {
2✔
280
                // up
1✔
281
                gwChassisList, err := c.ListGatewayChassisByLogicalRouterPort(lrpName, false)
1✔
282
                if err != nil {
1✔
283
                        klog.Errorf("failed to list gateway chassis for lrp %s, %v", lrpName, err)
×
284
                        return
×
285
                }
×
286
                if len(gwChassisList) == 0 {
2✔
287
                        klog.Errorf("no gateway chassis for lrp %s", lrpName)
1✔
288
                        return
1✔
289
                }
1✔
290
                goodChassis := gwChassisList[0]
×
291
                goodChassis.Priority = util.GwChassisMaxPriority + 1
×
292
                klog.Infof("raise good chassis %s priority to %d", goodChassis.Name, goodChassis.Priority)
×
293
                if err := c.UpdateGatewayChassis(&goodChassis, &goodChassis.Priority); err != nil {
×
294
                        klog.Errorf("failed to update good chassis %s, %v", goodChassis.Name, err)
×
295
                        return
×
296
                }
×
297
        }
298

299
        // LRP may still locate on a bad chassis node
300
        // update recheck the bfd status later
301
        if *oldBfd.Status == ovnnb.BFDStatusUp && *newBfd.Status == ovnnb.BFDStatusDown {
2✔
302
                // down
1✔
303
                lrpName := newBfd.LogicalPort
1✔
304
                gwChassisList, err := c.ListGatewayChassisByLogicalRouterPort(lrpName, false)
1✔
305
                if err != nil {
1✔
306
                        klog.Errorf("failed to list gateway chassis for lrp %s, %v", lrpName, err)
×
307
                        return
×
308
                }
×
309
                if len(gwChassisList) == 0 {
2✔
310
                        klog.Errorf("no gateway chassis for lrp %s", lrpName)
1✔
311
                        return
1✔
312
                }
1✔
313
                badChassis := gwChassisList[0]
×
314
                // centralized gw chassis node number probably less than 5
×
315
                badChassis.Priority = util.GwChassisMaxPriority - 5
×
316
                klog.Infof("lower bad chassis %s priority to %d", badChassis.Name, badChassis.Priority)
×
317
                if err := c.UpdateGatewayChassis(&badChassis, &badChassis.Priority); err != nil {
×
318
                        klog.Errorf("failed to update bad chassis %s, %v", badChassis.Name, err)
×
319
                        return
×
320
                }
×
321
                // lower bad chassis priority will not trigger bfd update
322
                // recheck until bfd status is up
323
                try := 1
×
324
                for {
×
325
                        time.Sleep(5 * time.Second)
×
326
                        klog.Warningf("the %d time check bfd status for lrp %s dst ip %s", try, lrpName, dstIP)
×
327
                        if ok, err := c.isLrpBfdUp(lrpName, dstIP); err != nil {
×
328
                                // bfd status is still down
×
329
                                // update bfd external_ids to trigger bfd update
×
330
                                klog.Errorf("failed to check bfd status for lrp %s dst ip %s, %v", lrpName, dstIP, err)
×
331
                                gwChassisList, err = c.ListGatewayChassisByLogicalRouterPort(lrpName, false)
×
332
                                if err != nil {
×
333
                                        klog.Errorf("failed to list gateway chassis for lrp %s, %v", lrpName, err)
×
334
                                        return
×
335
                                }
×
336
                                if len(gwChassisList) == 0 {
×
337
                                        klog.Errorf("no gateway chassis for lrp %s", lrpName)
×
338
                                        return
×
339
                                }
×
340
                                badChassis = gwChassisList[0]
×
341
                                if newBfd.ExternalIDs == nil {
×
342
                                        newBfd.ExternalIDs = make(map[string]string)
×
343
                                }
×
344
                                if newBfd.ExternalIDs["gateway_chassis"] == badChassis.Name {
×
345
                                        klog.Errorf("lrp stuck on bad chassis %s", badChassis.Name)
×
346
                                        return
×
347
                                }
×
348
                                newBfd.ExternalIDs["gateway_chassis"] = badChassis.Name
×
349
                                klog.Infof("update bfd for lrp %s dst ip %s external_ids gateway_chassis to %s", newBfd.LogicalPort, dstIP, newBfd.ExternalIDs["gateway_chassis"])
×
350
                                if err := c.UpdateBFD(newBfd, &newBfd.ExternalIDs); err != nil {
×
351
                                        klog.Errorf("failed to update bfd for lrp %s, %v", lrpName, err)
×
352
                                        return
×
353
                                }
×
354
                                continue
×
355
                        } else if ok {
×
356
                                break
×
357
                        }
358
                        try++
×
359
                }
360
        }
361
}
362

363
func (c *OVNNbClient) bfdDelL3HAHandler(table string, model model.Model) {
1✔
364
        if table != ovnnb.BFDTable {
2✔
365
                return
1✔
366
        }
1✔
367
        bfd := model.(*ovnnb.BFD)
1✔
368
        if bfd.ExternalIDs[ExternalIDVpcEgressGateway] != "" {
1✔
369
                return
×
370
        }
×
371
        klog.Infof("lrp %s del BFD to dst ip %s", bfd.LogicalPort, bfd.DstIP)
1✔
372
}
373

374
func (c *OVNNbClient) FindBFD(externalIDs map[string]string) ([]ovnnb.BFD, error) {
1✔
375
        ctx, cancel := context.WithTimeout(context.Background(), c.Timeout)
1✔
376
        defer cancel()
1✔
377

1✔
378
        bfdList := make([]ovnnb.BFD, 0)
1✔
379
        if err := c.ovsDbClient.WhereCache(func(bfd *ovnnb.BFD) bool {
2✔
380
                if len(bfd.ExternalIDs) == 0 && len(externalIDs) != 0 {
2✔
381
                        return false
1✔
382
                }
1✔
383
                for k, v := range externalIDs {
2✔
384
                        if bfd.ExternalIDs[k] != v {
2✔
385
                                return false
1✔
386
                        }
1✔
387
                }
388
                return true
1✔
389
        }).List(ctx, &bfdList); err != nil {
×
390
                err := fmt.Errorf("failed to find ovn BFD: %w", err)
×
391
                klog.Error(err)
×
392
                return nil, err
×
393
        }
×
394

395
        return bfdList, nil
1✔
396
}
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