Compare commits

..

200 Commits

Author SHA1 Message Date
c29dc79f96 Merge pull request #1056 from containernetworking/dependabot/go_modules/golang-82cdb19fbc
build(deps): bump the golang group across 1 directory with 3 updates
2024-06-17 17:46:35 +02:00
508c94caec build(deps): bump the golang group across 1 directory with 3 updates
Bumps the golang group with 2 updates in the / directory: [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) and [github.com/safchain/ethtool](https://github.com/safchain/ethtool).


Updates `github.com/onsi/ginkgo/v2` from 2.17.3 to 2.19.0
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/ginkgo/compare/v2.17.3...v2.19.0)

Updates `github.com/safchain/ethtool` from 0.3.0 to 0.4.0
- [Release notes](https://github.com/safchain/ethtool/releases)
- [Commits](https://github.com/safchain/ethtool/compare/v0.3.0...v0.4.0)

Updates `golang.org/x/sys` from 0.20.0 to 0.21.0
- [Commits](https://github.com/golang/sys/compare/v0.20.0...v0.21.0)

---
updated-dependencies:
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang
- dependency-name: github.com/safchain/ethtool
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-17 15:23:00 +00:00
b96f963c7a Merge pull request #1049 from containernetworking/dependabot/docker/dot-github/actions/retest-action/alpine-3.20
build(deps): bump alpine from 3.19 to 3.20 in /.github/actions/retest-action
2024-06-17 17:06:40 +02:00
518bc80c56 Merge pull request #1054 from s1061123/fix/1053
Fix release tar images' owner to root
2024-06-17 17:04:40 +02:00
434e9b9ef7 Fix release tar images' owner to root
Fix #1053

Signed-off-by: Tomofumi Hayashi <tohayash@redhat.com>
2024-06-17 11:06:40 +09:00
0e87bccf19 build(deps): bump alpine in /.github/actions/retest-action
Bumps alpine from 3.19 to 3.20.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-27 02:43:07 +00:00
0259301ae2 Merge pull request #1043 from containernetworking/dependabot/go_modules/golang-efff583b38
build(deps): bump the golang group with 2 updates
2024-05-20 09:14:04 +02:00
14cad164ec build(deps): bump the golang group with 2 updates
Bumps the golang group with 2 updates: [github.com/onsi/gomega](https://github.com/onsi/gomega) and [golang.org/x/sys](https://github.com/golang/sys).


Updates `github.com/onsi/gomega` from 1.33.0 to 1.33.1
- [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.33.0...v1.33.1)

Updates `golang.org/x/sys` from 0.19.0 to 0.20.0
- [Commits](https://github.com/golang/sys/compare/v0.19.0...v0.20.0)

---
updated-dependencies:
- dependency-name: github.com/onsi/gomega
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: golang
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-20 02:50:01 +00:00
1868e4fe2d Merge pull request #1035 from containernetworking/dependabot/github_actions/golangci/golangci-lint-action-6 2024-05-16 15:45:32 +00:00
5c95925a71 build(deps): bump golangci/golangci-lint-action from 4 to 6
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 4 to 6.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v4...v6)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-16 15:35:37 +00:00
505f5a7def Merge pull request #1042 from containernetworking/dependabot/go_modules/golang-e5a06e9046 2024-05-16 13:27:36 +00:00
dc8b8289fa build(deps): bump the golang group across 1 directory with 4 updates
Bumps the golang group with 2 updates in the / directory: [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) and [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo).


Updates `github.com/Microsoft/hcsshim` from 0.12.2 to 0.12.3
- [Release notes](https://github.com/Microsoft/hcsshim/releases)
- [Commits](https://github.com/Microsoft/hcsshim/compare/v0.12.2...v0.12.3)

Updates `github.com/onsi/ginkgo/v2` from 2.17.1 to 2.17.3
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/ginkgo/compare/v2.17.1...v2.17.3)

Updates `github.com/onsi/gomega` from 1.32.0 to 1.33.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.32.0...v1.33.0)

Updates `golang.org/x/sys` from 0.18.0 to 0.19.0
- [Commits](https://github.com/golang/sys/compare/v0.18.0...v0.19.0)

---
updated-dependencies:
- dependency-name: github.com/Microsoft/hcsshim
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: golang
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: golang
- dependency-name: github.com/onsi/gomega
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-16 13:16:06 +00:00
196ed2d00e Merge pull request #1040 from squeed/dependabot-dont-bump-cni
dependabot: don't automatically update cni packages
2024-05-16 22:14:58 +09:00
43139b3375 Merge branch 'main' into dependabot-dont-bump-cni 2024-05-16 21:43:34 +09:00
18d129f18b Merge pull request #1039 from squeed/bump-go-version
build: bump release go version
2024-05-16 21:42:44 +09:00
9397270f5e dependabot: don't automatically update cni packages
We should manage their lifecycle separately.

Signed-off-by: Casey Callendrello <c1@caseyc.net>
2024-05-16 11:25:50 +02:00
3656c69d0f build: bump release go version
Signed-off-by: Casey Callendrello <c1@caseyc.net>
2024-05-16 11:22:33 +02:00
3af6e6b61d Merge pull request #1037 from s1061123/fix-buildversion
Fix release script in github action
2024-05-16 11:16:34 +02:00
427af8636f Fix release script in github action
This changes adds BuildVersion linker flag in release to
fix CNI plugins output. Fixes #1019.

Signed-off-by: Tomofumi Hayashi <tohayash@redhat.com>
2024-05-15 02:55:03 +09:00
dc704d19d6 Merge pull request #1034 from testwill/close_file
fix: close resolv.conf
2024-05-13 21:19:20 +09:00
45a24d5d95 Merge branch 'main' into close_file 2024-05-13 17:23:42 +09:00
c0533466c8 Merge pull request #1029 from samuelkarp/log-peer-veth-failure
ip: include peer name in error message
2024-05-13 17:23:30 +09:00
ada798a3f7 fix: close resolv.conf
Signed-off-by: guoguangwu <guoguangwug@gmail.com>
2024-05-08 20:38:15 +08:00
eb49a034c4 ip: include peer name in error message
If makeVeth fails as a peer exists, the existing peer name should be
included in the error message.

Signed-off-by: Samuel Karp <samuelkarp@google.com>
2024-04-26 15:49:08 -07:00
670139cffa Merge pull request #1027 from containernetworking/dependabot/go_modules/golang.org/x/net-0.23.0
build(deps): bump golang.org/x/net from 0.20.0 to 0.23.0
2024-04-22 14:56:13 +09:00
717b4337b5 build(deps): bump golang.org/x/net from 0.20.0 to 0.23.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.20.0 to 0.23.0.
- [Commits](https://github.com/golang/net/compare/v0.20.0...v0.23.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-19 13:05:48 +00:00
ef076afac1 Merge pull request #921 from oOraph/dev/exclude_subnets_from_traffic_shapping2
Dev/exclude subnets from traffic shaping2
2024-04-09 00:08:02 +09:00
ccc1cfaa58 Simplify unit test
Signed-off-by: Tomofumi Hayashi <tohayash@redhat.com>
2024-04-08 15:42:20 +09:00
78ebd8bfb9 minor case change
even if json unmarshalling in golang with the standard libs is case unsensitive regarding the keys

Signed-off-by: Raphael <oOraph@users.noreply.github.com>
2024-04-08 15:39:47 +09:00
c666d1400d bandwidth plugin: split unit tests in several files
Signed-off-by: Raphael <oOraph@users.noreply.github.com>
2024-04-08 15:39:47 +09:00
ab0b386b4e bandwidth: possibility to specify shaped subnets or to exclude some from shaping
Signed-off-by: Raphael <oOraph@users.noreply.github.com>
2024-04-08 15:39:47 +09:00
52da39d3aa bandwidth: possibility to exclude some subnets from traffic shaping
what changed:

we had to refactor the bandwidth plugin and switch from a classless qdisc (tbf)
to a classful qdisc (htb).

subnets are to be provided in config or runtimeconfig just like other parameters

unit and integration tests were also adapted in consequence

unrelated changes:

test fixes: the most important tests were just silently skipped due to ginkgo Measure deprecation
(the ones actually checking the effectiveness of the traffic control)

Signed-off-by: Raphael <oOraph@users.noreply.github.com>
2024-04-08 15:39:46 +09:00
597408952e Merge pull request #1023 from containernetworking/dependabot/go_modules/golang-09a819dc01
build(deps): bump the golang group with 1 update
2024-04-03 20:45:59 +09:00
6f05dc325a build(deps): bump the golang group with 1 update
Bumps the golang group with 1 update: [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim).


Updates `github.com/Microsoft/hcsshim` from 0.12.1 to 0.12.2
- [Release notes](https://github.com/Microsoft/hcsshim/releases)
- [Commits](https://github.com/Microsoft/hcsshim/compare/v0.12.1...v0.12.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-01 02:41:52 +00:00
8ab3c63c2d Merge pull request #1022 from containernetworking/dependabot/go_modules/golang-e423e5d544
build(deps): bump the golang group with 4 updates
2024-03-25 15:37:06 +01:00
c464674317 build(deps): bump the golang group with 4 updates
Bumps the golang group with 4 updates: [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim), [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo), [github.com/onsi/gomega](https://github.com/onsi/gomega) and [golang.org/x/sys](https://github.com/golang/sys).


Updates `github.com/Microsoft/hcsshim` from 0.12.0 to 0.12.1
- [Release notes](https://github.com/Microsoft/hcsshim/releases)
- [Commits](https://github.com/Microsoft/hcsshim/compare/v0.12.0...v0.12.1)

Updates `github.com/onsi/ginkgo/v2` from 2.16.0 to 2.17.1
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/ginkgo/compare/v2.16.0...v2.17.1)

Updates `github.com/onsi/gomega` from 1.31.1 to 1.32.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.31.1...v1.32.0)

Updates `golang.org/x/sys` from 0.17.0 to 0.18.0
- [Commits](https://github.com/golang/sys/compare/v0.17.0...v0.18.0)

---
updated-dependencies:
- dependency-name: github.com/Microsoft/hcsshim
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: golang
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang
- dependency-name: github.com/onsi/gomega
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-25 02:15:46 +00:00
c860b78de4 Merge pull request #1003 from adrianchiris/support-sf
Support DeviceID on Auxiliary Bus
2024-03-12 21:05:16 +09:00
9f1bf2a848 Merge branch 'main' into support-sf 2024-03-12 20:51:56 +09:00
7567d28a73 Merge pull request #1002 from adrianchiris/use-temp-name
Use temporary name for netdevice when moving in/out of NS
2024-03-12 20:51:08 +09:00
ba5bdafe5d Use temporary name for netdevice when moving in/out of NS
Today, it is not possible to use host-device CNI to move a
host device to container namespace if a device already exists
in that namespace.

e.g when a delegate plugin (such as multus) is used to provide
multiple networks to a container, CNI Add call will fail if
the targeted host device name already exists in container network
namespace.

to overcome this, we use a temporary name for the interface before
moving it in/out of container network namespace.

Signed-off-by: adrianc <adrianc@nvidia.com>
2024-03-12 12:25:23 +02:00
d34720b531 Support DeviceID on Auxiliary Bus
Device plugins may allocate network device on a bus
different than PCI.

sriov-network-device-plugin supports the allocation
of network devices over Auxiliary bus[1][2][3].

extend host-device CNI to support such devices if provided
through runtime config.

- Check if device provided by DeviceID runtime config
  is present on either PCI bus or Auxiliary bus
- extend getLink method to support getting netdev link obj
  from auxiliary bus
- add unit-test to cover the new flow

[1] https://github.com/k8snetworkplumbingwg/sriov-network-device-plugin/tree/master?tab=readme-ov-file#auxiliary-network-devices-selectors
[2] https://github.com/k8snetworkplumbingwg/sriov-network-device-plugin/tree/master/docs/subfunctions
[3] https://docs.kernel.org/networking/devlink/devlink-port.html

Signed-off-by: adrianc <adrianc@nvidia.com>
2024-03-12 12:09:29 +02:00
8fc26ce7a0 Merge pull request #991 from containernetworking/dependabot/docker/dot-github/actions/retest-action/alpine-3.19
build(deps): bump alpine from 3.18 to 3.19 in /.github/actions/retest-action
2024-03-12 02:54:07 +09:00
c8d165df6d Merge branch 'main' into dependabot/docker/dot-github/actions/retest-action/alpine-3.19 2024-03-12 02:27:00 +09:00
1b5811957e Merge pull request #1010 from containernetworking/dependabot/github_actions/actions/checkout-4
build(deps): bump actions/checkout from 3 to 4
2024-03-11 18:12:59 +01:00
8a3014f202 build(deps): bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-11 17:03:59 +00:00
019727a392 Merge pull request #1005 from austinvazquez/update-golangci-lint-action-package
Update golangci-lint-action package to v4
2024-03-11 18:03:14 +01:00
352e0512e8 Update golangci-lint-action package to v4
This change updates golangci-lint-action package to v4 to resolve NodeJS
16 deprecation warnings.

Signed-off-by: Austin Vazquez <macedonv@amazon.com>
2024-03-11 17:52:02 +01:00
9c016b5d12 Rename unused variables to resolve lint warnings
Signed-off-by: Austin Vazquez <macedonv@amazon.com>
2024-03-11 17:52:02 +01:00
0729398940 Merge pull request #1017 from containernetworking/dependabot/go_modules/golang-6a70725da1
build(deps): bump the golang group with 5 updates
2024-03-11 17:50:33 +01:00
394ab0d149 build(deps): bump the golang group with 5 updates
Bumps the golang group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) | `0.11.4` | `0.12.0` |
| [github.com/alexflint/go-filemutex](https://github.com/alexflint/go-filemutex) | `1.2.0` | `1.3.0` |
| [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) | `2.13.2` | `2.16.0` |
| [github.com/onsi/gomega](https://github.com/onsi/gomega) | `1.30.0` | `1.31.1` |
| [golang.org/x/sys](https://github.com/golang/sys) | `0.15.0` | `0.17.0` |


Updates `github.com/Microsoft/hcsshim` from 0.11.4 to 0.12.0
- [Release notes](https://github.com/Microsoft/hcsshim/releases)
- [Commits](https://github.com/Microsoft/hcsshim/compare/v0.11.4...v0.12.0)

Updates `github.com/alexflint/go-filemutex` from 1.2.0 to 1.3.0
- [Release notes](https://github.com/alexflint/go-filemutex/releases)
- [Commits](https://github.com/alexflint/go-filemutex/compare/v1.2.0...v1.3.0)

Updates `github.com/onsi/ginkgo/v2` from 2.13.2 to 2.16.0
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/ginkgo/compare/v2.13.2...v2.16.0)

Updates `github.com/onsi/gomega` from 1.30.0 to 1.31.1
- [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.30.0...v1.31.1)

Updates `golang.org/x/sys` from 0.15.0 to 0.17.0
- [Commits](https://github.com/golang/sys/compare/v0.15.0...v0.17.0)

---
updated-dependencies:
- dependency-name: github.com/Microsoft/hcsshim
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang
- dependency-name: github.com/alexflint/go-filemutex
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang
- dependency-name: github.com/onsi/gomega
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-11 15:54:46 +00:00
0144de0fcf Merge pull request #1011 from containernetworking/dependabot/github_actions/actions/setup-go-5
build(deps): bump actions/setup-go from 3 to 5
2024-03-11 16:51:01 +01:00
47373d2612 build(deps): bump actions/setup-go from 3 to 5
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 3 to 5.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v3...v5)

---
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>
2024-03-11 15:07:08 +00:00
8e8410f726 Merge pull request #1006 from austinvazquez/update-go-in-ci
Update to Go v1.22 in CI and release
2024-03-11 16:06:20 +01:00
2bae9b67d3 Update to Go v1.22 in CI and release
Signed-off-by: Austin Vazquez <macedonv@amazon.com>
2024-03-11 15:52:12 +01:00
976edfe1bc Merge pull request #1009 from adrianchiris/fix-lint-version
Fix version of golangci-lint
2024-03-11 15:51:56 +01:00
cb244060c2 Fix version of golangci-lint
currently the workflow will use latest
version which is a moving target.

newer versions may cause ci failures due
to new checks added.

Signed-off-by: adrianc <adrianc@nvidia.com>
2024-02-13 10:35:41 +02:00
d1aada912d Merge pull request #1000 from s1061123/add-build-gh-action
Add github action to build binaries for each platform at release
2024-02-12 17:28:13 +01:00
8b2b1d20d6 Add github action to build binaries for each platform at release
This change introduces new github action to build cni plugin
binaries for each platform at tagged new release.

Signed-off-by: Tomofumi Hayashi <tohayash@redhat.com>
2024-02-06 01:01:35 +09:00
14bdce598f Merge pull request #997 from ormergi/bridge-cont-iface-state
bridge: Enable disabling bridge interface
2024-02-02 21:22:32 +01:00
7e131a0076 bridge: Enable disabling bridge interface
The new `disableContainerInterface` parameter is added to the bridge plugin to
enable setting the container interface state down.

When the parameter is enabled, the container interface (veth peer that is placed
at the container ns) remain down (i.e: disabled).
The bridge and host peer interfaces state are not affected by the parameter.

Since IPAM logic involve various configurations including waiting for addresses
to be realized and setting the interface state UP, the new parameter cannot work
with IPAM.
In case both IPAM and DisableContainerInterface parameters are set, the bridge
plugin will raise an error.

Signed-off-by: Or Mergi <ormergi@redhat.com>
2024-01-10 15:35:23 +02:00
b6a0e0bc96 Merge pull request #990 from containernetworking/dependabot/github_actions/actions/setup-go-5
build(deps): bump actions/setup-go from 4 to 5
2023-12-11 17:08:17 +01:00
133a764c4d build(deps): bump alpine in /.github/actions/retest-action
Bumps alpine from 3.18 to 3.19.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-11 02:50:07 +00:00
e6099fb83d build(deps): bump actions/setup-go from 4 to 5
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 4 to 5.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v4...v5)

---
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-12-11 02:16:03 +00:00
1fb5bf669e Merge pull request #982 from jingyuanliang/patch-1
Bump to golang:1.21-alpine in release.sh
2023-12-04 10:37:33 +01:00
3712c1cfcb Merge pull request #988 from containernetworking/dependabot/go_modules/golang-2d6cee5bad
build(deps): bump the golang group with 2 updates
2023-12-04 10:36:51 +01:00
825421709e build(deps): bump the golang group with 2 updates
Bumps the golang group with 2 updates: [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) and [golang.org/x/sys](https://github.com/golang/sys).


Updates `github.com/onsi/ginkgo/v2` from 2.13.1 to 2.13.2
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/ginkgo/compare/v2.13.1...v2.13.2)

Updates `golang.org/x/sys` from 0.14.0 to 0.15.0
- [Commits](https://github.com/golang/sys/compare/v0.14.0...v0.15.0)

---
updated-dependencies:
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: golang
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-04 02:47:46 +00:00
d708217503 Bump to golang:1.21-alpine in release.sh
Also make this overridable in env vars.

Signed-off-by: Jingyuan Liang <jingyuanliang@google.com>
2023-11-17 09:01:30 +00:00
abee8ccc0d Merge pull request #954 from cyclinder/improve_cmd_del
macvlan cmdDel: replace the loadConf function with json.unmarshal
2023-11-16 19:06:11 +01:00
e1474463ef Merge pull request #978 from containernetworking/dependabot/go_modules/golang-439c5fc513
build(deps): bump the golang group with 3 updates
2023-11-16 19:05:16 +01:00
11ee4b61d9 Merge pull request #969 from s1061123/fix-netns-override
Add CNI_NETNS_OVERRIDE for upcoming CNI change
2023-11-16 19:04:53 +01:00
a4cbf13a9b Add CNI_NETNS_OVERRIDE for upcoming CNI change
containernetwork/cni#890 introduces CNI_NETNS_OVERRIDE and plugin
testing requires this flag. This change enables CNI_NETNS_OVERRIDE
for further containernetwork/cni vendor update.

Signed-off-by: Tomofumi Hayashi <tohayash@redhat.com>
2023-11-16 23:18:00 +09:00
6cac5d603b build(deps): bump the golang group with 3 updates
Bumps the golang group with 3 updates: [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim), [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) and [github.com/onsi/gomega](https://github.com/onsi/gomega).


Updates `github.com/Microsoft/hcsshim` from 0.11.2 to 0.11.4
- [Release notes](https://github.com/Microsoft/hcsshim/releases)
- [Commits](https://github.com/Microsoft/hcsshim/compare/v0.11.2...v0.11.4)

Updates `github.com/onsi/ginkgo/v2` from 2.13.0 to 2.13.1
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/ginkgo/compare/v2.13.0...v2.13.1)

Updates `github.com/onsi/gomega` from 1.29.0 to 1.30.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.29.0...v1.30.0)

---
updated-dependencies:
- dependency-name: github.com/Microsoft/hcsshim
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: golang
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: golang
- dependency-name: github.com/onsi/gomega
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-16 12:41:14 +00:00
333fc9a0d7 Merge pull request #981 from arthur-zhang/dev-revert
revert some code in pr 962
2023-11-16 13:39:59 +01:00
f90ac41ae4 revert some code in pr 962
Signed-off-by: arthur-zhang <zhangya_no1@qq.com>
2023-11-14 10:04:18 +08:00
93a1b3d0e7 Merge pull request #979 from s1061123/fix/ndisc_ipvlan
Add ndisc_notify in ipvlan for ipv6 ndp
2023-11-14 00:27:01 +01:00
00406f9d1e Merge branch 'main' into fix/ndisc_ipvlan 2023-11-14 08:18:07 +09:00
e82848a9cb Merge pull request #962 from arthur-zhang/dev-pr-bridge
bridge: remove useless code
2023-11-13 18:01:02 +01:00
5280b4d582 bridge: fix spelling
Signed-off-by: arthur-zhang <zhangya_no1@qq.com>
2023-11-13 17:11:21 +01:00
495a2cbb0c bridge: remove useless firstV4Addr
Signed-off-by: arthur-zhang <zhangya_no1@qq.com>
2023-11-13 17:11:21 +01:00
8c59fc1eea bridge: remove useless check
gws.defaultRouteFound here is always false.

Signed-off-by: arthur-zhang <zhangya_no1@qq.com>
2023-11-13 17:11:21 +01:00
2eee7cef35 Merge pull request #974 from zshi-redhat/macvlan-ipv6-ndisc
macvlan: enable ipv6 ndisc_notify
2023-11-13 17:08:56 +01:00
1079e113fe Add ndisc_notify in ipvlan for ipv6 ndp
Signed-off-by: Tomofumi Hayashi <tohayash@redhat.com>
2023-11-14 01:07:59 +09:00
999ca15763 macvlan: enable ipv6 ndisc_notify
Signed-off-by: Zenghui Shi <zshi@redhat.com>
2023-11-07 19:43:50 +08:00
dad27e9f72 Merge pull request #963 from containernetworking/dependabot/go_modules/google.golang.org/grpc-1.56.3
build(deps): bump google.golang.org/grpc from 1.50.1 to 1.56.3
2023-11-01 10:21:47 +01:00
0b1a96ff30 build(deps): bump google.golang.org/grpc from 1.50.1 to 1.56.3
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.50.1 to 1.56.3.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.50.1...v1.56.3)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-31 19:09:22 +00:00
c8c26897ba Merge pull request #970 from containernetworking/dependabot/go_modules/golang-1eaf3aa819
build(deps): bump the golang group with 3 updates
2023-10-31 20:08:15 +01:00
28c5faee75 build(deps): bump the golang group with 3 updates
Bumps the golang group with 3 updates: [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim), [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) and [github.com/onsi/gomega](https://github.com/onsi/gomega).


Updates `github.com/Microsoft/hcsshim` from 0.11.1 to 0.11.2
- [Release notes](https://github.com/Microsoft/hcsshim/releases)
- [Commits](https://github.com/Microsoft/hcsshim/compare/v0.11.1...v0.11.2)

Updates `github.com/onsi/ginkgo/v2` from 2.12.0 to 2.13.0
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/ginkgo/compare/v2.12.0...v2.13.0)

Updates `github.com/onsi/gomega` from 1.28.0 to 1.29.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.28.0...v1.29.0)

---
updated-dependencies:
- dependency-name: github.com/Microsoft/hcsshim
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: golang
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang
- dependency-name: github.com/onsi/gomega
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-31 15:06:19 +00:00
d0d9e36662 Merge pull request #961 from squeed/dependabot-batch
dependabot: batch updates
2023-10-31 16:04:45 +01:00
f7662a2435 Merge pull request #968 from mmorel-35/patch-1
fix workflow warnings
2023-10-31 11:47:42 +01:00
aacae5c053 dependabot: batch updates
Rather than endless rebases, just batch all go updates to once a week.

Signed-off-by: Casey Callendrello <c1@caseyc.net>
2023-10-31 11:46:29 +01:00
6b7876125d fix workflow warnings
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2023-10-31 09:07:15 +01:00
2f0faf6721 Merge pull request #967 from squeed/fix-lint
fix lint errors
2023-10-31 08:40:30 +01:00
37531cdaf5 fix lint errors
Fix a small ginkgo compare issue, and ignore dot imports.

Signed-off-by: Casey Callendrello <c1@caseyc.net>
2023-10-30 17:55:55 +01:00
a8d4e0a7dd Merge pull request #949 from containernetworking/dependabot/go_modules/github.com/onsi/gomega-1.28.0
build(deps): bump github.com/onsi/gomega from 1.27.8 to 1.28.0
2023-10-17 12:31:08 +02:00
845ef62b74 macvlan cmdDel: replace the loadConf function with json.unmarshal
When the master interface on the node has been deleted, and loadConf tries
to get the MTU, This causes cmdDel to return a linkNotFound error to the
runtime. The cmdDel only needs to unmarshal the netConf. No need to
get the MTU. So we just replaced the loadConf function with
json.unmarshal in cmdDel.

Signed-off-by: cyclinder <qifeng.guo@daocloud.io>
2023-10-17 10:26:18 +08:00
691186ca7f build(deps): bump github.com/onsi/gomega from 1.27.8 to 1.28.0
Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.27.8 to 1.28.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.27.8...v1.28.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-10-16 15:44:53 +00:00
adaeedd6af Merge pull request #955 from containernetworking/dependabot/go_modules/golang.org/x/net-0.17.0
build(deps): bump golang.org/x/net from 0.10.0 to 0.17.0
2023-10-16 17:43:46 +02:00
19e5747a8c build(deps): bump golang.org/x/net from 0.10.0 to 0.17.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.10.0 to 0.17.0.
- [Commits](https://github.com/golang/net/compare/v0.10.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-16 15:26:26 +00:00
4cf3da4ae3 Merge pull request #948 from twz123/posix-sh
build: Use POSIX sh for shell scripts
2023-10-16 17:25:04 +02:00
c20da1521f Merge pull request #952 from containernetworking/dependabot/go_modules/golang.org/x/sys-0.13.0
build(deps): bump golang.org/x/sys from 0.10.0 to 0.13.0
2023-10-16 17:24:51 +02:00
b66b5dd85f Merge pull request #945 from containernetworking/dependabot/github_actions/actions/checkout-4
build(deps): bump actions/checkout from 3 to 4
2023-10-16 17:23:45 +02:00
e727ad6697 Merge pull request #946 from containernetworking/dependabot/go_modules/github.com/Microsoft/hcsshim-0.11.1
build(deps): bump github.com/Microsoft/hcsshim from 0.9.9 to 0.11.1
2023-10-16 17:23:25 +02:00
18172539d8 build(deps): bump github.com/Microsoft/hcsshim from 0.9.9 to 0.11.1
Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.9.9 to 0.11.1.
- [Release notes](https://github.com/Microsoft/hcsshim/releases)
- [Commits](https://github.com/Microsoft/hcsshim/compare/v0.9.9...v0.11.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-16 15:11:01 +00:00
f20b8408a4 Merge pull request #937 from containernetworking/dependabot/go_modules/github.com/coreos/go-iptables-0.7.0
build(deps): bump github.com/coreos/go-iptables from 0.6.0 to 0.7.0
2023-10-16 17:10:05 +02:00
6ff8e5eb86 Merge pull request #950 from ricky-rav/OCPBUGS-16788
Create IPAM files with 0600 permissions
2023-10-12 09:13:05 -05:00
61fa963636 build(deps): bump golang.org/x/sys from 0.10.0 to 0.13.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.10.0 to 0.13.0.
- [Commits](https://github.com/golang/sys/compare/v0.10.0...v0.13.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-10-09 02:20:37 +00:00
33ccedc66f Create IPAM files with 0600 permissions
Conform to CIS Benchmarks "1.1.9 Ensure that the Container Network Interface file permissions are set to 600 or more restrictive"
https://www.tenable.com/audits/items/CIS_Kubernetes_v1.20_v1.0.1_Level_1_Master.audit:f1717a5dd65d498074dd41c4a639e47d

Signed-off-by: Riccardo Ravaioli <rravaiol@redhat.com>
2023-10-02 11:59:31 +02:00
853b82d19f build: Use POSIX sh for shell scripts
The scripts didn't really use any bash specific features. Convert
them to POSIX shell scripts, so that the plugins can be built without
requiring bash.

Signed-off-by: Tom Wieczorek <twieczorek@mirantis.com>
2023-09-29 16:57:19 +02:00
d216b0c39b build(deps): bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-11 02:11:46 +00:00
f95505231a Merge pull request #942 from mmorel-35/patch-1
ci(lint) extend timeout to 5 min
2023-09-04 17:18:17 +02:00
5f25a93a47 ci(lint) extend timeout to 5 min
This extends the timeout or golangci-lint execution to 5 min as it is only one minute now it fails for several PR.

Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2023-09-01 20:45:00 +00:00
7c11d48630 build(deps): bump github.com/coreos/go-iptables from 0.6.0 to 0.7.0
Bumps [github.com/coreos/go-iptables](https://github.com/coreos/go-iptables) from 0.6.0 to 0.7.0.
- [Release notes](https://github.com/coreos/go-iptables/releases)
- [Commits](https://github.com/coreos/go-iptables/compare/v0.6.0...v0.7.0)

---
updated-dependencies:
- dependency-name: github.com/coreos/go-iptables
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-07 02:47:30 +00:00
9d9ec6e3e1 Merge pull request #927 from sockmister/vrf_filter_fix
vrf: fix route filter to use output iface
2023-07-21 13:49:33 +02:00
8fd63065a6 Merge pull request #913 from AlinaSecret/dhcp/fix-race-test
Fix race conditions in DHCP test
2023-07-21 12:55:01 +02:00
c1a7948b19 vrf: fix route filter to use output iface
current route filter uses RT_FILTER_IIF in conjunction with LinkIndex.
This combination is ignored by netlink, rendering the filter
ineffective

Signed-off-by: Poh Chiat Koh <poh@inter.link>
2023-07-21 12:50:21 +02:00
1561794ae9 Merge pull request #924 from SirPhuttel/go-iptables_review
Review code using go-iptables module
2023-07-21 12:23:08 +02:00
fb8ca5d31e Merge pull request #918 from SirPhuttel/rawhide_testing
Two minor testsuite fixes
2023-07-21 12:22:46 +02:00
f2574a7cb1 Merge pull request #926 from containernetworking/dependabot/go_modules/golang.org/x/sys-0.10.0
build(deps): bump golang.org/x/sys from 0.9.0 to 0.10.0
2023-07-21 11:56:30 +02:00
438548a9dd Merge pull request #902 from SirPhuttel/applyconfigecho
spoofcheck: Make use of go-nft's ApplyConfigEcho()
2023-07-20 12:01:18 +02:00
8e69e38d51 test_linux.sh: Do not fail if called twice
The script is set to exit on error, so mkdir failing because
/tmp/cni-rootless already exists aborts the test run. Call 'mkdir -p' to
avoid the spurious error.

Signed-off-by: Phil Sutter <psutter@redhat.com>
2023-07-20 11:34:34 +02:00
0a100e5d8f meta: firewall: Fix firewalld test with non-abstract sockets
On a recent Fedora Rawhide, dbus-daemon-1.14.8-1 prints a string
prefixed by 'unix:path' instead of the expected 'unix:abstract', thereby
failing the test. Allowing this alternate prefix fixes the test, so for
communication with the daemon it is not relevant.

Signed-off-by: Phil Sutter <psutter@redhat.com>
2023-07-20 11:34:34 +02:00
3eb775c5e6 plugins: meta: portmap: Implement a teardown() fast path
Just attempt to delete the known rules referring to the custom chain,
then flush and delete it. If the latter succeeds, no referencing rules
are left and the job is done.

If the final flush'n'delete fails, fall back to the referencing rule
search which is slow with large rulesets.

Signed-off-by: Phil Sutter <psutter@redhat.com>
2023-07-20 11:34:02 +02:00
719f60bb91 utils: iptables: Use go-iptables' ChainExists()
Starting with v0.5.0, go-iptables exports a fast ChainExists() which
does not rely upon listing all chains and searching the results but
probes chain existence by listing its first rule. This should make a
significant difference in rulesets with thousands of chains.

Signed-off-by: Phil Sutter <psutter@redhat.com>
2023-07-20 11:34:02 +02:00
2ba7f1608f spoofcheck: Make use of go-nft's ApplyConfigEcho()
Store the relevant applied config part for later to extract the rule to
delete from there instead of having to list the ruleset. This is much
faster especially with large rulesets.

Signed-off-by: Phil Sutter <psutter@redhat.com>
2023-07-20 11:32:09 +02:00
bf79945c70 Merge pull request #929 from squeed/fix-ci-cnitool-version
test: install binaries using `go install`
2023-07-20 11:26:31 +02:00
ba41448fe6 test: install binaries using go install
We were getting tip- versions of all the tools, and this was unstable.

Signed-off-by: Casey Callendrello <c1@caseyc.net>
2023-07-20 11:15:41 +02:00
13fd3de77f build(deps): bump golang.org/x/sys from 0.9.0 to 0.10.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.9.0 to 0.10.0.
- [Commits](https://github.com/golang/sys/compare/v0.9.0...v0.10.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-07-10 02:29:05 +00:00
283f200489 Merge pull request #897 from containernetworking/dependabot/docker/dot-github/actions/retest-action/alpine-3.18
build(deps): bump alpine from 3.17 to 3.18 in /.github/actions/retest-action
2023-07-03 17:05:49 +02:00
a7e8db00cb Merge pull request #911 from containernetworking/dependabot/go_modules/golang.org/x/sys-0.9.0
build(deps): bump golang.org/x/sys from 0.7.0 to 0.9.0
2023-07-03 17:05:17 +02:00
ffb2e2d7d1 Merge pull request #912 from containernetworking/dependabot/go_modules/github.com/onsi/ginkgo/v2-2.11.0
build(deps): bump github.com/onsi/ginkgo/v2 from 2.9.2 to 2.11.0
2023-07-03 17:05:02 +02:00
d03b84d8f2 Merge pull request #874 from travelping/vrf-add-routes
Add routes propagation for VRF plugin
2023-06-27 12:20:45 +02:00
1512d727cb Merge pull request #914 from tariq1890/tx-qlen
[tuning] add ability to set tx queue len
2023-06-26 17:47:01 +02:00
470eee1385 [tuning]add ability to set tx queue len
Signed-off-by: Tariq Ibrahim <tibrahim@nvidia.com>
2023-06-25 23:28:48 -07:00
2216cff9e8 build(deps): bump github.com/onsi/ginkgo/v2 from 2.9.2 to 2.11.0
Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.9.2 to 2.11.0.
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/ginkgo/compare/v2.9.2...v2.11.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-19 02:58:59 +00:00
83029befef build(deps): bump golang.org/x/sys from 0.7.0 to 0.9.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.7.0 to 0.9.0.
- [Commits](https://github.com/golang/sys/compare/v0.7.0...v0.9.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-06-19 02:58:45 +00:00
48aa2f4eef Fix race conditions in DHCP test
The test named "correctly handles multiple DELs for the same container" in the ipam/dhcp package experiences race conditions when multiple goroutines concurrently access and modify the Args struct (of type CmdArgs).
To address these issues, a copy of the CmdArgs struct is now created in each function to eliminate data races.

Also, the test-linux.sh and test-windows.sh scripts have been updated to include the '-race' flag, enabling race detection during testing. This change helps prevent future race conditions by activating the Go race detector.

Signed-off-by: Alina Sudakov <asudakov@redhat.com>
2023-06-14 17:57:46 +03:00
ca12d49b41 Add routes propagation for VRF plugin
Up until now, if previous plugin assigned routes to interface, movement of
this interface to new VRF cause routes to be deleted.

This patch adds funtionality to VRF plugin to save the routes before
interface is assgined to VRF, and then re-apply all saved routes to new VRF.

Signed-off-by: Artur Korzeniewski <artur.korzeniewski@travelping.com>
2023-06-02 14:21:28 +02:00
2b097c5a62 Merge pull request #900 from squeed/disable-stale
github: remove stale issue cleanup
2023-05-25 10:32:04 +02:00
0389a29052 github: remove stale issue cleanup
In retrospect, this was a bad idea. It's closing too many valid issues.

Signed-off-by: Casey Callendrello <c1@caseyc.net>
2023-05-25 10:31:15 +02:00
6265f4e4ca Merge pull request #832 from maiqueb/tap-plugin-set-as-bridge-port
tap: allow for a tap device to be created as a bridge port
2023-05-22 10:59:28 -05:00
edab9efdea tap: allow for a tap device to be created as a bridge port
This extends the tap plugin API enabling the user to instruct the CNI
plugin the created tap device must be set as a port of an *existing*
linux bridge on the pod network namespace.

This is helpful for KubeVirt, allowing network connectivity to be
extended from the pod's interface into the Virtual Machine running
inside the pod.

Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
2023-05-19 16:26:14 +02:00
1b2dc7c2a4 build(deps): bump alpine in /.github/actions/retest-action
Bumps alpine from 3.17 to 3.18.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-15 03:01:50 +00:00
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
1334 changed files with 114206 additions and 58218 deletions

View File

@ -1,4 +1,4 @@
FROM alpine:3.17
FROM alpine:3.20
RUN apk add --no-cache curl jq

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,21 @@
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"
groups:
golang:
patterns:
- "*"
exclude-patterns:
- "github.com/containernetworking/*"

View File

@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Re-Test Action
uses: ./.github/actions/retest-action

114
.github/workflows/release.yaml vendored Normal file
View File

@ -0,0 +1,114 @@
---
name: Release binaries
on:
push:
tags:
- 'v*'
jobs:
linux_release:
name: Release linux binaries
runs-on: ubuntu-latest
strategy:
matrix:
goarch: [amd64, arm, arm64, mips64le, ppc64le, riscv64, s390x]
steps:
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: 1.22
- name: Checkout code
uses: actions/checkout@v4
- name: Build
env:
GOARCH: ${{ matrix.goarch }}
CGO_ENABLED: 0
run: ./build_linux.sh -ldflags '-extldflags -static -X github.com/containernetworking/plugins/pkg/utils/buildversion.BuildVersion=${{ github.ref_name }}'
- name: COPY files
run: cp README.md LICENSE bin/
- name: Change plugin file ownership
working-directory: ./bin
run: sudo chown root:root ./*
- name: Create dist directory
run: mkdir dist
- name: Create archive file
working-directory: ./bin
run: tar cfzpv ../dist/cni-plugins-linux-${{ matrix.goarch }}-${{ github.ref_name }}.tgz .
- name: Create sha256 checksum
working-directory: ./dist
run: sha256sum cni-plugins-linux-${{ matrix.goarch }}-${{ github.ref_name }}.tgz | tee cni-plugins-linux-${{ matrix.goarch }}-${{ github.ref_name }}.tgz.sha256
- name: Create sha512 checksum
working-directory: ./dist
run: sha512sum cni-plugins-linux-${{ matrix.goarch }}-${{ github.ref_name }}.tgz | tee cni-plugins-linux-${{ matrix.goarch }}-${{ github.ref_name }}.tgz.sha512
- name: Upload binaries to release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ./dist/*
tag: ${{ github.ref }}
overwrite: true
file_glob: true
windows_releases:
name: Release windows binaries
runs-on: ubuntu-latest
strategy:
matrix:
goarch: [amd64]
steps:
- name: Install dos2unix
run: sudo apt-get install dos2unix
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: 1.21
- name: Checkout code
uses: actions/checkout@v4
- name: Build
env:
GOARCH: ${{ matrix.goarch }}
CGO_ENABLED: 0
run: ./build_windows.sh -ldflags '-extldflags -static -X github.com/containernetworking/plugins/pkg/utils/buildversion.BuildVersion=${{ github.ref_name }}'
- name: COPY files
run: cp README.md LICENSE bin/
- name: Change plugin file ownership
working-directory: ./bin
run: sudo chown root:root ./*
- name: Create dist directory
run: mkdir dist
- name: Create archive file
working-directory: ./bin
run: tar cpfzv ../dist/cni-plugins-windows-${{ matrix.goarch }}-${{ github.ref_name }}.tgz .
- name: Create sha256 checksum
working-directory: ./dist
run: sha256sum cni-plugins-windows-${{ matrix.goarch }}-${{ github.ref_name }}.tgz | tee cni-plugins-windows-${{ matrix.goarch }}-${{ github.ref_name }}.tgz.sha256
- name: Create sha512 checksum
working-directory: ./dist
run: sha512sum cni-plugins-windows-${{ matrix.goarch }}-${{ github.ref_name }}.tgz | tee cni-plugins-windows-${{ matrix.goarch }}-${{ github.ref_name }}.tgz.sha512
- name: Upload binaries to release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ./dist/*
tag: ${{ github.ref }}
overwrite: true
file_glob: true

View File

@ -1,13 +0,0 @@
name: 'Close stale issues and PRs'
on:
schedule:
- cron: '30 1 * * *'
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v7
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'

View File

@ -4,20 +4,37 @@ name: test
on: ["push", "pull_request"]
env:
GO_VERSION: "1.18"
GO_VERSION: "1.22"
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:
- uses: actions/checkout@v4
- name: setup go
uses: actions/setup-go@v3
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- uses: actions/checkout@v3
go-version-file: go.mod
- uses: ibiqlik/action-yamllint@v3
with:
format: auto
- uses: golangci/golangci-lint-action@v6
with:
version: v1.55.2
args: -v
skip-cache: true
build:
name: Build all linux architectures
needs: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: setup go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Build on all supported architectures
run: |
set -e
@ -26,9 +43,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
@ -37,24 +54,21 @@ jobs:
sudo apt-get install linux-modules-extra-$(uname -r)
- name: Install nftables
run: sudo apt-get install nftables
- uses: actions/checkout@v4
- name: setup go
uses: actions/setup-go@v3
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
go-version-file: go.mod
- name: Set up Go for root
run: |
sudo ln -sf `which go` `sudo which go` || true
sudo go version
- uses: actions/checkout@v3
- name: Install test binaries
env:
GO111MODULE: off
run: |
go get github.com/containernetworking/cni/cnitool
go get github.com/mattn/goveralls
go get github.com/modocache/gover
go install github.com/containernetworking/cni/cnitool@latest
go install github.com/mattn/goveralls@latest
go install github.com/modocache/gover@latest
- name: test
run: PATH=$PATH:$(go env GOPATH)/bin COVERALLS=1 ./test_linux.sh
@ -66,15 +80,15 @@ 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:
- uses: actions/checkout@v4
- name: setup go
uses: actions/setup-go@v3
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- uses: actions/checkout@v3
go-version-file: go.mod
- name: test
run: bash ./test_windows.sh

45
.golangci.yml Normal file
View File

@ -0,0 +1,45 @@
issues:
exclude-rules:
- linters:
- revive
text: "don't use ALL_CAPS in Go names; use CamelCase"
- linters:
- revive
text: " and that stutters;"
- path: '(.+)_test\.go'
text: "dot-imports: should not use dot imports"
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
timeout: 5m

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

View File

@ -1,8 +1,8 @@
#!/usr/bin/env bash
#!/usr/bin/env sh
set -e
cd "$(dirname "$0")"
if [ "$(uname)" == "Darwin" ]; then
if [ "$(uname)" = "Darwin" ]; then
export GOOS="${GOOS:-linux}"
fi

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/usr/bin/env sh
set -e
cd "$(dirname "$0")"

53
go.mod
View File

@ -1,43 +1,48 @@
module github.com/containernetworking/plugins
go 1.17
go 1.20
require (
github.com/Microsoft/hcsshim v0.9.6
github.com/alexflint/go-filemutex v1.2.0
github.com/Microsoft/hcsshim v0.12.3
github.com/alexflint/go-filemutex v1.3.0
github.com/buger/jsonparser v1.1.1
github.com/containernetworking/cni v1.1.2
github.com/coreos/go-iptables v0.6.0
github.com/coreos/go-iptables v0.7.0
github.com/coreos/go-systemd/v22 v22.5.0
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c
github.com/d2g/dhcp4client v1.0.0
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.26.0
github.com/opencontainers/selinux v1.8.2
github.com/safchain/ethtool v0.2.0
github.com/networkplumbing/go-nft v0.4.0
github.com/onsi/ginkgo/v2 v2.19.0
github.com/onsi/gomega v1.33.1
github.com/opencontainers/selinux v1.11.0
github.com/safchain/ethtool v0.4.0
github.com/vishvananda/netlink v1.2.1-beta.2
golang.org/x/sys v0.5.0
golang.org/x/sys v0.21.0
)
require (
github.com/Microsoft/go-winio v0.4.17 // indirect
github.com/bits-and-blooms/bitset v1.2.0 // indirect
github.com/containerd/cgroups v1.0.1 // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/containerd/cgroups/v3 v3.0.2 // indirect
github.com/containerd/errdefs v0.1.0 // indirect
github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // 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.7.0 // indirect
golang.org/x/text v0.7.0 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/vishvananda/netns v0.0.4 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/text v0.15.0 // indirect
golang.org/x/tools v0.21.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect
google.golang.org/grpc v1.62.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

1022
go.sum

File diff suppressed because it is too large Load Diff

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,21 @@
package integration_test
import (
"bytes"
"fmt"
"io"
"log"
"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"
@ -61,6 +61,13 @@ var _ = Describe("Basic PTP using cnitool", func() {
netConfPath, err := filepath.Abs("./testdata")
Expect(err).NotTo(HaveOccurred())
// Flush ipam stores to avoid conflicts
err = os.RemoveAll("/tmp/chained-ptp-bandwidth-test")
Expect(err).NotTo(HaveOccurred())
err = os.RemoveAll("/tmp/basic-ptp-test")
Expect(err).NotTo(HaveOccurred())
env = TestEnv([]string{
"CNI_PATH=" + cniPath,
"NETCONFPATH=" + netConfPath,
@ -83,6 +90,7 @@ var _ = Describe("Basic PTP using cnitool", func() {
env.runInNS(hostNS, cnitoolBin, "add", netName, contNS.LongName())
addrOutput := env.runInNS(contNS, "ip", "addr")
Expect(addrOutput).To(ContainSubstring(expectedIPPrefix))
env.runInNS(hostNS, cnitoolBin, "del", netName, contNS.LongName())
@ -146,10 +154,14 @@ var _ = Describe("Basic PTP using cnitool", func() {
chainedBridgeBandwidthEnv.runInNS(hostNS, cnitoolBin, "del", "network-chain-test", contNS1.LongName())
basicBridgeEnv.runInNS(hostNS, cnitoolBin, "del", "network-chain-test", contNS2.LongName())
contNS1.Del()
contNS2.Del()
hostNS.Del()
})
Measure("limits traffic only on the restricted bandwith veth device", func(b Benchmarker) {
ipRegexp := regexp.MustCompile("10\\.1[12]\\.2\\.\\d{1,3}")
It("limits traffic only on the restricted bandwidth veth device", func() {
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,31 +174,30 @@ 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.
packetInBytes := 3000
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)
})
start := time.Now()
makeTCPClientInNS(hostNS.ShortName(), chainedBridgeIP, chainedBridgeBandwidthPort, packetInBytes)
runtimeWithLimit := time.Since(start)
log.Printf("Runtime with qos limit %.2f seconds", runtimeWithLimit.Seconds())
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)
})
start = time.Now()
makeTCPClientInNS(hostNS.ShortName(), basicBridgeIP, basicBridgePort, packetInBytes)
runtimeWithoutLimit := time.Since(start)
log.Printf("Runtime without qos limit %.2f seconds", runtimeWithLimit.Seconds())
Expect(runtimeWithLimit).To(BeNumerically(">", runtimeWithoutLimit+1000*time.Millisecond))
}, 1)
})
})
})
@ -224,7 +235,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 +254,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 +271,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

@ -6,6 +6,7 @@
"mtu": 512,
"ipam": {
"type": "host-local",
"subnet": "10.1.2.0/24"
"subnet": "10.1.2.0/24",
"dataDir": "/tmp/basic-ptp-test"
}
}

View File

@ -8,7 +8,8 @@
"mtu": 512,
"ipam": {
"type": "host-local",
"subnet": "10.9.2.0/24"
"subnet": "10.9.2.0/24",
"dataDir": "/tmp/chained-ptp-bandwidth-test"
}
},
{

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 (%q) peer provided (%q) already exists", name, peerName)
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 {
@ -156,9 +149,9 @@ var _ = Describe("Link", func() {
It("returns useful error", func() {
_ = containerNetNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
_, _, err := ip.SetupVeth(containerVethName, mtu, "", hostNetNS)
Expect(err.Error()).To(Equal(fmt.Sprintf("container veth name provided (%s) already exists", containerVethName)))
testHostVethName := "test" + hostVethName
_, _, err := ip.SetupVethWithName(containerVethName, testHostVethName, mtu, "", hostNetNS)
Expect(err.Error()).To(Equal(fmt.Sprintf("container veth name (%q) peer provided (%q) already exists", containerVethName, testHostVethName)))
return nil
})
@ -181,15 +174,14 @@ 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() {
_ = containerNetNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
_, _, err := ip.SetupVeth(containerVethName, mtu, "", hostNetNS)
Expect(err.Error()).To(HavePrefix("container veth name provided"))
Expect(err.Error()).To(HaveSuffix("already exists"))
_, _, err := ip.SetupVethWithName(containerVethName, hostVethName, mtu, "", hostNetNS)
Expect(err.Error()).To(Equal(fmt.Sprintf("container veth name (%q) peer provided (%q) already exists", containerVethName, hostVethName)))
return nil
})
})
@ -197,7 +189,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 +203,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 +282,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"
@ -28,8 +30,8 @@ const (
)
type NftConfigurer interface {
Apply(*nft.Config) error
Read() (*nft.Config, error)
Apply(*nft.Config) (*nft.Config, error)
Read(filterCommands ...string) (*nft.Config, error)
}
type SpoofChecker struct {
@ -37,16 +39,23 @@ type SpoofChecker struct {
macAddress string
refID string
configurer NftConfigurer
rulestore *nft.Config
}
type defaultNftConfigurer struct{}
func (_ defaultNftConfigurer) Apply(cfg *nft.Config) error {
return nft.ApplyConfig(cfg)
func (dnc defaultNftConfigurer) Apply(cfg *nft.Config) (*nft.Config, error) {
const timeout = 55 * time.Second
ctxWithTimeout, cancelFunc := context.WithTimeout(context.Background(), timeout)
defer cancelFunc()
return nft.ApplyConfigEcho(ctxWithTimeout, 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 {
@ -54,7 +63,7 @@ func NewSpoofChecker(iface, macAddress, refID string) *SpoofChecker {
}
func NewSpoofCheckerWithConfigurer(iface, macAddress, refID string, configurer NftConfigurer) *SpoofChecker {
return &SpoofChecker{iface, macAddress, refID, configurer}
return &SpoofChecker{iface, macAddress, refID, configurer, nil}
}
// Setup applies nftables configuration to restrict traffic
@ -83,7 +92,7 @@ func (sc *SpoofChecker) Setup() error {
macChain := sc.macChain(ifaceChain.Name)
baseConfig.AddChain(macChain)
if err := sc.configurer.Apply(baseConfig); err != nil {
if _, err := sc.configurer.Apply(baseConfig); err != nil {
return fmt.Errorf("failed to setup spoof-check: %v", err)
}
@ -97,37 +106,51 @@ func (sc *SpoofChecker) Setup() error {
rulesConfig.AddRule(sc.matchMacRule(macChain.Name))
rulesConfig.AddRule(sc.dropRule(macChain.Name))
if err := sc.configurer.Apply(rulesConfig); err != nil {
rulestore, err := sc.configurer.Apply(rulesConfig)
if err != nil {
return fmt.Errorf("failed to setup spoof-check: %v", err)
}
sc.rulestore = rulestore
return nil
}
func (sc *SpoofChecker) findPreroutingRule(ruleToFind *schema.Rule) ([]*schema.Rule, error) {
ruleset := sc.rulestore
if ruleset == nil {
chain, err := sc.configurer.Read(listChainBridgeNatPrerouting()...)
if err != nil {
return nil, err
}
ruleset = chain
}
return ruleset.LookupRule(ruleToFind), nil
}
// Teardown removes the interface and mac-address specific chains and their rules.
// The table and base-chain are expected to survive while the base-chain rule that matches the
// interface is removed.
func (sc *SpoofChecker) Teardown() error {
ifaceChain := sc.ifaceChain()
currentConfig, ifaceMatchRuleErr := sc.configurer.Read()
if ifaceMatchRuleErr == nil {
expectedRuleToFind := sc.matchIfaceJumpToChainRule(preRoutingBaseChainName, ifaceChain.Name)
// It is safer to exclude the statement matching, avoiding cases where a current statement includes
// additional default entries (e.g. counters).
ruleToFindExcludingStatements := *expectedRuleToFind
ruleToFindExcludingStatements.Expr = nil
rules := currentConfig.LookupRule(&ruleToFindExcludingStatements)
if len(rules) > 0 {
c := nft.NewConfig()
for _, rule := range rules {
c.DeleteRule(rule)
}
if err := sc.configurer.Apply(c); err != nil {
ifaceMatchRuleErr = fmt.Errorf("failed to delete iface match rule: %v", err)
}
} else {
fmt.Fprintf(os.Stderr, "spoofcheck/teardown: unable to detect iface match rule for deletion: %+v", expectedRuleToFind)
expectedRuleToFind := sc.matchIfaceJumpToChainRule(preRoutingBaseChainName, ifaceChain.Name)
// It is safer to exclude the statement matching, avoiding cases where a current statement includes
// additional default entries (e.g. counters).
ruleToFindExcludingStatements := *expectedRuleToFind
ruleToFindExcludingStatements.Expr = nil
rules, ifaceMatchRuleErr := sc.findPreroutingRule(&ruleToFindExcludingStatements)
if ifaceMatchRuleErr == nil && len(rules) > 0 {
c := nft.NewConfig()
for _, rule := range rules {
c.DeleteRule(rule)
}
if _, err := sc.configurer.Apply(c); err != nil {
ifaceMatchRuleErr = fmt.Errorf("failed to delete iface match rule: %v", err)
}
// Drop the cache, it should contain deleted rule(s) now
sc.rulestore = nil
} else {
fmt.Fprintf(os.Stderr, "spoofcheck/teardown: unable to detect iface match rule for deletion: %+v", expectedRuleToFind)
}
regularChainsConfig := nft.NewConfig()
@ -135,7 +158,7 @@ func (sc *SpoofChecker) Teardown() error {
regularChainsConfig.DeleteChain(sc.macChain(ifaceChain.Name))
var regularChainsErr error
if err := sc.configurer.Apply(regularChainsConfig); err != nil {
if _, err := sc.configurer.Apply(regularChainsConfig); err != nil {
regularChainsErr = fmt.Errorf("failed to delete regular chains: %v", err)
}
@ -195,12 +218,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 +229,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 +251,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 +264,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"
@ -113,13 +113,32 @@ var _ = Describe("spoofcheck", func() {
)))
})
})
Context("echo", func() {
It("succeeds, no read called", func() {
c := configurerStub{}
sc := link.NewSpoofCheckerWithConfigurer(iface, mac, id, &c)
Expect(sc.Setup()).To(Succeed())
Expect(sc.Teardown()).To(Succeed())
Expect(c.readCalled).To(BeFalse())
})
It("succeeds, fall back to config read", func() {
c := configurerStub{applyReturnNil: true}
sc := link.NewSpoofCheckerWithConfigurer(iface, mac, id, &c)
Expect(sc.Setup()).To(Succeed())
c.readConfig = c.applyConfig[0]
Expect(sc.Teardown()).To(Succeed())
Expect(c.readCalled).To(BeTrue())
})
})
})
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 +152,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 +176,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 +273,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))
@ -275,21 +293,28 @@ type configurerStub struct {
failFirstApplyConfig bool
failSecondApplyConfig bool
failReadConfig bool
applyReturnNil bool
readCalled bool
}
func (a *configurerStub) Apply(c *nft.Config) error {
func (a *configurerStub) Apply(c *nft.Config) (*nft.Config, error) {
a.applyCounter++
if a.failFirstApplyConfig && a.applyCounter == 1 {
return fmt.Errorf(errorFirstApplyText)
return nil, fmt.Errorf(errorFirstApplyText)
}
if a.failSecondApplyConfig && a.applyCounter == 2 {
return fmt.Errorf(errorSecondApplyText)
return nil, fmt.Errorf(errorSecondApplyText)
}
a.applyConfig = append(a.applyConfig, c)
return nil
if a.applyReturnNil {
return nil, nil
}
return c, nil
}
func (a *configurerStub) Read() (*nft.Config, error) {
func (a *configurerStub) Read(_ ...string) (*nft.Config, error) {
a.readCalled = true
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) {
@ -181,7 +182,7 @@ var _ = Describe("Linux namespace operations", func() {
testNsInode, err := getInodeNS(targetNetNS)
Expect(err).NotTo(HaveOccurred())
Expect(testNsInode).NotTo(Equal(0))
Expect(testNsInode).NotTo(Equal(uint64(0)))
Expect(testNsInode).NotTo(Equal(origNSInode))
})

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

@ -29,6 +29,7 @@ func envCleanup() {
os.Unsetenv("CNI_NETNS")
os.Unsetenv("CNI_IFNAME")
os.Unsetenv("CNI_CONTAINERID")
os.Unsetenv("CNI_NETNS_OVERRIDE")
}
func CmdAdd(cniNetns, cniContainerID, cniIfname string, conf []byte, f func() error) (types.Result, []byte, error) {
@ -37,6 +38,7 @@ func CmdAdd(cniNetns, cniContainerID, cniIfname string, conf []byte, f func() er
os.Setenv("CNI_NETNS", cniNetns)
os.Setenv("CNI_IFNAME", cniIfname)
os.Setenv("CNI_CONTAINERID", cniContainerID)
os.Setenv("CNI_NETNS_OVERRIDE", "1")
defer envCleanup()
// Redirect stdout to capture plugin result
@ -81,19 +83,20 @@ 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)
os.Setenv("CNI_IFNAME", cniIfname)
os.Setenv("CNI_CONTAINERID", cniContainerID)
os.Setenv("CNI_NETNS_OVERRIDE", "1")
defer envCleanup()
return f()
}
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 {
@ -102,6 +105,7 @@ func CmdDel(cniNetns, cniContainerID, cniIfname string, f func() error) error {
os.Setenv("CNI_NETNS", cniNetns)
os.Setenv("CNI_IFNAME", cniIfname)
os.Setenv("CNI_CONTAINERID", cniContainerID)
os.Setenv("CNI_NETNS_OVERRIDE", "1")
defer envCleanup()
return f()

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

@ -29,9 +29,9 @@ func EnsureChain(ipt *iptables.IPTables, table, chain string) error {
if ipt == nil {
return errors.New("failed to ensure iptable chain: IPTables was nil")
}
exists, err := ChainExists(ipt, table, chain)
exists, err := ipt.ChainExists(table, chain)
if err != nil {
return fmt.Errorf("failed to list iptables chains: %v", err)
return fmt.Errorf("failed to check iptables chain existence: %v", err)
}
if !exists {
err = ipt.NewChain(table, chain)
@ -45,24 +45,6 @@ func EnsureChain(ipt *iptables.IPTables, table, chain string) error {
return nil
}
// ChainExists checks whether an iptables chain exists.
func ChainExists(ipt *iptables.IPTables, table, chain string) (bool, error) {
if ipt == nil {
return false, errors.New("failed to check iptable chain: IPTables was nil")
}
chains, err := ipt.ListChains(table)
if err != nil {
return false, err
}
for _, ch := range chains {
if ch == chain {
return true, nil
}
}
return false, nil
}
// DeleteRule idempotently delete the iptables rule in the specified table/chain.
// It does not return an error if the referring chain doesn't exist
func DeleteRule(ipt *iptables.IPTables, table, chain string, rulespec ...string) error {
@ -133,7 +115,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
})
@ -334,9 +332,17 @@ var _ = Describe("DHCP Operations", func() {
started.Done()
started.Wait()
err = originalNS.Do(func(ns.NetNS) error {
err := originalNS.Do(func(ns.NetNS) error {
return testutils.CmdDelWithArgs(args, func() error {
return cmdDel(args)
copiedArgs := &skel.CmdArgs{
ContainerID: args.ContainerID,
Netns: args.Netns,
IfName: args.IfName,
StdinData: args.StdinData,
Path: args.Path,
Args: args.Args,
}
return cmdDel(copiedArgs)
})
})
Expect(err).NotTo(HaveOccurred())
@ -363,7 +369,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 +390,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 +484,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 +494,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 +517,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 +596,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, 0o600)
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()), 0o600)
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

@ -28,6 +28,7 @@ func parseResolvConf(filename string) (*types.DNS, error) {
if err != nil {
return nil, err
}
defer fp.Close()
dns := types.DNS{}
scanner := bufio.NewScanner(fp)

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,20 @@ 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"`
DisableContainerInterface bool `json:"disableContainerInterface,omitempty"`
Args struct {
Cni BridgeArgs `json:"cni,omitempty"`
@ -65,7 +69,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 +105,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 +114,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 +148,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 +378,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 +392,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 +411,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 +448,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 +463,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 +522,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 {
@ -416,12 +531,16 @@ func cmdAdd(args *skel.CmdArgs) error {
isLayer3 := n.IPAM.Type != ""
if isLayer3 && n.DisableContainerInterface {
return fmt.Errorf("cannot use IPAM when DisableContainerInterface flag is set")
}
if n.IsDefaultGW {
n.IsGW = true
}
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 +554,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,32 +628,27 @@ 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
}
if n.IsGW {
var firstV4Addr net.IP
var vlanInterface *current.Interface
// Set the IP address(es) on the bridge and enable forwarding
for _, gws := range []*gwInfo{gwsV4, gwsV6} {
for _, gw := range gws.gws {
if gw.IP.To4() != nil && firstV4Addr == nil {
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)
}
@ -567,12 +681,13 @@ func cmdAdd(args *skel.CmdArgs) error {
}
}
}
} else {
} else if !n.DisableContainerInterface {
if err := netns.Do(func(_ ns.NetNS) error {
link, err := netlink.LinkByName(args.IfName)
if err != nil {
return fmt.Errorf("failed to retrieve link: %v", err)
}
// If layer 2 we still need to set the container veth to up
if err = netlink.LinkSetUp(link); err != nil {
return fmt.Errorf("failed to set %q up: %v", args.IfName, err)
@ -583,23 +698,28 @@ func cmdAdd(args *skel.CmdArgs) error {
}
}
var hostVeth netlink.Link
hostVeth, err := netlink.LinkByName(hostInterface.Name)
if err != nil {
return err
}
// check bridge port state
retries := []int{0, 50, 500, 1000, 1000}
for idx, sleep := range retries {
time.Sleep(time.Duration(sleep) * time.Millisecond)
if !n.DisableContainerInterface {
// check bridge port state
retries := []int{0, 50, 500, 1000, 1000}
for idx, sleep := range retries {
time.Sleep(time.Duration(sleep) * time.Millisecond)
hostVeth, err = netlink.LinkByName(hostInterface.Name)
if err != nil {
return err
}
if hostVeth.Attrs().OperState == netlink.OperUp {
break
}
hostVeth, err = netlink.LinkByName(hostInterface.Name)
if err != nil {
return err
}
if hostVeth.Attrs().OperState == netlink.OperUp {
break
}
if idx == len(retries)-1 {
return fmt.Errorf("bridge port in error state: %s", hostVeth.Attrs().OperState)
if idx == len(retries)-1 {
return fmt.Errorf("bridge port in error state: %s", hostVeth.Attrs().OperState)
}
}
}
@ -620,7 +740,7 @@ func cmdAdd(args *skel.CmdArgs) error {
}
// Use incoming DNS settings if provided, otherwise use the
// settings that were already configued by the IPAM plugin
// settings that were already configured by the IPAM plugin
if dnsConfSet(n.DNS) {
result.DNS = n.DNS
}
@ -670,7 +790,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.
@ -720,7 +839,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 +863,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 +894,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 +937,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 +965,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 +1071,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 +1082,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,25 @@ 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
disableContIface bool
AddErr020 string
DelErr020 string
AddErr010 string
DelErr010 string
envArgs string // CNI_ARGS
runtimeConfig struct {
@ -130,9 +133,32 @@ const (
vlan = `,
"vlan": %d`
vlanTrunkStartStr = `,
"vlanTrunk": [`
vlanTrunk = `
{
"id": %d
}`
vlanTrunkRange = `
{
"minID": %d,
"maxID": %d
}`
vlanTrunkEndStr = `
]`
preserveDefaultVlan = `,
"preserveDefaultVlan": false`
netDefault = `,
"isDefaultGateway": true`
disableContainerInterface = `,
"disableContainerInterface": true`
ipamStartStr = `,
"ipam": {
"type": "host-local"`
@ -192,7 +218,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()
}
@ -206,6 +253,10 @@ func (tc testCase) netConfJSON(dataDir string) string {
conf += fmt.Sprintf(macspoofchkFormat, tc.macspoofchk)
}
if tc.disableContIface {
conf += disableContainerInterface
}
if !tc.isLayer2 {
conf += netDefault
if tc.subnet != "" || tc.ranges != nil {
@ -285,7 +336,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 +348,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 +462,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 +485,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 +537,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 +579,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 +599,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 +613,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 +637,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
@ -609,14 +686,16 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result,
Expect(err).NotTo(HaveOccurred())
Expect(link.Attrs().Name).To(Equal(IFNAME))
Expect(link).To(BeAssignableToTypeOf(&netlink.Veth{}))
assertContainerInterfaceLinkState(&tc, link)
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(err).NotTo(HaveOccurred())
assertIPv6Addresses(&tc, addrs, expCIDRsV6)
// Ignore link local address which may or may not be
// ready when we read addresses.
var foundAddrs int
@ -650,7 +729,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 +739,18 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result,
return result, nil
}
func (tester *testerV10x) cmdCheckTest(tc testCase, conf *Net, dataDir string) {
func assertContainerInterfaceLinkState(tc *testCase, link netlink.Link) {
linkState := int(link.Attrs().OperState)
if tc.disableContIface {
Expect(linkState).ToNot(Equal(netlink.OperUp))
} else {
Expect(linkState).To(Equal(netlink.OperUp))
}
}
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 +777,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 +814,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 +878,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 +920,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 +940,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 +954,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 +978,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,10 +1026,11 @@ 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(err).NotTo(HaveOccurred())
assertIPv6Addresses(&tc, addrs, expCIDRsV6)
// Ignore link local address which may or may not be
// ready when we read addresses.
var foundAddrs int
@ -950,7 +1064,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 +1074,17 @@ func (tester *testerV04x) cmdAddTest(tc testCase, dataDir string) (types.Result,
return result, nil
}
func (tester *testerV04x) cmdCheckTest(tc testCase, conf *Net, dataDir string) {
func assertIPv6Addresses(tc *testCase, addrs []netlink.Addr, expCIDRsV6 []*net.IPNet) {
if tc.disableContIface {
Expect(addrs).To(BeEmpty())
} else {
Expect(addrs).To(HaveLen(len(expCIDRsV6) + 1)) // add one for the link-local
}
}
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 +1111,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 +1148,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 +1212,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 +1254,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 +1274,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 +1288,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 +1312,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 +1360,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 +1396,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 +1405,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 +1505,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 +1525,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 +1539,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 +1548,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 +1581,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 +1617,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 +1630,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 +1641,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 +1729,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 +1770,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 +1793,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 +1980,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 +2061,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 +2173,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 +2183,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 +2231,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 +2252,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())
@ -2257,6 +2490,36 @@ var _ = Describe("bridge Operations", func() {
return nil
})).To(Succeed())
})
It(fmt.Sprintf("[%s] should fail when both IPAM and DisableContainerInterface are set", ver), func() {
Expect(originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
tc := testCase{
cniVersion: ver,
subnet: "10.1.2.0/24",
disableContIface: true,
}
args := tc.createCmdArgs(targetNS, dataDir)
Expect(cmdAdd(args)).To(HaveOccurred())
return nil
})).To(Succeed())
})
It(fmt.Sprintf("[%s] should set the container veth peer state down", ver), func() {
Expect(originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
tc := testCase{
cniVersion: ver,
disableContIface: true,
isLayer2: true,
AddErr020: "cannot convert: no valid IP addresses",
AddErr010: "cannot convert: no valid IP addresses",
}
cmdAddDelTest(originalNS, targetNS, tc, dataDir)
return nil
})).To(Succeed())
})
}
It("check vlan id when loading net conf", func() {
@ -2286,7 +2549,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,12 +134,8 @@ 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 {
return err
}
@ -170,7 +164,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.
@ -245,7 +238,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 +254,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())
@ -377,7 +371,7 @@ var _ = Describe("dummy Operations", func() {
StdinData: []byte(fmt.Sprintf(confFmt, ver)),
}
_ = originalNS.Do(func(netNS ns.NetNS) error {
_ = originalNS.Do(func(_ ns.NetNS) error {
defer GinkgoRecover()
_, _, err = testutils.CmdAddWithArgs(args, func() error {

View File

@ -31,7 +31,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"
@ -39,7 +38,8 @@ import (
)
var (
sysBusPCI = "/sys/bus/pci/devices"
sysBusPCI = "/sys/bus/pci/devices"
sysBusAuxiliary = "/sys/bus/auxiliary/devices"
)
// Array of different linux drivers bound to network device needed for DPDK
@ -56,6 +56,9 @@ type NetConf struct {
RuntimeConfig struct {
DeviceID string `json:"deviceID,omitempty"`
} `json:"runtimeConfig,omitempty"`
// for internal use
auxDevice string `json:"-"` // Auxiliary device name as appears on Auxiliary bus (/sys/bus/auxiliary)
}
func init() {
@ -65,6 +68,31 @@ func init() {
runtime.LockOSThread()
}
// handleDeviceID updates netconf fields with DeviceID runtime config
func handleDeviceID(netconf *NetConf) error {
deviceID := netconf.RuntimeConfig.DeviceID
if deviceID == "" {
return nil
}
// Check if deviceID is a PCI device
pciPath := filepath.Join(sysBusPCI, deviceID)
if _, err := os.Stat(pciPath); err == nil {
netconf.PCIAddr = deviceID
return nil
}
// Check if deviceID is an Auxiliary device
auxPath := filepath.Join(sysBusAuxiliary, deviceID)
if _, err := os.Stat(auxPath); err == nil {
netconf.PCIAddr = ""
netconf.auxDevice = deviceID
return nil
}
return fmt.Errorf("runtime config DeviceID %s not found or unsupported", deviceID)
}
func loadConf(bytes []byte) (*NetConf, error) {
n := &NetConf{}
var err error
@ -72,12 +100,12 @@ func loadConf(bytes []byte) (*NetConf, error) {
return nil, fmt.Errorf("failed to load netconf: %v", err)
}
if n.RuntimeConfig.DeviceID != "" {
// Override PCI device with the standardized DeviceID provided in Runtime Config.
n.PCIAddr = n.RuntimeConfig.DeviceID
// Override device with the standardized DeviceID if provided in Runtime Config.
if err := handleDeviceID(n); err != nil {
return nil, err
}
if n.Device == "" && n.HWAddr == "" && n.KernelPath == "" && n.PCIAddr == "" {
if n.Device == "" && n.HWAddr == "" && n.KernelPath == "" && n.PCIAddr == "" && n.auxDevice == "" {
return nil, fmt.Errorf(`specify either "device", "hwaddr", "kernelpath" or "pciBusID"`)
}
@ -105,7 +133,7 @@ func cmdAdd(args *skel.CmdArgs) error {
result := &current.Result{}
var contDev netlink.Link
if !cfg.DPDKMode {
hostDev, err := getLink(cfg.Device, cfg.HWAddr, cfg.KernelPath, cfg.PCIAddr)
hostDev, err := getLink(cfg.Device, cfg.HWAddr, cfg.KernelPath, cfg.PCIAddr, cfg.auxDevice)
if err != nil {
return fmt.Errorf("failed to find host device: %v", err)
}
@ -161,10 +189,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
@ -205,34 +230,112 @@ func cmdDel(args *skel.CmdArgs) error {
return nil
}
// setTempName sets a temporary name for netdevice, returns updated Link object or error
// if occurred.
func setTempName(dev netlink.Link) (netlink.Link, error) {
tempName := fmt.Sprintf("%s%d", "temp_", dev.Attrs().Index)
// rename to tempName
if err := netlink.LinkSetName(dev, tempName); err != nil {
return nil, fmt.Errorf("failed to rename device %q to %q: %v", dev.Attrs().Name, tempName, err)
}
// Get updated Link obj
tempDev, err := netlink.LinkByName(tempName)
if err != nil {
return nil, fmt.Errorf("failed to find %q after rename to %q: %v", dev.Attrs().Name, tempName, err)
}
return tempDev, nil
}
func moveLinkIn(hostDev netlink.Link, containerNs ns.NetNS, ifName string) (netlink.Link, error) {
if err := netlink.LinkSetNsFd(hostDev, int(containerNs.Fd())); err != nil {
return nil, err
origLinkFlags := hostDev.Attrs().Flags
hostDevName := hostDev.Attrs().Name
defaultNs, err := ns.GetCurrentNS()
if err != nil {
return nil, fmt.Errorf("failed to get host namespace: %v", err)
}
// Devices can be renamed only when down
if err = netlink.LinkSetDown(hostDev); err != nil {
return nil, fmt.Errorf("failed to set %q down: %v", hostDev.Attrs().Name, err)
}
// restore original link state in case of error
defer func() {
if err != nil {
if origLinkFlags&net.FlagUp == net.FlagUp && hostDev != nil {
_ = netlink.LinkSetUp(hostDev)
}
}
}()
hostDev, err = setTempName(hostDev)
if err != nil {
return nil, fmt.Errorf("failed to rename device %q to temporary name: %v", hostDevName, err)
}
// restore original netdev name in case of error
defer func() {
if err != nil && hostDev != nil {
_ = netlink.LinkSetName(hostDev, hostDevName)
}
}()
if err = netlink.LinkSetNsFd(hostDev, int(containerNs.Fd())); err != nil {
return nil, fmt.Errorf("failed to move %q to container ns: %v", hostDev.Attrs().Name, err)
}
var contDev netlink.Link
if err := containerNs.Do(func(_ ns.NetNS) error {
tempDevName := hostDev.Attrs().Name
if err = containerNs.Do(func(_ ns.NetNS) error {
var err error
contDev, err = netlink.LinkByName(hostDev.Attrs().Name)
contDev, err = netlink.LinkByName(tempDevName)
if err != nil {
return fmt.Errorf("failed to find %q: %v", hostDev.Attrs().Name, err)
}
// Devices can be renamed only when down
if err = netlink.LinkSetDown(contDev); err != nil {
return fmt.Errorf("failed to set %q down: %v", hostDev.Attrs().Name, err)
return fmt.Errorf("failed to find %q: %v", tempDevName, err)
}
// move netdev back to host namespace in case of error
defer func() {
if err != nil {
_ = netlink.LinkSetNsFd(contDev, int(defaultNs.Fd()))
// we need to get updated link object as link was moved back to host namepsace
_ = defaultNs.Do(func(_ ns.NetNS) error {
hostDev, _ = netlink.LinkByName(tempDevName)
return nil
})
}
}()
// Save host device name into the container device's alias property
if err := netlink.LinkSetAlias(contDev, hostDev.Attrs().Name); err != nil {
return fmt.Errorf("failed to set alias to %q: %v", hostDev.Attrs().Name, err)
if err = netlink.LinkSetAlias(contDev, hostDevName); err != nil {
return fmt.Errorf("failed to set alias to %q: %v", tempDevName, err)
}
// Rename container device to respect args.IfName
if err := netlink.LinkSetName(contDev, ifName); err != nil {
return fmt.Errorf("failed to rename device %q to %q: %v", hostDev.Attrs().Name, ifName, err)
if err = netlink.LinkSetName(contDev, ifName); err != nil {
return fmt.Errorf("failed to rename device %q to %q: %v", tempDevName, ifName, err)
}
// restore tempDevName in case of error
defer func() {
if err != nil {
_ = netlink.LinkSetName(contDev, tempDevName)
}
}()
// Bring container device up
if err = netlink.LinkSetUp(contDev); err != nil {
return fmt.Errorf("failed to set %q up: %v", ifName, err)
}
// bring device down in case of error
defer func() {
if err != nil {
_ = netlink.LinkSetDown(contDev)
}
}()
// Retrieve link again to get up-to-date name and attributes
contDev, err = netlink.LinkByName(ifName)
if err != nil {
@ -253,11 +356,14 @@ func moveLinkOut(containerNs ns.NetNS, ifName string) error {
}
defer defaultNs.Close()
return containerNs.Do(func(_ ns.NetNS) error {
var tempName string
var origDev netlink.Link
err = containerNs.Do(func(_ ns.NetNS) error {
dev, err := netlink.LinkByName(ifName)
if err != nil {
return fmt.Errorf("failed to find %q: %v", ifName, err)
}
origDev = dev
// Devices can be renamed only when down
if err = netlink.LinkSetDown(dev); err != nil {
@ -275,16 +381,49 @@ func moveLinkOut(containerNs ns.NetNS, ifName string) error {
}
}()
// Rename the device to its original name from the host namespace
if err = netlink.LinkSetName(dev, dev.Attrs().Alias); err != nil {
return fmt.Errorf("failed to restore %q to original name %q: %v", ifName, dev.Attrs().Alias, err)
newLink, err := setTempName(dev)
if err != nil {
return fmt.Errorf("failed to rename device %q to temporary name: %v", ifName, err)
}
dev = newLink
tempName = dev.Attrs().Name
if err = netlink.LinkSetNsFd(dev, int(defaultNs.Fd())); err != nil {
return fmt.Errorf("failed to move %q to host netns: %v", dev.Attrs().Alias, err)
return fmt.Errorf("failed to move %q to host netns: %v", tempName, err)
}
return nil
})
if err != nil {
return err
}
// Rename the device to its original name from the host namespace
tempDev, err := netlink.LinkByName(tempName)
if err != nil {
return fmt.Errorf("failed to find %q in host namespace: %v", tempName, err)
}
if err = netlink.LinkSetName(tempDev, tempDev.Attrs().Alias); err != nil {
// move device back to container ns so it may be retired
defer func() {
_ = netlink.LinkSetNsFd(tempDev, int(containerNs.Fd()))
_ = containerNs.Do(func(_ ns.NetNS) error {
lnk, err := netlink.LinkByName(tempName)
if err != nil {
return err
}
_ = netlink.LinkSetName(lnk, ifName)
if origDev.Attrs().Flags&net.FlagUp == net.FlagUp {
_ = netlink.LinkSetUp(lnk)
}
return nil
})
}()
return fmt.Errorf("failed to restore %q to original name %q: %v", tempName, tempDev.Attrs().Alias, err)
}
return nil
}
func hasDpdkDriver(pciaddr string) (bool, error) {
@ -320,45 +459,46 @@ func printLink(dev netlink.Link, cniVersion string, containerNs ns.NetNS) error
return types.PrintResult(&result, cniVersion)
}
func getLink(devname, hwaddr, kernelpath, pciaddr string) (netlink.Link, error) {
links, err := netlink.LinkList()
func linkFromPath(path string) (netlink.Link, error) {
entries, err := os.ReadDir(path)
if err != nil {
return nil, fmt.Errorf("failed to list node links: %v", err)
return nil, fmt.Errorf("failed to read directory %s: %q", path, err)
}
if len(entries) > 0 {
// grab the first net device
return netlink.LinkByName(entries[0].Name())
}
return nil, fmt.Errorf("failed to find network device in path %s", path)
}
if len(devname) > 0 {
func getLink(devname, hwaddr, kernelpath, pciaddr string, auxDev string) (netlink.Link, error) {
switch {
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)
}
links, err := netlink.LinkList()
if err != nil {
return nil, fmt.Errorf("failed to list node links: %v", err)
}
for _, link := range links {
if bytes.Equal(link.Attrs().HardwareAddr, hwAddr) {
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)
}
netDir := filepath.Join(kernelpath, "net")
entries, err := os.ReadDir(netDir)
if err != nil {
return nil, fmt.Errorf("failed to find network devices at %q", netDir)
}
// Grab the first device from eg /sys/devices/pci0000:00/0000:00:19.0/net
for _, entry := range entries {
// Make sure it's really an interface
for _, l := range links {
if entry.Name() == l.Attrs().Name {
return l, nil
}
}
}
} else if len(pciaddr) > 0 {
return linkFromPath(netDir)
case len(pciaddr) > 0:
netDir := filepath.Join(sysBusPCI, pciaddr, "net")
if _, err := os.Lstat(netDir); err != nil {
virtioNetDir := filepath.Join(sysBusPCI, pciaddr, "virtio*", "net")
@ -368,14 +508,10 @@ func getLink(devname, hwaddr, kernelpath, pciaddr string) (netlink.Link, error)
}
netDir = matches[0]
}
entries, err := os.ReadDir(netDir)
if err != nil {
return nil, fmt.Errorf("failed to read net directory %s: %q", netDir, err)
}
if len(entries) > 0 {
return netlink.LinkByName(entries[0].Name())
}
return nil, fmt.Errorf("failed to find device name for pci address %s", pciaddr)
return linkFromPath(netDir)
case len(auxDev) > 0:
netDir := filepath.Join(sysBusAuxiliary, auxDev, "net")
return linkFromPath(netDir)
}
return nil, fmt.Errorf("failed to find physical interface")
@ -386,7 +522,6 @@ func main() {
}
func cmdCheck(args *skel.CmdArgs) error {
cfg, err := loadConf(args.StdinData)
if err != nil {
return err
@ -443,7 +578,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 +603,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) {
@ -898,6 +898,71 @@ var _ = Describe("base functionality", func() {
})
})
It(fmt.Sprintf("Works with a valid %s config on auxiliary device", ver), func() {
var origLink netlink.Link
ifname := "eth0"
fs := &fakeFilesystem{
dirs: []string{
fmt.Sprintf("sys/bus/auxiliary/devices/mlx5_core.sf.4/net/%s", ifname),
},
}
defer fs.use()()
// prepare ifname in original namespace
_ = originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
err := netlink.LinkAdd(&netlink.Dummy{
LinkAttrs: netlink.LinkAttrs{
Name: ifname,
},
})
Expect(err).NotTo(HaveOccurred())
origLink, err = netlink.LinkByName(ifname)
Expect(err).NotTo(HaveOccurred())
err = netlink.LinkSetUp(origLink)
Expect(err).NotTo(HaveOccurred())
return nil
})
// call CmdAdd
cniName := "net1"
conf := fmt.Sprintf(`{
"cniVersion": "%s",
"name": "cni-plugin-host-device-test",
"type": "host-device",
"runtimeConfig": {"deviceID": %q}
}`, ver, "mlx5_core.sf.4")
args := &skel.CmdArgs{
ContainerID: "dummy",
IfName: cniName,
Netns: targetNS.Path(),
StdinData: []byte(conf),
}
var resI types.Result
err := originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
var err error
resI, _, err = testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) })
return err
})
Expect(err).NotTo(HaveOccurred())
// check that the result was sane
t := newTesterByVersion(ver)
t.expectInterfaces(resI, cniName, origLink.Attrs().HardwareAddr.String(), targetNS.Path())
// call CmdDel
_ = originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
err = testutils.CmdDelWithArgs(args, func() error {
return cmdDel(args)
})
Expect(err).NotTo(HaveOccurred())
return nil
})
})
It(fmt.Sprintf("Works with a valid %s config with IPAM", ver), func() {
var origLink netlink.Link
@ -961,11 +1026,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 +1049,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) {
@ -1149,6 +1214,114 @@ var _ = Describe("base functionality", func() {
return nil
})
})
It(fmt.Sprintf("Test CmdAdd/Del when additioinal interface alreay exists in container ns with same name. %s config", ver), func() {
var (
origLink netlink.Link
containerLink netlink.Link
)
hostIfname := "eth0"
containerAdditionalIfname := "eth0"
// prepare host device in original namespace
_ = originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
err := netlink.LinkAdd(&netlink.Dummy{
LinkAttrs: netlink.LinkAttrs{
Name: hostIfname,
},
})
Expect(err).NotTo(HaveOccurred())
origLink, err = netlink.LinkByName(hostIfname)
Expect(err).NotTo(HaveOccurred())
err = netlink.LinkSetUp(origLink)
Expect(err).NotTo(HaveOccurred())
return nil
})
// prepare device in container namespace with same name as host device
_ = targetNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
err := netlink.LinkAdd(&netlink.Dummy{
LinkAttrs: netlink.LinkAttrs{
Name: containerAdditionalIfname,
},
})
Expect(err).NotTo(HaveOccurred())
containerLink, err = netlink.LinkByName(containerAdditionalIfname)
Expect(err).NotTo(HaveOccurred())
err = netlink.LinkSetUp(containerLink)
Expect(err).NotTo(HaveOccurred())
return nil
})
// call CmdAdd
cniName := "net1"
conf := fmt.Sprintf(`{
"cniVersion": "%s",
"name": "cni-plugin-host-device-test",
"type": "host-device",
"device": %q
}`, ver, hostIfname)
args := &skel.CmdArgs{
ContainerID: "dummy",
Netns: targetNS.Path(),
IfName: cniName,
StdinData: []byte(conf),
}
var resI types.Result
err := originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
var err error
resI, _, err = testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) })
return err
})
Expect(err).NotTo(HaveOccurred())
// check that the result was sane
t := newTesterByVersion(ver)
t.expectInterfaces(resI, cniName, origLink.Attrs().HardwareAddr.String(), targetNS.Path())
// assert that host device is now in the target namespace and is up
_ = targetNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
link, err := netlink.LinkByName(cniName)
Expect(err).NotTo(HaveOccurred())
Expect(link.Attrs().HardwareAddr).To(Equal(origLink.Attrs().HardwareAddr))
Expect(link.Attrs().Flags & net.FlagUp).To(Equal(net.FlagUp))
return nil
})
// call CmdDel, expect it to succeed
_ = originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
err = testutils.CmdDelWithArgs(args, func() error {
return cmdDel(args)
})
Expect(err).ToNot(HaveOccurred())
return nil
})
// assert container interface "eth0" still exists in target namespace and is up
err = targetNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
link, err := netlink.LinkByName(containerAdditionalIfname)
Expect(err).NotTo(HaveOccurred())
Expect(link.Attrs().HardwareAddr).To(Equal(containerLink.Attrs().HardwareAddr))
Expect(link.Attrs().Flags & net.FlagUp).To(Equal(net.FlagUp))
return nil
})
Expect(err).NotTo(HaveOccurred())
// assert that host device is now back in the original namespace
_ = originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
_, err := netlink.LinkByName(hostIfname)
Expect(err).NotTo(HaveOccurred())
return nil
})
})
}
})
@ -1167,7 +1340,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()))
}
@ -1181,6 +1354,7 @@ func (fs *fakeFilesystem) use() func() {
}
sysBusPCI = path.Join(fs.rootDir, "/sys/bus/pci/devices")
sysBusAuxiliary = path.Join(fs.rootDir, "/sys/bus/auxiliary/devices")
return func() {
// remove temporary fake fs

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"
@ -294,11 +293,9 @@ 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")
_, _ = sysctl.Sysctl(fmt.Sprintf("net/ipv6/conf/%s/ndisc_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
@ -337,7 +334,6 @@ func cmdDel(args *skel.CmdArgs) error {
}
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.
@ -357,7 +353,6 @@ func main() {
}
func cmdCheck(args *skel.CmdArgs) error {
n, _, err := loadConf(args, true)
if err != nil {
return err
@ -407,14 +402,13 @@ func cmdCheck(args *skel.CmdArgs) error {
contMap.Sandbox, args.Netns)
}
var m netlink.Link
if n.LinkContNs {
err = netns.Do(func(_ ns.NetNS) error {
m, err = netlink.LinkByName(n.Master)
_, err = netlink.LinkByName(n.Master)
return err
})
} else {
m, err = netlink.LinkByName(n.Master)
_, err = netlink.LinkByName(n.Master)
}
if err != nil {
@ -423,9 +417,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, n.Mode)
err := validateCniContainerInterface(contMap, n.Mode)
if err != nil {
return err
}
@ -447,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
@ -469,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,16 +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_INCONTAINER = "eth1"
const (
MASTER_NAME = "eth0"
MASTER_NAME_INCONTAINER = "eth1"
)
type Net struct {
Name string `json:"name"`
@ -92,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) {
@ -141,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())
@ -206,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 {
@ -228,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
}
@ -240,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())
@ -324,7 +326,7 @@ var _ = Describe("ipvlan Operations", func() {
if inContainer {
masterInterface = MASTER_NAME_INCONTAINER
}
//for _, ver := range testutils.AllSpecVersions {
// 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.
@ -471,8 +473,8 @@ var _ = Describe("ipvlan Operations", func() {
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}
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())

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"
@ -148,7 +147,8 @@ func getMTUByName(ifName string, namespace string, inContainer bool) (int, error
var link netlink.Link
var err error
if inContainer {
netns, err := ns.GetNS(namespace)
var netns ns.NetNS
netns, err = ns.GetNS(namespace)
if err != nil {
return 0, fmt.Errorf("failed to open netns %q: %v", netns, err)
}
@ -351,11 +351,9 @@ 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")
_, _ = sysctl.Sysctl(fmt.Sprintf("net/ipv6/conf/%s/ndisc_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
@ -385,13 +383,13 @@ func cmdAdd(args *skel.CmdArgs) error {
}
func cmdDel(args *skel.CmdArgs) error {
n, _, err := loadConf(args, args.Args)
var n NetConf
err := json.Unmarshal(args.StdinData, &n)
if err != nil {
return err
return fmt.Errorf("failed to load netConf: %v", err)
}
isLayer3 := n.IPAM.Type != ""
if isLayer3 {
err = ipam.ExecDel(n.IPAM.Type, args.StdinData)
if err != nil {
@ -413,7 +411,6 @@ func cmdDel(args *skel.CmdArgs) error {
}
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.
@ -433,7 +430,6 @@ func main() {
}
func cmdCheck(args *skel.CmdArgs) error {
n, _, err := loadConf(args, args.Args)
if err != nil {
return err
@ -456,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 {
@ -481,18 +477,17 @@ 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)
}
var m netlink.Link
if n.LinkContNs {
err = netns.Do(func(_ ns.NetNS) error {
m, err = netlink.LinkByName(n.Master)
_, err = netlink.LinkByName(n.Master)
return err
})
} else {
m, err = netlink.LinkByName(n.Master)
_, err = netlink.LinkByName(n.Master)
}
if err != nil {
return fmt.Errorf("failed to lookup master %q: %v", n.Master, err)
@ -500,9 +495,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, n.Mode)
err := validateCniContainerInterface(contMap, n.Mode)
if err != nil {
return err
}
@ -524,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 {
@ -555,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) {

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,16 +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_INCONTAINER = "eth1"
const (
MASTER_NAME = "eth0"
MASTER_NAME_INCONTAINER = "eth1"
)
type Net struct {
Name string `json:"name"`
@ -47,10 +48,10 @@ type Net struct {
Master string `json:"master"`
Mode string `json:"mode"`
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"`
@ -98,7 +99,6 @@ func buildOneConfig(netName string, cniVersion string, orig *Net, prevResult typ
}
return conf, nil
}
type tester interface {
@ -108,10 +108,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 {
@ -134,9 +136,9 @@ func (t *testerV10x) verifyResult(result types.Result, err error, name string, n
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(numAddrs))
Expect(r.IPs).To(HaveLen(numAddrs))
return r.Interfaces[0].Mac
}
@ -148,9 +150,9 @@ func verify0403(result types.Result, err error, name string, numAddrs int) strin
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(numAddrs))
Expect(r.IPs).To(HaveLen(numAddrs))
return r.Interfaces[0].Mac
}
@ -166,7 +168,7 @@ func (t *testerV03x) verifyResult(result types.Result, err error, name string, n
}
// verifyResult minimally verifies the Result and returns the interface's MAC address
func (t *testerV01xOr02x) verifyResult(result types.Result, err error, name string, numAddrs int) string {
func (t *testerV01xOr02x) verifyResult(result types.Result, err error, _ string, numAddrs int) string {
if result == nil && numAddrs == 0 {
Expect(err).To(MatchError("cannot convert: no valid IP addresses"))
return ""
@ -346,7 +348,7 @@ var _ = Describe("macvlan 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())
@ -407,7 +409,6 @@ var _ = Describe("macvlan Operations", func() {
return nil
})
Expect(err).NotTo(HaveOccurred())
})
It(fmt.Sprintf("[%s] configures and deconfigures a l2 macvlan link with ADD/DEL", ver), func() {
@ -459,7 +460,7 @@ var _ = Describe("macvlan Operations", func() {
addrs, err := netlink.AddrList(link, syscall.AF_INET)
Expect(err).NotTo(HaveOccurred())
Expect(len(addrs)).To(Equal(0))
Expect(addrs).To(BeEmpty())
return nil
})
Expect(err).NotTo(HaveOccurred())
@ -545,7 +546,7 @@ var _ = Describe("macvlan 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())
@ -637,8 +638,8 @@ var _ = Describe("macvlan Operations", func() {
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}
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())
@ -685,7 +686,7 @@ var _ = Describe("macvlan 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())
@ -767,7 +768,7 @@ var _ = Describe("macvlan Operations", func() {
addrs, err := netlink.AddrList(link, syscall.AF_INET)
Expect(err).NotTo(HaveOccurred())
Expect(len(addrs)).To(Equal(0))
Expect(addrs).To(BeEmpty())
return nil
})
Expect(err).NotTo(HaveOccurred())
@ -852,7 +853,7 @@ var _ = Describe("macvlan Operations", func() {
addrs, err := netlink.AddrList(link, syscall.AF_INET)
Expect(err).NotTo(HaveOccurred())
Expect(len(addrs)).To(Equal(0))
Expect(addrs).To(BeEmpty())
return nil
})
Expect(err).NotTo(HaveOccurred())

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