Skip to content

Commit 35afabf

Browse files
committed
Restore NO_FLOOD to OVS ports after reconnecting the OVS bridge
The NO_FLOOD configuration is lost when the OVS daemon is restarted. Currently, the only way to recover this configuration is by restarting the agent. This pull request adds logic to recover the configuration when receiving OVS reconnection events. Signed-off-by: Xu Liu <xliu2@vmware.com>
1 parent d5dd02e commit 35afabf

5 files changed

Lines changed: 69 additions & 8 deletions

File tree

pkg/agent/agent.go

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,6 @@ func (i *Initializer) initInterfaceStore() error {
287287
return intf
288288
}
289289
ifaceList := make([]*interfacestore.InterfaceConfig, 0, len(ovsPorts))
290-
ovsCtlClient := ovsctl.NewClient(i.ovsBridge)
291290
for index := range ovsPorts {
292291
port := &ovsPorts[index]
293292
ovsPort := &interfacestore.OVSPortConfig{
@@ -322,9 +321,8 @@ func (i *Initializer) initInterfaceStore() error {
322321
intf = cniserver.ParseOVSPortInterfaceConfig(port, ovsPort)
323322
case interfacestore.AntreaTrafficControl:
324323
intf = trafficcontrol.ParseTrafficControlInterfaceConfig(port, ovsPort)
325-
if err := ovsCtlClient.SetPortNoFlood(int(ovsPort.OFPort)); err != nil {
326-
klog.ErrorS(err, "Failed to set port with no-flood config", "PortName", port.Name)
327-
}
324+
case interfacestore.AntreaIPsec:
325+
intf = noderoute.ParseTunnelInterfaceConfig(port, ovsPort)
328326
default:
329327
klog.InfoS("Unknown Antrea interface type", "type", interfaceType)
330328
}
@@ -348,7 +346,11 @@ func (i *Initializer) initInterfaceStore() error {
348346
fallthrough
349347
case port.IFType == ovsconfig.STTTunnel:
350348
intf = parseTunnelInterfaceFunc(port, ovsPort)
351-
antreaIFType = interfacestore.AntreaTunnel
349+
if intf.Type == interfacestore.IPSecTunnelInterface {
350+
antreaIFType = interfacestore.AntreaIPsec
351+
} else {
352+
antreaIFType = interfacestore.AntreaTunnel
353+
}
352354
case port.Name == i.ovsBridge:
353355
intf = nil
354356
antreaIFType = interfacestore.AntreaHost
@@ -376,6 +378,23 @@ func (i *Initializer) initInterfaceStore() error {
376378
return nil
377379
}
378380

381+
func (i *Initializer) restorePortConfigs() error {
382+
ovsCtlClient := ovsctl.NewClient(i.ovsBridge)
383+
interfaces := i.ifaceStore.ListInterfaces()
384+
for _, intf := range interfaces {
385+
switch intf.Type {
386+
case interfacestore.IPSecTunnelInterface:
387+
fallthrough
388+
case interfacestore.TrafficControlInterface:
389+
if err := ovsCtlClient.SetPortNoFlood(int(intf.OFPort)); err != nil {
390+
return fmt.Errorf("failed to set port %s with no-flood: %w", intf.InterfaceName, err)
391+
}
392+
klog.InfoS("Set port no-flood successfully", "PortName", intf.InterfaceName)
393+
}
394+
}
395+
return nil
396+
}
397+
379398
// Initialize sets up agent initial configurations.
380399
func (i *Initializer) Initialize() error {
381400
klog.Info("Setting up node network")
@@ -394,6 +413,10 @@ func (i *Initializer) Initialize() error {
394413
return err
395414
}
396415

416+
if err := i.restorePortConfigs(); err != nil {
417+
return err
418+
}
419+
397420
if i.enableL7NetworkPolicy {
398421
// prepareL7NetworkPolicyInterfaces must be executed after setupOVSBridge since it requires interfaceStore.
399422
if err := i.prepareL7NetworkPolicyInterfaces(); err != nil {
@@ -568,11 +591,17 @@ func (i *Initializer) initOpenFlowPipeline() error {
568591
i.ofClient.ReplayFlows()
569592
klog.Info("Flow replay completed")
570593

594+
klog.InfoS("Restoring OF port configs to OVS bridge")
595+
if err := i.restorePortConfigs(); err != nil {
596+
klog.ErrorS(err, "Failed to restore OF port configs")
597+
} else {
598+
klog.InfoS("Port configs restoration completed")
599+
}
571600
// ofClient and ovsBridgeClient have their own mechanisms to restore connections with OVS, and it could
572601
// happen that ovsBridgeClient's connection is not ready when ofClient completes flow replay. We retry it
573602
// with a timeout that is longer time than ovsBridgeClient's maximum connecting retry interval (8 seconds)
574603
// to ensure the flag can be removed successfully.
575-
err := wait.PollImmediate(200*time.Millisecond, 10*time.Second, func() (done bool, err error) {
604+
err = wait.PollImmediate(200*time.Millisecond, 10*time.Second, func() (done bool, err error) {
576605
if err := i.FlowRestoreComplete(); err != nil {
577606
return false, nil
578607
}

pkg/agent/controller/noderoute/node_route_controller.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -677,8 +677,12 @@ func (c *Controller) createIPSecTunnelPort(nodeName string, nodeIP net.IP) (int3
677677
exists = false
678678
}
679679
}
680+
680681
if !exists {
681-
ovsExternalIDs := map[string]interface{}{ovsExternalIDNodeName: nodeName}
682+
ovsExternalIDs := map[string]interface{}{
683+
ovsExternalIDNodeName: nodeName,
684+
interfacestore.AntreaInterfaceTypeKey: interfacestore.AntreaIPsec,
685+
}
682686
portUUID, err := c.ovsBridgeClient.CreateTunnelPortExt(
683687
portName,
684688
c.networkConfig.TunnelType,
@@ -714,6 +718,7 @@ func (c *Controller) createIPSecTunnelPort(nodeName string, nodeIP net.IP) (int3
714718
// Let NodeRouteController retry at errors.
715719
return 0, fmt.Errorf("failed to get of_port of IPsec tunnel port for Node %s", nodeName)
716720
}
721+
717722
// Set the port with no-flood to reject ARP flood packets.
718723
if err := c.ovsCtlClient.SetPortNoFlood(int(ofPort)); err != nil {
719724
return 0, fmt.Errorf("failed to set port %s with no-flood config: %w", portName, err)

pkg/agent/interfacestore/interface_cache.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,15 @@ func (c *interfaceCache) GetInterface(interfaceKey string) (*InterfaceConfig, bo
123123
return iface.(*InterfaceConfig), found
124124
}
125125

126+
// ListInterfacesByType lists all interfaces from local cache.
127+
func (c *interfaceCache) ListInterfaces() []*InterfaceConfig {
128+
interfaceConfigs := make([]*InterfaceConfig, 0)
129+
for _, iface := range c.cache.List() {
130+
interfaceConfigs = append(interfaceConfigs, iface.(*InterfaceConfig))
131+
}
132+
return interfaceConfigs
133+
}
134+
126135
// GetInterfaceByName retrieves interface from local cache given the interface
127136
// name.
128137
func (c *interfaceCache) GetInterfaceByName(interfaceName string) (*InterfaceConfig, bool) {

pkg/agent/interfacestore/testing/mock_interfacestore.go

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/agent/interfacestore/types.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ const (
3535
TrafficControlInterface
3636
// ExternalEntityInterface is used to mark current interface is for ExternalEntity Endpoint
3737
ExternalEntityInterface
38+
// IPSecTunnelInterface is used to mark current interface is for IPSec tunnel port
39+
IPSecTunnelInterface
3840

3941
AntreaInterfaceTypeKey = "antrea-type"
4042
AntreaGateway = "gateway"
@@ -43,6 +45,7 @@ const (
4345
AntreaUplink = "uplink"
4446
AntreaHost = "host"
4547
AntreaTrafficControl = "traffic-control"
48+
AntreaIPsec = "ipsec-tunnel"
4649
AntreaUnset = ""
4750
)
4851

@@ -108,6 +111,7 @@ type InterfaceConfig struct {
108111
type InterfaceStore interface {
109112
Initialize(interfaces []*InterfaceConfig)
110113
AddInterface(interfaceConfig *InterfaceConfig)
114+
ListInterfaces() []*InterfaceConfig
111115
DeleteInterface(interfaceConfig *InterfaceConfig)
112116
GetInterface(interfaceKey string) (*InterfaceConfig, bool)
113117
GetInterfaceByName(interfaceName string) (*InterfaceConfig, bool)
@@ -162,7 +166,7 @@ func NewTunnelInterface(tunnelName string, tunnelType ovsconfig.TunnelType, dest
162166
// Node.
163167
func NewIPSecTunnelInterface(interfaceName string, tunnelType ovsconfig.TunnelType, nodeName string, nodeIP net.IP, psk, remoteName string, ovsPortConfig *OVSPortConfig) *InterfaceConfig {
164168
tunnelConfig := &TunnelInterfaceConfig{Type: tunnelType, NodeName: nodeName, RemoteIP: nodeIP, PSK: psk, RemoteName: remoteName}
165-
return &InterfaceConfig{InterfaceName: interfaceName, Type: TunnelInterface, TunnelInterfaceConfig: tunnelConfig, OVSPortConfig: ovsPortConfig}
169+
return &InterfaceConfig{InterfaceName: interfaceName, Type: IPSecTunnelInterface, TunnelInterfaceConfig: tunnelConfig, OVSPortConfig: ovsPortConfig}
166170
}
167171

168172
// NewUplinkInterface creates InterfaceConfig for the uplink interface.

0 commit comments

Comments
 (0)