Compare commits

..

72 Commits

Author SHA1 Message Date
38f18d26ec Merge pull request #892 from e0ne/ignore-not-found
[sbr]: Ignore LinkNotFoundError during cmdDel
2023-05-03 21:53:21 +02:00
e51301765c Merge pull request #891 from containernetworking/dependabot/go_modules/github.com/Microsoft/hcsshim-0.9.9
build(deps): bump github.com/Microsoft/hcsshim from 0.9.8 to 0.9.9
2023-05-03 17:26:09 +02:00
7e918412d5 [sbr]: Ignore LinkNotFoundError during cmdDel
Signed-off-by: Ivan Kolodyazhny <e0ne@e0ne.info>
2023-05-02 14:08:11 +03:00
99b475ab1a build(deps): bump github.com/Microsoft/hcsshim from 0.9.8 to 0.9.9
Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.9.8 to 0.9.9.
- [Release notes](https://github.com/Microsoft/hcsshim/releases)
- [Commits](https://github.com/Microsoft/hcsshim/compare/v0.9.8...v0.9.9)

---
updated-dependencies:
- dependency-name: github.com/Microsoft/hcsshim
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-01 03:02:09 +00:00
10b5639361 Merge pull request #885 from champtar/tuning-CHECK
tuning: fix cmdCheck when using IFNAME
2023-04-24 10:46:37 -05:00
65fe256058 Merge pull request #883 from mmorel-35/linter-2
enable govet and unparam linters
2023-04-24 17:42:55 +02:00
00b82fb666 Merge pull request #887 from champtar/route-CHECK
Fix ValidateExpectedRoute with non default routes and nil GW
2023-04-24 10:41:24 -05:00
c795a3c6b1 Merge pull request #888 from jingyuanliang/go120
Bump to golang 1.20 to pick up go1.19.6 / go1.20.1 CVE fixes
2023-04-24 17:37:28 +02:00
c10af01dfb Merge pull request #880 from maiqueb/mac-spoof-improv-read-only-required-chain-on-cni-del
bridge: read only required chain on cni del instead of the entire ruleset
2023-04-24 17:32:32 +02:00
9cf1a09835 Merge pull request #829 from tjjh89017/bridge_vlan_trunk
bridge: add vlan trunk support
2023-04-24 10:25:16 -05:00
d8fc886bf0 Bump to golang 1.20 to pick up go1.19.6 / go1.20.1 CVE fixes
Go 1.18 is already EOL and doesn't have fixes available.

Signed-off-by: Jingyuan Liang <jingyuanliang@google.com>
2023-04-21 05:21:43 +00:00
c347755f87 Fix ValidateExpectedRoute with non default routes and nil GW
Using ptp plugin with non default routes, we get the following error
when cri-o call CheckNetworkList():
```
Expected Route {Dst:{IP:198.18.128.0 Mask:ffff8000} GW:<nil>} not found in routing table
```
Using cniVersion 0.3.1 to bypass the check, we can see that the
route is added with a gateway
```
$ ip r
198.18.0.0/17 via 198.18.0.1 dev eth0 src 198.18.3.102
198.18.0.1 dev eth0 scope link src 198.18.3.102
198.18.128.0/17 via 198.18.0.1 dev eth0
```

If GW is nil only check if we have a route with a DST that matches, and
ignore the GW.

Fixes #886
Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2023-04-20 15:24:20 -04:00
5b7a263e8f tuning: fix cmdCheck when using IFNAME
Fixes: c16cff9805
Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2023-04-20 11:19:23 -04:00
135292e050 bridge, del: timeout after 55 secs of trying to list rules
Making sure the exec'ed nft command is executed in 55 secs allows for
CNI to fail early, thus preventing CRI from sending another CNI DEL
while the previous NFT call is still being processed.

This fix prevents part of the behavior described in [0], in which:
> cnv-bridge and nft comes pile up in a loop, increasing every 60, never
completes

The timeout had to be less than 60 seconds (otherwise CRI would still
trigger CNI DEL again) but large enough for this feature to have a
chance of working on older kernels (e.g. centOS 8), where it takes
longer to access even a specific chain/table.

Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
2023-04-20 11:19:07 +02:00
7dcd738d34 bridge, spoofcheck: only read the prerouting chain on CNI delete
Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
2023-04-20 10:35:42 +02:00
83fe87c5b0 build: consume specific tables/chains via go-nft
This go-nft version allows its users to only read particular
tables/chains when invoking `ReadConfig`, instead of the entire ruleset.

This will make deleting rules from a large ruleset faster, thus speeding
up CNI DELs.

Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2175041

Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
2023-04-20 10:08:18 +02:00
090af7db9a bridge: add vlan trunk support
add vlan trunk support for veth
vlan trunk only support L2 only mode without any IPAM
refer ovs-cni design
https://github.com/k8snetworkplumbingwg/ovs-cni/blob/main/pkg/plugin/plugin.go

design:
origin "vlan" option will be PVID or untagged vlan for the network.
"vlanTrunk" will setup tagged vlan for veth.

entry type:
`{ "id": 100 }` will specify only tagged vlan 100
`{ "minID": 100, "maxID": 120 }` will specify tagged vlan from 100 to
120 (include 100 and 120)
vlanTrunk is a list of above entry type, so you can use this to add
tagged vlan
`[
  { "id": 100 },
  {
    "minID": 1000,
    "maxID": 2000
  }
]`

complete config will be like this
{
  "cniVersion": "0.3.1",
  "name": "mynet",
  "type": "bridge",
  "bridge": "mynet0",
  "vlan": 100,
  "vlanTrunk": [
    { "id": 101 },
    { "minID": 1000, "maxID": 2000 },
    { "minID": 3000, "maxID": 4000 }
  ],
  "ipam": {}
}

Signed-off-by: Date Huang <date.huang@suse.com>
2023-04-19 22:55:14 +08:00
9f1f9a588b Merge pull request #875 from mlguerrero12/adddefaultvlanparam
Add parameter to disable default vlan
2023-04-17 17:47:34 +02:00
71aa710196 Merge pull request #873 from maiqueb/mac-spoof-remove-index-when-adding-rules
bridge, spoof check: remove drop rule index
2023-04-17 17:07:11 +02:00
10ddd9e454 enable govet and unparam linters
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2023-04-11 12:07:04 +02:00
4a6147a155 Merge pull request #881 from containernetworking/dependabot/go_modules/golang.org/x/sys-0.7.0 2023-04-05 19:24:31 +00:00
435ef2235d build(deps): bump golang.org/x/sys from 0.6.0 to 0.7.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.6.0 to 0.7.0.
- [Release notes](https://github.com/golang/sys/releases)
- [Commits](https://github.com/golang/sys/compare/v0.6.0...v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-05 19:14:01 +00:00
43db9cc063 Merge pull request #879 from squeed/bump-deps
go.mod: bump all deps
2023-04-05 21:13:05 +02:00
821982da1c Add parameter to disable default vlan
This new parameter allows users to remove the default vlan

Fixes: #667
Signed-off-by: Marcelo Guerrero Viveros <marguerr@redhat.com>
2023-04-05 18:20:40 +02:00
cac8230e7c bridge, spoof check: remove drop rule index
Rules are appendend by default, thus using an index is redundant.
Using an index also requires the full NFT cache, which causes a CNI ADD
to be extremely slow.

Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
2023-04-04 17:10:08 +02:00
bc5f3defe7 go.mod: bump all deps
Bump all transitive and direct dependencies.

Signed-off-by: Casey Callendrello <c1@caseyc.net>
2023-04-04 16:31:14 +02:00
47a4319462 Merge pull request #861 from containernetworking/dependabot/github_actions/actions/setup-go-4
build(deps): bump actions/setup-go from 3 to 4
2023-04-04 16:27:44 +02:00
68a661999a Merge pull request #870 from containernetworking/dependabot/github_actions/actions/stale-8
build(deps): bump actions/stale from 7 to 8
2023-04-04 16:27:10 +02:00
63235a2531 Merge pull request #878 from maiqueb/fix-ginkgo-linter-warnings
linter: fix ginkgolinter errors
2023-04-04 16:23:41 +02:00
7bbd4d19e9 linter: fix ginkgolinter errors
Use:
- `BeEmpty` instead of `HaveLen(0)`
- `Expect(x).To(BeZero())` instead of `Expect(x == 0).To(BeTrue())`

Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
2023-04-04 16:09:01 +02:00
deec68747e Merge pull request #853 from mmorel-35/ginkgolinter
enable ginkgolinter linter
2023-04-04 15:24:20 +02:00
6f6345ca05 Merge pull request #871 from mlguerrero12/fixwastedassignlinter
Fix wastedassign linter errors
2023-04-04 15:23:28 +02:00
6c0d73ecc0 Fix wastedassign linter errors
Signed-off-by: Marcelo Guerrero Viveros <marguerr@redhat.com>
2023-03-27 18:42:49 +02:00
8813bfea7b Merge pull request #855 from mmorel-35/linters
enable durationcheck,  predeclared, unconvert, unused and wastedassign linters
2023-03-27 10:53:34 -05:00
16d05ec100 Merge pull request #867 from mlguerrero12/fixlinters
Fix revive linter errors
2023-03-27 10:49:33 -05:00
086f7eb7a1 build(deps): bump actions/stale from 7 to 8
Bumps [actions/stale](https://github.com/actions/stale) from 7 to 8.
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/stale/compare/v7...v8)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-27 03:04:07 +00:00
d71d0f2da1 Fix revive linter errors
Golangci-lint is now running version 1.52.1. This introduced some errors.

Signed-off-by: Marcelo Guerrero Viveros <marguerr@redhat.com>
2023-03-24 21:04:39 +01:00
00e0d3b758 build(deps): bump actions/setup-go from 3 to 4
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 3 to 4.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-20 03:01:39 +00:00
2fb0efe8a3 enable durationcheck, predeclared, unconvert, unused and wastedassign linters
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2023-03-16 07:29:37 +01:00
3bc00017e3 Merge pull request #854 from mmorel-35/clean-linters
remove govet and gofmt from test_linux.sh
2023-03-14 11:49:37 +01:00
c0fe3b7bde remove govet and gofmt from test_linux.sh
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2023-03-13 22:47:17 +00:00
09f36a295d enable ginkgolinter linter
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2023-03-13 22:27:21 +00:00
d3ee71f240 Merge pull request #843 from mmorel-35/golangci-lint
ci(lint): setup golangci-lint
2023-03-13 22:26:32 +01:00
a02bf4b463 enable revive linter
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2023-03-13 17:59:41 +01:00
79f524689c enable gocritic linter
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2023-03-13 17:59:33 +01:00
5a7619c019 enable gosimple linter
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2023-03-13 17:59:31 +01:00
709e775b13 enable nonamedreturns linter
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2023-03-13 17:59:28 +01:00
3a04eb00bb enable ineffassign linter
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2023-03-06 11:51:40 +01:00
16ba4222bc enable contextcheck linter
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2023-03-06 11:23:07 +01:00
177e0bf2d9 enable staticcheck linter
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2023-03-02 11:06:22 +01:00
d12b81dec5 ci(lint): setup golangci-lint
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2023-03-01 06:55:40 +00:00
86e39cfe3c Merge pull request #836 from mmorel-35/yamllint
ci(lint): setup yamllint linter
2023-02-28 16:35:10 +01:00
6223674f25 ci(lint): setup yamllint linter
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2023-02-25 12:10:11 +00:00
36e1e162fa Merge pull request #812 from liornoy/ginkgov2
Update ginkgo to v2
2023-02-20 10:58:24 -06:00
286064b9ec Merge pull request #831 from mlguerrero12/fixerrorignored
Fix overwritten error var in getMTUByName
2023-02-20 10:13:34 -06:00
9ee4d3225d Fix overwritten error var in getMTUByName
this prevents the error to be lost which was causing the
panic while accesing a nil var.

Fix #830

Signed-off-by: Marcelo Guerrero Viveros <marguerr@redhat.com>
2023-02-16 12:28:17 +01:00
2d1005ec02 Update tests to utilize ginkgo/v2
This commit updates the import of ginkgo to v2 in
all of the tests.

Signed-off-by: liornoy <lnoy@redhat.com>
Co-authored-by: Sascha Grunert <sgrunert@redhat.com>
2023-02-13 21:15:18 +02:00
23c2134110 Update ginkgo to v2 in go.mod, go.sum, vendor
This commit updates ginkgo to v2.
Note that because ginkgo/v2 requires go1.18, it was
updated as well.

Signed-off-by: liornoy <lnoy@redhat.com>
Co-authored-by: Sascha Grunert <sgrunert@redhat.com>
2023-02-13 21:15:18 +02:00
fb92605570 Merge pull request #784 from mmirecki/tap-plugin
Tap plugin
2023-02-13 17:26:06 +01:00
01d0031487 Tap plugin
This PR adds a plugin to create tap devices.
The plugin adds a tap device to the container.

The plugin has a workaround for a golang netlink library
which does not allow for tap devices with no owner/group
to be created. When no tap owner/group is requested, the
plugin will fall back to using the ip tool for creating
the tap device. A fix to the golang netlink lib is pending.

Signed-off-by: mmirecki <mmirecki@redhat.com>
2023-02-13 17:14:46 +01:00
98e01b7c80 Merge pull request #824 from containernetworking/dependabot/go_modules/github.com/onsi/gomega-1.26.0
build(deps): bump github.com/onsi/gomega from 1.24.2 to 1.26.0
2023-02-13 10:09:15 -06:00
9a2f763345 build(deps): bump github.com/onsi/gomega from 1.24.2 to 1.26.0
Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.24.2 to 1.26.0.
- [Release notes](https://github.com/onsi/gomega/releases)
- [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/gomega/compare/v1.24.2...v1.26.0)

---
updated-dependencies:
- dependency-name: github.com/onsi/gomega
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 10:23:59 +00:00
98359ff8b4 Merge pull request #828 from containernetworking/dependabot/go_modules/golang.org/x/sys-0.5.0
build(deps): bump golang.org/x/sys from 0.4.0 to 0.5.0
2023-02-13 11:23:00 +01:00
29e6486154 build(deps): bump golang.org/x/sys from 0.4.0 to 0.5.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.4.0 to 0.5.0.
- [Release notes](https://github.com/golang/sys/releases)
- [Commits](https://github.com/golang/sys/compare/v0.4.0...v0.5.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 03:22:30 +00:00
bbf47c1083 Merge pull request #814 from mmirecki/macvlan_incontainermaster
Add support for in-container master for macvlans
2023-02-08 12:55:44 +01:00
5d02d91c96 Merge pull request #813 from mmirecki/ipvlan_incontainermaster
Add support for in-container master for ipvlan
2023-02-06 09:49:06 -06:00
755714d716 Merge pull request #781 from mmirecki/vlan_incontainermaster
Add support for in-container master for vlans
2023-02-06 09:47:58 -06:00
e2e14ee46f Merge pull request #821 from mccv1r0/portmapCheck
Only check or del ipv6 when an IPv6 is configured
2023-02-01 14:02:07 -06:00
fb5d195fc5 Only check ipv6 when an IPv6 is configured
Signed-off-by: Michael Cambria <mccv1r0@gmail.com>
2023-01-27 20:22:11 -05:00
ac7cf82531 Add support for in-container master for macvlans
Signed-off-by: mmirecki <mmirecki@redhat.com>
2023-01-25 12:58:28 +01:00
c798f80912 Add support for in-container master for ipvlan
Signed-off-by: mmirecki <mmirecki@redhat.com>
2023-01-25 12:11:06 +01:00
9fa80036d3 Add support for in-container master for vlans
Signed-off-by: mmirecki <mmirecki@redhat.com>
2023-01-25 11:50:12 +01:00
677 changed files with 54033 additions and 14566 deletions

View File

@ -8,4 +8,4 @@ runs:
using: 'docker'
image: 'Dockerfile'
env:
GITHUB_TOKEN: ${{ inputs.token }}
GITHUB_TOKEN: ${{ inputs.token }}

View File

@ -5,15 +5,15 @@
version: 2
updates:
- package-ecosystem: "docker" # See documentation for possible values
directory: "/.github/actions/retest-action" # Location of package manifests
- package-ecosystem: "docker" # See documentation for possible values
directory: "/.github/actions/retest-action" # Location of package manifests
schedule:
interval: "weekly"
- package-ecosystem: "github-actions" # See documentation for possible values
directory: "/" # Location of package manifests
- package-ecosystem: "github-actions" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
- package-ecosystem: "gomod" # See documentation for possible values
directory: "/" # Location of package manifests
- package-ecosystem: "gomod" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"

View File

@ -7,7 +7,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v7
- uses: actions/stale@v8
with:
stale-pr-message: 'This PR has been untouched for too long without an update. It will be closed in 7 days.'
exempt-issue-labels: 'keep'
exempt-issue-labels: 'keep'

View File

@ -4,16 +4,32 @@ name: test
on: ["push", "pull_request"]
env:
GO_VERSION: "1.18"
GO_VERSION: "1.20"
LINUX_ARCHES: "amd64 386 arm arm64 s390x mips64le ppc64le riscv64"
jobs:
build:
name: Build all linux architectures
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- name: setup go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version: ${{ env.GO_VERSION }}
- uses: actions/checkout@v3
- uses: ibiqlik/action-yamllint@v3
with:
format: auto
- uses: golangci/golangci-lint-action@v3
with:
args: -v
build:
name: Build all linux architectures
needs: lint
runs-on: ubuntu-latest
steps:
- name: setup go
uses: actions/setup-go@v4
with:
go-version: ${{ env.GO_VERSION }}
- uses: actions/checkout@v3
@ -26,9 +42,9 @@ jobs:
GOARCH=$arch ./build_linux.sh
rm bin/*
done
test-linux:
name: Run tests on Linux amd64
needs: build
runs-on: ubuntu-latest
steps:
- name: Install kernel module
@ -39,7 +55,7 @@ jobs:
run: sudo apt-get install nftables
- name: setup go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version: ${{ env.GO_VERSION }}
- name: Set up Go for root
@ -66,13 +82,13 @@ jobs:
PATH=$PATH:$(go env GOPATH)/bin
gover
goveralls -coverprofile=gover.coverprofile -service=github
test-win:
name: Build and run tests on Windows
needs: build
runs-on: windows-latest
steps:
- name: setup go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version: ${{ env.GO_VERSION }}
- uses: actions/checkout@v3

42
.golangci.yml Normal file
View File

@ -0,0 +1,42 @@
issues:
exclude-rules:
- linters:
- revive
text: "don't use ALL_CAPS in Go names; use CamelCase"
- linters:
- revive
text: " and that stutters;"
linters:
disable:
- errcheck
enable:
- contextcheck
- durationcheck
- gci
- ginkgolinter
- gocritic
- gofumpt
- gosimple
- govet
- ineffassign
- misspell
- nonamedreturns
- predeclared
- revive
- staticcheck
- unconvert
- unparam
- unused
- wastedassign
linters-settings:
gci:
sections:
- standard
- default
- prefix(github.com/containernetworking)
run:
skip-dirs:
- vendor

12
.yamllint.yml Normal file
View File

@ -0,0 +1,12 @@
extends: default
ignore: |
vendor
rules:
document-start: disable
line-length: disable
truthy:
ignore: |
.github/workflows/*.yml
.github/workflows/*.yaml

39
go.mod
View File

@ -1,9 +1,9 @@
module github.com/containernetworking/plugins
go 1.17
go 1.20
require (
github.com/Microsoft/hcsshim v0.9.6
github.com/Microsoft/hcsshim v0.9.9
github.com/alexflint/go-filemutex v1.2.0
github.com/buger/jsonparser v1.1.1
github.com/containernetworking/cni v1.1.2
@ -14,28 +14,31 @@ require (
github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5
github.com/godbus/dbus/v5 v5.1.0
github.com/mattn/go-shellwords v1.0.12
github.com/networkplumbing/go-nft v0.2.0
github.com/onsi/ginkgo v1.16.5
github.com/onsi/gomega v1.24.2
github.com/safchain/ethtool v0.2.0
github.com/networkplumbing/go-nft v0.3.0
github.com/onsi/ginkgo/v2 v2.9.2
github.com/onsi/gomega v1.27.6
github.com/opencontainers/selinux v1.11.0
github.com/safchain/ethtool v0.3.0
github.com/vishvananda/netlink v1.2.1-beta.2
golang.org/x/sys v0.4.0
golang.org/x/sys v0.7.0
)
require (
github.com/Microsoft/go-winio v0.4.17 // indirect
github.com/containerd/cgroups v1.0.1 // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/Microsoft/go-winio v0.6.0 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/google/pprof v0.0.0-20230323073829-e72429f035bd // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
go.opencensus.io v0.22.3 // indirect
golang.org/x/net v0.4.0 // indirect
golang.org/x/text v0.5.0 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/vishvananda/netns v0.0.4 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/mod v0.9.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/text v0.8.0 // indirect
golang.org/x/tools v0.7.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

135
go.sum
View File

@ -44,8 +44,9 @@ github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.4.17 h1:iT12IBVClFevaf8PuVyi3UmZOVh4OqnaLxDTW2O6j3w=
github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
@ -54,8 +55,8 @@ github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600=
github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
github.com/Microsoft/hcsshim v0.9.6 h1:VwnDOgLeoi2du6dAznfmspNqTiwczvjv4K7NxuY9jsY=
github.com/Microsoft/hcsshim v0.9.6/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
github.com/Microsoft/hcsshim v0.9.9 h1:FYrTiCNOc8ZddNBVkJBxWZYm22rgxHFmxMoGK66sDF0=
github.com/Microsoft/hcsshim v0.9.9/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
@ -125,8 +126,9 @@ github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1
github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
github.com/containerd/cgroups v1.0.1 h1:iJnMvco9XGvKUvNQkv88bE4uJXxRQH18efbKo9w5vHQ=
github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE=
@ -210,7 +212,6 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
@ -271,7 +272,6 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
@ -287,8 +287,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
@ -302,9 +302,10 @@ github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e h1:BWhy2j3IXJhjCbC68FptL43tDKIq8FladmaTs3Xs7Z8=
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
@ -324,8 +325,9 @@ github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4er
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
@ -348,8 +350,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@ -359,10 +361,10 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0=
@ -376,6 +378,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20230323073829-e72429f035bd h1:r8yyd+DJDmsUhGrRBxH5Pj7KeFK5l+Y3FsgT8keqKtk=
github.com/google/pprof v0.0.0-20230323073829-e72429f035bd/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@ -482,12 +486,11 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
github.com/networkplumbing/go-nft v0.2.0 h1:eKapmyVUt/3VGfhYaDos5yeprm+LPt881UeksmKKZHY=
github.com/networkplumbing/go-nft v0.2.0/go.mod h1:HnnM+tYvlGAsMU7yoYwXEVLLiDW9gdMmb5HoGcwpuQs=
github.com/networkplumbing/go-nft v0.3.0 h1:IIc6yHjN85KyJx21p3ZEsO0iBMYHNXux22rc9Q8TfFw=
github.com/networkplumbing/go-nft v0.3.0/go.mod h1:HnnM+tYvlGAsMU7yoYwXEVLLiDW9gdMmb5HoGcwpuQs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
@ -501,16 +504,9 @@ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU=
github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0=
github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo=
github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw=
github.com/onsi/ginkgo/v2 v2.6.1 h1:1xQPCjcqYw/J5LchOcp4/2q/jzJFjiAOc25chhnDw+Q=
github.com/onsi/ginkgo/v2 v2.6.1/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo=
github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU=
github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts=
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
@ -520,14 +516,8 @@ github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoT
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo=
github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc=
github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM=
github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM=
github.com/onsi/gomega v1.24.2 h1:J/tulyYK6JwBldPViHJReihxxZ+22FHs0piGjQAvoUE=
github.com/onsi/gomega v1.24.2/go.mod h1:gs3J10IS7Z7r7eXRoNJIrNqU4ToQukCJhFtKrWgHWnk=
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
@ -551,6 +541,8 @@ github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mo
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
@ -596,8 +588,8 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
github.com/safchain/ethtool v0.2.0 h1:dILxMBqDnQfX192cCAPjZr9v2IgVXeElHPy435Z/IdE=
github.com/safchain/ethtool v0.2.0/go.mod h1:WkKB1DnNtvsMlDmQ50sgwowDJV/hGbJSOvJoEXs1AJQ=
github.com/safchain/ethtool v0.3.0 h1:gimQJpsI6sc1yIqP/y8GYgiXn/NjgvpM0RNoWLVVmP0=
github.com/safchain/ethtool v0.3.0/go.mod h1:SA9BwrgyAqNo7M+uaL6IYbxpm5wk3L7Mm6ocLW+CJUs=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
@ -609,8 +601,9 @@ 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 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
@ -633,14 +626,19 @@ github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
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/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/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
@ -660,8 +658,8 @@ github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhg
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA=
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
@ -672,8 +670,6 @@ github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
@ -686,8 +682,9 @@ go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvS
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
@ -706,8 +703,6 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -739,10 +734,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -784,15 +777,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -809,8 +795,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -878,25 +863,13 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -904,10 +877,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -960,10 +931,8 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -1044,7 +1013,6 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@ -1063,7 +1031,6 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -4,7 +4,7 @@
// 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
// 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,
@ -14,21 +14,20 @@
package integration_test
import (
"bytes"
"fmt"
"io"
"math/rand"
"net"
"os"
"os/exec"
"path/filepath"
"bytes"
"io"
"net"
"regexp"
"strconv"
"strings"
"time"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gbytes"
"github.com/onsi/gomega/gexec"
@ -148,8 +147,8 @@ var _ = Describe("Basic PTP using cnitool", func() {
basicBridgeEnv.runInNS(hostNS, cnitoolBin, "del", "network-chain-test", contNS2.LongName())
})
Measure("limits traffic only on the restricted bandwith veth device", func(b Benchmarker) {
ipRegexp := regexp.MustCompile("10\\.1[12]\\.2\\.\\d{1,3}")
Measure("limits traffic only on the restricted bandwidth veth device", func(b Benchmarker) {
ipRegexp := regexp.MustCompile(`10\.1[12]\.2\.\d{1,3}`)
By(fmt.Sprintf("adding %s to %s\n\n", "chained-bridge-bandwidth", contNS1.ShortName()))
chainedBridgeBandwidthEnv.runInNS(hostNS, cnitoolBin, "add", "network-chain-test", contNS1.LongName())
@ -162,27 +161,24 @@ var _ = Describe("Basic PTP using cnitool", func() {
Expect(basicBridgeIP).To(ContainSubstring("10.11.2."))
var chainedBridgeBandwidthPort, basicBridgePort int
var err error
By(fmt.Sprintf("starting echo server in %s\n\n", contNS1.ShortName()))
chainedBridgeBandwidthPort, chainedBridgeBandwidthSession, err = startEchoServerInNamespace(contNS1)
Expect(err).ToNot(HaveOccurred())
chainedBridgeBandwidthPort, chainedBridgeBandwidthSession = startEchoServerInNamespace(contNS1)
By(fmt.Sprintf("starting echo server in %s\n\n", contNS2.ShortName()))
basicBridgePort, basicBridgeSession, err = startEchoServerInNamespace(contNS2)
Expect(err).ToNot(HaveOccurred())
basicBridgePort, basicBridgeSession = startEchoServerInNamespace(contNS2)
packetInBytes := 20000 // The shaper needs to 'warm'. Send enough to cause it to throttle,
// balanced by run time.
By(fmt.Sprintf("sending tcp traffic to the chained, bridged, traffic shaped container on ip address '%s:%d'\n\n", chainedBridgeIP, chainedBridgeBandwidthPort))
runtimeWithLimit := b.Time("with chained bridge and bandwidth plugins", func() {
makeTcpClientInNS(hostNS.ShortName(), chainedBridgeIP, chainedBridgeBandwidthPort, packetInBytes)
makeTCPClientInNS(hostNS.ShortName(), chainedBridgeIP, chainedBridgeBandwidthPort, packetInBytes)
})
By(fmt.Sprintf("sending tcp traffic to the basic bridged container on ip address '%s:%d'\n\n", basicBridgeIP, basicBridgePort))
runtimeWithoutLimit := b.Time("with basic bridged plugin", func() {
makeTcpClientInNS(hostNS.ShortName(), basicBridgeIP, basicBridgePort, packetInBytes)
makeTCPClientInNS(hostNS.ShortName(), basicBridgeIP, basicBridgePort, packetInBytes)
})
Expect(runtimeWithLimit).To(BeNumerically(">", runtimeWithoutLimit+1000*time.Millisecond))
@ -224,7 +220,7 @@ func (n Namespace) Del() {
(TestEnv{}).run("ip", "netns", "del", string(n))
}
func makeTcpClientInNS(netns string, address string, port int, numBytes int) {
func makeTCPClientInNS(netns string, address string, port int, numBytes int) {
payload := bytes.Repeat([]byte{'a'}, numBytes)
message := string(payload)
@ -243,7 +239,7 @@ func makeTcpClientInNS(netns string, address string, port int, numBytes int) {
Expect(string(out)).To(Equal(message))
}
func startEchoServerInNamespace(netNS Namespace) (int, *gexec.Session, error) {
func startEchoServerInNamespace(netNS Namespace) (int, *gexec.Session) {
session, err := startInNetNS(echoServerBinaryPath, netNS)
Expect(err).NotTo(HaveOccurred())
@ -260,7 +256,7 @@ func startEchoServerInNamespace(netNS Namespace) (int, *gexec.Session, error) {
io.Copy(GinkgoWriter, io.MultiReader(session.Out, session.Err))
}()
return port, session, nil
return port, session
}
func startInNetNS(binPath string, namespace Namespace) (*gexec.Session, error) {

View File

@ -4,7 +4,7 @@
// 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
// 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,
@ -17,7 +17,7 @@ import (
"strings"
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gexec"
)

View File

@ -14,7 +14,7 @@
package hns
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"testing"

View File

@ -18,7 +18,7 @@ import (
"net"
"github.com/Microsoft/hcsshim/hcn"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

View File

@ -17,7 +17,7 @@ package ip
import (
"net"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

View File

@ -47,13 +47,12 @@ func ParseIP(s string) *IP {
return nil
}
return newIP(ip, ipNet.Mask)
} else {
ip := net.ParseIP(s)
if ip == nil {
return nil
}
return newIP(ip, nil)
}
ip := net.ParseIP(s)
if ip == nil {
return nil
}
return newIP(ip, nil)
}
// ToIP will return a net.IP in standard form from this IP.

View File

@ -15,10 +15,10 @@
package ip_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestIp(t *testing.T) {

View File

@ -19,7 +19,7 @@ import (
"fmt"
"net"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
@ -124,7 +124,7 @@ var _ = Describe("IP Operations", func() {
}
for _, test := range testCases {
Expect(len(test.ip.ToIP())).To(Equal(test.expectedLen))
Expect(test.ip.ToIP()).To(HaveLen(test.expectedLen))
Expect(test.ip.ToIP()).To(Equal(test.expectedIP))
}
})
@ -174,8 +174,8 @@ var _ = Describe("IP Operations", func() {
}
})
It("Decode", func() {
Context("valid IP", func() {
Context("Decode", func() {
It("valid IP", func() {
testCases := []struct {
text string
expected *IP
@ -205,10 +205,9 @@ var _ = Describe("IP Operations", func() {
Expect(err).NotTo(HaveOccurred())
Expect(ip).To(Equal(test.expected))
}
})
Context("empty text", func() {
It("empty text", func() {
ip := &IP{}
err := json.Unmarshal([]byte(`""`), ip)
@ -216,7 +215,7 @@ var _ = Describe("IP Operations", func() {
Expect(ip).To(Equal(newIP(nil, nil)))
})
Context("invalid IP", func() {
It("invalid IP", func() {
testCases := []struct {
text string
expectedErr error
@ -243,7 +242,7 @@ var _ = Describe("IP Operations", func() {
}
})
Context("IP slice", func() {
It("IP slice", func() {
testCases := []struct {
text string
expected []*IP

View File

@ -58,5 +58,5 @@ func echo1(f string) error {
return nil
}
}
return os.WriteFile(f, []byte("1"), 0644)
return os.WriteFile(f, []byte("1"), 0o644)
}

View File

@ -4,7 +4,7 @@ import (
"os"
"time"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

View File

@ -104,7 +104,6 @@ func TeardownIPMasq(ipn *net.IPNet, chain string, comment string) error {
err = ipt.ClearChain("nat", chain)
if err != nil && !isNotExist(err) {
return err
}
err = ipt.DeleteChain("nat", chain)

View File

@ -28,9 +28,7 @@ import (
"github.com/containernetworking/plugins/pkg/utils/sysctl"
)
var (
ErrLinkNotFound = errors.New("link not found")
)
var ErrLinkNotFound = errors.New("link not found")
// makeVethPair is called from within the container's network namespace
func makeVethPair(name, peer string, mtu int, mac string, hostNS ns.NetNS) (netlink.Link, error) {
@ -69,38 +67,37 @@ func peerExists(name string) bool {
return true
}
func makeVeth(name, vethPeerName string, mtu int, mac string, hostNS ns.NetNS) (peerName string, veth netlink.Link, err error) {
func makeVeth(name, vethPeerName string, mtu int, mac string, hostNS ns.NetNS) (string, netlink.Link, error) {
var peerName string
var veth netlink.Link
var err error
for i := 0; i < 10; i++ {
if vethPeerName != "" {
peerName = vethPeerName
} else {
peerName, err = RandomVethName()
if err != nil {
return
return peerName, nil, err
}
}
veth, err = makeVethPair(name, peerName, mtu, mac, hostNS)
switch {
case err == nil:
return
return peerName, veth, nil
case os.IsExist(err):
if peerExists(peerName) && vethPeerName == "" {
continue
}
err = fmt.Errorf("container veth name provided (%v) already exists", name)
return
return peerName, veth, fmt.Errorf("container veth name provided (%v) already exists", name)
default:
err = fmt.Errorf("failed to make veth pair: %v", err)
return
return peerName, veth, fmt.Errorf("failed to make veth pair: %v", err)
}
}
// should really never be hit
err = fmt.Errorf("failed to find a unique veth name")
return
return peerName, nil, fmt.Errorf("failed to find a unique veth name")
}
// RandomVethName returns string "veth" with random prefix (hashed from entropy)

View File

@ -20,22 +20,15 @@ import (
"fmt"
"net"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/vishvananda/netlink"
"github.com/containernetworking/plugins/pkg/ip"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containernetworking/plugins/pkg/testutils"
"github.com/vishvananda/netlink"
)
func getHwAddr(linkname string) string {
veth, err := netlink.LinkByName(linkname)
Expect(err).NotTo(HaveOccurred())
return fmt.Sprintf("%s", veth.Attrs().HardwareAddr)
}
var _ = Describe("Link", func() {
const (
ifaceFormatString string = "i%d"
@ -64,7 +57,7 @@ var _ = Describe("Link", func() {
Expect(err).NotTo(HaveOccurred())
fakeBytes := make([]byte, 20)
//to be reset in AfterEach block
// to be reset in AfterEach block
rand.Reader = bytes.NewReader(fakeBytes)
_ = containerNetNS.Do(func(ns.NetNS) error {
@ -181,7 +174,7 @@ var _ = Describe("Link", func() {
Context("when there is no name available for the host-side", func() {
BeforeEach(func() {
//adding different interface to container ns
// adding different interface to container ns
containerVethName += "0"
})
It("returns useful error", func() {
@ -197,7 +190,7 @@ var _ = Describe("Link", func() {
Context("when there is no name conflict for the host or container interfaces", func() {
BeforeEach(func() {
//adding different interface to container and host ns
// adding different interface to container and host ns
containerVethName += "0"
rand.Reader = originalRandReader
})
@ -211,7 +204,7 @@ var _ = Describe("Link", func() {
return nil
})
//verify veths are in different namespaces
// verify veths are in different namespaces
_ = containerNetNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
@ -290,7 +283,7 @@ var _ = Describe("Link", func() {
// this will delete the host endpoint too
addr, err := ip.DelLinkByNameAddr(containerVethName)
Expect(err).NotTo(HaveOccurred())
Expect(addr).To(HaveLen(0))
Expect(addr).To(BeEmpty())
return nil
})
})

View File

@ -21,13 +21,13 @@ import (
"fmt"
"net"
"github.com/vishvananda/netlink"
"github.com/containernetworking/cni/pkg/types"
current "github.com/containernetworking/cni/pkg/types/100"
"github.com/vishvananda/netlink"
)
func ValidateExpectedInterfaceIPs(ifName string, resultIPs []*current.IPConfig) error {
// Ensure ips
for _, ips := range resultIPs {
ourAddr := netlink.Addr{IPNet: &ips.Address}
@ -49,12 +49,15 @@ func ValidateExpectedInterfaceIPs(ifName string, resultIPs []*current.IPConfig)
break
}
}
if match == false {
if !match {
return fmt.Errorf("Failed to match addr %v on interface %v", ourAddr, ifName)
}
// Convert the host/prefixlen to just prefix for route lookup.
_, ourPrefix, err := net.ParseCIDR(ourAddr.String())
if err != nil {
return err
}
findGwy := &netlink.Route{Dst: ourPrefix}
routeFilter := netlink.RT_FILTER_DST
@ -77,11 +80,13 @@ func ValidateExpectedInterfaceIPs(ifName string, resultIPs []*current.IPConfig)
}
func ValidateExpectedRoute(resultRoutes []*types.Route) error {
// Ensure that each static route in prevResults is found in the routing table
for _, route := range resultRoutes {
find := &netlink.Route{Dst: &route.Dst, Gw: route.GW}
routeFilter := netlink.RT_FILTER_DST | netlink.RT_FILTER_GW
routeFilter := netlink.RT_FILTER_DST
if route.GW != nil {
routeFilter |= netlink.RT_FILTER_GW
}
var family int
switch {

View File

@ -16,6 +16,7 @@ package ipam
import (
"context"
"github.com/containernetworking/cni/pkg/invoke"
"github.com/containernetworking/cni/pkg/types"
)

View File

@ -19,11 +19,11 @@ import (
"net"
"os"
"github.com/vishvananda/netlink"
current "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/plugins/pkg/ip"
"github.com/containernetworking/plugins/pkg/utils/sysctl"
"github.com/vishvananda/netlink"
)
const (
@ -44,7 +44,7 @@ func ConfigureIface(ifName string, res *current.Result) error {
}
var v4gw, v6gw net.IP
var has_enabled_ipv6 bool = false
hasEnabledIpv6 := false
for _, ipc := range res.IPs {
if ipc.Interface == nil {
continue
@ -57,7 +57,7 @@ func ConfigureIface(ifName string, res *current.Result) error {
// Make sure sysctl "disable_ipv6" is 0 if we are about to add
// an IPv6 address to the interface
if !has_enabled_ipv6 && ipc.Address.IP.To4() == nil {
if !hasEnabledIpv6 && ipc.Address.IP.To4() == nil {
// Enabled IPv6 for loopback "lo" and the interface
// being configured
for _, iface := range [2]string{"lo", ifName} {
@ -79,7 +79,7 @@ func ConfigureIface(ifName string, res *current.Result) error {
return fmt.Errorf("failed to enable IPv6 for interface %q (%s=%s): %v", iface, ipv6SysctlValueName, value, err)
}
}
has_enabled_ipv6 = true
hasEnabledIpv6 = true
}
addr := &netlink.Addr{IPNet: &ipc.Address, Label: ""}

View File

@ -18,15 +18,14 @@ import (
"net"
"syscall"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/vishvananda/netlink"
"github.com/containernetworking/cni/pkg/types"
current "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containernetworking/plugins/pkg/testutils"
"github.com/vishvananda/netlink"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
const LINK_NAME = "eth0"
@ -143,12 +142,12 @@ var _ = Describe("ConfigureIface", func() {
v4addrs, err := netlink.AddrList(link, syscall.AF_INET)
Expect(err).NotTo(HaveOccurred())
Expect(len(v4addrs)).To(Equal(1))
Expect(ipNetEqual(v4addrs[0].IPNet, ipv4)).To(Equal(true))
Expect(v4addrs).To(HaveLen(1))
Expect(ipNetEqual(v4addrs[0].IPNet, ipv4)).To(BeTrue())
v6addrs, err := netlink.AddrList(link, syscall.AF_INET6)
Expect(err).NotTo(HaveOccurred())
Expect(len(v6addrs)).To(Equal(2))
Expect(v6addrs).To(HaveLen(2))
var found bool
for _, a := range v6addrs {
@ -157,7 +156,7 @@ var _ = Describe("ConfigureIface", func() {
break
}
}
Expect(found).To(Equal(true))
Expect(found).To(BeTrue())
// Ensure the v4 route, v6 route, and subnet route
routes, err := netlink.RouteList(link, 0)
@ -177,8 +176,8 @@ var _ = Describe("ConfigureIface", func() {
break
}
}
Expect(v4found).To(Equal(true))
Expect(v6found).To(Equal(true))
Expect(v4found).To(BeTrue())
Expect(v6found).To(BeTrue())
return nil
})
@ -216,8 +215,8 @@ var _ = Describe("ConfigureIface", func() {
break
}
}
Expect(v4found).To(Equal(true))
Expect(v6found).To(Equal(true))
Expect(v4found).To(BeTrue())
Expect(v6found).To(BeTrue())
return nil
})

View File

@ -15,10 +15,10 @@
package ipam_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestIpam(t *testing.T) {

View File

@ -17,7 +17,7 @@ package link_test
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

View File

@ -15,8 +15,10 @@
package link
import (
"context"
"fmt"
"os"
"time"
"github.com/networkplumbing/go-nft/nft"
"github.com/networkplumbing/go-nft/nft/schema"
@ -29,7 +31,7 @@ const (
type NftConfigurer interface {
Apply(*nft.Config) error
Read() (*nft.Config, error)
Read(filterCommands ...string) (*nft.Config, error)
}
type SpoofChecker struct {
@ -41,12 +43,15 @@ type SpoofChecker struct {
type defaultNftConfigurer struct{}
func (_ defaultNftConfigurer) Apply(cfg *nft.Config) error {
func (dnc defaultNftConfigurer) Apply(cfg *nft.Config) error {
return nft.ApplyConfig(cfg)
}
func (_ defaultNftConfigurer) Read() (*nft.Config, error) {
return nft.ReadConfig()
func (dnc defaultNftConfigurer) Read(filterCommands ...string) (*nft.Config, error) {
const timeout = 55 * time.Second
ctxWithTimeout, cancelFunc := context.WithTimeout(context.Background(), timeout)
defer cancelFunc()
return nft.ReadConfigContext(ctxWithTimeout, filterCommands...)
}
func NewSpoofChecker(iface, macAddress, refID string) *SpoofChecker {
@ -109,7 +114,7 @@ func (sc *SpoofChecker) Setup() error {
// interface is removed.
func (sc *SpoofChecker) Teardown() error {
ifaceChain := sc.ifaceChain()
currentConfig, ifaceMatchRuleErr := sc.configurer.Read()
currentConfig, ifaceMatchRuleErr := sc.configurer.Read(listChainBridgeNatPrerouting()...)
if ifaceMatchRuleErr == nil {
expectedRuleToFind := sc.matchIfaceJumpToChainRule(preRoutingBaseChainName, ifaceChain.Name)
// It is safer to exclude the statement matching, avoiding cases where a current statement includes
@ -195,12 +200,10 @@ func (sc *SpoofChecker) matchMacRule(chain string) *schema.Rule {
}
func (sc *SpoofChecker) dropRule(chain string) *schema.Rule {
macRulesIndex := nft.NewRuleIndex()
return &schema.Rule{
Family: schema.FamilyBridge,
Table: natTableName,
Chain: chain,
Index: macRulesIndex.Next(),
Expr: []schema.Statement{
{Verdict: schema.Verdict{SimpleVerdict: schema.SimpleVerdict{Drop: true}}},
},
@ -208,7 +211,7 @@ func (sc *SpoofChecker) dropRule(chain string) *schema.Rule {
}
}
func (_ *SpoofChecker) baseChain() *schema.Chain {
func (sc *SpoofChecker) baseChain() *schema.Chain {
chainPriority := -300
return &schema.Chain{
Family: schema.FamilyBridge,
@ -230,7 +233,7 @@ func (sc *SpoofChecker) ifaceChain() *schema.Chain {
}
}
func (_ *SpoofChecker) macChain(ifaceChainName string) *schema.Chain {
func (sc *SpoofChecker) macChain(ifaceChainName string) *schema.Chain {
macChainName := ifaceChainName + "-mac"
return &schema.Chain{
Family: schema.FamilyBridge,
@ -243,3 +246,7 @@ func ruleComment(id string) string {
const refIDPrefix = "macspoofchk-"
return refIDPrefix + id
}
func listChainBridgeNatPrerouting() []string {
return []string{"chain", "bridge", natTableName, preRoutingBaseChainName}
}

View File

@ -16,9 +16,9 @@ package link_test
import (
"fmt"
"github.com/networkplumbing/go-nft/nft"
. "github.com/onsi/ginkgo"
"github.com/networkplumbing/go-nft/nft"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/containernetworking/plugins/pkg/link"
@ -116,10 +116,10 @@ var _ = Describe("spoofcheck", func() {
})
func assertExpectedRegularChainsDeletionInTeardownConfig(action configurerStub) {
deleteRegularChainRulesJsonConfig, err := action.applyConfig[1].ToJSON()
deleteRegularChainRulesJSONConfig, err := action.applyConfig[1].ToJSON()
ExpectWithOffset(1, err).NotTo(HaveOccurred())
expectedDeleteRegularChainRulesJsonConfig := `
expectedDeleteRegularChainRulesJSONConfig := `
{"nftables": [
{"delete": {"chain": {
"family": "bridge",
@ -133,14 +133,14 @@ func assertExpectedRegularChainsDeletionInTeardownConfig(action configurerStub)
}}}
]}`
ExpectWithOffset(1, string(deleteRegularChainRulesJsonConfig)).To(MatchJSON(expectedDeleteRegularChainRulesJsonConfig))
ExpectWithOffset(1, string(deleteRegularChainRulesJSONConfig)).To(MatchJSON(expectedDeleteRegularChainRulesJSONConfig))
}
func assertExpectedBaseChainRuleDeletionInTeardownConfig(action configurerStub) {
deleteBaseChainRuleJsonConfig, err := action.applyConfig[0].ToJSON()
deleteBaseChainRuleJSONConfig, err := action.applyConfig[0].ToJSON()
Expect(err).NotTo(HaveOccurred())
expectedDeleteIfaceMatchRuleJsonConfig := `
expectedDeleteIfaceMatchRuleJSONConfig := `
{"nftables": [
{"delete": {"rule": {
"family": "bridge",
@ -157,7 +157,7 @@ func assertExpectedBaseChainRuleDeletionInTeardownConfig(action configurerStub)
"comment": "macspoofchk-container99-net1"
}}}
]}`
Expect(string(deleteBaseChainRuleJsonConfig)).To(MatchJSON(expectedDeleteIfaceMatchRuleJsonConfig))
Expect(string(deleteBaseChainRuleJSONConfig)).To(MatchJSON(expectedDeleteIfaceMatchRuleJSONConfig))
}
func rowConfigWithRulesOnly() string {
@ -254,7 +254,6 @@ func assertExpectedRulesInSetupConfig(c configurerStub) {
"comment":"macspoofchk-container99-net1"}},
{"rule":{"family":"bridge","table":"nat","chain":"cni-br-iface-container99-net1-mac",
"expr":[{"drop":null}],
"index":0,
"comment":"macspoofchk-container99-net1"}}
]}`
ExpectWithOffset(1, string(jsonConfig)).To(MatchJSON(expectedConfig))
@ -289,7 +288,7 @@ func (a *configurerStub) Apply(c *nft.Config) error {
return nil
}
func (a *configurerStub) Read() (*nft.Config, error) {
func (a *configurerStub) Read(_ ...string) (*nft.Config, error) {
if a.failReadConfig {
return nil, fmt.Errorf(errorReadText)
}

View File

@ -21,11 +21,12 @@ import (
"path/filepath"
"sync"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containernetworking/plugins/pkg/testutils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"golang.org/x/sys/unix"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containernetworking/plugins/pkg/testutils"
)
func getInodeCurNetNS() (uint64, error) {

View File

@ -15,18 +15,14 @@
package ns_test
import (
"math/rand"
"runtime"
. "github.com/onsi/ginkgo"
"github.com/onsi/ginkgo/config"
. "github.com/onsi/gomega"
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestNs(t *testing.T) {
rand.Seed(config.GinkgoConfig.RandomSeed)
runtime.LockOSThread()
RegisterFailHandler(Fail)

View File

@ -21,7 +21,7 @@ type BadReader struct {
Error error
}
func (r *BadReader) Read(buffer []byte) (int, error) {
func (r *BadReader) Read(_ []byte) (int, error) {
if r.Error != nil {
return 0, r.Error
}

View File

@ -81,7 +81,7 @@ func CmdAddWithArgs(args *skel.CmdArgs, f func() error) (types.Result, []byte, e
return CmdAdd(args.Netns, args.ContainerID, args.IfName, args.StdinData, f)
}
func CmdCheck(cniNetns, cniContainerID, cniIfname string, conf []byte, f func() error) error {
func CmdCheck(cniNetns, cniContainerID, cniIfname string, f func() error) error {
os.Setenv("CNI_COMMAND", "CHECK")
os.Setenv("CNI_PATH", os.Getenv("PATH"))
os.Setenv("CNI_NETNS", cniNetns)
@ -93,7 +93,7 @@ func CmdCheck(cniNetns, cniContainerID, cniIfname string, conf []byte, f func()
}
func CmdCheckWithArgs(args *skel.CmdArgs, f func() error) error {
return CmdCheck(args.Netns, args.ContainerID, args.IfName, args.StdinData, f)
return CmdCheck(args.Netns, args.ContainerID, args.IfName, f)
}
func CmdDel(cniNetns, cniContainerID, cniIfname string, f func() error) error {

View File

@ -7,7 +7,7 @@ import (
"os/exec"
"strings"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gbytes"
"github.com/onsi/gomega/gexec"
@ -86,7 +86,7 @@ var _ = Describe("Echosvr", func() {
It("connects successfully using echo client", func() {
Eventually(session.Out).Should(gbytes.Say("\n"))
serverAddress := strings.TrimSpace(string(session.Out.Contents()))
fmt.Println("Server address", string(serverAddress))
fmt.Println("Server address", serverAddress)
cmd := exec.Command(clientBinaryPath, "-target", serverAddress, "-message", "hello")
clientSession, err := gexec.Start(cmd, GinkgoWriter, GinkgoWriter)

View File

@ -1,10 +1,10 @@
package main_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestEchosvr(t *testing.T) {

View File

@ -1,9 +1,10 @@
// Echosvr is a simple TCP echo server
//
// It prints its listen address on stdout
// 127.0.0.1:xxxxx
// A test should wait for this line, parse it
// and may then attempt to connect.
//
// 127.0.0.1:xxxxx
// A test should wait for this line, parse it
// and may then attempt to connect.
package main
import (
@ -43,11 +44,13 @@ func main() {
// Start UDP server
addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%s", port))
if err != nil {
log.Fatalf("Error from net.ResolveUDPAddr(): %s", err)
log.Printf("Error from net.ResolveUDPAddr(): %s", err)
return
}
sock, err := net.ListenUDP("udp", addr)
if err != nil {
log.Fatalf("Error from ListenUDP(): %s", err)
log.Printf("Error from ListenUDP(): %s", err)
return
}
defer sock.Close()
@ -55,10 +58,11 @@ func main() {
for {
n, addr, err := sock.ReadFrom(buffer)
if err != nil {
log.Fatalf("Error from ReadFrom(): %s", err)
log.Printf("Error from ReadFrom(): %s", err)
return
}
sock.SetWriteDeadline(time.Now().Add(1 * time.Minute))
n, err = sock.WriteTo(buffer[0:n], addr)
_, err = sock.WriteTo(buffer[0:n], addr)
if err != nil {
return
}

View File

@ -24,8 +24,9 @@ import (
"sync"
"syscall"
"github.com/containernetworking/plugins/pkg/ns"
"golang.org/x/sys/unix"
"github.com/containernetworking/plugins/pkg/ns"
)
func getNsRunDir() string {
@ -49,7 +50,6 @@ func getNsRunDir() string {
// Creates a new persistent (bind-mounted) network namespace and returns an object
// representing that namespace, without switching to it.
func NewNS() (ns.NetNS, error) {
nsRunDir := getNsRunDir()
b := make([]byte, 16)
@ -61,7 +61,7 @@ func NewNS() (ns.NetNS, error) {
// Create the directory for mounting network namespaces
// This needs to be a shared mountpoint in case it is mounted in to
// other namespaces (containers)
err = os.MkdirAll(nsRunDir, 0755)
err = os.MkdirAll(nsRunDir, 0o755)
if err != nil {
return nil, err
}

View File

@ -133,7 +133,6 @@ func InsertUnique(ipt *iptables.IPTables, table, chain string, prepend bool, rul
if prepend {
return ipt.Insert(table, chain, 1, rule...)
} else {
return ipt.Append(table, chain, rule...)
}
return ipt.Append(table, chain, rule...)
}

View File

@ -19,11 +19,12 @@ import (
"math/rand"
"runtime"
"github.com/coreos/go-iptables/iptables"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containernetworking/plugins/pkg/testutils"
"github.com/coreos/go-iptables/iptables"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
const TABLE = "filter" // We'll monkey around here
@ -34,7 +35,6 @@ var _ = Describe("chain tests", func() {
var cleanup func()
BeforeEach(func() {
// Save a reference to the original namespace,
// Add a new NS
currNs, err := ns.GetCurrentNS()
@ -60,7 +60,6 @@ var _ = Describe("chain tests", func() {
ipt.DeleteChain(TABLE, testChain)
currNs.Set()
}
})
AfterEach(func() {
@ -93,5 +92,4 @@ var _ = Describe("chain tests", func() {
Expect(err).NotTo(HaveOccurred())
})
})
})

View File

@ -46,7 +46,7 @@ func getSysctl(name string) (string, error) {
func setSysctl(name, value string) (string, error) {
fullName := filepath.Join("/proc/sys", toNormalName(name))
if err := os.WriteFile(fullName, []byte(value), 0644); err != nil {
if err := os.WriteFile(fullName, []byte(value), 0o644); err != nil {
return "", err
}

View File

@ -20,12 +20,13 @@ import (
"runtime"
"strings"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/vishvananda/netlink"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containernetworking/plugins/pkg/testutils"
"github.com/containernetworking/plugins/pkg/utils/sysctl"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vishvananda/netlink"
)
const (
@ -37,8 +38,7 @@ var _ = Describe("Sysctl tests", func() {
var testIfaceName string
var cleanup func()
BeforeEach(func() {
beforeEach := func() {
// Save a reference to the original namespace,
// Add a new NS
currNs, err := ns.GetCurrentNS()
@ -66,8 +66,7 @@ var _ = Describe("Sysctl tests", func() {
netlink.LinkDel(testIface)
currNs.Set()
}
})
}
AfterEach(func() {
cleanup()
@ -75,7 +74,8 @@ var _ = Describe("Sysctl tests", func() {
Describe("Sysctl", func() {
It("reads keys with dot separators", func() {
sysctlIfaceName := strings.Replace(testIfaceName, ".", "/", -1)
beforeEach()
sysctlIfaceName := strings.ReplaceAll(testIfaceName, ".", "/")
sysctlKey := fmt.Sprintf(sysctlDotKeyTemplate, sysctlIfaceName)
_, err := sysctl.Sysctl(sysctlKey)
@ -85,6 +85,7 @@ var _ = Describe("Sysctl tests", func() {
Describe("Sysctl", func() {
It("reads keys with slash separators", func() {
beforeEach()
sysctlKey := fmt.Sprintf(sysctlSlashKeyTemplate, testIfaceName)
_, err := sysctl.Sysctl(sysctlKey)
@ -94,7 +95,8 @@ var _ = Describe("Sysctl tests", func() {
Describe("Sysctl", func() {
It("writes keys with dot separators", func() {
sysctlIfaceName := strings.Replace(testIfaceName, ".", "/", -1)
beforeEach()
sysctlIfaceName := strings.ReplaceAll(testIfaceName, ".", "/")
sysctlKey := fmt.Sprintf(sysctlDotKeyTemplate, sysctlIfaceName)
_, err := sysctl.Sysctl(sysctlKey, "1")
@ -104,11 +106,11 @@ var _ = Describe("Sysctl tests", func() {
Describe("Sysctl", func() {
It("writes keys with slash separators", func() {
beforeEach()
sysctlKey := fmt.Sprintf(sysctlSlashKeyTemplate, testIfaceName)
_, err := sysctl.Sysctl(sysctlKey, "1")
Expect(err).NotTo(HaveOccurred())
})
})
})

View File

@ -17,7 +17,7 @@ package sysctl_test
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

View File

@ -15,10 +15,10 @@
package utils_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestUtils(t *testing.T) {

View File

@ -18,7 +18,7 @@ import (
"fmt"
"strings"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
@ -26,29 +26,29 @@ var _ = Describe("Utils", func() {
Describe("FormatChainName", func() {
It("must format a short name", func() {
chain := FormatChainName("test", "1234")
Expect(len(chain)).To(Equal(maxChainLength))
Expect(chain).To(HaveLen(maxChainLength))
Expect(chain).To(Equal("CNI-2bbe0c48b91a7d1b8a6753a8"))
})
It("must truncate a long name", func() {
chain := FormatChainName("testalongnamethatdoesnotmakesense", "1234")
Expect(len(chain)).To(Equal(maxChainLength))
Expect(chain).To(HaveLen(maxChainLength))
Expect(chain).To(Equal("CNI-374f33fe84ab0ed84dcdebe3"))
})
It("must be predictable", func() {
chain1 := FormatChainName("testalongnamethatdoesnotmakesense", "1234")
chain2 := FormatChainName("testalongnamethatdoesnotmakesense", "1234")
Expect(len(chain1)).To(Equal(maxChainLength))
Expect(len(chain2)).To(Equal(maxChainLength))
Expect(chain1).To(HaveLen(maxChainLength))
Expect(chain2).To(HaveLen(maxChainLength))
Expect(chain1).To(Equal(chain2))
})
It("must change when a character changes", func() {
chain1 := FormatChainName("testalongnamethatdoesnotmakesense", "1234")
chain2 := FormatChainName("testalongnamethatdoesnotmakesense", "1235")
Expect(len(chain1)).To(Equal(maxChainLength))
Expect(len(chain2)).To(Equal(maxChainLength))
Expect(chain1).To(HaveLen(maxChainLength))
Expect(chain2).To(HaveLen(maxChainLength))
Expect(chain1).To(Equal("CNI-374f33fe84ab0ed84dcdebe3"))
Expect(chain1).NotTo(Equal(chain2))
})
@ -57,35 +57,35 @@ var _ = Describe("Utils", func() {
Describe("MustFormatChainNameWithPrefix", func() {
It("generates a chain name with a prefix", func() {
chain := MustFormatChainNameWithPrefix("test", "1234", "PREFIX-")
Expect(len(chain)).To(Equal(maxChainLength))
Expect(chain).To(HaveLen(maxChainLength))
Expect(chain).To(Equal("CNI-PREFIX-2bbe0c48b91a7d1b8"))
})
It("must format a short name", func() {
chain := MustFormatChainNameWithPrefix("test", "1234", "PREFIX-")
Expect(len(chain)).To(Equal(maxChainLength))
Expect(chain).To(HaveLen(maxChainLength))
Expect(chain).To(Equal("CNI-PREFIX-2bbe0c48b91a7d1b8"))
})
It("must truncate a long name", func() {
chain := MustFormatChainNameWithPrefix("testalongnamethatdoesnotmakesense", "1234", "PREFIX-")
Expect(len(chain)).To(Equal(maxChainLength))
Expect(chain).To(HaveLen(maxChainLength))
Expect(chain).To(Equal("CNI-PREFIX-374f33fe84ab0ed84"))
})
It("must be predictable", func() {
chain1 := MustFormatChainNameWithPrefix("testalongnamethatdoesnotmakesense", "1234", "PREFIX-")
chain2 := MustFormatChainNameWithPrefix("testalongnamethatdoesnotmakesense", "1234", "PREFIX-")
Expect(len(chain1)).To(Equal(maxChainLength))
Expect(len(chain2)).To(Equal(maxChainLength))
Expect(chain1).To(HaveLen(maxChainLength))
Expect(chain2).To(HaveLen(maxChainLength))
Expect(chain1).To(Equal(chain2))
})
It("must change when a character changes", func() {
chain1 := MustFormatChainNameWithPrefix("testalongnamethatdoesnotmakesense", "1234", "PREFIX-")
chain2 := MustFormatChainNameWithPrefix("testalongnamethatdoesnotmakesense", "1235", "PREFIX-")
Expect(len(chain1)).To(Equal(maxChainLength))
Expect(len(chain2)).To(Equal(maxChainLength))
Expect(chain1).To(HaveLen(maxChainLength))
Expect(chain2).To(HaveLen(maxChainLength))
Expect(chain1).To(Equal("CNI-PREFIX-374f33fe84ab0ed84"))
Expect(chain1).NotTo(Equal(chain2))
})
@ -161,5 +161,4 @@ var _ = Describe("Utils", func() {
)
})
})
})

View File

@ -23,7 +23,7 @@ const (
MaxDHCPLen = 576
)
//Send the Discovery Packet to the Broadcast Channel
// Send the Discovery Packet to the Broadcast Channel
func DhcpSendDiscoverPacket(c *dhcp4client.Client, options dhcp4.Options) (dhcp4.Packet, error) {
discoveryPacket := c.DiscoverPacket()
@ -35,7 +35,7 @@ func DhcpSendDiscoverPacket(c *dhcp4client.Client, options dhcp4.Options) (dhcp4
return discoveryPacket, c.SendPacket(discoveryPacket)
}
//Send Request Based On the offer Received.
// Send Request Based On the offer Received.
func DhcpSendRequest(c *dhcp4client.Client, options dhcp4.Options, offerPacket *dhcp4.Packet) (dhcp4.Packet, error) {
requestPacket := c.RequestPacket(offerPacket)
@ -48,7 +48,7 @@ func DhcpSendRequest(c *dhcp4client.Client, options dhcp4.Options, offerPacket *
return requestPacket, c.SendPacket(requestPacket)
}
//Send Decline to the received acknowledgement.
// Send Decline to the received acknowledgement.
func DhcpSendDecline(c *dhcp4client.Client, acknowledgementPacket *dhcp4.Packet, options dhcp4.Options) (dhcp4.Packet, error) {
declinePacket := c.DeclinePacket(acknowledgementPacket)
@ -61,7 +61,7 @@ func DhcpSendDecline(c *dhcp4client.Client, acknowledgementPacket *dhcp4.Packet,
return declinePacket, c.SendPacket(declinePacket)
}
//Lets do a Full DHCP Request.
// Lets do a Full DHCP Request.
func DhcpRequest(c *dhcp4client.Client, options dhcp4.Options) (bool, dhcp4.Packet, error) {
discoveryPacket, err := DhcpSendDiscoverPacket(c, options)
if err != nil {
@ -91,8 +91,8 @@ func DhcpRequest(c *dhcp4client.Client, options dhcp4.Options) (bool, dhcp4.Pack
return true, acknowledgement, nil
}
//Renew a lease backed on the Acknowledgement Packet.
//Returns Successful, The AcknoledgementPacket, Any Errors
// Renew a lease backed on the Acknowledgement Packet.
// Returns Successful, The AcknoledgementPacket, Any Errors
func DhcpRenew(c *dhcp4client.Client, acknowledgement dhcp4.Packet, options dhcp4.Options) (bool, dhcp4.Packet, error) {
renewRequest := c.RenewalRequestPacket(&acknowledgement)
@ -120,8 +120,8 @@ func DhcpRenew(c *dhcp4client.Client, acknowledgement dhcp4.Packet, options dhcp
return true, newAcknowledgement, nil
}
//Release a lease backed on the Acknowledgement Packet.
//Returns Any Errors
// Release a lease backed on the Acknowledgement Packet.
// Returns Any Errors
func DhcpRelease(c *dhcp4client.Client, acknowledgement dhcp4.Packet, options dhcp4.Options) error {
release := c.ReleasePacket(&acknowledgement)

View File

@ -30,9 +30,10 @@ import (
"syscall"
"time"
"github.com/coreos/go-systemd/v22/activation"
"github.com/containernetworking/cni/pkg/skel"
current "github.com/containernetworking/cni/pkg/types/100"
"github.com/coreos/go-systemd/v22/activation"
)
var errNoMoreTries = errors.New("no more tries")
@ -55,7 +56,7 @@ func newDHCP(clientTimeout, clientResendMax time.Duration) *DHCP {
}
// TODO: current client ID is too long. At least the container ID should not be used directly.
// A seperate issue is necessary to ensure no breaking change is affecting other users.
// A separate issue is necessary to ensure no breaking change is affecting other users.
func generateClientID(containerID string, netName string, ifName string) string {
clientID := containerID + "/" + netName + "/" + ifName
// defined in RFC 2132, length size can not be larger than 1 octet. So we truncate 254 to make everyone happy.
@ -114,7 +115,7 @@ func (d *DHCP) Allocate(args *skel.CmdArgs, result *current.Result) error {
// Release stops maintenance of the lease acquired in Allocate()
// and sends a release msg to the DHCP server.
func (d *DHCP) Release(args *skel.CmdArgs, reply *struct{}) error {
func (d *DHCP) Release(args *skel.CmdArgs, _ *struct{}) error {
conf := NetConf{}
if err := json.Unmarshal(args.StdinData, &conf); err != nil {
return fmt.Errorf("error parsing netconf: %v", err)
@ -166,7 +167,7 @@ func getListener(socketPath string) (net.Listener, error) {
switch {
case len(l) == 0:
if err := os.MkdirAll(filepath.Dir(socketPath), 0700); err != nil {
if err := os.MkdirAll(filepath.Dir(socketPath), 0o700); err != nil {
return nil, err
}
return net.Listen("unix", socketPath)
@ -195,7 +196,7 @@ func runDaemon(
if !filepath.IsAbs(pidfilePath) {
return fmt.Errorf("Error writing pidfile %q: path not absolute", pidfilePath)
}
if err := os.WriteFile(pidfilePath, []byte(fmt.Sprintf("%d", os.Getpid())), 0644); err != nil {
if err := os.WriteFile(pidfilePath, []byte(fmt.Sprintf("%d", os.Getpid())), 0o644); err != nil {
return fmt.Errorf("Error writing pidfile %q: %v", pidfilePath, err)
}
}

View File

@ -16,21 +16,19 @@ package main
import (
"fmt"
"net"
"os"
"os/exec"
"sync"
"time"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/vishvananda/netlink"
"github.com/containernetworking/cni/pkg/skel"
current "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containernetworking/plugins/pkg/testutils"
"github.com/vishvananda/netlink"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("DHCP Multiple Lease Operations", func() {
@ -40,11 +38,10 @@ var _ = Describe("DHCP Multiple Lease Operations", func() {
var clientCmd *exec.Cmd
var socketPath string
var tmpDir string
var serverIP net.IPNet
var err error
BeforeEach(func() {
dhcpServerStopCh, serverIP, socketPath, originalNS, targetNS, err = dhcpSetupOriginalNS()
dhcpServerStopCh, socketPath, originalNS, targetNS, err = dhcpSetupOriginalNS()
Expect(err).NotTo(HaveOccurred())
// Move the container side to the container's NS
@ -64,7 +61,7 @@ var _ = Describe("DHCP Multiple Lease Operations", func() {
})
// Start the DHCP server
dhcpServerDone, err = dhcpServerStart(originalNS, net.IPv4(192, 168, 1, 5), serverIP.IP, 2, dhcpServerStopCh)
dhcpServerDone, err = dhcpServerStart(originalNS, 2, dhcpServerStopCh)
Expect(err).NotTo(HaveOccurred())
// Start the DHCP client daemon
@ -123,7 +120,7 @@ var _ = Describe("DHCP Multiple Lease Operations", func() {
addResult, err = current.GetResult(r)
Expect(err).NotTo(HaveOccurred())
Expect(len(addResult.IPs)).To(Equal(1))
Expect(addResult.IPs).To(HaveLen(1))
Expect(addResult.IPs[0].Address.String()).To(Equal("192.168.1.5/24"))
return nil
})
@ -146,7 +143,7 @@ var _ = Describe("DHCP Multiple Lease Operations", func() {
addResult, err = current.GetResult(r)
Expect(err).NotTo(HaveOccurred())
Expect(len(addResult.IPs)).To(Equal(1))
Expect(addResult.IPs).To(HaveLen(1))
Expect(addResult.IPs[0].Address.String()).To(Equal("192.168.1.6/24"))
return nil
})

View File

@ -15,10 +15,10 @@
package main
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestDHCP(t *testing.T) {

View File

@ -25,20 +25,18 @@ import (
"sync"
"time"
"github.com/containernetworking/cni/pkg/skel"
types100 "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containernetworking/plugins/pkg/testutils"
"github.com/vishvananda/netlink"
"github.com/d2g/dhcp4"
"github.com/d2g/dhcp4server"
"github.com/d2g/dhcp4server/leasepool"
"github.com/d2g/dhcp4server/leasepool/memorypool"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/vishvananda/netlink"
"github.com/containernetworking/cni/pkg/skel"
types100 "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containernetworking/plugins/pkg/testutils"
)
func getTmpDir() (string, error) {
@ -50,7 +48,7 @@ func getTmpDir() (string, error) {
return tmpDir, err
}
func dhcpServerStart(netns ns.NetNS, leaseIP, serverIP net.IP, numLeases int, stopCh <-chan bool) (*sync.WaitGroup, error) {
func dhcpServerStart(netns ns.NetNS, numLeases int, stopCh <-chan bool) (*sync.WaitGroup, error) {
// Add the expected IP to the pool
lp := memorypool.MemoryPool{}
@ -120,7 +118,7 @@ const (
)
var _ = BeforeSuite(func() {
err := os.MkdirAll(cniDirPrefix, 0700)
err := os.MkdirAll(cniDirPrefix, 0o700)
Expect(err).NotTo(HaveOccurred())
})
@ -202,7 +200,7 @@ var _ = Describe("DHCP Operations", func() {
})
// Start the DHCP server
dhcpServerDone, err = dhcpServerStart(originalNS, net.IPv4(192, 168, 1, 5), serverIP.IP, 1, dhcpServerStopCh)
dhcpServerDone, err = dhcpServerStart(originalNS, 1, dhcpServerStopCh)
Expect(err).NotTo(HaveOccurred())
// Start the DHCP client daemon
@ -273,7 +271,7 @@ var _ = Describe("DHCP Operations", func() {
addResult, err = types100.GetResult(r)
Expect(err).NotTo(HaveOccurred())
Expect(len(addResult.IPs)).To(Equal(1))
Expect(addResult.IPs).To(HaveLen(1))
Expect(addResult.IPs[0].Address.String()).To(Equal("192.168.1.5/24"))
return nil
})
@ -316,7 +314,7 @@ var _ = Describe("DHCP Operations", func() {
addResult, err = types100.GetResult(r)
Expect(err).NotTo(HaveOccurred())
Expect(len(addResult.IPs)).To(Equal(1))
Expect(addResult.IPs).To(HaveLen(1))
Expect(addResult.IPs[0].Address.String()).To(Equal("192.168.1.5/24"))
return nil
})
@ -363,7 +361,7 @@ const (
contVethName1 string = "eth1"
)
func dhcpSetupOriginalNS() (chan bool, net.IPNet, string, ns.NetNS, ns.NetNS, error) {
func dhcpSetupOriginalNS() (chan bool, string, ns.NetNS, ns.NetNS, error) {
var originalNS, targetNS ns.NetNS
var dhcpServerStopCh chan bool
var socketPath string
@ -384,11 +382,6 @@ func dhcpSetupOriginalNS() (chan bool, net.IPNet, string, ns.NetNS, ns.NetNS, er
targetNS, err = testutils.NewNS()
Expect(err).NotTo(HaveOccurred())
serverIP := net.IPNet{
IP: net.IPv4(192, 168, 1, 1),
Mask: net.IPv4Mask(255, 255, 255, 0),
}
// Use (original) NS
err = originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
@ -483,7 +476,7 @@ func dhcpSetupOriginalNS() (chan bool, net.IPNet, string, ns.NetNS, ns.NetNS, er
return nil
})
return dhcpServerStopCh, serverIP, socketPath, originalNS, targetNS, err
return dhcpServerStopCh, socketPath, originalNS, targetNS, err
}
var _ = Describe("DHCP Lease Unavailable Operations", func() {
@ -493,11 +486,10 @@ var _ = Describe("DHCP Lease Unavailable Operations", func() {
var clientCmd *exec.Cmd
var socketPath string
var tmpDir string
var serverIP net.IPNet
var err error
BeforeEach(func() {
dhcpServerStopCh, serverIP, socketPath, originalNS, targetNS, err = dhcpSetupOriginalNS()
dhcpServerStopCh, socketPath, originalNS, targetNS, err = dhcpSetupOriginalNS()
Expect(err).NotTo(HaveOccurred())
// Move the container side to the container's NS
@ -517,7 +509,7 @@ var _ = Describe("DHCP Lease Unavailable Operations", func() {
})
// Start the DHCP server
dhcpServerDone, err = dhcpServerStart(originalNS, net.IPv4(192, 168, 1, 5), serverIP.IP, 1, dhcpServerStopCh)
dhcpServerDone, err = dhcpServerStart(originalNS, 1, dhcpServerStopCh)
Expect(err).NotTo(HaveOccurred())
// Start the DHCP client daemon
@ -596,7 +588,7 @@ var _ = Describe("DHCP Lease Unavailable Operations", func() {
addResult, err = types100.GetResult(r)
Expect(err).NotTo(HaveOccurred())
Expect(len(addResult.IPs)).To(Equal(1))
Expect(addResult.IPs).To(HaveLen(1))
Expect(addResult.IPs[0].Address.String()).To(Equal("192.168.1.5/24"))
return nil
})

View File

@ -34,13 +34,17 @@ import (
// RFC 2131 suggests using exponential backoff, starting with 4sec
// and randomized to +/- 1sec
const resendDelay0 = 4 * time.Second
const resendDelayMax = 62 * time.Second
const (
resendDelay0 = 4 * time.Second
resendDelayMax = 62 * time.Second
)
// To speed up the retry for first few failures, we retry without
// backoff for a few times
const resendFastDelay = 2 * time.Second
const resendFastMax = 4
const (
resendFastDelay = 2 * time.Second
resendFastMax = 4
)
const (
leaseStateBound = iota
@ -79,9 +83,12 @@ var requestOptionsDefault = map[dhcp4.OptionCode]bool{
dhcp4.OptionSubnetMask: true,
}
func prepareOptions(cniArgs string, ProvideOptions []ProvideOption, RequestOptions []RequestOption) (
optsRequesting map[dhcp4.OptionCode]bool, optsProviding map[dhcp4.OptionCode][]byte, err error) {
func prepareOptions(cniArgs string, provideOptions []ProvideOption, requestOptions []RequestOption) (
map[dhcp4.OptionCode]bool, map[dhcp4.OptionCode][]byte, error,
) {
var optsRequesting map[dhcp4.OptionCode]bool
var optsProviding map[dhcp4.OptionCode][]byte
var err error
// parse CNI args
cniArgsParsed := map[string]string{}
for _, argPair := range strings.Split(cniArgs, ";") {
@ -94,23 +101,20 @@ func prepareOptions(cniArgs string, ProvideOptions []ProvideOption, RequestOptio
// parse providing options map
var optParsed dhcp4.OptionCode
optsProviding = make(map[dhcp4.OptionCode][]byte)
for _, opt := range ProvideOptions {
for _, opt := range provideOptions {
optParsed, err = parseOptionName(string(opt.Option))
if err != nil {
err = fmt.Errorf("Can not parse option %q: %w", opt.Option, err)
return
return nil, nil, fmt.Errorf("Can not parse option %q: %w", opt.Option, err)
}
if len(opt.Value) > 0 {
if len(opt.Value) > 255 {
err = fmt.Errorf("value too long for option %q: %q", opt.Option, opt.Value)
return
return nil, nil, fmt.Errorf("value too long for option %q: %q", opt.Option, opt.Value)
}
optsProviding[optParsed] = []byte(opt.Value)
}
if value, ok := cniArgsParsed[opt.ValueFromCNIArg]; ok {
if len(value) > 255 {
err = fmt.Errorf("value too long for option %q from CNI_ARGS %q: %q", opt.Option, opt.ValueFromCNIArg, opt.Value)
return
return nil, nil, fmt.Errorf("value too long for option %q from CNI_ARGS %q: %q", opt.Option, opt.ValueFromCNIArg, opt.Value)
}
optsProviding[optParsed] = []byte(value)
}
@ -119,14 +123,13 @@ func prepareOptions(cniArgs string, ProvideOptions []ProvideOption, RequestOptio
// parse necessary options map
optsRequesting = make(map[dhcp4.OptionCode]bool)
skipRequireDefault := false
for _, opt := range RequestOptions {
for _, opt := range requestOptions {
if opt.SkipDefault {
skipRequireDefault = true
}
optParsed, err = parseOptionName(string(opt.Option))
if err != nil {
err = fmt.Errorf("Can not parse option %q: %w", opt.Option, err)
return
return nil, nil, fmt.Errorf("Can not parse option %q: %w", opt.Option, err)
}
optsRequesting[optParsed] = true
}
@ -136,7 +139,7 @@ func prepareOptions(cniArgs string, ProvideOptions []ProvideOption, RequestOptio
optsRequesting[k] = v
}
}
return
return optsRequesting, optsProviding, err
}
// AcquireLease gets an DHCP lease and then maintains it in the background
@ -206,7 +209,7 @@ func (l *DHCPLease) Check() {
l.check <- struct{}{}
}
func (l *DHCPLease) getOptionsWithClientId() dhcp4.Options {
func (l *DHCPLease) getOptionsWithClientID() dhcp4.Options {
opts := make(dhcp4.Options)
opts[dhcp4.OptionClientIdentifier] = []byte(l.clientID)
// client identifier's first byte is "type"
@ -217,7 +220,7 @@ func (l *DHCPLease) getOptionsWithClientId() dhcp4.Options {
}
func (l *DHCPLease) getAllOptions() dhcp4.Options {
opts := l.getOptionsWithClientId()
opts := l.getOptionsWithClientID()
for k, v := range l.optsProviding {
opts[k] = v
@ -231,7 +234,7 @@ func (l *DHCPLease) getAllOptions() dhcp4.Options {
}
func (l *DHCPLease) acquire() error {
c, err := newDHCPClient(l.link, l.clientID, l.timeout, l.broadcast)
c, err := newDHCPClient(l.link, l.timeout, l.broadcast)
if err != nil {
return err
}
@ -302,7 +305,7 @@ func (l *DHCPLease) maintain() {
switch state {
case leaseStateBound:
sleepDur = l.renewalTime.Sub(time.Now())
sleepDur = time.Until(l.renewalTime)
if sleepDur <= 0 {
log.Printf("%v: renewing lease", l.clientID)
state = leaseStateRenewing
@ -359,7 +362,7 @@ func (l *DHCPLease) downIface() {
}
func (l *DHCPLease) renew() error {
c, err := newDHCPClient(l.link, l.clientID, l.timeout, l.broadcast)
c, err := newDHCPClient(l.link, l.timeout, l.broadcast)
if err != nil {
return err
}
@ -388,13 +391,13 @@ func (l *DHCPLease) renew() error {
func (l *DHCPLease) release() error {
log.Printf("%v: releasing lease", l.clientID)
c, err := newDHCPClient(l.link, l.clientID, l.timeout, l.broadcast)
c, err := newDHCPClient(l.link, l.timeout, l.broadcast)
if err != nil {
return err
}
defer c.Close()
opts := l.getOptionsWithClientId()
opts := l.getOptionsWithClientID()
if err = DhcpRelease(c, *l.ack, opts); err != nil {
return fmt.Errorf("failed to send DHCPRELEASE")
@ -424,9 +427,9 @@ func (l *DHCPLease) Routes() []*types.Route {
// RFC 3442 states that if Classless Static Routes (option 121)
// exist, we ignore Static Routes (option 33) and the Router/Gateway.
opt121_routes := parseCIDRRoutes(l.opts)
if len(opt121_routes) > 0 {
return append(routes, opt121_routes...)
opt121Routes := parseCIDRRoutes(l.opts)
if len(opt121Routes) > 0 {
return append(routes, opt121Routes...)
}
// Append Static Routes
@ -448,9 +451,9 @@ func jitter(span time.Duration) time.Duration {
}
func backoffRetry(resendMax time.Duration, f func() (*dhcp4.Packet, error)) (*dhcp4.Packet, error) {
var baseDelay time.Duration = resendDelay0
baseDelay := resendDelay0
var sleepTime time.Duration
var fastRetryLimit = resendFastMax
fastRetryLimit := resendFastMax
for {
pkt, err := f()
if err == nil {
@ -482,7 +485,7 @@ func backoffRetry(resendMax time.Duration, f func() (*dhcp4.Packet, error)) (*dh
}
func newDHCPClient(
link netlink.Link, clientID string,
link netlink.Link,
timeout time.Duration,
broadcast bool,
) (*dhcp4client.Client, error) {

View File

@ -118,27 +118,20 @@ func cmdAdd(args *skel.CmdArgs) error {
func cmdDel(args *skel.CmdArgs) error {
result := struct{}{}
if err := rpcCall("DHCP.Release", args, &result); err != nil {
return err
}
return nil
return rpcCall("DHCP.Release", args, &result)
}
func cmdCheck(args *skel.CmdArgs) error {
// Plugin must return result in same version as specified in netconf
versionDecoder := &version.ConfigDecoder{}
//confVersion, err := versionDecoder.Decode(args.StdinData)
// confVersion, err := versionDecoder.Decode(args.StdinData)
_, err := versionDecoder.Decode(args.StdinData)
if err != nil {
return err
}
result := &current.Result{CNIVersion: current.ImplementedSpecVersion}
if err := rpcCall("DHCP.Allocate", args, result); err != nil {
return err
}
return nil
return rpcCall("DHCP.Allocate", args, result)
}
func getSocketPath(stdinData []byte) (string, error) {

View File

@ -21,8 +21,9 @@ import (
"strconv"
"time"
"github.com/containernetworking/cni/pkg/types"
"github.com/d2g/dhcp4"
"github.com/containernetworking/cni/pkg/types"
)
var optionNameToID = map[string]dhcp4.OptionCode{

View File

@ -19,8 +19,9 @@ import (
"reflect"
"testing"
"github.com/containernetworking/cni/pkg/types"
"github.com/d2g/dhcp4"
"github.com/containernetworking/cni/pkg/types"
)
func validateRoutes(t *testing.T, routes []*types.Route) {

View File

@ -22,7 +22,6 @@ import (
"strconv"
current "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/plugins/pkg/ip"
"github.com/containernetworking/plugins/plugins/ipam/host-local/backend"
)
@ -197,7 +196,7 @@ func (i *RangeIter) Next() (*net.IPNet, net.IP) {
// If we've reached the end of this range, we need to advance the range
// RangeEnd is inclusive as well
if i.cur.Equal(r.RangeEnd) {
i.rangeIdx += 1
i.rangeIdx++
i.rangeIdx %= len(*i.rangeset)
r = (*i.rangeset)[i.rangeIdx]

View File

@ -15,10 +15,10 @@
package allocator_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestAllocator(t *testing.T) {

View File

@ -18,12 +18,12 @@ import (
"fmt"
"net"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/containernetworking/cni/pkg/types"
current "github.com/containernetworking/cni/pkg/types/100"
fakestore "github.com/containernetworking/plugins/plugins/ipam/host-local/backend/testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
type AllocatorTestCase struct {
@ -77,7 +77,7 @@ func (t AllocatorTestCase) run(idx int) (*current.IPConfig, error) {
p = append(p, Range{Subnet: types.IPNet(*subnet)})
}
Expect(p.Canonicalize()).To(BeNil())
Expect(p.Canonicalize()).To(Succeed())
store := fakestore.NewFakeStore(t.ipmap, map[string]net.IP{"rangeid": net.ParseIP(t.lastIP)})
@ -262,7 +262,6 @@ var _ = Describe("host-local ip allocator", func() {
res, err = alloc.Get("ID", "eth0", nil)
Expect(err).ToNot(HaveOccurred())
Expect(res.Address.String()).To(Equal("192.168.1.3/29"))
})
Context("when requesting a specific IP", func() {
@ -301,7 +300,6 @@ var _ = Describe("host-local ip allocator", func() {
Expect(err).To(HaveOccurred())
})
})
})
Context("when out of ips", func() {
It("returns a meaningful error", func() {
@ -332,7 +330,7 @@ var _ = Describe("host-local ip allocator", func() {
}
for idx, tc := range testCases {
_, err := tc.run(idx)
Expect(err).NotTo(BeNil())
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(HavePrefix("no IP addresses available in range set"))
}
})

View File

@ -21,7 +21,6 @@ import (
"github.com/containernetworking/cni/pkg/types"
"github.com/containernetworking/cni/pkg/version"
"github.com/containernetworking/plugins/pkg/ip"
)
@ -43,7 +42,7 @@ type Net struct {
// IPAMConfig represents the IP related network configuration.
// This nests Range because we initially only supported a single
// range directly, and wish to preserve backwards compatability
// range directly, and wish to preserve backwards compatibility
type IPAMConfig struct {
*Range
Name string

View File

@ -17,9 +17,10 @@ package allocator
import (
"net"
"github.com/containernetworking/cni/pkg/types"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/containernetworking/cni/pkg/types"
)
var _ = Describe("IPAM config", func() {
@ -415,7 +416,6 @@ var _ = Describe("IPAM config", func() {
}`
_, _, err := LoadIPAMConfig([]byte(input), "")
Expect(err).To(MatchError("invalid range set 0: mixed address families"))
})
It("Should should error on too many ranges", func() {

View File

@ -125,7 +125,7 @@ func (r *Range) Contains(addr net.IP) bool {
// Overlaps returns true if there is any overlap between ranges
func (r *Range) Overlaps(r1 *Range) bool {
// different familes
// different families
if len(r.RangeStart) != len(r1.RangeStart) {
return false
}

View File

@ -67,10 +67,8 @@ func (s *RangeSet) Canonicalize() error {
}
if i == 0 {
fam = len((*s)[i].RangeStart)
} else {
if fam != len((*s)[i].RangeStart) {
return fmt.Errorf("mixed address families")
}
} else if fam != len((*s)[i].RangeStart) {
return fmt.Errorf("mixed address families")
}
}

View File

@ -17,7 +17,7 @@ package allocator
import (
"net"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
@ -40,7 +40,6 @@ var _ = Describe("range sets", func() {
r, err = p.RangeFor(net.IP{192, 168, 99, 99})
Expect(r).To(BeNil())
Expect(err).To(MatchError("192.168.99.99 not in range set 192.168.0.1-192.168.0.254,172.16.1.1-172.16.1.254"))
})
It("should discover overlaps within a set", func() {

View File

@ -17,11 +17,10 @@ package allocator
import (
"net"
"github.com/containernetworking/cni/pkg/types"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/extensions/table"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/containernetworking/cni/pkg/types"
)
var _ = Describe("IP ranges", func() {

View File

@ -24,8 +24,10 @@ import (
"github.com/containernetworking/plugins/plugins/ipam/host-local/backend"
)
const lastIPFilePrefix = "last_reserved_ip."
const LineBreak = "\r\n"
const (
lastIPFilePrefix = "last_reserved_ip."
LineBreak = "\r\n"
)
var defaultDataDir = "/var/lib/cni/networks"
@ -44,7 +46,7 @@ func New(network, dataDir string) (*Store, error) {
dataDir = defaultDataDir
}
dir := filepath.Join(dataDir, network)
if err := os.MkdirAll(dir, 0755); err != nil {
if err := os.MkdirAll(dir, 0o755); err != nil {
return nil, err
}
@ -58,7 +60,7 @@ func New(network, dataDir string) (*Store, error) {
func (s *Store) Reserve(id string, ifname string, ip net.IP, rangeID string) (bool, error) {
fname := GetEscapedPath(s.dataDir, ip.String())
f, err := os.OpenFile(fname, os.O_RDWR|os.O_EXCL|os.O_CREATE, 0644)
f, err := os.OpenFile(fname, os.O_RDWR|os.O_EXCL|os.O_CREATE, 0o644)
if os.IsExist(err) {
return false, nil
}
@ -76,7 +78,7 @@ func (s *Store) Reserve(id string, ifname string, ip net.IP, rangeID string) (bo
}
// store the reserved ip in lastIPFile
ipfile := GetEscapedPath(s.dataDir, lastIPFilePrefix+rangeID)
err = os.WriteFile(ipfile, []byte(ip.String()), 0644)
err = os.WriteFile(ipfile, []byte(ip.String()), 0o644)
if err != nil {
return false, err
}
@ -93,7 +95,7 @@ func (s *Store) LastReservedIP(rangeID string) (net.IP, error) {
return net.ParseIP(string(data)), nil
}
func (s *Store) FindByKey(id string, ifname string, match string) (bool, error) {
func (s *Store) FindByKey(match string) (bool, error) {
found := false
err := filepath.Walk(s.dataDir, func(path string, info os.FileInfo, err error) error {
@ -110,27 +112,25 @@ func (s *Store) FindByKey(id string, ifname string, match string) (bool, error)
return nil
})
return found, err
}
func (s *Store) FindByID(id string, ifname string) bool {
s.Lock()
defer s.Unlock()
found := false
match := strings.TrimSpace(id) + LineBreak + ifname
found, err := s.FindByKey(id, ifname, match)
found, err := s.FindByKey(match)
// Match anything created by this id
if !found && err == nil {
match := strings.TrimSpace(id)
found, err = s.FindByKey(id, ifname, match)
found, _ = s.FindByKey(match)
}
return found
}
func (s *Store) ReleaseByKey(id string, ifname string, match string) (bool, error) {
func (s *Store) ReleaseByKey(match string) (bool, error) {
found := false
err := filepath.Walk(s.dataDir, func(path string, info os.FileInfo, err error) error {
if err != nil || info.IsDir() {
@ -149,20 +149,18 @@ func (s *Store) ReleaseByKey(id string, ifname string, match string) (bool, erro
return nil
})
return found, err
}
// N.B. This function eats errors to be tolerant and
// release as much as possible
func (s *Store) ReleaseByID(id string, ifname string) error {
found := false
match := strings.TrimSpace(id) + LineBreak + ifname
found, err := s.ReleaseByKey(id, ifname, match)
found, err := s.ReleaseByKey(match)
// For backwards compatibility, look for files written by a previous version
if !found && err == nil {
match := strings.TrimSpace(id)
found, err = s.ReleaseByKey(id, ifname, match)
_, err = s.ReleaseByKey(match)
}
return err
}
@ -198,7 +196,7 @@ func (s *Store) GetByID(id string, ifname string) []net.IP {
func GetEscapedPath(dataDir string, fname string) string {
if runtime.GOOS == "windows" {
fname = strings.Replace(fname, ":", "_", -1)
fname = strings.ReplaceAll(fname, ":", "_")
}
return filepath.Join(dataDir, fname)
}

View File

@ -15,10 +15,10 @@
package disk
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestLock(t *testing.T) {

View File

@ -15,9 +15,10 @@
package disk
import (
"github.com/alexflint/go-filemutex"
"os"
"path"
"github.com/alexflint/go-filemutex"
)
// FileLock wraps os.File to be used as a lock using flock

View File

@ -18,7 +18,7 @@ import (
"os"
"path/filepath"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
@ -30,7 +30,7 @@ var _ = Describe("Lock Operations", func() {
// create a dummy file to lock
path := filepath.Join(dir, "x")
f, err := os.OpenFile(path, os.O_RDONLY|os.O_CREATE, 0666)
f, err := os.OpenFile(path, os.O_RDONLY|os.O_CREATE, 0o666)
Expect(err).ToNot(HaveOccurred())
err = f.Close()
Expect(err).ToNot(HaveOccurred())

View File

@ -45,7 +45,7 @@ func (s *FakeStore) Close() error {
return nil
}
func (s *FakeStore) Reserve(id string, ifname string, ip net.IP, rangeID string) (bool, error) {
func (s *FakeStore) Reserve(id string, _ string, ip net.IP, rangeID string) (bool, error) {
key := ip.String()
if _, ok := s.ipMap[key]; !ok {
s.ipMap[key] = id
@ -63,7 +63,7 @@ func (s *FakeStore) LastReservedIP(rangeID string) (net.IP, error) {
return ip, nil
}
func (s *FakeStore) ReleaseByID(id string, ifname string) error {
func (s *FakeStore) ReleaseByID(id string, _ string) error {
toDelete := []string{}
for k, v := range s.ipMap {
if v == id {
@ -76,7 +76,7 @@ func (s *FakeStore) ReleaseByID(id string, ifname string) error {
return nil
}
func (s *FakeStore) GetByID(id string, ifname string) []net.IP {
func (s *FakeStore) GetByID(id string, _ string) []net.IP {
var ips []net.IP
for k, v := range s.ipMap {
if v == id {

View File

@ -17,9 +17,10 @@ package main
import (
"os"
"github.com/containernetworking/cni/pkg/types"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/containernetworking/cni/pkg/types"
)
var _ = Describe("parsing resolv.conf", func() {

View File

@ -15,10 +15,10 @@
package main
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestHostLocal(t *testing.T) {

View File

@ -21,14 +21,14 @@ import (
"path/filepath"
"strings"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/types"
types100 "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/plugins/pkg/testutils"
"github.com/containernetworking/plugins/plugins/ipam/host-local/backend/disk"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
const LineBreak = "\r\n"
@ -57,7 +57,7 @@ var _ = Describe("host-local Operations", func() {
ver := ver
It(fmt.Sprintf("[%s] allocates and releases addresses with ADD/DEL", ver), func() {
err := os.WriteFile(filepath.Join(tmpDir, "resolv.conf"), []byte("nameserver 192.0.2.3"), 0644)
err := os.WriteFile(filepath.Join(tmpDir, "resolv.conf"), []byte("nameserver 192.0.2.3"), 0o644)
Expect(err).NotTo(HaveOccurred())
conf := fmt.Sprintf(`{
@ -114,7 +114,7 @@ var _ = Describe("host-local Operations", func() {
Gateway: net.ParseIP("2001:db8:1::1"),
},
))
Expect(len(result.IPs)).To(Equal(2))
Expect(result.IPs).To(HaveLen(2))
for _, expectedRoute := range []*types.Route{
{Dst: mustCIDR("0.0.0.0/0"), GW: nil},
@ -166,7 +166,7 @@ var _ = Describe("host-local Operations", func() {
It(fmt.Sprintf("[%s] allocates and releases addresses on specific interface with ADD/DEL", ver), func() {
const ifname1 string = "eth1"
err := os.WriteFile(filepath.Join(tmpDir, "resolv.conf"), []byte("nameserver 192.0.2.3"), 0644)
err := os.WriteFile(filepath.Join(tmpDir, "resolv.conf"), []byte("nameserver 192.0.2.3"), 0o644)
Expect(err).NotTo(HaveOccurred())
conf0 := fmt.Sprintf(`{
@ -310,7 +310,7 @@ var _ = Describe("host-local Operations", func() {
result0, err := types100.GetResult(r0)
Expect(err).NotTo(HaveOccurred())
Expect(len(result0.IPs)).Should(Equal(1))
Expect(result0.IPs).Should(HaveLen(1))
Expect(result0.IPs[0].Address.String()).Should(Equal("10.1.2.2/24"))
// Allocate the IP with the same container ID
@ -330,7 +330,7 @@ var _ = Describe("host-local Operations", func() {
result1, err := types100.GetResult(r1)
Expect(err).NotTo(HaveOccurred())
Expect(len(result1.IPs)).Should(Equal(1))
Expect(result1.IPs).Should(HaveLen(1))
Expect(result1.IPs[0].Address.String()).Should(Equal("10.1.2.3/24"))
// Allocate the IP with the same container ID again
@ -356,7 +356,7 @@ var _ = Describe("host-local Operations", func() {
})
It(fmt.Sprintf("[%s] verify DEL works on backwards compatible allocate", ver), func() {
err := os.WriteFile(filepath.Join(tmpDir, "resolv.conf"), []byte("nameserver 192.0.2.3"), 0644)
err := os.WriteFile(filepath.Join(tmpDir, "resolv.conf"), []byte("nameserver 192.0.2.3"), 0o644)
Expect(err).NotTo(HaveOccurred())
conf := fmt.Sprintf(`{
@ -397,7 +397,7 @@ var _ = Describe("host-local Operations", func() {
contents, err := os.ReadFile(ipFilePath)
Expect(err).NotTo(HaveOccurred())
Expect(string(contents)).To(Equal(args.ContainerID + LineBreak + ifname))
err = os.WriteFile(ipFilePath, []byte(strings.TrimSpace(args.ContainerID)), 0644)
err = os.WriteFile(ipFilePath, []byte(strings.TrimSpace(args.ContainerID)), 0o644)
Expect(err).NotTo(HaveOccurred())
err = testutils.CmdDelWithArgs(args, func() error {
@ -504,7 +504,7 @@ var _ = Describe("host-local Operations", func() {
return cmdAdd(args)
})
Expect(err).NotTo(HaveOccurred())
Expect(strings.Index(string(out), "Error retriving last reserved ip")).To(Equal(-1))
Expect(strings.Index(string(out), "Error retrieving last reserved ip")).To(Equal(-1))
})
It(fmt.Sprintf("[%s] allocates a custom IP when requested by config args", ver), func() {
@ -546,7 +546,7 @@ var _ = Describe("host-local Operations", func() {
})
It(fmt.Sprintf("[%s] allocates custom IPs from multiple ranges", ver), func() {
err := os.WriteFile(filepath.Join(tmpDir, "resolv.conf"), []byte("nameserver 192.0.2.3"), 0644)
err := os.WriteFile(filepath.Join(tmpDir, "resolv.conf"), []byte("nameserver 192.0.2.3"), 0o644)
Expect(err).NotTo(HaveOccurred())
conf := fmt.Sprintf(`{
@ -594,7 +594,7 @@ var _ = Describe("host-local Operations", func() {
})
It(fmt.Sprintf("[%s] allocates custom IPs from multiple protocols", ver), func() {
err := os.WriteFile(filepath.Join(tmpDir, "resolv.conf"), []byte("nameserver 192.0.2.3"), 0644)
err := os.WriteFile(filepath.Join(tmpDir, "resolv.conf"), []byte("nameserver 192.0.2.3"), 0o644)
Expect(err).NotTo(HaveOccurred())
conf := fmt.Sprintf(`{

View File

@ -19,14 +19,13 @@ import (
"net"
"strings"
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
"github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator"
"github.com/containernetworking/plugins/plugins/ipam/host-local/backend/disk"
"github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/types"
current "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/cni/pkg/version"
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
"github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator"
"github.com/containernetworking/plugins/plugins/ipam/host-local/backend/disk"
)
func main() {
@ -34,7 +33,6 @@ func main() {
}
func cmdCheck(args *skel.CmdArgs) error {
ipamConf, _, err := allocator.LoadIPAMConfig(args.StdinData, args.Args)
if err != nil {
return err
@ -48,8 +46,8 @@ func cmdCheck(args *skel.CmdArgs) error {
}
defer store.Close()
containerIpFound := store.FindByID(args.ContainerID, args.IfName)
if containerIpFound == false {
containerIPFound := store.FindByID(args.ContainerID, args.IfName)
if !containerIPFound {
return fmt.Errorf("host-local: Failed to find address added by container %v", args.ContainerID)
}
@ -84,7 +82,7 @@ func cmdAdd(args *skel.CmdArgs) error {
// Store all requested IPs in a map, so we can easily remove ones we use
// and error if some remain
requestedIPs := map[string]net.IP{} //net.IP cannot be a key
requestedIPs := map[string]net.IP{} // net.IP cannot be a key
for _, ip := range ipamConf.IPArgs {
requestedIPs[ip.String()] = ip

View File

@ -276,7 +276,7 @@ func cmdAdd(args *skel.CmdArgs) error {
return types.PrintResult(result, confVersion)
}
func cmdDel(args *skel.CmdArgs) error {
func cmdDel(_ *skel.CmdArgs) error {
// Nothing required because of no resource allocation in static plugin.
return nil
}

View File

@ -17,7 +17,7 @@ package main_test
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

View File

@ -19,13 +19,13 @@ import (
"net"
"strings"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/types"
types100 "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/plugins/pkg/testutils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("static Operations", func() {
@ -97,7 +97,7 @@ var _ = Describe("static Operations", func() {
Gateway: net.ParseIP("3ffe:ffff:0::1"),
},
))
Expect(len(result.IPs)).To(Equal(2))
Expect(result.IPs).To(HaveLen(2))
Expect(result.Routes).To(Equal([]*types.Route{
{Dst: mustCIDR("0.0.0.0/0")},
@ -206,7 +206,7 @@ var _ = Describe("static Operations", func() {
Gateway: net.ParseIP("10.10.0.254"),
}))
Expect(len(result.IPs)).To(Equal(1))
Expect(result.IPs).To(HaveLen(1))
Expect(result.Routes).To(Equal([]*types.Route{
{Dst: mustCIDR("0.0.0.0/0")},
@ -272,7 +272,7 @@ var _ = Describe("static Operations", func() {
Gateway: nil,
}))
Expect(len(result.IPs)).To(Equal(2))
Expect(result.IPs).To(HaveLen(2))
// Release the IP
err = testutils.CmdDelWithArgs(args, func() error {
@ -337,7 +337,7 @@ var _ = Describe("static Operations", func() {
Address: mustCIDR("3ffe:ffff:0:01ff::1/64"),
},
))
Expect(len(result.IPs)).To(Equal(2))
Expect(result.IPs).To(HaveLen(2))
Expect(result.Routes).To(Equal([]*types.Route{
{Dst: mustCIDR("0.0.0.0/0"), GW: net.ParseIP("10.10.0.254")},
{Dst: mustCIDR("3ffe:ffff:0:01ff::1/64"), GW: net.ParseIP("3ffe:ffff:0::1")},
@ -407,7 +407,7 @@ var _ = Describe("static Operations", func() {
Address: mustCIDR("3ffe:ffff:0:01ff::1/64"),
},
))
Expect(len(result.IPs)).To(Equal(2))
Expect(result.IPs).To(HaveLen(2))
Expect(result.Routes).To(Equal([]*types.Route{
{Dst: mustCIDR("0.0.0.0/0"), GW: net.ParseIP("10.10.0.254")},
{Dst: mustCIDR("3ffe:ffff:0:01ff::1/64"), GW: net.ParseIP("3ffe:ffff:0::1")},
@ -482,7 +482,7 @@ var _ = Describe("static Operations", func() {
Address: mustCIDR("3ffe:ffff:0:01ff::1/64"),
},
))
Expect(len(result.IPs)).To(Equal(2))
Expect(result.IPs).To(HaveLen(2))
Expect(result.Routes).To(Equal([]*types.Route{
{Dst: mustCIDR("0.0.0.0/0"), GW: net.ParseIP("10.10.0.254")},
{Dst: mustCIDR("3ffe:ffff:0:01ff::1/64"), GW: net.ParseIP("3ffe:ffff:0::1")},

View File

@ -21,6 +21,7 @@ import (
"net"
"os"
"runtime"
"sort"
"syscall"
"time"
@ -46,17 +47,19 @@ const defaultBrName = "cni0"
type NetConf struct {
types.NetConf
BrName string `json:"bridge"`
IsGW bool `json:"isGateway"`
IsDefaultGW bool `json:"isDefaultGateway"`
ForceAddress bool `json:"forceAddress"`
IPMasq bool `json:"ipMasq"`
MTU int `json:"mtu"`
HairpinMode bool `json:"hairpinMode"`
PromiscMode bool `json:"promiscMode"`
Vlan int `json:"vlan"`
MacSpoofChk bool `json:"macspoofchk,omitempty"`
EnableDad bool `json:"enabledad,omitempty"`
BrName string `json:"bridge"`
IsGW bool `json:"isGateway"`
IsDefaultGW bool `json:"isDefaultGateway"`
ForceAddress bool `json:"forceAddress"`
IPMasq bool `json:"ipMasq"`
MTU int `json:"mtu"`
HairpinMode bool `json:"hairpinMode"`
PromiscMode bool `json:"promiscMode"`
Vlan int `json:"vlan"`
VlanTrunk []*VlanTrunk `json:"vlanTrunk,omitempty"`
PreserveDefaultVlan bool `json:"preserveDefaultVlan"`
MacSpoofChk bool `json:"macspoofchk,omitempty"`
EnableDad bool `json:"enabledad,omitempty"`
Args struct {
Cni BridgeArgs `json:"cni,omitempty"`
@ -65,7 +68,14 @@ type NetConf struct {
Mac string `json:"mac,omitempty"`
} `json:"runtimeConfig,omitempty"`
mac string
mac string
vlans []int
}
type VlanTrunk struct {
MinID *int `json:"minID,omitempty"`
MaxID *int `json:"maxID,omitempty"`
ID *int `json:"id,omitempty"`
}
type BridgeArgs struct {
@ -94,6 +104,8 @@ func init() {
func loadNetConf(bytes []byte, envArgs string) (*NetConf, string, error) {
n := &NetConf{
BrName: defaultBrName,
// Set default value equal to true to maintain existing behavior.
PreserveDefaultVlan: true,
}
if err := json.Unmarshal(bytes, n); err != nil {
return nil, "", fmt.Errorf("failed to load netconf: %v", err)
@ -101,6 +113,17 @@ func loadNetConf(bytes []byte, envArgs string) (*NetConf, string, error) {
if n.Vlan < 0 || n.Vlan > 4094 {
return nil, "", fmt.Errorf("invalid VLAN ID %d (must be between 0 and 4094)", n.Vlan)
}
var err error
n.vlans, err = collectVlanTrunk(n.VlanTrunk)
if err != nil {
// fail to parsing
return nil, "", err
}
// Currently bridge CNI only support access port(untagged only) or trunk port(tagged only)
if n.Vlan > 0 && n.vlans != nil {
return nil, "", errors.New("cannot set vlan and vlanTrunk at the same time")
}
if envArgs != "" {
e := MacEnvArgs{}
@ -124,12 +147,66 @@ func loadNetConf(bytes []byte, envArgs string) (*NetConf, string, error) {
return n, n.CNIVersion, nil
}
// This method is copied from https://github.com/k8snetworkplumbingwg/ovs-cni/blob/v0.27.2/pkg/plugin/plugin.go
func collectVlanTrunk(vlanTrunk []*VlanTrunk) ([]int, error) {
if vlanTrunk == nil {
return nil, nil
}
vlanMap := make(map[int]struct{})
for _, item := range vlanTrunk {
var minID int
var maxID int
var ID int
switch {
case item.MinID != nil && item.MaxID != nil:
minID = *item.MinID
if minID <= 0 || minID > 4094 {
return nil, errors.New("incorrect trunk minID parameter")
}
maxID = *item.MaxID
if maxID <= 0 || maxID > 4094 {
return nil, errors.New("incorrect trunk maxID parameter")
}
if maxID < minID {
return nil, errors.New("minID is greater than maxID in trunk parameter")
}
for v := minID; v <= maxID; v++ {
vlanMap[v] = struct{}{}
}
case item.MinID == nil && item.MaxID != nil:
return nil, errors.New("minID and maxID should be configured simultaneously, minID is missing")
case item.MinID != nil && item.MaxID == nil:
return nil, errors.New("minID and maxID should be configured simultaneously, maxID is missing")
}
// single vid
if item.ID != nil {
ID = *item.ID
if ID <= 0 || ID > 4094 {
return nil, errors.New("incorrect trunk id parameter")
}
vlanMap[ID] = struct{}{}
}
}
if len(vlanMap) == 0 {
return nil, nil
}
vlans := make([]int, 0, len(vlanMap))
for k := range vlanMap {
vlans = append(vlans, k)
}
sort.Slice(vlans, func(i int, j int) bool { return vlans[i] < vlans[j] })
return vlans, nil
}
// calcGateways processes the results from the IPAM plugin and does the
// following for each IP family:
// - Calculates and compiles a list of gateway addresses
// - Adds a default route if needed
func calcGateways(result *current.Result, n *NetConf) (*gwInfo, *gwInfo, error) {
gwsV4 := &gwInfo{}
gwsV6 := &gwInfo{}
@ -300,8 +377,8 @@ func ensureBridge(brName string, mtu int, promiscMode, vlanFiltering bool) (*net
return br, nil
}
func ensureVlanInterface(br *netlink.Bridge, vlanId int) (netlink.Link, error) {
name := fmt.Sprintf("%s.%d", br.Name, vlanId)
func ensureVlanInterface(br *netlink.Bridge, vlanID int, preserveDefaultVlan bool) (netlink.Link, error) {
name := fmt.Sprintf("%s.%d", br.Name, vlanID)
brGatewayVeth, err := netlink.LinkByName(name)
if err != nil {
@ -314,7 +391,7 @@ func ensureVlanInterface(br *netlink.Bridge, vlanId int) (netlink.Link, error) {
return nil, fmt.Errorf("faild to find host namespace: %v", err)
}
_, brGatewayIface, err := setupVeth(hostNS, br, name, br.MTU, false, vlanId, "")
_, brGatewayIface, err := setupVeth(hostNS, br, name, br.MTU, false, vlanID, nil, preserveDefaultVlan, "")
if err != nil {
return nil, fmt.Errorf("faild to create vlan gateway %q: %v", name, err)
}
@ -333,7 +410,7 @@ func ensureVlanInterface(br *netlink.Bridge, vlanId int) (netlink.Link, error) {
return brGatewayVeth, nil
}
func setupVeth(netns ns.NetNS, br *netlink.Bridge, ifName string, mtu int, hairpinMode bool, vlanID int, mac string) (*current.Interface, *current.Interface, error) {
func setupVeth(netns ns.NetNS, br *netlink.Bridge, ifName string, mtu int, hairpinMode bool, vlanID int, vlans []int, preserveDefaultVlan bool, mac string) (*current.Interface, *current.Interface, error) {
contIface := &current.Interface{}
hostIface := &current.Interface{}
@ -370,6 +447,14 @@ func setupVeth(netns ns.NetNS, br *netlink.Bridge, ifName string, mtu int, hairp
return nil, nil, fmt.Errorf("failed to setup hairpin mode for %v: %v", hostVeth.Attrs().Name, err)
}
if (vlanID != 0 || len(vlans) > 0) && !preserveDefaultVlan {
err = removeDefaultVlan(hostVeth)
if err != nil {
return nil, nil, fmt.Errorf("failed to remove default vlan on interface %q: %v", hostIface.Name, err)
}
}
// Currently bridge CNI only support access port(untagged only) or trunk port(tagged only)
if vlanID != 0 {
err = netlink.BridgeVlanAdd(hostVeth, uint16(vlanID), true, true, false, true)
if err != nil {
@ -377,16 +462,45 @@ func setupVeth(netns ns.NetNS, br *netlink.Bridge, ifName string, mtu int, hairp
}
}
for _, v := range vlans {
err = netlink.BridgeVlanAdd(hostVeth, uint16(v), false, false, false, true)
if err != nil {
return nil, nil, fmt.Errorf("failed to setup vlan tag on interface %q: %w", hostIface.Name, err)
}
}
return hostIface, contIface, nil
}
func removeDefaultVlan(hostVeth netlink.Link) error {
vlanInfo, err := netlink.BridgeVlanList()
if err != nil {
return err
}
brVlanInfo, ok := vlanInfo[int32(hostVeth.Attrs().Index)]
if ok {
for _, info := range brVlanInfo {
err = netlink.BridgeVlanDel(hostVeth, info.Vid, false, false, false, true)
if err != nil {
return err
}
}
}
return nil
}
func calcGatewayIP(ipn *net.IPNet) net.IP {
nid := ipn.IP.Mask(ipn.Mask)
return ip.NextIP(nid)
}
func setupBridge(n *NetConf) (*netlink.Bridge, *current.Interface, error) {
vlanFiltering := n.Vlan != 0
vlanFiltering := false
if n.Vlan != 0 || n.VlanTrunk != nil {
vlanFiltering = true
}
// create bridge if necessary
br, err := ensureBridge(n.BrName, n.MTU, n.PromiscMode, vlanFiltering)
if err != nil {
@ -407,7 +521,7 @@ func enableIPForward(family int) error {
}
func cmdAdd(args *skel.CmdArgs) error {
var success bool = false
success := false
n, cniVersion, err := loadNetConf(args.StdinData, args.Args)
if err != nil {
@ -421,7 +535,7 @@ func cmdAdd(args *skel.CmdArgs) error {
}
if n.HairpinMode && n.PromiscMode {
return fmt.Errorf("cannot set hairpin mode and promiscuous mode at the same time.")
return fmt.Errorf("cannot set hairpin mode and promiscuous mode at the same time")
}
br, brInterface, err := setupBridge(n)
@ -435,7 +549,7 @@ func cmdAdd(args *skel.CmdArgs) error {
}
defer netns.Close()
hostInterface, containerInterface, err := setupVeth(netns, br, args.IfName, n.MTU, n.HairpinMode, n.Vlan, n.mac)
hostInterface, containerInterface, err := setupVeth(netns, br, args.IfName, n.MTU, n.HairpinMode, n.Vlan, n.vlans, n.PreserveDefaultVlan, n.mac)
if err != nil {
return err
}
@ -509,10 +623,7 @@ func cmdAdd(args *skel.CmdArgs) error {
_, _ = sysctl.Sysctl(fmt.Sprintf("net/ipv4/conf/%s/arp_notify", args.IfName), "1")
// Add the IP to the interface
if err := ipam.ConfigureIface(args.IfName, result); err != nil {
return err
}
return nil
return ipam.ConfigureIface(args.IfName, result)
}); err != nil {
return err
}
@ -527,14 +638,16 @@ func cmdAdd(args *skel.CmdArgs) error {
firstV4Addr = gw.IP
}
if n.Vlan != 0 {
vlanIface, err := ensureVlanInterface(br, n.Vlan)
vlanIface, err := ensureVlanInterface(br, n.Vlan, n.PreserveDefaultVlan)
if err != nil {
return fmt.Errorf("failed to create vlan interface: %v", err)
}
if vlanInterface == nil {
vlanInterface = &current.Interface{Name: vlanIface.Attrs().Name,
Mac: vlanIface.Attrs().HardwareAddr.String()}
vlanInterface = &current.Interface{
Name: vlanIface.Attrs().Name,
Mac: vlanIface.Attrs().HardwareAddr.String(),
}
result.Interfaces = append(result.Interfaces, vlanInterface)
}
@ -720,7 +833,6 @@ type cniBridgeIf struct {
}
func validateInterface(intf current.Interface, expectInSb bool) (cniBridgeIf, netlink.Link, error) {
ifFound := cniBridgeIf{found: false}
if intf.Name == "" {
return ifFound, nil, fmt.Errorf("Interface name missing ")
@ -745,7 +857,6 @@ func validateInterface(intf current.Interface, expectInSb bool) (cniBridgeIf, ne
}
func validateCniBrInterface(intf current.Interface, n *NetConf) (cniBridgeIf, error) {
brFound, link, err := validateInterface(intf, false)
if err != nil {
return brFound, err
@ -777,7 +888,6 @@ func validateCniBrInterface(intf current.Interface, n *NetConf) (cniBridgeIf, er
}
func validateCniVethInterface(intf *current.Interface, brIf cniBridgeIf, contIf cniBridgeIf) (cniBridgeIf, error) {
vethFound, link, err := validateInterface(*intf, false)
if err != nil {
return vethFound, err
@ -821,7 +931,6 @@ func validateCniVethInterface(intf *current.Interface, brIf cniBridgeIf, contIf
}
func validateCniContainerInterface(intf current.Interface) (cniBridgeIf, error) {
vethFound, link, err := validateInterface(intf, true)
if err != nil {
return vethFound, err
@ -850,7 +959,6 @@ func validateCniContainerInterface(intf current.Interface) (cniBridgeIf, error)
}
func cmdCheck(args *skel.CmdArgs) error {
n, _, err := loadNetConf(args.StdinData, args.Args)
if err != nil {
return err
@ -957,7 +1065,7 @@ func cmdCheck(args *skel.CmdArgs) error {
}
// Check prevResults for ips, routes and dns against values found in the container
if err := netns.Do(func(_ ns.NetNS) error {
return netns.Do(func(_ ns.NetNS) error {
err = ip.ValidateExpectedInterfaceIPs(args.IfName, result.IPs)
if err != nil {
return err
@ -968,11 +1076,7 @@ func cmdCheck(args *skel.CmdArgs) error {
return err
}
return nil
}); err != nil {
return err
}
return nil
})
}
func uniqueID(containerID, cniIface string) string {

View File

@ -15,13 +15,26 @@
package main
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
var (
resolvConf string
err error
)
func TestBridge(t *testing.T) {
RegisterFailHandler(Fail)
resolvConf, err = newResolvConf()
Expect(err).NotTo(HaveOccurred())
RunSpecs(t, "plugins/main/bridge")
}
var _ = AfterSuite(func() {
deleteResolvConf(resolvConf)
})

View File

@ -23,6 +23,9 @@ import (
"github.com/coreos/go-iptables/iptables"
"github.com/networkplumbing/go-nft/nft"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/vishvananda/netlink"
"github.com/vishvananda/netlink/nl"
"github.com/containernetworking/cni/pkg/skel"
@ -32,12 +35,7 @@ import (
"github.com/containernetworking/plugins/pkg/ip"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containernetworking/plugins/pkg/testutils"
"github.com/vishvananda/netlink"
"github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
const (
@ -53,10 +51,11 @@ type Net struct {
Type string `json:"type,omitempty"`
BrName string `json:"bridge"`
IPAM *allocator.IPAMConfig `json:"ipam"`
//RuntimeConfig struct { // The capability arg
// RuntimeConfig struct { // The capability arg
// IPRanges []RangeSet `json:"ipRanges,omitempty"`
//} `json:"runtimeConfig,omitempty"`
//Args *struct {
// Args *struct {
// } `json:"runtimeConfig,omitempty"`
// A *IPAMArgs `json:"cni"`
DNS types.DNS `json:"dns"`
RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
@ -66,21 +65,23 @@ type Net struct {
// testCase defines the CNI network configuration and the expected
// bridge addresses for a test case.
type testCase struct {
cniVersion string // CNI Version
subnet string // Single subnet config: Subnet CIDR
gateway string // Single subnet config: Gateway
ranges []rangeInfo // Ranges list (multiple subnets config)
resolvConf string // host-local resolvConf file path
isGW bool
isLayer2 bool
expGWCIDRs []string // Expected gateway addresses in CIDR form
vlan int
ipMasq bool
macspoofchk bool
AddErr020 string
DelErr020 string
AddErr010 string
DelErr010 string
cniVersion string // CNI Version
subnet string // Single subnet config: Subnet CIDR
gateway string // Single subnet config: Gateway
ranges []rangeInfo // Ranges list (multiple subnets config)
resolvConf string // host-local resolvConf file path
isGW bool
isLayer2 bool
expGWCIDRs []string // Expected gateway addresses in CIDR form
vlan int
vlanTrunk []*VlanTrunk
removeDefaultVlan bool
ipMasq bool
macspoofchk bool
AddErr020 string
DelErr020 string
AddErr010 string
DelErr010 string
envArgs string // CNI_ARGS
runtimeConfig struct {
@ -130,6 +131,26 @@ const (
vlan = `,
"vlan": %d`
vlanTrunkStartStr = `,
"vlanTrunk": [`
vlanTrunk = `
{
"id": %d
}`
vlanTrunkRange = `
{
"minID": %d,
"maxID": %d
}`
vlanTrunkEndStr = `
]`
preserveDefaultVlan = `,
"preserveDefaultVlan": false`
netDefault = `,
"isDefaultGateway": true`
@ -192,7 +213,28 @@ func (tc testCase) netConfJSON(dataDir string) string {
conf := fmt.Sprintf(netConfStr, tc.cniVersion, BRNAME)
if tc.vlan != 0 {
conf += fmt.Sprintf(vlan, tc.vlan)
if tc.removeDefaultVlan {
conf += preserveDefaultVlan
}
}
if tc.isLayer2 && tc.vlanTrunk != nil {
conf += vlanTrunkStartStr
for i, vlan := range tc.vlanTrunk {
if i > 0 {
conf += ","
}
if vlan.ID != nil {
conf += fmt.Sprintf(vlanTrunk, *vlan.ID)
}
if vlan.MinID != nil && vlan.MaxID != nil {
conf += fmt.Sprintf(vlanTrunkRange, *vlan.MinID, *vlan.MaxID)
}
}
conf += vlanTrunkEndStr
}
if tc.ipMasq {
conf += tc.ipMasqConfig()
}
@ -285,7 +327,7 @@ var counter uint
// arguments for a test case.
func (tc testCase) createCmdArgs(targetNS ns.NetNS, dataDir string) *skel.CmdArgs {
conf := tc.netConfJSON(dataDir)
//defer func() { counter += 1 }()
// defer func() { counter += 1 }()
return &skel.CmdArgs{
ContainerID: fmt.Sprintf("dummy-%d", counter),
Netns: targetNS.Path(),
@ -297,18 +339,17 @@ func (tc testCase) createCmdArgs(targetNS ns.NetNS, dataDir string) *skel.CmdArg
// createCheckCmdArgs generates network configuration and creates command
// arguments for a Check test case.
func (tc testCase) createCheckCmdArgs(targetNS ns.NetNS, config *Net, dataDir string) *skel.CmdArgs {
func (tc testCase) createCheckCmdArgs(targetNS ns.NetNS, config *Net) *skel.CmdArgs {
conf, err := json.Marshal(config)
Expect(err).NotTo(HaveOccurred())
// TODO Don't we need to use the same counter as before?
//defer func() { counter += 1 }()
// defer func() { counter += 1 }()
return &skel.CmdArgs{
ContainerID: fmt.Sprintf("dummy-%d", counter),
Netns: targetNS.Path(),
IfName: IFNAME,
StdinData: []byte(conf),
StdinData: conf,
}
}
@ -412,9 +453,9 @@ func countIPAMIPs(path string) (int, error) {
return count, nil
}
func checkVlan(vlanId int, bridgeVlanInfo []*nl.BridgeVlanInfo) bool {
func checkVlan(vlanID int, bridgeVlanInfo []*nl.BridgeVlanInfo) bool {
for _, vlan := range bridgeVlanInfo {
if vlan.Vid == uint16(vlanId) {
if vlan.Vid == uint16(vlanID) {
return true
}
}
@ -435,10 +476,12 @@ type testerBase struct {
vethName string
}
type testerV10x testerBase
type testerV04x testerBase
type testerV03x testerBase
type testerV01xOr02x testerBase
type (
testerV10x testerBase
testerV04x testerBase
testerV03x testerBase
testerV01xOr02x testerBase
)
func newTesterByVersion(version string, testNS, targetNS ns.NetNS) cmdAddDelTester {
switch {
@ -485,9 +528,9 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result,
result = resultType.(*types100.Result)
if !tc.isLayer2 && tc.vlan != 0 {
Expect(len(result.Interfaces)).To(Equal(4))
Expect(result.Interfaces).To(HaveLen(4))
} else {
Expect(len(result.Interfaces)).To(Equal(3))
Expect(result.Interfaces).To(HaveLen(3))
}
Expect(result.Interfaces[0].Name).To(Equal(BRNAME))
@ -527,13 +570,16 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result,
vlans, isExist := interfaceMap[int32(peerLink.Attrs().Index)]
Expect(isExist).To(BeTrue())
Expect(checkVlan(tc.vlan, vlans)).To(BeTrue())
if tc.removeDefaultVlan {
Expect(vlans).To(HaveLen(1))
}
}
// Check the bridge vlan filtering equals true
if tc.vlan != 0 {
Expect(*link.(*netlink.Bridge).VlanFiltering).To(Equal(true))
if tc.vlan != 0 || tc.vlanTrunk != nil {
Expect(*link.(*netlink.Bridge).VlanFiltering).To(BeTrue())
} else {
Expect(*link.(*netlink.Bridge).VlanFiltering).To(Equal(false))
Expect(*link.(*netlink.Bridge).VlanFiltering).To(BeFalse())
}
// Ensure bridge has expected gateway address(es)
@ -544,7 +590,7 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result,
addrs, err = netlink.AddrList(vlanLink, netlink.FAMILY_ALL)
}
Expect(err).NotTo(HaveOccurred())
Expect(len(addrs)).To(BeNumerically(">", 0))
Expect(addrs).ToNot(BeEmpty())
for _, cidr := range tc.expGWCIDRs {
ip, subnet, err := net.ParseCIDR(cidr)
Expect(err).NotTo(HaveOccurred())
@ -558,16 +604,16 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result,
break
}
}
Expect(found).To(Equal(true), fmt.Sprintf("failed to find %s", cidr))
Expect(found).To(BeTrue(), fmt.Sprintf("failed to find %s", cidr))
}
// Check for the veth link in the main namespace
links, err := netlink.LinkList()
Expect(err).NotTo(HaveOccurred())
if !tc.isLayer2 && tc.vlan != 0 {
Expect(len(links)).To(Equal(5)) // Bridge, Bridge vlan veth, veth, and loopback
Expect(links).To(HaveLen(5)) // Bridge, Bridge vlan veth, veth, and loopback
} else {
Expect(len(links)).To(Equal(3)) // Bridge, veth, and loopback
Expect(links).To(HaveLen(3)) // Bridge, veth, and loopback
}
link, err = netlink.LinkByName(result.Interfaces[1].Name)
@ -582,6 +628,28 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result,
vlans, isExist := interfaceMap[int32(link.Attrs().Index)]
Expect(isExist).To(BeTrue())
Expect(checkVlan(tc.vlan, vlans)).To(BeTrue())
if tc.removeDefaultVlan {
Expect(vlans).To(HaveLen(1))
}
}
// check VlanTrunks exist on the veth interface
if tc.vlanTrunk != nil {
interfaceMap, err := netlink.BridgeVlanList()
Expect(err).NotTo(HaveOccurred())
vlans, isExist := interfaceMap[int32(link.Attrs().Index)]
Expect(isExist).To(BeTrue())
for _, vlanEntry := range tc.vlanTrunk {
if vlanEntry.ID != nil {
Expect(checkVlan(*vlanEntry.ID, vlans)).To(BeTrue())
}
if vlanEntry.MinID != nil && vlanEntry.MaxID != nil {
for vid := *vlanEntry.MinID; vid <= *vlanEntry.MaxID; vid++ {
Expect(checkVlan(vid, vlans)).To(BeTrue())
}
}
}
}
// Check that the bridge has a different mac from the veth
@ -613,9 +681,9 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result,
expCIDRsV4, expCIDRsV6 := tc.expectedCIDRs()
addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
Expect(err).NotTo(HaveOccurred())
Expect(len(addrs)).To(Equal(len(expCIDRsV4)))
Expect(addrs).To(HaveLen(len(expCIDRsV4)))
addrs, err = netlink.AddrList(link, netlink.FAMILY_V6)
Expect(len(addrs)).To(Equal(len(expCIDRsV6) + 1)) //add one for the link-local
Expect(addrs).To(HaveLen(len(expCIDRsV6) + 1)) // add one for the link-local
Expect(err).NotTo(HaveOccurred())
// Ignore link local address which may or may not be
// ready when we read addresses.
@ -650,7 +718,7 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result,
break
}
}
Expect(*found).To(Equal(true))
Expect(*found).To(BeTrue())
}
return nil
@ -660,9 +728,9 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result,
return result, nil
}
func (tester *testerV10x) cmdCheckTest(tc testCase, conf *Net, dataDir string) {
func (tester *testerV10x) cmdCheckTest(tc testCase, conf *Net, _ string) {
// Generate network config and command arguments
tester.args = tc.createCheckCmdArgs(tester.targetNS, conf, dataDir)
tester.args = tc.createCheckCmdArgs(tester.targetNS, conf)
// Execute cmdCHECK on the plugin
err := tester.testNS.Do(func(ns.NetNS) error {
@ -689,9 +757,9 @@ func (tester *testerV10x) cmdCheckTest(tc testCase, conf *Net, dataDir string) {
expCIDRsV4, expCIDRsV6 := tc.expectedCIDRs()
addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
Expect(err).NotTo(HaveOccurred())
Expect(len(addrs)).To(Equal(len(expCIDRsV4)))
Expect(addrs).To(HaveLen(len(expCIDRsV4)))
addrs, err = netlink.AddrList(link, netlink.FAMILY_V6)
Expect(len(addrs)).To(Equal(len(expCIDRsV6) + 1)) //add one for the link-local
Expect(addrs).To(HaveLen(len(expCIDRsV6) + 1)) // add one for the link-local
Expect(err).NotTo(HaveOccurred())
// Ignore link local address which may or may not be
// ready when we read addresses.
@ -726,7 +794,7 @@ func (tester *testerV10x) cmdCheckTest(tc testCase, conf *Net, dataDir string) {
break
}
}
Expect(*found).To(Equal(true))
Expect(*found).To(BeTrue())
}
return nil
@ -790,9 +858,9 @@ func (tester *testerV04x) cmdAddTest(tc testCase, dataDir string) (types.Result,
result = resultType.(*types040.Result)
if !tc.isLayer2 && tc.vlan != 0 {
Expect(len(result.Interfaces)).To(Equal(4))
Expect(result.Interfaces).To(HaveLen(4))
} else {
Expect(len(result.Interfaces)).To(Equal(3))
Expect(result.Interfaces).To(HaveLen(3))
}
Expect(result.Interfaces[0].Name).To(Equal(BRNAME))
@ -832,13 +900,16 @@ func (tester *testerV04x) cmdAddTest(tc testCase, dataDir string) (types.Result,
vlans, isExist := interfaceMap[int32(peerLink.Attrs().Index)]
Expect(isExist).To(BeTrue())
Expect(checkVlan(tc.vlan, vlans)).To(BeTrue())
if tc.removeDefaultVlan {
Expect(vlans).To(HaveLen(1))
}
}
// Check the bridge vlan filtering equals true
if tc.vlan != 0 {
Expect(*link.(*netlink.Bridge).VlanFiltering).To(Equal(true))
if tc.vlan != 0 || tc.vlanTrunk != nil {
Expect(*link.(*netlink.Bridge).VlanFiltering).To(BeTrue())
} else {
Expect(*link.(*netlink.Bridge).VlanFiltering).To(Equal(false))
Expect(*link.(*netlink.Bridge).VlanFiltering).To(BeFalse())
}
// Ensure bridge has expected gateway address(es)
@ -849,7 +920,7 @@ func (tester *testerV04x) cmdAddTest(tc testCase, dataDir string) (types.Result,
addrs, err = netlink.AddrList(vlanLink, netlink.FAMILY_ALL)
}
Expect(err).NotTo(HaveOccurred())
Expect(len(addrs)).To(BeNumerically(">", 0))
Expect(addrs).ToNot(BeEmpty())
for _, cidr := range tc.expGWCIDRs {
ip, subnet, err := net.ParseCIDR(cidr)
Expect(err).NotTo(HaveOccurred())
@ -863,16 +934,16 @@ func (tester *testerV04x) cmdAddTest(tc testCase, dataDir string) (types.Result,
break
}
}
Expect(found).To(Equal(true))
Expect(found).To(BeTrue())
}
// Check for the veth link in the main namespace
links, err := netlink.LinkList()
Expect(err).NotTo(HaveOccurred())
if !tc.isLayer2 && tc.vlan != 0 {
Expect(len(links)).To(Equal(5)) // Bridge, Bridge vlan veth, veth, and loopback
Expect(links).To(HaveLen(5)) // Bridge, Bridge vlan veth, veth, and loopback
} else {
Expect(len(links)).To(Equal(3)) // Bridge, veth, and loopback
Expect(links).To(HaveLen(3)) // Bridge, veth, and loopback
}
link, err = netlink.LinkByName(result.Interfaces[1].Name)
@ -887,6 +958,28 @@ func (tester *testerV04x) cmdAddTest(tc testCase, dataDir string) (types.Result,
vlans, isExist := interfaceMap[int32(link.Attrs().Index)]
Expect(isExist).To(BeTrue())
Expect(checkVlan(tc.vlan, vlans)).To(BeTrue())
if tc.removeDefaultVlan {
Expect(vlans).To(HaveLen(1))
}
}
// check VlanTrunks exist on the veth interface
if tc.vlanTrunk != nil {
interfaceMap, err := netlink.BridgeVlanList()
Expect(err).NotTo(HaveOccurred())
vlans, isExist := interfaceMap[int32(link.Attrs().Index)]
Expect(isExist).To(BeTrue())
for _, vlanEntry := range tc.vlanTrunk {
if vlanEntry.ID != nil {
Expect(checkVlan(*vlanEntry.ID, vlans)).To(BeTrue())
}
if vlanEntry.MinID != nil && vlanEntry.MaxID != nil {
for vid := *vlanEntry.MinID; vid <= *vlanEntry.MaxID; vid++ {
Expect(checkVlan(vid, vlans)).To(BeTrue())
}
}
}
}
// Check that the bridge has a different mac from the veth
@ -913,9 +1006,9 @@ func (tester *testerV04x) cmdAddTest(tc testCase, dataDir string) (types.Result,
expCIDRsV4, expCIDRsV6 := tc.expectedCIDRs()
addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
Expect(err).NotTo(HaveOccurred())
Expect(len(addrs)).To(Equal(len(expCIDRsV4)))
Expect(addrs).To(HaveLen(len(expCIDRsV4)))
addrs, err = netlink.AddrList(link, netlink.FAMILY_V6)
Expect(len(addrs)).To(Equal(len(expCIDRsV6) + 1)) //add one for the link-local
Expect(addrs).To(HaveLen(len(expCIDRsV6) + 1)) // add one for the link-local
Expect(err).NotTo(HaveOccurred())
// Ignore link local address which may or may not be
// ready when we read addresses.
@ -950,7 +1043,7 @@ func (tester *testerV04x) cmdAddTest(tc testCase, dataDir string) (types.Result,
break
}
}
Expect(*found).To(Equal(true))
Expect(*found).To(BeTrue())
}
return nil
@ -960,9 +1053,9 @@ func (tester *testerV04x) cmdAddTest(tc testCase, dataDir string) (types.Result,
return result, nil
}
func (tester *testerV04x) cmdCheckTest(tc testCase, conf *Net, dataDir string) {
func (tester *testerV04x) cmdCheckTest(tc testCase, conf *Net, _ string) {
// Generate network config and command arguments
tester.args = tc.createCheckCmdArgs(tester.targetNS, conf, dataDir)
tester.args = tc.createCheckCmdArgs(tester.targetNS, conf)
// Execute cmdCHECK on the plugin
err := tester.testNS.Do(func(ns.NetNS) error {
@ -989,9 +1082,9 @@ func (tester *testerV04x) cmdCheckTest(tc testCase, conf *Net, dataDir string) {
expCIDRsV4, expCIDRsV6 := tc.expectedCIDRs()
addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
Expect(err).NotTo(HaveOccurred())
Expect(len(addrs)).To(Equal(len(expCIDRsV4)))
Expect(addrs).To(HaveLen(len(expCIDRsV4)))
addrs, err = netlink.AddrList(link, netlink.FAMILY_V6)
Expect(len(addrs)).To(Equal(len(expCIDRsV6) + 1)) //add one for the link-local
Expect(addrs).To(HaveLen(len(expCIDRsV6) + 1)) // add one for the link-local
Expect(err).NotTo(HaveOccurred())
// Ignore link local address which may or may not be
// ready when we read addresses.
@ -1026,7 +1119,7 @@ func (tester *testerV04x) cmdCheckTest(tc testCase, conf *Net, dataDir string) {
break
}
}
Expect(*found).To(Equal(true))
Expect(*found).To(BeTrue())
}
return nil
@ -1090,9 +1183,9 @@ func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) (types.Result,
result = resultType.(*types040.Result)
if !tc.isLayer2 && tc.vlan != 0 {
Expect(len(result.Interfaces)).To(Equal(4))
Expect(result.Interfaces).To(HaveLen(4))
} else {
Expect(len(result.Interfaces)).To(Equal(3))
Expect(result.Interfaces).To(HaveLen(3))
}
Expect(result.Interfaces[0].Name).To(Equal(BRNAME))
@ -1132,13 +1225,16 @@ func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) (types.Result,
vlans, isExist := interfaceMap[int32(peerLink.Attrs().Index)]
Expect(isExist).To(BeTrue())
Expect(checkVlan(tc.vlan, vlans)).To(BeTrue())
if tc.removeDefaultVlan {
Expect(vlans).To(HaveLen(1))
}
}
// Check the bridge vlan filtering equals true
if tc.vlan != 0 {
Expect(*link.(*netlink.Bridge).VlanFiltering).To(Equal(true))
if tc.vlan != 0 || tc.vlanTrunk != nil {
Expect(*link.(*netlink.Bridge).VlanFiltering).To(BeTrue())
} else {
Expect(*link.(*netlink.Bridge).VlanFiltering).To(Equal(false))
Expect(*link.(*netlink.Bridge).VlanFiltering).To(BeFalse())
}
// Ensure bridge has expected gateway address(es)
@ -1149,7 +1245,7 @@ func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) (types.Result,
addrs, err = netlink.AddrList(vlanLink, netlink.FAMILY_ALL)
}
Expect(err).NotTo(HaveOccurred())
Expect(len(addrs)).To(BeNumerically(">", 0))
Expect(addrs).ToNot(BeEmpty())
for _, cidr := range tc.expGWCIDRs {
ip, subnet, err := net.ParseCIDR(cidr)
Expect(err).NotTo(HaveOccurred())
@ -1163,16 +1259,16 @@ func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) (types.Result,
break
}
}
Expect(found).To(Equal(true))
Expect(found).To(BeTrue())
}
// Check for the veth link in the main namespace
links, err := netlink.LinkList()
Expect(err).NotTo(HaveOccurred())
if !tc.isLayer2 && tc.vlan != 0 {
Expect(len(links)).To(Equal(5)) // Bridge, Bridge vlan veth, veth, and loopback
Expect(links).To(HaveLen(5)) // Bridge, Bridge vlan veth, veth, and loopback
} else {
Expect(len(links)).To(Equal(3)) // Bridge, veth, and loopback
Expect(links).To(HaveLen(3)) // Bridge, veth, and loopback
}
link, err = netlink.LinkByName(result.Interfaces[1].Name)
@ -1187,6 +1283,28 @@ func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) (types.Result,
vlans, isExist := interfaceMap[int32(link.Attrs().Index)]
Expect(isExist).To(BeTrue())
Expect(checkVlan(tc.vlan, vlans)).To(BeTrue())
if tc.removeDefaultVlan {
Expect(vlans).To(HaveLen(1))
}
}
// check VlanTrunks exist on the veth interface
if tc.vlanTrunk != nil {
interfaceMap, err := netlink.BridgeVlanList()
Expect(err).NotTo(HaveOccurred())
vlans, isExist := interfaceMap[int32(link.Attrs().Index)]
Expect(isExist).To(BeTrue())
for _, vlanEntry := range tc.vlanTrunk {
if vlanEntry.ID != nil {
Expect(checkVlan(*vlanEntry.ID, vlans)).To(BeTrue())
}
if vlanEntry.MinID != nil && vlanEntry.MaxID != nil {
for vid := *vlanEntry.MinID; vid <= *vlanEntry.MaxID; vid++ {
Expect(checkVlan(vid, vlans)).To(BeTrue())
}
}
}
}
// Check that the bridge has a different mac from the veth
@ -1213,7 +1331,7 @@ func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) (types.Result,
expCIDRsV4, expCIDRsV6 := tc.expectedCIDRs()
addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
Expect(err).NotTo(HaveOccurred())
Expect(len(addrs)).To(Equal(len(expCIDRsV4)))
Expect(addrs).To(HaveLen(len(expCIDRsV4)))
addrs, err = netlink.AddrList(link, netlink.FAMILY_V6)
Expect(err).NotTo(HaveOccurred())
// Ignore link local address which may or may not be
@ -1249,7 +1367,7 @@ func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) (types.Result,
break
}
}
Expect(*found).To(Equal(true))
Expect(*found).To(BeTrue())
}
return nil
@ -1258,11 +1376,10 @@ func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) (types.Result,
return result, nil
}
func (tester *testerV03x) cmdCheckTest(tc testCase, conf *Net, dataDir string) {
return
func (tester *testerV03x) cmdCheckTest(_ testCase, _ *Net, _ string) {
}
func (tester *testerV03x) cmdDelTest(tc testCase, dataDir string) {
func (tester *testerV03x) cmdDelTest(_ testCase, _ string) {
err := tester.testNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
@ -1359,13 +1476,16 @@ func (tester *testerV01xOr02x) cmdAddTest(tc testCase, dataDir string) (types.Re
vlans, isExist := interfaceMap[int32(peerLink.Attrs().Index)]
Expect(isExist).To(BeTrue())
Expect(checkVlan(tc.vlan, vlans)).To(BeTrue())
if tc.removeDefaultVlan {
Expect(vlans).To(HaveLen(1))
}
}
// Check the bridge vlan filtering equals true
if tc.vlan != 0 {
Expect(*link.(*netlink.Bridge).VlanFiltering).To(Equal(true))
Expect(*link.(*netlink.Bridge).VlanFiltering).To(BeTrue())
} else {
Expect(*link.(*netlink.Bridge).VlanFiltering).To(Equal(false))
Expect(*link.(*netlink.Bridge).VlanFiltering).To(BeFalse())
}
// Ensure bridge has expected gateway address(es)
@ -1376,7 +1496,7 @@ func (tester *testerV01xOr02x) cmdAddTest(tc testCase, dataDir string) (types.Re
addrs, err = netlink.AddrList(vlanLink, netlink.FAMILY_ALL)
}
Expect(err).NotTo(HaveOccurred())
Expect(len(addrs)).To(BeNumerically(">", 0))
Expect(addrs).ToNot(BeEmpty())
for _, cidr := range tc.expGWCIDRs {
ip, subnet, err := net.ParseCIDR(cidr)
Expect(err).NotTo(HaveOccurred())
@ -1390,7 +1510,7 @@ func (tester *testerV01xOr02x) cmdAddTest(tc testCase, dataDir string) (types.Re
break
}
}
Expect(found).To(Equal(true))
Expect(found).To(BeTrue())
}
// Check for the veth link in the main namespace; can't
@ -1399,9 +1519,9 @@ func (tester *testerV01xOr02x) cmdAddTest(tc testCase, dataDir string) (types.Re
links, err := netlink.LinkList()
Expect(err).NotTo(HaveOccurred())
if !tc.isLayer2 && tc.vlan != 0 {
Expect(len(links)).To(Equal(5)) // Bridge, Bridge vlan veth, veth, and loopback
Expect(links).To(HaveLen(5)) // Bridge, Bridge vlan veth, veth, and loopback
} else {
Expect(len(links)).To(Equal(3)) // Bridge, veth, and loopback
Expect(links).To(HaveLen(3)) // Bridge, veth, and loopback
}
// Grab the vlan map in the host NS for checking later
@ -1432,7 +1552,7 @@ func (tester *testerV01xOr02x) cmdAddTest(tc testCase, dataDir string) (types.Re
expCIDRsV4, expCIDRsV6 := tc.expectedCIDRs()
addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
Expect(err).NotTo(HaveOccurred())
Expect(len(addrs)).To(Equal(len(expCIDRsV4)))
Expect(addrs).To(HaveLen(len(expCIDRsV4)))
addrs, err = netlink.AddrList(link, netlink.FAMILY_V6)
Expect(err).NotTo(HaveOccurred())
// Ignore link local address which may or may not be
@ -1468,7 +1588,7 @@ func (tester *testerV01xOr02x) cmdAddTest(tc testCase, dataDir string) (types.Re
break
}
}
Expect(*found).To(Equal(true))
Expect(*found).To(BeTrue())
}
// Validate VLAN in the host NS. Since 0.1.0/0.2.0 don't return
@ -1481,6 +1601,9 @@ func (tester *testerV01xOr02x) cmdAddTest(tc testCase, dataDir string) (types.Re
vlans, isExist := hostNSVlanMap[int32(peerIndex)]
Expect(isExist).To(BeTrue())
Expect(checkVlan(tc.vlan, vlans)).To(BeTrue())
if tc.removeDefaultVlan {
Expect(vlans).To(HaveLen(1))
}
}
return nil
@ -1489,22 +1612,22 @@ func (tester *testerV01xOr02x) cmdAddTest(tc testCase, dataDir string) (types.Re
return nil, nil
}
func (tester *testerV01xOr02x) cmdCheckTest(tc testCase, conf *Net, dataDir string) {
return
func (tester *testerV01xOr02x) cmdCheckTest(_ testCase, _ *Net, _ string) {
}
func (tester *testerV01xOr02x) cmdDelTest(tc testCase, dataDir string) {
func (tester *testerV01xOr02x) cmdDelTest(tc testCase, _ string) {
err := tester.testNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
err := testutils.CmdDelWithArgs(tester.args, func() error {
return cmdDel(tester.args)
})
if expect020DelError(tc) {
switch {
case expect020DelError(tc):
Expect(err).To(MatchError(tc.DelErr020))
} else if expect010DelError(tc) {
case expect010DelError(tc):
Expect(err).To(MatchError(tc.DelErr010))
} else {
default:
Expect(err).NotTo(HaveOccurred())
}
return nil
@ -1577,7 +1700,6 @@ func buildOneConfig(name, cniVersion string, orig *Net, prevResult types.Result)
}
return conf, nil
}
func cmdAddDelCheckTest(origNS, targetNS ns.NetNS, tc testCase, dataDir string) {
@ -1619,9 +1741,6 @@ var _ = Describe("bridge Operations", func() {
var originalNS, targetNS ns.NetNS
var dataDir string
resolvConf, err := newResolvConf()
Expect(err).NotTo(HaveOccurred())
BeforeEach(func() {
// Create a new NetNS so we don't modify the host
var err error
@ -1645,9 +1764,60 @@ var _ = Describe("bridge Operations", func() {
Expect(testutils.UnmountNS(targetNS)).To(Succeed())
})
AfterSuite(func() {
deleteResolvConf(resolvConf)
})
var (
correctID int = 10
correctMinID int = 100
correctMaxID int = 105
incorrectMinID int = 1000
incorrectMaxID int = 100
overID int = 5000
negativeID int = -1
)
DescribeTable(
"collectVlanTrunk succeeds",
func(vlanTrunks []*VlanTrunk, expectedVIDs []int) {
Expect(collectVlanTrunk(vlanTrunks)).To(ConsistOf(expectedVIDs))
},
Entry("when provided an empty VLAN trunk configuration", []*VlanTrunk{}, nil),
Entry("when provided a VLAN trunk configuration with both min / max range", []*VlanTrunk{
{
MinID: &correctMinID,
MaxID: &correctMaxID,
},
}, []int{100, 101, 102, 103, 104, 105}),
Entry("when provided a VLAN trunk configuration with id only", []*VlanTrunk{
{
ID: &correctID,
},
}, []int{10}),
Entry("when provided a VLAN trunk configuration with id and range", []*VlanTrunk{
{
ID: &correctID,
},
{
MinID: &correctMinID,
MaxID: &correctMaxID,
},
}, []int{10, 100, 101, 102, 103, 104, 105}),
)
DescribeTable(
"collectVlanTrunk failed",
func(vlanTrunks []*VlanTrunk, expectedError error) {
_, err := collectVlanTrunk(vlanTrunks)
Expect(err).To(MatchError(expectedError))
},
Entry("when not passed the maxID", []*VlanTrunk{{MinID: &correctMinID}}, fmt.Errorf("minID and maxID should be configured simultaneously, maxID is missing")),
Entry("when not passed the minID", []*VlanTrunk{{MaxID: &correctMaxID}}, fmt.Errorf("minID and maxID should be configured simultaneously, minID is missing")),
Entry("when the minID is negative", []*VlanTrunk{{MinID: &negativeID, MaxID: &correctMaxID}}, fmt.Errorf("incorrect trunk minID parameter")),
Entry("when the minID is larger than 4094", []*VlanTrunk{{MinID: &overID, MaxID: &correctMaxID}}, fmt.Errorf("incorrect trunk minID parameter")),
Entry("when the maxID is larger than 4094", []*VlanTrunk{{MinID: &correctMinID, MaxID: &overID}}, fmt.Errorf("incorrect trunk maxID parameter")),
Entry("when the maxID is negative", []*VlanTrunk{{MinID: &correctMinID, MaxID: &overID}}, fmt.Errorf("incorrect trunk maxID parameter")),
Entry("when the ID is larger than 4094", []*VlanTrunk{{ID: &overID}}, fmt.Errorf("incorrect trunk id parameter")),
Entry("when the ID is negative", []*VlanTrunk{{ID: &negativeID}}, fmt.Errorf("incorrect trunk id parameter")),
Entry("when the maxID is smaller than minID", []*VlanTrunk{{MinID: &incorrectMinID, MaxID: &incorrectMaxID}}, fmt.Errorf("minID is greater than maxID in trunk parameter")),
)
for _, ver := range testutils.AllSpecVersions {
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
@ -1781,6 +1951,37 @@ var _ = Describe("bridge Operations", func() {
cmdAddDelTest(originalNS, targetNS, tc, dataDir)
})
// TODO find some way to put pointer
It(fmt.Sprintf("[%s] configures and deconfigures a l2 bridge with vlan id 100, vlanTrunk 101,200~210 using ADD/DEL", ver), func() {
id, minID, maxID := 101, 200, 210
tc := testCase{
cniVersion: ver,
isLayer2: true,
vlanTrunk: []*VlanTrunk{
{ID: &id},
{
MinID: &minID,
MaxID: &maxID,
},
},
AddErr020: "cannot convert: no valid IP addresses",
AddErr010: "cannot convert: no valid IP addresses",
}
cmdAddDelTest(originalNS, targetNS, tc, dataDir)
})
It(fmt.Sprintf("[%s] configures and deconfigures a l2 bridge with vlan id 100 and no default vlan using ADD/DEL", ver), func() {
tc := testCase{
cniVersion: ver,
isLayer2: true,
vlan: 100,
removeDefaultVlan: true,
AddErr020: "cannot convert: no valid IP addresses",
AddErr010: "cannot convert: no valid IP addresses",
}
cmdAddDelTest(originalNS, targetNS, tc, dataDir)
})
for i, tc := range []testCase{
{
// IPv4 only
@ -1831,6 +2032,11 @@ var _ = Describe("bridge Operations", func() {
tc.cniVersion = ver
cmdAddDelTest(originalNS, targetNS, tc, dataDir)
})
It(fmt.Sprintf("[%s] (%d) configures and deconfigures a bridge, veth with default route and vlanID 100 and no default vlan with ADD/DEL", ver, i), func() {
tc.cniVersion = ver
tc.removeDefaultVlan = true
cmdAddDelTest(originalNS, targetNS, tc, dataDir)
})
}
for i, tc := range []testCase{
@ -1938,7 +2144,7 @@ var _ = Describe("bridge Operations", func() {
checkBridgeIPs := func(cidr0, cidr1 string) {
addrs, err := netlink.AddrList(bridge, family)
Expect(err).NotTo(HaveOccurred())
Expect(len(addrs)).To(Equal(expNumAddrs))
Expect(addrs).To(HaveLen(expNumAddrs))
addr := addrs[0].IPNet.String()
Expect(addr).To(Equal(cidr0))
if cidr1 != "" {
@ -1948,7 +2154,7 @@ var _ = Describe("bridge Operations", func() {
}
// Check if ForceAddress has default value
Expect(conf.ForceAddress).To(Equal(false))
Expect(conf.ForceAddress).To(BeFalse())
// Set first address on bridge
err = ensureAddr(bridge, family, &gwnFirst, conf.ForceAddress)
@ -1996,8 +2202,6 @@ var _ = Describe("bridge Operations", func() {
It(fmt.Sprintf("[%s] ensure promiscuous mode on bridge", ver), func() {
const IFNAME = "bridge0"
const EXPECTED_IP = "10.0.0.0/8"
const CHANGED_EXPECTED_IP = "10.1.2.3/16"
conf := &NetConf{
NetConf: types.NetConf{
@ -2019,9 +2223,9 @@ var _ = Describe("bridge Operations", func() {
_, _, err := setupBridge(conf)
Expect(err).NotTo(HaveOccurred())
// Check if ForceAddress has default value
Expect(conf.ForceAddress).To(Equal(false))
Expect(conf.ForceAddress).To(BeFalse())
//Check if promiscuous mode is set correctly
// Check if promiscuous mode is set correctly
link, err := netlink.LinkByName("bridge0")
Expect(err).NotTo(HaveOccurred())
@ -2286,7 +2490,7 @@ var _ = Describe("bridge Operations", func() {
for _, test := range tests {
_, _, err := loadNetConf([]byte(test.netConfJSON("")), "")
if test.err == nil {
Expect(err).To(BeNil())
Expect(err).ToNot(HaveOccurred())
} else {
Expect(err).To(Equal(test.err))
}

View File

@ -26,7 +26,6 @@ import (
"github.com/containernetworking/cni/pkg/types"
current "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/cni/pkg/version"
"github.com/containernetworking/plugins/pkg/ip"
"github.com/containernetworking/plugins/pkg/ipam"
"github.com/containernetworking/plugins/pkg/ns"
@ -41,8 +40,7 @@ func parseNetConf(bytes []byte) (*types.NetConf, error) {
return conf, nil
}
func createDummy(conf *types.NetConf, ifName string, netns ns.NetNS) (*current.Interface, error) {
func createDummy(ifName string, netns ns.NetNS) (*current.Interface, error) {
dummy := &current.Interface{}
dm := &netlink.Dummy{
@ -92,7 +90,7 @@ func cmdAdd(args *skel.CmdArgs) error {
}
defer netns.Close()
dummyInterface, err := createDummy(conf, args.IfName, netns)
dummyInterface, err := createDummy(args.IfName, netns)
if err != nil {
return err
}
@ -136,10 +134,7 @@ func cmdAdd(args *skel.CmdArgs) error {
result.Interfaces = []*current.Interface{dummyInterface}
err = netns.Do(func(_ ns.NetNS) error {
if err := ipam.ConfigureIface(args.IfName, result); err != nil {
return err
}
return nil
return ipam.ConfigureIface(args.IfName, result)
})
if err != nil {
@ -245,7 +240,6 @@ func cmdCheck(args *skel.CmdArgs) error {
//
// Check prevResults for ips, routes and dns against values found in the container
if err := netns.Do(func(_ ns.NetNS) error {
// Check interface against values found in the container
err := validateCniContainerInterface(contMap)
if err != nil {
@ -262,11 +256,9 @@ func cmdCheck(args *skel.CmdArgs) error {
}
return nil
}
func validateCniContainerInterface(intf current.Interface) error {
var link netlink.Link
var err error

View File

@ -15,12 +15,11 @@
package main_test
import (
"github.com/onsi/gomega/gexec"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gexec"
)
var pathToLoPlugin string

View File

@ -23,6 +23,10 @@ import (
"strings"
"syscall"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/vishvananda/netlink"
"github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/types"
types020 "github.com/containernetworking/cni/pkg/types/020"
@ -31,11 +35,6 @@ import (
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containernetworking/plugins/pkg/testutils"
"github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator"
"github.com/vishvananda/netlink"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
const MASTER_NAME = "eth0"
@ -89,7 +88,6 @@ func buildOneConfig(netName string, cniVersion string, orig *Net, prevResult typ
}
return conf, nil
}
type tester interface {
@ -99,10 +97,12 @@ type tester interface {
type testerBase struct{}
type testerV10x testerBase
type testerV04x testerBase
type testerV03x testerBase
type testerV01xOr02x testerBase
type (
testerV10x testerBase
testerV04x testerBase
testerV03x testerBase
testerV01xOr02x testerBase
)
func newTesterByVersion(version string) tester {
switch {
@ -122,9 +122,9 @@ func (t *testerV10x) verifyResult(result types.Result, name string) string {
r, err := types100.GetResult(result)
Expect(err).NotTo(HaveOccurred())
Expect(len(r.Interfaces)).To(Equal(1))
Expect(r.Interfaces).To(HaveLen(1))
Expect(r.Interfaces[0].Name).To(Equal(name))
Expect(len(r.IPs)).To(Equal(1))
Expect(r.IPs).To(HaveLen(1))
return r.Interfaces[0].Mac
}
@ -133,9 +133,9 @@ func verify0403(result types.Result, name string) string {
r, err := types040.GetResult(result)
Expect(err).NotTo(HaveOccurred())
Expect(len(r.Interfaces)).To(Equal(1))
Expect(r.Interfaces).To(HaveLen(1))
Expect(r.Interfaces[0].Name).To(Equal(name))
Expect(len(r.IPs)).To(Equal(1))
Expect(r.IPs).To(HaveLen(1))
return r.Interfaces[0].Mac
}
@ -151,7 +151,7 @@ func (t *testerV03x) verifyResult(result types.Result, name string) string {
}
// verifyResult minimally verifies the Result and returns the interface's MAC address
func (t *testerV01xOr02x) verifyResult(result types.Result, name string) string {
func (t *testerV01xOr02x) verifyResult(result types.Result, _ string) string {
r, err := types020.GetResult(result)
Expect(err).NotTo(HaveOccurred())
@ -210,17 +210,11 @@ var _ = Describe("dummy Operations", func() {
ver := ver
It(fmt.Sprintf("[%s] creates an dummy link in a non-default namespace", ver), func() {
conf := &types.NetConf{
CNIVersion: ver,
Name: "testConfig",
Type: "dummy",
}
// Create dummy in other namespace
err := originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
_, err := createDummy(conf, "foobar0", targetNS)
_, err := createDummy("foobar0", targetNS)
Expect(err).NotTo(HaveOccurred())
return nil
})
@ -292,7 +286,7 @@ var _ = Describe("dummy Operations", func() {
addrs, err := netlink.AddrList(link, syscall.AF_INET)
Expect(err).NotTo(HaveOccurred())
Expect(len(addrs)).To(Equal(1))
Expect(addrs).To(HaveLen(1))
return nil
})
Expect(err).NotTo(HaveOccurred())

View File

@ -31,16 +31,13 @@ import (
"github.com/containernetworking/cni/pkg/types"
current "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/cni/pkg/version"
"github.com/containernetworking/plugins/pkg/ip"
"github.com/containernetworking/plugins/pkg/ipam"
"github.com/containernetworking/plugins/pkg/ns"
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
)
var (
sysBusPCI = "/sys/bus/pci/devices"
)
var sysBusPCI = "/sys/bus/pci/devices"
// Array of different linux drivers bound to network device needed for DPDK
var userspaceDrivers = []string{"vfio-pci", "uio_pci_generic", "igb_uio"}
@ -161,10 +158,7 @@ func cmdAdd(args *skel.CmdArgs) error {
if !cfg.DPDKMode {
err = containerNs.Do(func(_ ns.NetNS) error {
if err := ipam.ConfigureIface(args.IfName, newResult); err != nil {
return err
}
return nil
return ipam.ConfigureIface(args.IfName, newResult)
})
if err != nil {
return err
@ -325,10 +319,11 @@ func getLink(devname, hwaddr, kernelpath, pciaddr string) (netlink.Link, error)
if err != nil {
return nil, fmt.Errorf("failed to list node links: %v", err)
}
switch {
if len(devname) > 0 {
case len(devname) > 0:
return netlink.LinkByName(devname)
} else if len(hwaddr) > 0 {
case len(hwaddr) > 0:
hwAddr, err := net.ParseMAC(hwaddr)
if err != nil {
return nil, fmt.Errorf("failed to parse MAC address %q: %v", hwaddr, err)
@ -339,7 +334,7 @@ func getLink(devname, hwaddr, kernelpath, pciaddr string) (netlink.Link, error)
return link, nil
}
}
} else if len(kernelpath) > 0 {
case len(kernelpath) > 0:
if !filepath.IsAbs(kernelpath) || !strings.HasPrefix(kernelpath, "/sys/devices/") {
return nil, fmt.Errorf("kernel device path %q must be absolute and begin with /sys/devices/", kernelpath)
}
@ -358,7 +353,7 @@ func getLink(devname, hwaddr, kernelpath, pciaddr string) (netlink.Link, error)
}
}
}
} else if len(pciaddr) > 0 {
case len(pciaddr) > 0:
netDir := filepath.Join(sysBusPCI, pciaddr, "net")
if _, err := os.Lstat(netDir); err != nil {
virtioNetDir := filepath.Join(sysBusPCI, pciaddr, "virtio*", "net")
@ -386,7 +381,6 @@ func main() {
}
func cmdCheck(args *skel.CmdArgs) error {
cfg, err := loadConf(args.StdinData)
if err != nil {
return err
@ -443,7 +437,6 @@ func cmdCheck(args *skel.CmdArgs) error {
//
// Check prevResults for ips, routes and dns against values found in the container
if err := netns.Do(func(_ ns.NetNS) error {
// Check interface against values found in the container
err := validateCniContainerInterface(contMap)
if err != nil {
@ -469,7 +462,6 @@ func cmdCheck(args *skel.CmdArgs) error {
}
func validateCniContainerInterface(intf current.Interface) error {
var link netlink.Link
var err error

View File

@ -15,10 +15,10 @@
package main
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestVlan(t *testing.T) {

View File

@ -23,6 +23,10 @@ import (
"path"
"strings"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/vishvananda/netlink"
"github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/types"
types040 "github.com/containernetworking/cni/pkg/types/040"
@ -30,10 +34,6 @@ import (
"github.com/containernetworking/cni/pkg/version"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containernetworking/plugins/pkg/testutils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vishvananda/netlink"
)
type Net struct {
@ -86,14 +86,14 @@ func canonicalizeIP(ip *net.IP) error {
// LoadIPAMConfig creates IPAMConfig using json encoded configuration provided
// as `bytes`. At the moment values provided in envArgs are ignored so there
// is no possibility to overload the json configuration using envArgs
func LoadIPAMConfig(bytes []byte, envArgs string) (*IPAMConfig, string, error) {
func LoadIPAMConfig(bytes []byte, envArgs string) (*IPAMConfig, error) {
n := Net{}
if err := json.Unmarshal(bytes, &n); err != nil {
return nil, "", err
return nil, err
}
if n.IPAM == nil {
return nil, "", fmt.Errorf("IPAM config missing 'ipam' key")
return nil, fmt.Errorf("IPAM config missing 'ipam' key")
}
// Validate all ranges
@ -103,13 +103,13 @@ func LoadIPAMConfig(bytes []byte, envArgs string) (*IPAMConfig, string, error) {
for i := range n.IPAM.Addresses {
ip, addr, err := net.ParseCIDR(n.IPAM.Addresses[i].AddressStr)
if err != nil {
return nil, "", fmt.Errorf("invalid CIDR %s: %s", n.IPAM.Addresses[i].AddressStr, err)
return nil, fmt.Errorf("invalid CIDR %s: %s", n.IPAM.Addresses[i].AddressStr, err)
}
n.IPAM.Addresses[i].Address = *addr
n.IPAM.Addresses[i].Address.IP = ip
if err := canonicalizeIP(&n.IPAM.Addresses[i].Address.IP); err != nil {
return nil, "", fmt.Errorf("invalid address %d: %s", i, err)
return nil, fmt.Errorf("invalid address %d: %s", i, err)
}
if n.IPAM.Addresses[i].Address.IP.To4() != nil {
@ -123,7 +123,7 @@ func LoadIPAMConfig(bytes []byte, envArgs string) (*IPAMConfig, string, error) {
e := IPAMEnvArgs{}
err := types.LoadArgs(envArgs, &e)
if err != nil {
return nil, "", err
return nil, err
}
if e.IP != "" {
@ -132,7 +132,7 @@ func LoadIPAMConfig(bytes []byte, envArgs string) (*IPAMConfig, string, error) {
ip, subnet, err := net.ParseCIDR(ipstr)
if err != nil {
return nil, "", fmt.Errorf("invalid CIDR %s: %s", ipstr, err)
return nil, fmt.Errorf("invalid CIDR %s: %s", ipstr, err)
}
addr := Address{Address: net.IPNet{IP: ip, Mask: subnet.Mask}}
@ -149,7 +149,7 @@ func LoadIPAMConfig(bytes []byte, envArgs string) (*IPAMConfig, string, error) {
for _, item := range strings.Split(string(e.GATEWAY), ",") {
gwip := net.ParseIP(strings.TrimSpace(item))
if gwip == nil {
return nil, "", fmt.Errorf("invalid gateway address: %s", item)
return nil, fmt.Errorf("invalid gateway address: %s", item)
}
for i := range n.IPAM.Addresses {
@ -164,14 +164,14 @@ func LoadIPAMConfig(bytes []byte, envArgs string) (*IPAMConfig, string, error) {
// CNI spec 0.2.0 and below supported only one v4 and v6 address
if numV4 > 1 || numV6 > 1 {
if ok, _ := version.GreaterThanOrEqualTo(n.CNIVersion, "0.3.0"); !ok {
return nil, "", fmt.Errorf("CNI version %v does not support more than 1 address per family", n.CNIVersion)
return nil, fmt.Errorf("CNI version %v does not support more than 1 address per family", n.CNIVersion)
}
}
// Copy net name into IPAM so not to drag Net struct around
n.IPAM.Name = n.Name
return n.IPAM, n.CNIVersion, nil
return n.IPAM, nil
}
func buildOneConfig(name, cniVersion string, orig *Net, prevResult types.Result) (*Net, error) {
@ -214,7 +214,6 @@ func buildOneConfig(name, cniVersion string, orig *Net, prevResult types.Result)
}
return conf, nil
}
type tester interface {
@ -224,9 +223,11 @@ type tester interface {
type testerBase struct{}
type testerV10x testerBase
type testerV04x testerBase
type testerV03x testerBase
type (
testerV10x testerBase
testerV04x testerBase
testerV03x testerBase
)
func newTesterByVersion(version string) tester {
switch {
@ -259,8 +260,8 @@ func (t *testerV10x) expectDpdkInterfaceIP(result types.Result, ipAddress string
// check that the result was sane
res, err := types100.NewResultFromResult(result)
Expect(err).NotTo(HaveOccurred())
Expect(len(res.Interfaces)).To(Equal(0))
Expect(len(res.IPs)).To(Equal(1))
Expect(res.Interfaces).To(BeEmpty())
Expect(res.IPs).To(HaveLen(1))
Expect(res.IPs[0].Address.String()).To(Equal(ipAddress))
}
@ -281,8 +282,8 @@ func (t *testerV04x) expectDpdkInterfaceIP(result types.Result, ipAddress string
// check that the result was sane
res, err := types040.NewResultFromResult(result)
Expect(err).NotTo(HaveOccurred())
Expect(len(res.Interfaces)).To(Equal(0))
Expect(len(res.IPs)).To(Equal(1))
Expect(res.Interfaces).To(BeEmpty())
Expect(res.IPs).To(HaveLen(1))
Expect(res.IPs[0].Address.String()).To(Equal(ipAddress))
}
@ -303,8 +304,8 @@ func (t *testerV03x) expectDpdkInterfaceIP(result types.Result, ipAddress string
// check that the result was sane
res, err := types040.NewResultFromResult(result)
Expect(err).NotTo(HaveOccurred())
Expect(len(res.Interfaces)).To(Equal(0))
Expect(len(res.IPs)).To(Equal(1))
Expect(res.Interfaces).To(BeEmpty())
Expect(res.IPs).To(HaveLen(1))
Expect(res.IPs[0].Address.String()).To(Equal(ipAddress))
}
@ -664,11 +665,11 @@ var _ = Describe("base functionality", func() {
Expect(link.Attrs().HardwareAddr).To(Equal(origLink.Attrs().HardwareAddr))
Expect(link.Attrs().Flags & net.FlagUp).To(Equal(net.FlagUp))
//get the IP address of the interface in the target namespace
// get the IP address of the interface in the target namespace
addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
Expect(err).NotTo(HaveOccurred())
addr := addrs[0].IPNet.String()
//assert that IP address is what we set
// assert that IP address is what we set
Expect(addr).To(Equal(targetIP))
return nil
@ -711,7 +712,6 @@ var _ = Describe("base functionality", func() {
}
_, _, err := testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) })
Expect(err).To(MatchError(`specify either "device", "hwaddr", "kernelpath" or "pciBusID"`))
})
It(fmt.Sprintf("[%s] works with a valid config without IPAM", ver), func() {
@ -868,7 +868,7 @@ var _ = Describe("base functionality", func() {
err = json.Unmarshal([]byte(conf), &n)
Expect(err).NotTo(HaveOccurred())
n.IPAM, _, err = LoadIPAMConfig([]byte(conf), "")
n.IPAM, err = LoadIPAMConfig([]byte(conf), "")
Expect(err).NotTo(HaveOccurred())
if testutils.SpecVersionHasCHECK(ver) {
@ -961,11 +961,11 @@ var _ = Describe("base functionality", func() {
Expect(link.Attrs().HardwareAddr).To(Equal(origLink.Attrs().HardwareAddr))
Expect(link.Attrs().Flags & net.FlagUp).To(Equal(net.FlagUp))
//get the IP address of the interface in the target namespace
// get the IP address of the interface in the target namespace
addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
Expect(err).NotTo(HaveOccurred())
addr := addrs[0].IPNet.String()
//assert that IP address is what we set
// assert that IP address is what we set
Expect(addr).To(Equal(targetIP))
return nil
@ -984,7 +984,7 @@ var _ = Describe("base functionality", func() {
err = json.Unmarshal([]byte(conf), &n)
Expect(err).NotTo(HaveOccurred())
n.IPAM, _, err = LoadIPAMConfig([]byte(conf), "")
n.IPAM, err = LoadIPAMConfig([]byte(conf), "")
Expect(err).NotTo(HaveOccurred())
if testutils.SpecVersionHasCHECK(ver) {
@ -1167,7 +1167,7 @@ func (fs *fakeFilesystem) use() func() {
fs.rootDir = tmpDir
for _, dir := range fs.dirs {
err := os.MkdirAll(path.Join(fs.rootDir, dir), 0755)
err := os.MkdirAll(path.Join(fs.rootDir, dir), 0o755)
if err != nil {
panic(fmt.Errorf("error creating fake directory: %s", err.Error()))
}

View File

@ -26,7 +26,6 @@ import (
"github.com/containernetworking/cni/pkg/types"
current "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/cni/pkg/version"
"github.com/containernetworking/plugins/pkg/ip"
"github.com/containernetworking/plugins/pkg/ipam"
"github.com/containernetworking/plugins/pkg/ns"
@ -36,9 +35,10 @@ import (
type NetConf struct {
types.NetConf
Master string `json:"master"`
Mode string `json:"mode"`
MTU int `json:"mtu"`
Master string `json:"master"`
Mode string `json:"mode"`
MTU int `json:"mtu"`
LinkContNs bool `json:"linkInContainer,omitempty"`
}
func init() {
@ -48,9 +48,9 @@ func init() {
runtime.LockOSThread()
}
func loadConf(bytes []byte, cmdCheck bool) (*NetConf, string, error) {
func loadConf(args *skel.CmdArgs, cmdCheck bool) (*NetConf, string, error) {
n := &NetConf{}
if err := json.Unmarshal(bytes, n); err != nil {
if err := json.Unmarshal(args.StdinData, n); err != nil {
return nil, "", fmt.Errorf("failed to load netconf: %v", err)
}
@ -73,8 +73,8 @@ func loadConf(bytes []byte, cmdCheck bool) (*NetConf, string, error) {
}
if n.Master == "" {
if result == nil {
defaultRouteInterface, err := getDefaultRouteInterfaceName()
var defaultRouteInterface string
defaultRouteInterface, err = getNamespacedDefaultRouteInterfaceName(args.Netns, n.LinkContNs)
if err != nil {
return nil, "", err
}
@ -124,7 +124,15 @@ func createIpvlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interf
return nil, err
}
m, err := netlink.LinkByName(conf.Master)
var m netlink.Link
if conf.LinkContNs {
err = netns.Do(func(_ ns.NetNS) error {
m, err = netlink.LinkByName(conf.Master)
return err
})
} else {
m, err = netlink.LinkByName(conf.Master)
}
if err != nil {
return nil, fmt.Errorf("failed to lookup master %q: %v", conf.Master, err)
}
@ -146,8 +154,14 @@ func createIpvlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interf
Mode: mode,
}
if err := netlink.LinkAdd(mv); err != nil {
return nil, fmt.Errorf("failed to create ipvlan: %v", err)
if conf.LinkContNs {
err = netns.Do(func(_ ns.NetNS) error {
return netlink.LinkAdd(mv)
})
} else {
if err := netlink.LinkAdd(mv); err != nil {
return nil, fmt.Errorf("failed to create ipvlan: %v", err)
}
}
err = netns.Do(func(_ ns.NetNS) error {
@ -193,8 +207,31 @@ func getDefaultRouteInterfaceName() (string, error) {
return "", fmt.Errorf("no default route interface found")
}
func getNamespacedDefaultRouteInterfaceName(namespace string, inContainer bool) (string, error) {
if !inContainer {
return getDefaultRouteInterfaceName()
}
netns, err := ns.GetNS(namespace)
if err != nil {
return "", fmt.Errorf("failed to open netns %q: %v", netns, err)
}
defer netns.Close()
var defaultRouteInterface string
err = netns.Do(func(_ ns.NetNS) error {
defaultRouteInterface, err = getDefaultRouteInterfaceName()
if err != nil {
return err
}
return nil
})
if err != nil {
return "", err
}
return defaultRouteInterface, nil
}
func cmdAdd(args *skel.CmdArgs) error {
n, cniVersion, err := loadConf(args.StdinData, false)
n, cniVersion, err := loadConf(args, false)
if err != nil {
return err
}
@ -257,10 +294,7 @@ func cmdAdd(args *skel.CmdArgs) error {
err = netns.Do(func(_ ns.NetNS) error {
_, _ = sysctl.Sysctl(fmt.Sprintf("net/ipv4/conf/%s/arp_notify", args.IfName), "1")
if err := ipam.ConfigureIface(args.IfName, result); err != nil {
return err
}
return nil
return ipam.ConfigureIface(args.IfName, result)
})
if err != nil {
return err
@ -272,7 +306,7 @@ func cmdAdd(args *skel.CmdArgs) error {
}
func cmdDel(args *skel.CmdArgs) error {
n, _, err := loadConf(args.StdinData, false)
n, _, err := loadConf(args, false)
if err != nil {
return err
}
@ -319,8 +353,7 @@ func main() {
}
func cmdCheck(args *skel.CmdArgs) error {
n, _, err := loadConf(args.StdinData, true)
n, _, err := loadConf(args, true)
if err != nil {
return err
}
@ -369,16 +402,23 @@ func cmdCheck(args *skel.CmdArgs) error {
contMap.Sandbox, args.Netns)
}
m, err := netlink.LinkByName(n.Master)
if n.LinkContNs {
err = netns.Do(func(_ ns.NetNS) error {
_, err = netlink.LinkByName(n.Master)
return err
})
} else {
_, err = netlink.LinkByName(n.Master)
}
if err != nil {
return fmt.Errorf("failed to lookup master %q: %v", n.Master, err)
}
// Check prevResults for ips, routes and dns against values found in the container
if err := netns.Do(func(_ ns.NetNS) error {
// Check interface against values found in the container
err := validateCniContainerInterface(contMap, m.Attrs().Index, n.Mode)
err := validateCniContainerInterface(contMap, n.Mode)
if err != nil {
return err
}
@ -400,8 +440,7 @@ func cmdCheck(args *skel.CmdArgs) error {
return nil
}
func validateCniContainerInterface(intf current.Interface, masterIndex int, modeExpected string) error {
func validateCniContainerInterface(intf current.Interface, modeExpected string) error {
var link netlink.Link
var err error
@ -422,6 +461,9 @@ func validateCniContainerInterface(intf current.Interface, masterIndex int, mode
}
mode, err := modeFromString(modeExpected)
if err != nil {
return err
}
if ipv.Mode != mode {
currString, err := modeToString(ipv.Mode)
if err != nil {

View File

@ -15,10 +15,10 @@
package main
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestIpvlan(t *testing.T) {

View File

@ -22,6 +22,10 @@ import (
"strings"
"syscall"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/vishvananda/netlink"
"github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/types"
types020 "github.com/containernetworking/cni/pkg/types/020"
@ -29,15 +33,13 @@ import (
types100 "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containernetworking/plugins/pkg/testutils"
"github.com/vishvananda/netlink"
"github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
const MASTER_NAME = "eth0"
const (
MASTER_NAME = "eth0"
MASTER_NAME_INCONTAINER = "eth1"
)
type Net struct {
Name string `json:"name"`
@ -49,6 +51,7 @@ type Net struct {
DNS types.DNS `json:"dns"`
RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
PrevResult types100.Result `json:"-"`
LinkContNs bool `json:"linkInContainer"`
}
func buildOneConfig(cniVersion string, master string, orig *Net, prevResult types.Result) (*Net, error) {
@ -90,7 +93,6 @@ func buildOneConfig(cniVersion string, master string, orig *Net, prevResult type
}
return conf, nil
}
func ipvlanAddCheckDelTest(conf, masterName string, originalNS, targetNS ns.NetNS) {
@ -139,7 +141,7 @@ func ipvlanAddCheckDelTest(conf, masterName string, originalNS, targetNS ns.NetN
addrs, err := netlink.AddrList(link, syscall.AF_INET)
Expect(err).NotTo(HaveOccurred())
Expect(len(addrs)).To(Equal(1))
Expect(addrs).To(HaveLen(1))
return nil
})
Expect(err).NotTo(HaveOccurred())
@ -204,9 +206,11 @@ type tester interface {
type testerBase struct{}
type testerV10x testerBase
type testerV04x testerBase
type testerV02x testerBase
type (
testerV10x testerBase
testerV04x testerBase
testerV02x testerBase
)
func newTesterByVersion(version string) tester {
switch {
@ -226,9 +230,9 @@ func (t *testerV10x) verifyResult(result types.Result, name string) string {
r, err := types100.GetResult(result)
Expect(err).NotTo(HaveOccurred())
Expect(len(r.Interfaces)).To(Equal(1))
Expect(r.Interfaces).To(HaveLen(1))
Expect(r.Interfaces[0].Name).To(Equal(name))
Expect(len(r.IPs)).To(Equal(1))
Expect(r.IPs).To(HaveLen(1))
return r.Interfaces[0].Mac
}
@ -238,15 +242,15 @@ func (t *testerV04x) verifyResult(result types.Result, name string) string {
r, err := types040.GetResult(result)
Expect(err).NotTo(HaveOccurred())
Expect(len(r.Interfaces)).To(Equal(1))
Expect(r.Interfaces).To(HaveLen(1))
Expect(r.Interfaces[0].Name).To(Equal(name))
Expect(len(r.IPs)).To(Equal(1))
Expect(r.IPs).To(HaveLen(1))
return r.Interfaces[0].Mac
}
// verifyResult minimally verifies the Result and returns the interface's MAC address
func (t *testerV02x) verifyResult(result types.Result, name string) string {
func (t *testerV02x) verifyResult(result types.Result, _ string) string {
r, err := types020.GetResult(result)
Expect(err).NotTo(HaveOccurred())
@ -289,6 +293,22 @@ var _ = Describe("ipvlan Operations", func() {
return nil
})
Expect(err).NotTo(HaveOccurred())
err = targetNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
// Add master
err = netlink.LinkAdd(&netlink.Dummy{
LinkAttrs: netlink.LinkAttrs{
Name: MASTER_NAME_INCONTAINER,
},
})
Expect(err).NotTo(HaveOccurred())
_, err = netlink.LinkByName(MASTER_NAME_INCONTAINER)
Expect(err).NotTo(HaveOccurred())
return nil
})
Expect(err).NotTo(HaveOccurred())
})
AfterEach(func() {
@ -301,67 +321,77 @@ var _ = Describe("ipvlan Operations", func() {
Expect(testutils.UnmountNS(targetNS)).To(Succeed())
})
for _, ver := range testutils.AllSpecVersions {
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
ver := ver
for _, inContainer := range []bool{false, true} {
masterInterface := MASTER_NAME
if inContainer {
masterInterface = MASTER_NAME_INCONTAINER
}
// for _, ver := range testutils.AllSpecVersions {
for _, ver := range [...]string{"1.0.0"} {
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
ver := ver
isInContainer := inContainer // Tests need a local var with constant value
It(fmt.Sprintf("[%s] creates an ipvlan link in a non-default namespace", ver), func() {
conf := &NetConf{
NetConf: types.NetConf{
CNIVersion: ver,
Name: "testConfig",
Type: "ipvlan",
},
Master: MASTER_NAME,
Mode: "l2",
MTU: 1500,
}
It(fmt.Sprintf("[%s] creates an ipvlan link in a non-default namespace", ver), func() {
conf := &NetConf{
NetConf: types.NetConf{
CNIVersion: ver,
Name: "testConfig",
Type: "ipvlan",
},
Master: masterInterface,
Mode: "l2",
MTU: 1500,
LinkContNs: isInContainer,
}
err := originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
err := originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
_, err := createIpvlan(conf, "foobar0", targetNS)
Expect(err).NotTo(HaveOccurred())
return nil
})
_, err := createIpvlan(conf, "foobar0", targetNS)
Expect(err).NotTo(HaveOccurred())
return nil
// Make sure ipvlan link exists in the target namespace
err = targetNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
link, err := netlink.LinkByName("foobar0")
Expect(err).NotTo(HaveOccurred())
Expect(link.Attrs().Name).To(Equal("foobar0"))
return nil
})
Expect(err).NotTo(HaveOccurred())
})
Expect(err).NotTo(HaveOccurred())
// Make sure ipvlan link exists in the target namespace
err = targetNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
link, err := netlink.LinkByName("foobar0")
Expect(err).NotTo(HaveOccurred())
Expect(link.Attrs().Name).To(Equal("foobar0"))
return nil
})
Expect(err).NotTo(HaveOccurred())
})
It(fmt.Sprintf("[%s] configures and deconfigures an iplvan link with ADD/DEL", ver), func() {
conf := fmt.Sprintf(`{
It(fmt.Sprintf("[%s] configures and deconfigures an iplvan link with ADD/DEL", ver), func() {
conf := fmt.Sprintf(`{
"cniVersion": "%s",
"name": "mynet",
"type": "ipvlan",
"master": "%s",
"linkInContainer": %t,
"ipam": {
"type": "host-local",
"subnet": "10.1.2.0/24",
"dataDir": "%s"
}
}`, ver, MASTER_NAME, dataDir)
}`, ver, masterInterface, isInContainer, dataDir)
ipvlanAddCheckDelTest(conf, "", originalNS, targetNS)
})
ipvlanAddCheckDelTest(conf, "", originalNS, targetNS)
})
if testutils.SpecVersionHasChaining(ver) {
It(fmt.Sprintf("[%s] configures and deconfigures an iplvan link with ADD/DEL when chained", ver), func() {
conf := fmt.Sprintf(`{
if testutils.SpecVersionHasChaining(ver) {
It(fmt.Sprintf("[%s] configures and deconfigures an iplvan link with ADD/DEL when chained", ver), func() {
conf := fmt.Sprintf(`{
"cniVersion": "%s",
"name": "mynet",
"type": "ipvlan",
"linkInContainer": %t,
"prevResult": {
"interfaces": [
{
@ -378,84 +408,91 @@ var _ = Describe("ipvlan Operations", func() {
],
"routes": []
}
}`, ver, MASTER_NAME)
}`, ver, isInContainer, masterInterface)
ipvlanAddCheckDelTest(conf, MASTER_NAME, originalNS, targetNS)
})
}
ipvlanAddCheckDelTest(conf, masterInterface, originalNS, targetNS)
})
}
It(fmt.Sprintf("[%s] deconfigures an unconfigured ipvlan link with DEL", ver), func() {
conf := fmt.Sprintf(`{
It(fmt.Sprintf("[%s] deconfigures an unconfigured ipvlan link with DEL", ver), func() {
conf := fmt.Sprintf(`{
"cniVersion": "%s",
"name": "mynet",
"type": "ipvlan",
"master": "%s",
"linkInContainer": %t,
"ipam": {
"type": "host-local",
"subnet": "10.1.2.0/24",
"dataDir": "%s"
}
}`, ver, MASTER_NAME, dataDir)
}`, ver, masterInterface, isInContainer, dataDir)
args := &skel.CmdArgs{
ContainerID: "dummy",
Netns: targetNS.Path(),
IfName: "ipvl0",
StdinData: []byte(conf),
}
args := &skel.CmdArgs{
ContainerID: "dummy",
Netns: targetNS.Path(),
IfName: "ipvl0",
StdinData: []byte(conf),
}
err := originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
err := originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
err := testutils.CmdDelWithArgs(args, func() error {
return cmdDel(args)
err := testutils.CmdDelWithArgs(args, func() error {
return cmdDel(args)
})
Expect(err).NotTo(HaveOccurred())
return nil
})
Expect(err).NotTo(HaveOccurred())
return nil
})
Expect(err).NotTo(HaveOccurred())
})
It(fmt.Sprintf("[%s] configures and deconfigures a ipvlan link with ADD/DEL, without master config", ver), func() {
conf := fmt.Sprintf(`{
It(fmt.Sprintf("[%s] configures and deconfigures a ipvlan link with ADD/DEL, without master config", ver), func() {
conf := fmt.Sprintf(`{
"cniVersion": "%s",
"name": "mynet",
"type": "ipvlan",
"linkInContainer": %t,
"ipam": {
"type": "host-local",
"subnet": "10.1.2.0/24",
"dataDir": "%s"
}
}`, ver, dataDir)
}`, ver, isInContainer, dataDir)
// Make MASTER_NAME as default route interface
err := originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
link, err := netlink.LinkByName(MASTER_NAME)
Expect(err).NotTo(HaveOccurred())
err = netlink.LinkSetUp(link)
Expect(err).NotTo(HaveOccurred())
var address = &net.IPNet{IP: net.IPv4(192, 0, 0, 1), Mask: net.CIDRMask(24, 32)}
var addr = &netlink.Addr{IPNet: address}
err = netlink.AddrAdd(link, addr)
Expect(err).NotTo(HaveOccurred())
// add default gateway into MASTER
dst := &net.IPNet{
IP: net.IPv4(0, 0, 0, 0),
Mask: net.CIDRMask(0, 0),
// Make MASTER_NAME as default route interface
currentNs := originalNS
if isInContainer {
currentNs = targetNS
}
ip := net.IPv4(192, 0, 0, 254)
route := netlink.Route{LinkIndex: link.Attrs().Index, Dst: dst, Gw: ip}
err = netlink.RouteAdd(&route)
Expect(err).NotTo(HaveOccurred())
return nil
})
Expect(err).NotTo(HaveOccurred())
err := currentNs.Do(func(ns.NetNS) error {
defer GinkgoRecover()
ipvlanAddCheckDelTest(conf, MASTER_NAME, originalNS, targetNS)
})
link, err := netlink.LinkByName(masterInterface)
Expect(err).NotTo(HaveOccurred())
err = netlink.LinkSetUp(link)
Expect(err).NotTo(HaveOccurred())
address := &net.IPNet{IP: net.IPv4(192, 0, 0, 1), Mask: net.CIDRMask(24, 32)}
addr := &netlink.Addr{IPNet: address}
err = netlink.AddrAdd(link, addr)
Expect(err).NotTo(HaveOccurred())
// add default gateway into MASTER
dst := &net.IPNet{
IP: net.IPv4(0, 0, 0, 0),
Mask: net.CIDRMask(0, 0),
}
ip := net.IPv4(192, 0, 0, 254)
route := netlink.Route{LinkIndex: link.Attrs().Index, Dst: dst, Gw: ip}
err = netlink.RouteAdd(&route)
Expect(err).NotTo(HaveOccurred())
return nil
})
Expect(err).NotTo(HaveOccurred())
ipvlanAddCheckDelTest(conf, masterInterface, originalNS, targetNS)
})
}
}
})

View File

@ -26,7 +26,6 @@ import (
"github.com/containernetworking/cni/pkg/types"
current "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/cni/pkg/version"
"github.com/containernetworking/plugins/pkg/ns"
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
)
@ -112,7 +111,7 @@ func cmdAdd(args *skel.CmdArgs) error {
r := &current.Result{
CNIVersion: conf.CNIVersion,
Interfaces: []*current.Interface{
&current.Interface{
{
Name: args.IfName,
Mac: "00:00:00:00:00:00",
Sandbox: args.Netns,

View File

@ -15,12 +15,11 @@
package main_test
import (
"github.com/onsi/gomega/gexec"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gexec"
)
var pathToLoPlugin string

View File

@ -20,12 +20,13 @@ import (
"os/exec"
"strings"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containernetworking/plugins/pkg/testutils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gbytes"
"github.com/onsi/gomega/gexec"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containernetworking/plugins/pkg/testutils"
)
func generateConfig(cniVersion string) *strings.Reader {

View File

@ -27,7 +27,6 @@ import (
"github.com/containernetworking/cni/pkg/types"
current "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/cni/pkg/version"
"github.com/containernetworking/plugins/pkg/ip"
"github.com/containernetworking/plugins/pkg/ipam"
"github.com/containernetworking/plugins/pkg/ns"
@ -37,10 +36,11 @@ import (
type NetConf struct {
types.NetConf
Master string `json:"master"`
Mode string `json:"mode"`
MTU int `json:"mtu"`
Mac string `json:"mac,omitempty"`
Master string `json:"master"`
Mode string `json:"mode"`
MTU int `json:"mtu"`
Mac string `json:"mac,omitempty"`
LinkContNs bool `json:"linkInContainer,omitempty"`
RuntimeConfig struct {
Mac string `json:"mac,omitempty"`
@ -79,13 +79,36 @@ func getDefaultRouteInterfaceName() (string, error) {
return "", fmt.Errorf("no default route interface found")
}
func loadConf(bytes []byte, envArgs string) (*NetConf, string, error) {
func getNamespacedDefaultRouteInterfaceName(namespace string, inContainer bool) (string, error) {
if !inContainer {
return getDefaultRouteInterfaceName()
}
netns, err := ns.GetNS(namespace)
if err != nil {
return "", fmt.Errorf("failed to open netns %q: %v", netns, err)
}
defer netns.Close()
var defaultRouteInterface string
err = netns.Do(func(_ ns.NetNS) error {
defaultRouteInterface, err = getDefaultRouteInterfaceName()
if err != nil {
return err
}
return nil
})
if err != nil {
return "", err
}
return defaultRouteInterface, nil
}
func loadConf(args *skel.CmdArgs, envArgs string) (*NetConf, string, error) {
n := &NetConf{}
if err := json.Unmarshal(bytes, n); err != nil {
if err := json.Unmarshal(args.StdinData, n); err != nil {
return nil, "", fmt.Errorf("failed to load netconf: %v", err)
}
if n.Master == "" {
defaultRouteInterface, err := getDefaultRouteInterfaceName()
defaultRouteInterface, err := getNamespacedDefaultRouteInterfaceName(args.Netns, n.LinkContNs)
if err != nil {
return nil, "", err
}
@ -93,7 +116,7 @@ func loadConf(bytes []byte, envArgs string) (*NetConf, string, error) {
}
// check existing and MTU of master interface
masterMTU, err := getMTUByName(n.Master)
masterMTU, err := getMTUByName(n.Master, args.Netns, n.LinkContNs)
if err != nil {
return nil, "", err
}
@ -120,8 +143,24 @@ func loadConf(bytes []byte, envArgs string) (*NetConf, string, error) {
return n, n.CNIVersion, nil
}
func getMTUByName(ifName string) (int, error) {
link, err := netlink.LinkByName(ifName)
func getMTUByName(ifName string, namespace string, inContainer bool) (int, error) {
var link netlink.Link
var err error
if inContainer {
var netns ns.NetNS
netns, err = ns.GetNS(namespace)
if err != nil {
return 0, fmt.Errorf("failed to open netns %q: %v", netns, err)
}
defer netns.Close()
err = netns.Do(func(_ ns.NetNS) error {
link, err = netlink.LinkByName(ifName)
return err
})
} else {
link, err = netlink.LinkByName(ifName)
}
if err != nil {
return 0, err
}
@ -166,7 +205,15 @@ func createMacvlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Inter
return nil, err
}
m, err := netlink.LinkByName(conf.Master)
var m netlink.Link
if conf.LinkContNs {
err = netns.Do(func(_ ns.NetNS) error {
m, err = netlink.LinkByName(conf.Master)
return err
})
} else {
m, err = netlink.LinkByName(conf.Master)
}
if err != nil {
return nil, fmt.Errorf("failed to lookup master %q: %v", conf.Master, err)
}
@ -198,7 +245,16 @@ func createMacvlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Inter
Mode: mode,
}
if err := netlink.LinkAdd(mv); err != nil {
if conf.LinkContNs {
err = netns.Do(func(_ ns.NetNS) error {
return netlink.LinkAdd(mv)
})
} else {
if err = netlink.LinkAdd(mv); err != nil {
return nil, fmt.Errorf("failed to create macvlan: %v", err)
}
}
if err != nil {
return nil, fmt.Errorf("failed to create macvlan: %v", err)
}
@ -228,7 +284,7 @@ func createMacvlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Inter
}
func cmdAdd(args *skel.CmdArgs) error {
n, cniVersion, err := loadConf(args.StdinData, args.Args)
n, cniVersion, err := loadConf(args, args.Args)
if err != nil {
return err
}
@ -296,10 +352,7 @@ func cmdAdd(args *skel.CmdArgs) error {
err = netns.Do(func(_ ns.NetNS) error {
_, _ = sysctl.Sysctl(fmt.Sprintf("net/ipv4/conf/%s/arp_notify", args.IfName), "1")
if err := ipam.ConfigureIface(args.IfName, result); err != nil {
return err
}
return nil
return ipam.ConfigureIface(args.IfName, result)
})
if err != nil {
return err
@ -329,7 +382,7 @@ func cmdAdd(args *skel.CmdArgs) error {
}
func cmdDel(args *skel.CmdArgs) error {
n, _, err := loadConf(args.StdinData, args.Args)
n, _, err := loadConf(args, args.Args)
if err != nil {
return err
}
@ -377,8 +430,7 @@ func main() {
}
func cmdCheck(args *skel.CmdArgs) error {
n, _, err := loadConf(args.StdinData, args.Args)
n, _, err := loadConf(args, args.Args)
if err != nil {
return err
}
@ -400,7 +452,7 @@ func cmdCheck(args *skel.CmdArgs) error {
// Parse previous result.
if n.NetConf.RawPrevResult == nil {
return fmt.Errorf("Required prevResult missing")
return fmt.Errorf("required prevResult missing")
}
if err := version.ParsePrevResult(&n.NetConf); err != nil {
@ -425,20 +477,26 @@ func cmdCheck(args *skel.CmdArgs) error {
// The namespace must be the same as what was configured
if args.Netns != contMap.Sandbox {
return fmt.Errorf("Sandbox in prevResult %s doesn't match configured netns: %s",
return fmt.Errorf("sandbox in prevResult %s doesn't match configured netns: %s",
contMap.Sandbox, args.Netns)
}
m, err := netlink.LinkByName(n.Master)
if n.LinkContNs {
err = netns.Do(func(_ ns.NetNS) error {
_, err = netlink.LinkByName(n.Master)
return err
})
} else {
_, err = netlink.LinkByName(n.Master)
}
if err != nil {
return fmt.Errorf("failed to lookup master %q: %v", n.Master, err)
}
// Check prevResults for ips, routes and dns against values found in the container
if err := netns.Do(func(_ ns.NetNS) error {
// Check interface against values found in the container
err := validateCniContainerInterface(contMap, m.Attrs().Index, n.Mode)
err := validateCniContainerInterface(contMap, n.Mode)
if err != nil {
return err
}
@ -460,28 +518,30 @@ func cmdCheck(args *skel.CmdArgs) error {
return nil
}
func validateCniContainerInterface(intf current.Interface, parentIndex int, modeExpected string) error {
func validateCniContainerInterface(intf current.Interface, modeExpected string) error {
var link netlink.Link
var err error
if intf.Name == "" {
return fmt.Errorf("Container interface name missing in prevResult: %v", intf.Name)
return fmt.Errorf("container interface name missing in prevResult: %v", intf.Name)
}
link, err = netlink.LinkByName(intf.Name)
if err != nil {
return fmt.Errorf("Container Interface name in prevResult: %s not found", intf.Name)
return fmt.Errorf("container Interface name in prevResult: %s not found", intf.Name)
}
if intf.Sandbox == "" {
return fmt.Errorf("Error: Container interface %s should not be in host namespace", link.Attrs().Name)
return fmt.Errorf("error: Container interface %s should not be in host namespace", link.Attrs().Name)
}
macv, isMacvlan := link.(*netlink.Macvlan)
if !isMacvlan {
return fmt.Errorf("Error: Container interface %s not of type macvlan", link.Attrs().Name)
return fmt.Errorf("error: Container interface %s not of type macvlan", link.Attrs().Name)
}
mode, err := modeFromString(modeExpected)
if err != nil {
return err
}
if macv.Mode != mode {
currString, err := modeToString(macv.Mode)
if err != nil {
@ -491,12 +551,12 @@ func validateCniContainerInterface(intf current.Interface, parentIndex int, mode
if err != nil {
return err
}
return fmt.Errorf("Container macvlan mode %s does not match expected value: %s", currString, confString)
return fmt.Errorf("container macvlan mode %s does not match expected value: %s", currString, confString)
}
if intf.Mac != "" {
if intf.Mac != link.Attrs().HardwareAddr.String() {
return fmt.Errorf("Interface %s Mac %s doesn't match container Mac: %s", intf.Name, intf.Mac, link.Attrs().HardwareAddr)
return fmt.Errorf("interface %s Mac %s doesn't match container Mac: %s", intf.Name, intf.Mac, link.Attrs().HardwareAddr)
}
}

View File

@ -15,10 +15,10 @@
package main
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestMacvlan(t *testing.T) {

File diff suppressed because it is too large Load Diff

View File

@ -28,7 +28,6 @@ import (
"github.com/containernetworking/cni/pkg/types"
current "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/cni/pkg/version"
"github.com/containernetworking/plugins/pkg/ip"
"github.com/containernetworking/plugins/pkg/ipam"
"github.com/containernetworking/plugins/pkg/ns"
@ -282,7 +281,6 @@ func cmdDel(args *skel.CmdArgs) error {
}
return err
})
if err != nil {
// if NetNs is passed down by the Cloud Orchestration Engine, or if it called multiple times
// so don't return an error if the device is already removed.
@ -358,7 +356,6 @@ func cmdCheck(args *skel.CmdArgs) error {
//
// Check prevResults for ips, routes and dns against values found in the container
if err := netns.Do(func(_ ns.NetNS) error {
// Check interface against values found in the container
err := validateCniContainerInterface(contMap)
if err != nil {
@ -383,7 +380,6 @@ func cmdCheck(args *skel.CmdArgs) error {
}
func validateCniContainerInterface(intf current.Interface) error {
var link netlink.Link
var err error

View File

@ -15,10 +15,10 @@
package main
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestPtp(t *testing.T) {

View File

@ -20,6 +20,10 @@ import (
"os"
"strings"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/vishvananda/netlink"
"github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/types"
types020 "github.com/containernetworking/cni/pkg/types/020"
@ -27,12 +31,7 @@ import (
types100 "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containernetworking/plugins/pkg/testutils"
"github.com/vishvananda/netlink"
"github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
type Net struct {
@ -87,7 +86,6 @@ func buildOneConfig(netName string, cniVersion string, orig *Net, prevResult typ
}
return conf, nil
}
type tester interface {
@ -97,10 +95,12 @@ type tester interface {
type testerBase struct{}
type testerV10x testerBase
type testerV04x testerBase
type testerV03x testerBase
type testerV01xOr02x testerBase
type (
testerV10x testerBase
testerV04x testerBase
testerV03x testerBase
testerV01xOr02x testerBase
)
func newTesterByVersion(version string) tester {
switch {
@ -186,7 +186,7 @@ func (t *testerV03x) verifyResult(result types.Result, expectedIfName, expectedS
}
// verifyResult minimally verifies the Result and returns the interface's IP addresses and MAC address
func (t *testerV01xOr02x) verifyResult(result types.Result, expectedIfName, expectedSandbox string, expectedDNS types.DNS) ([]resultIP, string) {
func (t *testerV01xOr02x) verifyResult(result types.Result, _, _ string, _ types.DNS) ([]resultIP, string) {
r, err := types020.GetResult(result)
Expect(err).NotTo(HaveOccurred())
@ -259,7 +259,7 @@ var _ = Describe("ptp Operations", func() {
t := newTesterByVersion(cniVersion)
ips, mac := t.verifyResult(result, IFNAME, targetNS.Path(), expectedDNSConf)
Expect(len(ips)).To(Equal(numIPs))
Expect(ips).To(HaveLen(numIPs))
// Make sure ptp link exists in the target namespace
// Then, ping the gateway
@ -368,7 +368,7 @@ var _ = Describe("ptp Operations", func() {
doTest(conf, ver, 1, dnsConf, targetNS)
})
It(fmt.Sprintf("[%s] configures and deconfigures a dual-stack ptp link with ADD/DEL", ver), func() {
It(fmt.Sprintf("[%s] configures and deconfigures a dual-stack ptp link + routes with ADD/DEL", ver), func() {
conf := fmt.Sprintf(`{
"cniVersion": "%s",
"name": "mynet",
@ -381,6 +381,11 @@ var _ = Describe("ptp Operations", func() {
[{ "subnet": "10.1.2.0/24"}],
[{ "subnet": "2001:db8:1::0/66"}]
],
"routes": [
{ "dst": "0.0.0.0/0" },
{ "dst": "192.168.0.0/16" },
{ "dst": "1.2.3.4/32" }
],
"dataDir": "%s"
}
}`, ver, dataDir)

445
plugins/main/tap/tap.go Normal file
View File

@ -0,0 +1,445 @@
// Copyright 2022 CNI 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 main
import (
"encoding/json"
"errors"
"fmt"
"net"
"os/exec"
"runtime"
"strconv"
"syscall"
"github.com/opencontainers/selinux/go-selinux"
"github.com/vishvananda/netlink"
"golang.org/x/sys/unix"
"github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/types"
current "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/cni/pkg/version"
"github.com/containernetworking/plugins/pkg/ip"
"github.com/containernetworking/plugins/pkg/ipam"
"github.com/containernetworking/plugins/pkg/ns"
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
"github.com/containernetworking/plugins/pkg/utils/sysctl"
)
type NetConf struct {
types.NetConf
MultiQueue bool `json:"multiQueue"`
MTU int `json:"mtu"`
Mac string `json:"mac,omitempty"`
Owner *uint32 `json:"owner,omitempty"`
Group *uint32 `json:"group,omitempty"`
SelinuxContext string `json:"selinuxContext,omitempty"`
Args *struct{} `json:"args,omitempty"`
RuntimeConfig struct {
Mac string `json:"mac,omitempty"`
} `json:"runtimeConfig,omitempty"`
}
// MacEnvArgs represents CNI_ARG
type MacEnvArgs struct {
types.CommonArgs
MAC types.UnmarshallableString `json:"mac,omitempty"`
}
func init() {
// this ensures that main runs only on main thread (thread group leader).
// since namespace ops (unshare, setns) are done for a single thread, we
// must ensure that the goroutine does not jump from OS thread to thread
runtime.LockOSThread()
}
func loadConf(args *skel.CmdArgs) (*NetConf, string, error) {
n := &NetConf{}
if err := json.Unmarshal(args.StdinData, n); err != nil {
return nil, "", fmt.Errorf("failed to load netconf: %v", err)
}
if args.Args != "" {
e := MacEnvArgs{}
err := types.LoadArgs(args.Args, &e)
if err != nil {
return nil, "", err
}
if e.MAC != "" {
n.Mac = string(e.MAC)
}
}
if n.RuntimeConfig.Mac != "" {
n.Mac = n.RuntimeConfig.Mac
}
return n, n.CNIVersion, nil
}
// We want to share the parent process std{in|out|err} - fds 0 through 2.
// Since the FDs are inherited on fork / exec, we close on exec all others.
func closeFileDescriptorsOnExec() {
minFDToCloseOnExec := 3
maxFDToCloseOnExec := 256
for fd := minFDToCloseOnExec; fd < maxFDToCloseOnExec; fd++ {
syscall.CloseOnExec(fd)
}
}
// Due to issues with the vishvananda/netlink library (fix pending) it is not possible to create an ownerless/groupless
// tap device. Until the issue is fixed, the workaround for creating a tap device with no owner/group is to use the iptool
func createTapWithIptool(tmpName string, mtu int, multiqueue bool, mac string, owner *uint32, group *uint32) error {
closeFileDescriptorsOnExec()
tapDeviceArgs := []string{"tuntap", "add", "mode", "tap", "name", tmpName}
if multiqueue {
tapDeviceArgs = append(tapDeviceArgs, "multi_queue")
}
if owner != nil {
tapDeviceArgs = append(tapDeviceArgs, "user", fmt.Sprintf("%d", *owner))
}
if group != nil {
tapDeviceArgs = append(tapDeviceArgs, "group", fmt.Sprintf("%d", *group))
}
output, err := exec.Command("ip", tapDeviceArgs...).CombinedOutput()
if err != nil {
return fmt.Errorf("failed to run command %s: %v", output, err)
}
tapDeviceArgs = []string{"link", "set", tmpName}
if mtu != 0 {
tapDeviceArgs = append(tapDeviceArgs, "mtu", strconv.Itoa(mtu))
}
if mac != "" {
tapDeviceArgs = append(tapDeviceArgs, "address", mac)
}
output, err = exec.Command("ip", tapDeviceArgs...).CombinedOutput()
if err != nil {
return fmt.Errorf("failed to run command %s: %v", output, err)
}
return nil
}
func createLinkWithNetlink(tmpName string, mtu int, nsFd int, multiqueue bool, mac string, owner *uint32, group *uint32) error {
linkAttrs := netlink.LinkAttrs{
Name: tmpName,
Namespace: netlink.NsFd(nsFd),
}
if mtu != 0 {
linkAttrs.MTU = mtu
}
mv := &netlink.Tuntap{
LinkAttrs: linkAttrs,
Mode: netlink.TUNTAP_MODE_TAP,
}
if owner != nil {
mv.Owner = *owner
}
if group != nil {
mv.Group = *group
}
if mac != "" {
addr, err := net.ParseMAC(mac)
if err != nil {
return fmt.Errorf("invalid args %v for MAC addr: %v", mac, err)
}
linkAttrs.HardwareAddr = addr
}
mv.Flags = netlink.TUNTAP_VNET_HDR | unix.IFF_TAP
if multiqueue {
mv.Flags = netlink.TUNTAP_MULTI_QUEUE_DEFAULTS | mv.Flags
}
if err := netlink.LinkAdd(mv); err != nil {
return fmt.Errorf("failed to create tap: %v", err)
}
return nil
}
func createLink(tmpName string, conf *NetConf, netns ns.NetNS) error {
switch {
case conf.SelinuxContext != "":
if err := selinux.SetExecLabel(conf.SelinuxContext); err != nil {
return fmt.Errorf("failed set socket label: %v", err)
}
return createTapWithIptool(tmpName, conf.MTU, conf.MultiQueue, conf.Mac, conf.Owner, conf.Group)
case conf.Owner == nil || conf.Group == nil:
return createTapWithIptool(tmpName, conf.MTU, conf.MultiQueue, conf.Mac, conf.Owner, conf.Group)
default:
return createLinkWithNetlink(tmpName, conf.MTU, int(netns.Fd()), conf.MultiQueue, conf.Mac, conf.Owner, conf.Group)
}
}
func createTap(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interface, error) {
tap := &current.Interface{}
// due to kernel bug we have to create with tmpName or it might
// collide with the name on the host and error out
tmpName, err := ip.RandomVethName()
if err != nil {
return nil, err
}
err = netns.Do(func(_ ns.NetNS) error {
err := createLink(tmpName, conf, netns)
if err != nil {
return err
}
if err = ip.RenameLink(tmpName, ifName); err != nil {
link, err := netlink.LinkByName(tmpName)
if err != nil {
netlink.LinkDel(link)
return fmt.Errorf("failed to rename tap to %q: %v", ifName, err)
}
}
tap.Name = ifName
// Re-fetch link to get all properties/attributes
link, err := netlink.LinkByName(ifName)
if err != nil {
return fmt.Errorf("failed to refetch tap %q: %v", ifName, err)
}
err = netlink.LinkSetUp(link)
if err != nil {
return fmt.Errorf("failed to set tap interface up: %v", err)
}
tap.Mac = link.Attrs().HardwareAddr.String()
tap.Sandbox = netns.Path()
return nil
})
if err != nil {
return nil, err
}
return tap, nil
}
func cmdAdd(args *skel.CmdArgs) error {
n, cniVersion, err := loadConf(args)
if err != nil {
return err
}
isLayer3 := n.IPAM.Type != ""
netns, err := ns.GetNS(args.Netns)
if err != nil {
return fmt.Errorf("failed to open netns %q: %v", netns, err)
}
defer netns.Close()
tapInterface, err := createTap(n, args.IfName, netns)
if err != nil {
return err
}
// Delete link if err to avoid link leak in this ns
defer func() {
if err != nil {
netns.Do(func(_ ns.NetNS) error {
return ip.DelLinkByName(args.IfName)
})
}
}()
// Assume L2 interface only
result := &current.Result{
CNIVersion: current.ImplementedSpecVersion,
Interfaces: []*current.Interface{tapInterface},
}
if isLayer3 {
// run the IPAM plugin and get back the config to apply
r, err := ipam.ExecAdd(n.IPAM.Type, args.StdinData)
if err != nil {
return err
}
// Invoke ipam del if err to avoid ip leak
defer func() {
if err != nil {
ipam.ExecDel(n.IPAM.Type, args.StdinData)
}
}()
// Convert whatever the IPAM result was into the current Result type
ipamResult, err := current.NewResultFromResult(r)
if err != nil {
return err
}
if len(ipamResult.IPs) == 0 {
return errors.New("IPAM plugin returned missing IP config")
}
result.IPs = ipamResult.IPs
result.Routes = ipamResult.Routes
for _, ipc := range result.IPs {
// All addresses apply to the container tap interface
ipc.Interface = current.Int(0)
}
err = netns.Do(func(_ ns.NetNS) error {
_, _ = sysctl.Sysctl(fmt.Sprintf("net/ipv4/conf/%s/arp_notify", args.IfName), "1")
return ipam.ConfigureIface(args.IfName, result)
})
if err != nil {
return err
}
} else {
// For L2 just change interface status to up
err = netns.Do(func(_ ns.NetNS) error {
tapInterfaceLink, err := netlink.LinkByName(args.IfName)
if err != nil {
return fmt.Errorf("failed to find interface name %q: %v", tapInterface.Name, err)
}
if err := netlink.LinkSetUp(tapInterfaceLink); err != nil {
return fmt.Errorf("failed to set %q UP: %v", args.IfName, err)
}
return nil
})
if err != nil {
return err
}
}
result.DNS = n.DNS
return types.PrintResult(result, cniVersion)
}
func cmdDel(args *skel.CmdArgs) error {
n, _, err := loadConf(args)
if err != nil {
return err
}
isLayer3 := n.IPAM.Type != ""
if isLayer3 {
err = ipam.ExecDel(n.IPAM.Type, args.StdinData)
if err != nil {
return err
}
}
if args.Netns == "" {
return nil
}
// There is a netns so try to clean up. Delete can be called multiple times
// so don't return an error if the device is already removed.
err = ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error {
if err := ip.DelLinkByName(args.IfName); err != nil {
if err != ip.ErrLinkNotFound {
return err
}
}
return nil
})
if err != nil {
// if NetNs is passed down by the Cloud Orchestration Engine, or if it called multiple times
// so don't return an error if the device is already removed.
// https://github.com/kubernetes/kubernetes/issues/43014#issuecomment-287164444
_, ok := err.(ns.NSPathNotExistErr)
if ok {
return nil
}
return err
}
return err
}
func main() {
skel.PluginMain(cmdAdd, cmdCheck, cmdDel, version.All, bv.BuildString("tap"))
}
func cmdCheck(args *skel.CmdArgs) error {
n, _, err := loadConf(args)
if err != nil {
return err
}
isLayer3 := n.IPAM.Type != ""
netns, err := ns.GetNS(args.Netns)
if err != nil {
return fmt.Errorf("failed to open netns %q: %v", args.Netns, err)
}
defer netns.Close()
if isLayer3 {
// run the IPAM plugin and get back the config to apply
err = ipam.ExecCheck(n.IPAM.Type, args.StdinData)
if err != nil {
return err
}
}
// Parse previous result.
if n.NetConf.RawPrevResult == nil {
return fmt.Errorf("Required prevResult missing")
}
if err := version.ParsePrevResult(&n.NetConf); err != nil {
return err
}
result, err := current.NewResultFromResult(n.PrevResult)
if err != nil {
return err
}
var contMap current.Interface
// Find interfaces for names whe know, tap device name inside container
for _, intf := range result.Interfaces {
if args.IfName == intf.Name {
if args.Netns == intf.Sandbox {
contMap = *intf
continue
}
}
}
// The namespace must be the same as what was configured
if args.Netns != contMap.Sandbox {
return fmt.Errorf("Sandbox in prevResult %s doesn't match configured netns: %s",
contMap.Sandbox, args.Netns)
}
// Check prevResults for ips, routes and dns against values found in the container
return netns.Do(func(_ ns.NetNS) error {
err = ip.ValidateExpectedInterfaceIPs(args.IfName, result.IPs)
if err != nil {
return err
}
err = ip.ValidateExpectedRoute(result.Routes)
if err != nil {
return err
}
return nil
})
}

View File

@ -0,0 +1,27 @@
// Copyright 2022 CNI 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 main
import (
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestTap(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "plugins/meta/tap")
}

View File

@ -0,0 +1,318 @@
// Copyright 2022 CNI 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 main
import (
"encoding/json"
"fmt"
"net"
"os"
"strings"
"syscall"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/vishvananda/netlink"
"github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/types"
types020 "github.com/containernetworking/cni/pkg/types/020"
types040 "github.com/containernetworking/cni/pkg/types/040"
types100 "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containernetworking/plugins/pkg/testutils"
"github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator"
)
const (
TYPETAP = "tuntap"
IFNAME = "tapifc"
)
type Net struct {
Name string `json:"name"`
CNIVersion string `json:"cniVersion"`
Type string `json:"type,omitempty"`
IPAM *allocator.IPAMConfig `json:"ipam"`
RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
PrevResult types100.Result `json:"-"`
}
func buildOneConfig(netName string, cniVersion string, orig *Net, prevResult types.Result) (*Net, error) {
var err error
inject := map[string]interface{}{
"name": netName,
"cniVersion": cniVersion,
}
// Add previous plugin result
if prevResult != nil {
inject["prevResult"] = prevResult
}
// Ensure every config uses the same name and version
config := make(map[string]interface{})
confBytes, err := json.Marshal(orig)
if err != nil {
return nil, err
}
err = json.Unmarshal(confBytes, &config)
if err != nil {
return nil, fmt.Errorf("unmarshal existing network bytes: %s", err)
}
for key, value := range inject {
config[key] = value
}
newBytes, err := json.Marshal(config)
if err != nil {
return nil, err
}
conf := &Net{}
if err := json.Unmarshal(newBytes, &conf); err != nil {
return nil, fmt.Errorf("error parsing configuration: %s", err)
}
return conf, nil
}
type tester interface {
// verifyResult minimally verifies the Result and returns the interface's MAC address
verifyResult(result types.Result, name string) string
}
type testerBase struct{}
type (
testerV10x testerBase
testerV04x testerBase
testerV03x testerBase
testerV01xOr02x testerBase
)
func newTesterByVersion(version string) tester {
switch {
case strings.HasPrefix(version, "1.0."):
return &testerV10x{}
case strings.HasPrefix(version, "0.4."):
return &testerV04x{}
case strings.HasPrefix(version, "0.3."):
return &testerV03x{}
default:
return &testerV01xOr02x{}
}
}
// verifyResult minimally verifies the Result and returns the interface's MAC address
func (t *testerV10x) verifyResult(result types.Result, name string) string {
r, err := types100.GetResult(result)
Expect(err).NotTo(HaveOccurred())
Expect(r.Interfaces).To(HaveLen(1))
Expect(r.Interfaces[0].Name).To(Equal(name))
Expect(r.IPs).To(HaveLen(1))
return r.Interfaces[0].Mac
}
func verify0403(result types.Result, name string) string {
r, err := types040.GetResult(result)
Expect(err).NotTo(HaveOccurred())
Expect(r.Interfaces).To(HaveLen(1))
Expect(r.Interfaces[0].Name).To(Equal(name))
Expect(r.IPs).To(HaveLen(1))
return r.Interfaces[0].Mac
}
// verifyResult minimally verifies the Result and returns the interface's MAC address
func (t *testerV04x) verifyResult(result types.Result, name string) string {
return verify0403(result, name)
}
// verifyResult minimally verifies the Result and returns the interface's MAC address
func (t *testerV03x) verifyResult(result types.Result, name string) string {
return verify0403(result, name)
}
// verifyResult minimally verifies the Result and returns the interface's MAC address
func (t *testerV01xOr02x) verifyResult(result types.Result, _ string) string {
r, err := types020.GetResult(result)
Expect(err).NotTo(HaveOccurred())
Expect(r.IP4.IP.IP).NotTo(BeNil())
Expect(r.IP6).To(BeNil())
// 0.2 and earlier don't return MAC address
return ""
}
// Note: the tests might not work with some security modules (like selinux) enabled
// To test with security modules enabled please provide an appropriate plugin for creating the tap device
var _ = Describe("Add, check, remove tap plugin", func() {
var originalNS, targetNS ns.NetNS
var dataDir string
BeforeEach(func() {
// Create a new NetNS so we don't modify the host
var err error
originalNS, err = testutils.NewNS()
Expect(err).NotTo(HaveOccurred())
targetNS, err = testutils.NewNS()
Expect(err).NotTo(HaveOccurred())
dataDir, err = os.MkdirTemp("", "dummy")
Expect(err).NotTo(HaveOccurred())
})
AfterEach(func() {
Expect(os.RemoveAll(dataDir)).To(Succeed())
Expect(originalNS.Close()).To(Succeed())
Expect(testutils.UnmountNS(originalNS)).To(Succeed())
Expect(targetNS.Close()).To(Succeed())
Expect(testutils.UnmountNS(targetNS)).To(Succeed())
})
for _, ver := range testutils.AllSpecVersions {
ver := ver
It(fmt.Sprintf("[%s] add, check and remove a tap device run correctly", ver), func() {
conf := fmt.Sprintf(`{
"cniVersion": "%s",
"name": "tapTest",
"type": "tap",
"owner": 0,
"group": 0,
"ipam": {
"type": "host-local",
"subnet": "10.1.2.0/24",
"dataDir": "%s"
}
}`, ver, dataDir)
args := &skel.CmdArgs{
ContainerID: "dummy",
Netns: targetNS.Path(),
IfName: IFNAME,
StdinData: []byte(conf),
}
t := newTesterByVersion(ver)
var result types.Result
var macAddress string
var err error
err = originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
result, _, err = testutils.CmdAddWithArgs(args, func() error {
return cmdAdd(args)
})
Expect(err).NotTo(HaveOccurred())
macAddress = t.verifyResult(result, IFNAME)
return nil
})
Expect(err).NotTo(HaveOccurred())
By("Make sure the tap link exists in the target namespace")
err = targetNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
link, err := netlink.LinkByName(IFNAME)
Expect(err).NotTo(HaveOccurred())
Expect(link.Attrs().Name).To(Equal(IFNAME))
Expect(link.Type()).To(Equal(TYPETAP))
if macAddress != "" {
hwaddr, err := net.ParseMAC(macAddress)
Expect(err).NotTo(HaveOccurred())
Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr))
}
addrs, err := netlink.AddrList(link, syscall.AF_INET)
Expect(err).NotTo(HaveOccurred())
Expect(addrs).To(HaveLen(1))
return nil
})
Expect(err).NotTo(HaveOccurred())
By("Running cmdCheck")
n := &Net{}
err = json.Unmarshal([]byte(conf), &n)
Expect(err).NotTo(HaveOccurred())
n.IPAM, _, err = allocator.LoadIPAMConfig([]byte(conf), "")
Expect(err).NotTo(HaveOccurred())
newConf, err := buildOneConfig("tapTest", ver, n, result)
Expect(err).NotTo(HaveOccurred())
confString, err := json.Marshal(newConf)
Expect(err).NotTo(HaveOccurred())
args.StdinData = confString
err = originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
return testutils.CmdCheckWithArgs(args, func() error { return cmdCheck(args) })
})
if testutils.SpecVersionHasCHECK(ver) {
Expect(err).NotTo(HaveOccurred())
} else {
Expect(err).To(MatchError("config version does not allow CHECK"))
}
By("Running cmdDel")
args.StdinData = []byte(conf)
err = originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
err = testutils.CmdDelWithArgs(args, func() error {
return cmdDel(args)
})
Expect(err).NotTo(HaveOccurred())
return nil
})
Expect(err).NotTo(HaveOccurred())
err = targetNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
link, err := netlink.LinkByName(IFNAME)
Expect(err).To(HaveOccurred())
Expect(link).To(BeNil())
return nil
})
Expect(err).NotTo(HaveOccurred())
By("Running cmdDel more than once without error")
err = originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
err = testutils.CmdDelWithArgs(args, func() error {
return cmdDel(args)
})
Expect(err).NotTo(HaveOccurred())
return nil
})
Expect(err).NotTo(HaveOccurred())
})
}
})

View File

@ -26,7 +26,6 @@ import (
"github.com/containernetworking/cni/pkg/types"
current "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/cni/pkg/version"
"github.com/containernetworking/plugins/pkg/ip"
"github.com/containernetworking/plugins/pkg/ipam"
"github.com/containernetworking/plugins/pkg/ns"
@ -35,9 +34,10 @@ import (
type NetConf struct {
types.NetConf
Master string `json:"master"`
VlanId int `json:"vlanId"`
MTU int `json:"mtu,omitempty"`
Master string `json:"master"`
VlanID int `json:"vlanId"`
MTU int `json:"mtu,omitempty"`
LinkContNs bool `json:"linkInContainer,omitempty"`
}
func init() {
@ -47,32 +47,47 @@ func init() {
runtime.LockOSThread()
}
func loadConf(bytes []byte) (*NetConf, string, error) {
func loadConf(args *skel.CmdArgs) (*NetConf, string, error) {
n := &NetConf{}
if err := json.Unmarshal(bytes, n); err != nil {
if err := json.Unmarshal(args.StdinData, n); err != nil {
return nil, "", fmt.Errorf("failed to load netconf: %v", err)
}
if n.Master == "" {
return nil, "", fmt.Errorf("\"master\" field is required. It specifies the host interface name to create the VLAN for.")
return nil, "", fmt.Errorf("\"master\" field is required. It specifies the host interface name to create the VLAN for")
}
if n.VlanId < 0 || n.VlanId > 4094 {
return nil, "", fmt.Errorf("invalid VLAN ID %d (must be between 0 and 4095 inclusive)", n.VlanId)
if n.VlanID < 0 || n.VlanID > 4094 {
return nil, "", fmt.Errorf("invalid VLAN ID %d (must be between 0 and 4095 inclusive)", n.VlanID)
}
// check existing and MTU of master interface
masterMTU, err := getMTUByName(n.Master)
masterMTU, err := getMTUByName(n.Master, args.Netns, n.LinkContNs)
if err != nil {
return nil, "", err
}
if n.MTU < 0 || n.MTU > masterMTU {
return nil, "", fmt.Errorf("invalid MTU %d, must be [0, master MTU(%d)]", n.MTU, masterMTU)
}
return n, n.CNIVersion, nil
}
func getMTUByName(ifName string) (int, error) {
link, err := netlink.LinkByName(ifName)
func getMTUByName(ifName string, namespace string, inContainer bool) (int, error) {
var link netlink.Link
var err error
if inContainer {
var netns ns.NetNS
netns, err = ns.GetNS(namespace)
if err != nil {
return 0, fmt.Errorf("failed to open netns %q: %v", netns, err)
}
defer netns.Close()
err = netns.Do(func(_ ns.NetNS) error {
link, err = netlink.LinkByName(ifName)
return err
})
} else {
link, err = netlink.LinkByName(ifName)
}
if err != nil {
return 0, err
}
@ -82,7 +97,17 @@ func getMTUByName(ifName string) (int, error) {
func createVlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interface, error) {
vlan := &current.Interface{}
m, err := netlink.LinkByName(conf.Master)
var m netlink.Link
var err error
if conf.LinkContNs {
err = netns.Do(func(_ ns.NetNS) error {
m, err = netlink.LinkByName(conf.Master)
return err
})
} else {
m, err = netlink.LinkByName(conf.Master)
}
if err != nil {
return nil, fmt.Errorf("failed to lookup master %q: %v", conf.Master, err)
}
@ -101,10 +126,17 @@ func createVlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interfac
ParentIndex: m.Attrs().Index,
Namespace: netlink.NsFd(int(netns.Fd())),
},
VlanId: conf.VlanId,
VlanId: conf.VlanID,
}
if err := netlink.LinkAdd(v); err != nil {
if conf.LinkContNs {
err = netns.Do(func(_ ns.NetNS) error {
return netlink.LinkAdd(v)
})
} else {
err = netlink.LinkAdd(v)
}
if err != nil {
return nil, fmt.Errorf("failed to create vlan: %v", err)
}
@ -133,7 +165,7 @@ func createVlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interfac
}
func cmdAdd(args *skel.CmdArgs) error {
n, cniVersion, err := loadConf(args.StdinData)
n, cniVersion, err := loadConf(args)
if err != nil {
return err
}
@ -191,7 +223,7 @@ func cmdAdd(args *skel.CmdArgs) error {
}
func cmdDel(args *skel.CmdArgs) error {
n, _, err := loadConf(args.StdinData)
n, _, err := loadConf(args)
if err != nil {
return err
}
@ -277,7 +309,15 @@ func cmdCheck(args *skel.CmdArgs) error {
contMap.Sandbox, args.Netns)
}
m, err := netlink.LinkByName(conf.Master)
if conf.LinkContNs {
err = netns.Do(func(_ ns.NetNS) error {
_, err = netlink.LinkByName(conf.Master)
return err
})
} else {
_, err = netlink.LinkByName(conf.Master)
}
if err != nil {
return fmt.Errorf("failed to lookup master %q: %v", conf.Master, err)
}
@ -285,9 +325,8 @@ func cmdCheck(args *skel.CmdArgs) error {
//
// Check prevResults for ips, routes and dns against values found in the container
if err := netns.Do(func(_ ns.NetNS) error {
// Check interface against values found in the container
err := validateCniContainerInterface(contMap, m.Attrs().Index, conf.VlanId, conf.MTU)
err := validateCniContainerInterface(contMap, conf.VlanID, conf.MTU)
if err != nil {
return err
}
@ -309,8 +348,7 @@ func cmdCheck(args *skel.CmdArgs) error {
return nil
}
func validateCniContainerInterface(intf current.Interface, masterIndex int, vlanId int, mtu int) error {
func validateCniContainerInterface(intf current.Interface, vlanID int, mtu int) error {
var link netlink.Link
var err error
@ -331,7 +369,7 @@ func validateCniContainerInterface(intf current.Interface, masterIndex int, vlan
}
// TODO This works when unit testing via cnitool; fails with ./test.sh
//if masterIndex != vlan.Attrs().ParentIndex {
// if masterIndex != vlan.Attrs().ParentIndex {
// return fmt.Errorf("Container vlan Master %d does not match expected value: %d", vlan.Attrs().ParentIndex, masterIndex)
//}
@ -341,9 +379,9 @@ func validateCniContainerInterface(intf current.Interface, masterIndex int, vlan
}
}
if vlanId != vlan.VlanId {
if vlanID != vlan.VlanId {
return fmt.Errorf("Error: Tuning link %s configured promisc is %v, current value is %d",
intf.Name, vlanId, vlan.VlanId)
intf.Name, vlanID, vlan.VlanId)
}
if mtu != 0 {

View File

@ -15,10 +15,10 @@
package main
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestVlan(t *testing.T) {

Some files were not shown because too many files have changed in this diff Show More