Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace contiv/libovsdb with ovn-org/libovsdb #76

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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{

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe use

WhereCache(func(_ *vswitchd.OpenvSwitch) bool { return true }).Mutate

instead of matching on rootUUID, this way we don't need to maintain the rootUUID.

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