Skip to content

Commit

Permalink
Replace contiv/libovsdb with ovn-org/libovsdb
Browse files Browse the repository at this point in the history
contiv/libovsdb is abandoned and we were using a version from 2017

Instead we use github.com/ovn-org/libovsdb, which is still under active
development and is used by ovn-kubernetes.

We also move the ovsdbDriver code to an internal package: it is only
used for integration tests and does not need to be part of the public
API. All the functions that were not used anywhere are also removed.

Bump up version to v0.13.0.

Fixes antrea-io#62

Signed-off-by: Antonin Bas <[email protected]>
  • Loading branch information
antoninbas committed Oct 28, 2023
1 parent a73fa6b commit ebd672b
Show file tree
Hide file tree
Showing 11 changed files with 831 additions and 740 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v0.12.0
v0.13.0
21 changes: 16 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,34 @@ go 1.21
require (
antrea.io/libOpenflow v0.13.0
github.com/Microsoft/go-winio v0.6.1
github.com/contiv/libovsdb v0.0.0-20170227191248-d0061a53e358
github.com/orcaman/concurrent-map/v2 v2.0.1
github.com/ovn-org/libovsdb v0.6.1-0.20230912124059-239822fe891a
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.8.4
)

require (
github.com/cenkalti/hub v1.0.1-0.20140529221144-7be60e186e66 // indirect
github.com/cenkalti/rpc2 v0.0.0-20140912135055-44d0d95e4f52 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
github.com/cenkalti/hub v1.0.1 // indirect
github.com/cenkalti/rpc2 v0.0.0-20210604223624-c1acbc6ec984 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-logr/logr v1.2.0 // indirect
github.com/go-logr/logr v1.2.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/uuid v1.2.0 // indirect
github.com/kr/pretty v0.2.0 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.12.1 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.32.1 // indirect
github.com/prometheus/procfs v0.7.3 // indirect
golang.org/x/mod v0.8.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/tools v0.6.0 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
)
478 changes: 471 additions & 7 deletions go.sum

Large diffs are not rendered by default.

200 changes: 200 additions & 0 deletions ofctrl/internal/ovsdbDriver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
package internal

import (
"context"
"fmt"

"github.com/ovn-org/libovsdb/client"
"github.com/ovn-org/libovsdb/model"
"github.com/ovn-org/libovsdb/ovsdb"
log "github.com/sirupsen/logrus"

"antrea.io/ofnet/ofctrl/internal/vswitchd"
)

// OVS driver state
type OvsDriver struct {
// OVS client
client client.Client

// Name of the OVS bridge
brName string

rootUUID string
}

func newOvsDriver(ctx context.Context, bridgeName string) (*OvsDriver, error) {
dbModel, err := vswitchd.Model()
if err != nil {
return nil, err
}
ovs, err := client.NewOVSDBClient(dbModel, client.WithEndpoint("tcp:localhost:6640"))
if err != nil {
return nil, fmt.Errorf("failed to create client: %w", err)
}
if err := ovs.Connect(ctx); err != nil {
return nil, fmt.Errorf("failed to connect to ovsdb: %w", err)
}

if _, err := ovs.Monitor(
ctx,
ovs.NewMonitor(
client.WithTable(&vswitchd.OpenvSwitch{}),
client.WithTable(&vswitchd.Bridge{}),
),
); err != nil {
return nil, err
}

// Get root UUID
var rootUUID string
for uuid := range ovs.Cache().Table("Open_vSwitch").Rows() {
rootUUID = uuid
}

ovsDriver := &OvsDriver{
client: ovs,
brName: bridgeName,
rootUUID: rootUUID,
}
if err := ovsDriver.createBridge(ctx); err != nil {
return nil, fmt.Errorf("failed to create bridge: %w", err)
}
return ovsDriver, nil
}

// Create a new OVS driver
func NewOvsDriver(bridgeName string) *OvsDriver {
ovsDriver, err := newOvsDriver(context.Background(), bridgeName)
if err != nil {
log.Fatalf("fail to create OVS driver: %v", err)
}
return ovsDriver
}

// Delete removes the bridge and disconnects the client
func (d *OvsDriver) Delete() error {
if d.client != nil {
if err := d.deleteBridge(context.Background()); err != nil {
return fmt.Errorf("error when deleting bridge %s: %w", d.brName, err)
}
log.Infof("Deleting OVS bridge: %s", d.brName)
d.client.Disconnect()
}

return nil
}

// Wrapper for ovsDB transaction
func (d *OvsDriver) ovsdbTransact(ctx context.Context, ops []ovsdb.Operation) error {
// Print out what we are sending
log.Debugf("Transaction: %+v\n", ops)

// Perform OVSDB transaction
reply, err := d.client.Transact(ctx, ops...)
if err != nil {
return err
}

if _, err := ovsdb.CheckOperationResults(reply, ops); err != nil {
return err
}

return nil
}

