Skip to content

Commit

Permalink
Use OVS Interface external_ids to save Antrea Interface type
Browse files Browse the repository at this point in the history
Introduce Antrea Interface Type to map the OVS port to Antrea created
interfaces, and use OVS Interface external_ids field to save the
configuration. This type is helpful for Antrea to define more inteface
types.

Signed-off-by: wenyingd <[email protected]>
  • Loading branch information
wenyingd committed Nov 26, 2021
1 parent 4864914 commit 434ed24
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 39 deletions.
131 changes: 95 additions & 36 deletions pkg/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,50 +226,103 @@ func (i *Initializer) initInterfaceStore() error {
return err
}

parseGatewayInterfaceFunc := func(port *ovsconfig.OVSPortData, ovsPort *interfacestore.OVSPortConfig) *interfacestore.InterfaceConfig {
intf := &interfacestore.InterfaceConfig{
Type: interfacestore.GatewayInterface,
InterfaceName: port.Name,
OVSPortConfig: ovsPort}
if intf.InterfaceName != i.hostGateway {
klog.Warningf("The discovered gateway interface name %s is different from the configured value: %s",
intf.InterfaceName, i.hostGateway)
// Set the gateway interface name to the discovered name.
i.hostGateway = intf.InterfaceName
}
return intf
}
parseUplinkInterfaceFunc := func(port *ovsconfig.OVSPortData, ovsPort *interfacestore.OVSPortConfig) *interfacestore.InterfaceConfig {
return &interfacestore.InterfaceConfig{
Type: interfacestore.UplinkInterface,
InterfaceName: port.Name,
OVSPortConfig: ovsPort,
}
}
parseTunnelInterfaceFunc := func(port *ovsconfig.OVSPortData, ovsPort *interfacestore.OVSPortConfig) *interfacestore.InterfaceConfig {
intf := noderoute.ParseTunnelInterfaceConfig(port, ovsPort)
if intf != nil && port.OFPort == config.DefaultTunOFPort &&
intf.InterfaceName != i.nodeConfig.DefaultTunName {
klog.Infof("The discovered default tunnel interface name %s is different from the default value: %s",
intf.InterfaceName, i.nodeConfig.DefaultTunName)
// Set the default tunnel interface name to the discovered name.
i.nodeConfig.DefaultTunName = intf.InterfaceName
}
return intf
}
ifaceList := make([]*interfacestore.InterfaceConfig, 0, len(ovsPorts))
uplinkIfName := i.nodeConfig.UplinkNetConfig.Name
for index := range ovsPorts {
port := &ovsPorts[index]
ovsPort := &interfacestore.OVSPortConfig{
PortUUID: port.UUID,
OFPort: port.OFPort}
var intf *interfacestore.InterfaceConfig
switch {
case port.OFPort == config.HostGatewayOFPort:
intf = &interfacestore.InterfaceConfig{
Type: interfacestore.GatewayInterface,
InterfaceName: port.Name,
OVSPortConfig: ovsPort}
if intf.InterfaceName != i.hostGateway {
klog.Warningf("The discovered gateway interface name %s is different from the configured value: %s",
intf.InterfaceName, i.hostGateway)
// Set the gateway interface name to the discovered name.
i.hostGateway = intf.InterfaceName
interfaceType, ok := port.ExternalIDs[interfacestore.AntreaInterfaceTypeKey]
if !ok {
interfaceType = interfacestore.AntreaUnset
}
if interfaceType != interfacestore.AntreaUnset {
switch interfaceType {
case interfacestore.AntreaGateway:
intf = parseGatewayInterfaceFunc(port, ovsPort)
case interfacestore.AntreaUplink:
intf = parseUplinkInterfaceFunc(port, ovsPort)
case interfacestore.AntreaTunnel:
intf = parseTunnelInterfaceFunc(port, ovsPort)
case interfacestore.AntreaHost:
// Not load the host interface, because it is configured on the OVS bridge port, and we don't need a
// specific interface in the interfaceStore.
intf = nil
case interfacestore.AntreaContainer:
// The port should be for a container interface.
intf = cniserver.ParseOVSPortInterfaceConfig(port, ovsPort, true)
default:
klog.InfoS("Unknown Antrea interface type", "type", interfaceType)
}
} else {
// Antrea Interface type is not saved in OVS port external_ids in earlier Antrea versions, so we use
// the old way to decide the interface type for the upgrade case.
uplinkIfName := i.nodeConfig.UplinkNetConfig.Name
var antreaIFType string
switch {
case port.OFPort == config.HostGatewayOFPort:
intf = parseGatewayInterfaceFunc(port, ovsPort)
antreaIFType = interfacestore.AntreaGateway
case port.Name == uplinkIfName:
intf = parseUplinkInterfaceFunc(port, ovsPort)
antreaIFType = interfacestore.AntreaUplink
case port.IFType == ovsconfig.GeneveTunnel:
fallthrough
case port.IFType == ovsconfig.VXLANTunnel:
fallthrough
case port.IFType == ovsconfig.GRETunnel:
fallthrough
case port.IFType == ovsconfig.STTTunnel:
intf = parseTunnelInterfaceFunc(port, ovsPort)
antreaIFType = interfacestore.AntreaTunnel
case port.Name == i.ovsBridge:
intf = nil
antreaIFType = interfacestore.AntreaHost
default:
// The port should be for a container interface.
intf = cniserver.ParseOVSPortInterfaceConfig(port, ovsPort, true)
antreaIFType = interfacestore.AntreaContainer
}
case port.Name == uplinkIfName:
intf = &interfacestore.InterfaceConfig{
Type: interfacestore.UplinkInterface,
InterfaceName: port.Name,
OVSPortConfig: ovsPort,
updatedExtIDs := make(map[string]interface{})
for k, v := range port.ExternalIDs {
updatedExtIDs[k] = v
}
case port.IFType == ovsconfig.GeneveTunnel:
fallthrough
case port.IFType == ovsconfig.VXLANTunnel:
fallthrough
case port.IFType == ovsconfig.GRETunnel:
fallthrough
case port.IFType == ovsconfig.STTTunnel:
intf = noderoute.ParseTunnelInterfaceConfig(port, ovsPort)
if intf != nil && port.OFPort == config.DefaultTunOFPort &&
intf.InterfaceName != i.nodeConfig.DefaultTunName {
klog.Infof("The discovered default tunnel interface name %s is different from the default value: %s",
intf.InterfaceName, i.nodeConfig.DefaultTunName)
// Set the default tunnel interface name to the discovered name.
i.nodeConfig.DefaultTunName = intf.InterfaceName
updatedExtIDs[interfacestore.AntreaInterfaceTypeKey] = antreaIFType
if err := i.ovsBridgeClient.UpdatePortExternalIDs(port.Name, updatedExtIDs); err != nil {
klog.InfoS("Failed to set Antrea interface type on OVS port", "port", port.Name)
}
default:
// The port should be for a container interface.
intf = cniserver.ParseOVSPortInterfaceConfig(port, ovsPort, true)
}
if intf != nil {
ifaceList = append(ifaceList, intf)
Expand Down Expand Up @@ -556,7 +609,10 @@ func (i *Initializer) setupGatewayInterface() error {
gatewayIface, portExists := i.ifaceStore.GetInterface(i.hostGateway)
if !portExists {
klog.V(2).Infof("Creating gateway port %s on OVS bridge", i.hostGateway)
gwPortUUID, err := i.ovsBridgeClient.CreateInternalPort(i.hostGateway, config.HostGatewayOFPort, nil)
externalIDs := map[string]interface{}{
interfacestore.AntreaInterfaceTypeKey: interfacestore.AntreaGateway,
}
gwPortUUID, err := i.ovsBridgeClient.CreateInternalPort(i.hostGateway, config.HostGatewayOFPort, externalIDs)
if err != nil {
klog.Errorf("Failed to create gateway port %s on OVS bridge: %v", i.hostGateway, err)
return err
Expand Down Expand Up @@ -681,7 +737,10 @@ func (i *Initializer) setupDefaultTunnelInterface() error {
tunnelPortName = defaultTunInterfaceName
i.nodeConfig.DefaultTunName = tunnelPortName
}
tunnelPortUUID, err := i.ovsBridgeClient.CreateTunnelPortExt(tunnelPortName, i.networkConfig.TunnelType, config.DefaultTunOFPort, shouldEnableCsum, localIPStr, "", "", nil)
externalIDs := map[string]interface{}{
interfacestore.AntreaInterfaceTypeKey: interfacestore.AntreaTunnel,
}
tunnelPortUUID, err := i.ovsBridgeClient.CreateTunnelPortExt(tunnelPortName, i.networkConfig.TunnelType, config.DefaultTunOFPort, shouldEnableCsum, localIPStr, "", "", externalIDs)
if err != nil {
klog.Errorf("Failed to create tunnel port %s type %s on OVS bridge: %v", tunnelPortName, i.networkConfig.TunnelType, err)
return err
Expand Down
7 changes: 5 additions & 2 deletions pkg/agent/agent_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,10 @@ func (i *Initializer) prepareOVSBridge() error {
} else {
// OVS does not receive "ofport_request" param when creating local port, so here use config.AutoAssignedOFPort=0
// to ignore this param.
if _, err = i.ovsBridgeClient.CreateInternalPort(brName, config.AutoAssignedOFPort, nil); err != nil {
externalIDs := map[string]interface{}{
interfacestore.AntreaInterfaceTypeKey: interfacestore.AntreaHost,
}
if _, err = i.ovsBridgeClient.CreateInternalPort(brName, config.AutoAssignedOFPort, externalIDs); err != nil {
return err
}
}
Expand Down Expand Up @@ -208,7 +211,7 @@ func (i *Initializer) BridgeUplinkToOVSBridge() error {
return err
}
// Create uplink port.
uplinkPortUUId, err := i.ovsBridgeClient.CreateUplinkPort(uplink, config.UplinkOFPort, map[string]interface{}{"antrea-uplink": "true"})
uplinkPortUUId, err := i.ovsBridgeClient.CreateUplinkPort(uplink, config.UplinkOFPort, map[string]interface{}{"antrea-uplink": "true", interfacestore.AntreaInterfaceTypeKey: interfacestore.AntreaUplink})
if err != nil {
return fmt.Errorf("failed to add uplink port %s: err=%w", uplink, err)
}
Expand Down
17 changes: 17 additions & 0 deletions pkg/agent/agent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,23 @@ func TestInitstore(t *testing.T) {
if !found2 {
t.Errorf("Failed to load OVS port into local store")
}

// OVS port external_ids should be updated to set AntreaInterfaceTypeKey if it is not existing in OVSPortData.
delete(ovsPort1.ExternalIDs, interfacestore.AntreaInterfaceTypeKey)
delete(ovsPort2.ExternalIDs, interfacestore.AntreaInterfaceTypeKey)
initOVSPorts2 := []ovsconfig.OVSPortData{ovsPort1, ovsPort2}
mockOVSBridgeClient.EXPECT().GetPortList().Return(initOVSPorts2, nil)
updateExtIDsFunc := func(p ovsconfig.OVSPortData) map[string]interface{} {
extIDs := make(map[string]interface{})
for k, v := range p.ExternalIDs {
extIDs[k] = v
}
extIDs[interfacestore.AntreaInterfaceTypeKey] = interfacestore.AntreaContainer
return extIDs
}
mockOVSBridgeClient.EXPECT().UpdatePortExternalIDs(ovsPort1.Name, updateExtIDsFunc(ovsPort1)).Return(nil)
mockOVSBridgeClient.EXPECT().UpdatePortExternalIDs(ovsPort2.Name, updateExtIDsFunc(ovsPort2)).Return(nil)
initializer.initInterfaceStore()
}

func TestPersistRoundNum(t *testing.T) {
Expand Down
5 changes: 4 additions & 1 deletion pkg/agent/agent_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,10 @@ func (i *Initializer) prepareOVSBridge() error {
} else {
// OVS does not receive "ofport_request" param when creating local port, so here use config.AutoAssignedOFPort=0
// to ignore this param.
if _, err = i.ovsBridgeClient.CreateInternalPort(brName, config.AutoAssignedOFPort, nil); err != nil {
externalIDs := map[string]interface{}{
interfacestore.AntreaInterfaceTypeKey: interfacestore.AntreaHost,
}
if _, err = i.ovsBridgeClient.CreateInternalPort(brName, config.AutoAssignedOFPort, externalIDs); err != nil {
return err
}
}
Expand Down
1 change: 1 addition & 0 deletions pkg/agent/cniserver/pod_configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ func BuildOVSPortExternalIDs(containerConfig *interfacestore.InterfaceConfig) ma
externalIDs[ovsExternalIDIP] = getContainerIPsString(containerConfig.IPs)
externalIDs[ovsExternalIDPodName] = containerConfig.PodName
externalIDs[ovsExternalIDPodNamespace] = containerConfig.PodNamespace
externalIDs[interfacestore.AntreaInterfaceTypeKey] = interfacestore.AntreaContainer
return externalIDs
}

Expand Down
8 changes: 8 additions & 0 deletions pkg/agent/interfacestore/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ const (
TunnelInterface
// UplinkInterface is used to mark current interface is for uplink port
UplinkInterface

AntreaInterfaceTypeKey = "antrea-type"
AntreaGateway = "gateway"
AntreaContainer = "container"
AntreaTunnel = "tunnel"
AntreaUplink = "uplink"
AntreaHost = "host"
AntreaUnset = ""
)

type InterfaceType uint8
Expand Down
1 change: 1 addition & 0 deletions pkg/ovs/ovsconfig/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,5 @@ type OVSBridgeClient interface {
GetBridgeName() string
IsHardwareOffloadEnabled() bool
GetOVSDatapathType() OVSDatapathType
UpdatePortExternalIDs(portName string, externalIDs map[string]interface{}) Error
}
17 changes: 17 additions & 0 deletions pkg/ovs/ovsconfig/ovs_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -879,3 +879,20 @@ func (br *OVSBridge) getHardwareOffload() (bool, Error) {
func (br *OVSBridge) GetOVSDatapathType() OVSDatapathType {
return br.datapathType
}

func (br *OVSBridge) UpdatePortExternalIDs(portName string, externalIDs map[string]interface{}) Error {
tx := br.ovsdb.Transaction(openvSwitchSchema)
tx.Update(dbtransaction.Update{
Table: "Port",
Where: [][]interface{}{{"name", "==", portName}},
Row: map[string]interface{}{
"external_ids": helpers.MakeOVSDBMap(externalIDs),
},
})
_, err, temporary := tx.Commit()
if err != nil {
klog.Error("Transaction failed", err)
return NewTransactionError(err, temporary)
}
return nil
}
14 changes: 14 additions & 0 deletions pkg/ovs/ovsconfig/testing/mock_ovsconfig.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 434ed24

Please sign in to comment.