Repository: antrea-io/antrea
Pull request #2444 (2021-07-21 08:03:09)

Update Egress status when configuring static Egress
Update Egress status when configuring a static Egress.

For example:

Create an `Egress` resources, assign EgressIP field and the EgressIP has been assigned to Node 'kind-worker' manually.
```yaml
kind: Egress
metadata:
  name: egress-web-ipv4
spec:
  appliedTo:
    podSelector:
      matchLabels:
        role: web
    namespaceSelector:
      matchLabels:
        env: prod
  egressIP: 10.10.10.10
```

List the `Egress` resource with kubectl.

```yaml
# kubectl get egress
NAME                 EGRESSIP       AGE   NODE
egress-web-ipv4      10.10.0.10     1m    kind-worker
```

It is an additional PR for #2186, and makes the Egress status more user friendly.

Signed-off-by: Wenqi Qiu <wenqiq@vmware.com>

codecov-commenter: # [Codecov](https://codecov.io/gh/antrea-io/antrea/pull/2444?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) Report
> Merging [#2444](https://codecov.io/gh/antrea-io/antrea/pull/2444?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (798ec1d) into [main](https://codecov.io/gh/antrea-io/antrea/commit/7469d7e9220f0950928ba16a2a59a227051dd041?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (7469d7e) will **decrease** coverage by `20.77%`.
> The diff coverage is `0.00%`.

[![Impacted file tree graph](https://codecov.io/gh/antrea-io/antrea/pull/2444/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/2444?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None)

```diff
@@             Coverage Diff             @@
##             main    #2444       +/-   ##
===========================================
- Coverage   59.63%   38.85%   -20.78%     
===========================================
  Files         284      278        -6     
  Lines       22178    21348      -830     
===========================================
- Hits        13226     8295     -4931     
- Misses       7527    11873     +4346     
+ Partials     1425     1180      -245     
```

| Flag | Coverage Δ | |
|---|---|---|
| kind-e2e-tests | `38.85% <0.00%> (-8.01%)` | :arrow_down: |
| 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/2444?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/2444/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%> (-35.53%)` | :arrow_down: |
| [pkg/agent/controller/egress/id\_allocator.go](https://codecov.io/gh/antrea-io/antrea/pull/2444/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/crd\_utils.go](https://codecov.io/gh/antrea-io/antrea/pull/2444/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2NvbnRyb2xsZXIvbmV0d29ya3BvbGljeS9jcmRfdXRpbHMuZ28=) | `0.00% <0.00%> (-89.16%)` | :arrow_down: |
| [pkg/controller/networkpolicy/endpoint\_querier.go](https://codecov.io/gh/antrea-io/antrea/pull/2444/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/2444/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%> (-87.21%)` | :arrow_down: |
| [pkg/apis/controlplane/v1beta1/conversion.go](https://codecov.io/gh/antrea-io/antrea/pull/2444/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2FwaXMvY29udHJvbHBsYW5lL3YxYmV0YTEvY29udmVyc2lvbi5nbw==) | `1.20% <0.00%> (-83.14%)` | :arrow_down: |
| [...kg/controller/networkpolicy/antreanetworkpolicy.go](https://codecov.io/gh/antrea-io/antrea/pull/2444/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2NvbnRyb2xsZXIvbmV0d29ya3BvbGljeS9hbnRyZWFuZXR3b3JrcG9saWN5Lmdv) | `0.00% <0.00%> (-83.00%)` | :arrow_down: |
| [pkg/controller/egress/ipallocator/allocator.go](https://codecov.io/gh/antrea-io/antrea/pull/2444/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2NvbnRyb2xsZXIvZWdyZXNzL2lwYWxsb2NhdG9yL2FsbG9jYXRvci5nbw==) | `0.00% <0.00%> (-82.98%)` | :arrow_down: |
| [pkg/agent/util/iptables/lock.go](https://codecov.io/gh/antrea-io/antrea/pull/2444/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2FnZW50L3V0aWwvaXB0YWJsZXMvbG9jay5nbw==) | `0.00% <0.00%> (-81.82%)` | :arrow_down: |
| [pkg/agent/controller/networkpolicy/priority.go](https://codecov.io/gh/antrea-io/antrea/pull/2444/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2FnZW50L2NvbnRyb2xsZXIvbmV0d29ya3BvbGljeS9wcmlvcml0eS5nbw==) | `8.49% <0.00%> (-81.70%)` | :arrow_down: |
| ... and [129 more](https://codecov.io/gh/antrea-io/antrea/pull/2444/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) | |

wenqiq: It seems all comments have been addressed. PTAL. @tnqn 

Patch:
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index c79f644b1..f675f044a 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -8,9 +8,11 @@ on:
     branches:
     - main
     - release-*
-jobs:
 
+env:
+  go-cache-name: go
 
+jobs:
   test-unit:
     name: Unit test
     strategy:
@@ -18,18 +20,28 @@ jobs:
         os: [ubuntu-latest, windows-2019]
     runs-on: ${{ matrix.os }}
     steps:
-
     - name: Set up Go 1.15
       uses: actions/setup-go@v2
       with:
         go-version: 1.15
-
     - name: Check-out code
       uses: actions/checkout@v2
-
+    - uses: actions/cache@v2
+      with:
+        # In order:
+        # * Module download cache
+        # * Build cache (Linux)
+        # * Build cache (Mac)
+        path: |
+          ~/go/pkg/mod
+          ~/.cache/go-build
+          ~/Library/Caches/go-build
+          %LocalAppData%\go-build
+        key: ${{ runner.os }}-${{ env.go-cache-name }}-${{ hashFiles('**/go.sum') }}
+        restore-keys: |
+          ${{ runner.os }}-${{ env.go-cache-name }}-
     - name: Run unit tests
       run: make test-unit
-
     - name: Codecov
       uses: codecov/codecov-action@v1
       with:
@@ -38,7 +50,6 @@ jobs:
         flags: unit-tests
         name: codecov-unit-test
 
-
   golangci-lint:
     name: Golangci-lint
     strategy:
@@ -52,150 +63,122 @@ jobs:
         go-version: 1.15
     - name: Check-out code
       uses: actions/checkout@v2
-    - name: Run golangci-lint
-      run: make golangci
-
-
-  golangci-lint-netpol-tmp:
-    name: Golangci-lint for netpol code
-    runs-on: [ubuntu-latest]
-    steps:
-    - name: Set up Go 1.15
-      uses: actions/setup-go@v2
+    - uses: actions/cache@v2
       with:
-        go-version: 1.15
-    - name: Check-out code
-      uses: actions/checkout@v2
+        # In order:
+        # * Module download cache
+        # * Build cache (Linux)
+        # * Build cache (Mac)
+        path: |
+          ~/go/pkg/mod
+          ~/.cache/go-build
+          ~/Library/Caches/go-build
+          %LocalAppData%\go-build
+        key: ${{ runner.os }}-${{ env.go-cache-name }}-${{ hashFiles('**/go.sum') }}
+        restore-keys: |
+          ${{ runner.os }}-${{ env.go-cache-name }}-
     - name: Run golangci-lint
+      run: make golangci
+    - name: Run golangci-lint for netpol
       working-directory: hack/netpol
       run: make golangci
 
-
   bin:
-    name: Build Antrea binaries
+    name: Build Antrea and antctl binaries
     runs-on: [ubuntu-latest]
-    strategy:
-      matrix:
-        arch: [amd64, arm64, arm]
     steps:
-
     - name: Set up Go 1.15
       uses: actions/setup-go@v2
       with:
         go-version: 1.15
-
     - name: Check-out code
       uses: actions/checkout@v2
-
-    - name: Build Antrea binaries
-      run: GOARCH=${{ matrix.arch }} make bin
+    - uses: actions/cache@v2
+      with:
+        # In order:
+        # * Module download cache
+        # * Build cache (Linux)
+        # * Build cache (Mac)
+        path: |
+          ~/go/pkg/mod
+          ~/.cache/go-build
+          ~/Library/Caches/go-build
+          %LocalAppData%\go-build
+        key: ${{ runner.os }}-${{ env.go-cache-name }}-${{ hashFiles('**/go.sum') }}
+        restore-keys: |
+          ${{ runner.os }}-${{ env.go-cache-name }}-
+    - name: Build Antrea binaries for amd64
+      run: GOARCH=amd64 make bin
+    - name: Build Antrea binaries for arm64
+      run: GOARCH=arm64 make bin
+    - name: Build Antrea binaries for arm
+      run: GOARCH=arm make bin
+    - name: Build antctl binaries
+      run: make antctl
 
   windows-bin:
     name: Build Antrea Windows binaries
     runs-on: [ubuntu-latest]
     steps:
-
     - name: Set up Go 1.15
       uses: actions/setup-go@v2
       with:
         go-version: 1.15
-
     - name: Check-out code
       uses: actions/checkout@v2
-
+    - uses: actions/cache@v2
+      with:
+        # In order:
+        # * Module download cache
+        # * Build cache (Linux)
+        # * Build cache (Mac)
+        path: |
+          ~/go/pkg/mod
+          ~/.cache/go-build
+          ~/Library/Caches/go-build
+          %LocalAppData%\go-build
+        key: ${{ runner.os }}-${{ env.go-cache-name }}-${{ hashFiles('**/go.sum') }}
+        restore-keys: |
+          ${{ runner.os }}-${{ env.go-cache-name }}-
     - name: Build Antrea windows binaries
       run: make windows-bin
 
-  antctl:
-    name: Build antctl for macOS, Linux and Windows
-    runs-on: [ubuntu-latest]
-    steps:
-
-      - name: Set up Go 1.15
-        uses: actions/setup-go@v2
-        with:
-          go-version: 1.15
-
-      - name: Check-out code
-        uses: actions/checkout@v2
-
-      - name: Build antctl binaries
-        run: make antctl
-
-
-  codegen:
-    name: Check code generation
+  tidy-codegen-manifest:
+    name: Check tidy, code generation and manifest
     runs-on: [ubuntu-latest]
     steps:
-
     - name: Set up Go 1.15
       uses: actions/setup-go@v2
       with:
         go-version: 1.15
-
     - name: Check-out code
       uses: actions/checkout@v2
-
+    # tidy check need to be run before code generation which will regenerate codes.
+    - name: Check tidy
+      run: make test-tidy
     - name: Check code generation
       run: ./ci/check-codegen.sh
-
-
-  manifest:
-    name: Check manifest
-    runs-on: [ubuntu-latest]
-    steps:
-
-    - name: Set up Go 1.15
-      uses: actions/setup-go@v2
-      with:
-        go-version: 1.15
-
-    - name: Check-out code
-      uses: actions/checkout@v2
-
     - name: Check manifest
       run: ./ci/check-manifest.sh
 
-
-  tidy:
-    name: Check go.mod tidy
-    runs-on: [ubuntu-latest]
-    steps:
-
-    - name: Set up Go 1.15
-      uses: actions/setup-go@v2
-      with:
-        go-version: 1.15
-
-    - name: Check-out code
-      uses: actions/checkout@v2
-
-    - name: Check tidy
-      run: make test-tidy
-
   verify:
     name: Verify docs and spelling
     runs-on: [ubuntu-latest]
     steps:
-
     - name: Set up Go 1.15
       uses: actions/setup-go@v2
       with:
         go-version: 1.15
-
     - name: Check-out code
       uses: actions/checkout@v2
-
     - name: Run verify scripts
       run: make verify
-
     - name: Checking for broken Markdown links
       uses: antoninbas/github-action-markdown-link-check@1.0.9-pre
       with:
         folder-path: './docs'
         file-path: './README.md, ./CHANGELOG.md, ./CONTRIBUTING.md, ./GOVERNANCE.md, ./MAINTAINERS.md, ./ROADMAP.md, ./SECURITY.md'
         config-file: 'hack/.md_links_config.json'
-
     - name: Markdownlint
       run: |
         sudo npm install -g markdownlint-cli
diff --git a/build/yamls/antrea-aks.yml b/build/yamls/antrea-aks.yml
index 5a63e24d7..c2f0194a6 100644
--- a/build/yamls/antrea-aks.yml
+++ b/build/yamls/antrea-aks.yml
@@ -3402,7 +3402,6 @@ rules:
   - v1alpha1.stats.antrea.tanzu.vmware.com
   - v1beta1.system.antrea.tanzu.vmware.com
   - v1beta2.controlplane.antrea.tanzu.vmware.com
-  - v1beta1.controlplane.antrea.tanzu.vmware.com
   - v1alpha1.stats.antrea.io
   - v1beta1.system.antrea.io
   - v1beta2.controlplane.antrea.io
@@ -3415,6 +3414,7 @@ rules:
   - apiregistration.k8s.io
   resourceNames:
   - v1beta1.networking.antrea.tanzu.vmware.com
+  - v1beta1.controlplane.antrea.tanzu.vmware.com
   resources:
   - apiservices
   verbs:
@@ -4058,21 +4058,6 @@ spec:
 ---
 apiVersion: apiregistration.k8s.io/v1
 kind: APIService
-metadata:
-  labels:
-    app: antrea
-  name: v1beta1.controlplane.antrea.tanzu.vmware.com
-spec:
-  group: controlplane.antrea.tanzu.vmware.com
-  groupPriorityMinimum: 100
-  service:
-    name: antrea
-    namespace: kube-system
-  version: v1beta1
-  versionPriority: 100
----
-apiVersion: apiregistration.k8s.io/v1
-kind: APIService
 metadata:
   labels:
     app: antrea
diff --git a/build/yamls/antrea-eks.yml b/build/yamls/antrea-eks.yml
index dc5bc7201..53788c248 100644
--- a/build/yamls/antrea-eks.yml
+++ b/build/yamls/antrea-eks.yml
@@ -3402,7 +3402,6 @@ rules:
   - v1alpha1.stats.antrea.tanzu.vmware.com
   - v1beta1.system.antrea.tanzu.vmware.com
   - v1beta2.controlplane.antrea.tanzu.vmware.com
-  - v1beta1.controlplane.antrea.tanzu.vmware.com
   - v1alpha1.stats.antrea.io
   - v1beta1.system.antrea.io
   - v1beta2.controlplane.antrea.io
@@ -3415,6 +3414,7 @@ rules:
   - apiregistration.k8s.io
   resourceNames:
   - v1beta1.networking.antrea.tanzu.vmware.com
+  - v1beta1.controlplane.antrea.tanzu.vmware.com
   resources:
   - apiservices
   verbs:
@@ -4058,21 +4058,6 @@ spec:
 ---
 apiVersion: apiregistration.k8s.io/v1
 kind: APIService
-metadata:
-  labels:
-    app: antrea
-  name: v1beta1.controlplane.antrea.tanzu.vmware.com
-spec:
-  group: controlplane.antrea.tanzu.vmware.com
-  groupPriorityMinimum: 100
-  service:
-    name: antrea
-    namespace: kube-system
-  version: v1beta1
-  versionPriority: 100
----
-apiVersion: apiregistration.k8s.io/v1
-kind: APIService
 metadata:
   labels:
     app: antrea
diff --git a/build/yamls/antrea-gke.yml b/build/yamls/antrea-gke.yml
index 67fab434f..eccc11946 100644
--- a/build/yamls/antrea-gke.yml
+++ b/build/yamls/antrea-gke.yml
@@ -3402,7 +3402,6 @@ rules:
   - v1alpha1.stats.antrea.tanzu.vmware.com
   - v1beta1.system.antrea.tanzu.vmware.com
   - v1beta2.controlplane.antrea.tanzu.vmware.com
-  - v1beta1.controlplane.antrea.tanzu.vmware.com
   - v1alpha1.stats.antrea.io
   - v1beta1.system.antrea.io
   - v1beta2.controlplane.antrea.io
@@ -3415,6 +3414,7 @@ rules:
   - apiregistration.k8s.io
   resourceNames:
   - v1beta1.networking.antrea.tanzu.vmware.com
+  - v1beta1.controlplane.antrea.tanzu.vmware.com
   resources:
   - apiservices
   verbs:
@@ -4058,21 +4058,6 @@ spec:
 ---
 apiVersion: apiregistration.k8s.io/v1
 kind: APIService
-metadata:
-  labels:
-    app: antrea
-  name: v1beta1.controlplane.antrea.tanzu.vmware.com
-spec:
-  group: controlplane.antrea.tanzu.vmware.com
-  groupPriorityMinimum: 100
-  service:
-    name: antrea
-    namespace: kube-system
-  version: v1beta1
-  versionPriority: 100
----
-apiVersion: apiregistration.k8s.io/v1
-kind: APIService
 metadata:
   labels:
     app: antrea
diff --git a/build/yamls/antrea-ipsec.yml b/build/yamls/antrea-ipsec.yml
index 7c7b93f44..8677b97d2 100644
--- a/build/yamls/antrea-ipsec.yml
+++ b/build/yamls/antrea-ipsec.yml
@@ -3402,7 +3402,6 @@ rules:
   - v1alpha1.stats.antrea.tanzu.vmware.com
   - v1beta1.system.antrea.tanzu.vmware.com
   - v1beta2.controlplane.antrea.tanzu.vmware.com
-  - v1beta1.controlplane.antrea.tanzu.vmware.com
   - v1alpha1.stats.antrea.io
   - v1beta1.system.antrea.io
   - v1beta2.controlplane.antrea.io
@@ -3415,6 +3414,7 @@ rules:
   - apiregistration.k8s.io
   resourceNames:
   - v1beta1.networking.antrea.tanzu.vmware.com
+  - v1beta1.controlplane.antrea.tanzu.vmware.com
   resources:
   - apiservices
   verbs:
@@ -4072,21 +4072,6 @@ spec:
 ---
 apiVersion: apiregistration.k8s.io/v1
 kind: APIService
-metadata:
-  labels:
-    app: antrea
-  name: v1beta1.controlplane.antrea.tanzu.vmware.com
-spec:
-  group: controlplane.antrea.tanzu.vmware.com
-  groupPriorityMinimum: 100
-  service:
-    name: antrea
-    namespace: kube-system
-  version: v1beta1
-  versionPriority: 100
----
-apiVersion: apiregistration.k8s.io/v1
-kind: APIService
 metadata:
   labels:
     app: antrea
diff --git a/build/yamls/antrea.yml b/build/yamls/antrea.yml
index 7cfc149c0..64a1b3db7 100644
--- a/build/yamls/antrea.yml
+++ b/build/yamls/antrea.yml
@@ -3402,7 +3402,6 @@ rules:
   - v1alpha1.stats.antrea.tanzu.vmware.com
   - v1beta1.system.antrea.tanzu.vmware.com
   - v1beta2.controlplane.antrea.tanzu.vmware.com
-  - v1beta1.controlplane.antrea.tanzu.vmware.com
   - v1alpha1.stats.antrea.io
   - v1beta1.system.antrea.io
   - v1beta2.controlplane.antrea.io
@@ -3415,6 +3414,7 @@ rules:
   - apiregistration.k8s.io
   resourceNames:
   - v1beta1.networking.antrea.tanzu.vmware.com
+  - v1beta1.controlplane.antrea.tanzu.vmware.com
   resources:
   - apiservices
   verbs:
@@ -4063,21 +4063,6 @@ spec:
 ---
 apiVersion: apiregistration.k8s.io/v1
 kind: APIService
-metadata:
-  labels:
-    app: antrea
-  name: v1beta1.controlplane.antrea.tanzu.vmware.com
-spec:
-  group: controlplane.antrea.tanzu.vmware.com
-  groupPriorityMinimum: 100
-  service:
-    name: antrea
-    namespace: kube-system
-  version: v1beta1
-  versionPriority: 100
----
-apiVersion: apiregistration.k8s.io/v1
-kind: APIService
 metadata:
   labels:
     app: antrea
diff --git a/build/yamls/base/controller-rbac.yml b/build/yamls/base/controller-rbac.yml
index af7b90e76..fdc1e1e59 100644
--- a/build/yamls/base/controller-rbac.yml
+++ b/build/yamls/base/controller-rbac.yml
@@ -89,7 +89,6 @@ rules:
       - v1alpha1.stats.antrea.tanzu.vmware.com
       - v1beta1.system.antrea.tanzu.vmware.com
       - v1beta2.controlplane.antrea.tanzu.vmware.com
-      - v1beta1.controlplane.antrea.tanzu.vmware.com
       - v1alpha1.stats.antrea.io
       - v1beta1.system.antrea.io
       - v1beta2.controlplane.antrea.io
@@ -102,6 +101,7 @@ rules:
       - apiservices
     resourceNames:
       - v1beta1.networking.antrea.tanzu.vmware.com
+      - v1beta1.controlplane.antrea.tanzu.vmware.com
     verbs:
       - delete
   - apiGroups:
diff --git a/build/yamls/base/controller.yml b/build/yamls/base/controller.yml
index 71b632969..f6b6f0f7f 100644
--- a/build/yamls/base/controller.yml
+++ b/build/yamls/base/controller.yml
@@ -306,20 +306,6 @@ spec:
 # Deprecated in v1.0.0.
 apiVersion: apiregistration.k8s.io/v1
 kind: APIService
-metadata:
-  name: v1beta1.controlplane.antrea.tanzu.vmware.com
-spec:
-  group: controlplane.antrea.tanzu.vmware.com
-  groupPriorityMinimum: 100
-  version: v1beta1
-  versionPriority: 100
-  service:
-    name: antrea
-    namespace: kube-system
----
-# Deprecated in v1.0.0.
-apiVersion: apiregistration.k8s.io/v1
-kind: APIService
 metadata:
   name: v1beta1.system.antrea.tanzu.vmware.com
 spec:
diff --git a/cmd/antrea-agent/agent.go b/cmd/antrea-agent/agent.go
index 1007b3398..97499e41b 100644
--- a/cmd/antrea-agent/agent.go
+++ b/cmd/antrea-agent/agent.go
@@ -201,7 +201,8 @@ func run(o *Options) error {
 
 	var denyConnStore *connections.DenyConnectionStore
 	if features.DefaultFeatureGate.Enabled(features.FlowExporter) {
-		denyConnStore = connections.NewDenyConnectionStore(ifaceStore, proxier)
+		denyConnStore = connections.NewDenyConnectionStore(ifaceStore, proxier, o.staleConnectionTimeout)
+		go denyConnStore.RunPeriodicDeletion(stopCh)
 	}
 	networkPolicyController, err := networkpolicy.NewNetworkPolicyController(
 		antreaClientProvider,
@@ -382,7 +383,8 @@ func run(o *Options) error {
 			v6Enabled,
 			proxier,
 			networkPolicyController,
-			o.pollInterval)
+			o.pollInterval,
+			o.staleConnectionTimeout)
 		go conntrackConnStore.Run(stopCh)
 
 		flowExporter, err := exporter.NewFlowExporter(
diff --git a/cmd/antrea-agent/options.go b/cmd/antrea-agent/options.go
index bb8a9ed3c..a194615c1 100644
--- a/cmd/antrea-agent/options.go
+++ b/cmd/antrea-agent/options.go
@@ -44,6 +44,7 @@ const (
 	defaultFlowPollInterval        = 5 * time.Second
 	defaultActiveFlowExportTimeout = 30 * time.Second
 	defaultIdleFlowExportTimeout   = 15 * time.Second
+	defaultStaleConnectionTimeout  = 5 * time.Minute
 	defaultNPLPortRange            = "61000-62000"
 )
 
@@ -62,6 +63,8 @@ type Options struct {
 	activeFlowTimeout time.Duration
 	// Idle flow timeout to export records of inactive flows
 	idleFlowTimeout time.Duration
+	// Stale connection timeout to delete connections if they are not exported.
+	staleConnectionTimeout time.Duration
 }
 
 func newOptions() *Options {
@@ -254,10 +257,19 @@ func (o *Options) validateFlowExporterConfig() error {
 				return fmt.Errorf("IdleFlowExportTimeout is not provided in right format")
 			}
 			if o.idleFlowTimeout < o.pollInterval {
-				o.activeFlowTimeout = o.pollInterval
+				o.idleFlowTimeout = o.pollInterval
 				klog.Warningf("IdleFlowExportTimeout must be greater than or equal to FlowPollInterval")
 			}
 		}
+		if (o.activeFlowTimeout > defaultStaleConnectionTimeout) || (o.idleFlowTimeout > defaultStaleConnectionTimeout) {
+			if o.activeFlowTimeout > o.idleFlowTimeout {
+				o.staleConnectionTimeout = 2 * o.activeFlowTimeout
+			} else {
+				o.staleConnectionTimeout = 2 * o.idleFlowTimeout
+			}
+		} else {
+			o.staleConnectionTimeout = defaultStaleConnectionTimeout
+		}
 	}
 	return nil
 }
diff --git a/docs/api.md b/docs/api.md
index ba16a9689..641231ebb 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -46,7 +46,6 @@ These are the API group versions which are curently available when using Antrea.
 |---|---|---|---|---|---|
 | `clusterinformation.antrea.tanzu.vmware.com` | `v1beta1` | No | v0.3.0 | v1.0.0 | Dec 2021 |
 | `core.antrea.tanzu.vmware.com` | `v1alpha2` | No | v0.11.0 | v1.0.0 | Dec 2021 |
-| `controlplane.antrea.tanzu.vmware.com` | `v1beta1` | Yes | v0.10.0 | v0.11.0 | Aug 2021 |
 | `controlplane.antrea.tanzu.vmware.com` | `v1beta2` | Yes | v0.11.0 | v1.0.0 | Dec 2021 |
 | `ops.antrea.tanzu.vmware.com` | `v1alpha1` | No | v0.8.0 | v1.0.0 | Dec 2021 |
 | `security.antrea.tanzu.vmware.com` | `v1alpha1` | No | v0.8.0 | v1.0.0 | Dec 2021 |
@@ -62,6 +61,7 @@ These are the API group versions which are curently available when using Antrea.
 |---|---|---|---|---|---|
 | `core.antrea.tanzu.vmware.com` | `v1alpha1` | No | v0.8.0 | v0.11.0 | v0.11.0 |
 | `networking.antrea.tanzu.vmware.com` | `v1beta1` | Yes | v0.3.0 | v0.10.0 | v1.2.0 |
+| `controlplane.antrea.tanzu.vmware.com` | `v1beta1` | Yes | v0.10.0 | v0.11.0 | v1.3.0 |
 
 ## API renaming from `*.antrea.tanzu.vmware.com` to `*.antrea.io`
 
diff --git a/docs/egress.md b/docs/egress.md
index 3ad0ca797..a10d75adc 100644
--- a/docs/egress.md
+++ b/docs/egress.md
@@ -284,7 +284,7 @@ egress-staging       10.10.0.105    1m    node-5
 Now, the packets from the Pods with in the `prod` Namespace to the external
 network will be redirected to the `node-4` Node and SNATed to `10.10.0.104`
 while the packets from the Pods in the `staging` Namespace to the external
-network will be redirected to the `node-5` Node and SNATed to `10.10.0.12`.
+network will be redirected to the `node-5` Node and SNATed to `10.10.0.105`.
 
 In this configuration, if the `node-4` Node powers off, re-configuring
 `10.10.0.104` to another Node or updating the `egressIP` of `egress-prod` to
diff --git a/docs/kubernetes-installers.md b/docs/kubernetes-installers.md
index 0f7a22c8b..245a1ffdc 100644
--- a/docs/kubernetes-installers.md
+++ b/docs/kubernetes-installers.md
@@ -5,9 +5,9 @@
 The table below is not comprehensive. Antrea should work with most K8s
 installers and distributions. The table refers to specific version combinations
 which are known to work and have been tested, but support is not limited to that
-list. Each Antrea version supports [multiple K8s minor
-versions](versioning.md#supported-k8s-versions), and installers / distributions
-based on any one of these K8s versions should work with that Antrea version.
+list. Each Antrea version supports [multiple K8s minor versions](versioning.md#supported-k8s-versions),
+and installers / distributions based on any one of these K8s versions should
+work with that Antrea version.
 
 | Antrea Version | Installer / Distribution | Cloud Infra | Node Info | Node Size | Conformance Results | Comments |
 |-|-|-|-|-|-|-|
diff --git a/go.mod b/go.mod
index 3ca5321b9..aea79b8f0 100644
--- a/go.mod
+++ b/go.mod
@@ -3,6 +3,8 @@ module antrea.io/antrea
 go 1.15
 
 require (
+	antrea.io/libOpenflow v0.2.0
+	antrea.io/ofnet v0.1.0
 	github.com/Mellanox/sriovnet v1.0.2
 	github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331
 	github.com/Microsoft/hcsshim v0.8.9
@@ -16,8 +18,6 @@ require (
 	github.com/confluentinc/bincover v0.1.0
 	github.com/containernetworking/cni v0.8.0
 	github.com/containernetworking/plugins v0.8.7
-	github.com/contiv/libOpenflow v0.0.0-20210521033357-6b49eccb12e0
-	github.com/contiv/ofnet v0.0.0-00010101000000-000000000000
 	github.com/coreos/go-iptables v0.6.0
 	github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1 // indirect
 	github.com/go-openapi/spec v0.19.5
@@ -34,12 +34,12 @@ require (
 	github.com/prometheus/client_golang v1.7.1
 	github.com/prometheus/common v0.10.0
 	github.com/satori/go.uuid v1.2.0
-	github.com/sirupsen/logrus v1.7.0
+	github.com/sirupsen/logrus v1.8.1
 	github.com/spf13/afero v1.4.1
 	github.com/spf13/cobra v1.1.1
 	github.com/spf13/pflag v1.0.5
 	github.com/streamrail/concurrent-map v0.0.0-20160823150647-8bf1e9bacbf6 // indirect
-	github.com/stretchr/testify v1.6.1
+	github.com/stretchr/testify v1.7.0
 	github.com/ti-mo/conntrack v0.3.0
 	github.com/vishvananda/netlink v1.1.0
 	github.com/vmware/go-ipfix v0.5.4
@@ -67,11 +67,6 @@ require (
 	k8s.io/utils v0.0.0-20210305010621-2afb4311ab10
 )
 
-replace (
-	// hcshim repo is modifed to add "AdditionalParams" field to HNSEndpoint struct.
-	// We will use this replace before pushing the change to hcshim upstream repo.
-	github.com/Microsoft/hcsshim v0.8.9 => github.com/ruicao93/hcsshim v0.8.10-0.20210114035434-63fe00c1b9aa
-	// antrea/plugins/octant/go.mod also has this replacement since replace statement in dependencies
-	// were ignored. We need to change antrea/plugins/octant/go.mod if there is any change here.
-	github.com/contiv/ofnet => github.com/wenyingd/ofnet v0.0.0-20210526054554-3e71e19fd0cf
-)
+// hcshim repo is modifed to add "AdditionalParams" field to HNSEndpoint struct.
+// We will use this replace before pushing the change to hcshim upstream repo.
+replace github.com/Microsoft/hcsshim v0.8.9 => github.com/ruicao93/hcsshim v0.8.10-0.20210114035434-63fe00c1b9aa
diff --git a/go.sum b/go.sum
index 4175fc44a..127ea96d7 100644
--- a/go.sum
+++ b/go.sum
@@ -1,3 +1,7 @@
+antrea.io/libOpenflow v0.2.0 h1:bBNT3CI8q2FMQRdphP0dynImRK1LBDmA+cQOu7JULj4=
+antrea.io/libOpenflow v0.2.0/go.mod h1:CzEJZxDNAupiGxeL5VOw92PsxfyvehEAvE3PiC6gr8o=
+antrea.io/ofnet v0.1.0 h1:r5c/TM5pa8xSVd5xEUj1L2vYfc4EjIzCWs6cHbeuVFc=
+antrea.io/ofnet v0.1.0/go.mod h1:fLmHHD9XWeVza2pz/HEdLkGyA7pNutxlXCqodlwWQsA=
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
@@ -121,8 +125,6 @@ github.com/containernetworking/cni v0.8.0 h1:BT9lpgGoH4jw3lFC7Odz2prU5ruiYKcgAjM
 github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
 github.com/containernetworking/plugins v0.8.7 h1:bU7QieuAp+sACI2vCzESJ3FoT860urYP+lThyZkb/2M=
 github.com/containernetworking/plugins v0.8.7/go.mod h1:R7lXeZaBzpfqapcAbHRW8/CYwm0dHzbz0XEjofx0uB0=
-github.com/contiv/libOpenflow v0.0.0-20210521033357-6b49eccb12e0 h1:Vf4MMw2EBHj+sQaBgXiS6RR6CDi3ZF8xx59eZkWxmHY=
-github.com/contiv/libOpenflow v0.0.0-20210521033357-6b49eccb12e0/go.mod h1:DtsPlJOByJZ+MO9YITEGUlbJ/jfh/ef0qeNyBYaeNR4=
 github.com/contiv/libovsdb v0.0.0-20170227191248-d0061a53e358 h1:AiA9SKyNXulsU7aAnyka3UFHYOIH00A9HvdIRnDXlg0=
 github.com/contiv/libovsdb v0.0.0-20170227191248-d0061a53e358/go.mod h1:+qKEHaNVPj+wrn5st7TEFH9wcUWCJq5ZBvVKPQwzAeg=
 github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
@@ -567,8 +569,9 @@ github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjM
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
-github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
 github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
+github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
 github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
@@ -601,8 +604,9 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
-github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
 github.com/ti-mo/conntrack v0.3.0 h1:572/72R9la2FVvO6CbsLiCmR48U3pgCvIlLKoUrExDU=
 github.com/ti-mo/conntrack v0.3.0/go.mod h1:tPSYNx21TnjxGz99pLD/lAN4fuEViaJZz+pliMqnovk=
@@ -624,8 +628,6 @@ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7Zo
 github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
 github.com/vmware/go-ipfix v0.5.4 h1:n7TssKO8D4E3qpFmO6eDs7yU9Mr4fSbLFC+GstPU8kw=
 github.com/vmware/go-ipfix v0.5.4/go.mod h1:yzbG1rv+yJ8GeMrRm+MDhOV3akygNZUHLhC1pDoD2AY=
-github.com/wenyingd/ofnet v0.0.0-20210526054554-3e71e19fd0cf h1:EEGpnM6W07pq2nKdqk+lig1Qit5f8eUe+Vt1ditTLgk=
-github.com/wenyingd/ofnet v0.0.0-20210526054554-3e71e19fd0cf/go.mod h1:tZiqxY3POhek8GrqcmU+5bvVzDwY1zZ7Wh9+zwaoV3s=
 github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
 github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
diff --git a/hack/update-codegen-dockerized.sh b/hack/update-codegen-dockerized.sh
index c9895d6a2..6fe3213ff 100755
--- a/hack/update-codegen-dockerized.sh
+++ b/hack/update-codegen-dockerized.sh
@@ -115,7 +115,6 @@ $GOPATH/bin/client-gen \
   --clientset-name versioned \
   --input-base "${ANTREA_PKG}/pkg/legacyapis/" \
   --input "clusterinformation/v1beta1" \
-  --input "controlplane/v1beta1" \
   --input "controlplane/v1beta2" \
   --input "system/v1beta1" \
   --input "security/v1alpha1" \
diff --git a/pkg/agent/controller/egress/egress_controller.go b/pkg/agent/controller/egress/egress_controller.go
index dda8d89c7..3061caeb4 100644
--- a/pkg/agent/controller/egress/egress_controller.go
+++ b/pkg/agent/controller/egress/egress_controller.go
@@ -32,6 +32,7 @@ import (
 	"k8s.io/apimachinery/pkg/watch"
 	coreinformers "k8s.io/client-go/informers/core/v1"
 	"k8s.io/client-go/tools/cache"
+	"k8s.io/client-go/util/retry"
 	"k8s.io/client-go/util/workqueue"
 	"k8s.io/klog/v2"
 
@@ -521,15 +522,34 @@ func (c *EgressController) unbindPodEgress(pod, egress string) (string, bool) {
 	return "", false
 }
 
-func (c *EgressController) updateEgressStatus(egress *crdv1a2.Egress, nodeName string) error {
-	if egress.Status.EgressNode == nodeName {
-		return nil
-	}
-	klog.V(2).InfoS("Updating Egress status", "Egress", egress.Name, "oldNode", egress.Status.EgressNode, "newNode", nodeName)
+func (c *EgressController) updateEgressStatus(egress *crdv1a2.Egress, isLocal bool) error {
 	toUpdate := egress.DeepCopy()
-	toUpdate.Status.EgressNode = nodeName
-	if _, err := c.crdClient.CrdV1alpha2().Egresses().UpdateStatus(context.TODO(), toUpdate, metav1.UpdateOptions{}); err != nil {
-		return fmt.Errorf("updating Egress %s status error: %v", egress.Name, err)
+	var updateErr, getErr error
+	if err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
+		if isLocal {
+			// Do nothing if the current EgressNode in status is already this Node.
+			if toUpdate.Status.EgressNode == c.nodeName {
+				return nil
+			}
+			toUpdate.Status.EgressNode = c.nodeName
+		} else {
+			// Do nothing if the current EgressNode in status is not this Node.
+			if toUpdate.Status.EgressNode != c.nodeName {
+				return nil
+			}
+			toUpdate.Status.EgressNode = ""
+		}
+		klog.V(2).InfoS("Updating Egress status", "Egress", egress.Name, "oldNode", egress.Status.EgressNode, "newNode", toUpdate.Status.EgressNode)
+		_, updateErr = c.crdClient.CrdV1alpha2().Egresses().UpdateStatus(context.TODO(), toUpdate, metav1.UpdateOptions{})
+		if updateErr != nil && errors.IsConflict(updateErr) {
+			if toUpdate, getErr = c.crdClient.CrdV1alpha2().Egresses().Get(context.TODO(), egress.Name, metav1.GetOptions{}); getErr != nil {
+				return getErr
+			}
+		}
+		// Return the error from UPDATE.
+		return updateErr
+	}); err != nil {
+		return err
 	}
 	klog.V(2).InfoS("Updated Egress status", "Egress", egress.Name)
 	metrics.AntreaEgressStatusUpdates.Inc()
@@ -584,9 +604,6 @@ func (c *EgressController) syncEgress(egressName string) error {
 		if err := c.ipAssigner.AssignIP(egress.Spec.EgressIP); err != nil {
 			return err
 		}
-		if err := c.updateEgressStatus(egress, c.nodeName); err != nil {
-			return err
-		}
 	} else {
 		// Unassign the Egress IP from the local Node if it was assigned by the agent.
 		if err := c.ipAssigner.UnassignIP(egress.Spec.EgressIP); err != nil {
@@ -610,6 +627,10 @@ func (c *EgressController) syncEgress(egressName string) error {
 		eState.mark = mark
 	}
 
+	if err := c.updateEgressStatus(egress, c.localIPDetector.IsLocalIP(egress.Spec.EgressIP)); err != nil {
+		return fmt.Errorf("update Egress %s status error: %v", egressName, err)
+	}
+
 	// Copy the previous ofPorts and Pods. They will be used to identify stale ofPorts and Pods.
 	staleOFPorts := eState.ofPorts.Union(nil)
 	stalePods := eState.pods.Union(nil)
diff --git a/pkg/agent/controller/networkpolicy/packetin.go b/pkg/agent/controller/networkpolicy/packetin.go
index 233a4dc38..8657c633b 100644
--- a/pkg/agent/controller/networkpolicy/packetin.go
+++ b/pkg/agent/controller/networkpolicy/packetin.go
@@ -23,9 +23,9 @@ import (
 	"path/filepath"
 	"time"
 
-	"github.com/contiv/libOpenflow/openflow13"
-	"github.com/contiv/libOpenflow/protocol"
-	"github.com/contiv/ofnet/ofctrl"
+	"antrea.io/libOpenflow/openflow13"
+	"antrea.io/libOpenflow/protocol"
+	"antrea.io/ofnet/ofctrl"
 	"github.com/vmware/go-ipfix/pkg/registry"
 	"gopkg.in/natefinch/lumberjack.v2"
 	"k8s.io/klog/v2"
diff --git a/pkg/agent/controller/traceflow/packetin.go b/pkg/agent/controller/traceflow/packetin.go
index 474baecde..63c7ae6e4 100644
--- a/pkg/agent/controller/traceflow/packetin.go
+++ b/pkg/agent/controller/traceflow/packetin.go
@@ -21,9 +21,9 @@ import (
 	"net"
 	"time"
 
-	"github.com/contiv/libOpenflow/openflow13"
-	"github.com/contiv/libOpenflow/protocol"
-	"github.com/contiv/ofnet/ofctrl"
+	"antrea.io/libOpenflow/openflow13"
+	"antrea.io/libOpenflow/protocol"
+	"antrea.io/ofnet/ofctrl"
 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/client-go/util/retry"
 	"k8s.io/klog/v2"
diff --git a/pkg/agent/controller/traceflow/traceflow_controller.go b/pkg/agent/controller/traceflow/traceflow_controller.go
index e14730c63..79ad1b9a6 100644
--- a/pkg/agent/controller/traceflow/traceflow_controller.go
+++ b/pkg/agent/controller/traceflow/traceflow_controller.go
@@ -23,7 +23,7 @@ import (
 	"sync"
 	"time"
 
-	"github.com/contiv/libOpenflow/protocol"
+	"antrea.io/libOpenflow/protocol"
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
diff --git a/pkg/agent/flowexporter/connections/connections.go b/pkg/agent/flowexporter/connections/connections.go
index 9fe0ddefa..b6af4ea03 100644
--- a/pkg/agent/flowexporter/connections/connections.go
+++ b/pkg/agent/flowexporter/connections/connections.go
@@ -17,6 +17,7 @@ package connections
 import (
 	"fmt"
 	"sync"
+	"time"
 
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/klog/v2"
@@ -26,21 +27,28 @@ import (
 	"antrea.io/antrea/pkg/agent/proxy"
 )
 
+const (
+	periodicDeleteInterval = time.Minute
+)
+
 type connectionStore struct {
-	connections   map[flowexporter.ConnectionKey]*flowexporter.Connection
-	ifaceStore    interfacestore.InterfaceStore
-	antreaProxier proxy.Proxier
-	mutex         sync.Mutex
+	connections            map[flowexporter.ConnectionKey]*flowexporter.Connection
+	ifaceStore             interfacestore.InterfaceStore
+	antreaProxier          proxy.Proxier
+	staleConnectionTimeout time.Duration
+	mutex                  sync.Mutex
 }
 
 func NewConnectionStore(
 	ifaceStore interfacestore.InterfaceStore,
 	proxier proxy.Proxier,
+	staleConnectionTimeout time.Duration,
 ) connectionStore {
 	return connectionStore{
-		connections:   make(map[flowexporter.ConnectionKey]*flowexporter.Connection),
-		ifaceStore:    ifaceStore,
-		antreaProxier: proxier,
+		connections:            make(map[flowexporter.ConnectionKey]*flowexporter.Connection),
+		ifaceStore:             ifaceStore,
+		antreaProxier:          proxier,
+		staleConnectionTimeout: staleConnectionTimeout,
 	}
 }
 
diff --git a/pkg/agent/flowexporter/connections/conntrack_connections.go b/pkg/agent/flowexporter/connections/conntrack_connections.go
index 61580931e..265486672 100644
--- a/pkg/agent/flowexporter/connections/conntrack_connections.go
+++ b/pkg/agent/flowexporter/connections/conntrack_connections.go
@@ -57,6 +57,7 @@ func NewConntrackConnectionStore(
 	proxier proxy.Proxier,
 	npQuerier querier.AgentNetworkPolicyInfoQuerier,
 	pollInterval time.Duration,
+	staleConnectionTimeout time.Duration,
 ) *ConntrackConnectionStore {
 	return &ConntrackConnectionStore{
 		flowRecords:          flowRecords,
@@ -65,7 +66,7 @@ func NewConntrackConnectionStore(
 		v6Enabled:            v6Enabled,
 		networkPolicyQuerier: npQuerier,
 		pollInterval:         pollInterval,
-		connectionStore:      NewConnectionStore(ifaceStore, proxier),
+		connectionStore:      NewConnectionStore(ifaceStore, proxier, staleConnectionTimeout),
 	}
 }
 
@@ -100,12 +101,28 @@ func (cs *ConntrackConnectionStore) Run(stopCh <-chan struct{}) {
 // TODO: As optimization, only poll invalid/closed connections during every poll, and poll the established connections right before the export.
 func (cs *ConntrackConnectionStore) Poll() ([]int, error) {
 	klog.V(2).Infof("Polling conntrack")
-	// Reset IsPresent flag for all connections in connection map before dumping flows in conntrack module.
-	// if the connection does not exist in conntrack table and has been exported, we will delete it from connection map.
+	// Reset IsPresent flag for all connections in connection map before dumping
+	// flows in conntrack module. If the connection does not exist in conntrack
+	// table and has been exported, then we will delete it from connection map.
+	// In addition, if the connection was not exported for a specific time period,
+	// then we consider it to be stale and delete it.
 	deleteIfStaleOrResetConn := func(key flowexporter.ConnectionKey, conn *flowexporter.Connection) error {
-		if !conn.IsPresent && conn.DyingAndDoneExport {
-			if err := cs.DeleteConnWithoutLock(key); err != nil {
-				return err
+		if !conn.IsPresent {
+			if conn.DyingAndDoneExport {
+				if err := cs.DeleteConnWithoutLock(key); err != nil {
+					return err
+				}
+			} else {
+				record, exists := cs.flowRecords.GetFlowRecordFromMap(&key)
+				if exists {
+					// Delete the connection if it was not exported for the time
+					// period as specified by the stale connection timeout.
+					if time.Since(record.LastExportTime) >= cs.staleConnectionTimeout {
+						// Ignore error if flow record not found.
+						cs.flowRecords.DeleteFlowRecordFromMap(&key)
+						delete(cs.connections, key)
+					}
+				}
 			}
 		} else {
 			conn.IsPresent = false
diff --git a/pkg/agent/flowexporter/connections/deny_connections.go b/pkg/agent/flowexporter/connections/deny_connections.go
index d7709868b..e422cf8b0 100644
--- a/pkg/agent/flowexporter/connections/deny_connections.go
+++ b/pkg/agent/flowexporter/connections/deny_connections.go
@@ -32,9 +32,31 @@ type DenyConnectionStore struct {
 }
 
 func NewDenyConnectionStore(ifaceStore interfacestore.InterfaceStore,
-	proxier proxy.Proxier) *DenyConnectionStore {
+	proxier proxy.Proxier, staleConnectionTimeout time.Duration) *DenyConnectionStore {
 	return &DenyConnectionStore{
-		connectionStore: NewConnectionStore(ifaceStore, proxier),
+		connectionStore: NewConnectionStore(ifaceStore, proxier, staleConnectionTimeout),
+	}
+}
+
+func (ds *DenyConnectionStore) RunPeriodicDeletion(stopCh <-chan struct{}) {
+	pollTicker := time.NewTicker(periodicDeleteInterval)
+	defer pollTicker.Stop()
+
+	for {
+		select {
+		case <-stopCh:
+			break
+		case <-pollTicker.C:
+			deleteIfStaleConn := func(key flowexporter.ConnectionKey, conn *flowexporter.Connection) error {
+				// Delete the connection if it was not exported in last five minutes.
+				if time.Since(conn.LastExportTime) >= ds.staleConnectionTimeout {
+					delete(ds.connections, key)
+				}
+				return nil
+			}
+			ds.ForAllConnectionsDo(deleteIfStaleConn)
+			klog.V(2).Infof("Stale connections in the Deny Connection Store are successfully deleted.")
+		}
 	}
 }
 
diff --git a/pkg/agent/flowexporter/flowrecords/flow_records.go b/pkg/agent/flowexporter/flowrecords/flow_records.go
index 1c8a61e99..1e76444c8 100644
--- a/pkg/agent/flowexporter/flowrecords/flow_records.go
+++ b/pkg/agent/flowexporter/flowrecords/flow_records.go
@@ -15,6 +15,7 @@
 package flowrecords
 
 import (
+	"fmt"
 	"sync"
 	"time"
 
@@ -100,8 +101,7 @@ func (fr *FlowRecords) AddFlowRecordWithoutLock(connKey *flowexporter.Connection
 	fr.recordsMap[*connKey] = *record
 }
 
-// GetFlowRecordFromMap gets the flow record from record map given connection key.
-// This is used only for unit tests.
+// GetFlowRecordFromMap gets the flow record from record map given the connection key.
 func (fr *FlowRecords) GetFlowRecordFromMap(connKey *flowexporter.ConnectionKey) (*flowexporter.FlowRecord, bool) {
 	fr.mutex.Lock()
 	defer fr.mutex.Unlock()
@@ -109,6 +109,18 @@ func (fr *FlowRecords) GetFlowRecordFromMap(connKey *flowexporter.ConnectionKey)
 	return &record, exists
 }
 
+// DeleteFlowRecordFromMap deletes the flow record from record map given the connection key.
+func (fr *FlowRecords) DeleteFlowRecordFromMap(connKey *flowexporter.ConnectionKey) error {
+	fr.mutex.Lock()
+	defer fr.mutex.Unlock()
+	_, exists := fr.recordsMap[*connKey]
+	if !exists {
+		return fmt.Errorf("record with key %v doesn't exist in map", connKey)
+	}
+	delete(fr.recordsMap, *connKey)
+	return nil
+}
+
 // ValidateAndUpdateStats validates and updates the flow record given the connection
 // key. Caller is expected to grab lock.
 func (fr *FlowRecords) ValidateAndUpdateStats(connKey flowexporter.ConnectionKey, record flowexporter.FlowRecord) {
@@ -136,3 +148,16 @@ func (fr *FlowRecords) ForAllFlowRecordsDo(callback flowexporter.FlowRecordCallB
 	}
 	return nil
 }
+
+// ForAllFlowRecordsDoWithoutLock executes the callback for all records in the flow
+// record map. This is used in the perf testing.
+func (fr *FlowRecords) ForAllFlowRecordsDoWithoutLock(callback flowexporter.FlowRecordCallBack) error {
+	for k, v := range fr.recordsMap {
+		err := callback(k, v)
+		if err != nil {
+			klog.Errorf("Error when executing callback for flow record: %v", err)
+			return err
+		}
+	}
+	return nil
+}
diff --git a/pkg/agent/openflow/client.go b/pkg/agent/openflow/client.go
index 1daa6375b..c00bec3be 100644
--- a/pkg/agent/openflow/client.go
+++ b/pkg/agent/openflow/client.go
@@ -19,7 +19,7 @@ import (
 	"math/rand"
 	"net"
 
-	"github.com/contiv/libOpenflow/protocol"
+	"antrea.io/libOpenflow/protocol"
 	"k8s.io/klog/v2"
 
 	"antrea.io/antrea/pkg/agent/config"
diff --git a/pkg/agent/openflow/packetin.go b/pkg/agent/openflow/packetin.go
index 0ea767018..7874f120c 100644
--- a/pkg/agent/openflow/packetin.go
+++ b/pkg/agent/openflow/packetin.go
@@ -17,7 +17,7 @@ package openflow
 import (
 	"fmt"
 
-	"github.com/contiv/ofnet/ofctrl"
+	"antrea.io/ofnet/ofctrl"
 	"golang.org/x/time/rate"
 	"k8s.io/klog/v2"
 
diff --git a/pkg/agent/openflow/pipeline.go b/pkg/agent/openflow/pipeline.go
index 1819e8db4..9028f263a 100644
--- a/pkg/agent/openflow/pipeline.go
+++ b/pkg/agent/openflow/pipeline.go
@@ -24,8 +24,8 @@ import (
 	"sync"
 	"time"
 
-	"github.com/contiv/libOpenflow/protocol"
-	"github.com/contiv/ofnet/ofctrl"
+	"antrea.io/libOpenflow/protocol"
+	"antrea.io/ofnet/ofctrl"
 	"k8s.io/client-go/tools/cache"
 	"k8s.io/klog/v2"
 
diff --git a/pkg/apiserver/apiserver.go b/pkg/apiserver/apiserver.go
index 73ac0b48a..14375d263 100644
--- a/pkg/apiserver/apiserver.go
+++ b/pkg/apiserver/apiserver.go
@@ -206,12 +206,6 @@ func installAPIGroup(s *APIServer, c completedConfig) error {
 
 	// legacy groups
 	legacyCPGroup := genericapiserver.NewDefaultAPIGroupInfo(legacycontrolplane.GroupName, Scheme, metav1.ParameterCodec, Codecs)
-	legacyCPv1beta1Storage := map[string]rest.Storage{}
-	legacyCPv1beta1Storage["addressgroups"] = addressGroupStorage
-	legacyCPv1beta1Storage["appliedtogroups"] = appliedToGroupStorage
-	legacyCPv1beta1Storage["networkpolicies"] = networkPolicyStorage
-	legacyCPv1beta1Storage["nodestatssummaries"] = nodeStatsSummaryStorage
-	legacyCPGroup.VersionedResourcesStorageMap["v1beta1"] = legacyCPv1beta1Storage
 	legacyCPv1beta2Storage := map[string]rest.Storage{}
 	legacyCPv1beta2Storage["addressgroups"] = addressGroupStorage
 	legacyCPv1beta2Storage["appliedtogroups"] = appliedToGroupStorage
@@ -268,6 +262,7 @@ func CleanupDeprecatedAPIServices(aggregatorClient clientset.Interface) error {
 	// Also check: https://github.com/antrea-io/antrea/issues/494
 	deprecatedAPIServices := []string{
 		"v1beta1.networking.antrea.tanzu.vmware.com",
+		"v1beta1.controlplane.antrea.tanzu.vmware.com",
 	}
 	for _, as := range deprecatedAPIServices {
 		err := aggregatorClient.ApiregistrationV1().APIServices().Delete(context.TODO(), as, metav1.DeleteOptions{})
diff --git a/pkg/apiserver/certificate/cacert_controller.go b/pkg/apiserver/certificate/cacert_controller.go
index 9ababa312..59a150b59 100644
--- a/pkg/apiserver/certificate/cacert_controller.go
+++ b/pkg/apiserver/certificate/cacert_controller.go
@@ -49,7 +49,6 @@ var (
 	// apiServiceNames contains all the APIServices backed by antrea-controller.
 	apiServiceNames = []string{
 		"v1alpha1.stats.antrea.tanzu.vmware.com",
-		"v1beta1.controlplane.antrea.tanzu.vmware.com",
 		"v1beta2.controlplane.antrea.tanzu.vmware.com",
 		"v1beta1.system.antrea.tanzu.vmware.com",
 		"v1alpha1.stats.antrea.io",
diff --git a/pkg/legacyapis/controlplane/install/install.go b/pkg/legacyapis/controlplane/install/install.go
index f2ade9406..aacc222b0 100644
--- a/pkg/legacyapis/controlplane/install/install.go
+++ b/pkg/legacyapis/controlplane/install/install.go
@@ -19,14 +19,12 @@ import (
 	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
 
 	"antrea.io/antrea/pkg/legacyapis/controlplane"
-	"antrea.io/antrea/pkg/legacyapis/controlplane/v1beta1"
 	"antrea.io/antrea/pkg/legacyapis/controlplane/v1beta2"
 )
 
 // Install registers the API group and adds types to a scheme
 func Install(scheme *runtime.Scheme) {
 	utilruntime.Must(controlplane.AddToScheme(scheme))
-	utilruntime.Must(v1beta1.AddToScheme(scheme))
 	utilruntime.Must(v1beta2.AddToScheme(scheme))
-	utilruntime.Must(scheme.SetVersionPriority(v1beta2.SchemeGroupVersion, v1beta1.SchemeGroupVersion))
+	utilruntime.Must(scheme.SetVersionPriority(v1beta2.SchemeGroupVersion))
 }
diff --git a/pkg/legacyapis/controlplane/v1beta1/conversion.go b/pkg/legacyapis/controlplane/v1beta1/conversion.go
deleted file mode 100644
index 4952f2aff..000000000
--- a/pkg/legacyapis/controlplane/v1beta1/conversion.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// 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 v1beta1
-
-import (
-	"fmt"
-
-	"k8s.io/apimachinery/pkg/runtime"
-)
-
-func init() {
-	localSchemeBuilder.Register(addConversionFuncs)
-}
-
-// addConversionFuncs adds non-generated conversion functions to the given scheme.
-func addConversionFuncs(scheme *runtime.Scheme) error {
-	for _, kind := range []string{"AppliedToGroup", "AddressGroup", "NetworkPolicy"} {
-		err := scheme.AddFieldLabelConversionFunc(SchemeGroupVersion.WithKind(kind),
-			func(label, value string) (string, string, error) {
-				switch label {
-				// Antrea Agents select resources by nodeName.
-				case "metadata.name", "nodeName":
-					return label, value, nil
-				default:
-					return "", "", fmt.Errorf("field label not supported: %s", label)
-				}
-			},
-		)
-		if err != nil {
-			return err
-		}
-	}
-	return nil
-}
diff --git a/pkg/legacyapis/controlplane/v1beta1/doc.go b/pkg/legacyapis/controlplane/v1beta1/doc.go
deleted file mode 100644
index 7d3b0c0f2..000000000
--- a/pkg/legacyapis/controlplane/v1beta1/doc.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2019 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.
-
-// +k8s:openapi-gen=true
-// +k8s:deepcopy-gen=package
-// +k8s:protobuf-gen=package
-// +k8s:conversion-gen=antrea.io/antrea/pkg/apis/controlplane
-// +groupName=controlplane.antrea.tanzu.vmware.com
-
-// Package v1beta1 is the v1beta1 version of the Antrea NetworkPolicy API messages.
-package v1beta1
diff --git a/pkg/legacyapis/controlplane/v1beta1/register.go b/pkg/legacyapis/controlplane/v1beta1/register.go
deleted file mode 100644
index 0bbb06083..000000000
--- a/pkg/legacyapis/controlplane/v1beta1/register.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2019 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 v1beta1
-
-import (
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/runtime"
-	"k8s.io/apimachinery/pkg/runtime/schema"
-
-	"antrea.io/antrea/pkg/apis/controlplane/v1beta1"
-)
-
-// GroupName is the group name used in this package.
-const GroupName = "controlplane.antrea.tanzu.vmware.com"
-
-var (
-	// SchemeGroupVersion is group version used to register these objects.
-	SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"}
-)
-
-// Resource takes an unqualified resource and returns a Group qualified GroupResource.
-func Resource(resource string) schema.GroupResource {
-	return SchemeGroupVersion.WithResource(resource).GroupResource()
-}
-
-var (
-	SchemeBuilder      = runtime.NewSchemeBuilder(addKnownTypes)
-	localSchemeBuilder = &SchemeBuilder
-	AddToScheme        = localSchemeBuilder.AddToScheme
-)
-
-// Adds the list of known types to the given scheme.
-func addKnownTypes(scheme *runtime.Scheme) error {
-	scheme.AddKnownTypes(SchemeGroupVersion,
-		&v1beta1.AppliedToGroup{},
-		&v1beta1.AppliedToGroupPatch{},
-		&v1beta1.AppliedToGroupList{},
-		&v1beta1.AddressGroup{},
-		&v1beta1.AddressGroupPatch{},
-		&v1beta1.AddressGroupList{},
-		&v1beta1.NetworkPolicy{},
-		&v1beta1.NetworkPolicyList{},
-		&v1beta1.NodeStatsSummary{},
-	)
-
-	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
-	return nil
-}
diff --git a/pkg/legacyclient/clientset/versioned/clientset.go b/pkg/legacyclient/clientset/versioned/clientset.go
index be198820e..00cd6cf5f 100644
--- a/pkg/legacyclient/clientset/versioned/clientset.go
+++ b/pkg/legacyclient/clientset/versioned/clientset.go
@@ -20,7 +20,6 @@ import (
 	"fmt"
 
 	clusterinformationv1beta1 "antrea.io/antrea/pkg/legacyclient/clientset/versioned/typed/clusterinformation/v1beta1"
-	controlplanev1beta1 "antrea.io/antrea/pkg/legacyclient/clientset/versioned/typed/controlplane/v1beta1"
 	controlplanev1beta2 "antrea.io/antrea/pkg/legacyclient/clientset/versioned/typed/controlplane/v1beta2"
 	corev1alpha2 "antrea.io/antrea/pkg/legacyclient/clientset/versioned/typed/core/v1alpha2"
 	opsv1alpha1 "antrea.io/antrea/pkg/legacyclient/clientset/versioned/typed/ops/v1alpha1"
@@ -35,7 +34,6 @@ import (
 type Interface interface {
 	Discovery() discovery.DiscoveryInterface
 	ClusterinformationV1beta1() clusterinformationv1beta1.ClusterinformationV1beta1Interface
-	ControlplaneV1beta1() controlplanev1beta1.ControlplaneV1beta1Interface
 	ControlplaneV1beta2() controlplanev1beta2.ControlplaneV1beta2Interface
 	CoreV1alpha2() corev1alpha2.CoreV1alpha2Interface
 	OpsV1alpha1() opsv1alpha1.OpsV1alpha1Interface
@@ -49,7 +47,6 @@ type Interface interface {
 type Clientset struct {
 	*discovery.DiscoveryClient
 	clusterinformationV1beta1 *clusterinformationv1beta1.ClusterinformationV1beta1Client
-	controlplaneV1beta1       *controlplanev1beta1.ControlplaneV1beta1Client
 	controlplaneV1beta2       *controlplanev1beta2.ControlplaneV1beta2Client
 	coreV1alpha2              *corev1alpha2.CoreV1alpha2Client
 	opsV1alpha1               *opsv1alpha1.OpsV1alpha1Client
@@ -63,11 +60,6 @@ func (c *Clientset) ClusterinformationV1beta1() clusterinformationv1beta1.Cluste
 	return c.clusterinformationV1beta1
 }
 
-// ControlplaneV1beta1 retrieves the ControlplaneV1beta1Client
-func (c *Clientset) ControlplaneV1beta1() controlplanev1beta1.ControlplaneV1beta1Interface {
-	return c.controlplaneV1beta1
-}
-
 // ControlplaneV1beta2 retrieves the ControlplaneV1beta2Client
 func (c *Clientset) ControlplaneV1beta2() controlplanev1beta2.ControlplaneV1beta2Interface {
 	return c.controlplaneV1beta2
@@ -123,10 +115,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
 	if err != nil {
 		return nil, err
 	}
-	cs.controlplaneV1beta1, err = controlplanev1beta1.NewForConfig(&configShallowCopy)
-	if err != nil {
-		return nil, err
-	}
 	cs.controlplaneV1beta2, err = controlplanev1beta2.NewForConfig(&configShallowCopy)
 	if err != nil {
 		return nil, err
@@ -164,7 +152,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
 func NewForConfigOrDie(c *rest.Config) *Clientset {
 	var cs Clientset
 	cs.clusterinformationV1beta1 = clusterinformationv1beta1.NewForConfigOrDie(c)
-	cs.controlplaneV1beta1 = controlplanev1beta1.NewForConfigOrDie(c)
 	cs.controlplaneV1beta2 = controlplanev1beta2.NewForConfigOrDie(c)
 	cs.coreV1alpha2 = corev1alpha2.NewForConfigOrDie(c)
 	cs.opsV1alpha1 = opsv1alpha1.NewForConfigOrDie(c)
@@ -180,7 +167,6 @@ func NewForConfigOrDie(c *rest.Config) *Clientset {
 func New(c rest.Interface) *Clientset {
 	var cs Clientset
 	cs.clusterinformationV1beta1 = clusterinformationv1beta1.New(c)
-	cs.controlplaneV1beta1 = controlplanev1beta1.New(c)
 	cs.controlplaneV1beta2 = controlplanev1beta2.New(c)
 	cs.coreV1alpha2 = corev1alpha2.New(c)
 	cs.opsV1alpha1 = opsv1alpha1.New(c)
diff --git a/pkg/legacyclient/clientset/versioned/fake/clientset_generated.go b/pkg/legacyclient/clientset/versioned/fake/clientset_generated.go
index a77022d51..2fde5875a 100644
--- a/pkg/legacyclient/clientset/versioned/fake/clientset_generated.go
+++ b/pkg/legacyclient/clientset/versioned/fake/clientset_generated.go
@@ -20,8 +20,6 @@ import (
 	clientset "antrea.io/antrea/pkg/legacyclient/clientset/versioned"
 	clusterinformationv1beta1 "antrea.io/antrea/pkg/legacyclient/clientset/versioned/typed/clusterinformation/v1beta1"
 	fakeclusterinformationv1beta1 "antrea.io/antrea/pkg/legacyclient/clientset/versioned/typed/clusterinformation/v1beta1/fake"
-	controlplanev1beta1 "antrea.io/antrea/pkg/legacyclient/clientset/versioned/typed/controlplane/v1beta1"
-	fakecontrolplanev1beta1 "antrea.io/antrea/pkg/legacyclient/clientset/versioned/typed/controlplane/v1beta1/fake"
 	controlplanev1beta2 "antrea.io/antrea/pkg/legacyclient/clientset/versioned/typed/controlplane/v1beta2"
 	fakecontrolplanev1beta2 "antrea.io/antrea/pkg/legacyclient/clientset/versioned/typed/controlplane/v1beta2/fake"
 	corev1alpha2 "antrea.io/antrea/pkg/legacyclient/clientset/versioned/typed/core/v1alpha2"
@@ -93,11 +91,6 @@ func (c *Clientset) ClusterinformationV1beta1() clusterinformationv1beta1.Cluste
 	return &fakeclusterinformationv1beta1.FakeClusterinformationV1beta1{Fake: &c.Fake}
 }
 
-// ControlplaneV1beta1 retrieves the ControlplaneV1beta1Client
-func (c *Clientset) ControlplaneV1beta1() controlplanev1beta1.ControlplaneV1beta1Interface {
-	return &fakecontrolplanev1beta1.FakeControlplaneV1beta1{Fake: &c.Fake}
-}
-
 // ControlplaneV1beta2 retrieves the ControlplaneV1beta2Client
 func (c *Clientset) ControlplaneV1beta2() controlplanev1beta2.ControlplaneV1beta2Interface {
 	return &fakecontrolplanev1beta2.FakeControlplaneV1beta2{Fake: &c.Fake}
diff --git a/pkg/legacyclient/clientset/versioned/fake/register.go b/pkg/legacyclient/clientset/versioned/fake/register.go
index 7b0125244..bb69c2f8e 100644
--- a/pkg/legacyclient/clientset/versioned/fake/register.go
+++ b/pkg/legacyclient/clientset/versioned/fake/register.go
@@ -18,7 +18,6 @@ package fake
 
 import (
 	clusterinformationv1beta1 "antrea.io/antrea/pkg/legacyapis/clusterinformation/v1beta1"
-	controlplanev1beta1 "antrea.io/antrea/pkg/legacyapis/controlplane/v1beta1"
 	controlplanev1beta2 "antrea.io/antrea/pkg/legacyapis/controlplane/v1beta2"
 	corev1alpha2 "antrea.io/antrea/pkg/legacyapis/core/v1alpha2"
 	opsv1alpha1 "antrea.io/antrea/pkg/legacyapis/ops/v1alpha1"
@@ -37,7 +36,6 @@ var codecs = serializer.NewCodecFactory(scheme)
 
 var localSchemeBuilder = runtime.SchemeBuilder{
 	clusterinformationv1beta1.AddToScheme,
-	controlplanev1beta1.AddToScheme,
 	controlplanev1beta2.AddToScheme,
 	corev1alpha2.AddToScheme,
 	opsv1alpha1.AddToScheme,
diff --git a/pkg/legacyclient/clientset/versioned/scheme/register.go b/pkg/legacyclient/clientset/versioned/scheme/register.go
index adda86fb2..028a7a5c2 100644
--- a/pkg/legacyclient/clientset/versioned/scheme/register.go
+++ b/pkg/legacyclient/clientset/versioned/scheme/register.go
@@ -18,7 +18,6 @@ package scheme
 
 import (
 	clusterinformationv1beta1 "antrea.io/antrea/pkg/legacyapis/clusterinformation/v1beta1"
-	controlplanev1beta1 "antrea.io/antrea/pkg/legacyapis/controlplane/v1beta1"
 	controlplanev1beta2 "antrea.io/antrea/pkg/legacyapis/controlplane/v1beta2"
 	corev1alpha2 "antrea.io/antrea/pkg/legacyapis/core/v1alpha2"
 	opsv1alpha1 "antrea.io/antrea/pkg/legacyapis/ops/v1alpha1"
@@ -37,7 +36,6 @@ var Codecs = serializer.NewCodecFactory(Scheme)
 var ParameterCodec = runtime.NewParameterCodec(Scheme)
 var localSchemeBuilder = runtime.SchemeBuilder{
 	clusterinformationv1beta1.AddToScheme,
-	controlplanev1beta1.AddToScheme,
 	controlplanev1beta2.AddToScheme,
 	corev1alpha2.AddToScheme,
 	opsv1alpha1.AddToScheme,
diff --git a/pkg/legacyclient/clientset/versioned/typed/controlplane/v1beta1/controlplane_client.go b/pkg/legacyclient/clientset/versioned/typed/controlplane/v1beta1/controlplane_client.go
deleted file mode 100644
index 0f6df5614..000000000
--- a/pkg/legacyclient/clientset/versioned/typed/controlplane/v1beta1/controlplane_client.go
+++ /dev/null
@@ -1,82 +0,0 @@
-// 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.
-
-// Code generated by client-gen. DO NOT EDIT.
-
-package v1beta1
-
-import (
-	v1beta1 "antrea.io/antrea/pkg/legacyapis/controlplane/v1beta1"
-	"antrea.io/antrea/pkg/legacyclient/clientset/versioned/scheme"
-	rest "k8s.io/client-go/rest"
-)
-
-type ControlplaneV1beta1Interface interface {
-	RESTClient() rest.Interface
-}
-
-// ControlplaneV1beta1Client is used to interact with features provided by the controlplane.antrea.tanzu.vmware.com group.
-type ControlplaneV1beta1Client struct {
-	restClient rest.Interface
-}
-
-// NewForConfig creates a new ControlplaneV1beta1Client for the given config.
-func NewForConfig(c *rest.Config) (*ControlplaneV1beta1Client, error) {
-	config := *c
-	if err := setConfigDefaults(&config); err != nil {
-		return nil, err
-	}
-	client, err := rest.RESTClientFor(&config)
-	if err != nil {
-		return nil, err
-	}
-	return &ControlplaneV1beta1Client{client}, nil
-}
-
-// NewForConfigOrDie creates a new ControlplaneV1beta1Client for the given config and
-// panics if there is an error in the config.
-func NewForConfigOrDie(c *rest.Config) *ControlplaneV1beta1Client {
-	client, err := NewForConfig(c)
-	if err != nil {
-		panic(err)
-	}
-	return client
-}
-
-// New creates a new ControlplaneV1beta1Client for the given RESTClient.
-func New(c rest.Interface) *ControlplaneV1beta1Client {
-	return &ControlplaneV1beta1Client{c}
-}
-
-func setConfigDefaults(config *rest.Config) error {
-	gv := v1beta1.SchemeGroupVersion
-	config.GroupVersion = &gv
-	config.APIPath = "/apis"
-	config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
-
-	if config.UserAgent == "" {
-		config.UserAgent = rest.DefaultKubernetesUserAgent()
-	}
-
-	return nil
-}
-
-// RESTClient returns a RESTClient that is used to communicate
-// with API server by this client implementation.
-func (c *ControlplaneV1beta1Client) RESTClient() rest.Interface {
-	if c == nil {
-		return nil
-	}
-	return c.restClient
-}
diff --git a/pkg/legacyclient/clientset/versioned/typed/controlplane/v1beta1/doc.go b/pkg/legacyclient/clientset/versioned/typed/controlplane/v1beta1/doc.go
deleted file mode 100644
index c41ac51a8..000000000
--- a/pkg/legacyclient/clientset/versioned/typed/controlplane/v1beta1/doc.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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.
-
-// Code generated by client-gen. DO NOT EDIT.
-
-// This package has the automatically generated typed clients.
-package v1beta1
diff --git a/pkg/legacyclient/clientset/versioned/typed/controlplane/v1beta1/fake/doc.go b/pkg/legacyclient/clientset/versioned/typed/controlplane/v1beta1/fake/doc.go
deleted file mode 100644
index 5807b680f..000000000
--- a/pkg/legacyclient/clientset/versioned/typed/controlplane/v1beta1/fake/doc.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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.
-
-// Code generated by client-gen. DO NOT EDIT.
-
-// Package fake has the automatically generated clients.
-package fake
diff --git a/pkg/legacyclient/clientset/versioned/typed/controlplane/v1beta1/fake/fake_controlplane_client.go b/pkg/legacyclient/clientset/versioned/typed/controlplane/v1beta1/fake/fake_controlplane_client.go
deleted file mode 100644
index a9feaf0b0..000000000
--- a/pkg/legacyclient/clientset/versioned/typed/controlplane/v1beta1/fake/fake_controlplane_client.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// 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.
-
-// Code generated by client-gen. DO NOT EDIT.
-
-package fake
-
-import (
-	rest "k8s.io/client-go/rest"
-	testing "k8s.io/client-go/testing"
-)
-
-type FakeControlplaneV1beta1 struct {
-	*testing.Fake
-}
-
-// RESTClient returns a RESTClient that is used to communicate
-// with API server by this client implementation.
-func (c *FakeControlplaneV1beta1) RESTClient() rest.Interface {
-	var ret *rest.RESTClient
-	return ret
-}
diff --git a/pkg/legacyclient/clientset/versioned/typed/controlplane/v1beta1/generated_expansion.go b/pkg/legacyclient/clientset/versioned/typed/controlplane/v1beta1/generated_expansion.go
deleted file mode 100644
index 54dd65ae4..000000000
--- a/pkg/legacyclient/clientset/versioned/typed/controlplane/v1beta1/generated_expansion.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// 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.
-
-// Code generated by client-gen. DO NOT EDIT.
-
-package v1beta1
diff --git a/pkg/ovs/openflow/interfaces.go b/pkg/ovs/openflow/interfaces.go
index 6a4e2af1a..b6abef246 100644
--- a/pkg/ovs/openflow/interfaces.go
+++ b/pkg/ovs/openflow/interfaces.go
@@ -18,7 +18,7 @@ import (
 	"net"
 	"time"
 
-	"github.com/contiv/ofnet/ofctrl"
+	"antrea.io/ofnet/ofctrl"
 )
 
 type Protocol string
diff --git a/pkg/ovs/openflow/ofctrl_action.go b/pkg/ovs/openflow/ofctrl_action.go
index 9f19f7f1f..4308188db 100644
--- a/pkg/ovs/openflow/ofctrl_action.go
+++ b/pkg/ovs/openflow/ofctrl_action.go
@@ -8,8 +8,8 @@ import (
 
 	utilnet "k8s.io/utils/net"
 
-	"github.com/contiv/libOpenflow/openflow13"
-	"github.com/contiv/ofnet/ofctrl"
+	"antrea.io/libOpenflow/openflow13"
+	"antrea.io/ofnet/ofctrl"
 )
 
 type ofFlowAction struct {
diff --git a/pkg/ovs/openflow/ofctrl_bridge.go b/pkg/ovs/openflow/ofctrl_bridge.go
index 458e0b851..5d5a3f992 100644
--- a/pkg/ovs/openflow/ofctrl_bridge.go
+++ b/pkg/ovs/openflow/ofctrl_bridge.go
@@ -7,8 +7,8 @@ import (
 	"sync"
 	"time"
 
-	"github.com/contiv/libOpenflow/openflow13"
-	"github.com/contiv/ofnet/ofctrl"
+	"antrea.io/libOpenflow/openflow13"
+	"antrea.io/ofnet/ofctrl"
 	"golang.org/x/time/rate"
 	"k8s.io/klog/v2"
 
diff --git a/pkg/ovs/openflow/ofctrl_builder.go b/pkg/ovs/openflow/ofctrl_builder.go
index 073a61464..d665e2749 100644
--- a/pkg/ovs/openflow/ofctrl_builder.go
+++ b/pkg/ovs/openflow/ofctrl_builder.go
@@ -19,8 +19,8 @@ import (
 	"net"
 	"strings"
 
-	"github.com/contiv/libOpenflow/openflow13"
-	"github.com/contiv/ofnet/ofctrl"
+	"antrea.io/libOpenflow/openflow13"
+	"antrea.io/ofnet/ofctrl"
 )
 
 type ofFlowBuilder struct {
diff --git a/pkg/ovs/openflow/ofctrl_flow.go b/pkg/ovs/openflow/ofctrl_flow.go
index f98157fbb..ca2297f8e 100644
--- a/pkg/ovs/openflow/ofctrl_flow.go
+++ b/pkg/ovs/openflow/ofctrl_flow.go
@@ -4,8 +4,8 @@ import (
 	"fmt"
 	"strings"
 
-	"github.com/contiv/libOpenflow/openflow13"
-	"github.com/contiv/ofnet/ofctrl"
+	"antrea.io/libOpenflow/openflow13"
+	"antrea.io/ofnet/ofctrl"
 )
 
 type FlowStates struct {
diff --git a/pkg/ovs/openflow/ofctrl_group.go b/pkg/ovs/openflow/ofctrl_group.go
index c5e3ffff1..db5f92a80 100644
--- a/pkg/ovs/openflow/ofctrl_group.go
+++ b/pkg/ovs/openflow/ofctrl_group.go
@@ -17,8 +17,8 @@ package openflow
 import (
 	"fmt"
 
-	"github.com/contiv/libOpenflow/openflow13"
-	"github.com/contiv/ofnet/ofctrl"
+	"antrea.io/libOpenflow/openflow13"
+	"antrea.io/ofnet/ofctrl"
 )
 
 type ofGroup struct {
diff --git a/pkg/ovs/openflow/ofctrl_meter.go b/pkg/ovs/openflow/ofctrl_meter.go
index f90a1b66e..cca0a53cb 100644
--- a/pkg/ovs/openflow/ofctrl_meter.go
+++ b/pkg/ovs/openflow/ofctrl_meter.go
@@ -17,9 +17,9 @@ package openflow
 import (
 	"fmt"
 
-	"github.com/contiv/libOpenflow/openflow13"
-	"github.com/contiv/libOpenflow/util"
-	"github.com/contiv/ofnet/ofctrl"
+	"antrea.io/libOpenflow/openflow13"
+	"antrea.io/libOpenflow/util"
+	"antrea.io/ofnet/ofctrl"
 )
 
 type ofMeter struct {
diff --git a/pkg/ovs/openflow/ofctrl_packetin.go b/pkg/ovs/openflow/ofctrl_packetin.go
index 247eda8a4..850ac6eef 100644
--- a/pkg/ovs/openflow/ofctrl_packetin.go
+++ b/pkg/ovs/openflow/ofctrl_packetin.go
@@ -18,9 +18,9 @@ import (
 	"encoding/binary"
 	"errors"
 
-	"github.com/contiv/libOpenflow/protocol"
-	"github.com/contiv/libOpenflow/util"
-	"github.com/contiv/ofnet/ofctrl"
+	"antrea.io/libOpenflow/protocol"
+	"antrea.io/libOpenflow/util"
+	"antrea.io/ofnet/ofctrl"
 )
 
 const (
diff --git a/pkg/ovs/openflow/ofctrl_packetout.go b/pkg/ovs/openflow/ofctrl_packetout.go
index be99618bf..a3df4bd15 100644
--- a/pkg/ovs/openflow/ofctrl_packetout.go
+++ b/pkg/ovs/openflow/ofctrl_packetout.go
@@ -19,8 +19,8 @@ import (
 	"math/rand"
 	"net"
 
-	"github.com/contiv/libOpenflow/protocol"
-	"github.com/contiv/ofnet/ofctrl"
+	"antrea.io/libOpenflow/protocol"
+	"antrea.io/ofnet/ofctrl"
 	"k8s.io/klog/v2"
 )
 
diff --git a/plugins/octant/go.mod b/plugins/octant/go.mod
index e18074595..8531711e4 100644
--- a/plugins/octant/go.mod
+++ b/plugins/octant/go.mod
@@ -11,7 +11,6 @@ require (
 
 replace (
 	antrea.io/antrea => ../../
-	github.com/contiv/ofnet => github.com/wenyingd/ofnet v0.0.0-20201109024835-6fd225d8c8d1
 	k8s.io/api => k8s.io/api v0.19.8
 	k8s.io/apimachinery => k8s.io/apimachinery v0.19.8
 	k8s.io/client-go => k8s.io/client-go v0.19.8
diff --git a/plugins/octant/go.sum b/plugins/octant/go.sum
index 47fd9090e..2083d579e 100644
--- a/plugins/octant/go.sum
+++ b/plugins/octant/go.sum
@@ -1,3 +1,5 @@
+antrea.io/libOpenflow v0.2.0/go.mod h1:CzEJZxDNAupiGxeL5VOw92PsxfyvehEAvE3PiC6gr8o=
+antrea.io/ofnet v0.1.0/go.mod h1:fLmHHD9XWeVza2pz/HEdLkGyA7pNutxlXCqodlwWQsA=
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
@@ -134,8 +136,6 @@ github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDG
 github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
 github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
 github.com/containernetworking/plugins v0.8.7/go.mod h1:R7lXeZaBzpfqapcAbHRW8/CYwm0dHzbz0XEjofx0uB0=
-github.com/contiv/libOpenflow v0.0.0-20201014051314-c1702744526c/go.mod h1:DtsPlJOByJZ+MO9YITEGUlbJ/jfh/ef0qeNyBYaeNR4=
-github.com/contiv/libOpenflow v0.0.0-20210521033357-6b49eccb12e0/go.mod h1:DtsPlJOByJZ+MO9YITEGUlbJ/jfh/ef0qeNyBYaeNR4=
 github.com/contiv/libovsdb v0.0.0-20170227191248-d0061a53e358/go.mod h1:+qKEHaNVPj+wrn5st7TEFH9wcUWCJq5ZBvVKPQwzAeg=
 github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
 github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
@@ -591,6 +591,7 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
 github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
 github.com/skratchdot/open-golang v0.0.0-20190402232053-79abb63cd66e/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
@@ -628,8 +629,9 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
-github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
 github.com/ti-mo/conntrack v0.3.0/go.mod h1:tPSYNx21TnjxGz99pLD/lAN4fuEViaJZz+pliMqnovk=
@@ -651,7 +653,6 @@ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17
 github.com/vmware-tanzu/octant v0.17.0 h1:2H2AiQU5C1RiHxxYrrOosDHHI9eV51nP+e9PjRP+c48=
 github.com/vmware-tanzu/octant v0.17.0/go.mod h1:lA32xKa6icUclg+DjAX/E/Id1cTqwCXZUem3RGEp/2A=
 github.com/vmware/go-ipfix v0.5.4/go.mod h1:yzbG1rv+yJ8GeMrRm+MDhOV3akygNZUHLhC1pDoD2AY=
-github.com/wenyingd/ofnet v0.0.0-20201109024835-6fd225d8c8d1/go.mod h1:8mMMWAYBNUeTGXYKizOLETfN3WIbu3P5DgvS2jiXKdI=
 github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
 github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=


Test patch:
diff --git a/pkg/agent/controller/egress/egress_controller_test.go b/pkg/agent/controller/egress/egress_controller_test.go
index 95502c359..31e54b7cf 100644
--- a/pkg/agent/controller/egress/egress_controller_test.go
+++ b/pkg/agent/controller/egress/egress_controller_test.go
@@ -16,6 +16,7 @@ package egress
 
 import (
 	"context"
+	"fmt"
 	"net"
 	"reflect"
 	"testing"
@@ -24,10 +25,12 @@ import (
 	"github.com/golang/mock/gomock"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
+	"k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/util/sets"
 	"k8s.io/apimachinery/pkg/util/wait"
+	k8stesting "k8s.io/client-go/testing"
 	"k8s.io/client-go/util/workqueue"
 
 	ipassignertest "antrea.io/antrea/pkg/agent/controller/egress/ipassigner/testing"
@@ -38,7 +41,6 @@ import (
 	cpv1b2 "antrea.io/antrea/pkg/apis/controlplane/v1beta2"
 	crdv1a2 "antrea.io/antrea/pkg/apis/crd/v1alpha2"
 	"antrea.io/antrea/pkg/client/clientset/versioned"
-	"antrea.io/antrea/pkg/client/clientset/versioned/fake"
 	fakeversioned "antrea.io/antrea/pkg/client/clientset/versioned/fake"
 	crdinformers "antrea.io/antrea/pkg/client/informers/externalversions"
 	"antrea.io/antrea/pkg/util/k8s"
@@ -98,7 +100,7 @@ func newFakeController(t *testing.T, initObjects []runtime.Object) *fakeControll
 	mockRouteClient := routetest.NewMockInterface(controller)
 	mockIPAssigner := ipassignertest.NewMockIPAssigner(controller)
 
-	clientset := &fake.Clientset{}
+	clientset := &fakeversioned.Clientset{}
 	crdClient := fakeversioned.NewSimpleClientset(initObjects...)
 	crdInformerFactory := crdinformers.NewSharedInformerFactory(crdClient, 0)
 	egressInformer := crdInformerFactory.Crd().V1alpha2().Egresses()
@@ -114,6 +116,7 @@ func newFakeController(t *testing.T, initObjects []runtime.Object) *fakeControll
 	egressController := &EgressController{
 		ofClient:             mockOFClient,
 		routeClient:          mockRouteClient,
+		crdClient:            crdClient,
 		antreaClientProvider: &antreaClientGetter{clientset},
 		egressInformer:       egressInformer.Informer(),
 		egressLister:         egressInformer.Lister(),
@@ -148,6 +151,7 @@ func TestSyncEgress(t *testing.T) {
 		existingEgressGroup *cpv1b2.EgressGroup
 		newEgressGroup      *cpv1b2.EgressGroup
 		newLocalIPs         sets.String
+		expectedEgresses    []*crdv1a2.Egress
 		expectedCalls       func(mockOFClient *openflowtest.MockClient, mockRouteClient *routetest.MockInterface, mockIPAssigner *ipassignertest.MockIPAssigner)
 	}{
 		{
@@ -175,6 +179,12 @@ func TestSyncEgress(t *testing.T) {
 				},
 			},
 			newLocalIPs: sets.NewString(),
+			expectedEgresses: []*crdv1a2.Egress{
+				{
+					ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"},
+					Spec:       crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1},
+				},
+			},
 			expectedCalls: func(mockOFClient *openflowtest.MockClient, mockRouteClient *routetest.MockInterface, mockIPAssigner *ipassignertest.MockIPAssigner) {
 				mockOFClient.EXPECT().InstallSNATMarkFlows(net.ParseIP(fakeLocalEgressIP1), uint32(1))
 				mockOFClient.EXPECT().InstallPodSNATFlows(uint32(1), net.ParseIP(fakeLocalEgressIP1), uint32(1))
@@ -218,6 +228,13 @@ func TestSyncEgress(t *testing.T) {
 				},
 			},
 			newLocalIPs: sets.NewString(fakeRemoteEgressIP1),
+			expectedEgresses: []*crdv1a2.Egress{
+				{
+					ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"},
+					Spec:       crdv1a2.EgressSpec{EgressIP: fakeRemoteEgressIP1},
+					Status:     crdv1a2.EgressStatus{EgressNode: fakeNode},
+				},
+			},
 			expectedCalls: func(mockOFClient *openflowtest.MockClient, mockRouteClient *routetest.MockInterface, mockIPAssigner *ipassignertest.MockIPAssigner) {
 				mockOFClient.EXPECT().InstallPodSNATFlows(uint32(1), net.ParseIP(fakeRemoteEgressIP1), uint32(0))
 				mockOFClient.EXPECT().InstallPodSNATFlows(uint32(2), net.ParseIP(fakeRemoteEgressIP1), uint32(0))
@@ -258,6 +275,13 @@ func TestSyncEgress(t *testing.T) {
 					{Pod: &cpv1b2.PodReference{Name: "pod3", Namespace: "ns3"}},
 				},
 			},
+			expectedEgresses: []*crdv1a2.Egress{
+				{
+					ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"},
+					Spec:       crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP2},
+					Status:     crdv1a2.EgressStatus{EgressNode: fakeNode},
+				},
+			},
 			expectedCalls: func(mockOFClient *openflowtest.MockClient, mockRouteClient *routetest.MockInterface, mockIPAssigner *ipassignertest.MockIPAssigner) {
 				mockOFClient.EXPECT().InstallSNATMarkFlows(net.ParseIP(fakeLocalEgressIP1), uint32(1))
 				mockOFClient.EXPECT().InstallPodSNATFlows(uint32(1), net.ParseIP(fakeLocalEgressIP1), uint32(1))
@@ -303,6 +327,12 @@ func TestSyncEgress(t *testing.T) {
 					{Pod: &cpv1b2.PodReference{Name: "pod3", Namespace: "ns3"}},
 				},
 			},
+			expectedEgresses: []*crdv1a2.Egress{
+				{
+					ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"},
+					Spec:       crdv1a2.EgressSpec{EgressIP: fakeRemoteEgressIP1},
+				},
+			},
 			expectedCalls: func(mockOFClient *openflowtest.MockClient, mockRouteClient *routetest.MockInterface, mockIPAssigner *ipassignertest.MockIPAssigner) {
 				mockOFClient.EXPECT().InstallSNATMarkFlows(net.ParseIP(fakeLocalEgressIP1), uint32(1))
 				mockOFClient.EXPECT().InstallPodSNATFlows(uint32(1), net.ParseIP(fakeLocalEgressIP1), uint32(1))
@@ -346,6 +376,13 @@ func TestSyncEgress(t *testing.T) {
 					{Pod: &cpv1b2.PodReference{Name: "pod3", Namespace: "ns3"}},
 				},
 			},
+			expectedEgresses: []*crdv1a2.Egress{
+				{
+					ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"},
+					Spec:       crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1},
+					Status:     crdv1a2.EgressStatus{EgressNode: fakeNode},
+				},
+			},
 			expectedCalls: func(mockOFClient *openflowtest.MockClient, mockRouteClient *routetest.MockInterface, mockIPAssigner *ipassignertest.MockIPAssigner) {
 				mockOFClient.EXPECT().InstallPodSNATFlows(uint32(1), net.ParseIP(fakeRemoteEgressIP1), uint32(0))
 				mockOFClient.EXPECT().InstallPodSNATFlows(uint32(2), net.ParseIP(fakeRemoteEgressIP1), uint32(0))
@@ -387,6 +424,18 @@ func TestSyncEgress(t *testing.T) {
 					{Pod: &cpv1b2.PodReference{Name: "pod3", Namespace: "ns3"}},
 				},
 			},
+			expectedEgresses: []*crdv1a2.Egress{
+				{
+					ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"},
+					Spec:       crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1},
+					Status:     crdv1a2.EgressStatus{EgressNode: fakeNode},
+				},
+				{
+					ObjectMeta: metav1.ObjectMeta{Name: "egressB", UID: "uidB"},
+					Spec:       crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP2},
+					Status:     crdv1a2.EgressStatus{EgressNode: fakeNode},
+				},
+			},
 			expectedCalls: func(mockOFClient *openflowtest.MockClient, mockRouteClient *routetest.MockInterface, mockIPAssigner *ipassignertest.MockIPAssigner) {
 				mockOFClient.EXPECT().InstallSNATMarkFlows(net.ParseIP(fakeLocalEgressIP1), uint32(1))
 				mockOFClient.EXPECT().InstallPodSNATFlows(uint32(1), net.ParseIP(fakeLocalEgressIP1), uint32(1))
@@ -426,6 +475,18 @@ func TestSyncEgress(t *testing.T) {
 					{Pod: &cpv1b2.PodReference{Name: "pod3", Namespace: "ns3"}},
 				},
 			},
+			expectedEgresses: []*crdv1a2.Egress{
+				{
+					ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"},
+					Spec:       crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1},
+					Status:     crdv1a2.EgressStatus{EgressNode: fakeNode},
+				},
+				{
+					ObjectMeta: metav1.ObjectMeta{Name: "egressB", UID: "uidB"},
+					Spec:       crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1},
+					Status:     crdv1a2.EgressStatus{EgressNode: fakeNode},
+				},
+			},
 			expectedCalls: func(mockOFClient *openflowtest.MockClient, mockRouteClient *routetest.MockInterface, mockIPAssigner *ipassignertest.MockIPAssigner) {
 				mockOFClient.EXPECT().InstallSNATMarkFlows(net.ParseIP(fakeLocalEgressIP1), uint32(1))
 				mockOFClient.EXPECT().InstallPodSNATFlows(uint32(1), net.ParseIP(fakeLocalEgressIP1), uint32(1))
@@ -470,6 +531,11 @@ func TestSyncEgress(t *testing.T) {
 			// Call it one more time to ensure it's idempotent, no extra datapath calls are supposed to be made.
 			err = c.syncEgress(tt.newEgress.Name)
 			assert.NoError(t, err)
+			for _, expectedEgress := range tt.expectedEgresses {
+				gotEgress, err := c.crdClient.CrdV1alpha2().Egresses().Get(context.TODO(), expectedEgress.Name, metav1.GetOptions{})
+				require.NoError(t, err)
+				assert.Equal(t, expectedEgress, gotEgress)
+			}
 		})
 	}
 }
@@ -624,3 +690,90 @@ func addPodInterface(ifaceStore interfacestore.InterfaceStore, podNamespace, pod
 		OVSPortConfig:            &interfacestore.OVSPortConfig{OFPort: ofPort},
 	})
 }
+
+func TestUpdateEgressStatus(t *testing.T) {
+	getError := fmt.Errorf("fake get Egress error")
+	updateConflictError := &errors.StatusError{ErrStatus: metav1.Status{Reason: metav1.StatusReasonConflict, Message: "update Egress conflict"}}
+	updateError := fmt.Errorf("update Egress error")
+	tests := []struct {
+		name                 string
+		updateErrorNum       int
+		updateError          error
+		getErrorNum          int
+		expectedUpdateCalled int
+		expectedGetCalled    int
+		expectedError        error
+	}{
+		{
+			name:                 "succeed immediately",
+			updateErrorNum:       0,
+			updateError:          nil,
+			getErrorNum:          0,
+			expectedUpdateCalled: 1,
+			expectedGetCalled:    0,
+			expectedError:        nil,
+		},
+		{
+			name:                 "succeed after one update conflict failure",
+			updateErrorNum:       1,
+			updateError:          updateConflictError,
+			getErrorNum:          0,
+			expectedUpdateCalled: 2,
+			expectedGetCalled:    1,
+			expectedError:        nil,
+		},
+		{
+			name:                 "fail after one update failure",
+			updateErrorNum:       1,
+			updateError:          updateError,
+			getErrorNum:          0,
+			expectedUpdateCalled: 1,
+			expectedGetCalled:    0,
+			expectedError:        updateError,
+		},
+		{
+			name:                 "fail after one update conflict failure and one get failure",
+			updateErrorNum:       1,
+			updateError:          updateConflictError,
+			getErrorNum:          1,
+			expectedUpdateCalled: 1,
+			expectedGetCalled:    1,
+			expectedError:        getError,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			egress := crdv1a2.Egress{
+				ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA", ResourceVersion: "fake-ResourceVersion"},
+				Spec:       crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1},
+			}
+			fakeClient := &fakeversioned.Clientset{}
+			getCalled := 0
+			fakeClient.AddReactor("get", "egresses", func(action k8stesting.Action) (bool, runtime.Object, error) {
+				getCalled += 1
+				if getCalled <= tt.getErrorNum {
+					return true, nil, getError
+				}
+				return true, &egress, nil
+			})
+			updateCalled := 0
+			fakeClient.AddReactor("update", "*", func(action k8stesting.Action) (bool, runtime.Object, error) {
+				updateCalled += 1
+				if updateCalled <= tt.updateErrorNum {
+					return true, nil, tt.updateError
+				}
+				return true, &egress, nil
+			})
+
+			c := &EgressController{crdClient: fakeClient, nodeName: fakeNode}
+			_, err := c.crdClient.CrdV1alpha2().Egresses().Create(context.TODO(), &egress, metav1.CreateOptions{})
+			assert.NoError(t, err)
+			err = c.updateEgressStatus(&egress, true)
+			if err != tt.expectedError {
+				t.Errorf("Update Egress error not match, got: %v, expected: %v", err, tt.expectedError)
+			}
+			assert.Equal(t, tt.expectedGetCalled, getCalled, "Get called num not match")
+			assert.Equal(t, tt.expectedUpdateCalled, updateCalled, "Update called num not match")
+		})
+	}
+}
diff --git a/pkg/agent/controller/networkpolicy/packetin_test.go b/pkg/agent/controller/networkpolicy/packetin_test.go
index 1d0c3f439..f92c57ac4 100644
--- a/pkg/agent/controller/networkpolicy/packetin_test.go
+++ b/pkg/agent/controller/networkpolicy/packetin_test.go
@@ -18,9 +18,9 @@ import (
 	"net"
 	"testing"
 
-	"github.com/contiv/libOpenflow/protocol"
-	"github.com/contiv/libOpenflow/util"
-	"github.com/contiv/ofnet/ofctrl"
+	"antrea.io/libOpenflow/protocol"
+	"antrea.io/libOpenflow/util"
+	"antrea.io/ofnet/ofctrl"
 	"github.com/stretchr/testify/assert"
 )
 
diff --git a/pkg/agent/controller/traceflow/packetin_test.go b/pkg/agent/controller/traceflow/packetin_test.go
index 03d752a96..96c6cceb2 100644
--- a/pkg/agent/controller/traceflow/packetin_test.go
+++ b/pkg/agent/controller/traceflow/packetin_test.go
@@ -19,9 +19,9 @@ import (
 	"reflect"
 	"testing"
 
-	"github.com/contiv/libOpenflow/protocol"
-	"github.com/contiv/libOpenflow/util"
-	"github.com/contiv/ofnet/ofctrl"
+	"antrea.io/libOpenflow/protocol"
+	"antrea.io/libOpenflow/util"
+	"antrea.io/ofnet/ofctrl"
 	"github.com/stretchr/testify/assert"
 
 	"antrea.io/antrea/pkg/agent/openflow"
diff --git a/pkg/agent/flowexporter/connections/connections_test.go b/pkg/agent/flowexporter/connections/connections_test.go
index 0c9417f9e..de21af157 100644
--- a/pkg/agent/flowexporter/connections/connections_test.go
+++ b/pkg/agent/flowexporter/connections/connections_test.go
@@ -26,7 +26,10 @@ import (
 	interfacestoretest "antrea.io/antrea/pkg/agent/interfacestore/testing"
 )
 
-const testPollInterval = 0 // Not used in these tests, hence 0.
+const (
+	testPollInterval           = 0 // Not used in these tests, hence 0.
+	testStaleConnectionTimeout = 5 * time.Minute
+)
 
 func TestConnectionStore_ForAllConnectionsDo(t *testing.T) {
 	ctrl := gomock.NewController(t)
@@ -65,7 +68,7 @@ func TestConnectionStore_ForAllConnectionsDo(t *testing.T) {
 	}
 	// Create connectionStore
 	mockIfaceStore := interfacestoretest.NewMockInterfaceStore(ctrl)
-	connStore := NewConnectionStore(mockIfaceStore, nil)
+	connStore := NewConnectionStore(mockIfaceStore, nil, testStaleConnectionTimeout)
 	// Add flows to the Connection store
 	for i, flow := range testFlows {
 		connStore.connections[*testFlowKeys[i]] = flow
diff --git a/pkg/agent/flowexporter/connections/conntrack_connections_perf_test.go b/pkg/agent/flowexporter/connections/conntrack_connections_perf_test.go
index 0dc44c4ca..21b8c490a 100644
--- a/pkg/agent/flowexporter/connections/conntrack_connections_perf_test.go
+++ b/pkg/agent/flowexporter/connections/conntrack_connections_perf_test.go
@@ -105,7 +105,7 @@ func setupConntrackConnStore(b *testing.B) (*ConntrackConnectionStore, *connecti
 
 	npQuerier := queriertest.NewMockAgentNetworkPolicyInfoQuerier(ctrl)
 
-	return NewConntrackConnectionStore(mockConnDumper, flowrecords.NewFlowRecords(), mockIfaceStore, true, false, mockProxier, npQuerier, testPollInterval), mockConnDumper
+	return NewConntrackConnectionStore(mockConnDumper, flowrecords.NewFlowRecords(), mockIfaceStore, true, false, mockProxier, npQuerier, testPollInterval, testStaleConnectionTimeout), mockConnDumper
 }
 
 func generateConns() []*flowexporter.Connection {
diff --git a/pkg/agent/flowexporter/connections/conntrack_connections_test.go b/pkg/agent/flowexporter/connections/conntrack_connections_test.go
index d33998d82..5310e08fc 100644
--- a/pkg/agent/flowexporter/connections/conntrack_connections_test.go
+++ b/pkg/agent/flowexporter/connections/conntrack_connections_test.go
@@ -200,7 +200,7 @@ func TestConntrackConnectionStore_AddOrUpdateConn(t *testing.T) {
 	mockProxier := proxytest.NewMockProxier(ctrl)
 	mockConnDumper := connectionstest.NewMockConnTrackDumper(ctrl)
 	npQuerier := queriertest.NewMockAgentNetworkPolicyInfoQuerier(ctrl)
-	conntrackConnStore := NewConntrackConnectionStore(mockConnDumper, flowrecords.NewFlowRecords(), mockIfaceStore, true, false, mockProxier, npQuerier, testPollInterval)
+	conntrackConnStore := NewConntrackConnectionStore(mockConnDumper, flowrecords.NewFlowRecords(), mockIfaceStore, true, false, mockProxier, npQuerier, testPollInterval, testStaleConnectionTimeout)
 
 	// Add flow1conn and flow3conn to the Connection map
 	testFlow1Tuple := flowexporter.NewConnectionKey(&testFlow1)
@@ -320,7 +320,7 @@ func TestConnectionStore_DeleteConnectionByKey(t *testing.T) {
 	metrics.TotalAntreaConnectionsInConnTrackTable.Set(float64(len(testFlows)))
 	// Create connectionStore
 	mockIfaceStore := interfacestoretest.NewMockInterfaceStore(ctrl)
-	connStore := NewConntrackConnectionStore(nil, flowrecords.NewFlowRecords(), mockIfaceStore, true, false, nil, nil, testPollInterval)
+	connStore := NewConntrackConnectionStore(nil, flowrecords.NewFlowRecords(), mockIfaceStore, true, false, nil, nil, testPollInterval, testStaleConnectionTimeout)
 	// Add flows to the connection store.
 	for i, flow := range testFlows {
 		connStore.connections[*testFlowKeys[i]] = flow
@@ -344,7 +344,7 @@ func TestConnectionStore_MetricSettingInPoll(t *testing.T) {
 	// Create connectionStore
 	mockIfaceStore := interfacestoretest.NewMockInterfaceStore(ctrl)
 	mockConnDumper := connectionstest.NewMockConnTrackDumper(ctrl)
-	conntrackConnStore := NewConntrackConnectionStore(mockConnDumper, flowrecords.NewFlowRecords(), mockIfaceStore, true, false, nil, nil, testPollInterval)
+	conntrackConnStore := NewConntrackConnectionStore(mockConnDumper, flowrecords.NewFlowRecords(), mockIfaceStore, true, false, nil, nil, testPollInterval, testStaleConnectionTimeout)
 	// Hard-coded conntrack occupancy metrics for test
 	TotalConnections := 0
 	MaxConnections := 300000
diff --git a/pkg/agent/flowexporter/connections/deny_connections_test.go b/pkg/agent/flowexporter/connections/deny_connections_test.go
index 8ab76f187..4492b5dca 100644
--- a/pkg/agent/flowexporter/connections/deny_connections_test.go
+++ b/pkg/agent/flowexporter/connections/deny_connections_test.go
@@ -71,7 +71,7 @@ func TestDenyConnectionStore_AddOrUpdateConn(t *testing.T) {
 	mockIfaceStore.EXPECT().GetInterfaceByIP(tuple.SourceAddress.String()).Return(nil, false)
 	mockIfaceStore.EXPECT().GetInterfaceByIP(tuple.DestinationAddress.String()).Return(nil, false)
 
-	denyConnStore := NewDenyConnectionStore(mockIfaceStore, mockProxier)
+	denyConnStore := NewDenyConnectionStore(mockIfaceStore, mockProxier, testStaleConnectionTimeout)
 
 	denyConnStore.AddOrUpdateConn(&testFlow, refTime.Add(-(time.Second * 20)), uint64(60))
 	expConn := testFlow
@@ -99,7 +99,7 @@ func TestDenyConnectionStore_DeleteConnWithoutLock(t *testing.T) {
 	metrics.InitializeConnectionMetrics()
 	// Create denyConnectionStore
 	mockIfaceStore := interfacestoretest.NewMockInterfaceStore(ctrl)
-	connStore := NewDenyConnectionStore(mockIfaceStore, nil)
+	connStore := NewDenyConnectionStore(mockIfaceStore, nil, testStaleConnectionTimeout)
 	refTime := time.Now()
 	tuple1 := flowexporter.Tuple{SourceAddress: net.IP{1, 2, 3, 4}, DestinationAddress: net.IP{4, 3, 2, 1}, Protocol: 6, SourcePort: 65280, DestinationPort: 255}
 	tuple2 := flowexporter.Tuple{SourceAddress: net.IP{1, 2, 3, 4}, DestinationAddress: net.IP{8, 7, 6, 5}, Protocol: 6, SourcePort: 65280, DestinationPort: 255}
diff --git a/pkg/agent/flowexporter/exporter/exporter_perf_test.go b/pkg/agent/flowexporter/exporter/exporter_perf_test.go
index db967c703..f6b0b70d1 100644
--- a/pkg/agent/flowexporter/exporter/exporter_perf_test.go
+++ b/pkg/agent/flowexporter/exporter/exporter_perf_test.go
@@ -128,6 +128,44 @@ func BenchmarkExportDenyConns(b *testing.B) {
 
 }
 
+/*
+go test -test.v -run=None -test.benchmem -bench=BenchmarkGetRecordAndDeleteFromMap -memprofile memprofile.out -cpuprofile profile.out
+goos: linux
+goarch: amd64
+pkg: antrea.io/antrea/pkg/agent/flowexporter/exporter
+cpu: Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
+BenchmarkGetRecordAndDeleteFromMap
+    exporter_perf_test.go:150:
+        Summary:
+        Number of conntrack connections: 100000
+         Number of dying conntrack connections: 5000
+BenchmarkGetRecordAndDeleteFromMap-2   	168049232	         6.737 ns/op	       0 B/op	       0 allocs/op
+PASS
+ok  	antrea.io/antrea/pkg/agent/flowexporter/exporter	8.707s
+Reference value:
+	#conns
+	20000   168049232	 6.737 ns/op	  0 B/op   0 allocs/op
+*/
+func BenchmarkGetRecordAndDeleteFromMap(b *testing.B) {
+	disableLogToStderr()
+	ctrl := gomock.NewController(b)
+	defer ctrl.Finish()
+
+	conntrackConnStore := connections.NewConntrackConnectionStore(nil, flowrecords.NewFlowRecords(), nil, true, false, nil, nil, 1, 1)
+	records := addConnsAndGetRecords(conntrackConnStore)
+	b.ResetTimer()
+	for n := 0; n < b.N; n++ {
+		getFlowRecordAndDelete := func(key flowexporter.ConnectionKey, record flowexporter.FlowRecord) error {
+			if _, exists := records.GetFlowRecordFromMap(&key); exists {
+				return records.DeleteFlowRecordFromMap(&key)
+			}
+			return nil
+		}
+		records.ForAllFlowRecordsDoWithoutLock(getFlowRecordAndDelete)
+	}
+	b.Logf("\nSummary:\nNumber of conntrack connections: %d\n Number of dying conntrack connections: %d\n", testNumOfConns, testNumOfDyingConns)
+}
+
 func setupExporter(isConntrackConn bool) (*flowExporter, error) {
 	var err error
 	collectorAddr, err := startLocalServer()
@@ -137,8 +175,8 @@ func setupExporter(isConntrackConn bool) (*flowExporter, error) {
 
 	// create connection store and generate connections
 	records := flowrecords.NewFlowRecords()
-	denyConnStore := connections.NewDenyConnectionStore(nil, nil)
-	conntrackConnStore := connections.NewConntrackConnectionStore(nil, flowrecords.NewFlowRecords(), nil, true, false, nil, nil, 1)
+	denyConnStore := connections.NewDenyConnectionStore(nil, nil, 0)
+	conntrackConnStore := connections.NewConntrackConnectionStore(nil, flowrecords.NewFlowRecords(), nil, true, false, nil, nil, 1, 1)
 	if isConntrackConn {
 		records = addConnsAndGetRecords(conntrackConnStore)
 	} else {
diff --git a/pkg/agent/flowexporter/exporter/exporter_test.go b/pkg/agent/flowexporter/exporter/exporter_test.go
index d5e795d21..174a4f170 100644
--- a/pkg/agent/flowexporter/exporter/exporter_test.go
+++ b/pkg/agent/flowexporter/exporter/exporter_test.go
@@ -377,7 +377,7 @@ func runSendFlowRecordTests(t *testing.T, flowExp *flowExporter, isIPv6 bool) {
 	flowExp.process = mockIPFIXExpProc
 	flowExp.ipfixSet = mockDataSet
 	mockConnDumper := connectionstest.NewMockConnTrackDumper(ctrl)
-	flowExp.conntrackConnStore = connections.NewConntrackConnectionStore(mockConnDumper, flowrecords.NewFlowRecords(), nil, !isIPv6, isIPv6, nil, nil, 1)
+	flowExp.conntrackConnStore = connections.NewConntrackConnectionStore(mockConnDumper, flowrecords.NewFlowRecords(), nil, !isIPv6, isIPv6, nil, nil, 1, 1)
 
 	tests := []struct {
 		name               string
@@ -457,7 +457,7 @@ func runSendFlowRecordTests(t *testing.T, flowExp *flowExporter, isIPv6 bool) {
 			flowExp.numDataSetsSent = 0
 
 			denyConn := getDenyConnection(isIPv6, tt.isDenyConnActive, tt.protoID)
-			flowExp.denyConnStore = connections.NewDenyConnectionStore(nil, nil)
+			flowExp.denyConnStore = connections.NewDenyConnectionStore(nil, nil, 0)
 			flowExp.denyConnStore.AddOrUpdateConn(denyConn, denyConn.LastExportTime, denyConn.DeltaBytes)
 			assert.Equal(t, getNumOfConnections(flowExp.denyConnStore), 1)
 
diff --git a/pkg/agent/openflow/client_test.go b/pkg/agent/openflow/client_test.go
index 7df57c190..7f3af062e 100644
--- a/pkg/agent/openflow/client_test.go
+++ b/pkg/agent/openflow/client_test.go
@@ -23,7 +23,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/contiv/ofnet/ofctrl"
+	"antrea.io/ofnet/ofctrl"
 	"github.com/golang/mock/gomock"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
diff --git a/pkg/ovs/openflow/ofctrl_builder_test.go b/pkg/ovs/openflow/ofctrl_builder_test.go
index 2e023eff5..e3f0d6d1e 100644
--- a/pkg/ovs/openflow/ofctrl_builder_test.go
+++ b/pkg/ovs/openflow/ofctrl_builder_test.go
@@ -18,7 +18,7 @@ import (
 	"fmt"
 	"testing"
 
-	"github.com/contiv/ofnet/ofctrl"
+	"antrea.io/ofnet/ofctrl"
 	"github.com/stretchr/testify/require"
 )
 
diff --git a/pkg/ovs/openflow/ofctrl_packetin_test.go b/pkg/ovs/openflow/ofctrl_packetin_test.go
index c358464f2..106856b43 100644
--- a/pkg/ovs/openflow/ofctrl_packetin_test.go
+++ b/pkg/ovs/openflow/ofctrl_packetin_test.go
@@ -17,8 +17,8 @@ package openflow
 import (
 	"testing"
 
-	"github.com/contiv/libOpenflow/protocol"
-	"github.com/contiv/libOpenflow/util"
+	"antrea.io/libOpenflow/protocol"
+	"antrea.io/libOpenflow/util"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 )
diff --git a/pkg/ovs/openflow/ofctrl_packetout_test.go b/pkg/ovs/openflow/ofctrl_packetout_test.go
index 5c4e583ed..ed1625a22 100644
--- a/pkg/ovs/openflow/ofctrl_packetout_test.go
+++ b/pkg/ovs/openflow/ofctrl_packetout_test.go
@@ -5,8 +5,8 @@ import (
 	"reflect"
 	"testing"
 
-	"github.com/contiv/libOpenflow/protocol"
-	"github.com/contiv/ofnet/ofctrl"
+	"antrea.io/libOpenflow/protocol"
+	"antrea.io/ofnet/ofctrl"
 )
 
 func Test_ofPacketOutBuilder_SetSrcIP(t *testing.T) {
diff --git a/pkg/ovs/openflow/testing/mock_openflow.go b/pkg/ovs/openflow/testing/mock_openflow.go
index f641eb944..3397aebac 100644
--- a/pkg/ovs/openflow/testing/mock_openflow.go
+++ b/pkg/ovs/openflow/testing/mock_openflow.go
@@ -21,7 +21,7 @@ package testing
 
 import (
 	openflow "antrea.io/antrea/pkg/ovs/openflow"
-	ofctrl "github.com/contiv/ofnet/ofctrl"
+	ofctrl "antrea.io/ofnet/ofctrl"
 	gomock "github.com/golang/mock/gomock"
 	net "net"
 	reflect "reflect"
diff --git a/test/e2e/egress_test.go b/test/e2e/egress_test.go
index 29c2928fc..5394beb8f 100644
--- a/test/e2e/egress_test.go
+++ b/test/e2e/egress_test.go
@@ -169,13 +169,23 @@ ip netns exec %[1]s /agnhost netexec
 	assertClientIP(localPod, egressNodeIP)
 	assertClientIP(remotePod, egressNodeIP)
 
+	var err error
+	err = wait.Poll(time.Millisecond*100, time.Second, func() (bool, error) {
+		egress, err = data.crdClient.CrdV1alpha2().Egresses().Get(context.TODO(), egress.Name, metav1.GetOptions{})
+		if err != nil {
+			return false, err
+		}
+		return egress.Status.EgressNode == egressNode, nil
+	})
+	assert.NoError(t, err, "Egress failed to reach expected status")
+
 	t.Log("Updating the Egress's AppliedTo to remotePod only")
 	egress.Spec.AppliedTo = v1alpha2.AppliedTo{
 		PodSelector: &metav1.LabelSelector{
 			MatchLabels: map[string]string{"antrea-e2e": remotePod},
 		},
 	}
-	egress, err := data.crdClient.CrdV1alpha2().Egresses().Update(context.TODO(), egress, metav1.UpdateOptions{})
+	egress, err = data.crdClient.CrdV1alpha2().Egresses().Update(context.TODO(), egress, metav1.UpdateOptions{})
 	if err != nil {
 		t.Fatalf("Failed to update Egress %v: %v", egress, err)
 	}
@@ -342,7 +352,7 @@ func testEgressUpdateEgressIP(t *testing.T, data *TestData) {
 			toUpdate.Spec.ExternalIPPool = newPool.Name
 			toUpdate.Spec.EgressIP = newIP
 			egress, err = data.crdClient.CrdV1alpha2().Egresses().Update(context.TODO(), toUpdate, metav1.UpdateOptions{})
-			require.NoError(t, err, "Failed to delete Egress")
+			require.NoError(t, err, "Failed to update Egress")
 
 			_, err = data.checkEgressState(egress.Name, newIP, tt.newNode, "", time.Second)
 			require.NoError(t, err)
diff --git a/test/e2e/fixtures.go b/test/e2e/fixtures.go
index e912f24b2..74af68c7b 100644
--- a/test/e2e/fixtures.go
+++ b/test/e2e/fixtures.go
@@ -119,14 +119,14 @@ func skipIfNoWindowsNodes(tb testing.TB) {
 
 func skipIfFeatureDisabled(tb testing.TB, feature featuregate.Feature, checkAgent bool, checkController bool) {
 	if checkAgent {
-		if featureGate, err := GetAgentFeatures(antreaNamespace); err != nil {
+		if featureGate, err := GetAgentFeatures(); err != nil {
 			tb.Fatalf("Cannot determine if %s is enabled in the Agent: %v", feature, err)
 		} else if !featureGate.Enabled(feature) {
 			tb.Skipf("Skipping test because %s is not enabled in the Agent", feature)
 		}
 	}
 	if checkController {
-		if featureGate, err := GetControllerFeatures(antreaNamespace); err != nil {
+		if featureGate, err := GetControllerFeatures(); err != nil {
 			tb.Fatalf("Cannot determine if %s is enabled in the Controller: %v", feature, err)
 		} else if !featureGate.Enabled(feature) {
 			tb.Skipf("Skipping test because %s is not enabled in the Controller", feature)
diff --git a/test/e2e/flowaggregator_test.go b/test/e2e/flowaggregator_test.go
index 094bfea7a..f96db55a8 100644
--- a/test/e2e/flowaggregator_test.go
+++ b/test/e2e/flowaggregator_test.go
@@ -514,6 +514,7 @@ func checkRecordsForFlows(t *testing.T, data *TestData, srcIP string, dstIP stri
 		t.Errorf("Error when running iperf3 client: %v", err)
 	}
 	bwSlice, srcPort := getBandwidthAndSourcePort(stdout)
+	require.Equal(t, 2, len(bwSlice), "bandwidth value and / or bandwidth unit are not available")
 	// bandwidth from iperf output
 	bandwidthInFloat, err := strconv.ParseFloat(bwSlice[0], 64)
 	require.NoErrorf(t, err, "Error when converting iperf bandwidth %s to float64 type", bwSlice[0])
diff --git a/test/e2e/framework.go b/test/e2e/framework.go
index cf7d43d75..dcaaf3a91 100644
--- a/test/e2e/framework.go
+++ b/test/e2e/framework.go
@@ -55,6 +55,8 @@ import (
 	"antrea.io/antrea/test/e2e/providers"
 )
 
+var AntreaConfigMap *corev1.ConfigMap
+
 const (
 	defaultTimeout  = 90 * time.Second
 	defaultInterval = 1 * time.Second
@@ -1631,7 +1633,7 @@ func (data *TestData) GetEncapMode() (config.TrafficEncapModeType, error) {
 	return config.TrafficEncapModeEncap, nil
 }
 
-func getFeatures(confName string, antreaNamespace string) (featuregate.FeatureGate, error) {
+func getFeatures(confName string) (featuregate.FeatureGate, error) {
 	featureGate := features.DefaultMutableFeatureGate.DeepCopy()
 	var cfg interface{}
 	if err := yaml.Unmarshal([]byte(AntreaConfigMap.Data[confName]), &cfg); err != nil {
@@ -1651,12 +1653,12 @@ func getFeatures(confName string, antreaNamespace string) (featuregate.FeatureGa
 	return featureGate, nil
 }
 
-func GetAgentFeatures(antreaNamespace string) (featuregate.FeatureGate, error) {
-	return getFeatures(antreaAgentConfName, antreaNamespace)
+func GetAgentFeatures() (featuregate.FeatureGate, error) {
+	return getFeatures(antreaAgentConfName)
 }
 
-func GetControllerFeatures(antreaNamespace string) (featuregate.FeatureGate, error) {
-	return getFeatures(antreaControllerConfName, antreaNamespace)
+func GetControllerFeatures() (featuregate.FeatureGate, error) {
+	return getFeatures(antreaControllerConfName)
 }
 
 func (data *TestData) GetAntreaConfigMap(antreaNamespace string) (*corev1.ConfigMap, error) {
diff --git a/test/e2e/main_test.go b/test/e2e/main_test.go
index 32aaefc14..989fd6254 100644
--- a/test/e2e/main_test.go
+++ b/test/e2e/main_test.go
@@ -22,12 +22,8 @@ import (
 	"os"
 	"testing"
 	"time"
-
-	corev1 "k8s.io/api/core/v1"
 )
 
-var AntreaConfigMap *corev1.ConfigMap
-
 // setupLogging creates a temporary directory to export the test logs if necessary. If a directory
 // was provided by the user, it checks that the directory exists.
 func (tOptions *TestOptions) setupLogging() func() {
diff --git a/test/e2e/networkpolicy_test.go b/test/e2e/networkpolicy_test.go
index 5db351f2b..c465d8b33 100644
--- a/test/e2e/networkpolicy_test.go
+++ b/test/e2e/networkpolicy_test.go
@@ -356,11 +356,11 @@ func testDefaultDenyIngressPolicy(t *testing.T, data *TestData) {
 	defer data.deleteService(service.Name)
 
 	// client1 is a host network Pod and is on the same node as the server Pod, simulating kubelet probe traffic.
-	client1Name, _, cleanupFunc := createAndWaitForPod(t, data, data.createHostNetworkBusyboxPodOnNode, "test-hostnetwork-client-", serverNode, testNamespace)
+	client1Name, _, cleanupFunc := createAndWaitForPod(t, data, data.createHostNetworkBusyboxPodOnNode, "test-hostnetwork-client-can-connect-", serverNode, testNamespace)
 	defer cleanupFunc()
 
 	// client2 is a host network Pod and is on a different node from the server Pod, accessing the server Pod via the NodePort service.
-	client2Name, _, cleanupFunc := createAndWaitForPod(t, data, data.createHostNetworkBusyboxPodOnNode, "test-hostnetwork-client-", controlPlaneNodeName(), testNamespace)
+	client2Name, _, cleanupFunc := createAndWaitForPod(t, data, data.createHostNetworkBusyboxPodOnNode, "test-hostnetwork-client-cannot-connect-", controlPlaneNodeName(), testNamespace)
 	defer cleanupFunc()
 
 	spec := &networkingv1.NetworkPolicySpec{
diff --git a/test/integration/agent/flowexporter_test.go b/test/integration/agent/flowexporter_test.go
index df96d842f..8543735ed 100644
--- a/test/integration/agent/flowexporter_test.go
+++ b/test/integration/agent/flowexporter_test.go
@@ -37,7 +37,10 @@ import (
 	queriertest "antrea.io/antrea/pkg/querier/testing"
 )
 
-const testPollInterval = 0 // Not used in the test, hence 0.
+const (
+	testPollInterval           = 0 // Not used in the test, hence 0.
+	testStaleConnectionTimeout = 5 * time.Minute
+)
 
 func createConnsForTest() ([]*flowexporter.Connection, []*flowexporter.ConnectionKey) {
 	// Reference for flow timestamp
@@ -108,7 +111,7 @@ func TestConnectionStoreAndFlowRecords(t *testing.T) {
 	ifStoreMock := interfacestoretest.NewMockInterfaceStore(ctrl)
 	npQuerier := queriertest.NewMockAgentNetworkPolicyInfoQuerier(ctrl)
 	// TODO: Enhance the integration test by testing service.
-	conntrackConnStore := connections.NewConntrackConnectionStore(connDumperMock, flowrecords.NewFlowRecords(), ifStoreMock, true, false, nil, npQuerier, testPollInterval)
+	conntrackConnStore := connections.NewConntrackConnectionStore(connDumperMock, flowrecords.NewFlowRecords(), ifStoreMock, true, false, nil, npQuerier, testPollInterval, testStaleConnectionTimeout)
 	// Expect calls for connStore.poll and other callees
 	connDumperMock.EXPECT().DumpFlows(uint16(openflow.CtZone)).Return(testConns, 0, nil)
 	connDumperMock.EXPECT().GetMaxConnections().Return(0, nil)
diff --git a/test/integration/ovs/ofctrl_test.go b/test/integration/ovs/ofctrl_test.go
index 6f9cbbdd4..ffc469bf2 100644
--- a/test/integration/ovs/ofctrl_test.go
+++ b/test/integration/ovs/ofctrl_test.go
@@ -24,7 +24,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/contiv/ofnet/ofctrl"
+	"antrea.io/ofnet/ofctrl"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 	"golang.org/x/time/rate"