func (d *OvsDriver) createBridge(ctx context.Context) error {
// If the bridge already exists, just return
// FIXME: should we delete the old bridge and create new one?
if _, ok := d.getBridgeUUID(); ok {
return nil
}

const brNamedUUID = "testbr"

protocols := []vswitchd.BridgeProtocols{
vswitchd.BridgeProtocolsOpenflow10,
vswitchd.BridgeProtocolsOpenflow11,
vswitchd.BridgeProtocolsOpenflow12,
vswitchd.BridgeProtocolsOpenflow13,
vswitchd.BridgeProtocolsOpenflow14,
vswitchd.BridgeProtocolsOpenflow15,
}
br := &vswitchd.Bridge{
UUID: brNamedUUID,
FailMode: &vswitchd.BridgeFailModeSecure,
Name: d.brName,
Protocols: protocols,
}

insertOps, err := d.client.Create(br)
if err != nil {
return err
}

// Inserting/Deleting a Bridge row in Bridge table requires mutating
// the open_vswitch table.
ovsRow := vswitchd.OpenvSwitch{
UUID: d.rootUUID,
}
mutateOps, err := d.client.Where(&ovsRow).Mutate(&ovsRow, model.Mutation{
Field: &ovsRow.Bridges,
Mutator: "insert",
Value: []string{br.UUID},
})
if err != nil {
return err
}

ops := append(insertOps, mutateOps...)

return d.ovsdbTransact(ctx, ops)
}

func (d *OvsDriver) deleteBridge(ctx context.Context) error {
uuid, ok := d.getBridgeUUID()
if !ok {
return nil
}
br := &vswitchd.Bridge{
UUID: uuid,
}

deleteOps, err := d.client.Where(br).Delete()
if err != nil {
return err
}

// Inserting/Deleting a Bridge row in Bridge table requires mutating
// the open_vswitch table.
ovsRow := vswitchd.OpenvSwitch{
UUID: d.rootUUID,
}
mutateOps, err := d.client.Where(&ovsRow).Mutate(&ovsRow, model.Mutation{
Field: &ovsRow.Bridges,
Mutator: "delete",
Value: []string{br.UUID},
})
if err != nil {
return err
}

ops := append(deleteOps, mutateOps...)

return d.ovsdbTransact(ctx, ops)
}

func (d *OvsDriver) getBridgeUUID() (string, bool) {
rows := d.client.Cache().Table("Bridge").Rows()
for uuid, m := range rows {
br := m.(*vswitchd.Bridge)
if br.Name == d.brName {
return uuid, true
}
}
return "", false
}

func (d *OvsDriver) BridgeName() string {
return d.brName
}
31 changes: 31 additions & 0 deletions ofctrl/internal/vswitchd/bridge.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package vswitchd

type (
BridgeFailMode = string
BridgeProtocols = string
)

var (
BridgeFailModeStandalone BridgeFailMode = "standalone"
BridgeFailModeSecure BridgeFailMode = "secure"
BridgeProtocolsOpenflow10 BridgeProtocols = "OpenFlow10"
BridgeProtocolsOpenflow11 BridgeProtocols = "OpenFlow11"
BridgeProtocolsOpenflow12 BridgeProtocols = "OpenFlow12"
BridgeProtocolsOpenflow13 BridgeProtocols = "OpenFlow13"
BridgeProtocolsOpenflow14 BridgeProtocols = "OpenFlow14"
BridgeProtocolsOpenflow15 BridgeProtocols = "OpenFlow15"
)

// Bridge defines an object in Bridge table
// We only include the fields we need
type Bridge struct {
UUID string `ovsdb:"_uuid"`
// Include these fields (DatapathID, DatapathVersion) so that libovsdb
// does not complain about missing model fields.
DatapathID *string `ovsdb:"datapath_id"`
DatapathType string `ovsdb:"datapath_type"`
DatapathVersion string `ovsdb:"datapath_version"`
FailMode *BridgeFailMode `ovsdb:"fail_mode"`
Name string `ovsdb:"name"`
Protocols []BridgeProtocols `ovsdb:"protocols"`
}
12 changes: 12 additions & 0 deletions ofctrl/internal/vswitchd/model.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package vswitchd

import (
"github.com/ovn-org/libovsdb/model"
)

func Model() (model.ClientDBModel, error) {
return model.NewClientDBModel("Open_vSwitch", map[string]model.Model{
"Bridge": &Bridge{},
"Open_vSwitch": &OpenvSwitch{},
})
}
8 changes: 8 additions & 0 deletions ofctrl/internal/vswitchd/open_vswitch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package vswitchd

// OpenvSwitch defines an object in Open_vSwitch table
// We only include the fields we need
type OpenvSwitch struct {
UUID string `ovsdb:"_uuid"`
Bridges []string `ovsdb:"bridges"`
}
2 changes: 1 addition & 1 deletion ofctrl/multipart_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func TestMultipartReply(t *testing.T) {
brName := "brMultipart"
ovsBr := prepareControllerAndSwitch(t, app.OfActor, ctrl, brName)
defer func() {
assert.Nilf(t, ovsBr.DeleteBridge(brName), "Failed to delete br %s", brName)
assert.NoError(t, ovsBr.Delete())
ctrl.Delete()
}()
testTableFeatures(t, app)
Expand Down
Loading

0 comments on commit ebd672b

Please sign in to comment.