Repository: antrea-io/antrea
Pull request #3138 (2021-12-14 11:38:55)

Remove unused OF tables and flows on Windows
On Windows Node:
  - Since all traffic from uplink interface is output to bridge
local interface directly instead of being resubmitted to
UplinkTable, flows on UplinkTables are no longer needed.
  - Since SNAT is performed on Windows host, flows in
SNATTable which are used to perform SNAT are no longer needed.

Another update is to add function CleanOFTableCache to reset
ofTableCache and this function is only used in integration tests.

Signed-off-by: Hongliang Liu <lhongliang@vmware.com>

codecov-commenter: # [Codecov](https://codecov.io/gh/antrea-io/antrea/pull/3138?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) Report
> Merging [#3138](https://codecov.io/gh/antrea-io/antrea/pull/3138?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (b3c7409) into [main](https://codecov.io/gh/antrea-io/antrea/commit/a5114e7667750d2c5586478d56b3e86676df997d?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (a5114e7) will **decrease** coverage by `9.07%`.
> The diff coverage is `10.00%`.

[![Impacted file tree graph](https://codecov.io/gh/antrea-io/antrea/pull/3138/graphs/tree.svg?width=650&height=150&src=pr&token=TjWaLL2GoC&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None)](https://codecov.io/gh/antrea-io/antrea/pull/3138?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None)

```diff
@@            Coverage Diff             @@
##             main    #3138      +/-   ##
==========================================
- Coverage   40.35%   31.28%   -9.08%     
==========================================
  Files         167      288     +121     
  Lines       20879    24041    +3162     
==========================================
- Hits         8426     7521     -905     
- Misses      11632    15393    +3761     
- Partials      821     1127     +306     
```

| Flag | Coverage Δ | |
|---|---|---|
| kind-e2e-tests | `31.28% <10.00%> (?)` | |
| unit-tests | `?` | |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/antrea-io/antrea/pull/3138?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) | Coverage Δ | |
|---|---|---|
| [pkg/agent/controller/egress/egress\_controller.go](https://codecov.io/gh/antrea-io/antrea/pull/3138/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2FnZW50L2NvbnRyb2xsZXIvZWdyZXNzL2VncmVzc19jb250cm9sbGVyLmdv) | `0.00% <0.00%> (-38.81%)` | :arrow_down: |
| [pkg/agent/openflow/pipeline.go](https://codecov.io/gh/antrea-io/antrea/pull/3138/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2FnZW50L29wZW5mbG93L3BpcGVsaW5lLmdv) | `49.79% <0.00%> (+28.57%)` | :arrow_up: |
| [pkg/agent/openflow/pipeline\_other.go](https://codecov.io/gh/antrea-io/antrea/pull/3138/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2FnZW50L29wZW5mbG93L3BpcGVsaW5lX290aGVyLmdv) | `2.22% <ø> (+2.22%)` | :arrow_up: |
| [pkg/agent/proxy/proxier.go](https://codecov.io/gh/antrea-io/antrea/pull/3138/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2FnZW50L3Byb3h5L3Byb3hpZXIuZ28=) | `48.60% <ø> (+6.78%)` | :arrow_up: |
| [pkg/agent/openflow/client.go](https://codecov.io/gh/antrea-io/antrea/pull/3138/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2FnZW50L29wZW5mbG93L2NsaWVudC5nbw==) | `39.95% <12.50%> (+16.32%)` | :arrow_up: |
| [pkg/util/sets/int32.go](https://codecov.io/gh/antrea-io/antrea/pull/3138/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL3V0aWwvc2V0cy9pbnQzMi5nbw==) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pkg/util/sets/string.go](https://codecov.io/gh/antrea-io/antrea/pull/3138/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL3V0aWwvc2V0cy9zdHJpbmcuZ28=) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pkg/agent/controller/egress/id\_allocator.go](https://codecov.io/gh/antrea-io/antrea/pull/3138/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2FnZW50L2NvbnRyb2xsZXIvZWdyZXNzL2lkX2FsbG9jYXRvci5nbw==) | `0.00% <0.00%> (-100.00%)` | :arrow_down: |
| [pkg/controller/networkpolicy/endpoint\_querier.go](https://codecov.io/gh/antrea-io/antrea/pull/3138/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2NvbnRyb2xsZXIvbmV0d29ya3BvbGljeS9lbmRwb2ludF9xdWVyaWVyLmdv) | `2.85% <0.00%> (-88.58%)` | :arrow_down: |
| [pkg/controller/egress/controller.go](https://codecov.io/gh/antrea-io/antrea/pull/3138/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2NvbnRyb2xsZXIvZWdyZXNzL2NvbnRyb2xsZXIuZ28=) | `0.00% <0.00%> (-88.45%)` | :arrow_down: |
| ... and [271 more](https://codecov.io/gh/antrea-io/antrea/pull/3138/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) | |

hongliangl: /test-all-features-conformance
/test-conformance
/test-e2e
/test-flexible-ipam-e2e
/test-ipv6-conformance
/test-ipv6-e2e
/test-ipv6-networkpolicy
/test-ipv6-only-conformance
/test-ipv6-only-e2e
/test-ipv6-only-networkpolicy
/test-multicluster-e2e
/test-networkpolicy
/test-windows-conformance
/test-windows-e2e
/test-windows-networkpolicy
/test-windows-proxyall-e2e
XinShuYang: /test-windows-e2e
hongliangl: /test-all-features-conformance
/test-conformance
/test-e2e
/test-flexible-ipam-e2e
/test-ipv6-conformance
/test-ipv6-e2e
/test-ipv6-networkpolicy
/test-ipv6-only-conformance
/test-ipv6-only-e2e
/test-ipv6-only-networkpolicy
/test-multicluster-e2e
/test-networkpolicy
/test-windows-conformance
/test-windows-e2e
/test-windows-networkpolicy
/test-windows-proxyall-e2e
hongliangl: /test-all-features-conformance
/test-conformance
/test-e2e
/test-flexible-ipam-e2e
/test-ipv6-conformance
/test-ipv6-e2e
/test-ipv6-networkpolicy
/test-ipv6-only-conformance
/test-ipv6-only-e2e
/test-ipv6-only-networkpolicy
/test-multicluster-e2e
/test-networkpolicy
/test-windows-conformance
/test-windows-e2e
/test-windows-networkpolicy
/test-windows-proxyall-e2e
hongliangl: /test-all-features-conformance
/test-conformance
/test-e2e
/test-flexible-ipam-e2e
/test-ipv6-conformance
/test-ipv6-e2e
/test-ipv6-networkpolicy
/test-ipv6-only-conformance
/test-ipv6-only-e2e
/test-ipv6-only-networkpolicy
/test-multicluster-e2e
/test-networkpolicy
/test-windows-conformance
/test-windows-e2e
/test-windows-networkpolicy
/test-windows-proxyall-e2e
hongliangl: /test-e2e to
hongliangl: /test-all-features-conformance
/test-conformance
/test-e2e
/test-flexible-ipam-e2e
/test-ipv6-conformance
/test-ipv6-e2e
/test-ipv6-networkpolicy
/test-ipv6-only-conformance
/test-ipv6-only-e2e
/test-ipv6-only-networkpolicy
/test-multicluster-e2e
/test-networkpolicy
/test-windows-conformance
/test-windows-e2e
/test-windows-networkpolicy
/test-windows-proxyall-e2e

hongliangl: /test-e2e
hongliangl: /test-windows-conformance
/test-windows-e2e
/test-windows-networkpolicy
/test-windows-proxyall-e2e
hongliangl: /test-integration
hongliangl: /test-e2e
hongliangl: /test-integration
hongliangl: /test-all-features-conformance
/test-conformance
/test-e2e
/test-flexible-ipam-e2e
/test-ipv6-conformance
/test-ipv6-e2e
/test-ipv6-networkpolicy
/test-ipv6-only-conformance
/test-ipv6-only-e2e
/test-ipv6-only-networkpolicy
/test-multicluster-e2e
/test-networkpolicy
/test-windows-conformance
/test-windows-e2e
/test-windows-networkpolicy
/test-windows-proxyall-e2e
hongliangl: /test-integration
/test-e2e
/test-windows-networkpolicy
/test-windows-proxyall-e2e
/test-networkpolicy

hongliangl: /test-integration
hongliangl: /test-e2e
/test-windows-networkpolicy
hongliangl: /test-e2e
hongliangl: /test-e2e
hongliangl: /test-e2e
hongliangl: /test-windows-networkpolicy
hongliangl: /test-e2e
hongliangl: @tnqn @wenyingd Do you have any suggestions about this PR? Thanks.
hongliangl: /test-all-features-conformance
/test-conformance
/test-e2e
/test-flexible-ipam-e2e
/test-ipv6-conformance
/test-ipv6-e2e
/test-ipv6-networkpolicy
/test-ipv6-only-conformance
/test-ipv6-only-e2e
/test-ipv6-only-networkpolicy
/test-multicluster-e2e
/test-networkpolicy
/test-windows-conformance
/test-windows-e2e
/test-windows-networkpolicy
/test-windows-proxyall-e2e
hongliangl: /test-all-features-conformance
hongliangl: /test-all-features-conformance
/test-conformance
/test-e2e
/test-flexible-ipam-e2e
/test-ipv6-conformance
/test-ipv6-e2e
/test-ipv6-networkpolicy
/test-ipv6-only-conformance
/test-ipv6-only-e2e
/test-ipv6-only-networkpolicy
/test-multicluster-e2e
/test-networkpolicy
/test-windows-conformance
/test-windows-e2e
/test-windows-networkpolicy
/test-windows-proxyall-e2e
hongliangl: @jianjuns @tnqn @wenyingd Do you have any more comments about this PR? Thanks.
hongliangl: /test-all-features-conformance
/test-conformance
/test-e2e
/test-flexible-ipam-e2e
/test-ipv6-conformance
/test-ipv6-e2e
/test-ipv6-networkpolicy
/test-ipv6-only-conformance
/test-ipv6-only-e2e
/test-ipv6-only-networkpolicy
/test-multicluster-e2e
/test-networkpolicy
/test-windows-conformance
/test-windows-e2e
/test-windows-networkpolicy
/test-windows-proxyall-e2e
hongliangl: > No further comment from me.

Thanks!
hongliangl: @tnqn @wenyingd Do you have any further comments? Thanks.
hongliangl: /test-windows-all
hongliangl: /test-ipv6-conformance
/test-ipv6-e2e
/test-ipv6-networkpolicy
/test-ipv6-only-conformance
/test-ipv6-only-e2e
/test-ipv6-only-networkpolicy
/test-flexible-ipam-e2e
hongliangl: /test-windows-proxyall-e2e
hongliangl: @tnqn Do you have any further comments? Thanks.
hongliangl: /test-windows-all

hongliangl: /test-all
/test-windows-all

Patch:
diff --git a/hack/windows/Helper.psm1 b/hack/windows/Helper.psm1
index 92ba4ec65..09d0b7f3d 100644
--- a/hack/windows/Helper.psm1
+++ b/hack/windows/Helper.psm1
@@ -163,7 +163,7 @@ function New-KubeProxyServiceInterface {
         Write-Host "Network adapter $INTERFACE_TO_ADD_SERVICE_IP exists, exit."
         return
     }
-    if (!(Get-VMSwitch -Name $hnsSwitchName -ErrorAction SilentlyContinue)) {
+    if (!(Get-VMSwitch -ComputerName $(hostname) -Name $hnsSwitchName -ErrorAction SilentlyContinue)) {
         Write-Host "Creating internal switch: $hnsSwitchName for kube-proxy"
         New-VMSwitch -name $hnsSwitchName -SwitchType Internal
     }
@@ -216,7 +216,7 @@ function Start-OVSServices {
     }
     # Try to cleanup ovsdb-server configurations if the antrea-hnsnetwork is not existing. Or ovs-vswitchd service
     # will can not get started.
-    if (!(Get-VMswitch -Name "antrea-hnsnetwork" -SwitchType External -ErrorAction SilentlyContinue)) {
+    if (!(Get-VMswitch -ComputerName $(hostname) -Name "antrea-hnsnetwork" -SwitchType External -ErrorAction SilentlyContinue)) {
         & ovs-vsctl.exe --no-wait --if-exists del-br br-int
         if ($LASTEXITCODE) {
             return $false
diff --git a/hack/windows/Prepare-ServiceInterface.ps1 b/hack/windows/Prepare-ServiceInterface.ps1
index 33159867e..c962c2cb8 100644
--- a/hack/windows/Prepare-ServiceInterface.ps1
+++ b/hack/windows/Prepare-ServiceInterface.ps1
@@ -25,7 +25,7 @@ if (Get-NetAdapter -InterfaceAlias $INTERFACE_TO_ADD_SERVICE_IP -ErrorAction Sil
     return
 }
 [Environment]::SetEnvironmentVariable("INTERFACE_TO_ADD_SERVICE_IP", $INTERFACE_TO_ADD_SERVICE_IP, [System.EnvironmentVariableTarget]::Machine)
-$hnsSwitchName = $(Get-VMSwitch -SwitchType Internal).Name
+$hnsSwitchName = $(Get-VMSwitch -ComputerName $(hostname) -SwitchType Internal).Name
 Add-VMNetworkAdapter -ManagementOS -Name $InterfaceAlias -SwitchName $hnsSwitchName
 Set-NetIPInterface -ifAlias $INTERFACE_TO_ADD_SERVICE_IP -Forwarding Enabled
 
diff --git a/pkg/agent/openflow/client.go b/pkg/agent/openflow/client.go
index 09627844d..33b11e48b 100644
--- a/pkg/agent/openflow/client.go
+++ b/pkg/agent/openflow/client.go
@@ -30,6 +30,7 @@ import (
 	"antrea.io/antrea/pkg/agent/util"
 	binding "antrea.io/antrea/pkg/ovs/openflow"
 	utilip "antrea.io/antrea/pkg/util/ip"
+	"antrea.io/antrea/pkg/util/runtime"
 	"antrea.io/antrea/third_party/proxy"
 )
 
@@ -113,13 +114,6 @@ type Client interface {
 	InstallServiceFlows(groupID binding.GroupIDType, svcIP net.IP, svcPort uint16, protocol binding.Protocol, affinityTimeout uint16, nodeLocalExternal bool, svcType v1.ServiceType) error
 	// UninstallServiceFlows removes flows installed by InstallServiceFlows.
 	UninstallServiceFlows(svcIP net.IP, svcPort uint16, protocol binding.Protocol) error
-	// InstallLoadBalancerServiceFromOutsideFlows installs flows for LoadBalancer Service traffic from outside node.
-	// The traffic is received from uplink port and will be forwarded to gateway by the installed flows. And then
-	// kube-proxy will handle the traffic.
-	// This function is only used for Windows platform.
-	InstallLoadBalancerServiceFromOutsideFlows(svcIP net.IP, svcPort uint16, protocol binding.Protocol) error
-	// UninstallLoadBalancerServiceFromOutsideFlows removes flows installed by InstallLoadBalancerServiceFromOutsideFlows.
-	UninstallLoadBalancerServiceFromOutsideFlows(svcIP net.IP, svcPort uint16, protocol binding.Protocol) error
 
 	// GetFlowTableStatus should return an array of flow table status, all existing flow tables should be included in the list.
 	GetFlowTableStatus() []binding.TableStatus
@@ -146,9 +140,7 @@ type Client interface {
 	// are removed from PolicyRule.From, else from PolicyRule.To.
 	DeletePolicyRuleAddress(ruleID uint32, addrType types.AddressType, addresses []types.Address, priority *uint16) error
 
-	// InstallBridgeUplinkFlows installs Openflow flows between bridge local port and uplink port to support
-	// host networking.
-	// This function is only used for Windows platform.
+	// InstallBridgeUplinkFlows installs Openflow flows between bridge local port and uplink port to support host networking.
 	InstallBridgeUplinkFlows() error
 
 	// InstallExternalFlows sets up flows to enable Pods to communicate to
@@ -160,8 +152,7 @@ type Client interface {
 
 	// InstallSNATMarkFlows installs flows for a local SNAT IP. On Linux, a
 	// single flow is added to mark the packets tunnelled from remote Nodes
-	// that should be SNAT'd with the SNAT IP. On Windows, an extra flow is
-	// added to perform SNAT for the marked packets with the SNAT IP.
+	// that should be SNAT'd with the SNAT IP.
 	InstallSNATMarkFlows(snatIP net.IP, mark uint32) error
 
 	// UninstallSNATMarkFlows removes the flows installed to set the packet
@@ -850,11 +841,11 @@ func (c *client) InstallExternalFlows(exceptCIDRs []net.IPNet) error {
 }
 
 func (c *client) InstallSNATMarkFlows(snatIP net.IP, mark uint32) error {
-	flows := c.snatMarkFlows(snatIP, mark)
+	flow := c.snatIPFromTunnelFlow(snatIP, mark)
 	cacheKey := fmt.Sprintf("s%x", mark)
 	c.replayMutex.RLock()
 	defer c.replayMutex.RUnlock()
-	return c.addFlows(c.snatFlowCache, cacheKey, flows)
+	return c.addFlows(c.snatFlowCache, cacheKey, []binding.Flow{flow})
 }
 
 func (c *client) UninstallSNATMarkFlows(mark uint32) error {
@@ -1247,3 +1238,19 @@ func (c *client) SendIGMPQueryPacketOut(
 	packetOutObj := packetOutBuilder.Done()
 	return c.bridge.SendPacketOut(packetOutObj)
 }
+
+func (c *client) InstallBridgeUplinkFlows() error {
+	if runtime.IsWindowsPlatform() || c.connectUplinkToBridge {
+		podCIDRMap := make(map[binding.Protocol]net.IPNet)
+		if c.nodeConfig.PodIPv4CIDR != nil {
+			podCIDRMap[binding.ProtocolIP] = *c.nodeConfig.PodIPv4CIDR
+		}
+		//TODO: support IPv6
+		flows := c.hostBridgeUplinkFlows(podCIDRMap, cookie.Default)
+		if err := c.ofEntryOperations.AddAll(flows); err != nil {
+			return err
+		}
+		c.hostNetworkingFlows = flows
+	}
+	return nil
+}
diff --git a/pkg/agent/openflow/client_other.go b/pkg/agent/openflow/client_other.go
deleted file mode 100644
index 3e5562d50..000000000
--- a/pkg/agent/openflow/client_other.go
+++ /dev/null
@@ -1,50 +0,0 @@
-//go:build !windows
-// +build !windows
-
-// package openflow is needed by antctl which is compiled for macOS too.
-
-// Copyright 2021 Antrea Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package openflow
-
-import (
-	"net"
-
-	"antrea.io/antrea/pkg/agent/openflow/cookie"
-	binding "antrea.io/antrea/pkg/ovs/openflow"
-)
-
-func (c *client) InstallBridgeUplinkFlows() error {
-	if !c.connectUplinkToBridge {
-		return nil
-	}
-	// TODO(gran): support IPv6
-	if c.nodeConfig.PodIPv4CIDR != nil {
-		flows := c.hostBridgeUplinkFlows(*c.nodeConfig.PodIPv4CIDR, cookie.Default)
-		if err := c.ofEntryOperations.AddAll(flows); err != nil {
-			return err
-		}
-		c.hostNetworkingFlows = flows
-	}
-	return nil
-}
-
-func (c *client) InstallLoadBalancerServiceFromOutsideFlows(svcIP net.IP, svcPort uint16, protocol binding.Protocol) error {
-	return nil
-}
-
-func (c *client) UninstallLoadBalancerServiceFromOutsideFlows(svcIP net.IP, svcPort uint16, protocol binding.Protocol) error {
-	return nil
-}
diff --git a/pkg/agent/openflow/client_windows.go b/pkg/agent/openflow/client_windows.go
deleted file mode 100644
index bfe651df2..000000000
--- a/pkg/agent/openflow/client_windows.go
+++ /dev/null
@@ -1,53 +0,0 @@
-//go:build windows
-// +build windows
-
-// package openflow is needed by antctl which is compiled for macOS too.
-
-// Copyright 2021 Antrea Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package openflow
-
-import (
-	"fmt"
-	"net"
-
-	"antrea.io/antrea/pkg/agent/openflow/cookie"
-	binding "antrea.io/antrea/pkg/ovs/openflow"
-)
-
-func (c *client) InstallBridgeUplinkFlows() error {
-	flows := c.hostBridgeUplinkFlows(*c.nodeConfig.PodIPv4CIDR, cookie.Default)
-	if err := c.ofEntryOperations.AddAll(flows); err != nil {
-		return err
-	}
-	c.hostNetworkingFlows = flows
-	return nil
-}
-
-func (c *client) InstallLoadBalancerServiceFromOutsideFlows(svcIP net.IP, svcPort uint16, protocol binding.Protocol) error {
-	c.replayMutex.RLock()
-	defer c.replayMutex.RUnlock()
-	var flows []binding.Flow
-	flows = append(flows, c.loadBalancerServiceFromOutsideFlow(svcIP, svcPort, protocol))
-	cacheKey := fmt.Sprintf("L%s%s%x", svcIP, protocol, svcPort)
-	return c.addFlows(c.serviceFlowCache, cacheKey, flows)
-}
-
-func (c *client) UninstallLoadBalancerServiceFromOutsideFlows(svcIP net.IP, svcPort uint16, protocol binding.Protocol) error {
-	c.replayMutex.RLock()
-	defer c.replayMutex.RUnlock()
-	cacheKey := fmt.Sprintf("L%s%s%x", svcIP, protocol, svcPort)
-	return c.deleteFlows(c.serviceFlowCache, cacheKey)
-}
diff --git a/pkg/agent/openflow/pipeline.go b/pkg/agent/openflow/pipeline.go
index 784799b54..04c7feb29 100644
--- a/pkg/agent/openflow/pipeline.go
+++ b/pkg/agent/openflow/pipeline.go
@@ -42,7 +42,6 @@ import (
 
 var (
 	ClassifierTable              = binding.NewOFTable(0, "Classification")
-	UplinkTable                  = binding.NewOFTable(5, "Uplink")
 	SpoofGuardTable              = binding.NewOFTable(10, "SpoofGuard")
 	arpResponderTable            = binding.NewOFTable(20, "ARPResponder")
 	IPv6Table                    = binding.NewOFTable(21, "IPv6")
@@ -181,6 +180,23 @@ func GetTableList() []binding.Table {
 	return tables
 }
 
+// CleanOFTableCache is used to reset ofTableCache and only used in integration tests. When all integration tests about
+// openflow run in batch, unexpected flows could be installed on OVS due to stale ofTableCache, which may cause some tests
+// to fail. For example, for TestFuncA, SNATTable is needed; for TestFuncB, SNATTable is not needed. If TestFuncB is run
+// after TestFuncA, since ofTableCache (SNATTable is added by TestFuncA) is not reset, default flow of SNATTable will also
+// be realized on OVS when running TestFuncB (see "func (c *client) defaultFlows() (flows []binding.Flow)"). Note that,
+// the unexpected flows are not included in the map tableCache of OFBridge defined in pkg/ovs/openflow/ofctrl_bridge.go,
+// because the bridge will be destroyed after every test. For some tests, function checkOVSFlowMetrics (defined in
+// test/integration/agent/openflow_test.go) is used to check the flow number of every installed table. The expected table
+// list is read from the map tableCache of OFBridge, but the actual table list is dumped from OVS bridge (including the
+// unexpected flow). They are different, and as a result, TestFuncB will fail.
+func CleanOFTableCache() {
+	objs := ofTableCache.List()
+	for i := 0; i < len(objs); i++ {
+		ofTableCache.Delete(objs[i])
+	}
+}
+
 func GetAntreaPolicyEgressTables() []binding.Table {
 	return []binding.Table{
 		AntreaPolicyEgressRuleTable,
@@ -2225,20 +2241,6 @@ func (c *client) snatRuleFlow(ofPort uint32, snatIP net.IP, snatMark uint32, loc
 		Done()
 }
 
-// loadBalancerServiceFromOutsideFlow generates the flow to forward LoadBalancer service traffic from outside node
-// to gateway. kube-proxy will then handle the traffic.
-// This flow is for Windows Node only.
-func (c *client) loadBalancerServiceFromOutsideFlow(svcIP net.IP, svcPort uint16, protocol binding.Protocol) binding.Flow {
-	return UplinkTable.BuildFlow(priorityHigh).
-		MatchProtocol(protocol).
-		MatchDstPort(svcPort, nil).
-		MatchRegMark(FromUplinkRegMark).
-		MatchDstIP(svcIP).
-		Action().Output(config.HostGatewayOFPort).
-		Cookie(c.cookieAllocator.Request(cookie.Service).Raw()).
-		Done()
-}
-
 // serviceClassifierFlows generate the flows to match the first packet of Service NodePort and set a bit of a register
 // to mark the Service type as NodePort.
 func (c *client) serviceClassifierFlows(nodePortAddresses []net.IP, ipProtocol binding.Protocol) []binding.Flow {
@@ -2584,13 +2586,9 @@ func (c *client) generatePipeline() {
 	} else {
 		c.createOFTable(DNATTable, c.egressEntryTable, binding.TableMissActionNext)
 	}
-	// The default SNAT is implemented with OVS on Windows.
-	if c.enableEgress || runtime.IsWindowsPlatform() {
+	if c.enableEgress {
 		c.createOFTable(SNATTable, L2ForwardingCalcTable.GetID(), binding.TableMissActionNext)
 	}
-	if runtime.IsWindowsPlatform() || c.connectUplinkToBridge {
-		c.createOFTable(UplinkTable, SpoofGuardTable.GetID(), binding.TableMissActionNone)
-	}
 	if c.enableAntreaPolicy {
 		c.createOFTable(AntreaPolicyEgressRuleTable, EgressRuleTable.GetID(), binding.TableMissActionNext)
 		c.createOFTable(AntreaPolicyIngressRuleTable, IngressRuleTable.GetID(), binding.TableMissActionNext)
diff --git a/pkg/agent/openflow/pipeline_other.go b/pkg/agent/openflow/pipeline_other.go
index 379428004..4c1f72bde 100644
--- a/pkg/agent/openflow/pipeline_other.go
+++ b/pkg/agent/openflow/pipeline_other.go
@@ -27,14 +27,10 @@ import (
 	binding "antrea.io/antrea/pkg/ovs/openflow"
 )
 
-func (c *client) snatMarkFlows(snatIP net.IP, mark uint32) []binding.Flow {
-	return []binding.Flow{c.snatIPFromTunnelFlow(snatIP, mark)}
-}
-
 // hostBridgeUplinkFlows generates the flows that forward traffic between the
 // bridge local port and the uplink port to support the host traffic.
 // TODO(gran): sync latest changes from pipeline_windows.go
-func (c *client) hostBridgeUplinkFlows(localSubnet net.IPNet, category cookie.Category) (flows []binding.Flow) {
+func (c *client) hostBridgeUplinkFlows(localSubnetMap map[binding.Protocol]net.IPNet, category cookie.Category) (flows []binding.Flow) {
 	flows = []binding.Flow{
 		ClassifierTable.BuildFlow(priorityNormal).
 			MatchInPort(config.UplinkOFPort).
diff --git a/pkg/agent/openflow/pipeline_windows.go b/pkg/agent/openflow/pipeline_windows.go
index ccec12503..a3df5f328 100644
--- a/pkg/agent/openflow/pipeline_windows.go
+++ b/pkg/agent/openflow/pipeline_windows.go
@@ -22,65 +22,13 @@ import (
 
 	"antrea.io/antrea/pkg/agent/config"
 	"antrea.io/antrea/pkg/agent/openflow/cookie"
-	"antrea.io/antrea/pkg/agent/types"
 	binding "antrea.io/antrea/pkg/ovs/openflow"
 )
 
-const (
-	// ctZoneSNAT is only used on Windows and only when AntreaProxy is enabled.
-	// When a Pod access a ClusterIP Service, and the IP of the selected endpoint
-	// is not in "cluster-cidr". The request packets need to be SNAT'd(set src IP to local Node IP)
-	// after have been DNAT'd(set dst IP to endpoint IP).
-	// For example, the endpoint Pod may run in hostNetwork mode and the IP of the endpoint
-	// will be the current Node IP.
-	// We need to use a different ct_zone to track the SNAT'd connection because OVS
-	// does not support doing both DNAT and SNAT in the same ct_zone.
-	//
-	// An example of the connection is a Pod accesses kubernetes API service:
-	// Pod --> DNAT(CtZone) --> SNAT(ctZoneSNAT) --> Endpoint(API server NodeIP)
-	// Pod <-- unDNAT(CtZone) <-- unSNAT(ctZoneSNAT) <-- Endpoint(API server NodeIP)
-	ctZoneSNAT = 0xffdc
-)
-
-var (
-	// snatCTMark indicates SNAT is performed for packets of the connection.
-	snatCTMark = binding.NewCTMark(0x40, 0, 31)
-)
-
-func (c *client) snatMarkFlows(snatIP net.IP, mark uint32) []binding.Flow {
-	snatIPRange := &binding.IPRange{StartIP: snatIP, EndIP: snatIP}
-	nextTable := ConntrackCommitTable.GetNext()
-	flows := []binding.Flow{
-		c.snatIPFromTunnelFlow(snatIP, mark),
-		ConntrackCommitTable.BuildFlow(priorityNormal).
-			MatchProtocol(binding.ProtocolIP).
-			MatchCTStateNew(true).MatchCTStateTrk(true).MatchCTStateDNAT(false).
-			MatchPktMark(mark, &types.SNATIPMarkMask).
-			Action().CT(true, nextTable, CtZone).
-			SNAT(snatIPRange, nil).
-			LoadToCtMark(snatCTMark).CTDone().
-			Cookie(c.cookieAllocator.Request(cookie.SNAT).Raw()).
-			Done(),
-	}
-
-	if c.enableProxy {
-		flows = append(flows, ConntrackCommitTable.BuildFlow(priorityNormal).
-			MatchProtocol(binding.ProtocolIP).
-			MatchCTStateNew(true).MatchCTStateTrk(true).MatchCTStateDNAT(true).
-			MatchPktMark(mark, &types.SNATIPMarkMask).
-			Action().CT(true, nextTable, ctZoneSNAT).
-			SNAT(snatIPRange, nil).
-			LoadToCtMark(snatCTMark).CTDone().
-			Cookie(c.cookieAllocator.Request(cookie.SNAT).Raw()).
-			Done())
-	}
-	return flows
-}
-
 // hostBridgeUplinkFlows generates the flows that forward traffic between the
 // bridge local port and the uplink port to support the host traffic with
 // outside.
-func (c *client) hostBridgeUplinkFlows(localSubnet net.IPNet, category cookie.Category) (flows []binding.Flow) {
+func (c *client) hostBridgeUplinkFlows(localSubnetMap map[binding.Protocol]net.IPNet, category cookie.Category) (flows []binding.Flow) {
 	flows = []binding.Flow{
 		ClassifierTable.BuildFlow(priorityNormal).
 			MatchInPort(config.UplinkOFPort).
@@ -96,14 +44,17 @@ func (c *client) hostBridgeUplinkFlows(localSubnet net.IPNet, category cookie.Ca
 	if c.networkConfig.TrafficEncapMode.SupportsNoEncap() {
 		// If NoEncap is enabled, the reply packets from remote Pod can be forwarded to local Pod directly.
 		// by explicitly resubmitting them to ServiceHairpinTable and marking "macRewriteMark" at same time.
-		flows = append(flows, ClassifierTable.BuildFlow(priorityHigh).MatchProtocol(binding.ProtocolIP).
-			MatchInPort(config.UplinkOFPort).
-			MatchDstIPNet(localSubnet).
-			Action().LoadRegMark(FromUplinkRegMark).
-			Action().LoadRegMark(RewriteMACRegMark).
-			Action().GotoTable(ServiceHairpinTable.GetID()).
-			Cookie(c.cookieAllocator.Request(category).Raw()).
-			Done())
+		for ipProtocol, localSubnet := range localSubnetMap {
+			flows = append(flows, ClassifierTable.BuildFlow(priorityHigh).
+				MatchProtocol(ipProtocol).
+				MatchInPort(config.UplinkOFPort).
+				MatchDstIPNet(localSubnet).
+				Action().LoadRegMark(FromUplinkRegMark).
+				Action().LoadRegMark(RewriteMACRegMark).
+				Action().GotoTable(ServiceHairpinTable.GetID()).
+				Cookie(c.cookieAllocator.Request(category).Raw()).
+				Done())
+		}
 	}
 	return flows
 }
diff --git a/pkg/agent/proxy/proxier.go b/pkg/agent/proxy/proxier.go
index 571abc29c..840221866 100644
--- a/pkg/agent/proxy/proxier.go
+++ b/pkg/agent/proxy/proxier.go
@@ -314,9 +314,6 @@ func (p *proxier) installLoadBalancerService(groupID binding.GroupIDType, loadBa
 			if err := p.ofClient.InstallServiceFlows(groupID, net.ParseIP(ingress), svcPort, protocol, affinityTimeout, nodeLocalExternal, corev1.ServiceTypeLoadBalancer); err != nil {
 				return fmt.Errorf("failed to install Service LoadBalancer load balancing flows: %w", err)
 			}
-			if err := p.ofClient.InstallLoadBalancerServiceFromOutsideFlows(net.ParseIP(ingress), svcPort, protocol); err != nil {
-				return fmt.Errorf("failed to install Service LoadBalancer flows: %w", err)
-			}
 		}
 	}
 	if p.proxyAll {
@@ -334,9 +331,6 @@ func (p *proxier) uninstallLoadBalancerService(loadBalancerIPStrings []string, s
 			if err := p.ofClient.UninstallServiceFlows(net.ParseIP(ingress), svcPort, protocol); err != nil {
 				return fmt.Errorf("failed to remove Service LoadBalancer load balancing flows: %w", err)
 			}
-			if err := p.ofClient.UninstallLoadBalancerServiceFromOutsideFlows(net.ParseIP(ingress), svcPort, protocol); err != nil {
-				return fmt.Errorf("failed to remove Service LoadBalancer flows: %w", err)
-			}
 		}
 	}
 	if p.proxyAll {


Test patch:
diff --git a/pkg/agent/openflow/testing/mock_openflow.go b/pkg/agent/openflow/testing/mock_openflow.go
index ab49be308..5ca27c7bc 100644
--- a/pkg/agent/openflow/testing/mock_openflow.go
+++ b/pkg/agent/openflow/testing/mock_openflow.go
@@ -1,4 +1,4 @@
-// Copyright 2021 Antrea Authors
+// Copyright 2022 Antrea Authors
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -365,20 +365,6 @@ func (mr *MockClientMockRecorder) InstallGatewayFlows() *gomock.Call {
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InstallGatewayFlows", reflect.TypeOf((*MockClient)(nil).InstallGatewayFlows))
 }
 
-// InstallLoadBalancerServiceFromOutsideFlows mocks base method
-func (m *MockClient) InstallLoadBalancerServiceFromOutsideFlows(arg0 net.IP, arg1 uint16, arg2 openflow.Protocol) error {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "InstallLoadBalancerServiceFromOutsideFlows", arg0, arg1, arg2)
-	ret0, _ := ret[0].(error)
-	return ret0
-}
-
-// InstallLoadBalancerServiceFromOutsideFlows indicates an expected call of InstallLoadBalancerServiceFromOutsideFlows
-func (mr *MockClientMockRecorder) InstallLoadBalancerServiceFromOutsideFlows(arg0, arg1, arg2 interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InstallLoadBalancerServiceFromOutsideFlows", reflect.TypeOf((*MockClient)(nil).InstallLoadBalancerServiceFromOutsideFlows), arg0, arg1, arg2)
-}
-
 // InstallMulticastFlow mocks base method
 func (m *MockClient) InstallMulticastFlow(arg0 net.IP) error {
 	m.ctrl.T.Helper()
@@ -709,20 +695,6 @@ func (mr *MockClientMockRecorder) UninstallEndpointFlows(arg0, arg1 interface{})
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UninstallEndpointFlows", reflect.TypeOf((*MockClient)(nil).UninstallEndpointFlows), arg0, arg1)
 }
 
-// UninstallLoadBalancerServiceFromOutsideFlows mocks base method
-func (m *MockClient) UninstallLoadBalancerServiceFromOutsideFlows(arg0 net.IP, arg1 uint16, arg2 openflow.Protocol) error {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "UninstallLoadBalancerServiceFromOutsideFlows", arg0, arg1, arg2)
-	ret0, _ := ret[0].(error)
-	return ret0
-}
-
-// UninstallLoadBalancerServiceFromOutsideFlows indicates an expected call of UninstallLoadBalancerServiceFromOutsideFlows
-func (mr *MockClientMockRecorder) UninstallLoadBalancerServiceFromOutsideFlows(arg0, arg1, arg2 interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UninstallLoadBalancerServiceFromOutsideFlows", reflect.TypeOf((*MockClient)(nil).UninstallLoadBalancerServiceFromOutsideFlows), arg0, arg1, arg2)
-}
-
 // UninstallMulticastFlow mocks base method
 func (m *MockClient) UninstallMulticastFlow(arg0 net.IP) error {
 	m.ctrl.T.Helper()
diff --git a/pkg/agent/proxy/proxier_test.go b/pkg/agent/proxy/proxier_test.go
index fb76682be..21fb4baa4 100644
--- a/pkg/agent/proxy/proxier_test.go
+++ b/pkg/agent/proxy/proxier_test.go
@@ -301,9 +301,6 @@ func testLoadBalancer(t *testing.T, nodePortAddresses []net.IP, svcIP, ep1IP, ep
 		mockOFClient.EXPECT().InstallServiceFlows(groupID, loadBalancerIP, uint16(svcPort), bindingProtocol, uint16(0), nodeLocalExternal, corev1.ServiceTypeLoadBalancer).Times(1)
 	}
 	mockOFClient.EXPECT().InstallServiceFlows(groupID, gomock.Any(), uint16(svcNodePort), bindingProtocol, uint16(0), nodeLocalExternal, corev1.ServiceTypeNodePort).Times(1)
-	if proxyLoadBalancerIPs {
-		mockOFClient.EXPECT().InstallLoadBalancerServiceFromOutsideFlows(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
-	}
 	mockRouteClient.EXPECT().AddClusterIPRoute(svcIP).Times(1)
 	if proxyLoadBalancerIPs {
 		mockRouteClient.EXPECT().AddLoadBalancer([]string{loadBalancerIP.String()}).Times(1)
@@ -398,7 +395,6 @@ func testNodePort(t *testing.T, nodePortAddresses []net.IP, svcIP, ep1IP, ep2IP
 	mockOFClient.EXPECT().InstallServiceFlows(groupID, gomock.Any(), uint16(svcNodePort), bindingProtocol, uint16(0), nodeLocalExternal, corev1.ServiceTypeNodePort).Times(1)
 	mockRouteClient.EXPECT().AddClusterIPRoute(svcIP).Times(1)
 	mockRouteClient.EXPECT().AddNodePort(gomock.Any(), uint16(svcNodePort), bindingProtocol).Times(1)
-	mockOFClient.EXPECT().InstallLoadBalancerServiceFromOutsideFlows(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
 
 	fp.syncProxyRules()
 }
diff --git a/test/integration/agent/openflow_test.go b/test/integration/agent/openflow_test.go
index e4ddef735..237aca507 100644
--- a/test/integration/agent/openflow_test.go
+++ b/test/integration/agent/openflow_test.go
@@ -106,7 +106,8 @@ var (
 )
 
 func TestConnectivityFlows(t *testing.T) {
-	// Initialize ovs metrics (Prometheus) to test them
+	// Reset OVS metrics (Prometheus) and reinitialize them to test.
+	legacyregistry.Reset()
 	metrics.InitializeOVSMetrics()
 
 	// Hack the OS type if we run the test not on Windows Node.
@@ -123,6 +124,7 @@ func TestConnectivityFlows(t *testing.T) {
 		assert.Nil(t, err, fmt.Sprintf("Error while disconnecting from OVS bridge: %v", err))
 		err = ofTestUtils.DeleteOVSBridge(br)
 		assert.Nil(t, err, fmt.Sprintf("Error while deleting OVS bridge: %v", err))
+		ofClient.CleanOFTableCache()
 	}()
 
 	config := prepareConfiguration()
@@ -156,7 +158,8 @@ func TestConnectivityFlows(t *testing.T) {
 }
 
 func TestAntreaFlexibleIPAMConnectivityFlows(t *testing.T) {
-	// Initialize ovs metrics (Prometheus) to test them
+	// Reset OVS metrics (Prometheus) and reinitialize them to test.
+	legacyregistry.Reset()
 	metrics.InitializeOVSMetrics()
 
 	c = ofClient.NewClient(br, bridgeMgmtAddr, ovsconfig.OVSDatapathNetdev, true, false, true, false, false, true, false)
@@ -167,6 +170,7 @@ func TestAntreaFlexibleIPAMConnectivityFlows(t *testing.T) {
 		assert.Nil(t, err, fmt.Sprintf("Error while disconnecting from OVS bridge: %v", err))
 		err = ofTestUtils.DeleteOVSBridge(br)
 		assert.Nil(t, err, fmt.Sprintf("Error while deleting OVS bridge: %v", err))
+		ofClient.CleanOFTableCache()
 	}()
 
 	config := prepareConfiguration()
@@ -201,6 +205,10 @@ func TestAntreaFlexibleIPAMConnectivityFlows(t *testing.T) {
 }
 
 func TestReplayFlowsConnectivityFlows(t *testing.T) {
+	// Reset OVS metrics (Prometheus) and reinitialize them to test.
+	legacyregistry.Reset()
+	metrics.InitializeOVSMetrics()
+
 	c = ofClient.NewClient(br, bridgeMgmtAddr, ovsconfig.OVSDatapathNetdev, true, false, false, false, false, false, false)
 	err := ofTestUtils.PrepareOVSBridge(br)
 	require.Nil(t, err, fmt.Sprintf("Failed to prepare OVS bridge: %v", err))
@@ -210,6 +218,7 @@ func TestReplayFlowsConnectivityFlows(t *testing.T) {
 		assert.Nil(t, err, fmt.Sprintf("Error while disconnecting from OVS bridge: %v", err))
 		err = ofTestUtils.DeleteOVSBridge(br)
 		assert.Nil(t, err, fmt.Sprintf("Error while deleting OVS bridge: %v", err))
+		ofClient.CleanOFTableCache()
 	}()
 
 	config := prepareConfiguration()
@@ -237,6 +246,10 @@ func TestReplayFlowsConnectivityFlows(t *testing.T) {
 }
 
 func TestReplayFlowsNetworkPolicyFlows(t *testing.T) {
+	// Reset OVS metrics (Prometheus) and reinitialize them to test.
+	legacyregistry.Reset()
+	metrics.InitializeOVSMetrics()
+
 	c = ofClient.NewClient(br, bridgeMgmtAddr, ovsconfig.OVSDatapathNetdev, true, false, false, false, false, false, false)
 	err := ofTestUtils.PrepareOVSBridge(br)
 	require.Nil(t, err, fmt.Sprintf("Failed to prepare OVS bridge: %v", err))
@@ -249,6 +262,7 @@ func TestReplayFlowsNetworkPolicyFlows(t *testing.T) {
 		assert.Nil(t, err, fmt.Sprintf("Error while disconnecting from OVS bridge: %v", err))
 		err = ofTestUtils.DeleteOVSBridge(br)
 		assert.Nil(t, err, fmt.Sprintf("Error while deleting OVS bridge: %v", err))
+		ofClient.CleanOFTableCache()
 	}()
 
 	ruleID := uint32(100)
@@ -420,7 +434,8 @@ func testUninstallPodFlows(t *testing.T, config *testConfig) {
 }
 
 func TestNetworkPolicyFlows(t *testing.T) {
-	// Initialize ovs metrics (Prometheus) to test them
+	// Reset OVS metrics (Prometheus) and reinitialize them to test.
+	legacyregistry.Reset()
 	metrics.InitializeOVSMetrics()
 
 	c = ofClient.NewClient(br, bridgeMgmtAddr, ovsconfig.OVSDatapathNetdev, true, false, false, false, false, false, false)
@@ -435,6 +450,7 @@ func TestNetworkPolicyFlows(t *testing.T) {
 		assert.Nil(t, err, fmt.Sprintf("Error while disconnecting from OVS bridge: %v", err))
 		err = ofTestUtils.DeleteOVSBridge(br)
 		assert.Nil(t, err, fmt.Sprintf("Error while deleting OVS bridge: %v", err))
+		ofClient.CleanOFTableCache()
 	}()
 
 	ruleID := uint32(100)
@@ -530,7 +546,8 @@ func TestNetworkPolicyFlows(t *testing.T) {
 }
 
 func TestIPv6ConnectivityFlows(t *testing.T) {
-	// Initialize ovs metrics (Prometheus) to test them
+	// Reset OVS metrics (Prometheus) and reinitialize them to test.
+	legacyregistry.Reset()
 	metrics.InitializeOVSMetrics()
 
 	c = ofClient.NewClient(br, bridgeMgmtAddr, ovsconfig.OVSDatapathNetdev, true, false, true, false, false, false, false)
@@ -542,6 +559,7 @@ func TestIPv6ConnectivityFlows(t *testing.T) {
 		assert.Nil(t, err, fmt.Sprintf("Error while disconnecting from OVS bridge: %v", err))
 		err = ofTestUtils.DeleteOVSBridge(br)
 		assert.Nil(t, err, fmt.Sprintf("Error while deleting OVS bridge: %v", err))
+		ofClient.CleanOFTableCache()
 	}()
 	config := prepareIPv6Configuration()
 	t.Run("testInitialize", func(t *testing.T) {
@@ -575,6 +593,10 @@ type svcConfig struct {
 }
 
 func TestProxyServiceFlows(t *testing.T) {
+	// Reset OVS metrics (Prometheus) and reinitialize them to test.
+	legacyregistry.Reset()
+	metrics.InitializeOVSMetrics()
+
 	c = ofClient.NewClient(br, bridgeMgmtAddr, ovsconfig.OVSDatapathNetdev, true, false, false, false, false, false, false)
 	err := ofTestUtils.PrepareOVSBridge(br)
 	require.Nil(t, err, fmt.Sprintf("Failed to prepare OVS bridge %s", br))
@@ -587,6 +609,7 @@ func TestProxyServiceFlows(t *testing.T) {
 		assert.Nil(t, err, fmt.Sprintf("Error while disconnecting from OVS bridge: %v", err))
 		err = ofTestUtils.DeleteOVSBridge(br)
 		assert.Nil(t, err, fmt.Sprintf("Error while deleting OVS bridge: %v", err))
+		ofClient.CleanOFTableCache()
 	}()
 
 	endpoints := []k8sproxy.Endpoint{
@@ -1514,6 +1537,10 @@ func prepareSNATFlows(snatIP net.IP, mark, podOFPort, podOFPortRemote uint32, vM
 }
 
 func TestSNATFlows(t *testing.T) {
+	// Reset OVS metrics (Prometheus) and reinitialize them to test.
+	legacyregistry.Reset()
+	metrics.InitializeOVSMetrics()
+
 	c = ofClient.NewClient(br, bridgeMgmtAddr, ovsconfig.OVSDatapathNetdev, false, false, true, false, false, false, false)
 	err := ofTestUtils.PrepareOVSBridge(br)
 	require.Nil(t, err, fmt.Sprintf("Failed to prepare OVS bridge %s", br))
@@ -1527,6 +1554,7 @@ func TestSNATFlows(t *testing.T) {
 		assert.Nil(t, err, fmt.Sprintf("Error while disconnecting from OVS bridge: %v", err))
 		err = ofTestUtils.DeleteOVSBridge(br)
 		assert.Nil(t, err, fmt.Sprintf("Error while deleting OVS bridge: %v", err))
+		ofClient.CleanOFTableCache()
 	}()
 
 	snatIP := net.ParseIP("10.10.10.14")