Skip to content

Commit 0374143

Browse files
committed
[flexible-ipam] Use uplink interface name for host interface internal port
Add a suffix to uplink when bridging to OVS bridge. Signed-off-by: gran <gran@vmware.com>
1 parent c6df2eb commit 0374143

12 files changed

Lines changed: 149 additions & 108 deletions

File tree

pkg/agent/agent.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ func (i *Initializer) setupGatewayInterface() error {
606606
externalIDs := map[string]interface{}{
607607
interfacestore.AntreaInterfaceTypeKey: interfacestore.AntreaGateway,
608608
}
609-
gwPortUUID, err := i.ovsBridgeClient.CreateInternalPort(i.hostGateway, config.HostGatewayOFPort, externalIDs)
609+
gwPortUUID, err := i.ovsBridgeClient.CreateInternalPort(i.hostGateway, config.HostGatewayOFPort, "", externalIDs)
610610
if err != nil {
611611
klog.ErrorS(err, "Failed to create gateway port on OVS bridge", "port", i.hostGateway)
612612
return err
@@ -1144,8 +1144,11 @@ func (i *Initializer) getNodeInterfaceFromIP(nodeIPs *utilip.DualStackIPs) (v4IP
11441144
// getFreeOFPort returns an OpenFlow port number which is not used by any existing OVS port. Note that, the returned port
11451145
// is not saved in OVSDB yet before the real port is created, so it might introduce an issue for the same return value
11461146
// if it is called multiple times before OVS port creation.
1147-
func (i *Initializer) getFreeOFPort(startPort int) (int32, error) {
1147+
func (i *Initializer) getFreeOFPort(startPort int, reservedPorts []int32) (int32, error) {
11481148
existingOFPorts := sets.NewInt32()
1149+
for _, reservedPort := range reservedPorts {
1150+
existingOFPorts.Insert(reservedPort)
1151+
}
11491152
ports, err := i.ovsBridgeClient.GetPortList()
11501153
if err != nil {
11511154
return 0, err

pkg/agent/agent_linux.go

Lines changed: 102 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import (
3030
"antrea.io/antrea/pkg/agent/config"
3131
"antrea.io/antrea/pkg/agent/interfacestore"
3232
"antrea.io/antrea/pkg/agent/util"
33-
"antrea.io/antrea/pkg/ovs/ovsconfig"
3433
utilip "antrea.io/antrea/pkg/util/ip"
3534
)
3635

@@ -78,63 +77,39 @@ func (i *Initializer) prepareOVSBridge() error {
7877
return fmt.Errorf("failed to set datapath_id %s: err=%w", datapathID, err)
7978
}
8079

81-
// Create local port.
82-
brName := i.ovsBridgeClient.GetBridgeName()
83-
if _, err = i.ovsBridgeClient.GetOFPort(brName, false); err == nil {
84-
klog.Infof("OVS bridge local port %s already exists, skip the configuration", brName)
85-
// If uplink is internal port, get the real uplink interface.
80+
if hostOFPort, err := i.ovsBridgeClient.GetOFPort(uplinkNetConfig.Name, false); err == nil {
81+
klog.Infof("OVS bridge local port %s already exists", uplinkNetConfig.Name)
82+
i.nodeConfig.HostInterfaceOFPort = uint32(hostOFPort)
83+
// If local port exists, get the real uplink interface.
8684
// This branch is used when antrea-agent get a hard restart (e.g. SIGKILL)
87-
if uplinkNetConfig.Name == brName {
88-
ports, err := i.ovsBridgeClient.GetPortList()
89-
if err != nil {
90-
return err
91-
}
92-
klog.V(2).Infof("Found ports from OVS bridge: %+v", ports)
93-
var uplinkPort *ovsconfig.OVSPortData
94-
for index := range ports {
95-
antreaIfaceType, _ := ports[index].ExternalIDs[interfacestore.AntreaInterfaceTypeKey]
96-
if antreaIfaceType == interfacestore.AntreaUplink {
97-
uplinkPort = &ports[index]
98-
break
99-
}
100-
}
101-
if uplinkPort == nil {
102-
return fmt.Errorf("cannot find uplink port from OVS bridge %s", brName)
103-
}
104-
adapter, err2 := net.InterfaceByName(uplinkPort.Name)
105-
if err2 != nil {
106-
return fmt.Errorf("cannot find uplink port %s: err=%w", uplinkPort.Name, err2)
107-
}
108-
klog.Infof("Found uplink device %s", adapter.Name)
109-
uplinkNetConfig.OFPort = uint32(uplinkPort.OFPort)
110-
uplinkNetConfig.Name = adapter.Name
85+
bridgedUplinkName := util.GetBridgedUplinkName(uplinkNetConfig.Name)
86+
if uplinkOFPort, err := i.ovsBridgeClient.GetOFPort(bridgedUplinkName, false); err != nil {
87+
return fmt.Errorf("cannot find uplink port %s: err=%w", bridgedUplinkName, err)
88+
} else {
89+
uplinkNetConfig.OFPort = uint32(uplinkOFPort)
90+
}
91+
if adapter, err := net.InterfaceByName(bridgedUplinkName); err != nil {
92+
return fmt.Errorf("cannot find uplink port %s: err=%w", bridgedUplinkName, err)
93+
} else {
11194
uplinkNetConfig.Index = adapter.Index
112-
uplinkInterface := interfacestore.NewUplinkInterface(uplinkPort.Name)
113-
uplinkInterface.OVSPortConfig = &interfacestore.OVSPortConfig{uplinkPort.UUID, uplinkPort.OFPort} //nolint: govet
114-
i.ifaceStore.AddInterface(uplinkInterface)
11595
}
96+
klog.InfoS("Found uplink", "Name", adapter.Name, "Index", uplinkNetConfig.Index, "OFPort", uplinkNetConfig.OFPort)
11697
} else {
117-
// OVS does not receive "ofport_request" param when creating local port, so here use config.AutoAssignedOFPort=0
118-
// to ignore this param.
119-
externalIDs := map[string]interface{}{
120-
interfacestore.AntreaInterfaceTypeKey: interfacestore.AntreaHost,
121-
}
122-
if _, err = i.ovsBridgeClient.CreateInternalPort(brName, config.AutoAssignedOFPort, externalIDs); err != nil {
98+
freePort, err := i.getFreeOFPort(config.UplinkOFPort, nil)
99+
if err != nil {
100+
klog.ErrorS(err, "Failed to find a free port on OVS")
123101
return err
124102
}
125-
}
126-
127-
i.nodeConfig.HostInterfaceOFPort = config.BridgeOFPort
128-
if uplinkNetConfig.OFPort == 0 {
129-
freePort, err := i.getFreeOFPort(config.UplinkOFPort)
103+
uplinkNetConfig.OFPort = uint32(freePort)
104+
klog.InfoS("Set OpenFlow port in UplinkNetConfig", "ofport", uplinkNetConfig.OFPort)
105+
freePort, err = i.getFreeOFPort(config.UplinkOFPort, []int32{freePort})
130106
if err != nil {
131107
klog.ErrorS(err, "Failed to find a free port on OVS")
132108
return err
133109
}
134-
uplinkNetConfig.OFPort = uint32(freePort)
135-
klog.InfoS("Set OpenFlow port in UplinkNetConfig", "ofport", freePort)
110+
i.nodeConfig.HostInterfaceOFPort = uint32(freePort)
111+
klog.InfoS("Set host interface", "ofport", i.nodeConfig.HostInterfaceOFPort)
136112
}
137-
138113
return nil
139114
}
140115

@@ -179,7 +154,7 @@ func (i *Initializer) saveHostRoutes() error {
179154
// the antrea network initialize stage.
180155
// The backup routes are restored after the IP configuration change.
181156
func (i *Initializer) restoreHostRoutes() error {
182-
return i.restoreHostRoutesToInterface(i.ovsBridge)
157+
return i.restoreHostRoutesToInterface(i.nodeConfig.UplinkNetConfig.Name)
183158
}
184159

185160
func (i *Initializer) restoreHostRoutesToInterface(ifaceName string) error {
@@ -206,53 +181,65 @@ func (i *Initializer) ConnectUplinkToOVSBridge() error {
206181
klog.Infof("Bridging uplink to OVS bridge")
207182
var err error
208183
uplinkNetConfig := i.nodeConfig.UplinkNetConfig
209-
brName := i.ovsBridgeClient.GetBridgeName()
184+
uplinkName := uplinkNetConfig.Name
185+
bridgedUplinkName := util.GetBridgedUplinkName(uplinkNetConfig.Name)
210186

211187
// If uplink is already exists, return.
212-
uplink := uplinkNetConfig.Name
213-
if uplinkOFPort, err := i.ovsBridgeClient.GetOFPort(uplink, false); err == nil {
214-
klog.InfoS("Uplink already exists, skip the configuration", "uplink", uplink, "port", uplinkOFPort)
188+
if uplinkOFPort, err := i.ovsBridgeClient.GetOFPort(bridgedUplinkName, false); err == nil {
189+
klog.InfoS("Uplink already exists, skip the configuration", "uplink", bridgedUplinkName, "port", uplinkOFPort)
215190
return nil
216191
}
192+
uplinkIPs, err := getTransportIPNetDeviceByNameWithExcludedList(uplinkName, nil)
193+
if err != nil {
194+
return fmt.Errorf("failed to get uplink IPs: err=%w", err)
195+
}
196+
if err := util.ChangeAdapterName(uplinkName, bridgedUplinkName, true); err != nil {
197+
return fmt.Errorf("failed to change uplink interface name: err=%w", err)
198+
}
199+
217200
// Create uplink port.
218-
uplinkPortUUID, err := i.ovsBridgeClient.CreateUplinkPort(uplink, int32(i.nodeConfig.UplinkNetConfig.OFPort), map[string]interface{}{interfacestore.AntreaInterfaceTypeKey: interfacestore.AntreaUplink})
201+
uplinkPortUUID, err := i.ovsBridgeClient.CreateUplinkPort(bridgedUplinkName, int32(uplinkNetConfig.OFPort), map[string]interface{}{interfacestore.AntreaInterfaceTypeKey: interfacestore.AntreaUplink})
219202
if err != nil {
220-
return fmt.Errorf("failed to add uplink port %s: err=%w", uplink, err)
203+
return fmt.Errorf("failed to add uplink port %s: err=%w", bridgedUplinkName, err)
221204
}
222-
// Add newly created uplinkInterface to interface cache. This will be overwritten by initInterfaceStore.
223-
uplinkInterface := interfacestore.NewUplinkInterface(uplink)
224-
uplinkOFPort, err := i.ovsBridgeClient.GetOFPort(uplink, false)
205+
// Add newly created uplinkInterface to interface cache.
206+
uplinkInterface := interfacestore.NewUplinkInterface(bridgedUplinkName)
207+
uplinkOFPort, err := i.ovsBridgeClient.GetOFPort(bridgedUplinkName, false)
225208
if err != nil {
226-
return fmt.Errorf("failed to get uplink ofport %s: err=%w", uplink, err)
209+
return fmt.Errorf("failed to get uplink ofport %s: err=%w", bridgedUplinkName, err)
227210
}
228-
klog.InfoS("Allocated OpenFlow port for uplink interface", "port", uplink, "ofPort", uplinkOFPort)
211+
klog.InfoS("Allocated OpenFlow port for uplink interface", "port", bridgedUplinkName, "ofPort", uplinkOFPort)
229212
uplinkInterface.OVSPortConfig = &interfacestore.OVSPortConfig{uplinkPortUUID, uplinkOFPort} //nolint: govet
230213
i.ifaceStore.AddInterface(uplinkInterface)
231214

215+
// Create local port.
216+
externalIDs := map[string]interface{}{
217+
interfacestore.AntreaInterfaceTypeKey: interfacestore.AntreaHost,
218+
}
219+
if _, err = i.ovsBridgeClient.CreateInternalPort(uplinkName, int32(i.nodeConfig.HostInterfaceOFPort), uplinkNetConfig.MAC.String(), externalIDs); err != nil {
220+
return fmt.Errorf("cannot create host interface port %s: err=%w", uplinkName, err)
221+
}
222+
232223
// Move network configuration of uplink interface to OVS bridge local interface.
233224
// The net configuration of uplink will be restored by RestoreOVSBridge when shutting down.
234225
wait.PollImmediate(100*time.Millisecond, 10000*time.Millisecond, func() (bool, error) {
235226
// Wait a few seconds for OVS bridge local port.
236-
link, err := netlink.LinkByName(brName)
227+
link, err := netlink.LinkByName(uplinkName)
237228
if err != nil {
238-
klog.V(4).InfoS("OVS bridge local port is not ready", "port", brName, "err", err)
229+
klog.V(4).InfoS("OVS bridge local port is not ready", "port", uplinkName, "err", err)
239230
return false, nil
240231
}
241232
klog.InfoS("OVS bridge local port is ready", "type", link.Type(), "attrs", link.Attrs())
242233
return true, nil
243234
})
244-
brLink, err := netlink.LinkByName(brName)
235+
localLink, err := netlink.LinkByName(uplinkName)
245236
if err != nil {
246237
return err
247238
}
248-
if _, _, err = util.SetLinkUp(brName); err != nil {
249-
return err
250-
}
251-
if err = util.SetAdapterMACAddress(brName, &uplinkNetConfig.MAC); err != nil {
239+
if _, _, err = util.SetLinkUp(uplinkName); err != nil {
252240
return err
253241
}
254-
// TODO(gran): support IPv6
255-
if err = util.ConfigureLinkAddresses(brLink.Attrs().Index, []*net.IPNet{uplinkNetConfig.IP}); err != nil {
242+
if err = util.ConfigureLinkAddresses(localLink.Attrs().Index, uplinkIPs); err != nil {
256243
return err
257244
}
258245
if err = util.ConfigureLinkAddresses(uplinkNetConfig.Index, nil); err != nil {
@@ -274,36 +261,33 @@ func (i *Initializer) RestoreOVSBridge() {
274261
}
275262
klog.Infof("Restoring bridge config to uplink...")
276263
uplinkNetConfig := i.nodeConfig.UplinkNetConfig
277-
uplink := ""
264+
uplinkName := ""
265+
bridgedUplinkName := ""
278266
if uplinkNetConfig != nil {
279-
uplink = uplinkNetConfig.Name
267+
uplinkName = uplinkNetConfig.Name
268+
bridgedUplinkName = util.GetBridgedUplinkName(uplinkName)
280269
}
270+
brName := i.ovsBridge
281271

282-
brName := i.ovsBridgeClient.GetBridgeName()
283-
brLink, err := netlink.LinkByName(brName)
272+
uplinkIPs, err := getTransportIPNetDeviceByNameWithExcludedList(uplinkName, nil)
284273
if err != nil {
285-
klog.Warningf("OVS bridge local port not found: %+v", err)
274+
klog.ErrorS(err, "Failed to get uplink IPs")
286275
}
287-
288-
if uplink != "" {
289-
if err := util.DeleteOVSPort(brName, uplink); err != nil {
290-
klog.ErrorS(err, "Removing uplink port from bridge failed", "uplink", uplink, "bridge", brName)
276+
if uplinkName != "" {
277+
if err := util.DeleteOVSPort(brName, uplinkName); err != nil {
278+
klog.ErrorS(err, "Delete OVS port failed", "port", uplinkName)
291279
}
292-
if err := util.ConfigureLinkAddresses(uplinkNetConfig.Index, []*net.IPNet{uplinkNetConfig.IP}); err != nil {
293-
klog.ErrorS(err, "Configure IP to uplink failed", "uplink", uplink)
280+
if err := util.DeleteOVSPort(brName, bridgedUplinkName); err != nil {
281+
klog.ErrorS(err, "Delete OVS port failed", "port", bridgedUplinkName)
294282
}
295-
}
296-
if brLink != nil {
297-
if err := util.ConfigureLinkAddresses(brLink.Attrs().Index, nil); err != nil {
298-
klog.ErrorS(err, "Remove IP from bridge interface failed", "interface", brName)
283+
if err := util.ChangeAdapterName(bridgedUplinkName, uplinkName, true); err != nil {
284+
klog.ErrorS(err, "Restore uplink name failed", "uplink", bridgedUplinkName)
299285
}
300-
if err := netlink.LinkSetDown(brLink); err != nil {
301-
klog.ErrorS(err, "Disable bridge interface failed", "interface", brName)
286+
if err := util.ConfigureLinkAddresses(uplinkNetConfig.Index, uplinkIPs); err != nil {
287+
klog.ErrorS(err, "Configure IP to uplink failed", "uplink", uplinkName)
302288
}
303-
}
304-
if uplink != "" {
305-
if err := i.restoreHostRoutesToInterface(uplink); err != nil {
306-
klog.ErrorS(err, "Configure route to uplink interface failed", "interface", uplink)
289+
if err := i.restoreHostRoutesToInterface(uplinkName); err != nil {
290+
klog.ErrorS(err, "Configure route to uplink interface failed", "uplink", uplinkName)
307291
}
308292
}
309293
klog.Infof("Finished to restore bridge config to uplink...")
@@ -312,3 +296,32 @@ func (i *Initializer) RestoreOVSBridge() {
312296
func (i *Initializer) setInterfaceMTU(iface string, mtu int) error {
313297
return i.ovsBridgeClient.SetInterfaceMTU(iface, mtu)
314298
}
299+
300+
func getTransportIPNetDeviceByNameWithExcludedList(interfaceName string, excludedIPs []*net.IPNet) ([]*net.IPNet, error) {
301+
IPs := []*net.IPNet{}
302+
_, _, adapter, err := getTransportIPNetDeviceByName(interfaceName, "")
303+
if err != nil {
304+
return nil, err
305+
}
306+
addrs, _ := adapter.Addrs()
307+
for _, addr := range addrs {
308+
if ip, ipNet, err := net.ParseCIDR(addr.String()); err != nil {
309+
klog.Warningf("Unable to parse addr %+v, err=%+v", addr, err)
310+
} else if !ip.IsLinkLocalUnicast() {
311+
ipNet.IP = ip
312+
ipNetString := ipNet.String()
313+
isExcludedIP := false
314+
for _, excludedIP := range excludedIPs {
315+
if ipNetString == excludedIP.String() {
316+
isExcludedIP = true
317+
break
318+
}
319+
}
320+
if !isExcludedIP {
321+
IPs = append(IPs, ipNet)
322+
}
323+
}
324+
}
325+
klog.InfoS("Found IPs on interface", "IPs", IPs, "interface", interfaceName)
326+
return IPs, nil
327+
}

pkg/agent/agent_windows.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ func (i *Initializer) prepareOVSBridge() error {
150150
externalIDs := map[string]interface{}{
151151
interfacestore.AntreaInterfaceTypeKey: interfacestore.AntreaHost,
152152
}
153-
if _, err = i.ovsBridgeClient.CreateInternalPort(brName, config.AutoAssignedOFPort, externalIDs); err != nil {
153+
if _, err = i.ovsBridgeClient.CreateInternalPort(brName, config.AutoAssignedOFPort, "", externalIDs); err != nil {
154154
return err
155155
}
156156
}
@@ -165,7 +165,7 @@ func (i *Initializer) prepareOVSBridge() error {
165165
return nil
166166
}
167167
// Create uplink port.
168-
freePort, err := i.getFreeOFPort(config.UplinkOFPort)
168+
freePort, err := i.getFreeOFPort(config.UplinkOFPort, nil)
169169
if err != nil {
170170
klog.ErrorS(err, "Failed to find a free port on OVS")
171171
return err

pkg/agent/cniserver/pod_configuration.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ func (pc *podConfigurator) createOVSPort(ovsPortName string, ovsAttachInfo map[s
271271
var err error
272272
switch pc.ifConfigurator.getOVSInterfaceType(ovsPortName) {
273273
case internalOVSInterfaceType:
274-
portUUID, err = pc.ovsBridgeClient.CreateInternalPort(ovsPortName, 0, ovsAttachInfo)
274+
portUUID, err = pc.ovsBridgeClient.CreateInternalPort(ovsPortName, 0, "", ovsAttachInfo)
275275
default:
276276
if vlanID == 0 {
277277
portUUID, err = pc.ovsBridgeClient.CreatePort(ovsPortName, ovsPortName, ovsAttachInfo)

pkg/agent/controller/trafficcontrol/controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,7 @@ func ParseTrafficControlInterfaceConfig(portData *ovsconfig.OVSPortData, portCon
585585
// createOVSInternalPort creates an OVS internal port on OVS and corresponding interface on host. Note that, host interface
586586
// might not be available immediately after creating OVS internal port.
587587
func (c *Controller) createOVSInternalPort(portName string) (string, error) {
588-
portUUID, err := c.ovsBridgeClient.CreateInternalPort(portName, 0, trafficControlPortExternalIDs)
588+
portUUID, err := c.ovsBridgeClient.CreateInternalPort(portName, 0, "", trafficControlPortExternalIDs)
589589
if err != nil {
590590
return "", err
591591
}

pkg/agent/util/net.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ const (
3838

3939
FamilyIPv4 uint8 = 4
4040
FamilyIPv6 uint8 = 6
41+
42+
BridgedUplinkPrefix = "b-"
4143
)
4244

4345
func generateInterfaceName(key string, name string, useHead bool) string {
@@ -378,3 +380,8 @@ func PortToUint16(port int) uint16 {
378380
klog.Errorf("Port value %d out-of-bounds", port)
379381
return 0
380382
}
383+
384+
// GetBridgedUplinkName generates the uplink interface name after bridged to OVS
385+
func GetBridgedUplinkName(name string) string {
386+
return BridgedUplinkPrefix + name
387+
}

pkg/agent/util/net_linux.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,3 +237,19 @@ func DeleteOVSPort(brName, portName string) error {
237237
cmd := exec.Command("ovs-vsctl", "--if-exists", "del-port", brName, portName)
238238
return cmd.Run()
239239
}
240+
241+
// ChangeAdapterName changes adapter name.
242+
func ChangeAdapterName(adapterName string, adapterNewName string, isUp bool) error {
243+
klog.InfoS("Change adapter name", "oldName", adapterName, "newName", adapterNewName)
244+
link, err := netlink.LinkByName(adapterName)
245+
if err != nil {
246+
return err
247+
}
248+
if isUp {
249+
defer netlink.LinkSetUp(link)
250+
}
251+
if err := netlink.LinkSetDown(link); err != nil {
252+
return err
253+
}
254+
return netlink.LinkSetName(link, adapterNewName)
255+
}

pkg/ovs/ovsconfig/interfaces.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ type OVSBridgeClient interface {
3939
SetInterfaceOptions(name string, options map[string]interface{}) Error
4040
CreatePort(name, ifDev string, externalIDs map[string]interface{}) (string, Error)
4141
CreateAccessPort(name, ifDev string, externalIDs map[string]interface{}, vlanID uint16) (string, Error)
42-
CreateInternalPort(name string, ofPortRequest int32, externalIDs map[string]interface{}) (string, Error)
42+
CreateInternalPort(name string, ofPortRequest int32, mac string, externalIDs map[string]interface{}) (string, Error)
4343
CreateTunnelPort(name string, tunnelType TunnelType, ofPortRequest int32) (string, Error)
4444
CreateTunnelPortExt(name string, tunnelType TunnelType, ofPortRequest int32, csum bool, localIP string, remoteIP string, remoteName string, psk string, extraOptions, externalIDs map[string]interface{}) (string, Error)
4545
CreateUplinkPort(name string, ofPortRequest int32, externalIDs map[string]interface{}) (string, Error)

0 commit comments

Comments
 (0)