diff --git a/.github/dco.yml b/.github/dco.yml index 37e411e1be..ec724591a3 100644 --- a/.github/dco.yml +++ b/.github/dco.yml @@ -1,2 +1,3 @@ +--- require: - members: false \ No newline at end of file + members: false diff --git a/.travis.yml b/.travis.yml index 368502849d..eebd521dbd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,4 @@ +--- dist: trusty sudo: required @@ -5,20 +6,18 @@ language: go go: - "1.10.x" -go_import_path: github.com/ligato/vpp-agent - addons: apt: - update: - packages: - - npm + packages: + - npm + +go_import_path: github.com/ligato/vpp-agent git: depth: 10 submodules: false cache: - apt: true directories: - $HOME/.cache/go-build - $HOME/build-cache @@ -36,6 +35,7 @@ before_install: - go get github.com/mattn/goveralls script: + - make yamllint - make check-links || true - make lint - make dep-check @@ -50,7 +50,7 @@ notifications: slack: rooms: - ligato:xLH4aTwGx1dexPaloAegQ74O - on_success: always + on_success: change on_failure: always template: - "Build <%{build_url}|#%{build_number}> of *%{repository_slug}* on branch _%{branch}_ in PR: <%{pull_request_url}|#%{pull_request_number}>" diff --git a/.yamllint.yml b/.yamllint.yml new file mode 100644 index 0000000000..b54dd76d3c --- /dev/null +++ b/.yamllint.yml @@ -0,0 +1,8 @@ +--- +extends: default + +rules: + # 80 chars should be enough, but don't fail if a line is longer + line-length: + max: 80 + level: warning diff --git a/CHANGELOG.md b/CHANGELOG.md index adb19ce4d8..eb75eaca55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,61 @@ +# Release v1.6-vpp18.10 (2018-08-24) + +## Compatibility +- VPP 18.10-rc0~169-gb11f903a +- cn-infra v1.5 + +## Major Topics + +**New Flavors** + + Cn-infra 1.5 brought new and better flavors and it would be a shame not to implement it + in the vpp-agent. The old flavors package was removed and replaced with this new concept, + visible in [app package vpp-agent](app/vpp_agent.go). All examples were also updated. + +## Breaking Changes +- Flavors were replaces with [new way](app) of managing plugins. +- REST interface URLs were changed, see [readme](plugins/rest/README.md) for complete list. + +## New Features +- [rest plugin](plugins/rest) + * All VPP configuration types are now supported to be dumped using REST. Output consists from two parts; + data formatted as NB proto model, and metadata with VPP specific configuration (interface indexes, different + counters, etc.). + * REST prefix was changed. The new URL now contains API version and purpose (dump, put). The list of all + URLs can be found in the [readme](plugins/rest/README.md) +- [ifplugin](plugins/vpp/ifplugin) + * Added support for NAT virtual reassembly for both, IPv4 and IPv6. See change in + [nat proto file](plugins/vpp/model/nat/nat.proto) +- [l3plugin](plugins/vpp/l3plugin) + * Vpp-agent now knows about DROP-type routes. They can be configured and also dumped. VPP default routes, which are + DROP-type are recognized and registered. Currently, resync does not remove or correlate such a route type + automatically, so no default routes are unintentionally removed. + * New configurator for L3 IP scan neighbor was added, allowing to set/unset IP scan neigh parameters to the VPP. + +## Improvements +- [vpp plugins](plugins/vpp) + * all vppcalls were unified under API defined for every configuration type (e.g. interfaces, l2, l3, ...). + Configurators now use special handler object to access vppcalls. This should prevent duplicates and make + vppcalls cleaner and more understandable. +- [ifplugin](plugins/vpp/ifplugin) + * VPP interface DHCP configuration can now be dumped, and added to resync processing + * Interfaces and also L3 routes can be configured for non-zero VRF table if IPv6 is used. +- [examples](examples) + * All examples were reworked to use new flavors concept. The purpose was not changed. + +## Bugfix +* if VPP routes are dumped, all paths are returned +* NAT load-ballanced static mappings should be resynced correctly +* telemetry plugin now correctly parses parentheses for `show node counters` +* telemetry plugin will not hide an error caused by value loading if config file is not present +* linux plugin namespace handler now correctly handles namespace switching for interfaces with IPv6 addresses. + Default IPv6 address (link local) will not be moved to new namespace, if there is no more IPv6 addresses + configured within the interface. This should prevent failures in some cases where IPv6 is not enabled in the + destination namespace. +* VxLAN with non-zero VRF can be successfully removed +* Lint is now working again +* VPP route resync works correctly if next hop IP address is not defined + # Release v1.5.2 (2018-07-23) ## Compatibility diff --git a/Gopkg.lock b/Gopkg.lock index cedeba4a73..700a767e81 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -2,6 +2,8 @@ [[projects]] + branch = "master" + digest = "1:090b939a424724c096b5002d62ea42d9a69dc5fecc3eae0218955a5c6e4070ac" name = "git.fd.io/govpp.git" packages = [ "adapter", @@ -12,71 +14,99 @@ "cmd/binapi-generator", "codec", "core", - "core/bin_api/vpe" ] - revision = "f1bef4a3c66f4408afdeb64cda62ccd8562d0fc6" + pruneopts = "UT" + revision = "a3bb834db727a3ac9a1ffcfeae9265e5dead851f" + source = "github.com/FDio/govpp" [[projects]] branch = "master" + digest = "1:6da51e5ec493ad2b44cb04129e2d0a068c8fb9bd6cb5739d199573558696bb94" name = "github.com/Azure/go-ansiterm" packages = [ ".", - "winterm" + "winterm", ] + pruneopts = "UT" revision = "d6e3b3328b783f23731bc4d058875b0371ff8109" [[projects]] + digest = "1:bf42be3cb1519bf8018dfd99720b1005ee028d947124cab3ccf965da59381df6" name = "github.com/Microsoft/go-winio" packages = ["."] + pruneopts = "UT" revision = "7da180ee92d8bd8bb8c37fc560e673e6557c392f" version = "v0.4.7" [[projects]] branch = "master" + digest = "1:3721a10686511b80c052323423f0de17a8c06d417dbdd3b392b1578432a33aae" name = "github.com/Nvveen/Gotty" packages = ["."] + pruneopts = "UT" revision = "cd527374f1e5bff4938207604a14f2e38a9cf512" [[projects]] + digest = "1:a74fd61e4e9147799aab09264450de47f1637b043525fcf8cf0cd4b1476816e1" name = "github.com/Shopify/sarama" packages = [ ".", - "mocks" + "mocks", ] + pruneopts = "UT" revision = "3b1b38866a79f06deddf0487d5c27ba0697ccd65" version = "v1.15.0" [[projects]] branch = "master" + digest = "1:ec2d85f88fafc85b18d543d3435dbec6a4f895017ce73d45ae7c7fff2b57c29a" name = "github.com/bennyscetbun/jsongo" packages = ["."] + pruneopts = "UT" revision = "a97f4e906f8da60776250125ca8531adfd8ec44f" [[projects]] branch = "master" + digest = "1:5bb36304653e73c2ced864d49c9f344e7141a7ceef852442edcea212094ebc3c" name = "github.com/beorn7/perks" packages = ["quantile"] + pruneopts = "UT" revision = "4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9" [[projects]] + digest = "1:7b81d2ed76bf960333a8020c4b8c22abd6072f0b54ad31c66e90e6a17a19315a" + name = "github.com/bshuster-repo/logrus-logstash-hook" + packages = ["."] + pruneopts = "UT" + revision = "dbc1e22735aa6ed7bd9579a407c17bc7c4a4e046" + version = "v0.4.1" + +[[projects]] + digest = "1:4fdffd1724c105db8c394019cfc2444fd23466be04812850506437361ee5de55" name = "github.com/bsm/sarama-cluster" packages = ["."] - revision = "24016d206c730276dfb58f802999066f2f4bfeaa" - version = "v2.1.11" + pruneopts = "UT" + revision = "cf455bc755fe41ac9bb2861e7a961833d9c2ecc3" + version = "v2.1.13" [[projects]] branch = "master" + digest = "1:85f4b0e48294ebfd3282f631a27c72e324c3b980e095fa254d34292bd182719d" name = "github.com/buger/goterm" packages = ["."] + pruneopts = "UT" revision = "ef0fa5b75d0fa2b31323463783a6e90353771116" [[projects]] branch = "master" + digest = "1:fc8dbcc2a5de7c093e167828ebbdf551641761d2ad75431d3a167d467a264115" name = "github.com/containerd/continuity" packages = ["pathdriver"] + pruneopts = "UT" revision = "b2b946a77f5973f420514090d6f6dd58b08303f0" [[projects]] + digest = "1:78c50fbac6adb72e7b55afeb23390e8c5fdfb2983ad42240e549cc25bc8486a8" name = "github.com/coreos/etcd" packages = [ "auth/authpb", @@ -85,18 +115,22 @@ "etcdserver/api/v3rpc/rpctypes", "etcdserver/etcdserverpb", "mvcc/mvccpb", - "pkg/tlsutil" + "pkg/tlsutil", ] + pruneopts = "UT" revision = "66722b1ada68fcd5227db853ee92003169a975c8" version = "v3.2.0" [[projects]] + digest = "1:a2c1d0e43bd3baaa071d1b9ed72c27d78169b2b269f71c105ac4ba34b1be4a39" name = "github.com/davecgh/go-spew" packages = ["spew"] + pruneopts = "UT" revision = "346938d642f2ec3594ed81d874461961cd0faa76" version = "v1.1.0" [[projects]] + digest = "1:4ec8504b68b75f562efc4b291cba33194f88eaa4e68d9fc449e5b7ca68539329" name = "github.com/docker/docker" packages = [ "api/types", @@ -111,76 +145,121 @@ "api/types/swarm/runtime", "api/types/versions", "opts", - "pkg/archive", "pkg/fileutils", "pkg/homedir", "pkg/idtools", "pkg/ioutils", - "pkg/jsonmessage", "pkg/longpath", "pkg/mount", "pkg/pools", "pkg/stdcopy", "pkg/system", - "pkg/term", - "pkg/term/windows" ] - revision = "fe8aac6f5ae413a967adb0adad0b54abdfb825c4" + pruneopts = "UT" + revision = "3dfb26ab3cbf961298f8ce3f94659b5fe4146ceb" [[projects]] + digest = "1:87dcb59127512b84097086504c16595cf8fef35b9e0bfca565dfc06e198158d7" name = "github.com/docker/go-connections" packages = ["nat"] + pruneopts = "UT" revision = "3ede32e2033de7505e6500d6c868c2b9ed9f169d" version = "v0.3.0" [[projects]] + digest = "1:57d39983d01980c1317c2c5c6dd4b5b0c4a804ad2df800f2f6cbcd6a6d05f6ca" name = "github.com/docker/go-units" packages = ["."] + pruneopts = "UT" revision = "0dadbb0345b35ec7ef35e228dabb8de89a65bf52" version = "v0.3.2" [[projects]] + digest = "1:00d0d550a1f1d7ca03270ebc1e136f21f6b9dab37f0c37e9a90d56d2f7afcff9" + name = "github.com/docker/libnetwork" + packages = ["ipamutils"] + pruneopts = "UT" + revision = "19279f0492417475b6bfbd0aa529f73e8f178fb5" + +[[projects]] + digest = "1:1f0c7ab489b407a7f8f9ad16c25a504d28ab461517a971d341388a56156c1bd7" name = "github.com/eapache/go-resiliency" packages = ["breaker"] - revision = "6800482f2c813e689c88b7ed3282262385011890" - version = "v1.0.0" + pruneopts = "UT" + revision = "ea41b0fad31007accc7f806884dcdf3da98b79ce" + version = "v1.1.0" [[projects]] branch = "master" + digest = "1:0448d1c1a596941c608762912fe7c865f88d9ffa45afb8af1edcf1401762bf7e" name = "github.com/eapache/go-xerial-snappy" packages = ["."] - revision = "bb955e01b9346ac19dc29eb16586c90ded99a98c" + pruneopts = "UT" + revision = "040cc1a32f578808623071247fdbd5cc43f37f5f" [[projects]] + digest = "1:444b82bfe35c83bbcaf84e310fb81a1f9ece03edfed586483c869e2c046aef69" name = "github.com/eapache/queue" packages = ["."] + pruneopts = "UT" revision = "44cc805cf13205b55f69e14bcb69867d1ae92f98" version = "v1.1.0" [[projects]] + digest = "1:f4f6279cb37479954644babd8f8ef00584ff9fa63555d2c6718c1c3517170202" name = "github.com/elazarl/go-bindata-assetfs" packages = ["."] + pruneopts = "UT" revision = "30f82fa23fd844bd5bb1e5f216db87fd77b5eb43" version = "v1.0.0" [[projects]] + digest = "1:ad7ffa16c33f19ee2c17bce7ee865f5632cdc90d908aa313849900ecb3f722df" + name = "github.com/evalphobia/logrus_fluent" + packages = ["."] + pruneopts = "UT" + revision = "76779e73f35d90f5a873e7feaf6691999b2c5db4" + version = "v0.4.0" + +[[projects]] + digest = "1:1a1fda2eefc60b9b047b3812b26be4779352aa80cab966b77e6fe77b157a7a4b" + name = "github.com/fluent/fluent-logger-golang" + packages = ["fluent"] + pruneopts = "UT" + revision = "8bbc2356beaf021b04c9bd5cdc76ea5a7ccb40ec" + version = "v1.3.0" + +[[projects]] + digest = "1:abeb38ade3f32a92943e5be54f55ed6d6e3b6602761d74b4aab4c9dd45c18abd" name = "github.com/fsnotify/fsnotify" packages = ["."] + pruneopts = "UT" revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9" version = "v1.4.7" [[projects]] + digest = "1:027133e2c23fd4ff467e66d928ab4a64f7fd7cb2f77acdb580c483f7389d22d7" name = "github.com/fsouza/go-dockerclient" - packages = ["."] - revision = "9e921e30db8bcc1221fa0485ad9ce5b195fb4445" + packages = [ + ".", + "internal/archive", + "internal/jsonmessage", + "internal/term", + ] + pruneopts = "UT" + revision = "8842d40dbf5ee062d80f9dc429db31a0fe0cdc73" + version = "v1.2.2" [[projects]] + digest = "1:2cd7915ab26ede7d95b8749e6b1f933f1c6d5398030684e6505940a10f31cfda" name = "github.com/ghodss/yaml" packages = ["."] + pruneopts = "UT" revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7" version = "v1.0.0" [[projects]] + digest = "1:991bb96360eb8db70a40e9c496769fe6a7bbac4047f8376494d9837397078327" name = "github.com/go-redis/redis" packages = [ ".", @@ -188,23 +267,16 @@ "internal/consistenthash", "internal/hashtag", "internal/pool", - "internal/proto" - ] - revision = "4021ace05686f632ff17fd824bbed229fc474cf8" - version = "v6.8.2" - -[[projects]] - branch = "master" - name = "github.com/gocql/gocql" - packages = [ - ".", - "internal/lru", - "internal/murmur", - "internal/streams" + "internal/proto", + "internal/singleflight", + "internal/util", ] - revision = "dd47639f787e8583e1a13e17e20a9f6c4332bc29" + pruneopts = "UT" + revision = "480db94d33e6088e08d628833b6c0705451d24bb" + version = "v6.13.2" [[projects]] + digest = "1:47f4b03084d147ec4523ed341449f6dd40fdc2b6fe35375c6bd255ec03163b02" name = "github.com/gogo/protobuf" packages = [ "gogoproto", @@ -231,94 +303,99 @@ "protoc-gen-gogo/grpc", "protoc-gen-gogo/plugin", "vanity", - "vanity/command" + "vanity/command", ] + pruneopts = "UT" revision = "342cbe0a04158f6dcb03ca0079991a51a4248c02" version = "v0.5" [[projects]] branch = "master" + digest = "1:9b0e71863f18fc5de645a263184c8a6409ae731e847b35b25da4be818f1975fa" name = "github.com/golang/protobuf" packages = ["proto"] + pruneopts = "UT" revision = "c65a0412e71e8b9b3bfd22925720d23c0f054237" [[projects]] branch = "master" + digest = "1:4a0c6bb4805508a6287675fac876be2ac1182539ca8a32468d8128882e9d5009" name = "github.com/golang/snappy" packages = ["."] - revision = "553a641470496b2327abcac10b36396bd98e45c9" + pruneopts = "UT" + revision = "2e65f85255dbc3072edf28d6b5b8efc472979f5a" [[projects]] + digest = "1:160eabf7a69910fd74f29c692718bc2437c1c1c7d4c9dea9712357752a70e5df" name = "github.com/gorilla/context" packages = ["."] + pruneopts = "UT" revision = "1ea25387ff6f684839d82767c1733ff4d4d15d0a" version = "v1.1" [[projects]] + digest = "1:e73f5b0152105f18bc131fba127d9949305c8693f8a762588a82a48f61756f5f" name = "github.com/gorilla/mux" packages = ["."] - revision = "53c1911da2b537f792e7cafcb446b05ffe33b996" - version = "v1.6.1" - -[[projects]] - branch = "master" - name = "github.com/hailocab/go-hostpool" - packages = ["."] - revision = "e80d13ce29ede4452c43dea11e79b9bc8a15b478" + pruneopts = "UT" + revision = "e3702bed27f0d39777b0b37b664b6280e8ef8fbf" + version = "v1.6.2" [[projects]] + digest = "1:f8cb7c367c825e0c0be75f17e9b003d39b1240a1535fbbf095a18d7bb0d0c9c9" name = "github.com/hashicorp/consul" packages = ["api"] - revision = "fb848fc48818f58690db09d14640513aa6bf3c02" - version = "v1.0.7" + pruneopts = "UT" + revision = "e716d1b5f8be252b3e53906c6d5632e0228f30fa" + version = "v1.2.2" [[projects]] branch = "master" + digest = "1:77cb3be9b21ba7f1a4701e870c84ea8b66e7d74c7c8951c58155fdadae9414ec" name = "github.com/hashicorp/go-cleanhttp" packages = ["."] + pruneopts = "UT" revision = "d5fe4b57a186c716b0e00b8c301cbd9b4182694d" [[projects]] branch = "master" + digest = "1:45aad874d3c7d5e8610427c81870fb54970b981692930ec2a319ce4cb89d7a00" name = "github.com/hashicorp/go-rootcerts" packages = ["."] + pruneopts = "UT" revision = "6bb64b370b90e7ef1fa532be9e591a81c3493e00" [[projects]] + digest = "1:0dd7b7b01769f9df356dc99f9e4144bdbabf6c79041ea7c0892379c5737f3c44" name = "github.com/hashicorp/serf" packages = ["coordinate"] + pruneopts = "UT" revision = "d6574a5bb1226678d7010325fb6c985db20ee458" version = "v0.8.1" [[projects]] branch = "master" + digest = "1:2dbfffce77b67ce945b23c3a24396c19f346cd68e9e6a3b84ab2c1f599804110" name = "github.com/howeyc/crc16" packages = ["."] + pruneopts = "UT" revision = "2b2a61e366a66d3efb279e46176e7291001e0354" [[projects]] + digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be" name = "github.com/inconshreveable/mousetrap" packages = ["."] + pruneopts = "UT" revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" version = "v1.0" [[projects]] branch = "master" - name = "github.com/kr/pretty" - packages = ["."] - revision = "cfb55aafdaf3ec08f0db22699ab822c50091b1c4" - -[[projects]] - branch = "master" - name = "github.com/kr/text" - packages = ["."] - revision = "7cafcd837844e784b526369c9bce262804aebc60" - -[[projects]] + digest = "1:6dd5650e3030d5060e7df8d92f6a4c69b2361978ecc7d00dec3d371b6cbbae86" name = "github.com/ligato/cn-infra" packages = [ + "agent", "config", - "core", "datasync", "datasync/kvdbsync", "datasync/kvdbsync/local", @@ -330,16 +407,12 @@ "db/keyval/etcd", "db/keyval/kvproto", "db/keyval/redis", - "db/sql", - "db/sql/cassandra", - "flavors/connectors", - "flavors/local", - "flavors/rpc", "health/probe", "health/statuscheck", "health/statuscheck/model/status", "idxmap", "idxmap/mem", + "infra", "logging", "logging/logmanager", "logging/logrus", @@ -354,49 +427,62 @@ "servicelabel", "utils/addrs", "utils/clienttls", + "utils/once", "utils/safeclose", - "utils/structs" ] - revision = "22c14be88d97b2b8c38cce0a7141ea18bd042143" - version = "v1.4.1" + pruneopts = "T" + revision = "664a4d1263a2679014006424616880df0067a4ba" [[projects]] branch = "master" + digest = "1:3b55e68f7806bd4a804c9ac871c4e0cc224cc822feb7fa5e0bd7f1bfb4c31cfa" name = "github.com/logrusorgru/aurora.git" packages = ["."] + pruneopts = "UT" revision = "ca24023cc0175fdf372518cb1c5062cc86db2634" [[projects]] branch = "master" + digest = "1:fd0b11e9149f5aa2a2f17c7f577c905a93c04633ae6e0b2b51f486bfe68fadad" name = "github.com/lunixbochs/struc" packages = ["."] + pruneopts = "UT" revision = "ef56447db6a068ad9e52bc54a1aff5fb9e1ed2dd" [[projects]] - branch = "master" - name = "github.com/maraino/go-mock" - packages = ["."] - revision = "c0658195ada54274d527cb1b09ff1d31765509d6" - -[[projects]] + digest = "1:5985ef4caf91ece5d54817c11ea25f182697534f8ae6521eadcd628c142ac4b6" name = "github.com/matttproud/golang_protobuf_extensions" packages = ["pbutil"] + pruneopts = "UT" revision = "3247c84500bff8d9fb6d579d800f20b3e091582c" version = "v1.0.0" [[projects]] branch = "master" + digest = "1:8eb17c2ec4df79193ae65b621cd1c0c4697db3bc317fe6afdc76d7f2746abd05" name = "github.com/mitchellh/go-homedir" packages = ["."] - revision = "b8bc1bf767474819792c23f32d8286a45736f1c6" + pruneopts = "UT" + revision = "3864e76763d94a6df2f9960b16a20a33da9f9a66" [[projects]] + branch = "master" + digest = "1:5ab79470a1d0fb19b041a624415612f8236b3c06070161a910562f2b2d064355" + name = "github.com/mitchellh/mapstructure" + packages = ["."] + pruneopts = "UT" + revision = "f15292f7a699fcc1a38a80977f80a046874ba8ac" + +[[projects]] + digest = "1:6221a3a452964b1ff30efdc22209b124d54d04373e5993264d3fa9b13da0659d" name = "github.com/namsral/flag" packages = ["."] + pruneopts = "UT" revision = "71ceffbeb0ba60fccc853971bb3ed4d7d90bfd04" version = "v1.7.4-pre" [[projects]] + digest = "1:038734db8a70cdd73d4215081b22236e2aed3e65ca0727f6afd0ed839630e738" name = "github.com/onsi/gomega" packages = [ ".", @@ -410,164 +496,210 @@ "matchers/support/goraph/edge", "matchers/support/goraph/node", "matchers/support/goraph/util", - "types" + "types", ] + pruneopts = "UT" revision = "003f63b7f4cff3fc95357005358af2de0f5fe152" version = "v1.3.0" [[projects]] + digest = "1:ee4d4af67d93cc7644157882329023ce9a7bcfce956a079069a9405521c7cc8d" name = "github.com/opencontainers/go-digest" packages = ["."] + pruneopts = "UT" revision = "279bed98673dd5bef374d3b6e4b09e2af76183bf" version = "v1.0.0-rc1" [[projects]] + digest = "1:11db38d694c130c800d0aefb502fb02519e514dc53d9804ce51d1ad25ec27db6" name = "github.com/opencontainers/image-spec" packages = [ "specs-go", - "specs-go/v1" + "specs-go/v1", ] + pruneopts = "UT" revision = "d60099175f88c47cd379c4738d158884749ed235" version = "v1.0.1" [[projects]] + digest = "1:38ee335aedf4626620f3cf8f605661e71abdcce7b40b38921962beb3980f0a20" name = "github.com/opencontainers/runc" - packages = [ - "libcontainer/system", - "libcontainer/user" - ] + packages = ["libcontainer/user"] + pruneopts = "UT" revision = "baf6536d6259209c3edfa2b22237af82942d3dfa" version = "v0.1.1" [[projects]] - name = "github.com/pierrec/lz4" + digest = "1:5e73b34a27d827212102605789de00bd411b2e434812133c83935fe9897c75e1" + name = "github.com/philhofer/fwd" packages = ["."] - revision = "2fcda4cb7018ce05a25959d2fe08c83e3329f169" - version = "v1.1" + pruneopts = "UT" + revision = "bb6d471dc95d4fe11e432687f8b70ff496cf3136" + version = "v1.0.0" [[projects]] - name = "github.com/pierrec/xxHash" - packages = ["xxHash32"] - revision = "f051bb7f1d1aaf1b5a665d74fb6b0217712c69f7" - version = "v0.1.1" + digest = "1:29803f52611cbcc1dfe55b456e9fdac362af7248b3d29d7ea1bec0a12e71dff4" + name = "github.com/pierrec/lz4" + packages = [ + ".", + "internal/xxh32", + ] + pruneopts = "UT" + revision = "1958fd8fff7f115e79725b1288e0b878b3e06b00" + version = "v2.0.3" [[projects]] + digest = "1:40e195917a951a8bf867cd05de2a46aaf1806c50cf92eebf4c16f78cd196f747" name = "github.com/pkg/errors" packages = ["."] + pruneopts = "UT" revision = "645ef00459ed84a119197bfb8d8205042c6df63d" version = "v0.8.0" [[projects]] + digest = "1:d14a5f4bfecf017cb780bdde1b6483e5deb87e12c332544d2c430eda58734bcb" name = "github.com/prometheus/client_golang" packages = [ "prometheus", - "prometheus/promhttp" + "prometheus/promhttp", ] + pruneopts = "UT" revision = "c5b7fccd204277076155f10851dad72b76a49317" version = "v0.8.0" [[projects]] branch = "master" + digest = "1:32d10bdfa8f09ecf13598324dba86ab891f11db3c538b6a34d1c3b5b99d7c36b" name = "github.com/prometheus/client_model" packages = ["go"] + pruneopts = "UT" revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c" [[projects]] branch = "master" + digest = "1:fcce8c26e13e3d5018d5c42de857e8b700354d36afb900dd82bc642383981661" name = "github.com/prometheus/common" packages = [ "expfmt", "internal/bitbucket.org/ww/goautoneg", - "model" + "model", ] + pruneopts = "UT" revision = "89604d197083d4781071d3c65855d24ecfb0a563" [[projects]] branch = "master" + digest = "1:19504758005dbeb5c6c33e562dd51532da38c3717752e73791296c9288421dbf" name = "github.com/prometheus/procfs" packages = [ ".", "internal/util", "nfsd", - "xfs" + "xfs", ] + pruneopts = "UT" revision = "85fadb6e89903ef7cca6f6a804474cd5ea85b6e1" [[projects]] branch = "master" + digest = "1:c4556a44e350b50a490544d9b06e9fba9c286c21d6c0e47f54f3a9214597298c" name = "github.com/rcrowley/go-metrics" packages = ["."] - revision = "e181e095bae94582363434144c61a9653aff6e50" + pruneopts = "UT" + revision = "e2704e165165ec55d062f5919b4b29494e9fa790" [[projects]] + digest = "1:274f67cb6fed9588ea2521ecdac05a6d62a8c51c074c1fccc6a49a40ba80e925" name = "github.com/satori/go.uuid" packages = ["."] + pruneopts = "UT" revision = "f58768cc1a7a7e77a3bd49e98cdd21419399b6a3" version = "v1.2.0" [[projects]] + digest = "1:14b7e5f64170ca9942d257036dba61b096a900adb1b2ddecf7a7bc0d44de9e4c" name = "github.com/sirupsen/logrus" - packages = ["."] + packages = [ + ".", + "hooks/syslog", + ] + pruneopts = "UT" revision = "d682213848ed68c0a260ca37d6dd5ace8423f5ba" version = "v1.0.4" [[projects]] + digest = "1:7ffc0983035bc7e297da3688d9fe19d60a420e9c38bef23f845c53788ed6a05e" name = "github.com/spf13/cobra" packages = ["."] + pruneopts = "UT" revision = "7b2c5ac9fc04fc5efafb60700713d4fa609b777b" version = "v0.0.1" [[projects]] + digest = "1:1b21a2b4058a779f290c7341cd93267492e0ecea6c8b54f64a4a5fd7ff131034" name = "github.com/spf13/pflag" packages = ["."] + pruneopts = "UT" revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66" version = "v1.0.0" +[[projects]] + digest = "1:eaa6698f44de8f2977e93c9b946e60a8af75f565058658aad2df8032b55c84e5" + name = "github.com/tinylib/msgp" + packages = ["msgp"] + pruneopts = "UT" + revision = "b2b6a672cf1e5b90748f79b8b81fc8c5cf0571a1" + version = "1.0.2" + [[projects]] branch = "master" + digest = "1:0d7055e14293468d8a849d858d43e86d4d1be9f5361ec23813b55393b299f558" name = "github.com/ungerik/pkgreflect" packages = ["."] + pruneopts = "UT" revision = "bfeb2a93186329a0bb03885bea902e86842f633d" [[projects]] branch = "master" + digest = "1:e833d953c8467158fd0250a053ec390dd899945d4c6b87b07920ad431fc80dfe" name = "github.com/unrolled/render" packages = ["."] + pruneopts = "UT" revision = "65450fb6b2d3595beca39f969c411db8f8d5c806" [[projects]] branch = "master" + digest = "1:a33371c267e87664981ede8804eff9aac0e36d234deef66b176858c9476e63d4" name = "github.com/vishvananda/netlink" packages = [ ".", - "nl" + "nl", ] + pruneopts = "UT" revision = "5f5d5cddcf414bb44941b9c6c0d2df31253ec40e" [[projects]] branch = "master" + digest = "1:02b1d1b48bf853ea2a9bea029ffe54e3fd7804903a0eda9a78191db8984300d2" name = "github.com/vishvananda/netns" packages = ["."] + pruneopts = "UT" revision = "be1fbeda19366dea804f00efff2dd73a1642fdcc" [[projects]] branch = "master" - name = "github.com/willfaught/gockle" - packages = ["."] - revision = "4f254e1e0f0a12485963192ff605f61f1933e71f" - -[[projects]] - branch = "master" + digest = "1:707ec3bb6ccc1cd330b8789467fa6cd8dad40f63fed028ba777a6c2ca13a9838" name = "golang.org/x/crypto" packages = ["ssh/terminal"] + pruneopts = "UT" revision = "3d37316aaa6bd9929127ac9a527abf408178ea7b" [[projects]] branch = "master" + digest = "1:322768c2d083e730e27856aef1551d7ebc9e209f9e9549aca9d4e1cb095b5e87" name = "golang.org/x/net" packages = [ "context", - "context/ctxhttp", "html", "html/atom", "html/charset", @@ -576,21 +708,25 @@ "idna", "internal/timeseries", "lex/httplex", - "trace" + "trace", ] + pruneopts = "UT" revision = "0ed95abb35c445290478a5348a7b38bb154135fd" [[projects]] branch = "master" + digest = "1:322dcd045c1f20b4604d829832fbbb7cb29f2f7615179736c57b4f2a4ca25ee3" name = "golang.org/x/sys" packages = [ "unix", - "windows" + "windows", ] + pruneopts = "UT" revision = "af50095a40f9041b3b38960738837185c26e9419" [[projects]] branch = "master" + digest = "1:436b24586f8fee329e0dd65fd67c817681420cda1d7f934345c13fe78c212a73" name = "golang.org/x/text" packages = [ "collate", @@ -618,11 +754,13 @@ "unicode/bidi", "unicode/cldr", "unicode/norm", - "unicode/rangetable" + "unicode/rangetable", ] + pruneopts = "UT" revision = "e19ae1496984b1c655b8044a65c0300a3c878dd3" [[projects]] + digest = "1:2b235a29dd809925b0149f8625d9b9f8dcb92fdb6f1f661ac6188e419098cd96" name = "google.golang.org/grpc" packages = [ ".", @@ -636,26 +774,81 @@ "peer", "stats", "tap", - "transport" + "transport", ] + pruneopts = "UT" revision = "8050b9cbc271307e5a716a9d782803d09b0d6f2d" version = "v1.2.1" -[[projects]] - name = "gopkg.in/inf.v0" - packages = ["."] - revision = "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4" - version = "v0.9.0" - [[projects]] branch = "v2" + digest = "1:73e6fda93622790d2371344759df06ff5ff2fac64a6b6e8832b792e7402956e7" name = "gopkg.in/yaml.v2" packages = ["."] + pruneopts = "UT" revision = "d670f9405373e636a5a2765eea47fac0c9bc91a4" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "8d88cea9e950184c84919c5a1e32a620023704ffca5326cfc681225ed2c6c19b" + input-imports = [ + "git.fd.io/govpp.git/adapter", + "git.fd.io/govpp.git/adapter/mock", + "git.fd.io/govpp.git/adapter/vppapiclient", + "git.fd.io/govpp.git/api", + "git.fd.io/govpp.git/cmd/binapi-generator", + "git.fd.io/govpp.git/core", + "github.com/buger/goterm", + "github.com/elazarl/go-bindata-assetfs", + "github.com/fsouza/go-dockerclient", + "github.com/ghodss/yaml", + "github.com/gogo/protobuf/proto", + "github.com/gogo/protobuf/protoc-gen-gogo", + "github.com/golang/protobuf/proto", + "github.com/ligato/cn-infra/agent", + "github.com/ligato/cn-infra/config", + "github.com/ligato/cn-infra/datasync", + "github.com/ligato/cn-infra/datasync/kvdbsync", + "github.com/ligato/cn-infra/datasync/kvdbsync/local", + "github.com/ligato/cn-infra/datasync/msgsync", + "github.com/ligato/cn-infra/datasync/resync", + "github.com/ligato/cn-infra/db/keyval", + "github.com/ligato/cn-infra/db/keyval/consul", + "github.com/ligato/cn-infra/db/keyval/etcd", + "github.com/ligato/cn-infra/db/keyval/kvproto", + "github.com/ligato/cn-infra/db/keyval/redis", + "github.com/ligato/cn-infra/health/probe", + "github.com/ligato/cn-infra/health/statuscheck", + "github.com/ligato/cn-infra/health/statuscheck/model/status", + "github.com/ligato/cn-infra/idxmap", + "github.com/ligato/cn-infra/idxmap/mem", + "github.com/ligato/cn-infra/infra", + "github.com/ligato/cn-infra/logging", + "github.com/ligato/cn-infra/logging/logmanager", + "github.com/ligato/cn-infra/logging/logrus", + "github.com/ligato/cn-infra/logging/measure", + "github.com/ligato/cn-infra/messaging", + "github.com/ligato/cn-infra/messaging/kafka", + "github.com/ligato/cn-infra/rpc/grpc", + "github.com/ligato/cn-infra/rpc/prometheus", + "github.com/ligato/cn-infra/rpc/rest", + "github.com/ligato/cn-infra/servicelabel", + "github.com/ligato/cn-infra/utils/addrs", + "github.com/ligato/cn-infra/utils/safeclose", + "github.com/logrusorgru/aurora.git", + "github.com/lunixbochs/struc", + "github.com/namsral/flag", + "github.com/onsi/gomega", + "github.com/prometheus/client_golang/prometheus", + "github.com/prometheus/client_golang/prometheus/promhttp", + "github.com/sirupsen/logrus", + "github.com/spf13/cobra", + "github.com/ungerik/pkgreflect", + "github.com/unrolled/render", + "github.com/vishvananda/netlink", + "github.com/vishvananda/netns", + "golang.org/x/net/context", + "google.golang.org/grpc", + ] solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index b4dc198baf..b6f7ac238a 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -1,28 +1,7 @@ -# Gopkg.toml example +# Gopkg.toml # # Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md # for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" -# -# [prune] -# non-go = false -# go-tests = true -# unused-packages = true required = [ "git.fd.io/govpp.git/cmd/binapi-generator", @@ -31,12 +10,13 @@ required = [ ] [[constraint]] - name = "git.fd.io/govpp.git" - revision = "f1bef4a3c66f4408afdeb64cda62ccd8562d0fc6" + branch = "master" + name = "github.com/ligato/cn-infra" [[constraint]] - name = "github.com/ligato/cn-infra" - version = "1.4.1" + branch = "master" + name = "git.fd.io/govpp.git" + source = "github.com/FDio/govpp" [[constraint]] branch = "master" @@ -44,7 +24,7 @@ required = [ [[constraint]] name = "github.com/fsouza/go-dockerclient" - revision = "9e921e30db8bcc1221fa0485ad9ce5b195fb4445" + version = "1.0" [[constraint]] name = "github.com/ghodss/yaml" @@ -58,10 +38,6 @@ required = [ branch = "master" name = "github.com/golang/protobuf" -[[constraint]] - name = "github.com/gorilla/mux" - version = "1.6.1" - [[constraint]] branch = "master" name = "github.com/logrusorgru/aurora.git" @@ -102,6 +78,14 @@ required = [ name = "google.golang.org/grpc" version = "1.2.1" +[[override]] + name = "github.com/docker/libnetwork" + revision = "19279f0492417475b6bfbd0aa529f73e8f178fb5" + [prune] go-tests = true unused-packages = true + + [[prune.project]] + name = "github.com/ligato/cn-infra" + unused-packages = false diff --git a/Makefile b/Makefile index d3d00c6d28..5606cd87e1 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ VERSION ?= $(shell git describe --always --tags --dirty) COMMIT ?= $(shell git rev-parse HEAD) DATE := $(shell date +'%Y-%m-%dT%H:%M%:z') -CNINFRA := github.com/ligato/vpp-agent/vendor/github.com/ligato/cn-infra/core +CNINFRA := github.com/ligato/vpp-agent/vendor/github.com/ligato/cn-infra/agent LDFLAGS = -X $(CNINFRA).BuildVersion=$(VERSION) -X $(CNINFRA).CommitHash=$(COMMIT) -X $(CNINFRA).BuildDate=$(DATE) ifeq ($(NOSTRIP),) @@ -143,8 +143,8 @@ generate-binapi: get-binapi-generators cd plugins/vpp/binapi/tapv2 && pkgreflect cd plugins/vpp/binapi/vpe && pkgreflect cd plugins/vpp/binapi/vxlan && pkgreflect - @echo "=> applying patches" - patch -p1 -i plugins/vpp/binapi/*.patch + @echo "=> applying fix patches" + find plugins/vpp/binapi -maxdepth 1 -type f -name '*.patch' -exec patch --no-backup-if-mismatch -p1 -i {} \; verify-binapi: @echo "=> verifying binary api" @@ -162,7 +162,7 @@ bindata: get-bindata # Get dependency manager tool get-dep: - go get -v github.com/golang/dep/cmd/dep + curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh dep version # Install the project's dependencies @@ -177,13 +177,18 @@ dep-update: get-dep # Check state of dependencies dep-check: get-dep - dep ensure -dry-run -no-vendor + @echo "=> checking dependencies" + dep check + +LINTER := $(shell command -v gometalinter 2> /dev/null) # Get linter tools get-linters: +ifndef LINTER @echo "=> installing linters" go get -v github.com/alecthomas/gometalinter gometalinter --install +endif # Run linters lint: get-linters @@ -195,10 +200,14 @@ format: @echo "=> formatting the code" ./scripts/gofmt.sh +MDLINKCHECK := $(shell command -v markdown-link-check 2> /dev/null) + # Get link check tool get-linkcheck: - sudo apt-get install npm - npm install -g markdown-link-check +ifndef MDLINKCHECK + sudo apt-get update && sudo apt-get install -y npm + npm install -g markdown-link-check@3.6.2 +endif # Validate links in markdown files check-links: get-linkcheck @@ -218,6 +227,14 @@ travis: @echo "Files:" @echo "$$(git diff --name-only $$TRAVIS_COMMIT_RANGE)" +# Install yamllint +get-yamllint: + pip install --user yamllint + +# Lint the yaml files +yamllint: get-yamllint + @echo "=> linting the yaml files" + yamllint -c .yamllint.yml $(shell git ls-files '*.yaml' '*.yml' | grep -v 'vendor/') .PHONY: build clean \ install cmd examples clean-examples test \ @@ -226,4 +243,5 @@ travis: get-dep dep-install dep-update dep-check \ get-linters lint format \ get-linkcheck check-links \ - travis + travis \ + get-yamllint yamllint diff --git a/app/vpp_agent.go b/app/vpp_agent.go new file mode 100644 index 0000000000..5044b9d641 --- /dev/null +++ b/app/vpp_agent.go @@ -0,0 +1,138 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package app + +import ( + "sync" + + "github.com/ligato/cn-infra/datasync" + "github.com/ligato/cn-infra/datasync/kvdbsync" + "github.com/ligato/cn-infra/datasync/kvdbsync/local" + "github.com/ligato/cn-infra/datasync/msgsync" + "github.com/ligato/cn-infra/datasync/resync" + "github.com/ligato/cn-infra/db/keyval/consul" + "github.com/ligato/cn-infra/db/keyval/etcd" + "github.com/ligato/cn-infra/db/keyval/redis" + "github.com/ligato/cn-infra/health/probe" + "github.com/ligato/cn-infra/logging/logmanager" + "github.com/ligato/cn-infra/messaging/kafka" + "github.com/ligato/vpp-agent/plugins/linux" + "github.com/ligato/vpp-agent/plugins/rest" + "github.com/ligato/vpp-agent/plugins/telemetry" + "github.com/ligato/vpp-agent/plugins/vpp" + "github.com/ligato/vpp-agent/plugins/vpp/rpc" +) + +// VPPAgent defines plugins which will be loaded and their order. +// Note: the plugin itself is loaded after all its dependencies. It means that the VPP plugin is first in the list +// despite it needs to be loaded after the linux plugin. +type VPPAgent struct { + LogManager *logmanager.Plugin + + ETCDDataSync *kvdbsync.Plugin + ConsulDataSync *kvdbsync.Plugin + RedisDataSync *kvdbsync.Plugin + + VPP *vpp.Plugin + Linux *linux.Plugin + + GRPCService *rpc.Plugin + RESTAPI *rest.Plugin + Probe *probe.Plugin + Telemetry *telemetry.Plugin +} + +// New creates new VPPAgent instance. +func New() *VPPAgent { + etcdDataSync := kvdbsync.NewPlugin(kvdbsync.UseKV(&etcd.DefaultPlugin)) + consulDataSync := kvdbsync.NewPlugin(kvdbsync.UseKV(&consul.DefaultPlugin)) + redisDataSync := kvdbsync.NewPlugin(kvdbsync.UseKV(&redis.DefaultPlugin)) + + watcher := datasync.KVProtoWatchers{ + local.Get(), + etcdDataSync, + consulDataSync, + } + publisher := datasync.KVProtoWriters{ + etcdDataSync, + consulDataSync, + } + + ifStatePub := msgsync.NewPlugin( + msgsync.UseMessaging(&kafka.DefaultPlugin), + msgsync.UseConf(msgsync.Config{ + Topic: "if_state", + }), + ) + + vppPlugin := vpp.NewPlugin(vpp.UseDeps(func(deps *vpp.Deps) { + deps.Publish = publisher + deps.Watcher = watcher + deps.IfStatePub = ifStatePub + deps.DataSyncs = map[string]datasync.KeyProtoValWriter{ + "etcd": etcdDataSync, + "redis": redisDataSync, + } + deps.GRPCSvc = &rpc.DefaultPlugin + })) + linuxPlugin := linux.NewPlugin(linux.UseDeps(func(deps *linux.Deps) { + deps.VPP = vppPlugin + deps.Watcher = watcher + })) + vppPlugin.Deps.Linux = linuxPlugin + + var watchEventsMutex sync.Mutex + vppPlugin.Deps.WatchEventsMutex = &watchEventsMutex + linuxPlugin.Deps.WatchEventsMutex = &watchEventsMutex + + restPlugin := rest.NewPlugin(rest.UseDeps(func(deps *rest.Deps) { + deps.VPP = vppPlugin + })) + + return &VPPAgent{ + LogManager: &logmanager.DefaultPlugin, + ETCDDataSync: etcdDataSync, + ConsulDataSync: consulDataSync, + RedisDataSync: redisDataSync, + VPP: vppPlugin, + Linux: linuxPlugin, + GRPCService: &rpc.DefaultPlugin, + RESTAPI: restPlugin, + Probe: &probe.DefaultPlugin, + Telemetry: &telemetry.DefaultPlugin, + } +} + +// Init initializes main plugin. +func (VPPAgent) Init() error { + return nil +} + +// AfterInit executes resync. +func (VPPAgent) AfterInit() error { + // manually start resync after all plugins started + resync.DefaultPlugin.DoResync() + return nil +} + +// Close could close used resources. +func (VPPAgent) Close() error { + return nil +} + +// String returns name of the plugin. +func (VPPAgent) String() string { + return "VPPAgent" +} diff --git a/clientv1/linux/dbadapter/data_resync_db.go b/clientv1/linux/dbadapter/data_resync_db.go index 877253f6fe..d3f3991463 100644 --- a/clientv1/linux/dbadapter/data_resync_db.go +++ b/clientv1/linux/dbadapter/data_resync_db.go @@ -213,7 +213,7 @@ func (dsl *DataResyncDSL) Send() vppclient.Reply { toBeDeleted := keySet{} // fill all known keys associated with the Linux network configuration: - keys, err := dsl.listKeys(interfaces.InterfaceKeyPrefix()) + keys, err := dsl.listKeys(interfaces.Prefix) if err != nil { break } diff --git a/clientv1/linux/localclient/localclient_api.go b/clientv1/linux/localclient/localclient_api.go index 9f585d101a..339e1b6fd1 100644 --- a/clientv1/linux/localclient/localclient_api.go +++ b/clientv1/linux/localclient/localclient_api.go @@ -15,18 +15,17 @@ package localclient import ( - "github.com/ligato/cn-infra/core" "github.com/ligato/cn-infra/datasync/kvdbsync/local" "github.com/ligato/vpp-agent/clientv1/linux" "github.com/ligato/vpp-agent/clientv1/linux/dbadapter" ) // PluginID defines the name of Linux localclient plugin. -const PluginID core.PluginName = "LinuxPlugin_LOCAL_CLIENT" +//const PluginID core.PluginName = "LinuxPlugin_LOCAL_CLIENT" // DataResyncRequest allows creating a RESYNC request using convenient RESYNC // DSL and sending it locally through go channels (i.e. without using Data Store). -func DataResyncRequest(caller core.PluginName) linuxclient.DataResyncDSL { +func DataResyncRequest(caller string) linuxclient.DataResyncDSL { return dbadapter.NewDataResyncDSL(local.NewProtoTxn(local.Get().PropagateResync), nil /*no need to list anything*/) } @@ -34,6 +33,6 @@ func DataResyncRequest(caller core.PluginName) linuxclient.DataResyncDSL { // DataChangeRequest allows creating Data Change request(s) using convenient // Data Change DSL and sending it locally through go channels (i.e. without using // Data Store). -func DataChangeRequest(caller core.PluginName) linuxclient.DataChangeDSL { +func DataChangeRequest(caller string) linuxclient.DataChangeDSL { return dbadapter.NewDataChangeDSL(local.NewProtoTxn(local.Get().PropagateChanges)) } diff --git a/clientv1/vpp/dbadapter/data_change_db.go b/clientv1/vpp/dbadapter/data_change_db.go index f6a556ad97..5ae189dc83 100644 --- a/clientv1/vpp/dbadapter/data_change_db.go +++ b/clientv1/vpp/dbadapter/data_change_db.go @@ -167,7 +167,7 @@ func (dsl *PutDSL) StnRule(val *stn.STN_Rule) vppclient.PutDSL { // NAT44Global adds a request to set global configuration for NAT44 func (dsl *PutDSL) NAT44Global(nat44 *nat.Nat44Global) vppclient.PutDSL { - dsl.parent.txn.Put(nat.GlobalConfigKey(), nat44) + dsl.parent.txn.Put(nat.GlobalPrefix, nat44) return dsl } @@ -295,7 +295,7 @@ func (dsl *DeleteDSL) StnRule(ruleName string) vppclient.DeleteDSL { // NAT44Global adds a request to remove global configuration for NAT44 func (dsl *DeleteDSL) NAT44Global() vppclient.DeleteDSL { - dsl.parent.txn.Delete(nat.GlobalConfigKey()) + dsl.parent.txn.Delete(nat.GlobalPrefix) return dsl } diff --git a/clientv1/vpp/dbadapter/data_resync_db.go b/clientv1/vpp/dbadapter/data_resync_db.go index 306a8dac46..0e101c3694 100644 --- a/clientv1/vpp/dbadapter/data_resync_db.go +++ b/clientv1/vpp/dbadapter/data_resync_db.go @@ -185,7 +185,7 @@ func (dsl *DataResyncDSL) StnRule(val *stn.STN_Rule) vppclient.DataResyncDSL { // NAT44Global adds a request to RESYNC global configuration for NAT44 func (dsl *DataResyncDSL) NAT44Global(nat44 *nat.Nat44Global) vppclient.DataResyncDSL { - key := nat.GlobalConfigKey() + key := nat.GlobalPrefix dsl.txn.Put(key, nat44) dsl.txnKeys = append(dsl.txnKeys, key) @@ -245,27 +245,27 @@ func (dsl *DataResyncDSL) Send() vppclient.Reply { // fill all known keys of one VPP: - keys, err := dsl.listKeys(intf.InterfaceKeyPrefix()) + keys, err := dsl.listKeys(intf.Prefix) if err != nil { break } appendKeys(&toBeDeleted, keys) - keys, err = dsl.listKeys(l2.BridgeDomainKeyPrefix()) + keys, err = dsl.listKeys(l2.BdPrefix) if err != nil { break } appendKeys(&toBeDeleted, keys) - keys, err = dsl.listKeys(l2.XConnectKeyPrefix()) + keys, err = dsl.listKeys(l2.XConnectPrefix) if err != nil { break } appendKeys(&toBeDeleted, keys) - keys, err = dsl.listKeys(l3.RouteKeyPrefix()) + keys, err = dsl.listKeys(l3.RoutesPrefix) if err != nil { break } appendKeys(&toBeDeleted, keys) - keys, err = dsl.listKeys(l3.ArpKeyPrefix()) + keys, err = dsl.listKeys(l3.ArpPrefix) if err != nil { break } diff --git a/clientv1/vpp/localclient/localclient_api.go b/clientv1/vpp/localclient/localclient_api.go index ed7ab820fd..28637716a7 100644 --- a/clientv1/vpp/localclient/localclient_api.go +++ b/clientv1/vpp/localclient/localclient_api.go @@ -15,18 +15,17 @@ package localclient import ( - "github.com/ligato/cn-infra/core" "github.com/ligato/cn-infra/datasync/kvdbsync/local" "github.com/ligato/vpp-agent/clientv1/vpp" "github.com/ligato/vpp-agent/clientv1/vpp/dbadapter" ) // PluginID defines the name of VPP (vppplugin) localclient plugin. -const PluginID core.PluginName = "DefaultVppPlugins_LOCAL_CLIENT" +//const PluginID core.PluginName = "DefaultVppPlugins_LOCAL_CLIENT" // DataResyncRequest allows creating a RESYNC request using convenient RESYNC // DSL and sending it locally through go channels (i.e. without using Data Store). -func DataResyncRequest(caller core.PluginName) vppclient.DataResyncDSL { +func DataResyncRequest(caller string) vppclient.DataResyncDSL { return dbadapter.NewDataResyncDSL(local.NewProtoTxn(local.Get().PropagateResync), nil /*no need to list anything*/) } @@ -34,6 +33,6 @@ func DataResyncRequest(caller core.PluginName) vppclient.DataResyncDSL { // DataChangeRequest allows creating Data Change request(s) using convenient // Data Change DSL and sending it locally through go channels (i.e. without using // Data Store). -func DataChangeRequest(caller core.PluginName) vppclient.DataChangeDSL { +func DataChangeRequest(caller string) vppclient.DataChangeDSL { return dbadapter.NewDataChangeDSL(local.NewProtoTxn(local.Get().PropagateChanges)) } diff --git a/cmd/agentctl/cmd/clean_cmd.go b/cmd/agentctl/cmd/clean_cmd.go index 1064b891f1..cde71d860b 100644 --- a/cmd/agentctl/cmd/clean_cmd.go +++ b/cmd/agentctl/cmd/clean_cmd.go @@ -55,9 +55,9 @@ If no data type filter is specified, all data for the specified vpp(s) will be deleted. If no [agent-label-filter] argument is specified, data for all agents will be deleted.`, dataTypeFlagName, dataTypeFlagName, - status.StatusPrefix, interfaces.InterfacePrefix, - interfaces.IfStatePrefix, l2.BdPrefix, - l2.XconnectPrefix, l3.RoutesPrefix), + status.StatusPrefix, interfaces.Prefix, + interfaces.StatePrefix, l2.BdPrefix, + l2.XConnectPrefix, l3.RoutesPrefix), Example: fmt.Sprintf(` Delete all data for "vpp1": $ agentctl clean vpp1 Delete status data for "vpp1"": @@ -66,7 +66,7 @@ for all agents will be deleted.`, $ agentctl clean vpp1 -dataType %s,%s Delete all data for all agents (no filter): $ agentctl clean`, - status.StatusPrefix, status.StatusPrefix, interfaces.InterfacePrefix), + status.StatusPrefix, status.StatusPrefix, interfaces.Prefix), Run: cleanFunc, } diff --git a/cmd/agentctl/utils/common_utils_test.go b/cmd/agentctl/utils/common_utils_test.go index 2a5e51d56d..0032dd49d1 100644 --- a/cmd/agentctl/utils/common_utils_test.go +++ b/cmd/agentctl/utils/common_utils_test.go @@ -46,7 +46,7 @@ func Test02ParseKeyInterfaceConfig(t *testing.T) { ParseKey("/vnf-agent/{agent-label}/vpp/config/v1/interface/{interface-name}") gomega.Expect(label).To(gomega.BeEquivalentTo("{agent-label}")) - gomega.Expect(dataType).To(gomega.BeEquivalentTo(interfaces.InterfacePrefix)) + gomega.Expect(dataType).To(gomega.BeEquivalentTo(interfaces.Prefix)) gomega.Expect(params).To(gomega.BeEquivalentTo("{interface-name}")) } @@ -58,7 +58,7 @@ func Test03ParseKeyInterfaceStatus(t *testing.T) { ParseKey("/vnf-agent/{agent-label}/vpp/status/v1/interface/{interface-name}") gomega.Expect(label).To(gomega.BeEquivalentTo("{agent-label}")) - gomega.Expect(dataType).To(gomega.BeEquivalentTo(interfaces.IfStatePrefix)) + gomega.Expect(dataType).To(gomega.BeEquivalentTo(interfaces.StatePrefix)) gomega.Expect(params).To(gomega.BeEquivalentTo("{interface-name}")) } @@ -70,7 +70,7 @@ func Test04ParseKeyInterfaceError(t *testing.T) { ParseKey("/vnf-agent/{agent-label}/vpp/status/v1/interface/error/{interface-name}") gomega.Expect(label).To(gomega.BeEquivalentTo("{agent-label}")) - gomega.Expect(dataType).To(gomega.BeEquivalentTo(interfaces.IfErrorPrefix)) + gomega.Expect(dataType).To(gomega.BeEquivalentTo(interfaces.ErrorPrefix)) gomega.Expect(params).To(gomega.BeEquivalentTo("{interface-name}")) } @@ -118,7 +118,7 @@ func Test08ParseKeyFib(t *testing.T) { ParseKey("/vnf-agent/{agent-label}/vpp/config/v1/bd/{bd-label}/fib/{mac-address}") gomega.Expect(label).To(gomega.BeEquivalentTo("{agent-label}")) - gomega.Expect(dataType).To(gomega.BeEquivalentTo(l2.FIBPrefix)) + gomega.Expect(dataType).To(gomega.BeEquivalentTo(l2.FibPrefix)) gomega.Expect(params).To(gomega.BeEquivalentTo("{mac-address}")) } @@ -130,14 +130,14 @@ func Test09ParseKeyRoute(t *testing.T) { ParseKey("/vnf-agent/agent1/vpp/config/v1/vrf/vrf1/fib/192.168.1.0/24/192.168.2.1") gomega.Expect(label).To(gomega.BeEquivalentTo("agent1")) - gomega.Expect(dataType).To(gomega.BeEquivalentTo(l3.RouteKeyPrefix())) + gomega.Expect(dataType).To(gomega.BeEquivalentTo(l3.RoutesPrefix)) gomega.Expect(params).To(gomega.BeEquivalentTo("192.168.1.0/24/192.168.2.1")) label, dataType, params, _ = utils. ParseKey("/vnf-agent/agent2/vpp/config/v1/vrf/vrf2/fib/2001:db8:abcd:0012::0/64/2001:db8::1") gomega.Expect(label).To(gomega.BeEquivalentTo("agent2")) - gomega.Expect(dataType).To(gomega.BeEquivalentTo(l3.RouteKeyPrefix())) + gomega.Expect(dataType).To(gomega.BeEquivalentTo(l3.RoutesPrefix)) gomega.Expect(params).To(gomega.BeEquivalentTo("2001:db8:abcd:0012::0/64/2001:db8::1")) } @@ -149,6 +149,6 @@ func Test10ParseKeyVrf(t *testing.T) { ParseKey("/vnf-agent/agent1/vpp/config/v1/vrf/vrf1") gomega.Expect(label).To(gomega.BeEquivalentTo("agent1")) - gomega.Expect(dataType).To(gomega.BeEquivalentTo(l3.VrfKeyPrefix())) + gomega.Expect(dataType).To(gomega.BeEquivalentTo(l3.VrfPrefix)) gomega.Expect(params).To(gomega.BeEquivalentTo("vrf1")) } diff --git a/cmd/agentctl/utils/db_utils.go b/cmd/agentctl/utils/db_utils.go index d7c910b2f8..dd0504cabc 100644 --- a/cmd/agentctl/utils/db_utils.go +++ b/cmd/agentctl/utils/db_utils.go @@ -190,11 +190,11 @@ func (ed EtcdDump) ReadDataFromDb(db keyval.ProtoBroker, key string, vd = newVppDataRecord() } switch dataType { - case interfaces.InterfacePrefix: + case interfaces.Prefix: ed[label], err = readIfConfigFromDb(db, vd, key, params) - case interfaces.IfStatePrefix: + case interfaces.StatePrefix: ed[label], err = readIfStateFromDb(db, vd, key, params) - case interfaces.IfErrorPrefix: + case interfaces.ErrorPrefix: ed[label], err = readInterfaceErrorFromDb(db, vd, key, params) case l2.BdPrefix: ed[label], err = readBdConfigFromDb(db, vd, key, params) @@ -202,9 +202,9 @@ func (ed EtcdDump) ReadDataFromDb(db keyval.ProtoBroker, key string, ed[label], err = readBdStateFromDb(db, vd, key, params) case l2.BdErrPrefix: ed[label], err = readBdErrorFromDb(db, vd, key, params) - case l2.FIBPrefix: + case l2.FibPrefix: ed[label], err = readFibFromDb(db, vd, key) - case l2.XconnectPrefix: + case l2.XConnectPrefix: ed[label], err = readXconnectFromDb(db, vd, key, params) case l3.RoutesPrefix: ed[label], err = readRoutesFromDb(db, vd, key) diff --git a/cmd/vpp-agent-ctl/data_cmd.go b/cmd/vpp-agent-ctl/data_cmd.go index ac4d7316f1..12ff32ab63 100644 --- a/cmd/vpp-agent-ctl/data_cmd.go +++ b/cmd/vpp-agent-ctl/data_cmd.go @@ -190,7 +190,7 @@ func (ctl *VppAgentCtl) createBfdSession() { { Interface: "memif1", Enabled: true, - SourceAddress: "192.168.1.2", + SourceAddress: "172.125.40.1", DestinationAddress: "20.10.0.5", RequiredMinRxInterval: 8, DesiredMinTxInterval: 3, @@ -676,6 +676,39 @@ func (ctl *VppAgentCtl) deleteIPsecSA() { ctl.broker.Delete(saKey2) } +// createIPSecTunnelInterface configures IPSec tunnel interface +func (ctl *VppAgentCtl) createIPSecTunnelInterface() { + tunnelIf := ipsec.TunnelInterfaces_Tunnel{ + Name: "ipsec0", + Esn: false, + AntiReplay: false, + LocalSpi: 1000, + RemoteSpi: 1001, + LocalIp: "10.0.0.2", + RemoteIp: "10.0.0.1", + CryptoAlg: 1, + LocalCryptoKey: "4a506a794f574265564551694d653768", + RemoteCryptoKey: "4a506a794f574265564551694d653768", + IntegAlg: 2, + LocalIntegKey: "4339314b55523947594d6d3547666b45764e6a58", + RemoteIntegKey: "4339314b55523947594d6d3547666b45764e6a58", + Enabled: true, + IpAddresses: []string{"20.0.0.0/24"}, + Vrf: 0, + } + + ctl.Log.Println(tunnelIf) + ctl.broker.Put(ipsec.TunnelKey(tunnelIf.Name), &tunnelIf) +} + +// deleteIPSecTunnelInterface removes IPSec tunnel interface +func (ctl *VppAgentCtl) deleteIPSecTunnelInterface() { + tunnelKey := ipsec.TunnelKey("ipsec0") + + ctl.Log.Println("Deleting", tunnelKey) + ctl.broker.Delete(tunnelKey) +} + // STN // CreateStn puts STN configuration to the ETCD @@ -740,15 +773,27 @@ func (ctl *VppAgentCtl) createGlobalNat() { TwiceNat: false, }, }, + VirtualReassemblyIpv4: &nat.Nat44Global_VirtualReassembly{ + Timeout: 10, + MaxReass: 20, + MaxFrag: 10, + DropFrag: true, + }, + VirtualReassemblyIpv6: &nat.Nat44Global_VirtualReassembly{ + Timeout: 15, + MaxReass: 25, + MaxFrag: 15, + DropFrag: false, + }, } ctl.Log.Println(natGlobal) - ctl.broker.Put(nat.GlobalConfigKey(), natGlobal) + ctl.broker.Put(nat.GlobalPrefix, natGlobal) } // DeleteGlobalNat removes global NAT configuration from the ETCD func (ctl *VppAgentCtl) deleteGlobalNat() { - globalNat := nat.GlobalConfigKey() + globalNat := nat.GlobalPrefix ctl.Log.Println("Deleting", globalNat) ctl.broker.Delete(globalNat) @@ -780,17 +825,18 @@ func (ctl *VppAgentCtl) createDNat() { Label: "dnat1", StMappings: []*nat.Nat44DNat_DNatConfig_StaticMapping{ { - VrfId: 0, ExternalInterface: "tap1", ExternalIp: "192.168.0.1", ExternalPort: 8989, LocalIps: []*nat.Nat44DNat_DNatConfig_StaticMapping_LocalIP{ { + VrfId: 0, LocalIp: "172.124.0.2", LocalPort: 6500, Probability: 40, }, { + VrfId: 0, LocalIp: "172.125.10.5", LocalPort: 2300, Probability: 40, @@ -942,11 +988,28 @@ func (ctl *VppAgentCtl) createRoute() { Weight: 6, OutgoingInterface: "tap1", }, + // inter-vrf route without next hop addr (recursive lookup) + //{ + // Type: l3.StaticRoutes_Route_INTER_VRF, + // VrfId: 0, + // DstIpAddr: "1.2.3.4/32", + // ViaVrfId: 1, + //}, + // inter-vrf route with next hop addr + //{ + // Type: l3.StaticRoutes_Route_INTER_VRF, + // VrfId: 1, + // DstIpAddr: "10.1.1.3/32", + // NextHopAddr: "192.168.1.13", + // ViaVrfId: 0, + //}, }, } - ctl.Log.Print(routes.Routes[0]) - ctl.broker.Put(l3.RouteKey(routes.Routes[0].VrfId, routes.Routes[0].DstIpAddr, routes.Routes[0].NextHopAddr), routes.Routes[0]) + for _, r := range routes.Routes { + ctl.Log.Print(r) + ctl.broker.Put(l3.RouteKey(r.VrfId, r.DstIpAddr, r.NextHopAddr), r) + } } // DeleteRoute removes VPP route configuration from the ETCD @@ -1094,6 +1157,27 @@ func (ctl *VppAgentCtl) deleteProxyArpRanges() { ctl.broker.Delete(arpKey) } +// SetIPScanNeigh puts VPP IP scan neighbor configuration to the ETCD +func (ctl *VppAgentCtl) setIPScanNeigh() { + ipScanNeigh := &l3.IPScanNeighbor{ + Mode: l3.IPScanNeighbor_BOTH, + ScanInterval: 11, + MaxProcTime: 36, + MaxUpdate: 5, + ScanIntDelay: 16, + StaleThreshold: 26, + } + + log.Println(ipScanNeigh) + ctl.broker.Put(l3.IPScanNeighPrefix, ipScanNeigh) +} + +// UnsetIPScanNeigh removes VPP IP scan neighbor configuration from the ETCD +func (ctl *VppAgentCtl) unsetIPScanNeigh() { + ctl.Log.Println("Deleting", l3.IPScanNeighPrefix) + ctl.broker.Delete(l3.IPScanNeighPrefix) +} + // Linux ARP // CreateLinuxArp puts linux ARP entry configuration to the ETCD @@ -1257,7 +1341,7 @@ func (ctl *VppAgentCtl) deleteTxn() { // ReportIfaceErrorState reports interface status data to the ETCD func (ctl *VppAgentCtl) reportIfaceErrorState() { - ifErr, err := ctl.broker.ListValues(interfaces.IfErrorPrefix) + ifErr, err := ctl.broker.ListValues(interfaces.ErrorPrefix) if err != nil { ctl.Log.Fatal(err) return diff --git a/cmd/vpp-agent-ctl/json/nat-global.json b/cmd/vpp-agent-ctl/json/nat-global.json index eda835ecc1..30be7e418e 100644 --- a/cmd/vpp-agent-ctl/json/nat-global.json +++ b/cmd/vpp-agent-ctl/json/nat-global.json @@ -35,5 +35,17 @@ "lastSrcAddress": "10.10.0.2", "twiceNat": false } - ] + ], + "virtual-reassembly-ipv4": { + "timeout": 5, + "maxReass": 10, + "maxFrag": 15, + "dropFrag": true + }, + "virtual-reassembly-ipv6": { + "timeout": 20, + "maxReass": 25, + "maxFrag": 30, + "dropFrag": false + } } \ No newline at end of file diff --git a/cmd/vpp-agent-ctl/vpp-agent-ctl.go b/cmd/vpp-agent-ctl/vpp-agent-ctl.go index b613b1d464..f2f6f9075d 100644 --- a/cmd/vpp-agent-ctl/vpp-agent-ctl.go +++ b/cmd/vpp-agent-ctl/vpp-agent-ctl.go @@ -146,6 +146,10 @@ func do(ctl *VppAgentCtl) { ctl.createIPsecSA() case "-sad": ctl.deleteIPsecSA() + case "-tun": + ctl.createIPSecTunnelInterface() + case "-tund": + ctl.deleteIPSecTunnelInterface() // STN case "-stn": ctl.createStn() @@ -202,6 +206,10 @@ func do(ctl *VppAgentCtl) { ctl.addProxyArpRanges() case "-prxrd": ctl.deleteProxyArpRanges() + case "-ipscn": + ctl.setIPScanNeigh() + case "-ipscnd": + ctl.unsetIPScanNeigh() // Linux ARP case "-larp": ctl.createLinuxArp() @@ -258,8 +266,9 @@ func usage() { -afpkt, -afpktd - af_packet type interface -veth, -vethd - Linux VETH interface pair -ltap, -ltapd - Linux TAP interface - -spd, -spdd - IPsec security policy database - -sa, -sad - IPsec security associations + -spd, -spdd - IPSec security policy database + -sa, -sad - IPSec security associations + -tun -tund - IPSec tunnel interface -stn, -stnd - STN rule -gnat, -gnatd - Global NAT configuration -snat, -snatd - SNAT configuration @@ -273,6 +282,7 @@ func usage() { -prxr, -prxrd - Proxy ARP ranges -lrte, -lrted - Linux route -larp, -larpd - Linux ARP entry + -ipscn -ipscnd - VPP IP scan neighbor -el4, -dl4 - L4 features -appns, -appnsd - Application namespace diff --git a/cmd/vpp-agent/main.go b/cmd/vpp-agent/main.go index aa28305b0a..51b84ac192 100644 --- a/cmd/vpp-agent/main.go +++ b/cmd/vpp-agent/main.go @@ -19,29 +19,22 @@ package main import ( "os" - "github.com/ligato/cn-infra/core" + "github.com/ligato/cn-infra/agent" "github.com/ligato/cn-infra/logging" log "github.com/ligato/cn-infra/logging/logrus" - flavor "github.com/ligato/vpp-agent/flavors/vpp" + "github.com/ligato/vpp-agent/app" ) -// main is the main entry point into the VPP Agent. Firstly, a new CN-Infra -// Agent (app) is created, using the set of plugins defined in vpp_flavor -// (../../flavors/vpp). Secondly, the function calls EventLoopWithInterrupt() -// which initializes and starts all plugins and then waits for the user -// to terminate the VPP Agent process with SIGINT. All VPP Agent's work between -// the initialization and termination is performed by the plugins. func main() { - agent := flavor.NewAgent() + vppAgent := app.New() - err := core.EventLoopWithInterrupt(agent, nil) - if err != nil { - os.Exit(1) + a := agent.NewAgent(agent.AllPlugins(vppAgent)) + + if err := a.Run(); err != nil { + log.DefaultLogger().Fatal(err) } } -// init sets the Log output and Log level parameters for VPP Agent's default -// logger. func init() { log.DefaultLogger().SetOutput(os.Stdout) log.DefaultLogger().SetLevel(logging.DebugLevel) diff --git a/docker/dev/Dockerfile b/docker/dev/Dockerfile index 89645c0b3e..37b091bf1c 100644 --- a/docker/dev/Dockerfile +++ b/docker/dev/Dockerfile @@ -1,4 +1,4 @@ -ARG BASE_IMG=ubuntu:16.04 +ARG BASE_IMG FROM golang as verify-stage @@ -34,8 +34,8 @@ RUN apt-get update \ && apt-get install -y --no-install-recommends \ autoconf automake build-essential ca-certificates curl gdb git \ inetutils-traceroute iproute2 ipsec-tools iputils-ping \ - libapr1 libmbedcrypto0 libmbedtls10 libmbedx509-0 libtool \ - make netcat python software-properties-common sudo supervisor \ + libapr1 libmbedcrypto1 libmbedtls10 libmbedx509-0 libtool \ + make mc nano netcat python software-properties-common sudo supervisor \ telnet unzip wget \ && rm -rf /var/lib/apt/lists/* @@ -54,7 +54,7 @@ RUN mkdir -p /opt/vpp-agent/dev /opt/vpp-agent/plugin WORKDIR /opt/vpp-agent/dev -ARG VPP_REPO_URL=https://gerrit.fd.io/r/vpp.git +ARG VPP_REPO_URL ARG VPP_COMMIT ARG VPP_DEBUG_DEB diff --git a/docker/dev/build.sh b/docker/dev/build.sh index 34dd489883..75909891af 100755 --- a/docker/dev/build.sh +++ b/docker/dev/build.sh @@ -7,7 +7,7 @@ set -e IMAGE_TAG=${IMAGE_TAG:-'dev_vpp_agent'} DOCKERFILE=${DOCKERFILE:-'Dockerfile'} -BASE_IMG=${BASE_IMG:-'ubuntu:16.04'} +BASE_IMG=${BASE_IMG:-'ubuntu:18.04'} GOLANG_OS_ARCH=${GOLANG_OS_ARCH:-'linux-amd64'} source ../../vpp.env diff --git a/docker/prod/Dockerfile b/docker/prod/Dockerfile index c137ba4f30..258cee9765 100644 --- a/docker/prod/Dockerfile +++ b/docker/prod/Dockerfile @@ -1,16 +1,26 @@ FROM dev_vpp_agent as devimg -FROM ubuntu:16.04 +FROM ubuntu:18.04 RUN apt-get update \ && apt-get install -y --no-install-recommends \ # general tools - iproute2 iputils-ping inetutils-traceroute \ + inetutils-traceroute \ + iproute2 \ + iputils-ping \ # vpp requirements - openssl python libapr1 libnuma1 \ - libmbedcrypto0 libmbedtls10 libmbedx509-0 ca-certificates \ + ca-certificates \ + libapr1 \ + libc6 \ + libmbedcrypto1 \ + libmbedtls10 \ + libmbedx509-0 \ + libnuma1 \ + openssl \ # other - supervisor ipsec-tools \ + ipsec-tools \ + python \ + supervisor \ && rm -rf /var/lib/apt/lists/* # install vpp diff --git a/examples/govpp_call/deps.go b/examples/govpp_call/deps.go deleted file mode 100644 index f30c1b7df4..0000000000 --- a/examples/govpp_call/deps.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2017 Cisco and/or its affiliates. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at: -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "github.com/ligato/cn-infra/core" - "github.com/ligato/cn-infra/flavors/local" - "github.com/ligato/vpp-agent/flavors/vpp" - "github.com/ligato/vpp-agent/plugins/govppmux" -) - -// Deps is a helper struct which is grouping all dependencies injected to the plugin -type Deps struct { - GoVppmux govppmux.API - local.PluginInfraDeps // injected -} - -// ExampleFlavor is a set of plugins required for the datasync example. -type ExampleFlavor struct { - // Local flavor to access to Infra (logger, service label, status check) - *vpp.Flavor - // Example plugin - GovppExample ExamplePlugin - // Mark flavor as injected after Inject() - injected bool -} - -// Inject sets object references -func (ef *ExampleFlavor) Inject() (allReadyInjected bool) { - // Every flavor should be injected only once - if ef.injected { - return false - } - ef.injected = true - - // Init local flavor - if ef.Flavor == nil { - ef.Flavor = &vpp.Flavor{} - } - ef.Flavor.Inject() - - ef.GovppExample.PluginInfraDeps = *ef.Flavor.InfraDeps("govpp-example") - ef.GovppExample.GoVppmux = &ef.GoVPP - - return true -} - -// Plugins combines all Plugins in flavor to the list -func (ef *ExampleFlavor) Plugins() []*core.NamedPlugin { - ef.Inject() - return core.ListPluginsInFlavor(ef) -} diff --git a/examples/govpp_call/main.go b/examples/govpp_call/main.go index 7fae0be00e..2ca11df64d 100644 --- a/examples/govpp_call/main.go +++ b/examples/govpp_call/main.go @@ -18,12 +18,17 @@ import ( "time" govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/core" + "github.com/ligato/cn-infra/agent" + "github.com/ligato/cn-infra/datasync" + "github.com/ligato/cn-infra/datasync/kvdbsync/local" + "github.com/ligato/cn-infra/logging" + "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/cn-infra/utils/safeclose" - vppFlavor "github.com/ligato/vpp-agent/flavors/vpp" + "github.com/ligato/vpp-agent/plugins/govppmux" "github.com/ligato/vpp-agent/plugins/vpp" l2Api "github.com/ligato/vpp-agent/plugins/vpp/binapi/l2" "github.com/ligato/vpp-agent/plugins/vpp/model/l2" + "log" ) // ************************************************************************* @@ -42,41 +47,63 @@ import ( // required for the example are initialized. Agent is instantiated with generic plugins (etcd, Kafka, Status check, // HTTP and Log), and GOVPP, and resync plugin, and example plugin which demonstrates GOVPP call functionality. func main() { - // Init closes channel to stop the example. - exampleFinished := make(chan struct{}, 1) - - // Start Agent with ExampleFlavor - flavor := vppFlavor.Flavor{} - exampleFlavor := ExampleFlavor{ - GovppExample: ExamplePlugin{closeChannel: &exampleFinished}, - Flavor: &flavor, // inject VPP flavor + //Init close channel to stop the example. + closeChannel := make(chan struct{}, 1) + // Prepare all the dependencies for example plugin + watcher := datasync.KVProtoWatchers{ + local.Get(), + } + vppPlugin := vpp.NewPlugin(vpp.UseDeps(func(deps *vpp.Deps) { + deps.Watcher = watcher + })) + + // Inject dependencies to example plugin + ep := &ExamplePlugin{ + Log: logrus.DefaultLogger(), + closeChannel: closeChannel, + } + ep.Deps.VPP = vppPlugin + ep.Deps.GoVppMux = &govppmux.DefaultPlugin + + // Start Agent + a := agent.NewAgent( + agent.AllPlugins(ep), + agent.QuitOnClose(closeChannel), + ) + if err := a.Run(); err != nil { + log.Fatal() } - agent := core.NewAgent(core.Inject(&flavor, &exampleFlavor)) - - core.EventLoopWithInterrupt(agent, exampleFinished) } +// PluginName represents name of plugin. +const PluginName = "govpp-example" + // ExamplePlugin implements Plugin interface which is used to pass custom plugin instances to the Agent. type ExamplePlugin struct { Deps - VPP vpp.API - exampleIDSeq uint32 // Plugin-specific ID initialization vppChannel govppapi.Channel // Vpp channel to communicate with VPP // Fields below are used to properly finish the example. - closeChannel *chan struct{} + closeChannel chan struct{} + Log logging.Logger +} + +// Deps is example plugin dependencies. +type Deps struct { + GoVppMux *govppmux.Plugin + VPP *vpp.Plugin } // Init members of plugin. func (plugin *ExamplePlugin) Init() (err error) { // NewAPIChannel returns a new API channel for communication with VPP via govpp core. // It uses default buffer sizes for the request and reply Go channels. - plugin.vppChannel, err = plugin.GoVppmux.NewAPIChannel() + plugin.vppChannel, err = plugin.Deps.GoVppMux.NewAPIChannel() plugin.Log.Info("Default plugin plugin ready") - //plugin.VPP.DisableResync(l2.BridgeDomainKeyPrefix()) + plugin.VPP.DisableResync(l2.BdPrefix) // Make VPP call go plugin.VppCall() @@ -87,7 +114,12 @@ func (plugin *ExamplePlugin) Init() (err error) { // Close is called by Agent Core when the Agent is shutting down. It is supposed // to clean up resources that were allocated by the plugin during its lifetime. func (plugin *ExamplePlugin) Close() error { - return safeclose.Close(plugin.GoVppmux, plugin.vppChannel) + return safeclose.Close(plugin.vppChannel) +} + +// String returns plugin name +func (plugin *ExamplePlugin) String() string { + return PluginName } /*********** @@ -132,7 +164,7 @@ func (plugin *ExamplePlugin) VppCall() { plugin.Log.Info("Data successfully sent to VPP") // End the example. plugin.Log.Infof("etcd/datasync example finished, sending shutdown ...") - *plugin.closeChannel <- struct{}{} + close(plugin.closeChannel) } // Auxiliary function to build bridge domain data diff --git a/examples/grpc_vpp/notifications/main.go b/examples/grpc_vpp/notifications/main.go index 0a8194a393..1d9c7e5b9a 100644 --- a/examples/grpc_vpp/notifications/main.go +++ b/examples/grpc_vpp/notifications/main.go @@ -15,17 +15,16 @@ package main import ( + "fmt" "io" + "log" + "net" "os" "time" - "fmt" - "net" - - "github.com/ligato/cn-infra/core" - "github.com/ligato/cn-infra/flavors/local" + "github.com/ligato/cn-infra/agent" "github.com/ligato/cn-infra/logging" - log "github.com/ligato/cn-infra/logging/logrus" + "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/plugins/vpp/model/rpc" "github.com/namsral/flag" "golang.org/x/net/context" @@ -46,29 +45,30 @@ var ( // init sets the default logging level func init() { - log.DefaultLogger().SetOutput(os.Stdout) - log.DefaultLogger().SetLevel(logging.DebugLevel) + logrus.DefaultLogger().SetOutput(os.Stdout) + logrus.DefaultLogger().SetLevel(logging.DebugLevel) } // Start Agent plugins selected for this example. func main() { - // Init close channel to stop the example. - closeChannel := make(chan struct{}, 1) - flag.StringVar(&address, "address", defaultAddress, "address of GRPC server") flag.StringVar(&socketType, "socket-type", defaultSocket, "[tcp, tcp4, tcp6, unix, unixpacket]") flag.IntVar(&reqPer, "request-period", requestPeriod, "notification request period in seconds") - // Example plugin - agent := local.NewAgent(local.WithPlugins(func(flavor *local.FlavorLocal) []*core.NamedPlugin { - examplePlugin := &core.NamedPlugin{PluginName: "example-plugin", Plugin: &ExamplePlugin{}} - - return []*core.NamedPlugin{{examplePlugin.PluginName, examplePlugin}} - })) - - core.EventLoopWithInterrupt(agent, closeChannel) + // Inject dependencies to example plugin + ep := &ExamplePlugin{} + // Start Agent + a := agent.NewAgent( + agent.AllPlugins(ep), + ) + if err := a.Run(); err != nil { + log.Fatal() + } } +// PluginName represents name of plugin. +const PluginName = "grpc-notification-example" + // ExamplePlugin demonstrates the use of grpc to watch on VPP notifications using vpp-agent. type ExamplePlugin struct { conn *grpc.ClientConn @@ -92,7 +92,7 @@ func (plugin *ExamplePlugin) Init() (err error) { // Start notification watcher. go plugin.watchNotifications() - log.DefaultLogger().Info("Initialization of the example plugin has completed") + logrus.DefaultLogger().Info("Initialization of the example plugin has completed") return err } @@ -101,6 +101,11 @@ func (plugin *ExamplePlugin) Close() error { return nil } +// String returns plugin name +func (plugin *ExamplePlugin) String() string { + return PluginName +} + // Get is an implementation of client-side statistics streaming. func (plugin *ExamplePlugin) watchNotifications() { var nextIdx uint32 = 1 @@ -115,28 +120,28 @@ func (plugin *ExamplePlugin) watchNotifications() { // Get stream object stream, err := client.Get(context.Background(), request) if err != nil { - log.DefaultLogger().Error(err) + logrus.DefaultLogger().Error(err) return } // Receive all message from the stream - log.DefaultLogger().Info("Sending request ... ") + logrus.DefaultLogger().Info("Sending request ... ") var recvNotifs int for { notif, err := stream.Recv() if err == io.EOF { if recvNotifs == 0 { - log.DefaultLogger().Info("No new notifications") + logrus.DefaultLogger().Info("No new notifications") } else { - log.DefaultLogger().Infof("%d new notifications received", recvNotifs) + logrus.DefaultLogger().Infof("%d new notifications received", recvNotifs) } break } if err != nil { - log.DefaultLogger().Error(err) + logrus.DefaultLogger().Error(err) return } - log.DefaultLogger().Infof("(IDX: %d) Received notif: %v", + logrus.DefaultLogger().Infof("(IDX: %d) Received notif: %v", notif.NextIdx-1, notif.NIf) nextIdx = notif.NextIdx recvNotifs++ diff --git a/examples/grpc_vpp/remote_client/main.go b/examples/grpc_vpp/remote_client/main.go index e63b64cb83..f7f8335317 100644 --- a/examples/grpc_vpp/remote_client/main.go +++ b/examples/grpc_vpp/remote_client/main.go @@ -16,15 +16,14 @@ package main import ( "context" + "log" "net" "os" "sync" "time" - "github.com/ligato/cn-infra/core" - "github.com/ligato/cn-infra/flavors/local" "github.com/ligato/cn-infra/logging" - log "github.com/ligato/cn-infra/logging/logrus" + "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/cn-infra/utils/safeclose" "github.com/ligato/vpp-agent/clientv1/vpp/remoteclient" "github.com/ligato/vpp-agent/plugins/vpp/model/acl" @@ -35,6 +34,7 @@ import ( "fmt" + "github.com/ligato/cn-infra/agent" "github.com/namsral/flag" "google.golang.org/grpc" ) @@ -49,8 +49,8 @@ var socketType string // init sets the default logging level func init() { - log.DefaultLogger().SetOutput(os.Stdout) - log.DefaultLogger().SetLevel(logging.DebugLevel) + logrus.DefaultLogger().SetOutput(os.Stdout) + logrus.DefaultLogger().SetLevel(logging.DebugLevel) } /******** @@ -59,38 +59,41 @@ func init() { // Start Agent plugins selected for this example. func main() { - // Init close channel to stop the example. - closeChannel := make(chan struct{}, 1) - flag.StringVar(&address, "address", defaultAddress, "address of GRPC server") flag.StringVar(&socketType, "socket-type", defaultSocket, "socket type [tcp, tcp4, tcp6, unix, unixpacket]") - // Example plugin - agent := local.NewAgent(local.WithPlugins(func(flavor *local.FlavorLocal) []*core.NamedPlugin { - examplePlugin := &core.NamedPlugin{PluginName: PluginID, Plugin: &ExamplePlugin{}} - - return []*core.NamedPlugin{{examplePlugin.PluginName, examplePlugin}} - })) + //Init close channel to stop the example. + exampleFinished := make(chan struct{}, 1) + + // Inject dependencies to example plugin + ep := &ExamplePlugin{} + // Start Agent + a := agent.NewAgent( + agent.AllPlugins(ep), + agent.QuitOnClose(exampleFinished), + ) + if err := a.Run(); err != nil { + log.Fatal() + } // End when the localhost example is finished. - go closeExample("localhost example finished", closeChannel) + go closeExample("localhost example finished", exampleFinished) - core.EventLoopWithInterrupt(agent, closeChannel) } // Stop the agent with desired info message. -func closeExample(message string, closeChannel chan struct{}) { +func closeExample(message string, exampleFinished chan struct{}) { time.Sleep(25 * time.Second) - log.DefaultLogger().Info(message) - closeChannel <- struct{}{} + logrus.DefaultLogger().Info(message) + close(exampleFinished) } /****************** * Example plugin * ******************/ -// PluginID of example plugin -const PluginID core.PluginName = "example-plugin" +// PluginName represents name of plugin. +const PluginName = "grpc-config-example" // ExamplePlugin demonstrates the use of the remoteclient to locally transport example configuration into the default VPP plugins. type ExamplePlugin struct { @@ -119,7 +122,7 @@ func (plugin *ExamplePlugin) Init() (err error) { plugin.wg.Add(1) go plugin.reconfigureVPP(ctx) - log.DefaultLogger().Info("Initialization of the example plugin has completed") + logrus.DefaultLogger().Info("Initialization of the example plugin has completed") return nil } @@ -133,10 +136,15 @@ func (plugin *ExamplePlugin) Close() error { return err } - log.DefaultLogger().Info("Closed example plugin") + logrus.DefaultLogger().Info("Closed example plugin") return nil } +// String returns plugin name +func (plugin *ExamplePlugin) String() string { + return PluginName +} + // Dialer for unix domain socket func dialer(socket, address string, timeoutVal time.Duration) func(string, time.Duration) (net.Conn, error) { return func(addr string, timeout time.Duration) (net.Conn, error) { @@ -156,9 +164,9 @@ func (plugin *ExamplePlugin) resyncVPP() { StaticRoute(&routeThroughMemif1). Send().ReceiveReply() if err != nil { - log.DefaultLogger().Errorf("Failed to apply initial VPP configuration: %v", err) + logrus.DefaultLogger().Errorf("Failed to apply initial VPP configuration: %v", err) } else { - log.DefaultLogger().Info("Successfully applied initial VPP configuration") + logrus.DefaultLogger().Info("Successfully applied initial VPP configuration") } } @@ -186,13 +194,13 @@ func (plugin *ExamplePlugin) reconfigureVPP(ctx context.Context) { StaticRoute(0, dstNetAddr.String(), nextHopAddr.String()). /* remove the route going through memif1 */ Send().ReceiveReply() if err != nil { - log.DefaultLogger().Errorf("Failed to reconfigure VPP: %v", err) + logrus.DefaultLogger().Errorf("Failed to reconfigure VPP: %v", err) } else { - log.DefaultLogger().Info("Successfully reconfigured VPP") + logrus.DefaultLogger().Info("Successfully reconfigured VPP") } case <-ctx.Done(): // Cancel the scheduled re-configuration. - log.DefaultLogger().Info("Planned VPP re-configuration was canceled") + logrus.DefaultLogger().Info("Planned VPP re-configuration was canceled") } plugin.wg.Done() } diff --git a/examples/idx_bd_cache/deps.go b/examples/idx_bd_cache/deps.go deleted file mode 100644 index d5f70d1a0a..0000000000 --- a/examples/idx_bd_cache/deps.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2017 Cisco and/or its affiliates. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at: -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "github.com/ligato/cn-infra/core" - "github.com/ligato/cn-infra/datasync" - "github.com/ligato/cn-infra/datasync/kvdbsync" - "github.com/ligato/cn-infra/flavors/local" - "github.com/ligato/vpp-agent/flavors/vpp" -) - -// Deps is a helper struct which is grouping all dependencies injected to the plugin -type Deps struct { - Publisher datasync.KeyProtoValWriter // injected - Agent1 *kvdbsync.Plugin // injected - Agent2 *kvdbsync.Plugin // injected - local.PluginInfraDeps // injected -} - -// ExampleFlavor is a set of plugins required for the datasync example. -type ExampleFlavor struct { - // Local flavor to access to Infra (logger, service label, status check) - *vpp.Flavor - // Example plugin - IdxBdCacheExample ExamplePlugin - // Mark flavor as injected after Inject() - injected bool -} - -// Inject sets object references -func (ef *ExampleFlavor) Inject() (allReadyInjected bool) { - // Every flavor should be injected only once - if ef.injected { - return false - } - ef.injected = true - - // Init local flavor - if ef.Flavor == nil { - ef.Flavor = &vpp.Flavor{} - } - ef.Flavor.Inject() - - // Inject infra + transport (publisher, watcher) to example plugin - ef.IdxBdCacheExample.PluginInfraDeps = *ef.Flavor.InfraDeps("idx-bd-cache-example") - ef.IdxBdCacheExample.Publisher = &ef.ETCDDataSync - ef.IdxBdCacheExample.VPP = &ef.VPP - ef.IdxBdCacheExample.Agent1 = ef.Flavor.ETCDDataSync.OfDifferentAgent("agent1", ef) - ef.IdxBdCacheExample.Agent2 = ef.Flavor.ETCDDataSync.OfDifferentAgent("agent2", ef) - - return true -} - -// Plugins combines all Plugins in flavor to the list -func (ef *ExampleFlavor) Plugins() []*core.NamedPlugin { - ef.Inject() - return core.ListPluginsInFlavor(ef) -} diff --git a/examples/idx_bd_cache/main.go b/examples/idx_bd_cache/main.go index 2d453a67a6..9a7f94494b 100644 --- a/examples/idx_bd_cache/main.go +++ b/examples/idx_bd_cache/main.go @@ -15,58 +15,105 @@ package main import ( - "github.com/ligato/cn-infra/core" + "github.com/ligato/cn-infra/agent" + "github.com/ligato/cn-infra/datasync" + "github.com/ligato/cn-infra/datasync/kvdbsync" + "github.com/ligato/cn-infra/db/keyval/etcd" + "github.com/ligato/cn-infra/logging" + "github.com/ligato/cn-infra/servicelabel" "github.com/ligato/cn-infra/utils/safeclose" - vppFlavor "github.com/ligato/vpp-agent/flavors/vpp" "github.com/ligato/vpp-agent/plugins/vpp" "github.com/ligato/vpp-agent/plugins/vpp/l2plugin/l2idx" "github.com/ligato/vpp-agent/plugins/vpp/model/l2" - "github.com/ligato/vpp-agent/tests/go/itest/l2tst" + "log" ) +const agent1, agent2 = "agent1", "agent2" + // Start Agent plugins selected for this example. func main() { - // Init close channel to stop the example. - exampleFinished := make(chan struct{}, 1) - - // Start Agent with VPP Flavor and ExampleFlavor. - flavor := vppFlavor.Flavor{} - exampleFlavor := ExampleFlavor{ - IdxBdCacheExample: ExamplePlugin{closeChannel: &exampleFinished}, - Flavor: &flavor, // inject VPP flavor + // Agent 1 datasync plugin + serviceLabel1 := servicelabel.NewPlugin(servicelabel.UseLabel(agent1)) + serviceLabel1.SetName(agent1) + etcdDataSyncAgent1 := kvdbsync.NewPlugin(kvdbsync.UseKV(&etcd.DefaultPlugin), kvdbsync.UseDeps(func(deps *kvdbsync.Deps) { + deps.Log = logging.ForPlugin(agent1) + deps.ServiceLabel = serviceLabel1 + })) + etcdDataSyncAgent1.SetName("etcd-datasync-" + agent1) + + // Agent 2 datasync plugin + serviceLabel2 := servicelabel.NewPlugin(servicelabel.UseLabel(agent2)) + serviceLabel2.SetName(agent2) + etcdDataSyncAgent2 := kvdbsync.NewPlugin(kvdbsync.UseKV(&etcd.DefaultPlugin), kvdbsync.UseDeps(func(deps *kvdbsync.Deps) { + deps.Log = logging.ForPlugin(agent2) + deps.ServiceLabel = serviceLabel2 + })) + etcdDataSyncAgent2.SetName("etcd-datasync-" + agent2) + + // Example plugin datasync + etcdDataSync := kvdbsync.NewPlugin(kvdbsync.UseKV(&etcd.DefaultPlugin)) + + // VPP plugin + watcher := datasync.KVProtoWatchers{ + etcdDataSync, + } + vppPlugin := vpp.NewPlugin(vpp.UseDeps(func(deps *vpp.Deps) { + deps.Watcher = watcher + })) + + // Inject dependencies to example plugin + ep := &ExamplePlugin{ + exampleFinished: make(chan struct{}), + Deps: Deps{ + Log: logging.DefaultLogger, + ETCDDataSync: etcdDataSync, + VPP: vppPlugin, + Agent1: etcdDataSyncAgent1, + Agent2: etcdDataSyncAgent2, + }, } - agent := core.NewAgent(core.Inject(&flavor, &exampleFlavor)) - core.EventLoopWithInterrupt(agent, exampleFinished) + // Start Agent + a := agent.NewAgent( + agent.AllPlugins(ep), + agent.QuitOnClose(ep.exampleFinished), + ) + if err := a.Run(); err != nil { + log.Fatal() + } } +// PluginName represents name of plugin. +const PluginName = "idx-bd-cache-example" + // ExamplePlugin is used for demonstration of Bridge Domain Indexes - see Init(). type ExamplePlugin struct { Deps - // Linux plugin dependency - VPP vpp.API - bdIdxLocal l2idx.BDIndex bdIdxAgent1 l2idx.BDIndex bdIdxAgent2 l2idx.BDIndex // Fields below are used to properly finish the example. - closeChannel *chan struct{} + exampleFinished chan struct{} +} + +// Deps is a helper struct which is grouping all dependencies injected to the plugin +type Deps struct { + Log logging.Logger + ETCDDataSync datasync.KeyProtoValWriter + VPP vpp.API + Agent1 *kvdbsync.Plugin + Agent2 *kvdbsync.Plugin +} + +// String returns plugin name +func (plugin *ExamplePlugin) String() string { + return PluginName } // Init transport & bdIndexes, then watch, publish & lookup func (plugin *ExamplePlugin) Init() (err error) { - // Manually initialize 'other' agents (for example purpose only). - err = plugin.Agent1.Init() - if err != nil { - return err - } - err = plugin.Agent2.Init() - if err != nil { - return err - } - // Get access to local bridge domain indexes. plugin.bdIdxLocal = plugin.VPP.GetBDIndexes() @@ -84,16 +131,6 @@ func (plugin *ExamplePlugin) Init() (err error) { // AfterInit - call Cache() func (plugin *ExamplePlugin) AfterInit() error { - // Manually run AfterInit() on 'other' agents (for example purpose only). - err := plugin.Agent1.AfterInit() - if err != nil { - return err - } - err = plugin.Agent2.AfterInit() - if err != nil { - return err - } - // Publish test data plugin.publish() @@ -103,27 +140,27 @@ func (plugin *ExamplePlugin) AfterInit() error { // Close is called by Agent Core when the Agent is shutting down. It is supposed // to clean up resources that were allocated by the plugin during its lifetime. func (plugin *ExamplePlugin) Close() error { - return safeclose.Close(plugin.Agent1, plugin.Agent2, plugin.Publisher, plugin.Agent1, plugin.Agent2, - plugin.bdIdxLocal, plugin.bdIdxAgent1, plugin.bdIdxAgent2, plugin.closeChannel) + return safeclose.Close(plugin.Agent1, plugin.Agent2, plugin.ETCDDataSync, plugin.bdIdxLocal, plugin.bdIdxAgent1, + plugin.bdIdxAgent2) } // Test data are published to different agents (including local). func (plugin *ExamplePlugin) publish() (err error) { // Create bridge domain in local agent. - br0 := l2tst.SimpleBridgeDomain1XIfaceBuilder("bd0", "iface0", true) - err = plugin.Publisher.Put(l2.BridgeDomainKey(br0.Name), &br0) + br0 := newExampleBridgeDomain("bd0", "iface0") + err = plugin.ETCDDataSync.Put(l2.BridgeDomainKey(br0.Name), br0) if err != nil { return err } // Create bridge domain in agent1 - br1 := l2tst.SimpleBridgeDomain1XIfaceBuilder("bd1", "iface1", true) - err = plugin.Agent1.Put(l2.BridgeDomainKey(br1.Name), &br1) + br1 := newExampleBridgeDomain("bd1", "iface1") + err = plugin.Agent1.Put(l2.BridgeDomainKey(br1.Name), br1) if err != nil { return err } // Create bridge domain in agent2 - br2 := l2tst.SimpleBridgeDomain1XIfaceBuilder("bd2", "iface2", true) - err = plugin.Agent2.Put(l2.BridgeDomainKey(br2.Name), &br2) + br2 := newExampleBridgeDomain("bd2", "iface2") + err = plugin.Agent2.Put(l2.BridgeDomainKey(br2.Name), br2) return err } @@ -132,9 +169,9 @@ func (plugin *ExamplePlugin) consume() { plugin.Log.Info("Watching started") bdIdxChan := make(chan l2idx.BdChangeDto) // Subscribe local bd-idx-mapping and both of cache mapping. - plugin.bdIdxLocal.WatchNameToIdx(plugin.PluginName, bdIdxChan) - plugin.bdIdxAgent1.WatchNameToIdx(plugin.PluginName, bdIdxChan) - plugin.bdIdxAgent2.WatchNameToIdx(plugin.PluginName, bdIdxChan) + plugin.bdIdxLocal.WatchNameToIdx(PluginName, bdIdxChan) + plugin.bdIdxAgent1.WatchNameToIdx(PluginName, bdIdxChan) + plugin.bdIdxAgent2.WatchNameToIdx(PluginName, bdIdxChan) counter := 0 @@ -173,5 +210,17 @@ func (plugin *ExamplePlugin) lookup() { // End the example. plugin.Log.Infof("idx-bd-cache example finished, sending shutdown ...") - *plugin.closeChannel <- struct{}{} + close(plugin.exampleFinished) +} + +func newExampleBridgeDomain(bdName, ifName string) *l2.BridgeDomains_BridgeDomain { + return &l2.BridgeDomains_BridgeDomain{ + Name: bdName, + Interfaces: []*l2.BridgeDomains_BridgeDomain_Interfaces{ + { + Name: ifName, + BridgedVirtualInterface: true, + }, + }, + } } diff --git a/examples/idx_iface_cache/deps.go b/examples/idx_iface_cache/deps.go deleted file mode 100644 index 1009be1d30..0000000000 --- a/examples/idx_iface_cache/deps.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2017 Cisco and/or its affiliates. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at: -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "github.com/ligato/cn-infra/core" - "github.com/ligato/cn-infra/datasync" - "github.com/ligato/cn-infra/datasync/kvdbsync" - "github.com/ligato/cn-infra/flavors/local" - "github.com/ligato/vpp-agent/flavors/vpp" -) - -// Deps is a helper struct which is grouping all dependencies injected to the plugin -type Deps struct { - Publisher datasync.KeyProtoValWriter // injected - Agent1 *kvdbsync.Plugin // injected - Agent2 *kvdbsync.Plugin // injected - local.PluginInfraDeps // injected -} - -// ExampleFlavor is a set of plugins required for the datasync example. -type ExampleFlavor struct { - // Local flavor to access to Infra (logger, service label, status check) - *vpp.Flavor - // Example plugin - IdxIfaceCacheExample ExamplePlugin - // Mark flavor as injected after Inject() - injected bool -} - -// Inject sets object references -func (ef *ExampleFlavor) Inject() (allReadyInjected bool) { - // Every flavor should be injected only once - if ef.injected { - return false - } - ef.injected = true - - // Init local flavor - if ef.Flavor == nil { - ef.Flavor = &vpp.Flavor{} - } - ef.Flavor.Inject() - - // Inject infra + transport (publisher, watcher) to example plugin - ef.IdxIfaceCacheExample.PluginInfraDeps = *ef.Flavor.InfraDeps("idx-iface-cache-example") - ef.IdxIfaceCacheExample.Publisher = &ef.ETCDDataSync - ef.IdxIfaceCacheExample.VPP = &ef.VPP - ef.IdxIfaceCacheExample.Agent1 = ef.Flavor.ETCDDataSync.OfDifferentAgent("agent1", ef) - ef.IdxIfaceCacheExample.Agent2 = ef.Flavor.ETCDDataSync.OfDifferentAgent("agent2", ef) - - return true -} - -// Plugins combines all Plugins in flavor to the list -func (ef *ExampleFlavor) Plugins() []*core.NamedPlugin { - ef.Inject() - return core.ListPluginsInFlavor(ef) -} diff --git a/examples/idx_iface_cache/main.go b/examples/idx_iface_cache/main.go index faf709a7cc..5fdc1fa707 100644 --- a/examples/idx_iface_cache/main.go +++ b/examples/idx_iface_cache/main.go @@ -15,58 +15,105 @@ package main import ( - "github.com/ligato/cn-infra/core" + "github.com/ligato/cn-infra/agent" + "github.com/ligato/cn-infra/datasync" + "github.com/ligato/cn-infra/datasync/kvdbsync" + "github.com/ligato/cn-infra/db/keyval/etcd" + "github.com/ligato/cn-infra/logging" + "github.com/ligato/cn-infra/servicelabel" "github.com/ligato/cn-infra/utils/safeclose" - vppFlavor "github.com/ligato/vpp-agent/flavors/vpp" "github.com/ligato/vpp-agent/plugins/vpp" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" - "github.com/ligato/vpp-agent/tests/go/itest/iftst" + "log" ) +const agent1, agent2 = "agent1", "agent2" + // Start Agent plugins selected for this example. func main() { - // Init close channel to stop the example. - exampleFinished := make(chan struct{}, 1) - - // Start Agent with ExampleFlavor. - flavor := vppFlavor.Flavor{} - exampleFlavor := ExampleFlavor{ - IdxIfaceCacheExample: ExamplePlugin{closeChannel: &exampleFinished}, - Flavor: &flavor, // inject VPP flavor + // Agent 1 datasync plugin + serviceLabel1 := servicelabel.NewPlugin(servicelabel.UseLabel(agent1)) + serviceLabel1.SetName(agent1) + etcdDataSyncAgent1 := kvdbsync.NewPlugin(kvdbsync.UseKV(&etcd.DefaultPlugin), kvdbsync.UseDeps(func(deps *kvdbsync.Deps) { + deps.Log = logging.ForPlugin(agent1) + deps.ServiceLabel = serviceLabel1 + })) + etcdDataSyncAgent1.SetName("etcd-datasync-" + agent1) + + // Agent 2 datasync plugin + serviceLabel2 := servicelabel.NewPlugin(servicelabel.UseLabel(agent2)) + serviceLabel2.SetName(agent2) + etcdDataSyncAgent2 := kvdbsync.NewPlugin(kvdbsync.UseKV(&etcd.DefaultPlugin), kvdbsync.UseDeps(func(deps *kvdbsync.Deps) { + deps.Log = logging.ForPlugin(agent2) + deps.ServiceLabel = serviceLabel2 + })) + etcdDataSyncAgent2.SetName("etcd-datasync-" + agent2) + + // Example plugin datasync + etcdDataSync := kvdbsync.NewPlugin(kvdbsync.UseKV(&etcd.DefaultPlugin)) + + // VPP plugin + watcher := datasync.KVProtoWatchers{ + etcdDataSync, + } + vppPlugin := vpp.NewPlugin(vpp.UseDeps(func(deps *vpp.Deps) { + deps.Watcher = watcher + })) + + // Inject dependencies to example plugin + ep := &ExamplePlugin{ + exampleFinished: make(chan struct{}), + Deps: Deps{ + Log: logging.DefaultLogger, + ETCDDataSync: etcdDataSync, + VPP: vppPlugin, + Agent1: etcdDataSyncAgent1, + Agent2: etcdDataSyncAgent2, + }, } - agent := core.NewAgent(core.Inject(&flavor, &exampleFlavor)) - core.EventLoopWithInterrupt(agent, exampleFinished) + // Start Agent + a := agent.NewAgent( + agent.AllPlugins(ep), + agent.QuitOnClose(ep.exampleFinished), + ) + if err := a.Run(); err != nil { + log.Fatal() + } } +// PluginName represents name of plugin. +const PluginName = "idx-iface-cache-example" + // ExamplePlugin used for demonstration of SwIfIndexes - see Init() type ExamplePlugin struct { Deps - // Linux plugin dependency - VPP vpp.API - swIfIdxLocal ifaceidx.SwIfIndex swIfIdxAgent1 ifaceidx.SwIfIndex swIfIdxAgent2 ifaceidx.SwIfIndex // Fields below are used to properly finish the example. - closeChannel *chan struct{} + exampleFinished chan struct{} +} + +// Deps is a helper struct which is grouping all dependencies injected to the plugin +type Deps struct { + Log logging.Logger + ETCDDataSync *kvdbsync.Plugin + VPP vpp.API + Agent1 *kvdbsync.Plugin + Agent2 *kvdbsync.Plugin +} + +// String returns plugin name +func (plugin *ExamplePlugin) String() string { + return PluginName } // Init initializes transport & SwIfIndexes then watch, publish & lookup. func (plugin *ExamplePlugin) Init() (err error) { - // Manually initialize 'other' agents (for the example purpose only). - err = plugin.Agent1.Init() - if err != nil { - return err - } - err = plugin.Agent2.Init() - if err != nil { - return err - } - // Get access to local interface indexes. plugin.swIfIdxLocal = plugin.VPP.GetSwIfIndexes() @@ -84,16 +131,6 @@ func (plugin *ExamplePlugin) Init() (err error) { // AfterInit - call Cache() func (plugin *ExamplePlugin) AfterInit() error { - // Manually run AfterInit() on 'other' agents (for example purpose only). - err := plugin.Agent1.AfterInit() - if err != nil { - return err - } - err = plugin.Agent2.AfterInit() - if err != nil { - return err - } - // Publish test data. plugin.publish() @@ -103,27 +140,27 @@ func (plugin *ExamplePlugin) AfterInit() error { // Close is called by Agent Core when the Agent is shutting down. It is supposed // to clean up resources that were allocated by the plugin during its lifetime. func (plugin *ExamplePlugin) Close() error { - return safeclose.Close(plugin.Agent1, plugin.Agent2, plugin.Publisher, plugin.Agent1, plugin.Agent2, - plugin.swIfIdxLocal, plugin.swIfIdxAgent1, plugin.swIfIdxAgent2, plugin.closeChannel) + return safeclose.Close(plugin.Agent1, plugin.Agent2, plugin.swIfIdxLocal, plugin.swIfIdxAgent1, + plugin.swIfIdxAgent2) } // Test data are published to different agents (including local). func (plugin *ExamplePlugin) publish() (err error) { // Create interface in local agent. - iface0 := iftst.TapInterfaceBuilder("iface0", "192.168.1.1") - err = plugin.Publisher.Put(interfaces.InterfaceKey(iface0.Name), &iface0) + iface0 := newExampleInterface("iface0", "192.168.0.1") + err = plugin.ETCDDataSync.Put(interfaces.InterfaceKey(iface0.Name), iface0) if err != nil { return err } // Create interface in agent1. - iface1 := iftst.TapInterfaceBuilder("iface1", "192.168.0.2") - err = plugin.Agent1.Put(interfaces.InterfaceKey(iface1.Name), &iface1) + iface1 := newExampleInterface("iface1", "192.168.0.2") + err = plugin.Agent1.Put(interfaces.InterfaceKey(iface1.Name), iface1) if err != nil { return err } // Create interface in agent2. - iface2 := iftst.TapInterfaceBuilder("iface2", "192.168.0.3") - err = plugin.Agent2.Put(interfaces.InterfaceKey(iface2.Name), &iface2) + iface2 := newExampleInterface("iface2", "192.168.0.3") + err = plugin.Agent2.Put(interfaces.InterfaceKey(iface2.Name), iface2) return err } @@ -132,9 +169,9 @@ func (plugin *ExamplePlugin) consume() { plugin.Log.Info("Watching started") swIfIdxChan := make(chan ifaceidx.SwIfIdxDto) // Subscribe local iface-idx-mapping and both of cache mapping. - plugin.swIfIdxLocal.WatchNameToIdx(plugin.PluginName, swIfIdxChan) - plugin.swIfIdxAgent1.WatchNameToIdx(plugin.PluginName, swIfIdxChan) - plugin.swIfIdxAgent2.WatchNameToIdx(plugin.PluginName, swIfIdxChan) + plugin.swIfIdxLocal.WatchNameToIdx(PluginName, swIfIdxChan) + plugin.swIfIdxAgent1.WatchNameToIdx(PluginName, swIfIdxChan) + plugin.swIfIdxAgent2.WatchNameToIdx(PluginName, swIfIdxChan) counter := 0 @@ -173,5 +210,13 @@ func (plugin *ExamplePlugin) lookup() { // End the example. plugin.Log.Infof("idx-iface-cache example finished, sending shutdown ...") - *plugin.closeChannel <- struct{}{} + close(plugin.exampleFinished) +} + +func newExampleInterface(ifName, ipAddr string) *interfaces.Interfaces_Interface { + return &interfaces.Interfaces_Interface{ + Name: ifName, + Enabled: true, + IpAddresses: []string{ipAddr}, + } } diff --git a/examples/idx_mapping_lookup/main.go b/examples/idx_mapping_lookup/main.go index 329b13d3d3..2bb93c5765 100644 --- a/examples/idx_mapping_lookup/main.go +++ b/examples/idx_mapping_lookup/main.go @@ -15,8 +15,10 @@ package main import ( - "github.com/ligato/cn-infra/core" - "github.com/ligato/cn-infra/flavors/local" + "log" + + "github.com/ligato/cn-infra/agent" + "github.com/ligato/cn-infra/logging" "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/idxvpp" "github.com/ligato/vpp-agent/idxvpp/nametoidx" @@ -32,28 +34,32 @@ import ( // required for the example are initialized. Agent is instantiated with generic plugins (etcd, Kafka, Status check, // HTTP and Log) and example plugin which demonstrates index mapping lookup functionality. func main() { - // Init close channel to stop the example - exampleFinished := make(chan struct{}, 1) + ep := &ExamplePlugin{ + Log: logging.DefaultLogger, + exampleFinished: make(chan struct{}), + } // Start Agent - agent := local.NewAgent(local.WithPlugins(func(flavor *local.FlavorLocal) []*core.NamedPlugin { - examplePlug := &ExamplePlugin{closeChannel: &exampleFinished} - examplePlug.PluginLogDeps = *flavor.LogDeps("idx-mapping-lookup") - - return []*core.NamedPlugin{{examplePlug.PluginName, examplePlug}} - })) - - core.EventLoopWithInterrupt(agent, exampleFinished) + a := agent.NewAgent( + agent.AllPlugins(ep), + agent.QuitOnClose(ep.exampleFinished), + ) + if err := a.Run(); err != nil { + log.Fatal() + } } +// PluginName represents name of plugin. +const PluginName = "idx-mapping-lookup" + // ExamplePlugin implements Plugin interface which is used to pass custom plugin instances to the Agent. type ExamplePlugin struct { - Deps - exampleIdx idxvpp.NameToIdxRW // Name to index mapping registry exampleIDSeq uint32 // Provides unique ID for every item stored in mapping // Fields below are used to properly finish the example. - closeChannel *chan struct{} + exampleFinished chan struct{} + + Log logging.Logger } // Init is the entry point into the plugin that is called by Agent Core when the Agent is coming up. @@ -73,11 +79,21 @@ func (plugin *ExamplePlugin) Init() (err error) { // End the example. plugin.Log.Infof("idx-mapping-lookup example finished, sending shutdown ...") - *plugin.closeChannel <- struct{}{} + close(plugin.exampleFinished) return err } +// Close cleans up the resources. +func (plugin *ExamplePlugin) Close() error { + return nil +} + +// String returns plugin name +func (plugin *ExamplePlugin) String() string { + return PluginName +} + // Meta structure. It can contain any number of fields of different types. Metadata is optional and can be nil. type Meta struct { ip string diff --git a/examples/idx_mapping_watcher/main.go b/examples/idx_mapping_watcher/main.go index 5b5cad9a28..bb1fe3b595 100644 --- a/examples/idx_mapping_watcher/main.go +++ b/examples/idx_mapping_watcher/main.go @@ -17,10 +17,13 @@ package main import ( "strconv" - "github.com/ligato/cn-infra/core" + "log" + + "github.com/ligato/cn-infra/agent" "github.com/ligato/cn-infra/datasync" - "github.com/ligato/cn-infra/flavors/local" + "github.com/ligato/cn-infra/logging" "github.com/ligato/cn-infra/logging/logrus" + "github.com/ligato/cn-infra/utils/safeclose" "github.com/ligato/vpp-agent/idxvpp" "github.com/ligato/vpp-agent/idxvpp/nametoidx" ) @@ -42,31 +45,34 @@ const expectedEvents = 5 // required for the example are initialized. The Agent is instantiated with generic plugins (etcd, Kafka, Status check, // HTTP and Log) and example plugin which demonstrates index mapping watcher functionality. func main() { - // Init close channel to stop the example - exampleFinished := make(chan struct{}, 1) + ep := &ExamplePlugin{ + Log: logging.DefaultLogger, + exampleFinished: make(chan struct{}), + } // Start Agent - agent := local.NewAgent(local.WithPlugins(func(flavor *local.FlavorLocal) []*core.NamedPlugin { - examplePlug := &ExamplePlugin{closeChannel: &exampleFinished} - examplePlug.PluginLogDeps = *flavor.LogDeps("idx-watch-example") - - return []*core.NamedPlugin{{examplePlug.PluginName, examplePlug}} - })) - - core.EventLoopWithInterrupt(agent, exampleFinished) + a := agent.NewAgent( + agent.AllPlugins(ep), + agent.QuitOnClose(ep.exampleFinished), + ) + if err := a.Run(); err != nil { + log.Fatal() + } } +// PluginName represents name of plugin. +const PluginName = "idx-mapping-watcher" + // ExamplePlugin implements Plugin interface which is used to pass custom plugin instances to the Agent. type ExamplePlugin struct { - Deps - exampleIdx idxvpp.NameToIdxRW // Name-to-index mapping exampleIDSeq uint32 // Unique ID exIdxWatchChannel chan idxvpp.NameToIdxDto // Channel to watch changes in mapping watchDataReg datasync.WatchRegistration // To subscribe to mapping change events // Fields below are used to properly finish the example - eventCounter uint8 - closeChannel *chan struct{} + eventCounter uint8 + exampleFinished chan struct{} + Log logging.Logger } // Init is the entry point into the plugin that is called by Agent Core when the Agent is coming up. @@ -91,11 +97,21 @@ func (plugin *ExamplePlugin) Init() (err error) { }() // Subscribe name-to-index watcher. - plugin.exampleIdx.Watch(plugin.PluginName, nametoidx.ToChan(plugin.exIdxWatchChannel)) + plugin.exampleIdx.Watch(PluginName, nametoidx.ToChan(plugin.exIdxWatchChannel)) return err } +// Close cleans up the resources. +func (plugin *ExamplePlugin) Close() error { + return safeclose.Close(plugin.exIdxWatchChannel) +} + +// String returns plugin name +func (plugin *ExamplePlugin) String() string { + return PluginName +} + /************ * Register * ************/ @@ -135,7 +151,7 @@ func (plugin *ExamplePlugin) watchEvents() { // End the example when it is done (5 events are expected). if plugin.eventCounter == expectedEvents { plugin.Log.Infof("idx-watch-lookup example finished, sending shutdown ...") - *plugin.closeChannel <- struct{}{} + close(plugin.exampleFinished) } } } diff --git a/examples/idx_veth_cache/deps.go b/examples/idx_veth_cache/deps.go deleted file mode 100644 index 16bdded7e6..0000000000 --- a/examples/idx_veth_cache/deps.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2018 Cisco and/or its affiliates. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at: -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "github.com/ligato/cn-infra/core" - "github.com/ligato/cn-infra/datasync" - "github.com/ligato/cn-infra/datasync/kvdbsync" - "github.com/ligato/cn-infra/flavors/local" - "github.com/ligato/vpp-agent/flavors/vpp" -) - -// Deps is a helper struct which is grouping all dependencies injected to the plugin -type Deps struct { - Publisher datasync.KeyProtoValWriter // injected - Agent1 *kvdbsync.Plugin // injected - Agent2 *kvdbsync.Plugin // injected - local.PluginInfraDeps // injected -} - -// ExampleFlavor is a set of plugins required for the datasync example. -type ExampleFlavor struct { - // Local flavor to access to Infra (logger, service label, status check) - *vpp.Flavor - // Example plugin - IdxVethCacheExample ExamplePlugin - // Mark flavor as injected after Inject() - injected bool -} - -// Inject sets object references -func (ef *ExampleFlavor) Inject() (allReadyInjected bool) { - // Every flavor should be injected only once - if ef.injected { - return false - } - ef.injected = true - - // Init local flavor - if ef.Flavor == nil { - ef.Flavor = &vpp.Flavor{} - } - ef.Flavor.Inject() - - // Inject infra + transport (publisher, watcher) to example plugin - ef.IdxVethCacheExample.PluginInfraDeps = *ef.Flavor.InfraDeps("idx-veth-cache-example") - ef.IdxVethCacheExample.Linux = &ef.Linux - ef.IdxVethCacheExample.Publisher = &ef.ETCDDataSync - ef.IdxVethCacheExample.Agent1 = ef.Flavor.ETCDDataSync.OfDifferentAgent("agent1", ef) - ef.IdxVethCacheExample.Agent2 = ef.Flavor.ETCDDataSync.OfDifferentAgent("agent2", ef) - - return true -} - -// Plugins combines all Plugins in flavor to the list -func (ef *ExampleFlavor) Plugins() []*core.NamedPlugin { - ef.Inject() - return core.ListPluginsInFlavor(ef) -} diff --git a/examples/idx_veth_cache/main.go b/examples/idx_veth_cache/main.go index 2b540f22f0..82bf263d67 100644 --- a/examples/idx_veth_cache/main.go +++ b/examples/idx_veth_cache/main.go @@ -16,15 +16,20 @@ package main import ( "fmt" + "log" "os" "sync" "time" - "github.com/ligato/cn-infra/core" + "github.com/ligato/cn-infra/agent" + "github.com/ligato/cn-infra/datasync" + "github.com/ligato/cn-infra/datasync/kvdbsync" + "github.com/ligato/cn-infra/datasync/resync" + "github.com/ligato/cn-infra/db/keyval/etcd" "github.com/ligato/cn-infra/logging" - log "github.com/ligato/cn-infra/logging/logrus" + "github.com/ligato/cn-infra/logging/logrus" + "github.com/ligato/cn-infra/servicelabel" "github.com/ligato/cn-infra/utils/safeclose" - "github.com/ligato/vpp-agent/flavors/vpp" "github.com/ligato/vpp-agent/plugins/linux" linux_if "github.com/ligato/vpp-agent/plugins/linux/ifplugin/ifaceidx" linux_intf "github.com/ligato/vpp-agent/plugins/linux/model/interfaces" @@ -45,55 +50,97 @@ import ( // Init sets the default logging level. func init() { - log.DefaultLogger().SetOutput(os.Stdout) - log.DefaultLogger().SetLevel(logging.InfoLevel) + logrus.DefaultLogger().SetOutput(os.Stdout) + logrus.DefaultLogger().SetLevel(logging.InfoLevel) } +const agent1, agent2 = "agent1", "agent2" + // Start Agent plugins selected for this example. func main() { - // Init close channel to stop the example. - exampleFinished := make(chan struct{}, 1) - - // Start Agent with ExampleFlavor - vppFlavor := vpp.Flavor{} - exampleFlavor := ExampleFlavor{ - IdxVethCacheExample: ExamplePlugin{closeChannel: &exampleFinished}, - Flavor: &vppFlavor, // inject VPP flavor + // Agent 1 datasync plugin + serviceLabel1 := servicelabel.NewPlugin(servicelabel.UseLabel(agent1)) + serviceLabel1.SetName(agent1) + etcdDataSyncAgent1 := kvdbsync.NewPlugin(kvdbsync.UseKV(&etcd.DefaultPlugin), kvdbsync.UseDeps(func(deps *kvdbsync.Deps) { + deps.Log = logging.ForPlugin(agent1) + deps.ServiceLabel = serviceLabel1 + })) + etcdDataSyncAgent1.SetName("etcd-datasync-" + agent1) + + // Agent 2 datasync plugin + serviceLabel2 := servicelabel.NewPlugin(servicelabel.UseLabel(agent2)) + serviceLabel2.SetName(agent2) + etcdDataSyncAgent2 := kvdbsync.NewPlugin(kvdbsync.UseKV(&etcd.DefaultPlugin), kvdbsync.UseDeps(func(deps *kvdbsync.Deps) { + deps.Log = logging.ForPlugin(agent2) + deps.ServiceLabel = serviceLabel2 + })) + etcdDataSyncAgent2.SetName("etcd-datasync-" + agent2) + + // Example plugin datasync + etcdDataSync := kvdbsync.NewPlugin(kvdbsync.UseKV(&etcd.DefaultPlugin)) + + // Linux plugin + watcher := datasync.KVProtoWatchers{ + etcdDataSync, + } + linuxPlugin := linux.NewPlugin(linux.UseDeps(func(deps *linux.Deps) { + deps.Watcher = watcher + })) + + // Inject dependencies to example plugin + ep := &ExamplePlugin{ + exampleFinished: make(chan struct{}), + Deps: Deps{ + Log: logging.DefaultLogger, + ETCDDataSync: etcdDataSync, + Linux: linuxPlugin, + Agent1: etcdDataSyncAgent1, + Agent2: etcdDataSyncAgent2, + }, } - agent := core.NewAgent(core.Inject(&vppFlavor, &exampleFlavor)) - core.EventLoopWithInterrupt(agent, exampleFinished) + // Start Agent + a := agent.NewAgent( + agent.AllPlugins(ep), + agent.QuitOnClose(ep.exampleFinished), + ) + if err := a.Run(); err != nil { + log.Fatal() + } } +// PluginName represents name of plugin. +const PluginName = "idx-veth-cache-example" + // ExamplePlugin demonstrates the use of the name-to-idx cache in linux plugin. type ExamplePlugin struct { Deps - // Linux plugin dependency - Linux linux.API - linuxIfIdxLocal linux_if.LinuxIfIndex linuxIfIdxAgent1 linux_if.LinuxIfIndex linuxIfIdxAgent2 linux_if.LinuxIfIndex wg sync.WaitGroup // Fields below are used to properly finish the example. - closeChannel *chan struct{} + exampleFinished chan struct{} +} + +// Deps is a helper struct which is grouping all dependencies injected to the plugin +type Deps struct { + Log logging.Logger + ETCDDataSync *kvdbsync.Plugin + Linux *linux.Plugin + Agent1 *kvdbsync.Plugin + Agent2 *kvdbsync.Plugin +} + +// String returns plugin name +func (plugin *ExamplePlugin) String() string { + return PluginName } // Init initializes example plugin. func (plugin *ExamplePlugin) Init() error { - // Manually initialize 'other' agents (for example purpose only). - var err error - err = plugin.Agent1.Init() - if err != nil { - return err - } - err = plugin.Agent2.Init() - if err != nil { - return err - } - // Receive linux interfaces mapping. if plugin.Linux != nil { plugin.linuxIfIdxLocal = plugin.Linux.GetLinuxIfIndexes() @@ -108,22 +155,15 @@ func (plugin *ExamplePlugin) Init() error { plugin.linuxIfIdxAgent1 = linux_if.Cache(plugin.Agent1) plugin.linuxIfIdxAgent2 = linux_if.Cache(plugin.Agent2) - log.DefaultLogger().Info("Initialization of the example plugin has completed") + logrus.DefaultLogger().Info("Initialization of the example plugin has completed") - return err + return nil } // AfterInit - call Cache() func (plugin *ExamplePlugin) AfterInit() error { - // Manually run AfterInit() on 'other' agents (for example purpose only). - err := plugin.Agent1.AfterInit() - if err != nil { - return err - } - err = plugin.Agent2.AfterInit() - if err != nil { - return err - } + // Manually start resync (simulate vpp-agent default behaviour) + resync.DefaultPlugin.DoResync() // Publish test data. plugin.publish() @@ -135,13 +175,13 @@ func (plugin *ExamplePlugin) AfterInit() error { func (plugin *ExamplePlugin) Close() error { plugin.wg.Wait() - return safeclose.Close(plugin.Agent1, plugin.Agent2, plugin.Publisher, plugin.Agent1, plugin.Agent2, - plugin.linuxIfIdxLocal, plugin.linuxIfIdxAgent1, plugin.linuxIfIdxAgent2, plugin.closeChannel) + return safeclose.Close(plugin.Agent1, plugin.Agent2, plugin.Agent1, plugin.Agent2, + plugin.linuxIfIdxLocal, plugin.linuxIfIdxAgent1, plugin.linuxIfIdxAgent2) } // publish propagates example configuration to etcd. func (plugin *ExamplePlugin) publish() error { - log.DefaultLogger().Infof("Putting interfaces to ETCD") + logrus.DefaultLogger().Infof("Putting interfaces to ETCD") // VETH pair in default namespace vethDef := &veth11DefaultNs @@ -160,10 +200,10 @@ func (plugin *ExamplePlugin) publish() error { err = plugin.Agent2.Put(linux_intf.InterfaceKey(vethNs2Peer.Name), vethNs2Peer) if err != nil { - log.DefaultLogger().Errorf("Failed to apply initial Linux&VPP configuration: %v", err) + logrus.DefaultLogger().Errorf("Failed to apply initial Linux&VPP configuration: %v", err) return err } - log.DefaultLogger().Info("Successfully applied initial Linux&VPP configuration") + logrus.DefaultLogger().Info("Successfully applied initial Linux&VPP configuration") return err } @@ -174,9 +214,9 @@ func (plugin *ExamplePlugin) consume() (err error) { // Init chan to sent watch updates. linuxIfIdxChan := make(chan linux_if.LinuxIfIndexDto) // Register all agents (incl. local) to watch linux name-to-idx mapping changes. - plugin.linuxIfIdxLocal.WatchNameToIdx(plugin.PluginName, linuxIfIdxChan) - plugin.linuxIfIdxAgent1.WatchNameToIdx(plugin.PluginName, linuxIfIdxChan) - plugin.linuxIfIdxAgent2.WatchNameToIdx(plugin.PluginName, linuxIfIdxChan) + plugin.linuxIfIdxLocal.WatchNameToIdx(PluginName, linuxIfIdxChan) + plugin.linuxIfIdxAgent1.WatchNameToIdx(PluginName, linuxIfIdxChan) + plugin.linuxIfIdxAgent2.WatchNameToIdx(PluginName, linuxIfIdxChan) counter := 0 @@ -202,7 +242,7 @@ func (plugin *ExamplePlugin) consume() (err error) { // End the example. plugin.Log.Infof("idx-iface-cache example finished, sending shutdown ...") - *plugin.closeChannel <- struct{}{} + close(plugin.exampleFinished) return nil } @@ -219,17 +259,17 @@ func (plugin *ExamplePlugin) lookup() bool { // Look for loopback interface. if _, _, loopback = plugin.linuxIfIdxLocal.LookupIdx("lo"); loopback { - log.DefaultLogger().Info("Interface found: loopback") + logrus.DefaultLogger().Info("Interface found: loopback") } else { - log.DefaultLogger().Warn("Interface not found: loopback") + logrus.DefaultLogger().Warn("Interface not found: loopback") } // Look for VETH 11 default namespace interface on agent1. for i := 0; i <= 10; i++ { if _, _, veth11 = plugin.linuxIfIdxAgent1.LookupIdx(veth11DefaultNs.Name); veth11 { - log.DefaultLogger().Info("Interface found on agent1: veth11Def") + logrus.DefaultLogger().Info("Interface found on agent1: veth11Def") break } else if i == 3 { - log.DefaultLogger().Warn("Interface not found on agent1: veth11Def") + logrus.DefaultLogger().Warn("Interface not found on agent1: veth11Def") } else { // Try several times in case cache is not updated yet. time.Sleep(1 * time.Second) @@ -239,10 +279,10 @@ func (plugin *ExamplePlugin) lookup() bool { // Look for VETH 12 default namespace interface on agent1. for i := 0; i <= 3; i++ { if _, _, veth12 = plugin.linuxIfIdxAgent1.LookupIdx(veth12DefaultNs.Name); veth12 { - log.DefaultLogger().Info("Interface found on agent1: veth12Def") + logrus.DefaultLogger().Info("Interface found on agent1: veth12Def") break } else if i == 3 { - log.DefaultLogger().Warn("Interface not found on agent1: veth12Def") + logrus.DefaultLogger().Warn("Interface not found on agent1: veth12Def") } else { // Try several times in case cache is not updated yet. time.Sleep(1 * time.Second) @@ -252,10 +292,10 @@ func (plugin *ExamplePlugin) lookup() bool { // Look for VETH 21 ns1 namespace interface on agent2. for i := 0; i <= 3; i++ { if _, _, veth21 = plugin.linuxIfIdxAgent2.LookupIdx(veth21Ns1.Name); veth21 { - log.DefaultLogger().Info("Interface found on agent2: veth21ns1") + logrus.DefaultLogger().Info("Interface found on agent2: veth21ns1") break } else if i == 3 { - log.DefaultLogger().Warn("Interface not found on agent2 : veth21ns1") + logrus.DefaultLogger().Warn("Interface not found on agent2 : veth21ns1") } else { // Try several times in case cache is not updated yet. time.Sleep(1 * time.Second) @@ -265,10 +305,10 @@ func (plugin *ExamplePlugin) lookup() bool { // Look for VETH 22 ns2 namespace interface on agent2. for i := 0; i <= 3; i++ { if _, _, veth22 = plugin.linuxIfIdxAgent2.LookupIdx(veth22Ns2.Name); veth22 { - log.DefaultLogger().Info("Interface found on agent2: veth22ns2") + logrus.DefaultLogger().Info("Interface found on agent2: veth22ns2") break } else if i == 3 { - log.DefaultLogger().Warn("Interface not found on agent2: veth22ns2") + logrus.DefaultLogger().Warn("Interface not found on agent2: veth22ns2") } else { // Try several times in case cache is not updated yet. time.Sleep(1 * time.Second) diff --git a/examples/localclient_linux/tap/main.go b/examples/localclient_linux/tap/main.go index a47686b945..24eb05ae34 100644 --- a/examples/localclient_linux/tap/main.go +++ b/examples/localclient_linux/tap/main.go @@ -16,15 +16,19 @@ package main import ( "context" + "log" "sync" "time" - "github.com/ligato/cn-infra/core" + "github.com/ligato/cn-infra/agent" + "github.com/ligato/cn-infra/datasync" + "github.com/ligato/cn-infra/datasync/kvdbsync/local" "github.com/ligato/cn-infra/logging" - log "github.com/ligato/cn-infra/logging/logrus" + "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/clientv1/linux/localclient" - "github.com/ligato/vpp-agent/flavors/local" + "github.com/ligato/vpp-agent/plugins/linux" linux_intf "github.com/ligato/vpp-agent/plugins/linux/model/interfaces" + "github.com/ligato/vpp-agent/plugins/vpp" vpp_intf "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" vpp_l2 "github.com/ligato/vpp-agent/plugins/vpp/model/l2" "github.com/namsral/flag" @@ -86,51 +90,82 @@ var ( // Start Agent plugins selected for this example. func main() { - // Init close channel to stop the example. - closeChannel := make(chan struct{}, 1) - - agent := local.NewAgent(local.WithPlugins(func(flavor *local.FlavorVppLocal) []*core.NamedPlugin { - examplePlugin := &core.NamedPlugin{PluginName: PluginID, Plugin: &TapExamplePlugin{}} - - return []*core.NamedPlugin{{examplePlugin.PluginName, examplePlugin}} + //Init close channel to stop the example. + exampleFinished := make(chan struct{}) + // Prepare all the dependencies for example plugin + watcher := datasync.KVProtoWatchers{ + local.Get(), + } + vppPlugin := vpp.NewPlugin(vpp.UseDeps(func(deps *vpp.Deps) { + deps.Watcher = watcher + })) + linuxPlugin := linux.NewPlugin(linux.UseDeps(func(deps *linux.Deps) { + deps.VPP = vppPlugin + deps.Watcher = watcher })) + vppPlugin.Deps.Linux = linuxPlugin - // End when the localhost example is finished. - go closeExample("localhost example finished", closeChannel) + var watchEventsMutex sync.Mutex + vppPlugin.Deps.WatchEventsMutex = &watchEventsMutex + linuxPlugin.Deps.WatchEventsMutex = &watchEventsMutex + + // Inject dependencies to example plugin + ep := &TapExamplePlugin{ + Log: logging.DefaultLogger, + } + ep.Deps.VPP = vppPlugin + ep.Deps.Linux = linuxPlugin + + // Start Agent + a := agent.NewAgent( + agent.AllPlugins(ep), + agent.QuitOnClose(exampleFinished), + ) + if err := a.Run(); err != nil { + log.Fatal() + } - core.EventLoopWithInterrupt(agent, closeChannel) + go closeExample("localhost example finished", exampleFinished) } // Stop the agent with desired info message. -func closeExample(message string, closeChannel chan struct{}) { +func closeExample(message string, exampleFinished chan struct{}) { time.Sleep(time.Duration(*timeout+5) * time.Second) - log.DefaultLogger().Info(message) - closeChannel <- struct{}{} + logrus.DefaultLogger().Info(message) + close(exampleFinished) } /* TAP Example */ -// PluginID of an example plugin. -const PluginID core.PluginName = "tap-example-plugin" - // TapExamplePlugin uses localclient to transport example tap and its linux end // configuration to linuxplugin or VPP plugins type TapExamplePlugin struct { - log logging.Logger + Deps + + Log logging.Logger wg sync.WaitGroup cancel context.CancelFunc } +// Deps is example plugin dependencies. Keep order of fields. +type Deps struct { + VPP *vpp.Plugin + Linux *linux.Plugin +} + +// PluginName represents name of plugin. +const PluginName = "tap-example" + // Init initializes example plugin. func (plugin *TapExamplePlugin) Init() error { // Logger - plugin.log = log.DefaultLogger() - plugin.log.SetLevel(logging.DebugLevel) - plugin.log.Info("Initializing Tap example") + plugin.Log = logrus.DefaultLogger() + plugin.Log.SetLevel(logging.DebugLevel) + plugin.Log.Info("Initializing Tap example") // Flags flag.Parse() - plugin.log.Infof("Timeout between create and modify set to %d", *timeout) + plugin.Log.Infof("Timeout between create and modify set to %d", *timeout) // Apply initial Linux/VPP configuration. plugin.putInitialData() @@ -141,7 +176,7 @@ func (plugin *TapExamplePlugin) Init() error { plugin.wg.Add(1) go plugin.putModifiedData(ctx, *timeout) - plugin.log.Info("Tap example initialization done") + plugin.Log.Info("Tap example initialization done") return nil } @@ -150,22 +185,27 @@ func (plugin *TapExamplePlugin) Close() error { plugin.cancel() plugin.wg.Wait() - log.DefaultLogger().Info("Closed Tap plugin") + plugin.Log.Info("Closed Tap plugin") return nil } +// String returns plugin name +func (plugin *TapExamplePlugin) String() string { + return PluginName +} + // Configure initial data func (plugin *TapExamplePlugin) putInitialData() { - plugin.log.Infof("Applying initial configuration") - err := localclient.DataResyncRequest(PluginID). + plugin.Log.Infof("Applying initial configuration") + err := localclient.DataResyncRequest(PluginName). VppInterface(initialTap1()). LinuxInterface(initialLinuxTap1()). BD(bridgeDomain()). Send().ReceiveReply() if err != nil { - plugin.log.Errorf("Initial configuration failed: %v", err) + plugin.Log.Errorf("Initial configuration failed: %v", err) } else { - plugin.log.Info("Initial configuration successful") + plugin.Log.Info("Initial configuration successful") } } @@ -173,9 +213,9 @@ func (plugin *TapExamplePlugin) putInitialData() { func (plugin *TapExamplePlugin) putModifiedData(ctx context.Context, timeout int) { select { case <-time.After(time.Duration(timeout) * time.Second): - plugin.log.Infof("Applying modified configuration") + plugin.Log.Infof("Applying modified configuration") // Simulate configuration change after timeout - err := localclient.DataChangeRequest(PluginID). + err := localclient.DataChangeRequest(PluginName). Put(). VppInterface(modifiedTap1()). VppInterface(tap2()). @@ -183,13 +223,13 @@ func (plugin *TapExamplePlugin) putModifiedData(ctx context.Context, timeout int LinuxInterface(linuxTap2()). Send().ReceiveReply() if err != nil { - plugin.log.Errorf("Modified configuration failed: %v", err) + plugin.Log.Errorf("Modified configuration failed: %v", err) } else { - plugin.log.Info("Modified configuration successful") + plugin.Log.Info("Modified configuration successful") } case <-ctx.Done(): // Cancel the scheduled re-configuration. - plugin.log.Info("Modification of configuration canceled") + plugin.Log.Info("Modification of configuration canceled") } plugin.wg.Done() } diff --git a/examples/localclient_linux/veth/main.go b/examples/localclient_linux/veth/main.go index 23f7111bcb..ad0ea83fc0 100644 --- a/examples/localclient_linux/veth/main.go +++ b/examples/localclient_linux/veth/main.go @@ -19,12 +19,17 @@ import ( "sync" "time" - "github.com/ligato/cn-infra/core" + "log" + + "github.com/ligato/cn-infra/agent" + "github.com/ligato/cn-infra/datasync" + "github.com/ligato/cn-infra/datasync/kvdbsync/local" "github.com/ligato/cn-infra/logging" - log "github.com/ligato/cn-infra/logging/logrus" - "github.com/ligato/vpp-agent/clientv1/linux/localclient" - "github.com/ligato/vpp-agent/flavors/local" + "github.com/ligato/cn-infra/logging/logrus" + localclient2 "github.com/ligato/vpp-agent/clientv1/linux/localclient" + "github.com/ligato/vpp-agent/plugins/linux" linux_intf "github.com/ligato/vpp-agent/plugins/linux/model/interfaces" + "github.com/ligato/vpp-agent/plugins/vpp" vpp_intf "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" vpp_l2 "github.com/ligato/vpp-agent/plugins/vpp/model/l2" "github.com/namsral/flag" @@ -93,53 +98,89 @@ var ( /* Vpp-agent Init and Close*/ +// PluginName represents name of plugin. +const PluginName = "veth-example" + // Start Agent plugins selected for this example. func main() { - // Init close channel to stop the example. - closeChannel := make(chan struct{}, 1) - - agent := local.NewAgent(local.WithPlugins(func(flavor *local.FlavorVppLocal) []*core.NamedPlugin { - examplePlugin := &core.NamedPlugin{PluginName: PluginID, Plugin: &VethExamplePlugin{}} - - return []*core.NamedPlugin{{examplePlugin.PluginName, examplePlugin}} + //Init close channel to stop the example. + exampleFinished := make(chan struct{}, 1) + // Prepare all the dependencies for example plugin + watcher := datasync.KVProtoWatchers{ + local.Get(), + } + vppPlugin := vpp.NewPlugin(vpp.UseDeps(func(deps *vpp.Deps) { + deps.Watcher = watcher + })) + linuxPlugin := linux.NewPlugin(linux.UseDeps(func(deps *linux.Deps) { + deps.VPP = vppPlugin + deps.Watcher = watcher })) + vppPlugin.Deps.Linux = linuxPlugin - // End when the localhost example is finished. - go closeExample("localhost example finished", closeChannel) + var watchEventsMutex sync.Mutex + vppPlugin.Deps.WatchEventsMutex = &watchEventsMutex + linuxPlugin.Deps.WatchEventsMutex = &watchEventsMutex - core.EventLoopWithInterrupt(agent, closeChannel) + // Inject dependencies to example plugin + ep := &VethExamplePlugin{ + Log: logging.DefaultLogger, + } + ep.Deps.VPP = vppPlugin + ep.Deps.Linux = linuxPlugin + + // Start Agent + a := agent.NewAgent( + agent.AllPlugins(ep), + agent.QuitOnClose(exampleFinished), + ) + if err := a.Run(); err != nil { + log.Fatal() + } + + go closeExample("localhost example finished", exampleFinished) } // Stop the agent with desired info message. -func closeExample(message string, closeChannel chan struct{}) { +func closeExample(message string, exampleFinished chan struct{}) { time.Sleep(time.Duration(*timeout+5) * time.Second) - log.DefaultLogger().Info(message) - closeChannel <- struct{}{} + logrus.DefaultLogger().Info(message) + close(exampleFinished) } /* VETH Example */ -// PluginID of an example plugin. -const PluginID core.PluginName = "veth-example-plugin" - // VethExamplePlugin uses localclient to transport example veth and af-packet // configuration to linuxplugin, eventually VPP plugins type VethExamplePlugin struct { - log logging.Logger + Deps + + Log logging.Logger wg sync.WaitGroup cancel context.CancelFunc } +// Deps is example plugin dependencies. Keep order of fields. +type Deps struct { + VPP *vpp.Plugin + Linux *linux.Plugin +} + +// String returns plugin name +func (plugin *VethExamplePlugin) String() string { + return PluginName +} + // Init initializes example plugin. func (plugin *VethExamplePlugin) Init() error { // Logger - plugin.log = log.DefaultLogger() - plugin.log.SetLevel(logging.DebugLevel) - plugin.log.Info("Initializing Veth example") + plugin.Log = logrus.DefaultLogger() + plugin.Log.SetLevel(logging.DebugLevel) + plugin.Log.Info("Initializing Veth example") // Flags flag.Parse() - plugin.log.Infof("Timeout between create and modify set to %d", *timeout) + plugin.Log.Infof("Timeout between create and modify set to %d", *timeout) // Apply initial Linux/VPP configuration. plugin.putInitialData() @@ -150,7 +191,7 @@ func (plugin *VethExamplePlugin) Init() error { plugin.wg.Add(1) go plugin.putModifiedData(ctx, *timeout) - plugin.log.Info("Veth example initialization done") + plugin.Log.Info("Veth example initialization done") return nil } @@ -159,23 +200,23 @@ func (plugin *VethExamplePlugin) Close() error { plugin.cancel() plugin.wg.Wait() - log.DefaultLogger().Info("Closed Veth plugin") + plugin.Log.Info("Closed Veth plugin") return nil } // Configure initial data func (plugin *VethExamplePlugin) putInitialData() { - plugin.log.Infof("Applying initial configuration") - err := localclient.DataResyncRequest(PluginID). + plugin.Log.Infof("Applying initial configuration") + err := localclient2.DataResyncRequest(PluginName). LinuxInterface(initialVeth11()). LinuxInterface(initialVeth12()). VppInterface(afPacket1()). BD(bridgeDomain()). Send().ReceiveReply() if err != nil { - plugin.log.Errorf("Initial configuration failed: %v", err) + plugin.Log.Errorf("Initial configuration failed: %v", err) } else { - plugin.log.Info("Initial configuration successful") + plugin.Log.Info("Initial configuration successful") } } @@ -183,9 +224,9 @@ func (plugin *VethExamplePlugin) putInitialData() { func (plugin *VethExamplePlugin) putModifiedData(ctx context.Context, timeout int) { select { case <-time.After(time.Duration(timeout) * time.Second): - plugin.log.Infof("Applying modified configuration") + plugin.Log.Infof("Applying modified configuration") // Simulate configuration change after timeout - err := localclient.DataChangeRequest(PluginID). + err := localclient2.DataChangeRequest(PluginName). Put(). LinuxInterface(modifiedVeth11()). LinuxInterface(modifiedVeth12()). @@ -194,13 +235,13 @@ func (plugin *VethExamplePlugin) putModifiedData(ctx context.Context, timeout in VppInterface(afPacket2()). Send().ReceiveReply() if err != nil { - plugin.log.Errorf("Modified configuration failed: %v", err) + plugin.Log.Errorf("Modified configuration failed: %v", err) } else { - plugin.log.Info("Modified configuration successful") + plugin.Log.Info("Modified configuration successful") } case <-ctx.Done(): // Cancel the scheduled re-configuration. - plugin.log.Info("Modification of configuration canceled") + plugin.Log.Info("Modification of configuration canceled") } plugin.wg.Done() } diff --git a/examples/localclient_vpp/nat/main.go b/examples/localclient_vpp/nat/main.go index 8a5bdf7a54..0ff60eafdb 100644 --- a/examples/localclient_vpp/nat/main.go +++ b/examples/localclient_vpp/nat/main.go @@ -16,14 +16,17 @@ package main import ( "context" + "log" "sync" "time" - "github.com/ligato/cn-infra/core" + "github.com/ligato/cn-infra/agent" + "github.com/ligato/cn-infra/datasync" + "github.com/ligato/cn-infra/datasync/kvdbsync/local" "github.com/ligato/cn-infra/logging" - log "github.com/ligato/cn-infra/logging/logrus" + "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/clientv1/vpp/localclient" - "github.com/ligato/vpp-agent/flavors/local" + "github.com/ligato/vpp-agent/plugins/vpp" vpp_intf "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" "github.com/ligato/vpp-agent/plugins/vpp/model/nat" "github.com/namsral/flag" @@ -105,51 +108,70 @@ vpp# // Start Agent plugins selected for this example. func main() { - // Init close channel to stop the example. - closeChannel := make(chan struct{}, 1) - - agent := local.NewAgent(local.WithPlugins(func(flavor *local.FlavorVppLocal) []*core.NamedPlugin { - examplePlugin := &core.NamedPlugin{PluginName: PluginID, Plugin: &NatExamplePlugin{}} - - return []*core.NamedPlugin{{examplePlugin.PluginName, examplePlugin}} + //Init close channel to stop the example. + exampleFinished := make(chan struct{}, 1) + // Prepare all the dependencies for example plugin + watcher := datasync.KVProtoWatchers{ + local.Get(), + } + vppPlugin := vpp.NewPlugin(vpp.UseDeps(func(deps *vpp.Deps) { + deps.Watcher = watcher })) - // End when the localhost example is finished. - go closeExample("NAT44 example finished", closeChannel) + // Inject dependencies to example plugin + ep := &NatExamplePlugin{} + ep.Deps.Log = logging.DefaultLogger + ep.Deps.VPP = vppPlugin + + // Start Agent + a := agent.NewAgent( + agent.AllPlugins(ep), + agent.QuitOnClose(exampleFinished), + ) + if err := a.Run(); err != nil { + log.Fatal() + } - core.EventLoopWithInterrupt(agent, closeChannel) + go closeExample("localhost example finished", exampleFinished) } // Stop the agent with desired info message. -func closeExample(message string, closeChannel chan struct{}) { +func closeExample(message string, exampleFinished chan struct{}) { time.Sleep(time.Duration(*timeout+5) * time.Second) - log.DefaultLogger().Info(message) - closeChannel <- struct{}{} + logrus.DefaultLogger().Info(message) + close(exampleFinished) } /* NAT44 Example */ -// PluginID of an example plugin. -const PluginID core.PluginName = "nat-example-plugin" - // NatExamplePlugin uses localclient to transport example global NAT and DNAT and af-packet // configuration to NAT VPP plugin type NatExamplePlugin struct { - log logging.Logger + Deps + wg sync.WaitGroup cancel context.CancelFunc } +// Deps is example plugin dependencies. +type Deps struct { + Log logging.Logger + VPP *vpp.Plugin +} + +// PluginName represents name of plugin. +const PluginName = "nat-example" + // Init initializes example plugin. func (plugin *NatExamplePlugin) Init() error { // Logger - plugin.log = log.DefaultLogger() - plugin.log.SetLevel(logging.DebugLevel) - plugin.log.Info("Initializing NAT44 example") + plugin.Log = logrus.DefaultLogger() + plugin.Log.SetLevel(logging.DebugLevel) + plugin.Log.Info("Initializing NAT44 example") // Flags flag.Parse() - plugin.log.Infof("Timeout between configuring NAT global and DNAT set to %d", *timeout) + plugin.Log.Infof("Timeout between configuring NAT global and DNAT set to %d", *timeout) // Apply initial VPP configuration. plugin.putGlobalConfig() @@ -160,7 +182,7 @@ func (plugin *NatExamplePlugin) Init() error { plugin.wg.Add(1) go plugin.putDNAT(ctx, *timeout) - plugin.log.Info("NAT example initialization done") + plugin.Log.Info("NAT example initialization done") return nil } @@ -169,23 +191,28 @@ func (plugin *NatExamplePlugin) Close() error { plugin.cancel() plugin.wg.Wait() - log.DefaultLogger().Info("Closed NAT example plugin") + logrus.DefaultLogger().Info("Closed NAT example plugin") return nil } +// String returns plugin name +func (plugin *NatExamplePlugin) String() string { + return PluginName +} + // Configure NAT44 Global config func (plugin *NatExamplePlugin) putGlobalConfig() { - plugin.log.Infof("Applying NAT44 global configuration") - err := localclient.DataResyncRequest(PluginID). + plugin.Log.Infof("Applying NAT44 global configuration") + err := localclient.DataResyncRequest(PluginName). Interface(interface1()). Interface(interface2()). Interface(interface3()). NAT44Global(globalNat()). Send().ReceiveReply() if err != nil { - plugin.log.Errorf("NAT44 global configuration failed: %v", err) + plugin.Log.Errorf("NAT44 global configuration failed: %v", err) } else { - plugin.log.Info("NAT44 global configuration successful") + plugin.Log.Info("NAT44 global configuration successful") } } @@ -193,19 +220,19 @@ func (plugin *NatExamplePlugin) putGlobalConfig() { func (plugin *NatExamplePlugin) putDNAT(ctx context.Context, timeout int) { select { case <-time.After(time.Duration(timeout) * time.Second): - plugin.log.Infof("Applying DNAT configuration") - err := localclient.DataChangeRequest(PluginID). + plugin.Log.Infof("Applying DNAT configuration") + err := localclient.DataChangeRequest(PluginName). Put(). NAT44DNat(dNat()). Send().ReceiveReply() if err != nil { - plugin.log.Errorf("DNAT configuration failed: %v", err) + plugin.Log.Errorf("DNAT configuration failed: %v", err) } else { - plugin.log.Info("DNAT configuration successful") + plugin.Log.Info("DNAT configuration successful") } case <-ctx.Done(): // Cancel the scheduled DNAT configuration. - plugin.log.Info("DNAT configuration canceled") + plugin.Log.Info("DNAT configuration canceled") } plugin.wg.Done() } @@ -314,17 +341,18 @@ func dNat() *nat.Nat44DNat_DNatConfig { StMappings: []*nat.Nat44DNat_DNatConfig_StaticMapping{ { // DNAT static mapping with load balancer (multiple local addresses) - VrfId: 0, ExternalInterface: "memif1", ExternalIp: "192.168.0.1", ExternalPort: 8989, LocalIps: []*nat.Nat44DNat_DNatConfig_StaticMapping_LocalIP{ { + VrfId: 0, LocalIp: "172.124.0.2", LocalPort: 6500, Probability: 40, }, { + VrfId: 0, LocalIp: "172.125.10.5", LocalPort: 2300, Probability: 40, @@ -335,12 +363,12 @@ func dNat() *nat.Nat44DNat_DNatConfig { }, { // DNAT static mapping without load balancer (single local address) - VrfId: 0, ExternalInterface: "memif2", ExternalIp: "192.168.0.2", ExternalPort: 8989, LocalIps: []*nat.Nat44DNat_DNatConfig_StaticMapping_LocalIP{ { + VrfId: 0, LocalIp: "172.124.0.3", LocalPort: 6501, Probability: 50, diff --git a/examples/localclient_vpp/plugins/main.go b/examples/localclient_vpp/plugins/main.go index 3862b35543..5c261978d7 100644 --- a/examples/localclient_vpp/plugins/main.go +++ b/examples/localclient_vpp/plugins/main.go @@ -20,11 +20,15 @@ import ( "sync" "time" - "github.com/ligato/cn-infra/core" + "log" + + "github.com/ligato/cn-infra/agent" + "github.com/ligato/cn-infra/datasync" + "github.com/ligato/cn-infra/datasync/kvdbsync/local" "github.com/ligato/cn-infra/logging" - log "github.com/ligato/cn-infra/logging/logrus" + "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/clientv1/vpp/localclient" - "github.com/ligato/vpp-agent/flavors/local" + "github.com/ligato/vpp-agent/plugins/vpp" "github.com/ligato/vpp-agent/plugins/vpp/model/acl" "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" "github.com/ligato/vpp-agent/plugins/vpp/model/l2" @@ -33,8 +37,8 @@ import ( // init sets the default logging level. func init() { - log.DefaultLogger().SetOutput(os.Stdout) - log.DefaultLogger().SetLevel(logging.DebugLevel) + logrus.DefaultLogger().SetOutput(os.Stdout) + logrus.DefaultLogger().SetLevel(logging.DebugLevel) } /******** @@ -43,41 +47,62 @@ func init() { // Start Agent plugins selected for this example. func main() { - // Init close channel to stop the example. - closeChannel := make(chan struct{}, 1) + //Init close channel to stop the example. + exampleFinished := make(chan struct{}, 1) + // Prepare all the dependencies for example plugin + watcher := datasync.KVProtoWatchers{ + local.Get(), + } + vppPlugin := vpp.NewPlugin(vpp.UseDeps(func(deps *vpp.Deps) { + deps.Watcher = watcher + })) - agent := local.NewAgent(local.WithPlugins(func(flavor *local.FlavorVppLocal) []*core.NamedPlugin { - examplePlugin := &core.NamedPlugin{PluginName: PluginID, Plugin: &ExamplePlugin{}} + var watchEventsMutex sync.Mutex + vppPlugin.Deps.WatchEventsMutex = &watchEventsMutex - return []*core.NamedPlugin{{examplePlugin.PluginName, examplePlugin}} - })) + // Inject dependencies to example plugin + ep := &ExamplePlugin{} + ep.Deps.VPP = vppPlugin - // End when the localhost example is finished. - go closeExample("localhost example finished", closeChannel) + // Start Agent + a := agent.NewAgent( + agent.AllPlugins(ep), + agent.QuitOnClose(exampleFinished), + ) + if err := a.Run(); err != nil { + log.Fatal() + } - core.EventLoopWithInterrupt(agent, closeChannel) + go closeExample("localhost example finished", exampleFinished) } // Stop the agent with desired info message. -func closeExample(message string, closeChannel chan struct{}) { +func closeExample(message string, exampleFinished chan struct{}) { time.Sleep(25 * time.Second) - log.DefaultLogger().Info(message) - closeChannel <- struct{}{} + logrus.DefaultLogger().Info(message) + close(exampleFinished) } /****************** * Example plugin * ******************/ -// PluginID of example plugin -const PluginID core.PluginName = "example-plugin" - // ExamplePlugin demonstrates the use of the localclient to locally transport example configuration into the default VPP plugins. type ExamplePlugin struct { + Deps + wg sync.WaitGroup cancel context.CancelFunc } +// Deps is example plugin dependencies. +type Deps struct { + VPP *vpp.Plugin +} + +// PluginName represents name of plugin. +const PluginName = "plugin-example" + // Init initializes example plugin. func (plugin *ExamplePlugin) Init() error { // Apply initial VPP configuration. @@ -89,7 +114,7 @@ func (plugin *ExamplePlugin) Init() error { plugin.wg.Add(1) go plugin.reconfigureVPP(ctx) - log.DefaultLogger().Info("Initialization of the example plugin has completed") + logrus.DefaultLogger().Info("Initialization of the example plugin has completed") return nil } @@ -98,22 +123,27 @@ func (plugin *ExamplePlugin) Close() error { plugin.cancel() plugin.wg.Wait() - log.DefaultLogger().Info("Closed example plugin") + logrus.DefaultLogger().Info("Closed example plugin") return nil } +// String returns plugin name +func (plugin *ExamplePlugin) String() string { + return PluginName +} + // resyncVPP propagates snapshot of the whole initial configuration to VPP plugins. func (plugin *ExamplePlugin) resyncVPP() { - err := localclient.DataResyncRequest(PluginID). + err := localclient.DataResyncRequest(PluginName). Interface(&memif1AsMaster). Interface(&tap1Disabled). Interface(&loopback1). StaticRoute(&routeThroughMemif1). Send().ReceiveReply() if err != nil { - log.DefaultLogger().Errorf("Failed to apply initial VPP configuration: %v", err) + logrus.DefaultLogger().Errorf("Failed to apply initial VPP configuration: %v", err) } else { - log.DefaultLogger().Info("Successfully applied initial VPP configuration") + logrus.DefaultLogger().Info("Successfully applied initial VPP configuration") } } @@ -122,7 +152,7 @@ func (plugin *ExamplePlugin) reconfigureVPP(ctx context.Context) { select { case <-time.After(15 * time.Second): // Simulate configuration change exactly 15seconds after resync. - err := localclient.DataChangeRequest(PluginID). + err := localclient.DataChangeRequest(PluginName). Put(). Interface(&memif1AsSlave). /* turn memif1 into slave, remove the IP address */ Interface(&memif2). /* newly added memif interface */ @@ -135,13 +165,13 @@ func (plugin *ExamplePlugin) reconfigureVPP(ctx context.Context) { StaticRoute(0, "192.168.2.1/32", "192.168.1.1"). /* remove the route going through memif1 */ Send().ReceiveReply() if err != nil { - log.DefaultLogger().Errorf("Failed to reconfigure VPP: %v", err) + logrus.DefaultLogger().Errorf("Failed to reconfigure VPP: %v", err) } else { - log.DefaultLogger().Info("Successfully reconfigured VPP") + logrus.DefaultLogger().Info("Successfully reconfigured VPP") } case <-ctx.Done(): // cancel the scheduled re-configuration - log.DefaultLogger().Info("Planned VPP re-configuration was canceled") + logrus.DefaultLogger().Info("Planned VPP re-configuration was canceled") } plugin.wg.Done() } diff --git a/flavors/README.md b/flavors/README.md deleted file mode 100644 index 998bb10a56..0000000000 --- a/flavors/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# Flavors - -A flavor is a reusable collection of plugins. It allows inspecting -capabilities available to an agent. By convention, a Flavor should -provide: - * a method called `Inject()`, which should wire the flavor's plugins - together and to their external dependencies (typically via dependency - injection. - * a method called `Plugins()`, which should return all plugins contained - in the Flavor, including plugins contained in [reused Flavors][1]. - -Example: -```go -type MyFlavor struct { - injected bool - Aplugin a.Plugin - Bplugin b.Plugin - Cplugin c.Plugin -} - -func (f *MyFlavor) Inject() bool { - if f.injected { - return false - } - f.injected = true - f.Bplugin.A = &f.Aplugin - f.Cplugin.B = &f.Bplugin - return true -} - -func (f *MyFlavor) Plugins() []*core.NamedPlugin { - f.Inject() - return core.ListPluginsInFlavor(f) -} -``` - -[1]: https://github.com/ligato/cn-infra/blob/master/docs/guidelines/PLUGIN_FLAVORS.md \ No newline at end of file diff --git a/flavors/doc.go b/flavors/doc.go deleted file mode 100644 index faf5f94d5b..0000000000 --- a/flavors/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package flavors contains predefined vpp-agent flavors. -package flavors diff --git a/flavors/local/local_flavor.go b/flavors/local/local_flavor.go deleted file mode 100644 index 18ee3971ff..0000000000 --- a/flavors/local/local_flavor.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) 2017 Cisco and/or its affiliates. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at: -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package local defines flavor used for VPP agents managed only locally. -package local - -import ( - "github.com/ligato/cn-infra/core" - "github.com/ligato/cn-infra/flavors/local" - - "github.com/ligato/cn-infra/datasync" - local_sync "github.com/ligato/cn-infra/datasync/kvdbsync/local" - "github.com/ligato/vpp-agent/clientv1/linux/localclient" - "github.com/ligato/vpp-agent/plugins/govppmux" - "github.com/ligato/vpp-agent/plugins/linux" - "github.com/ligato/vpp-agent/plugins/vpp" -) - -// NewAgent returns a new instance of the Agent with plugins. -// It is an alias for core.NewAgent() to implicit use of the FlavorVppLocal -func NewAgent(opts ...core.Option) *core.Agent { - return core.NewAgent(&FlavorVppLocal{}, opts...) -} - -// WithPlugins for adding custom plugins to SFC Controller -// is a callback that uses flavor input to -// inject dependencies for custom plugins that are in output -// -// Example: -// -// NewAgent(vppFlavor.WithPlugins(func(flavor) { -// return []*core.NamedPlugin{{"my-plugin", &MyPlugin{DependencyXY: &flavor.FlavorXY}}} -// })) -func WithPlugins(listPlugins func(local *FlavorVppLocal) []*core.NamedPlugin) core.WithPluginsOpt { - return &withPluginsOpt{listPlugins} -} - -// FlavorVppLocal glues together multiple plugins to manage VPP and Linux -// configuration using the local client. -type FlavorVppLocal struct { - *local.FlavorLocal - LinuxLocalClient localclient.Plugin - GoVPP govppmux.GOVPPPlugin - Linux linux.Plugin - VPP vpp.Plugin - - injected bool -} - -// Inject sets inter-plugin references. -func (f *FlavorVppLocal) Inject() bool { - if f.injected { - return false - } - f.injected = true - - if f.FlavorLocal == nil { - f.FlavorLocal = &local.FlavorLocal{} - } - f.FlavorLocal.Inject() - - f.GoVPP.Deps.PluginInfraDeps = *f.FlavorLocal.InfraDeps("govpp") - f.Linux.Deps.PluginInfraDeps = *f.FlavorLocal.InfraDeps("linux-plugin", local.WithConf()) - f.Linux.Watcher = &datasync.CompositeKVProtoWatcher{Adapters: []datasync.KeyValProtoWatcher{local_sync.Get()}} - f.VPP.Watch = &datasync.CompositeKVProtoWatcher{Adapters: []datasync.KeyValProtoWatcher{local_sync.Get()}} - f.VPP.Deps.PluginInfraDeps = *f.FlavorLocal.InfraDeps("vpp-plugin", local.WithConf()) - f.VPP.Deps.Linux = &f.Linux - f.VPP.Deps.GoVppmux = &f.GoVPP - - return true -} - -// Plugins combines all Plugins in the flavor to a list. -func (f *FlavorVppLocal) Plugins() []*core.NamedPlugin { - f.Inject() - return core.ListPluginsInFlavor(f) -} - -// withPluginsOpt is return value of vppLocal.WithPlugins() utility -// to easily define new plugins for the agent based on FlavorVppLocal. -type withPluginsOpt struct { - callback func(local *FlavorVppLocal) []*core.NamedPlugin -} - -// OptionMarkerCore is just for marking implementation that it implements this interface -func (opt *withPluginsOpt) OptionMarkerCore() {} - -// Plugins methods is here to implement core.WithPluginsOpt go interface -// is a callback that uses flavor input for dependency injection -// for custom plugins (returned as NamedPlugin) -func (opt *withPluginsOpt) Plugins(flavors ...core.Flavor) []*core.NamedPlugin { - for _, flavor := range flavors { - if f, ok := flavor.(*FlavorVppLocal); ok { - return opt.callback(f) - } - } - - panic("wrong usage of vppLocal.WithPlugin() for other than FlavorVppLocal") -} diff --git a/flavors/vpp/vpp_flavor.go b/flavors/vpp/vpp_flavor.go deleted file mode 100644 index b43404ed2c..0000000000 --- a/flavors/vpp/vpp_flavor.go +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) 2018 Cisco and/or its affiliates. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at: -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package vpp defines the standard flavor used for full-featured VPP agents. -package vpp - -import ( - "sync" - - "github.com/ligato/cn-infra/core" - "github.com/ligato/cn-infra/datasync" - local_sync "github.com/ligato/cn-infra/datasync/kvdbsync/local" - "github.com/ligato/cn-infra/datasync/msgsync" - "github.com/ligato/cn-infra/flavors/connectors" - "github.com/ligato/cn-infra/flavors/local" - "github.com/ligato/cn-infra/flavors/rpc" - "github.com/ligato/vpp-agent/plugins/govppmux" - "github.com/ligato/vpp-agent/plugins/linux" - "github.com/ligato/vpp-agent/plugins/rest" - "github.com/ligato/vpp-agent/plugins/telemetry" - "github.com/ligato/vpp-agent/plugins/vpp" - rpcsvc "github.com/ligato/vpp-agent/plugins/vpp/rpc" -) - -// kafkaIfStateTopic is the topic where interface state changes are published. -const kafkaIfStateTopic = "if_state" - -// NewAgent returns a new instance of the Agent with plugins. -// It is an alias for core.NewAgent() to implicit use of the FlavorVppLocal -func NewAgent(opts ...core.Option) *core.Agent { - return core.NewAgent(&Flavor{}, opts...) -} - -// WithPlugins for adding custom plugins to SFC Controller. -// is a callback that uses flavor input to -// inject dependencies for custom plugins that are in output. -// -// Example: -// -// NewAgent(vppFlavor.WithPlugins(func(flavor) { -// return []*core.NamedPlugin{{"my-plugin", &MyPlugin{DependencyXY: &flavor.FlavorXY}}} -// })) -func WithPlugins(listPlugins func(local *Flavor) []*core.NamedPlugin) core.WithPluginsOpt { - return &withPluginsOpt{listPlugins} -} - -// Flavor glues together multiple plugins to build a full-featured VPP agent. -type Flavor struct { - *local.FlavorLocal - *connectors.AllConnectorsFlavor // connectors have to be started before vpp flavor - *rpc.FlavorRPC - - // This can be reused later even for the Linux plugin, - // it has its own configuration. - IfStatePub msgsync.PubPlugin - - GoVPP govppmux.GOVPPPlugin - Linux linux.Plugin - VPP vpp.Plugin - - GRPCSvcPlugin rpcsvc.GRPCSvcPlugin - RESTAPIPlugin rest.Plugin - TelemetryPlugin telemetry.Plugin - - injected bool -} - -// Inject sets inter-plugin references. -func (f *Flavor) Inject() bool { - if f.injected { - return false - } - f.injected = true - - f.injectEmbedded() - - f.GoVPP.Deps.PluginInfraDeps = *f.FlavorLocal.InfraDeps("govpp", local.WithConf()) - f.GoVPP.Deps.Resync = &f.ResyncOrch - f.VPP.Deps.PluginInfraDeps = *f.FlavorLocal.InfraDeps("vpp-plugin", local.WithConf()) - f.VPP.Deps.Linux = &f.Linux - f.VPP.Deps.GoVppmux = &f.GoVPP - - f.VPP.Deps.Publish = &datasync.CompositeKVProtoWriter{Adapters: []datasync.KeyProtoValWriter{ - &f.AllConnectorsFlavor.ETCDDataSync, - &f.AllConnectorsFlavor.ConsulDataSync, - }} - - /* note: now configurable with `status-publishers` in vppplugin - f.VPP.Deps.PublishStatistics = &datasync.CompositeKVProtoWriter{Adapters: []datasync.KeyProtoValWriter{ - &f.AllConnectorsFlavor.ETCDDataSync, &f.AllConnectorsFlavor.RedisDataSync}, - }*/ - f.VPP.Deps.DataSyncs = map[string]datasync.KeyProtoValWriter{ - "etcd": &f.AllConnectorsFlavor.ETCDDataSync, - "redis": &f.AllConnectorsFlavor.RedisDataSync, - } - - f.IfStatePub.Messaging = &f.Kafka - f.IfStatePub.PluginInfraDeps = *f.InfraDeps("ifstate-pub") - // If needed, provide configuration using ifstate-pub-config. - // Set default configuration; it is overridable using ifstate-pub-config. - // Intent of not putting this configuration into the vpp plugin is that - // this way it is reusable even for the Linux plugin. - f.IfStatePub.Cfg.Topic = kafkaIfStateTopic - - f.VPP.Deps.IfStatePub = &f.IfStatePub - f.VPP.Deps.Watch = &datasync.CompositeKVProtoWatcher{Adapters: []datasync.KeyValProtoWatcher{ - local_sync.Get(), - &f.AllConnectorsFlavor.ETCDDataSync, - &f.AllConnectorsFlavor.ConsulDataSync, - }} - f.VPP.Deps.GRPCSvc = &f.GRPCSvcPlugin - - f.Linux.Deps.PluginInfraDeps = *f.FlavorLocal.InfraDeps("linux-plugin", local.WithConf()) - f.Linux.Deps.VPP = &f.VPP - f.Linux.Deps.Watcher = &datasync.CompositeKVProtoWatcher{Adapters: []datasync.KeyValProtoWatcher{ - local_sync.Get(), - &f.AllConnectorsFlavor.ETCDDataSync, - &f.AllConnectorsFlavor.ConsulDataSync, - }} - - // Mutex for synchronizing watching events - var watchEventsMutex sync.Mutex - f.VPP.Deps.WatchEventsMutex = &watchEventsMutex - f.Linux.Deps.WatchEventsMutex = &watchEventsMutex - - // Init GRPC service after VPP & Linux plugins - f.GRPCSvcPlugin.Deps.PluginLogDeps = *f.LogDeps("vpp-grpc-svc") - f.GRPCSvcPlugin.Deps.GRPCServer = &f.FlavorRPC.GRPC - - f.RESTAPIPlugin.Deps.PluginInfraDeps = *f.FlavorLocal.InfraDeps("rest") - f.RESTAPIPlugin.Deps.HTTPHandlers = &f.FlavorRPC.HTTP - f.RESTAPIPlugin.Deps.GoVppmux = &f.GoVPP - - f.TelemetryPlugin.Deps.PluginInfraDeps = *f.FlavorLocal.InfraDeps("telemetry") - f.TelemetryPlugin.Deps.Prometheus = &f.FlavorRPC.Prometheus - f.TelemetryPlugin.Deps.GoVppmux = &f.GoVPP - - return true -} - -func (f *Flavor) injectEmbedded() { - if f.FlavorLocal == nil { - f.FlavorLocal = &local.FlavorLocal{} - } - f.FlavorLocal.Inject() - if f.FlavorRPC == nil { - f.FlavorRPC = &rpc.FlavorRPC{FlavorLocal: f.FlavorLocal} - } - f.FlavorRPC.Inject() - if f.AllConnectorsFlavor == nil { - f.AllConnectorsFlavor = &connectors.AllConnectorsFlavor{FlavorLocal: f.FlavorLocal} - } - f.AllConnectorsFlavor.Inject() -} - -// Plugins combine all Plugins in the flavor to a list. -func (f *Flavor) Plugins() []*core.NamedPlugin { - f.Inject() - return core.ListPluginsInFlavor(f) -} - -// withPluginsOpt is return value of vppLocal.WithPlugins() utility -// to easily define new plugins for the agent based on Flavor. -type withPluginsOpt struct { - callback func(local *Flavor) []*core.NamedPlugin -} - -// OptionMarkerCore is just for marking implementation that it implements this interface -func (opt *withPluginsOpt) OptionMarkerCore() {} - -// Plugins methods is here to implement core.WithPluginsOpt go interface -// is a callback that uses flavor input for dependency injection -// for custom plugins (returned as NamedPlugin) -func (opt *withPluginsOpt) Plugins(flavors ...core.Flavor) []*core.NamedPlugin { - for _, flavor := range flavors { - if f, ok := flavor.(*Flavor); ok { - return opt.callback(f) - } - } - - panic("wrong usage of vpp.WithPlugin() for other than Flavor") -} diff --git a/idxvpp/api.go b/idxvpp/api.go index 23bed6baef..3f4452860e 100644 --- a/idxvpp/api.go +++ b/idxvpp/api.go @@ -17,7 +17,6 @@ package idxvpp import ( "errors" - "github.com/ligato/cn-infra/core" "github.com/ligato/cn-infra/idxmap" ) @@ -142,5 +141,5 @@ type NameToIdx interface { // ifIdxEv.Done() // ... // } - Watch(subscriber core.PluginName, callback func(NameToIdxDto)) + Watch(subscriber string, callback func(NameToIdxDto)) } diff --git a/idxvpp/nametoidx/inmemory_name_to_idx_mapping.go b/idxvpp/nametoidx/inmemory_name_to_idx_mapping.go index 32769bb973..ef8d1f938b 100644 --- a/idxvpp/nametoidx/inmemory_name_to_idx_mapping.go +++ b/idxvpp/nametoidx/inmemory_name_to_idx_mapping.go @@ -18,9 +18,9 @@ import ( "strconv" "time" - "github.com/ligato/cn-infra/core" "github.com/ligato/cn-infra/idxmap" "github.com/ligato/cn-infra/idxmap/mem" + "github.com/ligato/cn-infra/infra" "github.com/ligato/cn-infra/logging" "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/idxvpp" @@ -142,7 +142,7 @@ func (mem *nameToIdxMem) ListNames() (names []string) { // Watch starts monitoring a change in the mapping. When yhe change occurs, the callback is called. // ToChan utility can be used to receive changes through channel. -func (mem *nameToIdxMem) Watch(subscriber core.PluginName, callback func(idxvpp.NameToIdxDto)) { +func (mem *nameToIdxMem) Watch(subscriber string, callback func(idxvpp.NameToIdxDto)) { watcher := func(dto idxmap.NamedMappingGenericEvent) { internalMeta, ok := dto.Value.(*nameToIdxMeta) if !ok { @@ -156,7 +156,7 @@ func (mem *nameToIdxMem) Watch(subscriber core.PluginName, callback func(idxvpp. } callback(msg) } - mem.internal.Watch(subscriber, watcher) + mem.internal.Watch(infra.PluginName(subscriber), watcher) } // ToChan is an utility that allows to receive notification through a channel. diff --git a/idxvpp/persist/persistent_name_mapping.go b/idxvpp/persist/persistent_name_mapping.go index ac5175fc56..5d45bfad26 100644 --- a/idxvpp/persist/persistent_name_mapping.go +++ b/idxvpp/persist/persistent_name_mapping.go @@ -26,7 +26,6 @@ import ( "sync" "time" - "github.com/ligato/cn-infra/core" "github.com/ligato/cn-infra/logging" log "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/idxvpp" @@ -71,7 +70,7 @@ func Marshalling(agentLabel string, idxMap idxvpp.NameToIdx, loadedFromFile idxv return err } - idxMap.Watch(core.PluginName("idxpersist"), nametoidx.ToChan(changes)) + idxMap.Watch("idxpersist", nametoidx.ToChan(changes)) err = persist.loadIdxMapFile(loadedFromFile) if err != nil { diff --git a/k8s/dev-setup/vnf-vpp.yaml b/k8s/dev-setup/vnf-vpp.yaml index eee935a570..22c541f724 100644 --- a/k8s/dev-setup/vnf-vpp.yaml +++ b/k8s/dev-setup/vnf-vpp.yaml @@ -53,12 +53,12 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vnf-vpp-cfg - - name: agent-config - configMap: - name: vnf-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp + - name: vpp-config + configMap: + name: vnf-vpp-cfg + - name: agent-config + configMap: + name: vnf-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp diff --git a/k8s/dev-setup/vswitch-vpp.yaml b/k8s/dev-setup/vswitch-vpp.yaml index 1c28ec0b5d..48332b25a4 100644 --- a/k8s/dev-setup/vswitch-vpp.yaml +++ b/k8s/dev-setup/vswitch-vpp.yaml @@ -52,12 +52,12 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vswitch-vpp-cfg - - name: agent-config - configMap: - name: vswitch-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp + - name: vpp-config + configMap: + name: vswitch-vpp-cfg + - name: agent-config + configMap: + name: vswitch-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp diff --git a/k8s/perf-demo/etcd.yaml b/k8s/perf-demo/etcd.yaml index e8969307bd..44d83635ab 100644 --- a/k8s/perf-demo/etcd.yaml +++ b/k8s/perf-demo/etcd.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -5,20 +6,20 @@ metadata: spec: hostNetwork: true containers: - - image: quay.io/coreos/etcd:v3.0.16 - name: etcd - command: + - image: quay.io/coreos/etcd:v3.0.16 + name: etcd + command: - /usr/local/bin/etcd - - --advertise-client-urls + - --advertise-client-urls - http://0.0.0.0:22379 - - --listen-client-urls + - --listen-client-urls - http://0.0.0.0:22379 - --listen-peer-urls - http://0.0.0.0:22380 - ports: + ports: - containerPort: 22379 hostPort: 22379 name: serverport - env: - - name: ETCDCTL_API - value: "3" + env: + - name: ETCDCTL_API + value: "3" diff --git a/k8s/perf-demo/kafka.yaml b/k8s/perf-demo/kafka.yaml index bf1cd20a83..61362b7647 100644 --- a/k8s/perf-demo/kafka.yaml +++ b/k8s/perf-demo/kafka.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -5,17 +6,17 @@ metadata: spec: hostNetwork: true containers: - - image: spotify/kafka - name: kafka - ports: + - image: spotify/kafka + name: kafka + ports: - containerPort: 2181 hostPort: 2181 name: zookeeper - containerPort: 9092 hostPort: 9092 name: kafka - env: - - name: ADVERTISED_HOST - value: "172.17.0.1" - - name: ADVERTISED_PORT - value: "9092" + env: + - name: ADVERTISED_HOST + value: "172.17.0.1" + - name: ADVERTISED_PORT + value: "9092" diff --git a/k8s/perf-demo/scenario1/vnf/vnf-agent-cfg.yaml b/k8s/perf-demo/scenario1/vnf/vnf-agent-cfg.yaml index 99c38bb48f..3b22475a40 100644 --- a/k8s/perf-demo/scenario1/vnf/vnf-agent-cfg.yaml +++ b/k8s/perf-demo/scenario1/vnf/vnf-agent-cfg.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: ConfigMap metadata: @@ -11,4 +12,3 @@ data: kafka.conf: | addrs: - "172.17.0.1:9092" - diff --git a/k8s/perf-demo/scenario1/vnf/vnf.yaml b/k8s/perf-demo/scenario1/vnf/vnf.yaml index f1eeff6e95..3bfd57c2ff 100644 --- a/k8s/perf-demo/scenario1/vnf/vnf.yaml +++ b/k8s/perf-demo/scenario1/vnf/vnf.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -33,13 +34,12 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vnf-vpp-cfg - - name: agent-config - configMap: - name: vnf-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp - + - name: vpp-config + configMap: + name: vnf-vpp-cfg + - name: agent-config + configMap: + name: vnf-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp diff --git a/k8s/perf-demo/scenario1/vswitch/vswitch-agent-cfg.yaml b/k8s/perf-demo/scenario1/vswitch/vswitch-agent-cfg.yaml index 68ca242366..6e7aef4669 100644 --- a/k8s/perf-demo/scenario1/vswitch/vswitch-agent-cfg.yaml +++ b/k8s/perf-demo/scenario1/vswitch/vswitch-agent-cfg.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: ConfigMap metadata: @@ -11,4 +12,3 @@ data: kafka.conf: | addrs: - "172.17.0.1:9092" - diff --git a/k8s/perf-demo/scenario1/vswitch/vswitch.yaml b/k8s/perf-demo/scenario1/vswitch/vswitch.yaml index 5d83c557fa..96799185b0 100644 --- a/k8s/perf-demo/scenario1/vswitch/vswitch.yaml +++ b/k8s/perf-demo/scenario1/vswitch/vswitch.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -35,13 +36,12 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vswitch-vpp-cfg - - name: agent-config - configMap: - name: vswitch-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp - + - name: vpp-config + configMap: + name: vswitch-vpp-cfg + - name: agent-config + configMap: + name: vswitch-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp diff --git a/k8s/perf-demo/scenario2/vnf/vnf-agent-cfg.yaml b/k8s/perf-demo/scenario2/vnf/vnf-agent-cfg.yaml index 99c38bb48f..3b22475a40 100644 --- a/k8s/perf-demo/scenario2/vnf/vnf-agent-cfg.yaml +++ b/k8s/perf-demo/scenario2/vnf/vnf-agent-cfg.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: ConfigMap metadata: @@ -11,4 +12,3 @@ data: kafka.conf: | addrs: - "172.17.0.1:9092" - diff --git a/k8s/perf-demo/scenario2/vnf/vnf1.yaml b/k8s/perf-demo/scenario2/vnf/vnf1.yaml index 7c80c18bd2..67c6248545 100644 --- a/k8s/perf-demo/scenario2/vnf/vnf1.yaml +++ b/k8s/perf-demo/scenario2/vnf/vnf1.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -33,13 +34,12 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vnf1-vpp-cfg - - name: agent-config - configMap: - name: vnf-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp - + - name: vpp-config + configMap: + name: vnf1-vpp-cfg + - name: agent-config + configMap: + name: vnf-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp diff --git a/k8s/perf-demo/scenario2/vnf/vnf2.yaml b/k8s/perf-demo/scenario2/vnf/vnf2.yaml index ca54936d1e..ccb3c47946 100644 --- a/k8s/perf-demo/scenario2/vnf/vnf2.yaml +++ b/k8s/perf-demo/scenario2/vnf/vnf2.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -33,13 +34,12 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vnf2-vpp-cfg - - name: agent-config - configMap: - name: vnf-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp - + - name: vpp-config + configMap: + name: vnf2-vpp-cfg + - name: agent-config + configMap: + name: vnf-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp diff --git a/k8s/perf-demo/scenario2/vswitch/vswitch-agent-cfg.yaml b/k8s/perf-demo/scenario2/vswitch/vswitch-agent-cfg.yaml index 68ca242366..6e7aef4669 100644 --- a/k8s/perf-demo/scenario2/vswitch/vswitch-agent-cfg.yaml +++ b/k8s/perf-demo/scenario2/vswitch/vswitch-agent-cfg.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: ConfigMap metadata: @@ -11,4 +12,3 @@ data: kafka.conf: | addrs: - "172.17.0.1:9092" - diff --git a/k8s/perf-demo/scenario2/vswitch/vswitch-vpp-cfg.yaml b/k8s/perf-demo/scenario2/vswitch/vswitch-vpp-cfg.yaml index bb5761bb93..2116ebb11e 100644 --- a/k8s/perf-demo/scenario2/vswitch/vswitch-vpp-cfg.yaml +++ b/k8s/perf-demo/scenario2/vswitch/vswitch-vpp-cfg.yaml @@ -23,4 +23,3 @@ data: workers 0 } } - diff --git a/k8s/perf-demo/scenario2/vswitch/vswitch.yaml b/k8s/perf-demo/scenario2/vswitch/vswitch.yaml index 5d83c557fa..96799185b0 100644 --- a/k8s/perf-demo/scenario2/vswitch/vswitch.yaml +++ b/k8s/perf-demo/scenario2/vswitch/vswitch.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -35,13 +36,12 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vswitch-vpp-cfg - - name: agent-config - configMap: - name: vswitch-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp - + - name: vpp-config + configMap: + name: vswitch-vpp-cfg + - name: agent-config + configMap: + name: vswitch-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp diff --git a/k8s/perf-demo/scenario4/vnf/vnf-agent-cfg.yaml b/k8s/perf-demo/scenario4/vnf/vnf-agent-cfg.yaml index 99c38bb48f..3b22475a40 100644 --- a/k8s/perf-demo/scenario4/vnf/vnf-agent-cfg.yaml +++ b/k8s/perf-demo/scenario4/vnf/vnf-agent-cfg.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: ConfigMap metadata: @@ -11,4 +12,3 @@ data: kafka.conf: | addrs: - "172.17.0.1:9092" - diff --git a/k8s/perf-demo/scenario4/vnf/vnf.yaml b/k8s/perf-demo/scenario4/vnf/vnf.yaml index f1eeff6e95..3bfd57c2ff 100644 --- a/k8s/perf-demo/scenario4/vnf/vnf.yaml +++ b/k8s/perf-demo/scenario4/vnf/vnf.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -33,13 +34,12 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vnf-vpp-cfg - - name: agent-config - configMap: - name: vnf-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp - + - name: vpp-config + configMap: + name: vnf-vpp-cfg + - name: agent-config + configMap: + name: vnf-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp diff --git a/k8s/perf-demo/scenario4/vswitch/vswitch-agent-cfg.yaml b/k8s/perf-demo/scenario4/vswitch/vswitch-agent-cfg.yaml index 68ca242366..6e7aef4669 100644 --- a/k8s/perf-demo/scenario4/vswitch/vswitch-agent-cfg.yaml +++ b/k8s/perf-demo/scenario4/vswitch/vswitch-agent-cfg.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: ConfigMap metadata: @@ -11,4 +12,3 @@ data: kafka.conf: | addrs: - "172.17.0.1:9092" - diff --git a/k8s/perf-demo/scenario4/vswitch/vswitch.yaml b/k8s/perf-demo/scenario4/vswitch/vswitch.yaml index 7a8d30eab1..e8865de119 100644 --- a/k8s/perf-demo/scenario4/vswitch/vswitch.yaml +++ b/k8s/perf-demo/scenario4/vswitch/vswitch.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -38,16 +39,15 @@ spec: - name: docker-socket mountPath: /var/run/docker.sock volumes: - - name: vpp-config - configMap: - name: vswitch-vpp-cfg - - name: agent-config - configMap: - name: vswitch-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp - - name: docker-socket - hostPath: - path: /var/run/docker.sock - + - name: vpp-config + configMap: + name: vswitch-vpp-cfg + - name: agent-config + configMap: + name: vswitch-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp + - name: docker-socket + hostPath: + path: /var/run/docker.sock diff --git a/k8s/perf-demo/with-controller/scenario1/sfc/sfc-cfg.yaml b/k8s/perf-demo/with-controller/scenario1/sfc/sfc-cfg.yaml index 82239a1716..e0a562db85 100644 --- a/k8s/perf-demo/with-controller/scenario1/sfc/sfc-cfg.yaml +++ b/k8s/perf-demo/with-controller/scenario1/sfc/sfc-cfg.yaml @@ -51,4 +51,3 @@ data: - port_labels: - port1 - port2 - diff --git a/k8s/perf-demo/with-controller/scenario1/sfc/sfc.yaml b/k8s/perf-demo/with-controller/scenario1/sfc/sfc.yaml index e2a03a1902..c0c75147be 100644 --- a/k8s/perf-demo/with-controller/scenario1/sfc/sfc.yaml +++ b/k8s/perf-demo/with-controller/scenario1/sfc/sfc.yaml @@ -17,6 +17,6 @@ spec: - name: controller-config mountPath: /opt/sfc-controller/dev volumes: - - name: controller-config - configMap: - name: sfc-controller-cfg + - name: controller-config + configMap: + name: sfc-controller-cfg diff --git a/k8s/perf-demo/with-controller/scenario1/vnf/vnf-agent-cfg.yaml b/k8s/perf-demo/with-controller/scenario1/vnf/vnf-agent-cfg.yaml index 99c38bb48f..3b22475a40 100644 --- a/k8s/perf-demo/with-controller/scenario1/vnf/vnf-agent-cfg.yaml +++ b/k8s/perf-demo/with-controller/scenario1/vnf/vnf-agent-cfg.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: ConfigMap metadata: @@ -11,4 +12,3 @@ data: kafka.conf: | addrs: - "172.17.0.1:9092" - diff --git a/k8s/perf-demo/with-controller/scenario1/vnf/vnf-vpp-cfg.yaml b/k8s/perf-demo/with-controller/scenario1/vnf/vnf-vpp-cfg.yaml index 805d8dfe8a..7459890d30 100644 --- a/k8s/perf-demo/with-controller/scenario1/vnf/vnf-vpp-cfg.yaml +++ b/k8s/perf-demo/with-controller/scenario1/vnf/vnf-vpp-cfg.yaml @@ -18,4 +18,3 @@ data: disable } } - diff --git a/k8s/perf-demo/with-controller/scenario1/vnf/vnf.yaml b/k8s/perf-demo/with-controller/scenario1/vnf/vnf.yaml index f1eeff6e95..3bfd57c2ff 100644 --- a/k8s/perf-demo/with-controller/scenario1/vnf/vnf.yaml +++ b/k8s/perf-demo/with-controller/scenario1/vnf/vnf.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -33,13 +34,12 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vnf-vpp-cfg - - name: agent-config - configMap: - name: vnf-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp - + - name: vpp-config + configMap: + name: vnf-vpp-cfg + - name: agent-config + configMap: + name: vnf-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp diff --git a/k8s/perf-demo/with-controller/scenario1/vswitch/vswitch-agent-cfg.yaml b/k8s/perf-demo/with-controller/scenario1/vswitch/vswitch-agent-cfg.yaml index 68ca242366..6e7aef4669 100644 --- a/k8s/perf-demo/with-controller/scenario1/vswitch/vswitch-agent-cfg.yaml +++ b/k8s/perf-demo/with-controller/scenario1/vswitch/vswitch-agent-cfg.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: ConfigMap metadata: @@ -11,4 +12,3 @@ data: kafka.conf: | addrs: - "172.17.0.1:9092" - diff --git a/k8s/perf-demo/with-controller/scenario1/vswitch/vswitch.yaml b/k8s/perf-demo/with-controller/scenario1/vswitch/vswitch.yaml index 5d83c557fa..96799185b0 100644 --- a/k8s/perf-demo/with-controller/scenario1/vswitch/vswitch.yaml +++ b/k8s/perf-demo/with-controller/scenario1/vswitch/vswitch.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -35,13 +36,12 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vswitch-vpp-cfg - - name: agent-config - configMap: - name: vswitch-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp - + - name: vpp-config + configMap: + name: vswitch-vpp-cfg + - name: agent-config + configMap: + name: vswitch-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp diff --git a/k8s/perf-demo/with-controller/scenario2/sfc/sfc-cfg.yaml b/k8s/perf-demo/with-controller/scenario2/sfc/sfc-cfg.yaml index 583be5e3bb..6e2acebdff 100644 --- a/k8s/perf-demo/with-controller/scenario2/sfc/sfc-cfg.yaml +++ b/k8s/perf-demo/with-controller/scenario2/sfc/sfc-cfg.yaml @@ -73,4 +73,3 @@ data: - port_labels: - port1 - port2 - diff --git a/k8s/perf-demo/with-controller/scenario2/sfc/sfc.yaml b/k8s/perf-demo/with-controller/scenario2/sfc/sfc.yaml index e2a03a1902..c0c75147be 100644 --- a/k8s/perf-demo/with-controller/scenario2/sfc/sfc.yaml +++ b/k8s/perf-demo/with-controller/scenario2/sfc/sfc.yaml @@ -17,6 +17,6 @@ spec: - name: controller-config mountPath: /opt/sfc-controller/dev volumes: - - name: controller-config - configMap: - name: sfc-controller-cfg + - name: controller-config + configMap: + name: sfc-controller-cfg diff --git a/k8s/perf-demo/with-controller/scenario2/vnf/vnf-agent-cfg.yaml b/k8s/perf-demo/with-controller/scenario2/vnf/vnf-agent-cfg.yaml index 99c38bb48f..3b22475a40 100644 --- a/k8s/perf-demo/with-controller/scenario2/vnf/vnf-agent-cfg.yaml +++ b/k8s/perf-demo/with-controller/scenario2/vnf/vnf-agent-cfg.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: ConfigMap metadata: @@ -11,4 +12,3 @@ data: kafka.conf: | addrs: - "172.17.0.1:9092" - diff --git a/k8s/perf-demo/with-controller/scenario2/vnf/vnf1.yaml b/k8s/perf-demo/with-controller/scenario2/vnf/vnf1.yaml index 7c80c18bd2..67c6248545 100644 --- a/k8s/perf-demo/with-controller/scenario2/vnf/vnf1.yaml +++ b/k8s/perf-demo/with-controller/scenario2/vnf/vnf1.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -33,13 +34,12 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vnf1-vpp-cfg - - name: agent-config - configMap: - name: vnf-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp - + - name: vpp-config + configMap: + name: vnf1-vpp-cfg + - name: agent-config + configMap: + name: vnf-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp diff --git a/k8s/perf-demo/with-controller/scenario2/vnf/vnf2.yaml b/k8s/perf-demo/with-controller/scenario2/vnf/vnf2.yaml index ca54936d1e..ccb3c47946 100644 --- a/k8s/perf-demo/with-controller/scenario2/vnf/vnf2.yaml +++ b/k8s/perf-demo/with-controller/scenario2/vnf/vnf2.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -33,13 +34,12 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vnf2-vpp-cfg - - name: agent-config - configMap: - name: vnf-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp - + - name: vpp-config + configMap: + name: vnf2-vpp-cfg + - name: agent-config + configMap: + name: vnf-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp diff --git a/k8s/perf-demo/with-controller/scenario2/vswitch/vswitch-agent-cfg.yaml b/k8s/perf-demo/with-controller/scenario2/vswitch/vswitch-agent-cfg.yaml index 68ca242366..6e7aef4669 100644 --- a/k8s/perf-demo/with-controller/scenario2/vswitch/vswitch-agent-cfg.yaml +++ b/k8s/perf-demo/with-controller/scenario2/vswitch/vswitch-agent-cfg.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: ConfigMap metadata: @@ -11,4 +12,3 @@ data: kafka.conf: | addrs: - "172.17.0.1:9092" - diff --git a/k8s/perf-demo/with-controller/scenario2/vswitch/vswitch.yaml b/k8s/perf-demo/with-controller/scenario2/vswitch/vswitch.yaml index 5d83c557fa..96799185b0 100644 --- a/k8s/perf-demo/with-controller/scenario2/vswitch/vswitch.yaml +++ b/k8s/perf-demo/with-controller/scenario2/vswitch/vswitch.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -35,13 +36,12 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vswitch-vpp-cfg - - name: agent-config - configMap: - name: vswitch-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp - + - name: vpp-config + configMap: + name: vswitch-vpp-cfg + - name: agent-config + configMap: + name: vswitch-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp diff --git a/k8s/perf-demo/with-controller/scenario23/sfc/sfc.yaml b/k8s/perf-demo/with-controller/scenario23/sfc/sfc.yaml index e2a03a1902..c0c75147be 100644 --- a/k8s/perf-demo/with-controller/scenario23/sfc/sfc.yaml +++ b/k8s/perf-demo/with-controller/scenario23/sfc/sfc.yaml @@ -17,6 +17,6 @@ spec: - name: controller-config mountPath: /opt/sfc-controller/dev volumes: - - name: controller-config - configMap: - name: sfc-controller-cfg + - name: controller-config + configMap: + name: sfc-controller-cfg diff --git a/k8s/perf-demo/with-controller/scenario23/vnf/vnf-agent-cfg.yaml b/k8s/perf-demo/with-controller/scenario23/vnf/vnf-agent-cfg.yaml index 99c38bb48f..3b22475a40 100644 --- a/k8s/perf-demo/with-controller/scenario23/vnf/vnf-agent-cfg.yaml +++ b/k8s/perf-demo/with-controller/scenario23/vnf/vnf-agent-cfg.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: ConfigMap metadata: @@ -11,4 +12,3 @@ data: kafka.conf: | addrs: - "172.17.0.1:9092" - diff --git a/k8s/perf-demo/with-controller/scenario23/vnf/vnf1.yaml b/k8s/perf-demo/with-controller/scenario23/vnf/vnf1.yaml index 7c80c18bd2..67c6248545 100644 --- a/k8s/perf-demo/with-controller/scenario23/vnf/vnf1.yaml +++ b/k8s/perf-demo/with-controller/scenario23/vnf/vnf1.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -33,13 +34,12 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vnf1-vpp-cfg - - name: agent-config - configMap: - name: vnf-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp - + - name: vpp-config + configMap: + name: vnf1-vpp-cfg + - name: agent-config + configMap: + name: vnf-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp diff --git a/k8s/perf-demo/with-controller/scenario23/vnf/vnf2.yaml b/k8s/perf-demo/with-controller/scenario23/vnf/vnf2.yaml index ca54936d1e..ccb3c47946 100644 --- a/k8s/perf-demo/with-controller/scenario23/vnf/vnf2.yaml +++ b/k8s/perf-demo/with-controller/scenario23/vnf/vnf2.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -33,13 +34,12 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vnf2-vpp-cfg - - name: agent-config - configMap: - name: vnf-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp - + - name: vpp-config + configMap: + name: vnf2-vpp-cfg + - name: agent-config + configMap: + name: vnf-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp diff --git a/k8s/perf-demo/with-controller/scenario23/vnf/vnf3.yaml b/k8s/perf-demo/with-controller/scenario23/vnf/vnf3.yaml index 6142f8dd3e..4a6d7cb9be 100644 --- a/k8s/perf-demo/with-controller/scenario23/vnf/vnf3.yaml +++ b/k8s/perf-demo/with-controller/scenario23/vnf/vnf3.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -33,13 +34,12 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vnf3-vpp-cfg - - name: agent-config - configMap: - name: vnf-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp - + - name: vpp-config + configMap: + name: vnf3-vpp-cfg + - name: agent-config + configMap: + name: vnf-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp diff --git a/k8s/perf-demo/with-controller/scenario23/vswitch/vswitch-agent-cfg.yaml b/k8s/perf-demo/with-controller/scenario23/vswitch/vswitch-agent-cfg.yaml index 68ca242366..6e7aef4669 100644 --- a/k8s/perf-demo/with-controller/scenario23/vswitch/vswitch-agent-cfg.yaml +++ b/k8s/perf-demo/with-controller/scenario23/vswitch/vswitch-agent-cfg.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: ConfigMap metadata: @@ -11,4 +12,3 @@ data: kafka.conf: | addrs: - "172.17.0.1:9092" - diff --git a/k8s/perf-demo/with-controller/scenario23/vswitch/vswitch.yaml b/k8s/perf-demo/with-controller/scenario23/vswitch/vswitch.yaml index 5d83c557fa..96799185b0 100644 --- a/k8s/perf-demo/with-controller/scenario23/vswitch/vswitch.yaml +++ b/k8s/perf-demo/with-controller/scenario23/vswitch/vswitch.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -35,13 +36,12 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vswitch-vpp-cfg - - name: agent-config - configMap: - name: vswitch-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp - + - name: vpp-config + configMap: + name: vswitch-vpp-cfg + - name: agent-config + configMap: + name: vswitch-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp diff --git a/k8s/perf-demo/with-controller/scenario4/sfc/sfc-cfg.yaml b/k8s/perf-demo/with-controller/scenario4/sfc/sfc-cfg.yaml index e0381c517c..de0a916466 100644 --- a/k8s/perf-demo/with-controller/scenario4/sfc/sfc-cfg.yaml +++ b/k8s/perf-demo/with-controller/scenario4/sfc/sfc-cfg.yaml @@ -51,4 +51,3 @@ data: - port_labels: - port1 - port2 - diff --git a/k8s/perf-demo/with-controller/scenario4/sfc/sfc.yaml b/k8s/perf-demo/with-controller/scenario4/sfc/sfc.yaml index e2a03a1902..c0c75147be 100644 --- a/k8s/perf-demo/with-controller/scenario4/sfc/sfc.yaml +++ b/k8s/perf-demo/with-controller/scenario4/sfc/sfc.yaml @@ -17,6 +17,6 @@ spec: - name: controller-config mountPath: /opt/sfc-controller/dev volumes: - - name: controller-config - configMap: - name: sfc-controller-cfg + - name: controller-config + configMap: + name: sfc-controller-cfg diff --git a/k8s/perf-demo/with-controller/scenario4/vnf/vnf-agent-cfg.yaml b/k8s/perf-demo/with-controller/scenario4/vnf/vnf-agent-cfg.yaml index 99c38bb48f..3b22475a40 100644 --- a/k8s/perf-demo/with-controller/scenario4/vnf/vnf-agent-cfg.yaml +++ b/k8s/perf-demo/with-controller/scenario4/vnf/vnf-agent-cfg.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: ConfigMap metadata: @@ -11,4 +12,3 @@ data: kafka.conf: | addrs: - "172.17.0.1:9092" - diff --git a/k8s/perf-demo/with-controller/scenario4/vnf/vnf.yaml b/k8s/perf-demo/with-controller/scenario4/vnf/vnf.yaml index f1eeff6e95..3bfd57c2ff 100644 --- a/k8s/perf-demo/with-controller/scenario4/vnf/vnf.yaml +++ b/k8s/perf-demo/with-controller/scenario4/vnf/vnf.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -33,13 +34,12 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vnf-vpp-cfg - - name: agent-config - configMap: - name: vnf-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp - + - name: vpp-config + configMap: + name: vnf-vpp-cfg + - name: agent-config + configMap: + name: vnf-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp diff --git a/k8s/perf-demo/with-controller/scenario4/vswitch/vswitch-agent-cfg.yaml b/k8s/perf-demo/with-controller/scenario4/vswitch/vswitch-agent-cfg.yaml index 68ca242366..6e7aef4669 100644 --- a/k8s/perf-demo/with-controller/scenario4/vswitch/vswitch-agent-cfg.yaml +++ b/k8s/perf-demo/with-controller/scenario4/vswitch/vswitch-agent-cfg.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: ConfigMap metadata: @@ -11,4 +12,3 @@ data: kafka.conf: | addrs: - "172.17.0.1:9092" - diff --git a/k8s/perf-demo/with-controller/scenario4/vswitch/vswitch.yaml b/k8s/perf-demo/with-controller/scenario4/vswitch/vswitch.yaml index 7a8d30eab1..e8865de119 100644 --- a/k8s/perf-demo/with-controller/scenario4/vswitch/vswitch.yaml +++ b/k8s/perf-demo/with-controller/scenario4/vswitch/vswitch.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -38,16 +39,15 @@ spec: - name: docker-socket mountPath: /var/run/docker.sock volumes: - - name: vpp-config - configMap: - name: vswitch-vpp-cfg - - name: agent-config - configMap: - name: vswitch-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp - - name: docker-socket - hostPath: - path: /var/run/docker.sock - + - name: vpp-config + configMap: + name: vswitch-vpp-cfg + - name: agent-config + configMap: + name: vswitch-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp + - name: docker-socket + hostPath: + path: /var/run/docker.sock diff --git a/plugins/govppmux/govpp.conf b/plugins/govppmux/govpp.conf index 8692ee3502..f0fece8b53 100644 --- a/plugins/govppmux/govpp.conf +++ b/plugins/govppmux/govpp.conf @@ -1,6 +1,14 @@ -# set custom shared memory prefix for VPP -shm-prefix: vpp +# Custom shared memory prefix for VPP. Not used by default. +shm-prefix: # If VPP lost connection, this flag allows to automatically run the whole resync procedure -# for all registered plugins after reconnection +# for all registered plugins after reconnection. resync-after-reconnect: false + +# Requests failed because of the temporary VPP disconnect can be re-tried. Field defines number of +# retry attempts. Default is zero, meaning the feature is disabled. +retry-request-count: 0 + +# Defines timeout between retry attempts. Default value is 500ms. If retry-request-count is set to zero, +# the field has no effect. +retry-request-timeout: 500000000 diff --git a/plugins/govppmux/govpp_channel.go b/plugins/govppmux/govpp_channel.go new file mode 100644 index 0000000000..bfed46541e --- /dev/null +++ b/plugins/govppmux/govpp_channel.go @@ -0,0 +1,73 @@ +package govppmux + +import ( + "time" + + govppapi "git.fd.io/govpp.git/api" + "git.fd.io/govpp.git/core" + "github.com/ligato/cn-infra/logging/logrus" +) + +// goVppChan implements govpp channel interface. Instance is returned by NewAPIChannel() or NewAPIChannelBuffered(), +// and contains *govpp.channel dynamic type (vppChan field). Implemented methods allow custom handling of low-level +// govpp. +type goVppChan struct { + govppapi.Channel + // Retry data + retry retryConfig +} + +// govppRequestCtx is custom govpp RequestCtx. +type govppRequestCtx struct { + // Original request context + requestCtx govppapi.RequestCtx + // Function allowing to re-send request in case it's granted by the config file + sendRequest func(govppapi.Message) govppapi.RequestCtx + // Parameter for sendRequest + requestMsg govppapi.Message + // Retry data + retry retryConfig +} + +// helper struct holding info about retry configuration +type retryConfig struct { + attempts int + timeout time.Duration +} + +// ReceiveReply handles request and returns error if occurred. Also does retry if this option is available. +func (r *govppRequestCtx) ReceiveReply(reply govppapi.Message) error { + var timeout time.Duration + maxAttempts := r.retry.attempts + if r.retry.timeout > 0 { // Default value is 500ms + timeout = r.retry.timeout + } + + var err error + // Receive reply from original send + if err = r.requestCtx.ReceiveReply(reply); err == core.ErrNotConnected && maxAttempts > 0 { + // Try to re-sent requests + for attemptIdx := 1; attemptIdx <= maxAttempts; attemptIdx++ { + // Wait, then try again + time.Sleep(timeout) + logrus.DefaultLogger().Warnf("Govppmux: retrying binary API message %v, attempt: %d", + r.requestMsg.GetMessageName(), attemptIdx) + if err = r.sendRequest(r.requestMsg).ReceiveReply(reply); err != core.ErrNotConnected { + return err + } + } + } + + return err +} + +// SendRequest sends asynchronous request to the vpp and receives context used to receive reply. +// Plugin govppmux allows to re-send retry which failed because of disconnected vpp, if enabled. +func (c *goVppChan) SendRequest(request govppapi.Message) govppapi.RequestCtx { + sendRequest := c.Channel.SendRequest + // Send request now and wait for context + requestCtx := sendRequest(request) + + // Return context with value and function which allows to send request again if needed + return &govppRequestCtx{requestCtx, sendRequest, request, c.retry} +} diff --git a/plugins/govppmux/options.go b/plugins/govppmux/options.go new file mode 100644 index 0000000000..77798e189c --- /dev/null +++ b/plugins/govppmux/options.go @@ -0,0 +1,48 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package govppmux + +import ( + "github.com/ligato/cn-infra/health/statuscheck" +) + +// DefaultPlugin is default instance of Plugin +var DefaultPlugin = *NewPlugin() + +// NewPlugin creates a new Plugin with the provides Options +func NewPlugin(opts ...Option) *Plugin { + p := &Plugin{} + + p.PluginName = "govpp" + p.StatusCheck = &statuscheck.DefaultPlugin + + for _, o := range opts { + o(p) + } + + p.PluginDeps.Setup() + + return p +} + +// Option is a function that acts on a Plugin to inject Dependencies or configuration +type Option func(*Plugin) + +// UseDeps returns Option that can inject custom dependencies. +func UseDeps(cb func(*Deps)) Option { + return func(p *Plugin) { + cb(&p.Deps) + } +} diff --git a/plugins/govppmux/plugin_impl_govppmux.go b/plugins/govppmux/plugin_impl_govppmux.go index ce8518023b..a5db6c5a04 100644 --- a/plugins/govppmux/plugin_impl_govppmux.go +++ b/plugins/govppmux/plugin_impl_govppmux.go @@ -22,32 +22,27 @@ import ( "git.fd.io/govpp.git/adapter" govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/vpe" - govpp "git.fd.io/govpp.git/core" "github.com/ligato/cn-infra/datasync/resync" - "github.com/ligato/cn-infra/flavors/local" "github.com/ligato/cn-infra/health/statuscheck" + "github.com/ligato/cn-infra/infra" "github.com/ligato/cn-infra/logging" "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/plugins/govppmux/vppcalls" + aclvppcalls "github.com/ligato/vpp-agent/plugins/vpp/aclplugin/vppcalls" ) -func init() { - govpp.SetControlPingMessages(&vpe.ControlPing{}, &vpe.ControlPingReply{}) -} - -// GOVPPPlugin implements the govppmux plugin interface. -type GOVPPPlugin struct { - Deps // Inject. +// Plugin implements the govppmux plugin interface. +type Plugin struct { + Deps vppConn *govpp.Connection vppAdapter adapter.VppAdapter vppConChan chan govpp.ConnectionEvent - replyTimeout time.Duration - reconnectResync bool - lastConnErr error + lastConnErr error + + config *Config // Cancel can be used to cancel all goroutines and their jobs inside of the plugin. cancel context.CancelFunc @@ -58,8 +53,9 @@ type GOVPPPlugin struct { // Deps groups injected dependencies of plugin // so that they do not mix with other plugin fields. type Deps struct { - local.PluginInfraDeps // inject - Resync *resync.Plugin + infra.PluginDeps + StatusCheck statuscheck.PluginStatusWriter + Resync *resync.Plugin } // Config groups the configurable parameter of GoVpp. @@ -72,27 +68,24 @@ type Config struct { // shared memory segments are created directly in the SHM directory /dev/shm. ShmPrefix string `json:"shm-prefix"` ReconnectResync bool `json:"resync-after-reconnect"` + // How many times can be request resent in case vpp is suddenly disconnected. + RetryRequestCount int `json:"retry-request-count"` + // Time between request resend attempts. Default is 500ms. + RetryRequestTimeout time.Duration `json:"retry-request-timeout"` } -func defaultConfig() Config { - return Config{ +func defaultConfig() *Config { + return &Config{ HealthCheckProbeInterval: time.Second, HealthCheckReplyTimeout: 100 * time.Millisecond, HealthCheckThreshold: 1, ReplyTimeout: time.Second, + RetryRequestTimeout: 500 * time.Millisecond, } } -// FromExistingAdapter is used mainly for testing purposes. -func FromExistingAdapter(vppAdapter adapter.VppAdapter) *GOVPPPlugin { - ret := &GOVPPPlugin{ - vppAdapter: vppAdapter, - } - return ret -} - // Init is the entry point called by Agent Core. A single binary-API connection to VPP is established. -func (plugin *GOVPPPlugin) Init() error { +func (plugin *Plugin) Init() error { var err error govppLogger := plugin.Deps.Log.NewLogger("GoVpp") @@ -103,24 +96,19 @@ func (plugin *GOVPPPlugin) Init() error { plugin.PluginName = plugin.Deps.PluginName - cfg := defaultConfig() - found, err := plugin.PluginConfig.GetValue(&cfg) + plugin.config = defaultConfig() + found, err := plugin.Cfg.LoadValue(plugin.config) if err != nil { return err } - var shmPrefix string if found { - govpp.SetHealthCheckProbeInterval(cfg.HealthCheckProbeInterval) - govpp.SetHealthCheckReplyTimeout(cfg.HealthCheckReplyTimeout) - govpp.SetHealthCheckThreshold(cfg.HealthCheckThreshold) - plugin.replyTimeout = cfg.ReplyTimeout - plugin.reconnectResync = cfg.ReconnectResync - shmPrefix = cfg.ShmPrefix - plugin.Log.Debug("Setting govpp parameters", cfg) + govpp.SetHealthCheckProbeInterval(plugin.config.HealthCheckProbeInterval) + govpp.SetHealthCheckReplyTimeout(plugin.config.HealthCheckReplyTimeout) + govpp.SetHealthCheckThreshold(plugin.config.HealthCheckThreshold) } if plugin.vppAdapter == nil { - plugin.vppAdapter = NewVppAdapter(shmPrefix) + plugin.vppAdapter = NewVppAdapter(plugin.config.ShmPrefix) } else { plugin.Log.Info("Reusing existing vppAdapter") //this is used for testing purposes } @@ -138,13 +126,12 @@ func (plugin *GOVPPPlugin) Init() error { return errors.New("unable to connect to VPP") } vppConnectTime := time.Since(startTime) - plugin.Log.WithField("durationInNs", vppConnectTime.Nanoseconds()).Info("Connecting to VPP took ", vppConnectTime) + plugin.Log.Info("Connecting to VPP took ", vppConnectTime) plugin.retrieveVersion() // Register providing status reports (push mode) plugin.StatusCheck.Register(plugin.PluginName, nil) plugin.StatusCheck.ReportStateChange(plugin.PluginName, statuscheck.OK, nil) - plugin.Log.Debug("govpp connect success ", plugin.vppConn) var ctx context.Context ctx, plugin.cancel = context.WithCancel(context.Background()) @@ -154,7 +141,7 @@ func (plugin *GOVPPPlugin) Init() error { } // Close cleans up the resources allocated by the govppmux plugin. -func (plugin *GOVPPPlugin) Close() error { +func (plugin *Plugin) Close() error { plugin.cancel() plugin.wg.Wait() @@ -173,15 +160,19 @@ func (plugin *GOVPPPlugin) Close() error { // Example of binary API call from some plugin using GOVPP: // ch, _ := govpp_mux.NewAPIChannel() // ch.SendRequest(req).ReceiveReply -func (plugin *GOVPPPlugin) NewAPIChannel() (govppapi.Channel, error) { +func (plugin *Plugin) NewAPIChannel() (govppapi.Channel, error) { ch, err := plugin.vppConn.NewAPIChannel() if err != nil { return nil, err } - if plugin.replyTimeout > 0 { - ch.SetReplyTimeout(plugin.replyTimeout) + if plugin.config.ReplyTimeout > 0 { + ch.SetReplyTimeout(plugin.config.ReplyTimeout) + } + retryCfg := retryConfig{ + plugin.config.RetryRequestCount, + plugin.config.RetryRequestTimeout, } - return ch, nil + return &goVppChan{ch, retryCfg}, nil } // NewAPIChannelBuffered returns a new API channel for communication with VPP via govpp core. @@ -190,19 +181,23 @@ func (plugin *GOVPPPlugin) NewAPIChannel() (govppapi.Channel, error) { // Example of binary API call from some plugin using GOVPP: // ch, _ := govpp_mux.NewAPIChannelBuffered(100, 100) // ch.SendRequest(req).ReceiveReply -func (plugin *GOVPPPlugin) NewAPIChannelBuffered(reqChanBufSize, replyChanBufSize int) (govppapi.Channel, error) { +func (plugin *Plugin) NewAPIChannelBuffered(reqChanBufSize, replyChanBufSize int) (govppapi.Channel, error) { ch, err := plugin.vppConn.NewAPIChannelBuffered(reqChanBufSize, replyChanBufSize) if err != nil { return nil, err } - if plugin.replyTimeout > 0 { - ch.SetReplyTimeout(plugin.replyTimeout) + if plugin.config.ReplyTimeout > 0 { + ch.SetReplyTimeout(plugin.config.ReplyTimeout) + } + retryCfg := retryConfig{ + plugin.config.RetryRequestCount, + plugin.config.RetryRequestTimeout, } - return ch, nil + return &goVppChan{ch, retryCfg}, nil } // handleVPPConnectionEvents handles VPP connection events. -func (plugin *GOVPPPlugin) handleVPPConnectionEvents(ctx context.Context) { +func (plugin *Plugin) handleVPPConnectionEvents(ctx context.Context) { plugin.wg.Add(1) defer plugin.wg.Done() @@ -211,7 +206,7 @@ func (plugin *GOVPPPlugin) handleVPPConnectionEvents(ctx context.Context) { case status := <-plugin.vppConChan: if status.State == govpp.Connected { plugin.retrieveVersion() - if plugin.reconnectResync && plugin.lastConnErr != nil { + if plugin.config.ReconnectResync && plugin.lastConnErr != nil { plugin.Log.Info("Starting resync after VPP reconnect") if plugin.Resync != nil { plugin.Resync.DoResync() @@ -232,7 +227,7 @@ func (plugin *GOVPPPlugin) handleVPPConnectionEvents(ctx context.Context) { } } -func (plugin *GOVPPPlugin) retrieveVersion() { +func (plugin *Plugin) retrieveVersion() { vppAPIChan, err := plugin.vppConn.NewAPIChannel() if err != nil { plugin.Log.Error("getting new api channel failed:", err) @@ -247,5 +242,13 @@ func (plugin *GOVPPPlugin) retrieveVersion() { } plugin.Log.Debugf("version info: %+v", info) - plugin.Log.Infof("VPP version: %v (%v)", info.Version, info.BuildDate) + plugin.Log.Infof("VPP version: %q (%v)", info.Version, info.BuildDate) + + // Get VPP ACL plugin version + var aclVersion string + if aclVersion, err = aclvppcalls.GetACLPluginVersion(vppAPIChan); err != nil { + plugin.Log.Warn("getting acl version info failed:", err) + return + } + plugin.Log.Infof("VPP ACL plugin version: %q", aclVersion) } diff --git a/plugins/govppmux/vppcalls/vpe_vppcalls.go b/plugins/govppmux/vppcalls/vpe_vppcalls.go index 3c142576f0..ab9b0c322a 100644 --- a/plugins/govppmux/vppcalls/vpe_vppcalls.go +++ b/plugins/govppmux/vppcalls/vpe_vppcalls.go @@ -94,7 +94,7 @@ var ( memoryRe = regexp.MustCompile(`Thread\s+(\d+)\s+(\w+).?\s+(\d+) objects, ([\dkmg\.]+) of ([\dkmg\.]+) used, ([\dkmg\.]+) free, ([\dkmg\.]+) reclaimed, ([\dkmg\.]+) overhead, ([\dkmg\.]+) capacity`) ) -// GetNodeCounters retrieves node counters info +// GetMemory retrieves `show memory` info. func GetMemory(vppChan govppapi.Channel) (*MemoryInfo, error) { data, err := RunCliCommand(vppChan, "show memory") if err != nil { @@ -148,10 +148,10 @@ type NodeCounter struct { var ( // Regular expression to parse output from `show node counters` - nodeCountersRe = regexp.MustCompile(`^\s+(\d+)\s+([\w-\/]+)\s+([\w- ]+)$`) + nodeCountersRe = regexp.MustCompile(`^\s+(\d+)\s+([\w-\/]+)\s+(.+)$`) ) -// GetNodeCounters retrieves node counters info +// GetNodeCounters retrieves node counters info. func GetNodeCounters(vppChan govppapi.Channel) (*NodeCounterInfo, error) { data, err := RunCliCommand(vppChan, "show node counters") if err != nil { @@ -238,7 +238,7 @@ var ( runtimeItemsRe = regexp.MustCompile(`([\w-:\.]+)\s+(\w+(?:[ -]\w+)*)\s+(\d+)\s+(\d+)\s+(\d+)\s+([0-9\.e]+)\s+([0-9\.e]+)\s+`) ) -// GetNodeCounters retrieves node counters info +// GetRuntimeInfo retrieves how runtime info. func GetRuntimeInfo(vppChan govppapi.Channel) (*RuntimeInfo, error) { data, err := RunCliCommand(vppChan, "show runtime") if err != nil { diff --git a/plugins/govppmux/vppcalls/vpe_vppcalls_test.go b/plugins/govppmux/vppcalls/vpe_vppcalls_test.go index fae483b9bc..9437cca80f 100644 --- a/plugins/govppmux/vppcalls/vpe_vppcalls_test.go +++ b/plugins/govppmux/vppcalls/vpe_vppcalls_test.go @@ -214,6 +214,7 @@ func TestGetNodeCounters(t *testing.T) { 1 arp-input ARP replies sent 4 ip4-input ip4 spoofed local-address packet drops 2 memif1/1-output interface is down + 1 cdp-input good cdp packets (processed) ` ctx.MockVpp.MockReply(&vpe.CliInbandReply{ Reply: []byte(reply), @@ -223,7 +224,7 @@ func TestGetNodeCounters(t *testing.T) { info, err := vppcalls.GetNodeCounters(ctx.MockChannel) Expect(err).ShouldNot(HaveOccurred()) - Expect(info.Counters).To(HaveLen(9)) + Expect(info.Counters).To(HaveLen(10)) Expect(info.Counters[0]).To(Equal(vppcalls.NodeCounter{ Count: 32, Node: "ipsec-output-ip4", @@ -244,4 +245,9 @@ func TestGetNodeCounters(t *testing.T) { Node: "memif1/1-output", Reason: "interface is down", })) + Expect(info.Counters[9]).To(Equal(vppcalls.NodeCounter{ + Count: 1, + Node: "cdp-input", + Reason: "good cdp packets (processed)", + })) } diff --git a/plugins/linux/data_change.go b/plugins/linux/data_change.go index 54287b1be6..16a87277c2 100644 --- a/plugins/linux/data_change.go +++ b/plugins/linux/data_change.go @@ -68,7 +68,7 @@ func (plugin *Plugin) changePropagateRequest(dataChng datasync.ChangeEvent) erro // DataChangeIface propagates data change to the ifConfigurator. func (plugin *Plugin) dataChangeIface(diff bool, value *interfaces.LinuxInterfaces_Interface, prevValue *interfaces.LinuxInterfaces_Interface, - changeType datasync.PutDel) error { + changeType datasync.Op) error { plugin.Log.Debug("dataChangeIface ", diff, " ", changeType, " ", value, " ", prevValue) if datasync.Delete == changeType { @@ -81,7 +81,7 @@ func (plugin *Plugin) dataChangeIface(diff bool, value *interfaces.LinuxInterfac // DataChangeArp propagates data change to the arpConfigurator func (plugin *Plugin) dataChangeArp(diff bool, value *l3.LinuxStaticArpEntries_ArpEntry, prevValue *l3.LinuxStaticArpEntries_ArpEntry, - changeType datasync.PutDel) error { + changeType datasync.Op) error { plugin.Log.Debug("dataChangeArp ", diff, " ", changeType, " ", value, " ", prevValue) if datasync.Delete == changeType { @@ -94,7 +94,7 @@ func (plugin *Plugin) dataChangeArp(diff bool, value *l3.LinuxStaticArpEntries_A // DataChangeRoute propagates data change to the routeConfigurator func (plugin *Plugin) dataChangeRoute(diff bool, value *l3.LinuxStaticRoutes_Route, prevValue *l3.LinuxStaticRoutes_Route, - changeType datasync.PutDel) error { + changeType datasync.Op) error { plugin.Log.Debug("dataChangeRoute ", diff, " ", changeType, " ", value, " ", prevValue) if datasync.Delete == changeType { diff --git a/plugins/linux/data_resync.go b/plugins/linux/data_resync.go index 2d86fff851..e76f91053c 100644 --- a/plugins/linux/data_resync.go +++ b/plugins/linux/data_resync.go @@ -151,7 +151,7 @@ func resyncAppendRoutes(resyncData datasync.KeyValIterator, req *DataResyncReq) func (plugin *Plugin) subscribeWatcher() (err error) { plugin.Log.Debug("subscribeWatcher begin") - plugin.ifIndexes.WatchNameToIdx(plugin.PluginName, plugin.ifIndexesWatchChan) + plugin.ifIndexes.WatchNameToIdx(plugin.String(), plugin.ifIndexesWatchChan) plugin.watchDataReg, err = plugin.Watcher. Watch("linuxplugin", plugin.changeChan, plugin.resyncChan, interfaces.InterfaceKeyPrefix(), diff --git a/plugins/linux/ifplugin/data_resync.go b/plugins/linux/ifplugin/data_resync.go index 1d6f83f91e..53776652b6 100644 --- a/plugins/linux/ifplugin/data_resync.go +++ b/plugins/linux/ifplugin/data_resync.go @@ -19,7 +19,6 @@ import ( "fmt" "net" "strconv" - "strings" "time" "github.com/ligato/vpp-agent/plugins/linux/ifplugin/ifaceidx" @@ -236,12 +235,16 @@ func (plugin *LinuxInterfaceConfigurator) isLinuxIfModified(nbIf, linuxIf *inter nbIf.Enabled, linuxIf.Enabled) return true } - // Remove IPv6 link local addresses (default values) + // Remove link local addresses + var newIPIdx int for ipIdx, ipAddress := range linuxIf.IpAddresses { - if strings.HasPrefix(ipAddress, "fe80") { - linuxIf.IpAddresses = append(linuxIf.IpAddresses[:ipIdx], linuxIf.IpAddresses[ipIdx+1:]...) + if !net.ParseIP(linuxIf.IpAddresses[ipIdx]).IsLinkLocalUnicast() { + linuxIf.IpAddresses[newIPIdx] = ipAddress + newIPIdx++ } } + // Prune IP address list + linuxIf.IpAddresses = linuxIf.IpAddresses[:newIPIdx] // IP address count if len(nbIf.IpAddresses) != len(linuxIf.IpAddresses) { plugin.log.Debugf("Linux interface RESYNC comparison: ip address count does not match (NB: %d, Linux: %d)", @@ -339,9 +342,8 @@ func (plugin *LinuxInterfaceConfigurator) findLinuxInterface(nbIf *interfaces.Li if _, ok := err.(netlink.LinkNotFoundError); ok { // Interface was not found return nil, nil - } else { - return nil, fmt.Errorf("RESYNC Linux interface %s: %v", nbIf.HostIfName, err) } + return nil, fmt.Errorf("RESYNC Linux interface %s: %v", nbIf.HostIfName, err) } if linkIf == nil || linkIf.Attrs() == nil { return nil, fmt.Errorf("RESYNC Linux interface %v: link is nil", nbIf.HostIfName) diff --git a/plugins/linux/ifplugin/ifaceidx/iface_cache.go b/plugins/linux/ifplugin/ifaceidx/iface_cache.go index a68d8c38aa..3ee6d8ac95 100644 --- a/plugins/linux/ifplugin/ifaceidx/iface_cache.go +++ b/plugins/linux/ifplugin/ifaceidx/iface_cache.go @@ -50,5 +50,5 @@ func ParseNameFromKey(key string) (name string, err error) { return key[lastSlashPos+1:], nil } - return key, fmt.Errorf("Incorrect format of the key %s", key) + return key, fmt.Errorf("incorrect format of the key %s", key) } diff --git a/plugins/linux/ifplugin/ifaceidx/linux_if_index.go b/plugins/linux/ifplugin/ifaceidx/linux_if_index.go index 256179be6d..0a018d7119 100644 --- a/plugins/linux/ifplugin/ifaceidx/linux_if_index.go +++ b/plugins/linux/ifplugin/ifaceidx/linux_if_index.go @@ -15,7 +15,6 @@ package ifaceidx import ( - "github.com/ligato/cn-infra/core" log "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/idxvpp" "github.com/ligato/vpp-agent/idxvpp/nametoidx" @@ -57,7 +56,7 @@ type LinuxIfIndex interface { LookupNameByHostIfName(hostIfName string) []string // WatchNameToIdx allows to subscribe for watching changes in linuxIfIndex mapping. - WatchNameToIdx(subscriber core.PluginName, pluginChannel chan LinuxIfIndexDto) + WatchNameToIdx(subscriber string, pluginChannel chan LinuxIfIndexDto) } // LinuxIfIndexRW is mapping between software interface indices (used internally in VPP) @@ -170,7 +169,7 @@ func (linuxIfIdx *linuxIfIndex) UnregisterName(name string) (idx uint32, metadat } // WatchNameToIdx allows to subscribe for watching changes in linuxIfIndex mapping. -func (linuxIfIdx *linuxIfIndex) WatchNameToIdx(subscriber core.PluginName, pluginChannel chan LinuxIfIndexDto) { +func (linuxIfIdx *linuxIfIndex) WatchNameToIdx(subscriber string, pluginChannel chan LinuxIfIndexDto) { ch := make(chan idxvpp.NameToIdxDto) linuxIfIdx.mapping.Watch(subscriber, nametoidx.ToChan(ch)) go func() { diff --git a/plugins/linux/ifplugin/interface_config.go b/plugins/linux/ifplugin/interface_config.go index d3ebceefd5..820934b452 100644 --- a/plugins/linux/ifplugin/interface_config.go +++ b/plugins/linux/ifplugin/interface_config.go @@ -73,7 +73,7 @@ type LinuxInterfaceConfigurator struct { ifHandler linuxcalls.NetlinkAPI nsHandler nsplugin.NamespaceAPI - //Timer used to measure and store time + // Timer used to measure and store time stopwatch *measure.Stopwatch } @@ -158,9 +158,10 @@ func (plugin *LinuxInterfaceConfigurator) ConfigureLinuxInterface(linuxIf *inter case interfaces.LinuxInterfaces_AUTO_TAP: if linuxIf.Tap != nil && linuxIf.Tap.TempIfName != "" { return plugin.configureTapInterface(linuxIf.Tap.TempIfName, linuxIf) - } else { - return plugin.configureTapInterface(linuxIf.HostIfName, linuxIf) } + + return plugin.configureTapInterface(linuxIf.HostIfName, linuxIf) + default: return fmt.Errorf("unknown linux interface type: %v", linuxIf.Type) } @@ -973,7 +974,7 @@ func addressExists(configured []netlink.Addr, provided *net.IPNet) bool { return false } -// ResolveCreatedInterface resolves a new vpp interfaces +// ResolveCreatedVPPInterface resolves a new vpp interfaces func (plugin *LinuxInterfaceConfigurator) ResolveCreatedVPPInterface(ifConfigMetaData *vppIf.Interfaces_Interface) error { plugin.log.Infof("Linux IF configurator: resolve created vpp interface %v", ifConfigMetaData) @@ -1007,7 +1008,7 @@ func (plugin *LinuxInterfaceConfigurator) ResolveCreatedVPPInterface(ifConfigMet return plugin.configureTapInterface(hostIfName, linuxIf) } -// ResolveDeletedInterface resolves removed vpp interfaces +// ResolveDeletedVPPInterface resolves removed vpp interfaces func (plugin *LinuxInterfaceConfigurator) ResolveDeletedVPPInterface(ifConfigMetaData *vppIf.Interfaces_Interface) error { plugin.log.Infof("Linux IF configurator: resolve deleted vpp interface %v", ifConfigMetaData) diff --git a/plugins/linux/ifplugin/interface_config_test.go b/plugins/linux/ifplugin/interface_config_test.go index 4846eb333f..80247ca894 100644 --- a/plugins/linux/ifplugin/interface_config_test.go +++ b/plugins/linux/ifplugin/interface_config_test.go @@ -20,7 +20,6 @@ import ( "testing" "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/cn-infra/utils/safeclose" "github.com/ligato/vpp-agent/idxvpp/nametoidx" @@ -508,9 +507,9 @@ func ifTestSetup(t *testing.T) (*ifplugin.LinuxInterfaceConfigurator, *linuxmock RegisterTestingT(t) // Loggers - pluginLog := logging.ForPlugin("linux-if-log", logrus.NewLogRegistry()) + pluginLog := logging.ForPlugin("linux-if-log") pluginLog.SetLevel(logging.DebugLevel) - nsHandleLog := logging.ForPlugin("ns-handle-log", logrus.NewLogRegistry()) + nsHandleLog := logging.ForPlugin("ns-handle-log") nsHandleLog.SetLevel(logging.DebugLevel) // Linux interface indexes swIfIndexes := ifaceidx.NewLinuxIfIndex(nametoidx.NewNameToIdx(pluginLog, "if", nil)) @@ -535,6 +534,7 @@ func ifTestTeardown(plugin *ifplugin.LinuxInterfaceConfigurator, Expect(err).To(BeNil()) err = plugin.Close() Expect(err).To(BeNil()) + logging.DefaultRegistry.ClearRegistry() } /* Linux interface Test Data */ diff --git a/plugins/linux/ifplugin/interface_stage.go b/plugins/linux/ifplugin/interface_stage.go index 1dd5f207aa..5d84bf0ab0 100644 --- a/plugins/linux/ifplugin/interface_stage.go +++ b/plugins/linux/ifplugin/interface_stage.go @@ -49,7 +49,7 @@ type LinuxInterfaceStateUpdater struct { } // Init channels for interface state watcher, start it in separate go routine and subscribe to default namespace -func (plugin *LinuxInterfaceStateUpdater) Init(logger logging.PluginLogger, ctx context.Context, ifIndexes ifaceidx.LinuxIfIndexRW, +func (plugin *LinuxInterfaceStateUpdater) Init(ctx context.Context, logger logging.PluginLogger, ifIndexes ifaceidx.LinuxIfIndexRW, stateChan chan *LinuxInterfaceStateNotification) error { // Logger plugin.log = logger.NewLogger("-if-state") diff --git a/plugins/linux/ifplugin/linuxcalls/admin_linuxcalls.go b/plugins/linux/ifplugin/linuxcalls/admin_linuxcalls.go index 5202313815..5a6847baa8 100644 --- a/plugins/linux/ifplugin/linuxcalls/admin_linuxcalls.go +++ b/plugins/linux/ifplugin/linuxcalls/admin_linuxcalls.go @@ -37,7 +37,7 @@ import ( ) // SetInterfaceDown calls Netlink API LinkSetDown. -func (handler *netLinkHandler) SetInterfaceDown(ifName string) error { +func (handler *NetLinkHandler) SetInterfaceDown(ifName string) error { defer func(t time.Time) { handler.stopwatch.TimeLog("interface-admin-down").LogTimeEntry(time.Since(t)) }(time.Now()) @@ -50,7 +50,7 @@ func (handler *netLinkHandler) SetInterfaceDown(ifName string) error { } // SetInterfaceUp calls Netlink API LinkSetUp. -func (handler *netLinkHandler) SetInterfaceUp(ifName string) error { +func (handler *NetLinkHandler) SetInterfaceUp(ifName string) error { defer func(t time.Time) { handler.stopwatch.TimeLog("interface-admin-up").LogTimeEntry(time.Since(t)) }(time.Now()) diff --git a/plugins/linux/ifplugin/linuxcalls/ip_linuxcalls.go b/plugins/linux/ifplugin/linuxcalls/ip_linuxcalls.go index 8e6890dc32..1fccb48681 100644 --- a/plugins/linux/ifplugin/linuxcalls/ip_linuxcalls.go +++ b/plugins/linux/ifplugin/linuxcalls/ip_linuxcalls.go @@ -38,7 +38,7 @@ import ( ) // GetAddressList calls AddrList netlink API -func (handler *netLinkHandler) GetAddressList(ifName string) ([]netlink.Addr, error) { +func (handler *NetLinkHandler) GetAddressList(ifName string) ([]netlink.Addr, error) { defer func(t time.Time) { handler.stopwatch.TimeLog("get-address-list").LogTimeEntry(time.Since(t)) }(time.Now()) @@ -52,7 +52,7 @@ func (handler *netLinkHandler) GetAddressList(ifName string) ([]netlink.Addr, er } // AddInterfaceIP calls AddrAdd Netlink API. -func (handler *netLinkHandler) AddInterfaceIP(ifName string, addr *net.IPNet) error { +func (handler *NetLinkHandler) AddInterfaceIP(ifName string, addr *net.IPNet) error { defer func(t time.Time) { handler.stopwatch.TimeLog("add-interface-ip").LogTimeEntry(time.Since(t)) }(time.Now()) @@ -66,7 +66,7 @@ func (handler *netLinkHandler) AddInterfaceIP(ifName string, addr *net.IPNet) er } // DelInterfaceIP calls AddrDel Netlink API. -func (handler *netLinkHandler) DelInterfaceIP(ifName string, addr *net.IPNet) error { +func (handler *NetLinkHandler) DelInterfaceIP(ifName string, addr *net.IPNet) error { defer func(t time.Time) { handler.stopwatch.TimeLog("del-interface-ip").LogTimeEntry(time.Since(t)) }(time.Now()) @@ -80,7 +80,7 @@ func (handler *netLinkHandler) DelInterfaceIP(ifName string, addr *net.IPNet) er } // SetInterfaceMTU calls LinkSetMTU Netlink API. -func (handler *netLinkHandler) SetInterfaceMTU(ifName string, mtu int) error { +func (handler *NetLinkHandler) SetInterfaceMTU(ifName string, mtu int) error { defer func(t time.Time) { handler.stopwatch.TimeLog("set-interface-mtu").LogTimeEntry(time.Since(t)) }(time.Now()) diff --git a/plugins/linux/ifplugin/linuxcalls/link_linuxcalls.go b/plugins/linux/ifplugin/linuxcalls/link_linuxcalls.go index d967d513d3..5a51ffb368 100644 --- a/plugins/linux/ifplugin/linuxcalls/link_linuxcalls.go +++ b/plugins/linux/ifplugin/linuxcalls/link_linuxcalls.go @@ -38,7 +38,7 @@ import ( ) // GetLinkByName calls netlink API to get Link type from interface name -func (handler *netLinkHandler) GetLinkByName(ifName string) (netlink.Link, error) { +func (handler *NetLinkHandler) GetLinkByName(ifName string) (netlink.Link, error) { defer func(t time.Time) { handler.stopwatch.TimeLog("get-link-from-interface").LogTimeEntry(time.Since(t)) }(time.Now()) @@ -47,7 +47,7 @@ func (handler *netLinkHandler) GetLinkByName(ifName string) (netlink.Link, error } // GetLinkList calls netlink API to get all Links in namespace -func (handler *netLinkHandler) GetLinkList() ([]netlink.Link, error) { +func (handler *NetLinkHandler) GetLinkList() ([]netlink.Link, error) { defer func(t time.Time) { handler.stopwatch.TimeLog("get-link-list").LogTimeEntry(time.Since(t)) }(time.Now()) @@ -56,7 +56,7 @@ func (handler *netLinkHandler) GetLinkList() ([]netlink.Link, error) { } // GetInterfaceType returns the type (string representation) of a given interface. -func (handler *netLinkHandler) GetInterfaceType(ifName string) (string, error) { +func (handler *NetLinkHandler) GetInterfaceType(ifName string) (string, error) { defer func(t time.Time) { handler.stopwatch.TimeLog("get-interface-type").LogTimeEntry(time.Since(t)) }(time.Now()) @@ -69,7 +69,7 @@ func (handler *netLinkHandler) GetInterfaceType(ifName string) (string, error) { } // InterfaceExists checks if interface with a given name exists. -func (handler *netLinkHandler) InterfaceExists(ifName string) (bool, error) { +func (handler *NetLinkHandler) InterfaceExists(ifName string) (bool, error) { defer func(t time.Time) { handler.stopwatch.TimeLog("interface-exists").LogTimeEntry(time.Since(t)) }(time.Now()) @@ -85,7 +85,7 @@ func (handler *netLinkHandler) InterfaceExists(ifName string) (bool, error) { } // RenameInterface changes the name of the interface to . -func (handler *netLinkHandler) RenameInterface(ifName string, newName string) error { +func (handler *NetLinkHandler) RenameInterface(ifName string, newName string) error { defer func(t time.Time) { handler.stopwatch.TimeLog("rename-interface").LogTimeEntry(time.Since(t)) }(time.Now()) @@ -110,7 +110,7 @@ func (handler *netLinkHandler) RenameInterface(ifName string, newName string) er } // GetInterfaceByName return *net.Interface type from interface name -func (handler *netLinkHandler) GetInterfaceByName(ifName string) (*net.Interface, error) { +func (handler *NetLinkHandler) GetInterfaceByName(ifName string) (*net.Interface, error) { defer func(t time.Time) { handler.stopwatch.TimeLog("get-interface-by-name").LogTimeEntry(time.Since(t)) }(time.Now()) diff --git a/plugins/linux/ifplugin/linuxcalls/mac_linuxcalls.go b/plugins/linux/ifplugin/linuxcalls/mac_linuxcalls.go index ed5a0c504f..11540d71c3 100644 --- a/plugins/linux/ifplugin/linuxcalls/mac_linuxcalls.go +++ b/plugins/linux/ifplugin/linuxcalls/mac_linuxcalls.go @@ -38,7 +38,7 @@ import ( ) // SetInterfaceMac calls LinkSetHardwareAddr netlink API. -func (handler *netLinkHandler) SetInterfaceMac(ifName string, macAddress string) error { +func (handler *NetLinkHandler) SetInterfaceMac(ifName string, macAddress string) error { defer func(t time.Time) { handler.stopwatch.TimeLog("set-interface-mac").LogTimeEntry(time.Since(t)) }(time.Now()) diff --git a/plugins/linux/ifplugin/linuxcalls/netlink_api.go b/plugins/linux/ifplugin/linuxcalls/netlink_api.go index 873635ff88..7ee532748c 100644 --- a/plugins/linux/ifplugin/linuxcalls/netlink_api.go +++ b/plugins/linux/ifplugin/linuxcalls/netlink_api.go @@ -57,14 +57,14 @@ type NetlinkAPI interface { GetInterfaceByName(ifName string) (*net.Interface, error) } -// netLinkHandler is accessor for netlink methods -type netLinkHandler struct { +// NetLinkHandler is accessor for netlink methods +type NetLinkHandler struct { stopwatch *measure.Stopwatch } // NewNetLinkHandler creates new instance of netlink handler -func NewNetLinkHandler(stopwatch *measure.Stopwatch) *netLinkHandler { - return &netLinkHandler{ +func NewNetLinkHandler(stopwatch *measure.Stopwatch) *NetLinkHandler { + return &NetLinkHandler{ stopwatch: stopwatch, } } diff --git a/plugins/linux/ifplugin/linuxcalls/veth_linuxcalls.go b/plugins/linux/ifplugin/linuxcalls/veth_linuxcalls.go index 34b1630e52..cc54a95364 100644 --- a/plugins/linux/ifplugin/linuxcalls/veth_linuxcalls.go +++ b/plugins/linux/ifplugin/linuxcalls/veth_linuxcalls.go @@ -38,7 +38,7 @@ import ( ) // AddVethInterfacePair calls LinkAdd Netlink API for the Netlink.Veth interface type. -func (handler *netLinkHandler) AddVethInterfacePair(ifName, peerIfName string) error { +func (handler *NetLinkHandler) AddVethInterfacePair(ifName, peerIfName string) error { defer func(t time.Time) { handler.stopwatch.TimeLog("add-veth-iface-pair").LogTimeEntry(time.Since(t)) }(time.Now()) @@ -58,7 +58,7 @@ func (handler *netLinkHandler) AddVethInterfacePair(ifName, peerIfName string) e } // DelVethInterfacePair calls LinkDel Netlink API for the Netlink.Veth interface type. -func (handler *netLinkHandler) DelVethInterfacePair(ifName, peerIfName string) error { +func (handler *NetLinkHandler) DelVethInterfacePair(ifName, peerIfName string) error { defer func(t time.Time) { handler.stopwatch.TimeLog("del-veth-iface-pair").LogTimeEntry(time.Since(t)) }(time.Now()) @@ -78,7 +78,7 @@ func (handler *netLinkHandler) DelVethInterfacePair(ifName, peerIfName string) e } // GetVethPeerName return the peer name for a given VETH interface. -func (handler *netLinkHandler) GetVethPeerName(ifName string) (string, error) { +func (handler *NetLinkHandler) GetVethPeerName(ifName string) (string, error) { defer func(t time.Time) { handler.stopwatch.TimeLog("get-veth-peer-name").LogTimeEntry(time.Since(t)) }(time.Now()) diff --git a/plugins/linux/l3plugin/arp_config.go b/plugins/linux/l3plugin/arp_config.go index d938c81d8b..df5a996a30 100644 --- a/plugins/linux/l3plugin/arp_config.go +++ b/plugins/linux/l3plugin/arp_config.go @@ -46,7 +46,7 @@ type LinuxArpConfigurator struct { // Mappings ifIndexes ifaceidx.LinuxIfIndexRW arpIndexes l3idx.LinuxARPIndexRW - arpIfCache map[string]*arpToInterface // Cache for non-configurable ARPs due to missing interface + arpIfCache map[string]*ArpToInterface // Cache for non-configurable ARPs due to missing interface arpIdxSeq uint32 // Linux namespace/calls handler @@ -59,7 +59,7 @@ type LinuxArpConfigurator struct { // ArpToInterface is an object which stores ARP-to-interface pairs used in cache. // Field 'isAdd' marks whether the entry should be added or removed -type arpToInterface struct { +type ArpToInterface struct { arp *l3.LinuxStaticArpEntries_ArpEntry ifName string isAdd bool @@ -71,7 +71,7 @@ func (plugin *LinuxArpConfigurator) GetArpIndexes() l3idx.LinuxARPIndexRW { } // GetArpInterfaceCache returns internal non-configurable interface cache, mainly for testing purpose -func (plugin *LinuxArpConfigurator) GetArpInterfaceCache() map[string]*arpToInterface { +func (plugin *LinuxArpConfigurator) GetArpInterfaceCache() map[string]*ArpToInterface { return plugin.arpIfCache } @@ -85,7 +85,7 @@ func (plugin *LinuxArpConfigurator) Init(logger logging.PluginLogger, l3Handler // In-memory mappings plugin.ifIndexes = ifIndexes plugin.arpIndexes = l3idx.NewLinuxARPIndex(nametoidx.NewNameToIdx(plugin.log, "linux_arp_indexes", nil)) - plugin.arpIfCache = make(map[string]*arpToInterface) + plugin.arpIfCache = make(map[string]*ArpToInterface) plugin.arpIdxSeq = 1 // L3 and namespace handler @@ -117,7 +117,7 @@ func (plugin *LinuxArpConfigurator) ConfigureLinuxStaticArpEntry(arpEntry *l3.Li if !found || ifData == nil { plugin.log.Debugf("cannot create ARP entry %s due to missing interface %s (found: %v, data: %v), cached", arpEntry.Name, arpEntry.Interface, found, ifData) - plugin.arpIfCache[arpEntry.Name] = &arpToInterface{ + plugin.arpIfCache[arpEntry.Name] = &ArpToInterface{ arp: arpEntry, ifName: arpEntry.Interface, isAdd: true, @@ -266,7 +266,7 @@ func (plugin *LinuxArpConfigurator) DeleteLinuxStaticArpEntry(arpEntry *l3.Linux _, ifData, foundIface := plugin.ifIndexes.LookupIdx(arpEntry.Interface) if !foundIface || ifData == nil { plugin.log.Debugf("cannot remove ARP entry %v due to missing interface %v, cached", arpEntry.Name, arpEntry.Interface) - plugin.arpIfCache[arpEntry.Name] = &arpToInterface{ + plugin.arpIfCache[arpEntry.Name] = &ArpToInterface{ arp: arpEntry, ifName: arpEntry.Interface, } @@ -432,7 +432,7 @@ func (plugin *LinuxArpConfigurator) ResolveDeletedInterface(ifName string, ifIdx HardwareAddr: mac, })) // Cache - plugin.arpIfCache[arpName] = &arpToInterface{ + plugin.arpIfCache[arpName] = &ArpToInterface{ arp: arp, ifName: ifName, isAdd: true, diff --git a/plugins/linux/l3plugin/arp_config_test.go b/plugins/linux/l3plugin/arp_config_test.go index 5399d72754..e563968975 100644 --- a/plugins/linux/l3plugin/arp_config_test.go +++ b/plugins/linux/l3plugin/arp_config_test.go @@ -18,8 +18,9 @@ import ( "fmt" "testing" + "net" + "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/linux/ifplugin/ifaceidx" @@ -29,7 +30,6 @@ import ( "github.com/ligato/vpp-agent/tests/linuxmock" . "github.com/onsi/gomega" "github.com/vishvananda/netlink" - "net" ) /* Linux ARP configurator init and close */ @@ -156,9 +156,9 @@ func arpTestSetup(t *testing.T) (*l3plugin.LinuxArpConfigurator, *linuxmock.L3Ne RegisterTestingT(t) // Loggers - pluginLog := logging.ForPlugin("linux-arp-log", logrus.NewLogRegistry()) + pluginLog := logging.ForPlugin("linux-arp-log") pluginLog.SetLevel(logging.DebugLevel) - nsHandleLog := logging.ForPlugin("ns-handle-log", logrus.NewLogRegistry()) + nsHandleLog := logging.ForPlugin("ns-handle-log") nsHandleLog.SetLevel(logging.DebugLevel) // Linux interface indexes ifIndexes := ifaceidx.NewLinuxIfIndex(nametoidx.NewNameToIdx(pluginLog, "if", nil)) @@ -175,6 +175,7 @@ func arpTestSetup(t *testing.T) (*l3plugin.LinuxArpConfigurator, *linuxmock.L3Ne func arpTestTeardown(plugin *l3plugin.LinuxArpConfigurator) { err := plugin.Close() Expect(err).To(BeNil()) + logging.DefaultRegistry.ClearRegistry() } func getArpID(ifIdx uint32, ip, mac string) *netlink.Neigh { diff --git a/plugins/linux/l3plugin/l3idx/linux_l3_arp_index.go b/plugins/linux/l3plugin/l3idx/linux_l3_arp_index.go index 935fcdfeba..6215b1b4e2 100644 --- a/plugins/linux/l3plugin/l3idx/linux_l3_arp_index.go +++ b/plugins/linux/l3plugin/l3idx/linux_l3_arp_index.go @@ -15,7 +15,6 @@ package l3idx import ( - "github.com/ligato/cn-infra/core" "github.com/ligato/vpp-agent/idxvpp" "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/linux/model/l3" @@ -38,7 +37,7 @@ type LinuxARPIndex interface { LookupNameByHostIfName(hostIfName string) []string // WatchNameToIdx allows to subscribe for watching changes in linuxIfIndex mapping - WatchNameToIdx(subscriber core.PluginName, pluginChannel chan LinuxARPIndexDto) + WatchNameToIdx(subscriber string, pluginChannel chan LinuxARPIndexDto) } // LinuxARPIndexRW is mapping between software ARP indexes (used internally in VPP) @@ -111,7 +110,7 @@ func (linuxArpIndex *linuxArpIndex) UnregisterName(name string) (idx uint32, met } // WatchNameToIdx allows to subscribe for watching changes in linuxIfIndex mapping -func (linuxArpIndex *linuxArpIndex) WatchNameToIdx(subscriber core.PluginName, pluginChannel chan LinuxARPIndexDto) { +func (linuxArpIndex *linuxArpIndex) WatchNameToIdx(subscriber string, pluginChannel chan LinuxARPIndexDto) { ch := make(chan idxvpp.NameToIdxDto) linuxArpIndex.mapping.Watch(subscriber, nametoidx.ToChan(ch)) go func() { diff --git a/plugins/linux/l3plugin/l3idx/linux_l3_route_index.go b/plugins/linux/l3plugin/l3idx/linux_l3_route_index.go index 00b76a3c9b..8907086023 100644 --- a/plugins/linux/l3plugin/l3idx/linux_l3_route_index.go +++ b/plugins/linux/l3plugin/l3idx/linux_l3_route_index.go @@ -17,7 +17,6 @@ package l3idx import ( "net" - "github.com/ligato/cn-infra/core" "github.com/ligato/vpp-agent/idxvpp" "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/linux/model/l3" @@ -44,7 +43,7 @@ type LinuxRouteIndex interface { LookupRouteByIP(ns *l3.LinuxStaticRoutes_Route_Namespace, ipAddress string) (*l3.LinuxStaticRoutes_Route, error) // WatchNameToIdx allows to subscribe for watching changes in linuxIfIndex mapping - WatchNameToIdx(subscriber core.PluginName, pluginChannel chan LinuxRouteIndexDto) + WatchNameToIdx(subscriber string, pluginChannel chan LinuxRouteIndexDto) } // LinuxRouteIndexRW is mapping between software route indexes (used internally in VPP) @@ -160,7 +159,7 @@ func (linuxRouteIndex *linuxRouteIndex) UnregisterName(name string) (idx uint32, } // WatchNameToIdx allows to subscribe for watching changes in linuxIfIndex mapping -func (linuxRouteIndex *linuxRouteIndex) WatchNameToIdx(subscriber core.PluginName, pluginChannel chan LinuxRouteIndexDto) { +func (linuxRouteIndex *linuxRouteIndex) WatchNameToIdx(subscriber string, pluginChannel chan LinuxRouteIndexDto) { ch := make(chan idxvpp.NameToIdxDto) linuxRouteIndex.mapping.Watch(subscriber, nametoidx.ToChan(ch)) go func() { diff --git a/plugins/linux/l3plugin/linuxcalls/arp_linuxcalls.go b/plugins/linux/l3plugin/linuxcalls/arp_linuxcalls.go index b5166b1b48..5024e2b4e7 100644 --- a/plugins/linux/l3plugin/linuxcalls/arp_linuxcalls.go +++ b/plugins/linux/l3plugin/linuxcalls/arp_linuxcalls.go @@ -23,7 +23,7 @@ import ( ) // AddArpEntry creates a new static ARP entry -func (handler *netLinkHandler) AddArpEntry(name string, arpEntry *netlink.Neigh) error { +func (handler *NetLinkHandler) AddArpEntry(name string, arpEntry *netlink.Neigh) error { defer func(t time.Time) { handler.stopwatch.TimeLog("add-arp-entry").LogTimeEntry(time.Since(t)) }(time.Now()) @@ -32,7 +32,7 @@ func (handler *netLinkHandler) AddArpEntry(name string, arpEntry *netlink.Neigh) } // SetArpEntry updates existing arp entry -func (handler *netLinkHandler) SetArpEntry(name string, arpEntry *netlink.Neigh) error { +func (handler *NetLinkHandler) SetArpEntry(name string, arpEntry *netlink.Neigh) error { defer func(t time.Time) { handler.stopwatch.TimeLog("set-arp-entry").LogTimeEntry(time.Since(t)) }(time.Now()) @@ -41,7 +41,7 @@ func (handler *netLinkHandler) SetArpEntry(name string, arpEntry *netlink.Neigh) } // DelArpEntry removes an static ARP entry -func (handler *netLinkHandler) DelArpEntry(name string, arpEntry *netlink.Neigh) error { +func (handler *NetLinkHandler) DelArpEntry(name string, arpEntry *netlink.Neigh) error { defer func(t time.Time) { handler.stopwatch.TimeLog("del-arp-entry").LogTimeEntry(time.Since(t)) }(time.Now()) @@ -51,7 +51,7 @@ func (handler *netLinkHandler) DelArpEntry(name string, arpEntry *netlink.Neigh) // GetArpEntries reads all configured static ARP entries for given interface // and parameters works as filters, if they are set to zero, all arp entries are returned -func (handler *netLinkHandler) GetArpEntries(interfaceIdx int, family int) ([]netlink.Neigh, error) { +func (handler *NetLinkHandler) GetArpEntries(interfaceIdx int, family int) ([]netlink.Neigh, error) { defer func(t time.Time) { handler.stopwatch.TimeLog("get-arp-entries").LogTimeEntry(time.Since(t)) }(time.Now()) diff --git a/plugins/linux/l3plugin/linuxcalls/netlink_api.go b/plugins/linux/l3plugin/linuxcalls/netlink_api.go index 4bad6c07bc..53560ff560 100644 --- a/plugins/linux/l3plugin/linuxcalls/netlink_api.go +++ b/plugins/linux/l3plugin/linuxcalls/netlink_api.go @@ -39,14 +39,14 @@ type NetlinkAPI interface { DelStaticRoute(name string, route *netlink.Route) error } -// netLinkHandler is accessor for netlink methods -type netLinkHandler struct { +// NetLinkHandler is accessor for netlink methods +type NetLinkHandler struct { stopwatch *measure.Stopwatch } // NewNetLinkHandler creates new instance of netlink handler -func NewNetLinkHandler(stopwatch *measure.Stopwatch) *netLinkHandler { - return &netLinkHandler{ +func NewNetLinkHandler(stopwatch *measure.Stopwatch) *NetLinkHandler { + return &NetLinkHandler{ stopwatch: stopwatch, } } diff --git a/plugins/linux/l3plugin/linuxcalls/route_linuxcalls.go b/plugins/linux/l3plugin/linuxcalls/route_linuxcalls.go index f613219659..2ed25de6e0 100644 --- a/plugins/linux/l3plugin/linuxcalls/route_linuxcalls.go +++ b/plugins/linux/l3plugin/linuxcalls/route_linuxcalls.go @@ -23,7 +23,7 @@ import ( ) // AddStaticRoute creates the new static route -func (handler *netLinkHandler) AddStaticRoute(name string, route *netlink.Route) error { +func (handler *NetLinkHandler) AddStaticRoute(name string, route *netlink.Route) error { defer func(t time.Time) { handler.stopwatch.TimeLog("add-static-route").LogTimeEntry(time.Since(t)) }(time.Now()) @@ -32,7 +32,7 @@ func (handler *netLinkHandler) AddStaticRoute(name string, route *netlink.Route) } // ReplaceStaticRoute removes the static route -func (handler *netLinkHandler) ReplaceStaticRoute(name string, route *netlink.Route) error { +func (handler *NetLinkHandler) ReplaceStaticRoute(name string, route *netlink.Route) error { defer func(t time.Time) { handler.stopwatch.TimeLog("replace-static-route").LogTimeEntry(time.Since(t)) }(time.Now()) @@ -41,7 +41,7 @@ func (handler *netLinkHandler) ReplaceStaticRoute(name string, route *netlink.Ro } // DelStaticRoute removes the static route -func (handler *netLinkHandler) DelStaticRoute(name string, route *netlink.Route) error { +func (handler *NetLinkHandler) DelStaticRoute(name string, route *netlink.Route) error { defer func(t time.Time) { handler.stopwatch.TimeLog("del-static-route").LogTimeEntry(time.Since(t)) }(time.Now()) diff --git a/plugins/linux/l3plugin/route_config.go b/plugins/linux/l3plugin/route_config.go index fd0651a577..fc8233fefb 100644 --- a/plugins/linux/l3plugin/route_config.go +++ b/plugins/linux/l3plugin/route_config.go @@ -504,7 +504,7 @@ func (plugin *LinuxRouteConfigurator) createDefaultRoute(netLinkRoute *netlink.R // Gateway gateway := net.ParseIP(route.GwAddr) if gateway == nil { - fmt.Errorf("unable to create route %s as default, gateway is nil", route.Name) + return fmt.Errorf("unable to create route %s as default, gateway is nil", route.Name) } netLinkRoute.Gw = gateway diff --git a/plugins/linux/l3plugin/route_config_test.go b/plugins/linux/l3plugin/route_config_test.go index 44196dcc32..03453ba067 100644 --- a/plugins/linux/l3plugin/route_config_test.go +++ b/plugins/linux/l3plugin/route_config_test.go @@ -20,7 +20,6 @@ import ( "testing" "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/linux/ifplugin/ifaceidx" @@ -321,9 +320,9 @@ func routeTestSetup(t *testing.T) (*l3plugin.LinuxRouteConfigurator, *linuxmock. RegisterTestingT(t) // Loggers - pluginLog := logging.ForPlugin("linux-route-log", logrus.NewLogRegistry()) + pluginLog := logging.ForPlugin("linux-route-log") pluginLog.SetLevel(logging.DebugLevel) - nsHandleLog := logging.ForPlugin("ns-handle-log", logrus.NewLogRegistry()) + nsHandleLog := logging.ForPlugin("ns-handle-log") nsHandleLog.SetLevel(logging.DebugLevel) // Linux interface indexes ifIndexes := ifaceidx.NewLinuxIfIndex(nametoidx.NewNameToIdx(pluginLog, "if", nil)) @@ -340,6 +339,7 @@ func routeTestSetup(t *testing.T) (*l3plugin.LinuxRouteConfigurator, *linuxmock. func routeTestTeardown(plugin *l3plugin.LinuxRouteConfigurator) { err := plugin.Close() Expect(err).To(BeNil()) + logging.DefaultRegistry.ClearRegistry() } func getRouteID(dst, gw string, ifIdx, table uint32) *netlink.Route { diff --git a/plugins/linux/linuxplugin.conf b/plugins/linux/linuxplugin.conf index ae4764e219..6e09eb0564 100644 --- a/plugins/linux/linuxplugin.conf +++ b/plugins/linux/linuxplugin.conf @@ -1,6 +1,6 @@ # Enable or disable feature to measure netlink API call duration. Measured time is shown directly in log (info level). # Measurement is taken also for certain procedures, like resync of plugin startup. Turned off by default. -stopwatch: true +stopwatch: false # Used to disable entire linux plugin functionality. Turned off by default. disabled: false \ No newline at end of file diff --git a/plugins/linux/linuxplugin_init.go b/plugins/linux/linuxplugin_init.go index eb70015a90..026854434e 100644 --- a/plugins/linux/linuxplugin_init.go +++ b/plugins/linux/linuxplugin_init.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package linuxplugin implements the Linux plugin that handles management +// Package linux implements the Linux plugin that handles management // of Linux VETH interfaces. package linux @@ -21,8 +21,10 @@ import ( "sync" "github.com/ligato/cn-infra/datasync" - "github.com/ligato/cn-infra/flavors/local" + "github.com/ligato/cn-infra/health/statuscheck" + "github.com/ligato/cn-infra/infra" "github.com/ligato/cn-infra/logging/measure" + "github.com/ligato/cn-infra/servicelabel" "github.com/ligato/cn-infra/utils/safeclose" "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/linux/ifplugin" @@ -77,14 +79,17 @@ type Plugin struct { // Deps groups injected dependencies of plugin // so that they do not mix with other plugin fields. type Deps struct { - local.PluginInfraDeps // injected - Watcher datasync.KeyValProtoWatcher // injected - VPP *vpp.Plugin - WatchEventsMutex *sync.Mutex + infra.PluginDeps + StatusCheck statuscheck.PluginStatusWriter + ServiceLabel servicelabel.ReaderAPI + + Watcher datasync.KeyValProtoWatcher // injected + VPP *vpp.Plugin + WatchEventsMutex *sync.Mutex } -// LinuxConfig holds the linuxplugin configuration. -type LinuxConfig struct { +// Config holds the linuxplugin configuration. +type Config struct { Stopwatch bool `json:"stopwatch"` Disabled bool `json:"disabled"` } @@ -110,7 +115,7 @@ func (plugin *Plugin) GetLinuxRouteIndexes() l3idx.LinuxRouteIndex { // InjectVppIfIndexes injects VPP interfaces mapping into Linux plugin func (plugin *Plugin) InjectVppIfIndexes(indexes ifaceVPP.SwIfIndex) { plugin.vppIfIndexes = indexes - plugin.vppIfIndexes.WatchNameToIdx(plugin.PluginName, plugin.vppIfIndexesWatchChan) + plugin.vppIfIndexes.WatchNameToIdx(plugin.String(), plugin.vppIfIndexesWatchChan) } // Init gets handlers for ETCD and Kafka and delegates them to ifConfigurator. @@ -183,7 +188,7 @@ func (plugin *Plugin) Close() error { plugin.ifConfigurator, plugin.arpConfigurator, plugin.routeConfigurator, // Channels plugin.ifIndexesWatchChan, plugin.ifMicroserviceNotif, plugin.changeChan, plugin.resyncChan, - plugin.msChan, plugin.vppIfIndexesWatchChan, + plugin.msChan, // Registrations plugin.watchDataReg, ) @@ -237,9 +242,9 @@ func (plugin *Plugin) initL3() error { return plugin.routeConfigurator.Init(plugin.Log, l3Handler, plugin.nsHandler, plugin.ifIndexes, plugin.stopwatch) } -func (plugin *Plugin) retrieveLinuxConfig() (*LinuxConfig, error) { - config := &LinuxConfig{} - found, err := plugin.PluginInfraDeps.GetValue(config) +func (plugin *Plugin) retrieveLinuxConfig() (*Config, error) { + config := &Config{} + found, err := plugin.Cfg.LoadValue(config) if !found { plugin.Log.Debug("Linuxplugin config not found") return nil, nil diff --git a/plugins/linux/nsplugin/microservices.go b/plugins/linux/nsplugin/microservices.go index 4a8483af63..395ab3649e 100644 --- a/plugins/linux/nsplugin/microservices.go +++ b/plugins/linux/nsplugin/microservices.go @@ -53,8 +53,8 @@ func (e *unavailableMicroserviceErr) Error() string { // Microservice is used to store PID and ID of the container running a given microservice. type Microservice struct { Label string - Pid int - Id string + PID int + ID string } // MicroserviceEvent contains microservice object and event type @@ -184,7 +184,7 @@ func (plugin *NsHandler) processNewMicroservice(nsMgmtCtx *NamespaceMgmtCtx, mic microservice, restarted := plugin.microServiceByLabel[microserviceLabel] if restarted { - plugin.processTerminatedMicroservice(nsMgmtCtx, microservice.Id) + plugin.processTerminatedMicroservice(nsMgmtCtx, microservice.ID) plugin.log.WithFields(logging.Fields{"label": microserviceLabel, "new-pid": pid, "new-id": id}). Warn("Microservice has been restarted") } else { @@ -192,7 +192,7 @@ func (plugin *NsHandler) processNewMicroservice(nsMgmtCtx *NamespaceMgmtCtx, mic Debug("Discovered new microservice") } - microservice = &Microservice{Label: microserviceLabel, Pid: pid, Id: id} + microservice = &Microservice{Label: microserviceLabel, PID: pid, ID: id} plugin.microServiceByLabel[microserviceLabel] = microservice plugin.microServiceByID[id] = microservice @@ -212,11 +212,11 @@ func (plugin *NsHandler) processTerminatedMicroservice(nsMgmtCtx *NamespaceMgmtC Warn("Detected removal of an unknown microservice") return } - plugin.log.WithFields(logging.Fields{"label": microservice.Label, "pid": microservice.Pid, "id": microservice.Id}). + plugin.log.WithFields(logging.Fields{"label": microservice.Label, "pid": microservice.PID, "id": microservice.ID}). Debug("Microservice has terminated") delete(plugin.microServiceByLabel, microservice.Label) - delete(plugin.microServiceByID, microservice.Id) + delete(plugin.microServiceByID, microservice.ID) // Send notification to interface configurator plugin.ifMicroserviceNotif <- &MicroserviceEvent{ diff --git a/plugins/linux/nsplugin/ns_handler.go b/plugins/linux/nsplugin/ns_handler.go index 244a045e97..fd7541643d 100644 --- a/plugins/linux/nsplugin/ns_handler.go +++ b/plugins/linux/nsplugin/ns_handler.go @@ -24,13 +24,12 @@ import ( "sync" "syscall" - "bytes" "github.com/fsouza/go-dockerclient" "github.com/ligato/cn-infra/logging" + ipAddrs "github.com/ligato/cn-infra/utils/addrs" "github.com/ligato/vpp-agent/plugins/linux/ifplugin/linuxcalls" intf "github.com/ligato/vpp-agent/plugins/linux/model/interfaces" "github.com/ligato/vpp-agent/plugins/linux/model/l3" - "github.com/vishvananda/netlink" "github.com/vishvananda/netns" ) @@ -184,19 +183,13 @@ func (plugin *NsHandler) SetInterfaceNamespace(ctx *NamespaceMgmtCtx, ifName str // When interface moves from one namespace to another, it loses all its IP addresses, admin status // and MTU configuration -- we need to remember the interface configuration before the move // and re-configure the interface in the new namespace. - - netIntf, err := net.InterfaceByName(ifName) - if err != nil { - return err - } - - addrs, err := netIntf.Addrs() + addresses, isIPv6, err := plugin.getLinuxIfAddrs(link.Attrs().Name) if err != nil { return err } // Move the interface into the namespace. - err = netlink.LinkSetNsFd(link, int(ns)) + err = plugin.sysHandler.LinkSetNsFd(link, int(ns)) if err != nil { return err } @@ -204,15 +197,15 @@ func (plugin *NsHandler) SetInterfaceNamespace(ctx *NamespaceMgmtCtx, ifName str "dest-namespace-fd": int(ns)}). Debug("Moved Linux interface across namespaces") - // re-configure interface in its new namespace + // Re-configure interface in its new namespace revertNs, err := plugin.SwitchNamespace(ifaceNs, ctx) if err != nil { return err } defer revertNs() - if netIntf.Flags&net.FlagUp == 1 { - // re-enable interface + if link.Attrs().Flags&net.FlagUp == 1 { + // Re-enable interface err = plugin.ifHandler.SetInterfaceUp(ifName) if nil != err { return fmt.Errorf("failed to enable Linux interface `%s`: %v", ifName, err) @@ -221,48 +214,35 @@ func (plugin *NsHandler) SetInterfaceNamespace(ctx *NamespaceMgmtCtx, ifName str Debug("Linux interface was re-enabled") } - // Get all configured interface addresses - confAddresses, err := plugin.ifHandler.GetAddressList(ifName) - if err != nil { - return err - } - - // re-add IP addresses - for i := range addrs { - ip, network, err := net.ParseCIDR(addrs[i].String()) - network.IP = ip /* combine IP address with netmask */ - if err != nil { - return fmt.Errorf("failed to parse IPv4 address of a Linux interface `%s`: %v", ifName, err) - } - // Check link local addresses which cannot be reassigned - if addressExists(confAddresses, network) { - plugin.log.Debugf("Cannot assign %s to interface %s, IP already exists", - network.IP.String(), ifName) + // Re-add IP addresses + for _, address := range addresses { + // Skip IPv6 link local address if there is no other IPv6 address + if !isIPv6 && address.IP.IsLinkLocalUnicast() { continue } - err = plugin.ifHandler.AddInterfaceIP(ifName, network) + err = plugin.ifHandler.AddInterfaceIP(ifName, address) if err != nil { if err.Error() == "file exists" { continue } - return fmt.Errorf("failed to assign IPv4 address to a Linux interface `%s`: %v", ifName, err) + return fmt.Errorf("failed to assign IP address to a Linux interface `%s`: %v", ifName, err) } - plugin.log.WithFields(logging.Fields{"ifName": ifName, "addr": network}). + plugin.log.WithFields(logging.Fields{"ifName": ifName, "addr": address}). Debug("IP address was re-assigned to Linux interface") } - // revert back the MTU config - err = plugin.ifHandler.SetInterfaceMTU(ifName, netIntf.MTU) + // Revert back the MTU config + err = plugin.ifHandler.SetInterfaceMTU(ifName, link.Attrs().MTU) if nil != err { return fmt.Errorf("failed to set MTU of a Linux interface `%s`: %v", ifName, err) } - plugin.log.WithFields(logging.Fields{"ifName": ifName, "mtu": netIntf.MTU}). + plugin.log.WithFields(logging.Fields{"ifName": ifName, "mtu": link.Attrs().MTU}). Debug("MTU was reconfigured for Linux interface") return nil } -// switchToNamespace switches the network namespace of the current thread. +// SwitchToNamespace switches the network namespace of the current thread. func (plugin *NsHandler) SwitchToNamespace(nsMgmtCtx *NamespaceMgmtCtx, ns *intf.LinuxInterfaces_Interface_Namespace) (revert func(), err error) { if ns != nil && ns.Type == intf.LinuxInterfaces_Interface_Namespace_MICROSERVICE_REF_NS { // Convert namespace @@ -463,19 +443,34 @@ func (plugin *NsHandler) convertMicroserviceNsToPidNs(microserviceLabel string) if microservice, ok := plugin.microServiceByLabel[microserviceLabel]; ok { pidNamespace := &Namespace{} pidNamespace.Type = PidRefNs - pidNamespace.Pid = uint32(microservice.Pid) + pidNamespace.Pid = uint32(microservice.PID) return pidNamespace } return nil } -func addressExists(configured []netlink.Addr, provided *net.IPNet) bool { - for _, confAddr := range configured { - if bytes.Equal(confAddr.IP, provided.IP) { - return true +// getLinuxIfAddrs returns a list of IP addresses for given linux interface with info whether there is IPv6 address +// (except default link local) +func (plugin *NsHandler) getLinuxIfAddrs(ifName string) ([]*net.IPNet, bool, error) { + var networks []*net.IPNet + addrs, err := plugin.ifHandler.GetAddressList(ifName) + if err != nil { + return nil, false, fmt.Errorf("failed to get IP address set from linux interface %s", ifName) + } + var containsIPv6 bool + for _, ipAddr := range addrs { + network, ipv6, err := ipAddrs.ParseIPWithPrefix(ipAddr.String()) + if err != nil { + return nil, false, fmt.Errorf("failed to parse IP address %s", ipAddr.String()) } + // Set once if IP address is version 6 and not a link local address + if !containsIPv6 && ipv6 && !ipAddr.IP.IsLinkLocalUnicast() { + containsIPv6 = true + } + networks = append(networks, network) } - return false + + return networks, containsIPv6, nil } // dupNsHandle duplicates namespace handle. diff --git a/plugins/linux/nsplugin/ns_handler_test.go b/plugins/linux/nsplugin/ns_handler_test.go index 638c4bb9ed..13b81010ec 100644 --- a/plugins/linux/nsplugin/ns_handler_test.go +++ b/plugins/linux/nsplugin/ns_handler_test.go @@ -17,19 +17,23 @@ package nsplugin_test import ( "testing" + "net" + "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/logrus" + "github.com/ligato/vpp-agent/plugins/linux/model/interfaces" "github.com/ligato/vpp-agent/plugins/linux/nsplugin" "github.com/ligato/vpp-agent/tests/linuxmock" . "github.com/onsi/gomega" + "github.com/vishvananda/netlink" + "github.com/ligato/cn-infra/utils/safeclose" ) /* Linux namespace handler init and close */ // Test init function func TestNsHandlerInit(t *testing.T) { - plugin, _, _, _, _ := nsHandlerTestSetup(t) - defer nsHandlerTestTeardown(plugin) + plugin, ifHandler, sysHandler, msChan, ifNotif := nsHandlerTestSetup(t) + defer nsHandlerTestTeardown(plugin, ifHandler, sysHandler, msChan, ifNotif) // Base fields Expect(plugin).ToNot(BeNil()) @@ -43,12 +47,115 @@ func TestNsHandlerInit(t *testing.T) { /* Namespace handler Test Setup */ +func TestSetInterfaceNamespace(t *testing.T) { + plugin, ifHandler, sysHandler, msChan, ifNotif := nsHandlerTestSetup(t) + defer nsHandlerTestTeardown(plugin, ifHandler, sysHandler, msChan, ifNotif) + + // IP address list + var ipAddresses []netlink.Addr + ipAddresses = append(ipAddresses, + netlink.Addr{IPNet: getIPNetAddress("10.0.0.1/24")}, + netlink.Addr{IPNet: getIPNetAddress("172.168.0.1/24")}, + netlink.Addr{IPNet: getIPNetAddress("192.168.0.1/24")}, + // Link local address which should be skipped + netlink.Addr{IPNet: getIPNetAddress("fe80::883f:c3ff:fe9e:fba/64")}) + ifHandler.When("GetLinkByName").ThenReturn(&netlink.Tuntap{ + LinkAttrs: netlink.LinkAttrs{ + Name: "if1", + Flags: net.FlagUp, + }, + }) + ifHandler.When("GetAddressList").ThenReturn(ipAddresses) + sysHandler.When("LinkSetNsFd").ThenReturn() + + // Context and namespace + ctx := nsplugin.NewNamespaceMgmtCtx() + ns := &interfaces.LinuxInterfaces_Interface_Namespace{ + Type: interfaces.LinuxInterfaces_Interface_Namespace_NAMED_NS, + } + + err := plugin.SetInterfaceNamespace(ctx, "if1", ns) + Expect(err).To(BeNil()) + + // Check calls to ensure that only required IP addresses were configured + num, calls := ifHandler.GetCallsFor("AddInterfaceIP") + Expect(num).To(Equal(3)) + Expect(calls).ToNot(BeNil()) + for callIdx, call := range calls { + ifName := call[0].(string) + Expect(ifName).To(Equal("if1")) + ipAdd := call[1].(*net.IPNet) + if callIdx == 1 { + Expect(ipAdd.String()).To(Equal("10.0.0.1/24")) + } + if callIdx == 2 { + Expect(ipAdd.String()).To(Equal("172.168.0.1/24")) + } + if callIdx == 3 { + Expect(ipAdd.String()).To(Equal("192.168.0.1/24")) + } + } +} + +func TestSetInterfaceNamespaceIPv6(t *testing.T) { + plugin, ifHandler, sysHandler, msChan, ifNotif := nsHandlerTestSetup(t) + defer nsHandlerTestTeardown(plugin, ifHandler, sysHandler, msChan, ifNotif) + + // IP address list + var ipAddresses []netlink.Addr + ipAddresses = append(ipAddresses, + netlink.Addr{IPNet: getIPNetAddress("10.0.0.1/24")}, + netlink.Addr{IPNet: getIPNetAddress("172.168.0.1/24")}, + // Link local address should not be skipped if there is another non-link-local IPv6 + netlink.Addr{IPNet: getIPNetAddress("fe80::883f:c3ff:fe9e:fba/64")}, + netlink.Addr{IPNet: getIPNetAddress("ad48::42:e8ff:feb1:e976/64")}) + ifHandler.When("GetLinkByName").ThenReturn(&netlink.Tuntap{ + LinkAttrs: netlink.LinkAttrs{ + Name: "if1", + Flags: net.FlagUp, + }, + }) + ifHandler.When("GetAddressList").ThenReturn(ipAddresses) + sysHandler.When("LinkSetNsFd").ThenReturn() + + // Context and namespace + ctx := nsplugin.NewNamespaceMgmtCtx() + ns := &interfaces.LinuxInterfaces_Interface_Namespace{ + Type: interfaces.LinuxInterfaces_Interface_Namespace_NAMED_NS, + } + + err := plugin.SetInterfaceNamespace(ctx, "if1", ns) + Expect(err).To(BeNil()) + + // Check calls to ensure that only required IP addresses were configured + num, calls := ifHandler.GetCallsFor("AddInterfaceIP") + Expect(num).To(Equal(4)) + Expect(calls).ToNot(BeNil()) + for callIdx, call := range calls { + ifName := call[0].(string) + Expect(ifName).To(Equal("if1")) + ipAdd := call[1].(*net.IPNet) + if callIdx == 1 { + Expect(ipAdd.String()).To(Equal("10.0.0.1/24")) + } + if callIdx == 2 { + Expect(ipAdd.String()).To(Equal("172.168.0.1/24")) + } + if callIdx == 3 { + Expect(ipAdd.String()).To(Equal("fe80::883f:c3ff:fe9e:fba/64")) + } + if callIdx == 4 { + Expect(ipAdd.String()).To(Equal("ad48::42:e8ff:feb1:e976/64")) + } + } +} + func nsHandlerTestSetup(t *testing.T) (*nsplugin.NsHandler, *linuxmock.IfNetlinkHandlerMock, *linuxmock.SystemMock, chan *nsplugin.MicroserviceCtx, chan *nsplugin.MicroserviceEvent) { RegisterTestingT(t) // Loggers - pluginLog := logging.ForPlugin("linux-ns-handler-log", logrus.NewLogRegistry()) + pluginLog := logging.ForPlugin("linux-ns-handler-log") pluginLog.SetLevel(logging.DebugLevel) // Handlers ifHandler := linuxmock.NewIfNetlinkHandlerMock() @@ -64,6 +171,17 @@ func nsHandlerTestSetup(t *testing.T) (*nsplugin.NsHandler, *linuxmock.IfNetlink return plugin, ifHandler, sysHandler, msChan, ifNotif } -func nsHandlerTestTeardown(plugin *nsplugin.NsHandler) { +func nsHandlerTestTeardown(plugin *nsplugin.NsHandler, ifHnadler *linuxmock.IfNetlinkHandlerMock, sysHnadler *linuxmock.SystemMock, + msChan chan *nsplugin.MicroserviceCtx, msEventChan chan *nsplugin.MicroserviceEvent) { Expect(plugin.Close()).To(Succeed()) + err := safeclose.Close(ifHnadler, sysHnadler, msChan, msEventChan) + Expect(err).To(BeNil()) + logging.DefaultRegistry.ClearRegistry() +} + +func getIPNetAddress(ipAddr string) *net.IPNet { + ip, ipNet, err := net.ParseCIDR(ipAddr) + ipNet.IP = ip + Expect(err).To(BeNil()) + return ipNet } diff --git a/plugins/linux/nsplugin/system_api.go b/plugins/linux/nsplugin/system_api.go index f5d874fad7..fbe761986f 100644 --- a/plugins/linux/nsplugin/system_api.go +++ b/plugins/linux/nsplugin/system_api.go @@ -15,19 +15,22 @@ package nsplugin import ( - "github.com/vishvananda/netns" "os" "syscall" + + "github.com/vishvananda/netlink" + "github.com/vishvananda/netns" ) -// Defines all methods required for managing operating system, system calls and namespaces on system level +// SystemAPI defines all methods required for managing operating system, system calls and namespaces on system level type SystemAPI interface { OperatingSystem Syscall + NetNsNamespace NetlinkNamespace } -// Operating system defines all methods calling os package +// OperatingSystem defines all methods calling os package type OperatingSystem interface { // Open file OpenFile(name string, flag int, perm os.FileMode) (*os.File, error) @@ -45,8 +48,8 @@ type Syscall interface { Unmount(target string, flags int) (err error) } -// NetlinkNamespace defines method for namespace handling from netlink package -type NetlinkNamespace interface { +// NetNsNamespace defines method for namespace handling from netns package +type NetNsNamespace interface { // NewNetworkNamespace crates new namespace and returns handle to manage it further NewNetworkNamespace() (ns netns.NsHandle, err error) // GetNamespaceFromName returns namespace handle from its name @@ -55,46 +58,69 @@ type NetlinkNamespace interface { SetNamespace(ns netns.NsHandle) (err error) } -type systemHandler struct{} +// NetlinkNamespace defines method for namespace handling from netlink package +type NetlinkNamespace interface { + // LinkSetNsFd puts the device into a new network namespace. + LinkSetNsFd(link netlink.Link, fd int) (err error) +} + +// SystemHandler implements interfaces. +type SystemHandler struct{} -func NewSystemHandler() *systemHandler { - return &systemHandler{} +// NewSystemHandler returns new handler. +func NewSystemHandler() *SystemHandler { + return &SystemHandler{} } /* Operating system */ -func (osh *systemHandler) OpenFile(name string, flag int, perm os.FileMode) (*os.File, error) { +// OpenFile implements OperatingSystem. +func (osh *SystemHandler) OpenFile(name string, flag int, perm os.FileMode) (*os.File, error) { return os.OpenFile(name, flag, perm) } -func (osh *systemHandler) MkDirAll(path string, perm os.FileMode) error { +// MkDirAll implements OperatingSystem. +func (osh *SystemHandler) MkDirAll(path string, perm os.FileMode) error { return os.MkdirAll(path, perm) } -func (osh *systemHandler) Remove(name string) error { +// Remove implements OperatingSystem. +func (osh *SystemHandler) Remove(name string) error { return os.Remove(name) } /* Syscall */ -func (osh *systemHandler) Mount(source string, target string, fsType string, flags uintptr, data string) error { +// Mount implements Syscall. +func (osh *SystemHandler) Mount(source string, target string, fsType string, flags uintptr, data string) error { return syscall.Mount(source, target, fsType, flags, data) } -func (osh *systemHandler) Unmount(target string, flags int) error { +// Unmount implements Syscall. +func (osh *SystemHandler) Unmount(target string, flags int) error { return syscall.Unmount(target, flags) } -/* Netlink namespace */ +/* Netns namespace */ -func (osh *systemHandler) NewNetworkNamespace() (ns netns.NsHandle, err error) { +// NewNetworkNamespace implements NetNsNamespace. +func (osh *SystemHandler) NewNetworkNamespace() (ns netns.NsHandle, err error) { return netns.New() } -func (osh *systemHandler) GetNamespaceFromName(name string) (ns netns.NsHandle, err error) { +// GetNamespaceFromName implements NetNsNamespace. +func (osh *SystemHandler) GetNamespaceFromName(name string) (ns netns.NsHandle, err error) { return netns.GetFromName(name) } -func (osh *systemHandler) SetNamespace(ns netns.NsHandle) (err error) { +// SetNamespace implements NetNsNamespace. +func (osh *SystemHandler) SetNamespace(ns netns.NsHandle) (err error) { return netns.Set(ns) } + +/* Netlink namespace */ + +// LinkSetNsFd implements NetlinkNamespace. +func (osh *SystemHandler) LinkSetNsFd(link netlink.Link, fd int) (err error) { + return netlink.LinkSetNsFd(link, fd) +} diff --git a/plugins/linux/options.go b/plugins/linux/options.go new file mode 100644 index 0000000000..5e328795e0 --- /dev/null +++ b/plugins/linux/options.go @@ -0,0 +1,59 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package linux + +import ( + "github.com/ligato/cn-infra/config" + "github.com/ligato/cn-infra/health/statuscheck" + "github.com/ligato/cn-infra/logging" + "github.com/ligato/cn-infra/servicelabel" +) + +// DefaultPlugin is default instance of Plugin +//var DefaultPlugin = NewPlugin() + +// NewPlugin creates a new Plugin with the provides Options +func NewPlugin(opts ...Option) *Plugin { + p := &Plugin{} + + p.PluginName = "linux" + p.StatusCheck = &statuscheck.DefaultPlugin + p.ServiceLabel = &servicelabel.DefaultPlugin + + for _, o := range opts { + o(p) + } + + if p.Log == nil { + p.Log = logging.ForPlugin(p.String()) + } + if p.Cfg == nil { + p.Cfg = config.ForPlugin(p.String(), + config.WithCustomizedFlag(config.FlagName(p.String()), "linux-plugin.conf"), + ) + } + + return p +} + +// Option is a function that acts on a Plugin to inject Dependencies or configuration +type Option func(*Plugin) + +// UseDeps returns Option that can inject custom dependencies. +func UseDeps(cb func(*Deps)) Option { + return func(p *Plugin) { + cb(&p.Deps) + } +} diff --git a/plugins/rest/README.md b/plugins/rest/README.md index 26c15c634c..23f56465f2 100644 --- a/plugins/rest/README.md +++ b/plugins/rest/README.md @@ -1,6 +1,6 @@ # REST API Plugin -The `restplugin` is a core Agent Plugin used of exposing REST API for the following: +The `restplugin` is a core Agent Plugin used to expose REST API for the following: * Run VPP CLI commands * Exposes existing Northbound objects * Provides logging mechanism so that the VPPCLI command and response can be searched in elastic search @@ -11,54 +11,122 @@ curl -H "Content-Type: application/json" -X POST -d '{"vppclicommand":"show inte ``` ## Exposing existing Northbound objects + +Here is the list of supported REST URLs. If configuration dump URL is used, the output is based on proto model +structure for given data type together with VPP-specific data which are not a part of the model (indexes for +interfaces or ACLs, internal names, etc.). Those data are in separate section labeled as `Meta`. + +**Access lists** + +URLs to obtain ACL IP/MACIP configuration are as follows. + ``` -curl http://0.0.0.0:9191/interfaces -curl http://0.0.0.0:9191/bridgedomainids -curl http://0.0.0.0:9191/bridgedomains -curl http://0.0.0.0:9191/fibs -curl http://0.0.0.0:9191/xconnectpairs -curl http://0.0.0.0:9191/staticroutes -curl http://0.0.0.0:9191/acl/interface/ // Get ACLs for interface -curl http://0.0.0.0:9191/acl/ip // Get all IP ACLs -curl http://0.0.0.0:9191/acl/ip/example // Get an example ACL -``` - -Configure an IP ACL: -``` -curl -H "Content-Type: application/json" -X POST -d '' http://0.0.0.0:9191/interface/acl/ip -``` - -For example: -``` -curl -H "Content-Type: application/json" -X POST -d '{ - "acl_name": "example" - "rules": [ - { - "rule_name": "acl1_rule1", { "actions": { - "acl_action": 1, - "match": { - "ip_rule": { - "ip": { - "destination_network": "1.2.3.4/24", - "source_network": "5.6.7.8/24" - }, - "tcp": { - "destination_port_range": { - "lower_port": 80, - "upper_port": 8080 - }, - "source_port_range": { - "lower_port": 10, - "upper_port": 1010 - }, - "tcp_flags_mask": 255, - "tcp_flags_value": 9 - } - } - } - } - ] -}' http://0.0.0.0:9191/interface/acl/ip +curl GET http://0.0.0.0:9191/vpp/dump/v1/acl/ip +curl GET http://0.0.0.0:9191/vpp/dump/v1/acl/macip +``` + +**Interfaces** + +REST plugin exposes configured interfaces, which can be show all together, or only interfaces +of specific type. + ``` +curl GET http://0.0.0.0:9191/vpp/dump/v1/interfaces +curl GET http://0.0.0.0:9191/vpp/dump/v1/interfaces/loopback +curl GET http://0.0.0.0:9191/vpp/dump/v1/interfaces/ethernet +curl GET http://0.0.0.0:9191/vpp/dump/v1/interfaces/memif +curl GET http://0.0.0.0:9191/vpp/dump/v1/interfaces/tap +curl GET http://0.0.0.0:9191/vpp/dump/v1/interfaces/vxlan +curl GET http://0.0.0.0:9191/vpp/dump/v1/interfaces/afpacket +``` + +**BFD** + +REST plugin allows to dump bidirectional forwarding detection sessions, authentication keys, +or the whole configuration. + +``` +curl GET http://0.0.0.0:9191/vpp/dump/v1/bfd +curl GET http://0.0.0.0:9191/vpp/dump/v1/bfd/sessions +curl GET http://0.0.0.0:9191/vpp/dump/v1/bfd/authkeys +``` + +**NAT** + +REST plugin allows to dump NAT44 global configuration, DNAT configuration or both of them together. +SNAT is currently not supported in the model, so REST dump is not available as well. + +``` +curl GET http://0.0.0.0:9191/vpp/dump/v1/nat +curl GET http://0.0.0.0:9191/vpp/dump/v1/nat/global +curl GET http://0.0.0.0:9191/vpp/dump/v1/nat/dnat +``` + +**STN** + +Steal the NIC feature REST API contains one uri returning the list of STN rules. + +``` +curl GET http://0.0.0.0:9191/vpp/dump/v1/stn +``` + +**L2 plugin** + +Support for bridge domains, FIBs and cross connects. It is also possible to get all +the bridge domain IDs. + +``` +curl GET http://0.0.0.0:9191/vpp/dump/v1/bdid +curl GET http://0.0.0.0:9191/vpp/dump/v1/bd +curl GET http://0.0.0.0:9191/vpp/dump/v1/fib +curl GET http://0.0.0.0:9191/vpp/dump/v1/xc +``` + +**L3 plugin** + +ARPs, proxy ARP interfaces/ranges and static routes exposed via REST: + +``` +curl GET http://0.0.0.0:9191/vpp/dump/v1/arps +curl GET http://0.0.0.0:9191/vpp/dump/v1/proxyarp/interfaces +curl GET http://0.0.0.0:9191/vpp/dump/v1/proxyarp/ranges +curl GET http://0.0.0.0:9191/vpp/dump/v1/routes +``` + +**L4 plugin** + +L4 plugin exposes session configuration: + +``` +curl GET http://0.0.0.0:9191/vpp/dump/v1/sessions +``` + +**Telemetry** + +REST allows to get all the telemetry data, or selective using specific key: + +``` +curl GET http://0.0.0.0:9191/vpp/dump/v1/telemetry +curl GET http://0.0.0.0:9191/vpp/dump/v1/telemetry/memory +curl GET http://0.0.0.0:9191/vpp/dump/v1/telemetry/runtime +curl GET http://0.0.0.0:9191/vpp/dump/v1/telemetry/nodecount +``` + +**CLI command** + +Allows to use VPP CLI command via REST. Commands are defined as a map as following: + +``` +curl POST http://0.0.0.0:9191/vpp/command -d '{"vppclicommand":""}' +``` + +**Index** + +REST to get index page. Configuration items are sorted by type (ifplugin, telemetry, etc.) + +``` +curl GET http://0.0.0.0:9191/ +``` + ## Logging mechanism -The REST API request is logged to stdout. The log contains VPPCLI command and VPPCLI response. It is searchable in elastic search using "VPPCLI". \ No newline at end of file +The REST API request is logged to stdout. The log contains VPPCLI command and VPPCLI response. It is searchable in elastic search using "VPPCLI". diff --git a/plugins/rest/bindata.go b/plugins/rest/bindata.go index c844aa1ec9..ad39786135 100644 --- a/plugins/rest/bindata.go +++ b/plugins/rest/bindata.go @@ -6,10 +6,10 @@ package rest import ( + "github.com/elazarl/go-bindata-assetfs" "bytes" "compress/gzip" "fmt" - "github.com/elazarl/go-bindata-assetfs" "io" "io/ioutil" "os" @@ -69,7 +69,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _templatesIndexTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2c\x8e\xb1\x0a\x02\x31\x0c\x86\xf7\x3e\x45\xec\x03\x5c\xe0\x46\xc9\x75\x51\x07\x17\xbd\xc1\xc5\xb1\xd2\x78\x3d\xe8\x55\x38\x2a\x28\x21\xef\x2e\xb5\x37\x85\x3f\x7c\xf9\xfe\xd0\xee\x78\x3d\xdc\xee\xe3\x09\x62\x59\x92\x33\x54\x07\x24\x9f\xa7\xc1\x72\xb6\x75\xc1\x3e\x38\x03\x00\x40\x65\x2e\x89\xdd\x39\x07\xfe\x10\xb6\x60\x08\x1b\x40\x8f\x57\xf8\x56\xbc\x6f\xc0\x9e\x30\xf6\xce\xd0\x3b\x39\x23\xb2\xfa\x3c\x31\x74\xaa\x4d\x94\xe6\x66\xfc\x07\x0f\x71\xe5\xe7\x60\x45\xba\xd1\x97\xa8\x6a\x9d\x48\x77\xf1\x0b\xab\x12\xfa\xad\x1b\xeb\x8d\x08\xe7\xa0\x6a\x08\xab\x96\x70\xeb\xc4\xf6\xfb\x2f\x00\x00\xff\xff\x53\x9c\xf7\x70\xcc\x00\x00\x00") +var _templatesIndexTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x54\x90\x41\x4b\x03\x31\x10\x85\xef\xf9\x15\xe3\xd2\xa3\x34\xd0\xde\xca\x6c\x2e\xda\x43\x0f\x6a\x0f\x5e\x3c\x8e\x64\x6c\x8a\xd9\x28\x4b\x04\x97\x61\xfe\xbb\xcc\xa6\xed\xe2\x69\x78\x8f\xf7\xbd\xf0\x82\x77\x8f\x2f\x0f\xaf\x6f\xc7\x3d\xa4\x3a\xe4\xe0\xd0\x0e\x64\x2a\xa7\xbe\xe3\xd2\x99\xc1\x14\x83\x03\x00\xc0\x7a\xae\x99\xc3\xa1\x44\xfe\x45\xdf\x84\x43\xdf\x02\xf8\xfe\x15\x27\x8b\x6f\x5a\x60\x87\x3e\x6d\x82\xc3\x9f\x1c\x9c\xc8\x48\xe5\xc4\xb0\xfa\xe4\xe9\x1e\x56\x91\x2a\xc1\xae\x87\xf5\xa1\xf2\xf0\x44\xdf\xaa\xad\x3e\x6d\x83\x88\x65\x54\x8d\xde\xb6\x57\x6f\xb0\x61\xfb\x52\xc7\xc9\xd8\x59\x5d\xc0\x19\xce\xe7\x70\x13\xb3\x41\x90\x46\xfe\xe8\x3b\x91\x85\x5c\x1f\xa9\x26\xd5\x2e\xfc\x33\x9f\x69\x60\x55\xf4\xb4\x34\xa0\xbf\xf6\x89\x70\x89\xaa\xee\x7a\xd1\xdb\x22\xf4\x97\xb9\xbe\x7d\xdb\x5f\x00\x00\x00\xff\xff\xdb\x95\x2c\xc1\x47\x01\x00\x00") func templatesIndexTmplBytes() ([]byte, error) { return bindataRead( @@ -84,7 +84,7 @@ func templatesIndexTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "templates/index.tmpl", size: 204, mode: os.FileMode(436), modTime: time.Unix(1525877975, 0)} + info := bindataFileInfo{name: "templates/index.tmpl", size: 327, mode: os.FileMode(420), modTime: time.Unix(1533194427, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -183,7 +183,6 @@ type bintree struct { Func func() (*asset, error) Children map[string]*bintree } - var _bintree = &bintree{nil, map[string]*bintree{ "templates": &bintree{nil, map[string]*bintree{ "index.tmpl": &bintree{templatesIndexTmpl, map[string]*bintree{}}, @@ -237,6 +236,7 @@ func _filePath(dir, name string) string { return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) } + func assetFS() *assetfs.AssetFS { assetInfo := func(path string) (os.FileInfo, error) { return os.Stat(path) diff --git a/plugins/rest/options.go b/plugins/rest/options.go new file mode 100644 index 0000000000..6b6a5e6de3 --- /dev/null +++ b/plugins/rest/options.go @@ -0,0 +1,33 @@ +package rest + +import ( + "github.com/ligato/cn-infra/rpc/rest" + "github.com/ligato/vpp-agent/plugins/govppmux" +) + +// NewPlugin creates a new Plugin with the provides Options +func NewPlugin(opts ...Option) *Plugin { + p := &Plugin{} + + p.PluginName = "vpp-rest" + p.HTTPHandlers = &rest.DefaultPlugin + p.GoVppmux = &govppmux.DefaultPlugin + + for _, o := range opts { + o(p) + } + + p.PluginDeps.Setup() + + return p +} + +// Option is a function that acts on a Plugin to inject Dependencies or configuration +type Option func(*Plugin) + +// UseDeps returns Option that can inject custom dependencies. +func UseDeps(cb func(*Deps)) Option { + return func(p *Plugin) { + cb(&p.Deps) + } +} diff --git a/plugins/rest/plugin_impl_rest.go b/plugins/rest/plugin_impl_rest.go index 9480c66ade..dd4e9ca04b 100644 --- a/plugins/rest/plugin_impl_rest.go +++ b/plugins/rest/plugin_impl_rest.go @@ -16,30 +16,72 @@ package rest import ( "fmt" + "sync" - "github.com/ligato/cn-infra/flavors/local" + "git.fd.io/govpp.git/api" + "github.com/ligato/cn-infra/infra" "github.com/ligato/cn-infra/rpc/rest" + "github.com/ligato/cn-infra/utils/safeclose" "github.com/ligato/vpp-agent/plugins/govppmux" + "github.com/ligato/vpp-agent/plugins/rest/resturl" + "github.com/ligato/vpp-agent/plugins/vpp" + aclvppcalls "github.com/ligato/vpp-agent/plugins/vpp/aclplugin/vppcalls" + ifvppcalls "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" + ipsecvppcalls "github.com/ligato/vpp-agent/plugins/vpp/ipsecplugin/vppcalls" + l2vppcalls "github.com/ligato/vpp-agent/plugins/vpp/l2plugin/vppcalls" + l3vppcalls "github.com/ligato/vpp-agent/plugins/vpp/l3plugin/vppcalls" + l4vppcalls "github.com/ligato/vpp-agent/plugins/vpp/l4plugin/vppcalls" ) +// REST api methods const ( - swIndexVarName = "swindex" + GET = "GET" + POST = "POST" ) // Plugin registers Rest Plugin type Plugin struct { Deps - indexItems []indexItem + // Index page + index *index + + // Channels + vppChan api.Channel + dumpChan api.Channel + + // Handlers + aclHandler aclvppcalls.ACLVppRead + ifHandler ifvppcalls.IfVppRead + bfdHandler ifvppcalls.BfdVppRead + natHandler ifvppcalls.NatVppRead + stnHandler ifvppcalls.StnVppRead + ipSecHandler ipsecvppcalls.IPSecVPPRead + bdHandler l2vppcalls.BridgeDomainVppRead + fibHandler l2vppcalls.FibVppRead + xcHandler l2vppcalls.XConnectVppRead + arpHandler l3vppcalls.ArpVppRead + pArpHandler l3vppcalls.ProxyArpVppRead + rtHandler l3vppcalls.RouteVppRead + l4Handler l4vppcalls.L4VppRead + + govppmux sync.Mutex } // Deps represents dependencies of Rest Plugin type Deps struct { - local.PluginInfraDeps + infra.PluginDeps HTTPHandlers rest.HTTPHandlers GoVppmux govppmux.API + VPP vpp.API } +// index defines map of main index page entries +type index struct { + ItemMap map[string][]indexItem +} + +// indexItem is single index page entry type indexItem struct { Name string Path string @@ -47,15 +89,84 @@ type indexItem struct { // Init initializes the Rest Plugin func (plugin *Plugin) Init() (err error) { - plugin.indexItems = []indexItem{ - {Name: "Interfaces", Path: "/interfaces"}, - {Name: "Bridge domains", Path: "/bridgedomains"}, - {Name: "L2Fibs", Path: "/l2fibs"}, - {Name: "XConnectorPairs", Path: "/xconnectpairs"}, - {Name: "Static routes", Path: "/staticroutes"}, - {Name: "ACL IP", Path: "/acl/ip"}, - {Name: "Telemetry", Path: "/telemetry"}, + // Check VPP dependency + if plugin.VPP == nil { + return fmt.Errorf("REST plugin requires VPP plugin API") + } + // VPP channels + if plugin.vppChan, err = plugin.GoVppmux.NewAPIChannel(); err != nil { + return err + } + if plugin.dumpChan, err = plugin.GoVppmux.NewAPIChannel(); err != nil { + return err } + // Indexes + ifIndexes := plugin.VPP.GetSwIfIndexes() + bdIndexes := plugin.VPP.GetBDIndexes() + spdIndexes := plugin.VPP.GetIPSecSPDIndexes() + + // Initialize handlers + plugin.aclHandler = aclvppcalls.NewACLVppHandler(plugin.vppChan, plugin.dumpChan, nil) + plugin.ifHandler = ifvppcalls.NewIfVppHandler(plugin.vppChan, plugin.Log, nil) + plugin.bfdHandler = ifvppcalls.NewBfdVppHandler(plugin.vppChan, ifIndexes, plugin.Log, nil) + plugin.natHandler = ifvppcalls.NewNatVppHandler(plugin.vppChan, plugin.dumpChan, ifIndexes, plugin.Log, nil) + plugin.stnHandler = ifvppcalls.NewStnVppHandler(plugin.vppChan, ifIndexes, plugin.Log, nil) + plugin.ipSecHandler = ipsecvppcalls.NewIPsecVppHandler(plugin.vppChan, ifIndexes, spdIndexes, plugin.Log, nil) + plugin.bdHandler = l2vppcalls.NewBridgeDomainVppHandler(plugin.vppChan, ifIndexes, plugin.Log, nil) + plugin.fibHandler = l2vppcalls.NewFibVppHandler(plugin.vppChan, plugin.dumpChan, ifIndexes, bdIndexes, plugin.Log, nil) + plugin.xcHandler = l2vppcalls.NewXConnectVppHandler(plugin.vppChan, ifIndexes, plugin.Log, nil) + plugin.arpHandler = l3vppcalls.NewArpVppHandler(plugin.vppChan, ifIndexes, plugin.Log, nil) + plugin.pArpHandler = l3vppcalls.NewProxyArpVppHandler(plugin.vppChan, ifIndexes, plugin.Log, nil) + plugin.rtHandler = l3vppcalls.NewRouteVppHandler(plugin.vppChan, ifIndexes, plugin.Log, nil) + plugin.l4Handler = l4vppcalls.NewL4VppHandler(plugin.vppChan, plugin.Log, nil) + + // Fill index item lists + idxMap := map[string][]indexItem{ + "ACL plugin": { + {Name: "IP-type access lists", Path: resturl.ACLIP}, + {Name: "MACIP-type access lists", Path: resturl.ACLMACIP}, + }, + "Interface plugin": { + {Name: "All interfaces", Path: resturl.Interface}, + {Name: "Loopbacks", Path: resturl.Loopback}, + {Name: "Ethernets", Path: resturl.Ethernet}, + {Name: "Memifs", Path: resturl.Memif}, + {Name: "Taps", Path: resturl.Tap}, + {Name: "VxLANs", Path: resturl.VxLan}, + {Name: "Af-packets", Path: resturl.AfPacket}, + }, + "IPSec plugin": { + {Name: "Security policy databases", Path: resturl.IPSecSpd}, + {Name: "Security associations", Path: resturl.IPSecSa}, + {Name: "Tunnel interfaces", Path: resturl.IPSecTnIf}, + }, + "L2 plugin": { + {Name: "Bridge domains", Path: resturl.Bd}, + {Name: "Bridge domain IDs", Path: resturl.BdID}, + {Name: "L2Fibs", Path: resturl.Fib}, + {Name: "Cross connects", Path: resturl.Xc}, + }, + "L3 plugin": { + {Name: "Bridge domains", Path: resturl.Bd}, + {Name: "Bridge domain IDs", Path: resturl.BdID}, + {Name: "L2Fibs", Path: resturl.Fib}, + {Name: "Cross connects", Path: resturl.Xc}, + }, + "L4 plugin": { + {Name: "L4 sessions", Path: resturl.Sessions}, + }, + "Telemetry": { + {Name: "All data", Path: resturl.Telemetry}, + {Name: "Memory", Path: resturl.TMemory}, + {Name: "Runtime", Path: resturl.TRuntime}, + {Name: "Node count", Path: resturl.TNodeCount}, + }, + } + + plugin.index = &index{ + ItemMap: idxMap, + } + return nil } @@ -63,31 +174,23 @@ func (plugin *Plugin) Init() (err error) { func (plugin *Plugin) AfterInit() (err error) { plugin.Log.Debug("REST API Plugin is up and running") - plugin.HTTPHandlers.RegisterHTTPHandler("/interfaces", plugin.interfacesGetHandler, "GET") - plugin.HTTPHandlers.RegisterHTTPHandler("/bridgedomains", plugin.bridgeDomainsGetHandler, "GET") - plugin.HTTPHandlers.RegisterHTTPHandler("/bridgedomainids", plugin.bridgeDomainIdsGetHandler, "GET") - plugin.HTTPHandlers.RegisterHTTPHandler("/l2fibs", plugin.fibTableEntriesGetHandler, "GET") - plugin.HTTPHandlers.RegisterHTTPHandler("/xconnectpairs", plugin.xconnectPairsGetHandler, "GET") - plugin.HTTPHandlers.RegisterHTTPHandler("/staticroutes", plugin.staticRoutesGetHandler, "GET") - plugin.HTTPHandlers.RegisterHTTPHandler(fmt.Sprintf("/acl/interface/{%s:[0-9]+}", swIndexVarName), - plugin.interfaceACLGetHandler, "GET") - plugin.HTTPHandlers.RegisterHTTPHandler("/acl/ip", plugin.ipACLPostHandler, "POST") - plugin.HTTPHandlers.RegisterHTTPHandler("/acl/ip", plugin.ipACLGetHandler, "GET") - plugin.HTTPHandlers.RegisterHTTPHandler("/acl/ip/example", plugin.exampleIpACLGetHandler, "GET") - plugin.HTTPHandlers.RegisterHTTPHandler("/acl/macip", plugin.macipACLPostHandler, "POST") - plugin.HTTPHandlers.RegisterHTTPHandler("/acl/macip", plugin.macipACLGetHandler, "GET") - plugin.HTTPHandlers.RegisterHTTPHandler("/acl/macip/example", plugin.exampleMacIpACLGetHandler, "GET") - plugin.HTTPHandlers.RegisterHTTPHandler("/command", plugin.commandHandler, "POST") - plugin.HTTPHandlers.RegisterHTTPHandler("/telemetry", plugin.telemetryHandler, "GET") - plugin.HTTPHandlers.RegisterHTTPHandler("/telemetry/memory", plugin.telemetryMemoryHandler, "GET") - plugin.HTTPHandlers.RegisterHTTPHandler("/telemetry/runtime", plugin.telemetryRuntimeHandler, "GET") - plugin.HTTPHandlers.RegisterHTTPHandler("/telemetry/nodecount", plugin.telemetryNodeCountHandler, "GET") - plugin.HTTPHandlers.RegisterHTTPHandler("/", plugin.indexHandler, "GET") + plugin.registerAccessListHandlers() + plugin.registerInterfaceHandlers() + plugin.registerBfdHandlers() + plugin.registerNatHandlers() + plugin.registerStnHandlers() + plugin.registerIPSecHandlers() + plugin.registerL2Handlers() + plugin.registerL3Handlers() + plugin.registerL4Handlers() + plugin.registerTelemetryHandlers() + plugin.registerCommandHandler() + plugin.registerIndexHandlers() return nil } // Close is used to clean up resources used by Plugin func (plugin *Plugin) Close() (err error) { - return nil + return safeclose.Close(plugin.vppChan, plugin.dumpChan) } diff --git a/plugins/rest/rest_handlers.go b/plugins/rest/rest_handlers.go index 45b7b7ad2a..221c7443dd 100644 --- a/plugins/rest/rest_handlers.go +++ b/plugins/rest/rest_handlers.go @@ -21,436 +21,213 @@ import ( "fmt" "io/ioutil" "net/http" - "strconv" govppapi "git.fd.io/govpp.git/api" - "git.fd.io/govpp.git/core/bin_api/vpe" - "github.com/gorilla/mux" "github.com/ligato/vpp-agent/plugins/govppmux/vppcalls" + "github.com/ligato/vpp-agent/plugins/rest/resturl" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/vpe" + "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" "github.com/unrolled/render" - - aclcalls "github.com/ligato/vpp-agent/plugins/vpp/aclplugin/vppcalls" - acldump "github.com/ligato/vpp-agent/plugins/vpp/aclplugin/vppdump" - ifplugin "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppdump" - l2plugin "github.com/ligato/vpp-agent/plugins/vpp/l2plugin/vppdump" - l3plugin "github.com/ligato/vpp-agent/plugins/vpp/l3plugin/vppdump" - "github.com/ligato/vpp-agent/plugins/vpp/model/acl" ) -// interfacesGetHandler - used to get list of all interfaces -func (plugin *Plugin) interfacesGetHandler(formatter *render.Render) http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - - plugin.Log.Debug("Getting list of all interfaces") - - // create an API channel - ch, err := plugin.GoVppmux.NewAPIChannel() - if err != nil { - plugin.Log.Errorf("Error creating channel: %v", err) - formatter.JSON(w, http.StatusInternalServerError, err) - return - } - defer ch.Close() - - res, err := ifplugin.DumpInterfaces(plugin.Log, ch, nil) - if err != nil { - plugin.Log.Errorf("Error: %v", err) - formatter.JSON(w, http.StatusInternalServerError, err) - return - } - - plugin.Log.Debug(res) - formatter.JSON(w, http.StatusOK, res) - } +// Registers access list REST handlers +func (plugin *Plugin) registerAccessListHandlers() { + // GET IP ACLs + plugin.registerHTTPHandler(resturl.ACLIP, GET, func() (interface{}, error) { + return plugin.aclHandler.DumpIPACL(nil) + }) + // GET MACIP ACLs + plugin.registerHTTPHandler(resturl.ACLMACIP, GET, func() (interface{}, error) { + return plugin.aclHandler.DumpMACIPACL(nil) + }) } -// bridgeDomainIdsGetHandler - used to get list of all bridge domain ids -func (plugin *Plugin) bridgeDomainIdsGetHandler(formatter *render.Render) http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - - plugin.Log.Debug("Getting list of all bridge domain ids") - - // create an API channel - ch, err := plugin.GoVppmux.NewAPIChannel() - if err != nil { - plugin.Log.Errorf("Error creating channel: %v", err) - formatter.JSON(w, http.StatusInternalServerError, err) - return - } - defer ch.Close() - - res, err := l2plugin.DumpBridgeDomainIDs(ch, nil) - if err != nil { - plugin.Log.Errorf("Error: %v", err) - formatter.JSON(w, http.StatusInternalServerError, err) - return - } - - plugin.Log.Debug(res) - formatter.JSON(w, http.StatusOK, res) - } +// Registers interface REST handlers +func (plugin *Plugin) registerInterfaceHandlers() { + // GET all interfaces + plugin.registerHTTPHandler(resturl.Interface, GET, func() (interface{}, error) { + return plugin.ifHandler.DumpInterfaces() + }) + // GET loopback interfaces + plugin.registerHTTPHandler(resturl.Loopback, GET, func() (interface{}, error) { + return plugin.ifHandler.DumpInterfacesByType(interfaces.InterfaceType_SOFTWARE_LOOPBACK) + }) + // GET ethernet interfaces + plugin.registerHTTPHandler(resturl.Ethernet, GET, func() (interface{}, error) { + return plugin.ifHandler.DumpInterfacesByType(interfaces.InterfaceType_ETHERNET_CSMACD) + }) + // GET memif interfaces + plugin.registerHTTPHandler(resturl.Memif, GET, func() (interface{}, error) { + return plugin.ifHandler.DumpInterfacesByType(interfaces.InterfaceType_MEMORY_INTERFACE) + }) + // GET tap interfaces + plugin.registerHTTPHandler(resturl.Tap, GET, func() (interface{}, error) { + return plugin.ifHandler.DumpInterfacesByType(interfaces.InterfaceType_TAP_INTERFACE) + }) + // GET af-packet interfaces + plugin.registerHTTPHandler(resturl.AfPacket, GET, func() (interface{}, error) { + return plugin.ifHandler.DumpInterfacesByType(interfaces.InterfaceType_AF_PACKET_INTERFACE) + }) + // GET VxLAN interfaces + plugin.registerHTTPHandler(resturl.VxLan, GET, func() (interface{}, error) { + return plugin.ifHandler.DumpInterfacesByType(interfaces.InterfaceType_VXLAN_TUNNEL) + }) } -// bridgeDomainsGetHandler - used to get list of all bridge domains -func (plugin *Plugin) bridgeDomainsGetHandler(formatter *render.Render) http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - - plugin.Log.Debug("Getting list of all bridge domains") - - // create an API channel - ch, err := plugin.GoVppmux.NewAPIChannel() - if err != nil { - plugin.Log.Errorf("Error creating channel: %v", err) - formatter.JSON(w, http.StatusInternalServerError, err) - return - } - defer ch.Close() - - res, err := l2plugin.DumpBridgeDomains(ch, nil) - if err != nil { - plugin.Log.Errorf("Error: %v", err) - formatter.JSON(w, http.StatusInternalServerError, nil) - return - } - - plugin.Log.Debug(res) - formatter.JSON(w, http.StatusOK, res) - } +// Registers BFD REST handlers +func (plugin *Plugin) registerBfdHandlers() { + // GET BFD configuration + plugin.registerHTTPHandler(resturl.BfdURL, GET, func() (interface{}, error) { + return plugin.bfdHandler.DumpBfdSingleHop() + }) + // GET BFD sessions + plugin.registerHTTPHandler(resturl.BfdSession, GET, func() (interface{}, error) { + return plugin.bfdHandler.DumpBfdSessions() + }) + // GET BFD authentication keys + plugin.registerHTTPHandler(resturl.BfdAuthKey, GET, func() (interface{}, error) { + return plugin.bfdHandler.DumpBfdAuthKeys() + }) } -// fibTableEntriesGetHandler - used to get list of all fib entries -func (plugin *Plugin) fibTableEntriesGetHandler(formatter *render.Render) http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - - plugin.Log.Debug("Getting list of all fibs") - - // create an API channel - ch, err := plugin.GoVppmux.NewAPIChannel() - if err != nil { - plugin.Log.Errorf("Error creating channel: %v", err) - formatter.JSON(w, http.StatusInternalServerError, err) - return - } - defer ch.Close() - - res, err := l2plugin.DumpFIBTableEntries(ch, nil) - if err != nil { - plugin.Log.Errorf("Error: %v", err) - formatter.JSON(w, http.StatusInternalServerError, nil) - return - } - - plugin.Log.Debug(res) - formatter.JSON(w, http.StatusOK, res) - } +// Registers NAT REST handlers +func (plugin *Plugin) registerNatHandlers() { + // GET NAT configuration + plugin.registerHTTPHandler(resturl.NatURL, GET, func() (interface{}, error) { + return plugin.natHandler.Nat44Dump() + }) + // GET NAT global config + plugin.registerHTTPHandler(resturl.NatGlobal, GET, func() (interface{}, error) { + return plugin.natHandler.Nat44GlobalConfigDump() + }) + // GET DNAT config + plugin.registerHTTPHandler(resturl.NatDNat, GET, func() (interface{}, error) { + return plugin.natHandler.Nat44DNatDump() + }) } -// xconnectPairsGetHandler - used to get list of all connect pairs (transmit and receive interfaces) -func (plugin *Plugin) xconnectPairsGetHandler(formatter *render.Render) http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - - plugin.Log.Debug("Getting list of all xconnect pairs") - - // create an API channel - ch, err := plugin.GoVppmux.NewAPIChannel() - if err != nil { - plugin.Log.Errorf("Error creating channel: %v", err) - formatter.JSON(w, http.StatusInternalServerError, err) - return - } - defer ch.Close() - - res, err := l2plugin.DumpXConnectPairs(ch, nil) - if err != nil { - plugin.Log.Errorf("Error: %v", err) - formatter.JSON(w, http.StatusInternalServerError, nil) - } - - plugin.Log.Debug(res) - formatter.JSON(w, http.StatusOK, res) - } +// Registers STN REST handlers +func (plugin *Plugin) registerStnHandlers() { + // GET STN configuration + plugin.registerHTTPHandler(resturl.StnURL, GET, func() (interface{}, error) { + return plugin.stnHandler.DumpStnRules() + }) } -// staticRoutesGetHandler - used to get list of all static routes -func (plugin *Plugin) staticRoutesGetHandler(formatter *render.Render) http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - - plugin.Log.Debug("Getting list of all static routes") - - // create an API channel - ch, err := plugin.GoVppmux.NewAPIChannel() - if err != nil { - plugin.Log.Errorf("Error creating channel: %v", err) - formatter.JSON(w, http.StatusInternalServerError, err) - return - } - defer ch.Close() - - res, err := l3plugin.DumpStaticRoutes(plugin.Log, ch, nil) - if err != nil { - plugin.Log.Errorf("Error: %v", err) - formatter.JSON(w, http.StatusInternalServerError, nil) - return - } - - plugin.Log.Debug(res) - formatter.JSON(w, http.StatusOK, res) - } +// Registers IPSec REST handlers +func (plugin *Plugin) registerIPSecHandlers() { + // GET IPSec SPD configuration + plugin.registerHTTPHandler(resturl.IPSecSpd, GET, func() (interface{}, error) { + return plugin.ipSecHandler.DumpIPSecSPD() + }) + // GET IPSec SA configuration + plugin.registerHTTPHandler(resturl.IPSecSa, GET, func() (interface{}, error) { + return plugin.ipSecHandler.DumpIPSecSA() + }) + // GET IPSec Tunnel configuration + plugin.registerHTTPHandler(resturl.IPSecTnIf, GET, func() (interface{}, error) { + return plugin.ipSecHandler.DumpIPSecTunnelInterfaces() + }) } -// interfaceACLGetHandler - used to get acl configuration for a particular interface -func (plugin *Plugin) interfaceACLGetHandler(formatter *render.Render) http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - - plugin.Log.Debug("Getting acl configuration of interface") - - vars := mux.Vars(req) - if vars == nil { - plugin.Log.Error("Interface software index not specified.") - formatter.JSON(w, http.StatusNotFound, "Interface software index not specified.") - return - } - - plugin.Log.Infof("Received request for swIndex: %v", vars[swIndexVarName]) - - swIndexuInt64, err := strconv.ParseUint(vars[swIndexVarName], 10, 32) - if err != nil { - plugin.Log.Error("Failed to unmarshal request body.") - formatter.JSON(w, http.StatusInternalServerError, err) - return - } - - // create an API channel - ch, err := plugin.GoVppmux.NewAPIChannel() - if err != nil { - plugin.Log.Errorf("Error creating channel: %v", err) - formatter.JSON(w, http.StatusInternalServerError, err) - return - } - defer ch.Close() - - swIndex := uint32(swIndexuInt64) - res, err := acldump.DumpInterfaceIPAcls(plugin.Deps.Log, swIndex, ch, nil) - if err != nil { - plugin.Deps.Log.Errorf("Error: %v", err) - formatter.JSON(w, http.StatusInternalServerError, err) - return - } - res, err = acldump.DumpInterfaceMACIPAcls(plugin.Log, swIndex, ch, nil) - if err != nil { - plugin.Log.Errorf("Error: %v", err) - formatter.JSON(w, http.StatusInternalServerError, err) - return - } - - plugin.Log.Debug(res) - formatter.JSON(w, http.StatusOK, res) - } +// Registers L2 plugin REST handlers +func (plugin *Plugin) registerL2Handlers() { + // GET bridge domain IDs + plugin.registerHTTPHandler(resturl.BdID, GET, func() (interface{}, error) { + return plugin.bdHandler.DumpBridgeDomainIDs() + }) + // GET bridge domains + plugin.registerHTTPHandler(resturl.Bd, GET, func() (interface{}, error) { + return plugin.bdHandler.DumpBridgeDomains() + }) + // GET FIB entries + plugin.registerHTTPHandler(resturl.Fib, GET, func() (interface{}, error) { + return plugin.fibHandler.DumpFIBTableEntries() + }) + // GET cross connects + plugin.registerHTTPHandler(resturl.Xc, GET, func() (interface{}, error) { + return plugin.xcHandler.DumpXConnectPairs() + }) } -// ipACLGetHandler - used to get configuration of IP ACLs -func (plugin *Plugin) ipACLGetHandler(formatter *render.Render) http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - - plugin.Log.Debug("Getting acls") - - // create an API channel - ch, err := plugin.GoVppmux.NewAPIChannel() - if err != nil { - plugin.Log.Errorf("Error creating channel: %v", err) - formatter.JSON(w, http.StatusInternalServerError, err) - return - } - defer ch.Close() - - res, err := acldump.DumpIPACL(nil, plugin.Deps.Log, ch, nil) - if err != nil { - plugin.Deps.Log.Errorf("Error: %v", err) - formatter.JSON(w, http.StatusInternalServerError, err) - return - } - - plugin.Deps.Log.Debug(res) - formatter.JSON(w, http.StatusOK, res) - } +// Registers L3 plugin REST handlers +func (plugin *Plugin) registerL3Handlers() { + // GET ARP entries + plugin.registerHTTPHandler(resturl.Arps, GET, func() (interface{}, error) { + return plugin.arpHandler.DumpArpEntries() + }) + // GET proxy ARP interfaces + plugin.registerHTTPHandler(resturl.PArpIfs, GET, func() (interface{}, error) { + return plugin.pArpHandler.DumpProxyArpInterfaces() + }) + // GET proxy ARP ranges + plugin.registerHTTPHandler(resturl.PArpRngs, GET, func() (interface{}, error) { + return plugin.pArpHandler.DumpProxyArpRanges() + }) + // GET static routes + plugin.registerHTTPHandler(resturl.Routes, GET, func() (interface{}, error) { + return plugin.rtHandler.DumpStaticRoutes() + }) } -func (plugin *Plugin) macipACLGetHandler(formatter *render.Render) http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - plugin.Deps.Log.Info("Getting macip acls") - - // create an API channel - ch, err := plugin.Deps.GoVppmux.NewAPIChannel() - defer ch.Close() - if err != nil { - plugin.Deps.Log.Errorf("Error: %v", err) - formatter.JSON(w, http.StatusInternalServerError, err) - return - } - - res, err := acldump.DumpMACIPACL(nil, plugin.Deps.Log, ch, nil) - if err != nil { - plugin.Log.Errorf("Error: %v", err) - formatter.JSON(w, http.StatusInternalServerError, err) - return - } - - plugin.Log.Debug(res) - formatter.JSON(w, http.StatusOK, res) - } +// Registers L3 plugin REST handlers +func (plugin *Plugin) registerL4Handlers() { + // GET static routes + plugin.registerHTTPHandler(resturl.Sessions, GET, func() (interface{}, error) { + return plugin.l4Handler.DumpL4Config() + }) } -// exampleACLGetHandler - used to get an example ACL configuration -func (plugin *Plugin) exampleIpACLGetHandler(formatter *render.Render) http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - - plugin.Log.Debug("Getting example acl") - - ipRule := &acl.AccessLists_Acl_Rule_Match_IpRule{ - Ip: &acl.AccessLists_Acl_Rule_Match_IpRule_Ip{ - DestinationNetwork: "1.2.3.4/24", - SourceNetwork: "5.6.7.8/24", - }, - Tcp: &acl.AccessLists_Acl_Rule_Match_IpRule_Tcp{ - DestinationPortRange: &acl.AccessLists_Acl_Rule_Match_IpRule_PortRange{ - LowerPort: 80, - UpperPort: 8080, - }, - SourcePortRange: &acl.AccessLists_Acl_Rule_Match_IpRule_PortRange{ - LowerPort: 10, - UpperPort: 1010, - }, - TcpFlagsMask: 0xFF, - TcpFlagsValue: 9, - }, - } - - rule := &acl.AccessLists_Acl_Rule{ - Match: &acl.AccessLists_Acl_Rule_Match{ - IpRule: ipRule, - }, - AclAction: acl.AclAction_PERMIT, - } - - aclRes := acl.AccessLists_Acl{ - AclName: "example", - Rules: []*acl.AccessLists_Acl_Rule{rule}, - } - - plugin.Log.Debug(aclRes) - formatter.JSON(w, http.StatusOK, aclRes) - } +// Registers Telemetry handler +func (plugin *Plugin) registerTelemetryHandlers() { + plugin.HTTPHandlers.RegisterHTTPHandler(resturl.Telemetry, plugin.telemetryHandler, GET) + plugin.HTTPHandlers.RegisterHTTPHandler(resturl.TMemory, plugin.telemetryMemoryHandler, GET) + plugin.HTTPHandlers.RegisterHTTPHandler(resturl.TRuntime, plugin.telemetryRuntimeHandler, GET) + plugin.HTTPHandlers.RegisterHTTPHandler(resturl.TNodeCount, plugin.telemetryNodeCountHandler, GET) } -func (plugin *Plugin) exampleMacIpACLGetHandler(formatter *render.Render) http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - plugin.Deps.Log.Info("Getting example macip acl") - - macipRule := &acl.AccessLists_Acl_Rule_Match_MacIpRule{ - SourceAddress: "192.168.0.1", - SourceAddressPrefix: uint32(16), - SourceMacAddress: "02:00:DE:AD:00:02", - SourceMacAddressMask: "ff:ff:ff:ff:00:00", - } - - rule := &acl.AccessLists_Acl_Rule{ - Match: &acl.AccessLists_Acl_Rule_Match{ - MacipRule: macipRule, - }, - AclAction: acl.AclAction_PERMIT, - } - - aclRes := acl.AccessLists_Acl{ - AclName: "example", - Rules: []*acl.AccessLists_Acl_Rule{rule}, - } - - plugin.Deps.Log.Debug(aclRes) - formatter.JSON(w, http.StatusOK, aclRes) - } +// Registers command handler +func (plugin *Plugin) registerCommandHandler() { + plugin.HTTPHandlers.RegisterHTTPHandler(resturl.Command, plugin.commandHandler, POST) } -// ipACLPostHandler - used to get acl configuration for a particular interface -func (plugin *Plugin) ipACLPostHandler(formatter *render.Render) http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - - body, err := ioutil.ReadAll(req.Body) - if err != nil { - plugin.Deps.Log.Error("Failed to parse request body.") - formatter.JSON(w, http.StatusBadRequest, err) - return - } - aclParam := acl.AccessLists_Acl{} - err = json.Unmarshal(body, &aclParam) - if err != nil { - plugin.Deps.Log.Error("Failed to unmarshal request body.") - formatter.JSON(w, http.StatusBadRequest, err) - return - } +// Registers index page +func (plugin *Plugin) registerIndexHandlers() { + r := render.New(render.Options{ + Directory: "templates", + Asset: Asset, + AssetNames: AssetNames, + }) - // create an API channel - ch, err := plugin.Deps.GoVppmux.NewAPIChannel() - defer ch.Close() - if err != nil { - plugin.Deps.Log.Errorf("Error: %v", err) - formatter.JSON(w, http.StatusInternalServerError, err) - return - } + handlerFunc := func(formatter *render.Render) http.HandlerFunc { + return func(w http.ResponseWriter, req *http.Request) { - var aclIndex struct { - Idx uint32 `json:"acl_index"` + plugin.Log.Debugf("%v - %s %q", req.RemoteAddr, req.Method, req.URL) + r.HTML(w, http.StatusOK, "index", plugin.index) } - aclIndex.Idx, err = aclcalls.AddIPAcl(aclParam.Rules, aclParam.AclName, plugin.Deps.Log, ch, nil) - if err != nil { - plugin.Deps.Log.Errorf("Error: %v", err) - formatter.JSON(w, http.StatusInternalServerError, aclIndex) - return - } - - plugin.Deps.Log.Debug(aclIndex) - formatter.JSON(w, http.StatusOK, aclIndex) } + plugin.HTTPHandlers.RegisterHTTPHandler(resturl.Index, handlerFunc, GET) } -func (plugin *Plugin) macipACLPostHandler(formatter *render.Render) http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { +// registerHTTPHandler is common register method for all handlers +func (plugin *Plugin) registerHTTPHandler(key, method string, f func() (interface{}, error)) { + handlerFunc := func(formatter *render.Render) http.HandlerFunc { + return func(w http.ResponseWriter, req *http.Request) { + plugin.govppmux.Lock() + defer plugin.govppmux.Unlock() - body, err := ioutil.ReadAll(req.Body) - if err != nil { - plugin.Log.Error("Failed to parse request body.") - formatter.JSON(w, http.StatusBadRequest, err) - return - } - aclParam := acl.AccessLists_Acl{} - err = json.Unmarshal(body, &aclParam) - if err != nil { - plugin.Log.Error("Failed to unmarshal request body.") - formatter.JSON(w, http.StatusBadRequest, err) - return - } - - // create an API channel - ch, err := plugin.GoVppmux.NewAPIChannel() - if err != nil { - plugin.Log.Errorf("Error creating channel: %v", err) - formatter.JSON(w, http.StatusInternalServerError, err) - return - } - defer ch.Close() - - var aclIndex struct { - Idx uint32 `json:"acl_index"` - } - aclIndex.Idx, err = aclcalls.AddMacIPAcl(aclParam.Rules, aclParam.AclName, plugin.Deps.Log, ch, nil) - if err != nil { - plugin.Log.Errorf("Error: %v", err) - formatter.JSON(w, http.StatusInternalServerError, aclIndex) - return + res, err := f() + if err != nil { + plugin.Deps.Log.Errorf("Error: %v", err) + errStr := fmt.Sprintf("500 Internal server error: %s\n", err.Error()) + formatter.Text(w, http.StatusInternalServerError, errStr) + return + } + plugin.Deps.Log.Debugf("Rest uri: %s, data: %v", key, res) + formatter.JSON(w, http.StatusOK, res) } - - plugin.Log.Debug(aclIndex) - formatter.JSON(w, http.StatusOK, aclIndex) } + plugin.HTTPHandlers.RegisterHTTPHandler(key, handlerFunc, method) } // commandHandler - used to execute VPP CLI commands @@ -496,12 +273,12 @@ func (plugin *Plugin) commandHandler(formatter *render.Render) http.HandlerFunc reply := &vpe.CliInbandReply{} err = ch.SendRequest(r).ReceiveReply(reply) if err != nil { - err = fmt.Errorf("Sending request failed: %v", err) + err = fmt.Errorf("sending request failed: %v", err) plugin.Log.Error(err) formatter.JSON(w, http.StatusInternalServerError, err) return } else if reply.Retval > 0 { - err = fmt.Errorf("Request returned error code: %v", reply.Retval) + err = fmt.Errorf("request returned error code: %v", reply.Retval) plugin.Log.Error(err) formatter.JSON(w, http.StatusInternalServerError, err) return @@ -520,9 +297,9 @@ func (plugin *Plugin) sendCommand(ch govppapi.Channel, command string) ([]byte, reply := &vpe.CliInbandReply{} if err := ch.SendRequest(r).ReceiveReply(reply); err != nil { - return nil, fmt.Errorf("Sending request failed: %v", err) + return nil, fmt.Errorf("sending request failed: %v", err) } else if reply.Retval > 0 { - return nil, fmt.Errorf("Request returned error code: %v", reply.Retval) + return nil, fmt.Errorf("request returned error code: %v", reply.Retval) } return reply.Reply[:reply.Length], nil @@ -638,17 +415,3 @@ func (plugin *Plugin) telemetryNodeCountHandler(formatter *render.Render) http.H formatter.JSON(w, http.StatusOK, nodeCounters) } } - -// indexHandler - used to get index page -func (plugin *Plugin) indexHandler(formatter *render.Render) http.HandlerFunc { - r := render.New(render.Options{ - Directory: "templates", - Asset: Asset, - AssetNames: AssetNames, - }) - return func(w http.ResponseWriter, req *http.Request) { - plugin.Log.Debugf("%v - %s %q", req.RemoteAddr, req.Method, req.URL) - - r.HTML(w, http.StatusOK, "index", plugin.indexItems) - } -} diff --git a/plugins/rest/resturl/rest_url.go b/plugins/rest/resturl/rest_url.go new file mode 100644 index 0000000000..15f1aee09a --- /dev/null +++ b/plugins/rest/resturl/rest_url.go @@ -0,0 +1,128 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package resturl + +// Access list REST urls +const ( + // REST ACL IP prefix + ACLIP = "/vpp/dump/v1/acl/ip" + // REST ACL MACIP prefix + ACLMACIP = "/vpp/dump/v1/acl/macip" +) + +// BFD REST urls +const ( + // BfdURL is a REST path of a bfd + BfdURL = "/vpp/dump/v1/bfd" + // BfdSession is a REST path of a bfd sessions + BfdSession = "/vpp/dump/v1/bfd/sessions" + // BfdAuthKey is a REST path of a bfd authentication keys + BfdAuthKey = "/vpp/dump/v1/bfd/authkeys" +) + +// Interface REST urls +const ( + // restInterface is rest interface path + Interface = "/vpp/dump/v1/interfaces" + // restLoopback is path for loopback interface + Loopback = "/vpp/dump/v1/interfaces/loopback" + // restLoopback is path for physical interface + Ethernet = "/vpp/dump/v1/interfaces/ethernet" + // restLoopback is path for memif interface + Memif = "/vpp/dump/v1/interfaces/memif" + // restLoopback is path for tap interface + Tap = "/vpp/dump/v1/interfaces/tap" + // restAfPacket is path for af-packet interface + AfPacket = "/vpp/dump/v1/interfaces/afpacket" + // restLoopback is path for vxlan interface + VxLan = "/vpp/dump/v1/interfaces/vxlan" +) + +// NAT REST urls +const ( + // NatURL is a REST path of a NAT + NatURL = "/vpp/dump/v1/nat" + // NatGlobal is a REST path of a global NAT config + NatGlobal = "/vpp/dump/v1/nat/global" + // NatDNat is a REST path of a DNAT configurations + NatDNat = "/vpp/dump/v1/nat/dnat" +) + +// STN REST url +const ( + // StnURL is a REST path of a STN + StnURL = "/vpp/dump/v1/stn" +) + +// IPSec REST url +const ( + // IPSecSpd is a REST path of a IPSec SPD + IPSecSpd = "/vpp/dump/v1/ipsec/spd" + // IPSecSa is a REST path of a IPSec SA + IPSecSa = "/vpp/dump/v1/ipsec/sa" + // IPSecTnIf is a REST path of a IPSec Tunnels + IPSecTnIf = "/vpp/dump/v1/ipsec/tunnel" +) + +// L2 plugin +const ( + // restBd is rest bridge domain path + Bd = "/vpp/dump/v1/bd" + // restBdId is rest bridge domain ID path + BdID = "/vpp/dump/v1/bdid" + // restFib is rest FIB path + Fib = "/vpp/dump/v1/fib" + // restXc is rest cross-connect path + Xc = "/vpp/dump/v1/xc" +) + +// L3 plugin +const ( + // Routes is rest static route path + Routes = "/vpp/dump/v1/routes" + // Arps is rest ARPs path + Arps = "/vpp/dump/v1/arps" + // PArpIfs is rest proxy ARP interfaces path + PArpIfs = "/vpp/dump/v1/proxyarp/interfaces" + // PArpRngs is rest proxy ARP ranges path + PArpRngs = "/vpp/dump/v1/proxyarp/ranges" +) + +// L4 plugin +const ( + // Sessions is rest L4 configuration path + Sessions = "/vpp/dump/v1/sessions" +) + +// Command +const ( + // Command allows to put CLI command to the rest + Command = "/vpp/command" +) + +// Telemetry +const ( + // Telemetry reads various types of metrics data from the VPP + Telemetry = "/vpp/telemetry" + TMemory = "/vpp/telemetry/memory" + TRuntime = "/vpp/telemetry/runtime" + TNodeCount = "/vpp/telemetry/nodecount" +) + +// Index +const ( + // Index can be used to get the full index page + Index = "/" +) diff --git a/plugins/rest/templates/index.tmpl b/plugins/rest/templates/index.tmpl index ad2b9f4353..79a636104d 100644 --- a/plugins/rest/templates/index.tmpl +++ b/plugins/rest/templates/index.tmpl @@ -6,10 +6,13 @@

Index:

    -{{range .}} -
  • - {{.Name}} -
  • +{{range $key, $data := .ItemMap}} +

    {{$key}}:

    + {{range $dataEntry := $data}} +
  • + {{$dataEntry.Name}} +
  • + {{end}} {{end}}
diff --git a/plugins/telemetry/config.go b/plugins/telemetry/config.go index 35a0eb3487..bb785943d9 100644 --- a/plugins/telemetry/config.go +++ b/plugins/telemetry/config.go @@ -27,14 +27,14 @@ type Config struct { // getConfig returns telemetry plugin file configuration if exists func (p *Plugin) getConfig() (*Config, error) { config := &Config{} - found, err := p.PluginInfraDeps.GetValue(config) + found, err := p.Cfg.LoadValue(config) + if err != nil { + return nil, err + } if !found { p.Log.Debug("Telemetry config not found") return nil, nil } - if err != nil { - return nil, err - } p.Log.Debug("Telemetry config found") return config, err } diff --git a/plugins/telemetry/options.go b/plugins/telemetry/options.go new file mode 100644 index 0000000000..1228bb23cb --- /dev/null +++ b/plugins/telemetry/options.go @@ -0,0 +1,38 @@ +package telemetry + +import ( + "github.com/ligato/cn-infra/rpc/prometheus" + "github.com/ligato/cn-infra/servicelabel" + "github.com/ligato/vpp-agent/plugins/govppmux" +) + +// DefaultPlugin is default instance of Plugin +var DefaultPlugin = *NewPlugin() + +// NewPlugin creates a new Plugin with the provides Options +func NewPlugin(opts ...Option) *Plugin { + p := &Plugin{} + + p.PluginName = "telemetry" + p.ServiceLabel = &servicelabel.DefaultPlugin + p.GoVppmux = &govppmux.DefaultPlugin + p.Prometheus = &prometheus.DefaultPlugin + + for _, o := range opts { + o(p) + } + + p.PluginDeps.Setup() + + return p +} + +// Option is a function that acts on a Plugin to inject Dependencies or configuration +type Option func(*Plugin) + +// UseDeps returns Option that can inject custom dependencies. +func UseDeps(cb func(*Deps)) Option { + return func(p *Plugin) { + cb(&p.Deps) + } +} diff --git a/plugins/telemetry/telemetry.go b/plugins/telemetry/telemetry.go index 5e52037390..f0b6e68e7f 100644 --- a/plugins/telemetry/telemetry.go +++ b/plugins/telemetry/telemetry.go @@ -19,8 +19,9 @@ import ( "time" govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/flavors/local" + "github.com/ligato/cn-infra/infra" prom "github.com/ligato/cn-infra/rpc/prometheus" + "github.com/ligato/cn-infra/servicelabel" "github.com/ligato/vpp-agent/plugins/govppmux" "github.com/ligato/vpp-agent/plugins/govppmux/vppcalls" "github.com/prometheus/client_golang/prometheus" @@ -105,10 +106,10 @@ type Plugin struct { // Deps represents dependencies of Telemetry Plugin type Deps struct { - local.PluginInfraDeps - - GoVppmux govppmux.API - Prometheus prom.API + infra.PluginDeps + ServiceLabel servicelabel.ReaderAPI + GoVppmux govppmux.API + Prometheus prom.API } type runtimeStats struct { diff --git a/plugins/vpp/aclplugin/acl_config.go b/plugins/vpp/aclplugin/acl_config.go index 254a451fde..882ec9fac5 100644 --- a/plugins/vpp/aclplugin/acl_config.go +++ b/plugins/vpp/aclplugin/acl_config.go @@ -29,7 +29,6 @@ import ( "github.com/ligato/vpp-agent/plugins/govppmux" "github.com/ligato/vpp-agent/plugins/vpp/aclplugin/aclidx" "github.com/ligato/vpp-agent/plugins/vpp/aclplugin/vppcalls" - "github.com/ligato/vpp-agent/plugins/vpp/aclplugin/vppdump" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" "github.com/ligato/vpp-agent/plugins/vpp/model/acl" ) @@ -58,19 +57,19 @@ type ACLConfigurator struct { // In-memory mappings ifIndexes ifaceidx.SwIfIndex - l2AclIndexes aclidx.AclIndexRW - l3l4AclIndexes aclidx.AclIndexRW + l2AclIndexes aclidx.ACLIndexRW + l3l4AclIndexes aclidx.ACLIndexRW // Cache for ACL un-configured interfaces ifCache []*ACLIfCacheEntry - // VPP binary api call helper - vppCalls *vppcalls.ACLInterfacesVppCalls - // VPP channels vppChan govppapi.Channel vppDumpChan govppapi.Channel + // ACL VPP calls handler + aclHandler vppcalls.ACLVppAPI + // Timer used to measure and store time stopwatch *measure.Stopwatch } @@ -84,8 +83,8 @@ func (plugin *ACLConfigurator) Init(logger logging.PluginLogger, goVppMux govppm // Mappings plugin.ifIndexes = swIfIndexes - plugin.l2AclIndexes = aclidx.NewAclIndex(nametoidx.NewNameToIdx(plugin.log, "acl_l2_indexes", nil)) - plugin.l3l4AclIndexes = aclidx.NewAclIndex(nametoidx.NewNameToIdx(plugin.log, "acl_l3_l4_indexes", nil)) + plugin.l2AclIndexes = aclidx.NewACLIndex(nametoidx.NewNameToIdx(plugin.log, "acl_l2_indexes", nil)) + plugin.l3l4AclIndexes = aclidx.NewACLIndex(nametoidx.NewNameToIdx(plugin.log, "acl_l3_l4_indexes", nil)) // VPP channels plugin.vppChan, err = goVppMux.NewAPIChannel() @@ -97,26 +96,13 @@ func (plugin *ACLConfigurator) Init(logger logging.PluginLogger, goVppMux govppm return err } - // Stopwatch + // Configurator-wide stopwatch instance if enableStopwatch { - plugin.stopwatch = measure.NewStopwatch("ACLConfigurator", plugin.log) + plugin.stopwatch = measure.NewStopwatch("ACL-configurator", plugin.log) } - // Message compatibility - if err = plugin.vppChan.CheckMessageCompatibility(vppcalls.AclMessages...); err != nil { - plugin.log.Error(err) - return err - } - - // VPP calls helper object - plugin.vppCalls = vppcalls.NewACLInterfacesVppCalls(plugin.log, plugin.vppChan, plugin.ifIndexes, plugin.stopwatch) - - // Get VPP ACL plugin version - var aclVersion string - if aclVersion, err = vppcalls.GetAclPluginVersion(plugin.vppChan, plugin.stopwatch); err != nil { - return err - } - plugin.log.Infof("VPP ACL plugin version is %s", aclVersion) + // ACL binary api handler + plugin.aclHandler = vppcalls.NewACLVppHandler(plugin.vppChan, plugin.vppDumpChan, plugin.stopwatch) return nil } @@ -133,12 +119,12 @@ func (plugin *ACLConfigurator) clearMapping() { } // GetL2AclIfIndexes exposes l2 acl interface name-to-index mapping -func (plugin *ACLConfigurator) GetL2AclIfIndexes() aclidx.AclIndexRW { +func (plugin *ACLConfigurator) GetL2AclIfIndexes() aclidx.ACLIndexRW { return plugin.l2AclIndexes } // GetL3L4AclIfIndexes exposes l3/l4 acl interface name-to-index mapping -func (plugin *ACLConfigurator) GetL3L4AclIfIndexes() aclidx.AclIndexRW { +func (plugin *ACLConfigurator) GetL3L4AclIfIndexes() aclidx.ACLIndexRW { return plugin.l3l4AclIndexes } @@ -156,7 +142,7 @@ func (plugin *ACLConfigurator) ConfigureACL(acl *acl.AccessLists_Acl) error { var vppACLIndex uint32 var err error if isL2MacIP { - vppACLIndex, err = vppcalls.AddMacIPAcl(rules, acl.AclName, plugin.log, plugin.vppChan, plugin.stopwatch) + vppACLIndex, err = plugin.aclHandler.AddMacIPACL(rules, acl.AclName) if err != nil { return err } @@ -165,7 +151,7 @@ func (plugin *ACLConfigurator) ConfigureACL(acl *acl.AccessLists_Acl) error { plugin.l2AclIndexes.RegisterName(acl.AclName, agentACLIndex, acl) plugin.log.Debugf("ACL %v registered with index %v", acl.AclName, agentACLIndex) } else { - vppACLIndex, err = vppcalls.AddIPAcl(rules, acl.AclName, plugin.log, plugin.vppChan, plugin.stopwatch) + vppACLIndex, err = plugin.aclHandler.AddIPACL(rules, acl.AclName) if err != nil { return err } @@ -179,18 +165,18 @@ func (plugin *ACLConfigurator) ConfigureACL(acl *acl.AccessLists_Acl) error { if ifaces := acl.GetInterfaces(); ifaces != nil { if isL2MacIP { aclIfIndices := plugin.getOrCacheInterfaces(acl.Interfaces.Ingress, vppACLIndex, L2) - err := plugin.vppCalls.SetMacIPAclToInterface(vppACLIndex, aclIfIndices) + err := plugin.aclHandler.SetMacIPACLToInterface(vppACLIndex, aclIfIndices) if err != nil { return err } } else { aclIfInIndices := plugin.getOrCacheInterfaces(acl.Interfaces.Ingress, vppACLIndex, INGRESS) - err = plugin.vppCalls.SetACLToInterfacesAsIngress(vppACLIndex, aclIfInIndices) + err = plugin.aclHandler.SetACLToInterfacesAsIngress(vppACLIndex, aclIfInIndices) if err != nil { return err } aclIfEgIndices := plugin.getOrCacheInterfaces(acl.Interfaces.Egress, vppACLIndex, EGRESS) - err = plugin.vppCalls.SetACLToInterfacesAsEgress(vppACLIndex, aclIfEgIndices) + err = plugin.aclHandler.SetACLToInterfacesAsEgress(vppACLIndex, aclIfEgIndices) if err != nil { return err } @@ -214,7 +200,7 @@ func (plugin *ACLConfigurator) ModifyACL(oldACL, newACL *acl.AccessLists_Acl) (e if isL2MacIP { agentACLIndex, _, found := plugin.l2AclIndexes.LookupIdx(oldACL.AclName) if !found { - plugin.log.Infof("Acl %v index not found", oldACL.AclName) + plugin.log.Infof("ACL %v index not found", oldACL.AclName) return nil } // Index used in VPP = index used in mapping - 1 @@ -222,21 +208,21 @@ func (plugin *ACLConfigurator) ModifyACL(oldACL, newACL *acl.AccessLists_Acl) (e } else { agentACLIndex, _, found := plugin.l3l4AclIndexes.LookupIdx(oldACL.AclName) if !found { - plugin.log.Infof("Acl %v index not found", oldACL.AclName) + plugin.log.Infof("ACL %v index not found", oldACL.AclName) return nil } vppACLIndex = agentACLIndex - 1 } if isL2MacIP { // L2 ACL - err := vppcalls.ModifyMACIPAcl(vppACLIndex, rules, newACL.AclName, plugin.log, plugin.vppChan, plugin.stopwatch) + err := plugin.aclHandler.ModifyMACIPACL(vppACLIndex, rules, newACL.AclName) if err != nil { return err } // There is no need to update index because modified ACL keeps the old one. } else { // L3/L4 ACL can be modified directly. - err := vppcalls.ModifyIPAcl(vppACLIndex, rules, newACL.AclName, plugin.log, plugin.vppChan, plugin.stopwatch) + err := plugin.aclHandler.ModifyIPACL(vppACLIndex, rules, newACL.AclName) if err != nil { return err } @@ -248,7 +234,7 @@ func (plugin *ACLConfigurator) ModifyACL(oldACL, newACL *acl.AccessLists_Acl) (e // Remove L2 ACL from old interfaces. if oldACL.Interfaces != nil { - err := plugin.vppCalls.RemoveMacIPIngressACLFromInterfaces(vppACLIndex, plugin.getInterfaces(oldACL.Interfaces.Ingress)) + err := plugin.aclHandler.RemoveMacIPIngressACLFromInterfaces(vppACLIndex, plugin.getInterfaces(oldACL.Interfaces.Ingress)) if err != nil { return err } @@ -256,7 +242,7 @@ func (plugin *ACLConfigurator) ModifyACL(oldACL, newACL *acl.AccessLists_Acl) (e // Put L2 ACL to new interfaces. if newACL.Interfaces != nil { aclMacInterfaces := plugin.getOrCacheInterfaces(newACL.Interfaces.Ingress, vppACLIndex, L2) - err := plugin.vppCalls.SetMacIPAclToInterface(vppACLIndex, aclMacInterfaces) + err := plugin.aclHandler.SetMacIPACLToInterface(vppACLIndex, aclMacInterfaces) if err != nil { return err } @@ -271,25 +257,25 @@ func (plugin *ACLConfigurator) ModifyACL(oldACL, newACL *acl.AccessLists_Acl) (e addedEgInterfaces, removedEgInterfaces := diffInterfaces(aclOldEgInterfaces, aclNewEgInterfaces) if len(removedInInterfaces) > 0 { - err = plugin.vppCalls.RemoveIPIngressACLFromInterfaces(vppACLIndex, removedInInterfaces) + err = plugin.aclHandler.RemoveIPIngressACLFromInterfaces(vppACLIndex, removedInInterfaces) if err != nil { return err } } if len(removedEgInterfaces) > 0 { - err = plugin.vppCalls.RemoveIPEgressACLFromInterfaces(vppACLIndex, removedEgInterfaces) + err = plugin.aclHandler.RemoveIPEgressACLFromInterfaces(vppACLIndex, removedEgInterfaces) if err != nil { return err } } if len(addedInInterfaces) > 0 { - err = plugin.vppCalls.SetACLToInterfacesAsIngress(vppACLIndex, addedInInterfaces) + err = plugin.aclHandler.SetACLToInterfacesAsIngress(vppACLIndex, addedInInterfaces) if err != nil { return err } } if len(addedEgInterfaces) > 0 { - err = plugin.vppCalls.SetACLToInterfacesAsEgress(vppACLIndex, addedEgInterfaces) + err = plugin.aclHandler.SetACLToInterfacesAsEgress(vppACLIndex, addedEgInterfaces) if err != nil { return err } @@ -314,13 +300,13 @@ func (plugin *ACLConfigurator) DeleteACL(acl *acl.AccessLists_Acl) (err error) { // Remove interfaces from L2 ACL. vppACLIndex := agentL2AclIndex - 1 if acl.Interfaces != nil { - err := plugin.vppCalls.RemoveMacIPIngressACLFromInterfaces(vppACLIndex, plugin.getInterfaces(acl.Interfaces.Ingress)) + err := plugin.aclHandler.RemoveMacIPIngressACLFromInterfaces(vppACLIndex, plugin.getInterfaces(acl.Interfaces.Ingress)) if err != nil { return err } } // Remove ACL L2. - err := vppcalls.DeleteMacIPAcl(vppACLIndex, plugin.log, plugin.vppChan, plugin.stopwatch) + err := plugin.aclHandler.DeleteMacIPACL(vppACLIndex) if err != nil { return err } @@ -331,18 +317,18 @@ func (plugin *ACLConfigurator) DeleteACL(acl *acl.AccessLists_Acl) (err error) { // Remove interfaces. vppACLIndex := agentL3L4AclIndex - 1 if acl.Interfaces != nil { - err = plugin.vppCalls.RemoveIPIngressACLFromInterfaces(vppACLIndex, plugin.getInterfaces(acl.Interfaces.Ingress)) + err = plugin.aclHandler.RemoveIPIngressACLFromInterfaces(vppACLIndex, plugin.getInterfaces(acl.Interfaces.Ingress)) if err != nil { return err } - err = plugin.vppCalls.RemoveIPEgressACLFromInterfaces(vppACLIndex, plugin.getInterfaces(acl.Interfaces.Egress)) + err = plugin.aclHandler.RemoveIPEgressACLFromInterfaces(vppACLIndex, plugin.getInterfaces(acl.Interfaces.Egress)) if err != nil { return err } } // Remove ACL L3/L4. - err := vppcalls.DeleteIPAcl(vppACLIndex, plugin.log, plugin.vppChan, plugin.stopwatch) + err := plugin.aclHandler.DeleteIPACL(vppACLIndex) if err != nil { return err } @@ -355,26 +341,26 @@ func (plugin *ACLConfigurator) DeleteACL(acl *acl.AccessLists_Acl) (err error) { // DumpIPACL returns all configured IP ACLs in proto format func (plugin *ACLConfigurator) DumpIPACL() (acls []*acl.AccessLists_Acl, err error) { - aclsWithIndex, err := vppdump.DumpIPACL(plugin.ifIndexes, plugin.log, plugin.vppDumpChan, plugin.stopwatch) + aclsWithIndex, err := plugin.aclHandler.DumpIPACL(plugin.ifIndexes) if err != nil { plugin.log.Error(err) return nil, err } for _, aclWithIndex := range aclsWithIndex { - acls = append(acls, aclWithIndex.ACLDetails) + acls = append(acls, aclWithIndex.ACL) } return acls, nil } // DumpMACIPACL returns all configured MACIP ACLs in proto format func (plugin *ACLConfigurator) DumpMACIPACL() (acls []*acl.AccessLists_Acl, err error) { - aclsWithIndex, err := vppdump.DumpMACIPACL(plugin.ifIndexes, plugin.log, plugin.vppDumpChan, plugin.stopwatch) + aclsWithIndex, err := plugin.aclHandler.DumpMACIPACL(plugin.ifIndexes) if err != nil { plugin.log.Error(err) return nil, err } for _, aclWithIndex := range aclsWithIndex { - acls = append(acls, aclWithIndex.ACLDetails) + acls = append(acls, aclWithIndex.ACL) } return acls, nil } @@ -421,17 +407,17 @@ func (plugin *ACLConfigurator) ResolveCreatedInterface(ifName string, ifIdx uint var ifIndices []uint32 switch aclCacheEntry.ifAttr { case L2: - if err := plugin.vppCalls.SetMacIPAclToInterface(aclCacheEntry.aclID, append(ifIndices, ifIdx)); err != nil { + if err := plugin.aclHandler.SetMacIPACLToInterface(aclCacheEntry.aclID, append(ifIndices, ifIdx)); err != nil { plugin.log.Error(err) wasErr = err } case INGRESS: - if err := plugin.vppCalls.SetACLToInterfacesAsIngress(aclCacheEntry.aclID, append(ifIndices, ifIdx)); err != nil { + if err := plugin.aclHandler.SetACLToInterfacesAsIngress(aclCacheEntry.aclID, append(ifIndices, ifIdx)); err != nil { plugin.log.Error(err) wasErr = err } case EGRESS: - if err := plugin.vppCalls.SetACLToInterfacesAsEgress(aclCacheEntry.aclID, append(ifIndices, ifIdx)); err != nil { + if err := plugin.aclHandler.SetACLToInterfacesAsEgress(aclCacheEntry.aclID, append(ifIndices, ifIdx)); err != nil { plugin.log.Error(err) wasErr = err } @@ -465,14 +451,14 @@ func (plugin *ACLConfigurator) ResolveDeletedInterface(ifName string, ifIdx uint plugin.log.Warnf("ACL %v not found in the mapping", aclName) continue } - vppAclIdx := aclIdx - 1 + vppACLIdx := aclIdx - 1 if ifaces := aclData.GetInterfaces(); ifaces != nil { // Look over ingress interfaces for _, iface := range ifaces.Ingress { if iface == ifName { plugin.ifCache = append(plugin.ifCache, &ACLIfCacheEntry{ ifName: ifName, - aclID: vppAclIdx, + aclID: vppACLIdx, ifAttr: INGRESS, }) } @@ -482,7 +468,7 @@ func (plugin *ACLConfigurator) ResolveDeletedInterface(ifName string, ifIdx uint if iface == ifName { plugin.ifCache = append(plugin.ifCache, &ACLIfCacheEntry{ ifName: ifName, - aclID: vppAclIdx, + aclID: vppACLIdx, ifAttr: EGRESS, }) } @@ -496,14 +482,14 @@ func (plugin *ACLConfigurator) ResolveDeletedInterface(ifName string, ifIdx uint plugin.log.Warnf("ACL %v not found in the mapping", aclName) continue } - vppAclIdx := aclIdx - 1 + vppACLIdx := aclIdx - 1 if ifaces := aclData.GetInterfaces(); ifaces != nil { // Look over ingress interfaces for _, ingressIf := range ifaces.Ingress { if ingressIf == ifName { plugin.ifCache = append(plugin.ifCache, &ACLIfCacheEntry{ ifName: ifName, - aclID: vppAclIdx, + aclID: vppACLIdx, ifAttr: L2, }) } @@ -556,7 +542,7 @@ func (plugin *ACLConfigurator) validateRules(aclName string, rules []*acl.Access } } if len(validL3L4Rules) > 0 && len(validL2Rules) > 0 { - plugin.log.Errorf("Acl %v contains even L2 rules and L3/L4 rules. This case is not supported yet, only L3/L4 rules will be resolved", + plugin.log.Errorf("ACL %v contains even L2 rules and L3/L4 rules. This case is not supported yet, only L3/L4 rules will be resolved", aclName) return validL3L4Rules, false } else if len(validL3L4Rules) > 0 { diff --git a/plugins/vpp/aclplugin/acl_config_test.go b/plugins/vpp/aclplugin/acl_config_test.go index cd716b5cf2..80d116e7c8 100644 --- a/plugins/vpp/aclplugin/acl_config_test.go +++ b/plugins/vpp/aclplugin/acl_config_test.go @@ -20,7 +20,6 @@ import ( "git.fd.io/govpp.git/adapter/mock" "git.fd.io/govpp.git/core" "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/vpp/aclplugin" acl_api "github.com/ligato/vpp-agent/plugins/vpp/binapi/acl" @@ -73,29 +72,8 @@ var macipAcls = acl.AccessLists_Acl{ }, } -// Test AclConfigurator initialization -func TestAclConfiguratorInit(t *testing.T) { - RegisterTestingT(t) - ctx := &vppcallmock.TestCtx{ - MockVpp: &mock.VppAdapter{}, - } - connection, _ := core.Connect(ctx.MockVpp) - defer connection.Disconnect() - - plugin := &aclplugin.ACLConfigurator{} - - ctx.MockVpp.MockReply(&acl_api.ACLPluginGetVersionReply{}) - - // Test init - err := plugin.Init(logging.ForPlugin("test-log", logrus.NewLogRegistry()), connection, nil, false) - Expect(err).To(BeNil()) - err = plugin.Close() - Expect(err).To(BeNil()) -} - // Test creation of ACLs and sets acls to interfaces func TestConfigureACL(t *testing.T) { - // Setup ctx, connection, plugin := aclTestSetup(t, false) defer aclTestTeardown(connection, plugin) @@ -120,7 +98,6 @@ func TestConfigureACL(t *testing.T) { // Test modification of non existing acl func TestModifyNonExistingACL(t *testing.T) { - // Setup ctx, connection, plugin := aclTestSetup(t, true) defer aclTestTeardown(connection, plugin) @@ -155,7 +132,6 @@ func TestModifyNonExistingACL(t *testing.T) { // Test modification of given acl func TestModifyACL(t *testing.T) { - // Setup ctx, connection, plugin := aclTestSetup(t, true) defer aclTestTeardown(connection, plugin) @@ -239,7 +215,6 @@ func TestModifyACL(t *testing.T) { // Test deletion of non existing acl func TestDeleteNonExistingACL(t *testing.T) { - // Setup ctx, connection, plugin := aclTestSetup(t, false) defer aclTestTeardown(connection, plugin) @@ -256,8 +231,6 @@ func TestDeleteNonExistingACL(t *testing.T) { // Test deletion of given acl func TestDeleteACL(t *testing.T) { - // Setup - ctx, connection, plugin := aclTestSetup(t, true) defer aclTestTeardown(connection, plugin) @@ -292,7 +265,6 @@ func TestDeleteACL(t *testing.T) { // Test listiong of IP ACLs func TestDumpIPACL(t *testing.T) { - // Setup ctx, connection, plugin := aclTestSetup(t, true) defer aclTestTeardown(connection, plugin) @@ -330,7 +302,6 @@ func TestDumpIPACL(t *testing.T) { // Test listiong of MACIP ACLs func TestDumpMACIPACL(t *testing.T) { - // Setup ctx, connection, plugin := aclTestSetup(t, true) defer aclTestTeardown(connection, plugin) @@ -369,7 +340,6 @@ func TestDumpMACIPACL(t *testing.T) { // Test configures new interface for every ACL found in cache func TestResolveCreatedInterface(t *testing.T) { - // Setup ctx, connection, plugin := aclTestSetup(t, false) defer aclTestTeardown(connection, plugin) @@ -397,7 +367,6 @@ func TestResolveCreatedInterface(t *testing.T) { // Test configuration of interfaces with deleted ACLs func TestResolveDeletedInterface(t *testing.T) { - // Setup ctx, connection, plugin := aclTestSetup(t, true) defer aclTestTeardown(connection, plugin) @@ -425,6 +394,7 @@ func TestResolveDeletedInterface(t *testing.T) { /* ACL Test Setup */ func aclTestSetup(t *testing.T, createIfs bool) (*vppcallmock.TestCtx, *core.Connection, *aclplugin.ACLConfigurator) { RegisterTestingT(t) + ctx := &vppcallmock.TestCtx{ MockVpp: &mock.VppAdapter{}, } @@ -432,8 +402,9 @@ func aclTestSetup(t *testing.T, createIfs bool) (*vppcallmock.TestCtx, *core.Con Expect(err).ShouldNot(HaveOccurred()) // Logger - log := logging.ForPlugin("test-log", logrus.NewLogRegistry()) + log := logging.ForPlugin("test-log") log.SetLevel(logging.DebugLevel) + // Interface indices ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(log, "acl-plugin", nil)) if createIfs { @@ -444,7 +415,6 @@ func aclTestSetup(t *testing.T, createIfs bool) (*vppcallmock.TestCtx, *core.Con } // Configurator - ctx.MockVpp.MockReply(&acl_api.ACLPluginGetVersionReply{1, 0}) plugin := &aclplugin.ACLConfigurator{} err = plugin.Init(log, connection, ifIndexes, false) Expect(err).To(BeNil()) @@ -455,6 +425,6 @@ func aclTestSetup(t *testing.T, createIfs bool) (*vppcallmock.TestCtx, *core.Con /* ACL Test Teardown */ func aclTestTeardown(connection *core.Connection, plugin *aclplugin.ACLConfigurator) { connection.Disconnect() - err := plugin.Close() - Expect(err).To(BeNil()) + Expect(plugin.Close()).To(BeNil()) + logging.DefaultRegistry.ClearRegistry() } diff --git a/plugins/vpp/aclplugin/aclidx/aclidx.go b/plugins/vpp/aclplugin/aclidx/aclidx.go index 3e046403bd..b2b6c2f09c 100644 --- a/plugins/vpp/aclplugin/aclidx/aclidx.go +++ b/plugins/vpp/aclplugin/aclidx/aclidx.go @@ -15,15 +15,14 @@ package aclidx import ( - "github.com/ligato/cn-infra/core" "github.com/ligato/vpp-agent/idxvpp" "github.com/ligato/vpp-agent/idxvpp/nametoidx" acl_model "github.com/ligato/vpp-agent/plugins/vpp/model/acl" ) -// AclIndex provides read-only access to mapping between ACL indices (used internally in VPP) +// ACLIndex provides read-only access to mapping between ACL indices (used internally in VPP) // and ACL names. -type AclIndex interface { +type ACLIndex interface { // GetMapping returns internal read-only mapping with metadata. GetMapping() idxvpp.NameToIdxRW @@ -34,12 +33,12 @@ type AclIndex interface { LookupName(idx uint32) (name string, metadata *acl_model.AccessLists_Acl, exists bool) // WatchNameToIdx allows to subscribe for watching changes in aclIndex mapping. - WatchNameToIdx(subscriber core.PluginName, pluginChannel chan AclIdxDto) + WatchNameToIdx(subscriber string, pluginChannel chan IdxDto) } -// AclIndexRW is mapping between ACL indices (used internally in VPP) and ACL names. -type AclIndexRW interface { - AclIndex +// ACLIndexRW is mapping between ACL indices (used internally in VPP) and ACL names. +type ACLIndexRW interface { + ACLIndex // RegisterName adds a new item into name-to-index mapping. RegisterName(name string, idx uint32, ifMeta *acl_model.AccessLists_Acl) @@ -57,15 +56,15 @@ type aclIndex struct { mapping idxvpp.NameToIdxRW } -// AclIdxDto represents an item sent through watch channel in aclIndex. +// IdxDto represents an item sent through watch channel in aclIndex. // In contrast to NameToIdxDto, it contains typed metadata. -type AclIdxDto struct { +type IdxDto struct { idxvpp.NameToIdxDtoWithoutMeta Metadata *acl_model.AccessLists_Acl } -// NewAclIndex creates new instance of aclIndex. -func NewAclIndex(mapping idxvpp.NameToIdxRW) AclIndexRW { +// NewACLIndex creates new instance of aclIndex. +func NewACLIndex(mapping idxvpp.NameToIdxRW) ACLIndexRW { return &aclIndex{mapping: mapping} } @@ -112,21 +111,19 @@ func (acl *aclIndex) castMetadata(meta interface{}) *acl_model.AccessLists_Acl { if ifMeta, ok := meta.(*acl_model.AccessLists_Acl); ok { return ifMeta } - return nil } // WatchNameToIdx allows to subscribe for watching changes in swIfIndex mapping. -func (acl *aclIndex) WatchNameToIdx(subscriber core.PluginName, pluginChannel chan AclIdxDto) { +func (acl *aclIndex) WatchNameToIdx(subscriber string, pluginChannel chan IdxDto) { ch := make(chan idxvpp.NameToIdxDto) acl.mapping.Watch(subscriber, nametoidx.ToChan(ch)) go func() { for c := range ch { - pluginChannel <- AclIdxDto{ + pluginChannel <- IdxDto{ NameToIdxDtoWithoutMeta: c.NameToIdxDtoWithoutMeta, Metadata: acl.castMetadata(c.Metadata), } - } }() } diff --git a/plugins/vpp/aclplugin/aclidx/aclidx_test.go b/plugins/vpp/aclplugin/aclidx/aclidx_test.go index 19c7e298d9..4f043bb222 100644 --- a/plugins/vpp/aclplugin/aclidx/aclidx_test.go +++ b/plugins/vpp/aclplugin/aclidx/aclidx_test.go @@ -15,21 +15,22 @@ package aclidx_test import ( + "testing" + "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/idxvpp" "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/vpp/aclplugin/aclidx" "github.com/ligato/vpp-agent/plugins/vpp/model/acl" . "github.com/onsi/gomega" - "testing" ) -func aclIndexTestInitialization(t *testing.T) (idxvpp.NameToIdxRW, aclidx.AclIndexRW) { +func aclIndexTestInitialization(t *testing.T) (idxvpp.NameToIdxRW, aclidx.ACLIndexRW) { RegisterTestingT(t) // initialize index nameToIdx := nametoidx.NewNameToIdx(logrus.DefaultLogger(), "index_test", nil) - index := aclidx.NewAclIndex(nameToIdx) + index := aclidx.NewACLIndex(nameToIdx) names := nameToIdx.ListNames() // check if names were empty @@ -108,12 +109,12 @@ func TestWatchNameToIdx(t *testing.T) { _, aclIndex := aclIndexTestInitialization(t) - c := make(chan aclidx.AclIdxDto) + c := make(chan aclidx.IdxDto) aclIndex.WatchNameToIdx("testName", c) aclIndex.RegisterName("aclX", 0, &acldata) - var dto aclidx.AclIdxDto + var dto aclidx.IdxDto Eventually(c).Should(Receive(&dto)) Expect(dto.Name).To(Equal("aclX")) Expect(dto.NameToIdxDtoWithoutMeta.Idx).To(Equal(uint32(0))) diff --git a/plugins/vpp/aclplugin/data_resync.go b/plugins/vpp/aclplugin/data_resync.go index 717c3e1f59..8cd23f4e01 100644 --- a/plugins/vpp/aclplugin/data_resync.go +++ b/plugins/vpp/aclplugin/data_resync.go @@ -15,8 +15,6 @@ package aclplugin import ( - "github.com/ligato/vpp-agent/plugins/vpp/aclplugin/vppcalls" - "github.com/ligato/vpp-agent/plugins/vpp/aclplugin/vppdump" "github.com/ligato/vpp-agent/plugins/vpp/model/acl" ) @@ -34,12 +32,12 @@ func (plugin *ACLConfigurator) Resync(nbACLs []*acl.AccessLists_Acl) error { plugin.clearMapping() // Retrieve existing IpACL config - vppIpACLs, err := vppdump.DumpIPACL(plugin.ifIndexes, plugin.log, plugin.vppChan, plugin.stopwatch) + vppIPACLs, err := plugin.aclHandler.DumpIPACL(plugin.ifIndexes) if err != nil { return err } // Retrieve existing MacIpACL config - vppMacIpACLs, err := vppdump.DumpMACIPACL(plugin.ifIndexes, plugin.log, plugin.vppChan, plugin.stopwatch) + vppMacIPACLs, err := plugin.aclHandler.DumpMACIPACL(plugin.ifIndexes) if err != nil { return err } @@ -47,32 +45,32 @@ func (plugin *ACLConfigurator) Resync(nbACLs []*acl.AccessLists_Acl) error { // Remove all configured VPP ACLs // Note: due to inability to dump ACL interfaces, it is not currently possible to correctly // calculate difference between configs - for _, vppIpACL := range vppIpACLs { + for _, vppIPACL := range vppIPACLs { // ACL with IP-type rules uses different binary call to create/remove than MACIP-type. // Check what type of rules is in the ACL - ipRulesExist := len(vppIpACL.ACLDetails.Rules) > 0 && vppIpACL.ACLDetails.Rules[0].GetMatch().GetIpRule() != nil + ipRulesExist := len(vppIPACL.ACL.Rules) > 0 && vppIPACL.ACL.Rules[0].GetMatch().GetIpRule() != nil if ipRulesExist { - if err := vppcalls.DeleteIPAcl(vppIpACL.Identifier.ACLIndex, plugin.log, plugin.vppChan, plugin.stopwatch); err != nil { + if err := plugin.aclHandler.DeleteIPACL(vppIPACL.Meta.Index); err != nil { plugin.log.Error(err) return err } // Unregister. - plugin.l3l4AclIndexes.UnregisterName(vppIpACL.ACLDetails.AclName) + plugin.l3l4AclIndexes.UnregisterName(vppIPACL.ACL.AclName) continue } } - for _, vppMacIpACL := range vppMacIpACLs { - ipRulesExist := len(vppMacIpACL.ACLDetails.Rules) > 0 && vppMacIpACL.ACLDetails.Rules[0].GetMatch().GetMacipRule() != nil + for _, vppMacIPACL := range vppMacIPACLs { + ipRulesExist := len(vppMacIPACL.ACL.Rules) > 0 && vppMacIPACL.ACL.Rules[0].GetMatch().GetMacipRule() != nil if ipRulesExist { - if err := vppcalls.DeleteMacIPAcl(vppMacIpACL.Identifier.ACLIndex, plugin.log, plugin.vppChan, plugin.stopwatch); err != nil { + if err := plugin.aclHandler.DeleteMacIPACL(vppMacIPACL.Meta.Index); err != nil { plugin.log.Error(err) return err } // Unregister. - plugin.l2AclIndexes.UnregisterName(vppMacIpACL.ACLDetails.AclName) + plugin.l2AclIndexes.UnregisterName(vppMacIPACL.ACL.AclName) continue } } diff --git a/plugins/vpp/aclplugin/data_resync_test.go b/plugins/vpp/aclplugin/data_resync_test.go index 19074b38d5..dfcd27398e 100644 --- a/plugins/vpp/aclplugin/data_resync_test.go +++ b/plugins/vpp/aclplugin/data_resync_test.go @@ -17,58 +17,12 @@ package aclplugin_test import ( "testing" - "git.fd.io/govpp.git/adapter/mock" - govppapi "git.fd.io/govpp.git/api" acl_api "github.com/ligato/vpp-agent/plugins/vpp/binapi/acl" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/vpe" "github.com/ligato/vpp-agent/plugins/vpp/model/acl" + "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" ) -type vppReplyMock struct { - Id uint16 - Ping bool - Message govppapi.Message -} - -func vppMockHandler(vppMock *mock.VppAdapter, dataList []*vppReplyMock) mock.ReplyHandler { - var sendControlPing bool - - return func(request mock.MessageDTO) (reply []byte, msgID uint16, prepared bool) { - if sendControlPing { - sendControlPing = false - data := &vpe.ControlPingReply{} - reply, err := vppMock.ReplyBytes(request, data) - Expect(err).To(BeNil()) - msgID, err := vppMock.GetMsgID(data.GetMessageName(), data.GetCrcString()) - Expect(err).To(BeNil()) - return reply, msgID, true - } - - for _, dataMock := range dataList { - if request.MsgID == dataMock.Id { - // Send control ping next iteration if set - sendControlPing = dataMock.Ping - msgID, err := vppMock.GetMsgID(dataMock.Message.GetMessageName(), dataMock.Message.GetCrcString()) - Expect(err).To(BeNil()) - reply, err := vppMock.ReplyBytes(request, dataMock.Message) - Expect(err).To(BeNil()) - return reply, msgID, true - } - } - - replyMsg, msgID, ok := vppMock.ReplyFor(request.MsgName) - - if ok { - reply, err := vppMock.ReplyBytes(request, replyMsg) - Expect(err).To(BeNil()) - return reply, msgID, true - } - - return reply, 0, false - } -} - var acls = []*acl.AccessLists_Acl{ {AclName: "acl1", Rules: []*acl.AccessLists_Acl_Rule{ @@ -116,39 +70,38 @@ func TestResyncEmpty(t *testing.T) { ctx, connection, plugin := aclTestSetup(t, false) defer aclTestTeardown(connection, plugin) - ctx.MockVpp.RegisterBinAPITypes(acl_api.Types) - ctx.MockVpp.MockReplyHandler(vppMockHandler(ctx.MockVpp, []*vppReplyMock{ + ctx.MockReplies([]*vppcallmock.HandleReplies{ { - Id: 1011, + Name: (&acl_api.ACLDump{}).GetMessageName(), Ping: true, Message: &acl_api.ACLDetails{}, }, { - Id: 1015, + Name: (&acl_api.ACLInterfaceListDump{}).GetMessageName(), Ping: true, Message: &acl_api.ACLInterfaceListDetails{}, }, { - Id: 1013, + Name: (&acl_api.MacipACLDump{}).GetMessageName(), Ping: true, Message: &acl_api.MacipACLDetails{}, }, { - Id: 1017, + Name: (&acl_api.MacipACLInterfaceListDump{}).GetMessageName(), Ping: true, Message: &acl_api.MacipACLInterfaceListDetails{}, }, { - Id: 1001, + Name: (&acl_api.ACLAddReplace{}).GetMessageName(), Ping: false, Message: &acl_api.ACLAddReplaceReply{}, }, { - Id: 1005, + Name: (&acl_api.MacipACLAdd{}).GetMessageName(), Ping: false, Message: &acl_api.MacipACLAddReply{}, }, - })) + }) err := plugin.Resync(acls) Expect(err).To(BeNil()) @@ -168,10 +121,9 @@ func TestResyncConfigured(t *testing.T) { ctx, connection, plugin := aclTestSetup(t, false) defer aclTestTeardown(connection, plugin) - ctx.MockVpp.RegisterBinAPITypes(acl_api.Types) - ctx.MockVpp.MockReplyHandler(vppMockHandler(ctx.MockVpp, []*vppReplyMock{ + ctx.MockReplies([]*vppcallmock.HandleReplies{ { - Id: 1011, + Name: (&acl_api.ACLDump{}).GetMessageName(), Ping: true, Message: &acl_api.ACLDetails{ ACLIndex: 0, @@ -181,7 +133,7 @@ func TestResyncConfigured(t *testing.T) { }, }, { - Id: 1015, + Name: (&acl_api.ACLInterfaceListDump{}).GetMessageName(), Ping: true, Message: &acl_api.ACLInterfaceListDetails{ SwIfIndex: 1, @@ -191,7 +143,7 @@ func TestResyncConfigured(t *testing.T) { }, }, { - Id: 1013, + Name: (&acl_api.MacipACLDump{}).GetMessageName(), Ping: true, Message: &acl_api.MacipACLDetails{ ACLIndex: 0, @@ -201,7 +153,7 @@ func TestResyncConfigured(t *testing.T) { }, }, { - Id: 1017, + Name: (&acl_api.MacipACLInterfaceListDump{}).GetMessageName(), Ping: true, Message: &acl_api.MacipACLInterfaceListDetails{ SwIfIndex: 1, @@ -210,26 +162,26 @@ func TestResyncConfigured(t *testing.T) { }, }, { - Id: 1003, + Name: (&acl_api.ACLDel{}).GetMessageName(), Ping: false, Message: &acl_api.ACLDelReply{}, }, { - Id: 1009, + Name: (&acl_api.MacipACLDel{}).GetMessageName(), Ping: false, Message: &acl_api.MacipACLDelReply{}, }, { - Id: 1001, + Name: (&acl_api.ACLAddReplace{}).GetMessageName(), Ping: false, Message: &acl_api.ACLAddReplaceReply{}, }, { - Id: 1005, + Name: (&acl_api.MacipACLAdd{}).GetMessageName(), Ping: false, Message: &acl_api.MacipACLAddReply{}, }, - })) + }) plugin.GetL3L4AclIfIndexes().RegisterName("acl3", 1, nil) plugin.GetL2AclIfIndexes().RegisterName("acl4", 1, nil) @@ -265,10 +217,9 @@ func TestResyncErr1(t *testing.T) { ctx, connection, plugin := aclTestSetup(t, false) defer aclTestTeardown(connection, plugin) - ctx.MockVpp.RegisterBinAPITypes(acl_api.Types) - ctx.MockVpp.MockReplyHandler(vppMockHandler(ctx.MockVpp, []*vppReplyMock{ + ctx.MockReplies([]*vppcallmock.HandleReplies{ { - Id: 1011, + Name: (&acl_api.ACLDump{}).GetMessageName(), Ping: true, Message: &acl_api.ACLDetails{ ACLIndex: 0, @@ -278,7 +229,7 @@ func TestResyncErr1(t *testing.T) { }, }, { - Id: 1015, + Name: (&acl_api.ACLInterfaceListDump{}).GetMessageName(), Ping: true, Message: &acl_api.ACLInterfaceListDetails{ SwIfIndex: 1, @@ -288,7 +239,7 @@ func TestResyncErr1(t *testing.T) { }, }, { - Id: 1013, + Name: (&acl_api.MacipACLDump{}).GetMessageName(), Ping: true, Message: &acl_api.MacipACLDetails{ ACLIndex: 0, @@ -298,7 +249,7 @@ func TestResyncErr1(t *testing.T) { }, }, { - Id: 1017, + Name: (&acl_api.MacipACLInterfaceListDump{}).GetMessageName(), Ping: true, Message: &acl_api.MacipACLInterfaceListDetails{ SwIfIndex: 1, @@ -308,11 +259,11 @@ func TestResyncErr1(t *testing.T) { }, // wrong msg { - Id: 1003, + Name: (&acl_api.ACLDel{}).GetMessageName(), Ping: false, Message: &acl_api.MacipACLDelReply{}, }, - })) + }) plugin.GetL3L4AclIfIndexes().RegisterName("acl3", 1, nil) plugin.GetL2AclIfIndexes().RegisterName("acl4", 1, nil) @@ -336,10 +287,9 @@ func TestResyncErr2(t *testing.T) { ctx, connection, plugin := aclTestSetup(t, false) defer aclTestTeardown(connection, plugin) - ctx.MockVpp.RegisterBinAPITypes(acl_api.Types) - ctx.MockVpp.MockReplyHandler(vppMockHandler(ctx.MockVpp, []*vppReplyMock{ + ctx.MockReplies([]*vppcallmock.HandleReplies{ { - Id: 1011, + Name: (&acl_api.ACLDump{}).GetMessageName(), Ping: true, Message: &acl_api.ACLDetails{ ACLIndex: 0, @@ -349,7 +299,7 @@ func TestResyncErr2(t *testing.T) { }, }, { - Id: 1015, + Name: (&acl_api.ACLInterfaceListDump{}).GetMessageName(), Ping: true, Message: &acl_api.ACLInterfaceListDetails{ SwIfIndex: 1, @@ -359,7 +309,7 @@ func TestResyncErr2(t *testing.T) { }, }, { - Id: 1013, + Name: (&acl_api.MacipACLDump{}).GetMessageName(), Ping: true, Message: &acl_api.MacipACLDetails{ ACLIndex: 0, @@ -369,7 +319,7 @@ func TestResyncErr2(t *testing.T) { }, }, { - Id: 1017, + Name: (&acl_api.MacipACLInterfaceListDump{}).GetMessageName(), Ping: true, Message: &acl_api.MacipACLInterfaceListDetails{ SwIfIndex: 1, @@ -378,17 +328,17 @@ func TestResyncErr2(t *testing.T) { }, }, { - Id: 1003, + Name: (&acl_api.ACLDel{}).GetMessageName(), Ping: false, Message: &acl_api.ACLDelReply{}, }, // wrong msg { - Id: 1009, + Name: (&acl_api.MacipACLDel{}).GetMessageName(), Ping: false, Message: &acl_api.ACLDelReply{}, }, - })) + }) plugin.GetL3L4AclIfIndexes().RegisterName("acl3", 1, nil) plugin.GetL2AclIfIndexes().RegisterName("acl4", 1, nil) @@ -413,10 +363,9 @@ func TestResyncErr3(t *testing.T) { ctx, connection, plugin := aclTestSetup(t, false) defer aclTestTeardown(connection, plugin) - ctx.MockVpp.RegisterBinAPITypes(acl_api.Types) - ctx.MockVpp.MockReplyHandler(vppMockHandler(ctx.MockVpp, []*vppReplyMock{ + ctx.MockReplies([]*vppcallmock.HandleReplies{ { - Id: 1011, + Name: (&acl_api.ACLDump{}).GetMessageName(), Ping: true, Message: &acl_api.ACLDetails{ ACLIndex: 0, @@ -426,7 +375,7 @@ func TestResyncErr3(t *testing.T) { }, }, { - Id: 1015, + Name: (&acl_api.ACLInterfaceListDump{}).GetMessageName(), Ping: true, Message: &acl_api.ACLInterfaceListDetails{ SwIfIndex: 1, @@ -436,7 +385,7 @@ func TestResyncErr3(t *testing.T) { }, }, { - Id: 1013, + Name: (&acl_api.MacipACLDump{}).GetMessageName(), Ping: true, Message: &acl_api.MacipACLDetails{ ACLIndex: 0, @@ -446,7 +395,7 @@ func TestResyncErr3(t *testing.T) { }, }, { - Id: 1017, + Name: (&acl_api.MacipACLInterfaceListDump{}).GetMessageName(), Ping: true, Message: &acl_api.MacipACLInterfaceListDetails{ SwIfIndex: 1, @@ -455,22 +404,22 @@ func TestResyncErr3(t *testing.T) { }, }, { - Id: 1003, + Name: (&acl_api.ACLDel{}).GetMessageName(), Ping: false, Message: &acl_api.ACLDelReply{}, }, { - Id: 1009, + Name: (&acl_api.MacipACLDel{}).GetMessageName(), Ping: false, Message: &acl_api.MacipACLDelReply{}, }, // wrong msg { - Id: 1001, + Name: (&acl_api.ACLAddReplace{}).GetMessageName(), Ping: false, Message: &acl_api.MacipACLAddReplaceReply{}, }, - })) + }) err := plugin.Resync(acls) Expect(err).To(Not(BeNil())) diff --git a/plugins/vpp/aclplugin/vppcalls/acl_vppcalls.go b/plugins/vpp/aclplugin/vppcalls/acl_vppcalls.go index e34a13f154..e3cdf6b5d4 100644 --- a/plugins/vpp/aclplugin/vppcalls/acl_vppcalls.go +++ b/plugins/vpp/aclplugin/vppcalls/acl_vppcalls.go @@ -17,65 +17,32 @@ package vppcalls import ( "fmt" "net" - "strconv" "strings" "time" govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/measure" - "github.com/ligato/vpp-agent/plugins/vpp/aclplugin/vppdump" - acl_api "github.com/ligato/vpp-agent/plugins/vpp/binapi/acl" + aclapi "github.com/ligato/vpp-agent/plugins/vpp/binapi/acl" "github.com/ligato/vpp-agent/plugins/vpp/model/acl" ) -// AclMessages is list of used VPP messages for compatibility check -var AclMessages = []govppapi.Message{ - &acl_api.ACLAddReplace{}, - &acl_api.ACLAddReplaceReply{}, - &acl_api.ACLDel{}, - &acl_api.ACLDelReply{}, - &acl_api.MacipACLAdd{}, - &acl_api.MacipACLAddReply{}, - &acl_api.MacipACLAddReplace{}, - &acl_api.MacipACLAddReplaceReply{}, - &acl_api.MacipACLDel{}, - &acl_api.MacipACLDelReply{}, - &acl_api.ACLDump{}, - &acl_api.ACLDetails{}, - &acl_api.MacipACLDump{}, - &acl_api.MacipACLDetails{}, - &acl_api.ACLInterfaceListDump{}, - &acl_api.ACLInterfaceListDetails{}, - &acl_api.MacipACLInterfaceListDump{}, - &acl_api.MacipACLInterfaceListDetails{}, - &acl_api.ACLInterfaceSetACLList{}, - &acl_api.ACLInterfaceSetACLListReply{}, - &acl_api.MacipACLInterfaceAddDel{}, - &acl_api.MacipACLInterfaceAddDelReply{}, -} +// GetACLPluginVersion retrieves ACL plugin version. +func GetACLPluginVersion(ch govppapi.Channel) (string, error) { + req := &aclapi.ACLPluginGetVersion{} + reply := &aclapi.ACLPluginGetVersionReply{} -// GetAclPluginVersion returns version of the VPP ACL plugin -func GetAclPluginVersion(vppChannel govppapi.Channel, stopwatch *measure.Stopwatch) (string, error) { - defer func(t time.Time) { - stopwatch.TimeLog(acl_api.ACLPluginGetVersion{}).LogTimeEntry(time.Since(t)) - }(time.Now()) - - req := &acl_api.ACLPluginGetVersion{} - reply := &acl_api.ACLPluginGetVersionReply{} - // Does not return retval - if err := vppChannel.SendRequest(req).ReceiveReply(reply); err != nil { + if err := ch.SendRequest(req).ReceiveReply(reply); err != nil { return "", fmt.Errorf("failed to get VPP ACL plugin version: %v", err) } - return strconv.Itoa(int(reply.Major)) + "." + strconv.Itoa(int(reply.Minor)), nil + version := fmt.Sprintf("%d.%d", reply.Major, reply.Minor) + + return version, nil } -// AddIPAcl create new L3/4 ACL. Input index == 0xffffffff, VPP provides index in reply. -func AddIPAcl(rules []*acl.AccessLists_Acl_Rule, aclName string, log logging.Logger, - vppChannel govppapi.Channel, stopwatch *measure.Stopwatch) (uint32, error) { +// AddIPACL implements ACL handler. +func (handler *ACLVppHandler) AddIPACL(rules []*acl.AccessLists_Acl_Rule, aclName string) (uint32, error) { defer func(t time.Time) { - stopwatch.TimeLog(acl_api.ACLAddReplace{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(aclapi.ACLAddReplace{}).LogTimeEntry(time.Since(t)) }(time.Now()) // Prepare Ip rules @@ -87,68 +54,58 @@ func AddIPAcl(rules []*acl.AccessLists_Acl_Rule, aclName string, log logging.Log return 0, fmt.Errorf("no rules found for ACL %v", aclName) } - req := &acl_api.ACLAddReplace{ + req := &aclapi.ACLAddReplace{ ACLIndex: 0xffffffff, // to make new Entry Count: uint32(len(aclIPRules)), Tag: []byte(aclName), R: aclIPRules, } + reply := &aclapi.ACLAddReplaceReply{} - reply := &acl_api.ACLAddReplaceReply{} - if err = vppChannel.SendRequest(req).ReceiveReply(reply); err != nil { + if err = handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return 0, fmt.Errorf("failed to write ACL %v: %v", aclName, err) - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return 0, fmt.Errorf("%s returned %v while writing ACL %v to VPP", reply.GetMessageName(), reply.Retval, aclName) } - log.Infof("%v Ip ACL rule(s) written for ACL %v with index %v", len(aclIPRules), aclName, reply.ACLIndex) - return reply.ACLIndex, nil } -// AddMacIPAcl creates new L2 MAC IP ACL. VPP provides index in reply. -func AddMacIPAcl(rules []*acl.AccessLists_Acl_Rule, aclName string, log logging.Logger, - vppChannel govppapi.Channel, stopwatch *measure.Stopwatch) (uint32, error) { +// AddMacIPACL implements ACL handler. +func (handler *ACLVppHandler) AddMacIPACL(rules []*acl.AccessLists_Acl_Rule, aclName string) (uint32, error) { defer func(t time.Time) { - stopwatch.TimeLog(acl_api.MacipACLAdd{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(aclapi.MacipACLAdd{}).LogTimeEntry(time.Since(t)) }(time.Now()) // Prepare MAc Ip rules - aclMacIPRules, err := transformACLMacIPRules(rules) + aclMacIPRules, err := handler.transformACLMacIPRules(rules) if err != nil { return 0, err } if len(aclMacIPRules) == 0 { - log.Debugf("No Mac Ip ACL rules written for ACL %v", aclName) return 0, fmt.Errorf("no rules found for ACL %v", aclName) } - req := &acl_api.MacipACLAdd{ + req := &aclapi.MacipACLAdd{ Count: uint32(len(aclMacIPRules)), Tag: []byte(aclName), R: aclMacIPRules, } + reply := &aclapi.MacipACLAddReply{} - reply := &acl_api.MacipACLAddReply{} - if err := vppChannel.SendRequest(req).ReceiveReply(reply); err != nil { + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return 0, fmt.Errorf("failed to write ACL %v: %v", aclName, err) - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return 0, fmt.Errorf("%s returned %v while writing ACL %v to VPP", reply.GetMessageName(), reply.Retval, aclName) } - log.Infof("%v Mac Ip ACL rule(s) written for ACL %v with index %v", len(aclMacIPRules), aclName, reply.ACLIndex) - return reply.ACLIndex, nil } -// ModifyIPAcl uses index (provided by VPP) to identify ACL which is modified. -func ModifyIPAcl(aclIndex uint32, rules []*acl.AccessLists_Acl_Rule, aclName string, log logging.Logger, - vppChannel govppapi.Channel, stopwatch *measure.Stopwatch) error { - +// ModifyIPACL implements ACL handler. +func (handler *ACLVppHandler) ModifyIPACL(aclIndex uint32, rules []*acl.AccessLists_Acl_Rule, aclName string) error { defer func(t time.Time) { - stopwatch.TimeLog(acl_api.ACLAddReplace{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(aclapi.ACLAddReplace{}).LogTimeEntry(time.Since(t)) }(time.Now()) // Prepare Ip rules @@ -157,40 +114,34 @@ func ModifyIPAcl(aclIndex uint32, rules []*acl.AccessLists_Acl_Rule, aclName str return err } if len(aclIPRules) == 0 { - log.Debugf("No Ip ACL rules written for ACL %v", aclName) return nil } - req := &acl_api.ACLAddReplace{ + req := &aclapi.ACLAddReplace{ ACLIndex: aclIndex, Count: uint32(len(aclIPRules)), Tag: []byte(aclName), R: aclIPRules, } + reply := &aclapi.ACLAddReplaceReply{} - reply := &acl_api.ACLAddReplaceReply{} - if err := vppChannel.SendRequest(req).ReceiveReply(reply); err != nil { + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return fmt.Errorf("failed to write ACL %v: %v", aclName, err) - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %v while writing ACL %v to VPP", reply.GetMessageName(), reply.Retval, aclName) } - log.Infof("%v Ip ACL rule(s) written for ACL %v with index %v", len(aclIPRules), aclName, aclIndex) - return nil } -// ModifyMACIPAcl uses index (provided by VPP) to identify ACL which is modified. -func ModifyMACIPAcl(aclIndex uint32, rules []*acl.AccessLists_Acl_Rule, aclName string, log logging.Logger, - vppChannel govppapi.Channel, stopwatch *measure.Stopwatch) error { - +// ModifyMACIPACL implements ACL handler. +func (handler *ACLVppHandler) ModifyMACIPACL(aclIndex uint32, rules []*acl.AccessLists_Acl_Rule, aclName string) error { defer func(t time.Time) { - stopwatch.TimeLog(acl_api.ACLAddReplace{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(aclapi.ACLAddReplace{}).LogTimeEntry(time.Since(t)) }(time.Now()) // Prepare MAc Ip rules - aclMacIPRules, err := transformACLMacIPRules(rules) + aclMacIPRules, err := handler.transformACLMacIPRules(rules) if err != nil { return err } @@ -198,76 +149,67 @@ func ModifyMACIPAcl(aclIndex uint32, rules []*acl.AccessLists_Acl_Rule, aclName return fmt.Errorf("no rules found for ACL %v", aclName) } - req := &acl_api.MacipACLAddReplace{ + req := &aclapi.MacipACLAddReplace{ ACLIndex: aclIndex, Count: uint32(len(aclMacIPRules)), Tag: []byte(aclName), R: aclMacIPRules, } + reply := &aclapi.MacipACLAddReplaceReply{} - reply := &acl_api.MacipACLAddReplaceReply{} - if err := vppChannel.SendRequest(req).ReceiveReply(reply); err != nil { + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return fmt.Errorf("failed to write ACL %v: %v", aclName, err) - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %v while writing ACL %v to VPP", reply.GetMessageName(), reply.Retval, aclName) } - log.Infof("%v Ip ACL rule(s) written for ACL %v with index %v", len(aclMacIPRules), aclName, aclIndex) - return nil } -// DeleteIPAcl removes L3/L4 ACL. -func DeleteIPAcl(aclIndex uint32, log logging.Logger, vppChannel govppapi.Channel, stopwatch *measure.Stopwatch) error { +// DeleteIPACL implements ACL handler. +func (handler *ACLVppHandler) DeleteIPACL(aclIndex uint32) error { defer func(t time.Time) { - stopwatch.TimeLog(acl_api.ACLDel{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(aclapi.ACLDel{}).LogTimeEntry(time.Since(t)) }(time.Now()) - msg := &acl_api.ACLDel{ + req := &aclapi.ACLDel{ ACLIndex: aclIndex, } + reply := &aclapi.ACLDelReply{} - reply := &acl_api.ACLDelReply{} - if err := vppChannel.SendRequest(msg).ReceiveReply(reply); err != nil { + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return fmt.Errorf("failed to remove L3/L4 ACL %v: %v", aclIndex, err) - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %v while removing L3/L4 ACL %v", reply.GetMessageName(), reply.Retval, aclIndex) } - log.Infof("L3/L4 ACL %v removed", aclIndex) - return nil } -// DeleteMacIPAcl removes L2 ACL. -func DeleteMacIPAcl(aclIndex uint32, log logging.Logger, vppChannel govppapi.Channel, stopwatch *measure.Stopwatch) error { +// DeleteMacIPACL implements ACL handler. +func (handler *ACLVppHandler) DeleteMacIPACL(aclIndex uint32) error { defer func(t time.Time) { - stopwatch.TimeLog(acl_api.MacipACLDel{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(aclapi.MacipACLDel{}).LogTimeEntry(time.Since(t)) }(time.Now()) - msg := &acl_api.MacipACLDel{ + req := &aclapi.MacipACLDel{ ACLIndex: aclIndex, } + reply := &aclapi.MacipACLDelReply{} - reply := &acl_api.MacipACLDelReply{} - if err := vppChannel.SendRequest(msg).ReceiveReply(reply); err != nil { + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return fmt.Errorf("failed to remove L2 ACL %v: %v", aclIndex, err) - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %v while removing L2 ACL %v", reply.GetMessageName(), reply.Retval, aclIndex) } - log.Infof("L2 ACL %v removed", aclIndex) - return nil } // Method transforms provided set of IP proto ACL rules to binapi ACL rules. -func transformACLIpRules(rules []*acl.AccessLists_Acl_Rule) (aclIPRules []acl_api.ACLRule, err error) { +func transformACLIpRules(rules []*acl.AccessLists_Acl_Rule) (aclIPRules []aclapi.ACLRule, err error) { for _, rule := range rules { - aclRule := &acl_api.ACLRule{ + aclRule := &aclapi.ACLRule{ IsPermit: uint8(rule.AclAction), } // Match @@ -294,9 +236,9 @@ func transformACLIpRules(rules []*acl.AccessLists_Acl_Rule) (aclIPRules []acl_ap return aclIPRules, nil } -func transformACLMacIPRules(rules []*acl.AccessLists_Acl_Rule) (aclMacIPRules []acl_api.MacipACLRule, err error) { +func (handler *ACLVppHandler) transformACLMacIPRules(rules []*acl.AccessLists_Acl_Rule) (aclMacIPRules []aclapi.MacipACLRule, err error) { for _, rule := range rules { - aclMacIPRule := &acl_api.MacipACLRule{ + aclMacIPRule := &aclapi.MacipACLRule{ IsPermit: uint8(rule.AclAction), } // Matche @@ -305,11 +247,11 @@ func transformACLMacIPRules(rules []*acl.AccessLists_Acl_Rule) (aclMacIPRules [] // Source IP Address + Prefix srcIPAddress := net.ParseIP(macIPRule.SourceAddress) if srcIPAddress.To4() != nil { - aclMacIPRule.IsIpv6 = 0 + aclMacIPRule.IsIPv6 = 0 aclMacIPRule.SrcIPAddr = srcIPAddress.To4() aclMacIPRule.SrcIPPrefixLen = uint8(macIPRule.SourceAddressPrefix) } else if srcIPAddress.To16() != nil { - aclMacIPRule.IsIpv6 = 1 + aclMacIPRule.IsIPv6 = 1 aclMacIPRule.SrcIPAddr = srcIPAddress.To16() aclMacIPRule.SrcIPPrefixLen = uint8(macIPRule.SourceAddressPrefix) } else { @@ -334,7 +276,7 @@ func transformACLMacIPRules(rules []*acl.AccessLists_Acl_Rule) (aclMacIPRules [] // The function sets an IP ACL rule fields into provided ACL Rule object. Source // and destination addresses have to be the same IP version and contain a network mask. -func ipACL(ipRule *acl.AccessLists_Acl_Rule_Match_IpRule_Ip, aclRule *acl_api.ACLRule) (*acl_api.ACLRule, error) { +func ipACL(ipRule *acl.AccessLists_Acl_Rule_Match_IpRule_Ip, aclRule *aclapi.ACLRule) (*aclapi.ACLRule, error) { var ( err error srcIP net.IP @@ -380,34 +322,34 @@ func ipACL(ipRule *acl.AccessLists_Acl_Rule_Match_IpRule_Ip, aclRule *acl_api.AC if srcIP.To4() != nil || dstIP.To4() != nil { // Ipv4 case - aclRule.IsIpv6 = 0 + aclRule.IsIPv6 = 0 aclRule.SrcIPAddr = srcIP.To4() aclRule.SrcIPPrefixLen = srcMask aclRule.DstIPAddr = dstIP.To4() aclRule.DstIPPrefixLen = dstMask } else if srcIP.To16() != nil || dstIP.To16() != nil { // Ipv6 case - aclRule.IsIpv6 = 1 + aclRule.IsIPv6 = 1 aclRule.SrcIPAddr = srcIP.To16() aclRule.SrcIPPrefixLen = srcMask aclRule.DstIPAddr = dstIP.To16() aclRule.DstIPPrefixLen = dstMask } else { // Both empty - aclRule.IsIpv6 = 0 + aclRule.IsIPv6 = 0 } return aclRule, nil } // The function sets an ICMP ACL rule fields into provided ACL Rule object. // The ranges are exclusive, use first = 0 and last = 255/65535 (icmpv4/icmpv6) to match "any". -func icmpACL(icmpRule *acl.AccessLists_Acl_Rule_Match_IpRule_Icmp, aclRule *acl_api.ACLRule) *acl_api.ACLRule { +func icmpACL(icmpRule *acl.AccessLists_Acl_Rule_Match_IpRule_Icmp, aclRule *aclapi.ACLRule) *aclapi.ACLRule { if icmpRule == nil { return aclRule } if icmpRule.Icmpv6 { - aclRule.Proto = vppdump.ICMPv6Proto // IANA ICMPv6 - aclRule.IsIpv6 = 1 + aclRule.Proto = ICMPv6Proto // IANA ICMPv6 + aclRule.IsIPv6 = 1 // ICMPv6 type range aclRule.SrcportOrIcmptypeFirst = uint16(icmpRule.IcmpTypeRange.First) aclRule.SrcportOrIcmptypeLast = uint16(icmpRule.IcmpTypeRange.Last) @@ -415,8 +357,8 @@ func icmpACL(icmpRule *acl.AccessLists_Acl_Rule_Match_IpRule_Icmp, aclRule *acl_ aclRule.DstportOrIcmpcodeFirst = uint16(icmpRule.IcmpCodeRange.First) aclRule.DstportOrIcmpcodeLast = uint16(icmpRule.IcmpCodeRange.First) } else { - aclRule.Proto = vppdump.ICMPv4Proto // IANA ICMPv4 - aclRule.IsIpv6 = 0 + aclRule.Proto = ICMPv4Proto // IANA ICMPv4 + aclRule.IsIPv6 = 0 // ICMPv4 type range aclRule.SrcportOrIcmptypeFirst = uint16(icmpRule.IcmpTypeRange.First) aclRule.SrcportOrIcmptypeLast = uint16(icmpRule.IcmpTypeRange.Last) @@ -428,8 +370,8 @@ func icmpACL(icmpRule *acl.AccessLists_Acl_Rule_Match_IpRule_Icmp, aclRule *acl_ } // Sets an TCP ACL rule fields into provided ACL Rule object. -func tcpACL(tcpRule *acl.AccessLists_Acl_Rule_Match_IpRule_Tcp, aclRule *acl_api.ACLRule) *acl_api.ACLRule { - aclRule.Proto = vppdump.TCPProto // IANA TCP +func tcpACL(tcpRule *acl.AccessLists_Acl_Rule_Match_IpRule_Tcp, aclRule *aclapi.ACLRule) *aclapi.ACLRule { + aclRule.Proto = TCPProto // IANA TCP aclRule.SrcportOrIcmptypeFirst = uint16(tcpRule.SourcePortRange.LowerPort) aclRule.SrcportOrIcmptypeLast = uint16(tcpRule.SourcePortRange.UpperPort) aclRule.DstportOrIcmpcodeFirst = uint16(tcpRule.DestinationPortRange.LowerPort) @@ -440,8 +382,8 @@ func tcpACL(tcpRule *acl.AccessLists_Acl_Rule_Match_IpRule_Tcp, aclRule *acl_api } // Sets an UDP ACL rule fields into provided ACL Rule object. -func udpACL(udpRule *acl.AccessLists_Acl_Rule_Match_IpRule_Udp, aclRule *acl_api.ACLRule) *acl_api.ACLRule { - aclRule.Proto = vppdump.UDPProto // IANA UDP +func udpACL(udpRule *acl.AccessLists_Acl_Rule_Match_IpRule_Udp, aclRule *aclapi.ACLRule) *aclapi.ACLRule { + aclRule.Proto = UDPProto // IANA UDP aclRule.SrcportOrIcmptypeFirst = uint16(udpRule.SourcePortRange.LowerPort) aclRule.SrcportOrIcmptypeLast = uint16(udpRule.SourcePortRange.UpperPort) aclRule.DstportOrIcmpcodeFirst = uint16(udpRule.DestinationPortRange.LowerPort) diff --git a/plugins/vpp/aclplugin/vppcalls/acl_vppcalls_test.go b/plugins/vpp/aclplugin/vppcalls/acl_vppcalls_test.go index 3686f9445f..65b12d4f15 100644 --- a/plugins/vpp/aclplugin/vppcalls/acl_vppcalls_test.go +++ b/plugins/vpp/aclplugin/vppcalls/acl_vppcalls_test.go @@ -17,7 +17,6 @@ package vppcalls import ( "testing" - "github.com/ligato/cn-infra/logging/logrus" acl_api "github.com/ligato/vpp-agent/plugins/vpp/binapi/acl" "github.com/ligato/vpp-agent/plugins/vpp/model/acl" "github.com/ligato/vpp-agent/tests/vppcallmock" @@ -110,7 +109,7 @@ var aclErr6Rules = []*acl.AccessLists_Acl_Rule{ }, } -var acl_IPrules = []*acl.AccessLists_Acl_Rule{ +var aclIPrules = []*acl.AccessLists_Acl_Rule{ { RuleName: "permitIPv4", AclAction: acl.AclAction_PERMIT, @@ -225,7 +224,7 @@ var acl_IPrules = []*acl.AccessLists_Acl_Rule{ }, } -var acl_MACIPrules = []*acl.AccessLists_Acl_Rule{ +var aclMACIPrules = []*acl.AccessLists_Acl_Rule{ { RuleName: "denyIPv4", AclAction: acl.AclAction_DENY, @@ -258,28 +257,30 @@ func TestAddIPAcl(t *testing.T) { defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&acl_api.ACLAddReplaceReply{}) - aclIndex, err := AddIPAcl(acl_IPrules, "test0", logrus.DefaultLogger(), ctx.MockChannel, nil) + aclHandler := NewACLVppHandler(ctx.MockChannel, ctx.MockChannel, nil) + + aclIndex, err := aclHandler.AddIPACL(aclIPrules, "test0") Expect(err).To(BeNil()) Expect(aclIndex).To(BeEquivalentTo(0)) - _, err = AddIPAcl(aclNoRules, "test1", logrus.DefaultLogger(), ctx.MockChannel, nil) + _, err = aclHandler.AddIPACL(aclNoRules, "test1") Expect(err).To(Not(BeNil())) - _, err = AddIPAcl(aclErr1Rules, "test2", logrus.DefaultLogger(), ctx.MockChannel, nil) + _, err = aclHandler.AddIPACL(aclErr1Rules, "test2") Expect(err).To(Not(BeNil())) - _, err = AddIPAcl(aclErr2Rules, "test3", logrus.DefaultLogger(), ctx.MockChannel, nil) + _, err = aclHandler.AddIPACL(aclErr2Rules, "test3") Expect(err).To(Not(BeNil())) - _, err = AddIPAcl(aclErr3Rules, "test4", logrus.DefaultLogger(), ctx.MockChannel, nil) + _, err = aclHandler.AddIPACL(aclErr3Rules, "test4") Expect(err).To(Not(BeNil())) ctx.MockVpp.MockReply(&acl_api.MacipACLAddReply{}) - _, err = AddIPAcl(acl_IPrules, "test5", logrus.DefaultLogger(), ctx.MockChannel, nil) + _, err = aclHandler.AddIPACL(aclIPrules, "test5") Expect(err).To(Not(BeNil())) ctx.MockVpp.MockReply(&acl_api.ACLAddReplaceReply{Retval: -1}) - _, err = AddIPAcl(acl_IPrules, "test6", logrus.DefaultLogger(), ctx.MockChannel, nil) + _, err = aclHandler.AddIPACL(aclIPrules, "test6") Expect(err).To(Not(BeNil())) } @@ -289,29 +290,31 @@ func TestAddMacIPAcl(t *testing.T) { defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&acl_api.MacipACLAddReply{}) - aclIndex, err := AddMacIPAcl(acl_MACIPrules, "test6", logrus.DefaultLogger(), ctx.MockChannel, nil) + aclHandler := NewACLVppHandler(ctx.MockChannel, ctx.MockChannel, nil) + + aclIndex, err := aclHandler.AddMacIPACL(aclMACIPrules, "test6") Expect(err).To(BeNil()) Expect(aclIndex).To(BeEquivalentTo(0)) - _, err = AddMacIPAcl(aclNoRules, "test7", logrus.DefaultLogger(), ctx.MockChannel, nil) + _, err = aclHandler.AddMacIPACL(aclNoRules, "test7") Expect(err).To(Not(BeNil())) - _, err = AddMacIPAcl(aclErr4Rules, "test8", logrus.DefaultLogger(), ctx.MockChannel, nil) + _, err = aclHandler.AddMacIPACL(aclErr4Rules, "test8") Expect(err).To(Not(BeNil())) - _, err = AddMacIPAcl(aclErr5Rules, "test9", logrus.DefaultLogger(), ctx.MockChannel, nil) + _, err = aclHandler.AddMacIPACL(aclErr5Rules, "test9") Expect(err).To(Not(BeNil())) - _, err = AddMacIPAcl(aclErr6Rules, "test10", logrus.DefaultLogger(), ctx.MockChannel, nil) + _, err = aclHandler.AddMacIPACL(aclErr6Rules, "test10") Expect(err).To(Not(BeNil())) Expect(err.Error()).To(BeEquivalentTo("invalid IP address ")) ctx.MockVpp.MockReply(&acl_api.ACLAddReplaceReply{}) - _, err = AddMacIPAcl(acl_MACIPrules, "test11", logrus.DefaultLogger(), ctx.MockChannel, nil) + _, err = aclHandler.AddMacIPACL(aclMACIPrules, "test11") Expect(err).To(Not(BeNil())) ctx.MockVpp.MockReply(&acl_api.MacipACLAddReply{Retval: -1}) - _, err = AddMacIPAcl(acl_MACIPrules, "test12", logrus.DefaultLogger(), ctx.MockChannel, nil) + _, err = aclHandler.AddMacIPACL(aclMACIPrules, "test12") Expect(err).To(Not(BeNil())) } @@ -321,7 +324,9 @@ func TestDeleteIPAcl(t *testing.T) { defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&acl_api.ACLAddReplaceReply{}) - aclIndex, err := AddIPAcl(acl_IPrules, "test_del0", logrus.DefaultLogger(), ctx.MockChannel, nil) + aclHandler := NewACLVppHandler(ctx.MockChannel, ctx.MockChannel, nil) + + aclIndex, err := aclHandler.AddIPACL(aclIPrules, "test_del0") Expect(err).To(BeNil()) Expect(aclIndex).To(BeEquivalentTo(0)) @@ -341,20 +346,20 @@ func TestDeleteIPAcl(t *testing.T) { } ctx.MockVpp.MockReply(&acl_api.ACLAddReplaceReply{ACLIndex: 1}) - aclIndex, err = AddIPAcl(rule2del, "test_del1", logrus.DefaultLogger(), ctx.MockChannel, nil) + aclIndex, err = aclHandler.AddIPACL(rule2del, "test_del1") Expect(err).To(BeNil()) Expect(aclIndex).To(BeEquivalentTo(1)) ctx.MockVpp.MockReply(&acl_api.ACLAddReplaceReply{}) - err = DeleteIPAcl(5, logrus.DefaultLogger(), ctx.MockChannel, nil) + err = aclHandler.DeleteIPACL(5) Expect(err).To(Not(BeNil())) ctx.MockVpp.MockReply(&acl_api.ACLDelReply{Retval: -1}) - err = DeleteIPAcl(5, logrus.DefaultLogger(), ctx.MockChannel, nil) + err = aclHandler.DeleteIPACL(5) Expect(err).To(Not(BeNil())) ctx.MockVpp.MockReply(&acl_api.ACLDelReply{}) - err = DeleteIPAcl(1, logrus.DefaultLogger(), ctx.MockChannel, nil) + err = aclHandler.DeleteIPACL(1) Expect(err).To(BeNil()) } @@ -364,7 +369,9 @@ func TestDeleteMACIPAcl(t *testing.T) { defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&acl_api.MacipACLAddReply{}) - aclIndex, err := AddMacIPAcl(acl_MACIPrules, "test_del2", logrus.DefaultLogger(), ctx.MockChannel, nil) + aclHandler := NewACLVppHandler(ctx.MockChannel, ctx.MockChannel, nil) + + aclIndex, err := aclHandler.AddMacIPACL(aclMACIPrules, "test_del2") Expect(err).To(BeNil()) Expect(aclIndex).To(BeEquivalentTo(0)) @@ -384,20 +391,20 @@ func TestDeleteMACIPAcl(t *testing.T) { } ctx.MockVpp.MockReply(&acl_api.MacipACLAddReply{ACLIndex: 1}) - aclIndex, err = AddMacIPAcl(rule2del, "test_del3", logrus.DefaultLogger(), ctx.MockChannel, nil) + aclIndex, err = aclHandler.AddMacIPACL(rule2del, "test_del3") Expect(err).To(BeNil()) Expect(aclIndex).To(BeEquivalentTo(1)) ctx.MockVpp.MockReply(&acl_api.MacipACLAddReply{}) - err = DeleteMacIPAcl(5, logrus.DefaultLogger(), ctx.MockChannel, nil) + err = aclHandler.DeleteMacIPACL(5) Expect(err).To(Not(BeNil())) ctx.MockVpp.MockReply(&acl_api.MacipACLDelReply{Retval: -1}) - err = DeleteMacIPAcl(5, logrus.DefaultLogger(), ctx.MockChannel, nil) + err = aclHandler.DeleteMacIPACL(5) Expect(err).To(Not(BeNil())) ctx.MockVpp.MockReply(&acl_api.MacipACLDelReply{}) - err = DeleteMacIPAcl(1, logrus.DefaultLogger(), ctx.MockChannel, nil) + err = aclHandler.DeleteMacIPACL(1) Expect(err).To(BeNil()) } @@ -407,7 +414,9 @@ func TestModifyIPAcl(t *testing.T) { defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&acl_api.ACLAddReplaceReply{}) - aclIndex, err := AddIPAcl(acl_IPrules, "test_modify", logrus.DefaultLogger(), ctx.MockChannel, nil) + aclHandler := NewACLVppHandler(ctx.MockChannel, ctx.MockChannel, nil) + + aclIndex, err := aclHandler.AddIPACL(aclIPrules, "test_modify") Expect(err).To(BeNil()) Expect(aclIndex).To(BeEquivalentTo(0)) @@ -439,21 +448,21 @@ func TestModifyIPAcl(t *testing.T) { } ctx.MockVpp.MockReply(&acl_api.ACLAddReplaceReply{}) - err = ModifyIPAcl(0, rule2modify, "test_modify0", logrus.DefaultLogger(), ctx.MockChannel, nil) + err = aclHandler.ModifyIPACL(0, rule2modify, "test_modify0") Expect(err).To(BeNil()) - err = ModifyIPAcl(0, aclErr1Rules, "test_modify1", logrus.DefaultLogger(), ctx.MockChannel, nil) + err = aclHandler.ModifyIPACL(0, aclErr1Rules, "test_modify1") Expect(err).To(Not(BeNil())) - err = ModifyIPAcl(0, aclNoRules, "test_modify2", logrus.DefaultLogger(), ctx.MockChannel, nil) + err = aclHandler.ModifyIPACL(0, aclNoRules, "test_modify2") Expect(err).To(BeNil()) ctx.MockVpp.MockReply(&acl_api.MacipACLAddReplaceReply{}) - err = ModifyIPAcl(0, acl_IPrules, "test_modify3", logrus.DefaultLogger(), ctx.MockChannel, nil) + err = aclHandler.ModifyIPACL(0, aclIPrules, "test_modify3") Expect(err).To(Not(BeNil())) ctx.MockVpp.MockReply(&acl_api.ACLAddReplaceReply{Retval: -1}) - err = ModifyIPAcl(0, acl_IPrules, "test_modify4", logrus.DefaultLogger(), ctx.MockChannel, nil) + err = aclHandler.ModifyIPACL(0, aclIPrules, "test_modify4") Expect(err).To(Not(BeNil())) } @@ -463,7 +472,9 @@ func TestModifyMACIPAcl(t *testing.T) { defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&acl_api.MacipACLAddReply{}) - aclIndex, err := AddMacIPAcl(acl_MACIPrules, "test_modify", logrus.DefaultLogger(), ctx.MockChannel, nil) + aclHandler := NewACLVppHandler(ctx.MockChannel, ctx.MockChannel, nil) + + aclIndex, err := aclHandler.AddMacIPACL(aclMACIPrules, "test_modify") Expect(err).To(BeNil()) Expect(aclIndex).To(BeEquivalentTo(0)) @@ -495,17 +506,17 @@ func TestModifyMACIPAcl(t *testing.T) { } ctx.MockVpp.MockReply(&acl_api.MacipACLAddReplaceReply{}) - err = ModifyMACIPAcl(0, rule2modify, "test_modify0", logrus.DefaultLogger(), ctx.MockChannel, nil) + err = aclHandler.ModifyMACIPACL(0, rule2modify, "test_modify0") Expect(err).To(BeNil()) - err = ModifyMACIPAcl(0, aclErr1Rules, "test_modify1", logrus.DefaultLogger(), ctx.MockChannel, nil) + err = aclHandler.ModifyMACIPACL(0, aclErr1Rules, "test_modify1") Expect(err).To(Not(BeNil())) ctx.MockVpp.MockReply(&acl_api.MacipACLAddReplaceReply{}) - err = ModifyMACIPAcl(0, acl_IPrules, "test_modify3", logrus.DefaultLogger(), ctx.MockChannel, nil) + err = aclHandler.ModifyMACIPACL(0, aclIPrules, "test_modify3") Expect(err).To(Not(BeNil())) ctx.MockVpp.MockReply(&acl_api.MacipACLAddReplaceReply{Retval: -1}) - err = ModifyMACIPAcl(0, acl_IPrules, "test_modify4", logrus.DefaultLogger(), ctx.MockChannel, nil) + err = aclHandler.ModifyMACIPACL(0, aclIPrules, "test_modify4") Expect(err).To(Not(BeNil())) } diff --git a/plugins/vpp/aclplugin/vppcalls/api_vppcalls.go b/plugins/vpp/aclplugin/vppcalls/api_vppcalls.go new file mode 100644 index 0000000000..d6c37178b4 --- /dev/null +++ b/plugins/vpp/aclplugin/vppcalls/api_vppcalls.go @@ -0,0 +1,99 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vppcalls + +import ( + govppapi "git.fd.io/govpp.git/api" + "github.com/ligato/cn-infra/logging/measure" + aclapi "github.com/ligato/vpp-agent/plugins/vpp/binapi/acl" + "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" + "github.com/ligato/vpp-agent/plugins/vpp/model/acl" +) + +// ACLVppAPI provides read/write methods required to handle VPP access lists +type ACLVppAPI interface { + ACLVppWrite + ACLVppRead +} + +// ACLVppWrite provides write methods for ACL plugin +type ACLVppWrite interface { + // AddIPACL create new L3/4 ACL. Input index == 0xffffffff, VPP provides index in reply. + AddIPACL(rules []*acl.AccessLists_Acl_Rule, aclName string) (uint32, error) + // AddMacIPACL creates new L2 MAC IP ACL. VPP provides index in reply. + AddMacIPACL(rules []*acl.AccessLists_Acl_Rule, aclName string) (uint32, error) + // ModifyIPACL uses index (provided by VPP) to identify ACL which is modified. + ModifyIPACL(aclIndex uint32, rules []*acl.AccessLists_Acl_Rule, aclName string) error + // ModifyMACIPACL uses index (provided by VPP) to identify ACL which is modified. + ModifyMACIPACL(aclIndex uint32, rules []*acl.AccessLists_Acl_Rule, aclName string) error + // DeleteIPACL removes L3/L4 ACL. + DeleteIPACL(aclIndex uint32) error + // DeleteMacIPACL removes L2 ACL. + DeleteMacIPACL(aclIndex uint32) error + // SetACLToInterfacesAsIngress sets ACL to all provided interfaces as ingress + SetACLToInterfacesAsIngress(ACLIndex uint32, ifIndices []uint32) error + // RemoveIPIngressACLFromInterfaces removes ACL from interfaces + RemoveIPIngressACLFromInterfaces(ACLIndex uint32, ifIndices []uint32) error + // SetACLToInterfacesAsEgress sets ACL to all provided interfaces as egress + SetACLToInterfacesAsEgress(ACLIndex uint32, ifIndices []uint32) error + // RemoveIPEgressACLFromInterfaces removes ACL from interfaces + RemoveIPEgressACLFromInterfaces(ACLIndex uint32, ifIndices []uint32) error + // SetMacIPACLToInterface adds L2 ACL to interface. + SetMacIPACLToInterface(aclIndex uint32, ifIndices []uint32) error + // RemoveMacIPIngressACLFromInterfaces removes L2 ACL from interfaces. + RemoveMacIPIngressACLFromInterfaces(removedACLIndex uint32, ifIndices []uint32) error +} + +// ACLVppRead provides read methods for ACL plugin +type ACLVppRead interface { + // DumpIPACL returns all IP-type ACLs + DumpIPACL(swIfIndices ifaceidx.SwIfIndex) ([]*ACLDetails, error) + // DumpIPACL returns all MACIP-type ACLs + DumpMACIPACL(swIfIndices ifaceidx.SwIfIndex) ([]*ACLDetails, error) + // DumpACLInterfaces returns a map of IP ACL indices with interfaces + DumpIPACLInterfaces(indices []uint32, swIfIndices ifaceidx.SwIfIndex) (map[uint32]*acl.AccessLists_Acl_Interfaces, error) + // DumpMACIPACLInterfaces returns a map of MACIP ACL indices with interfaces + DumpMACIPACLInterfaces(indices []uint32, swIfIndices ifaceidx.SwIfIndex) (map[uint32]*acl.AccessLists_Acl_Interfaces, error) + // DumpIPAcls returns a list of all configured ACLs with IP-type ruleData. + DumpIPAcls() (map[ACLMeta][]aclapi.ACLRule, error) + // DumpMacIPAcls returns a list of all configured ACL with IPMAC-type ruleData. + DumpMacIPAcls() (map[ACLMeta][]aclapi.MacipACLRule, error) + // DumpInterfaceAcls finds interface in VPP and returns its ACL configuration + DumpInterfaceIPAcls(swIndex uint32) (acl.AccessLists, error) + // DumpInterfaceMACIPAcls finds interface in VPP and returns its MACIP ACL configuration + DumpInterfaceMACIPAcls(swIndex uint32) (acl.AccessLists, error) + // DumpInterfaceIPACLs finds interface in VPP and returns its IP ACL configuration. + DumpInterfaceIPACLs(swIndex uint32) (*aclapi.ACLInterfaceListDetails, error) + // DumpInterfaceMACIPACLs finds interface in VPP and returns its MACIP ACL configuration. + DumpInterfaceMACIPACLs(swIndex uint32) (*aclapi.MacipACLInterfaceListDetails, error) + // DumpInterfaces finds all interfaces in VPP and returns their ACL configurations + DumpInterfaces() ([]*aclapi.ACLInterfaceListDetails, []*aclapi.MacipACLInterfaceListDetails, error) +} + +// ACLVppHandler is accessor for acl-related vppcalls methods +type ACLVppHandler struct { + stopwatch *measure.Stopwatch + callsChannel govppapi.Channel + dumpChannel govppapi.Channel +} + +// NewACLVppHandler creates new instance of acl vppcalls handler +func NewACLVppHandler(callsChan, dumpChan govppapi.Channel, stopwatch *measure.Stopwatch) *ACLVppHandler { + return &ACLVppHandler{ + callsChannel: callsChan, + dumpChannel: dumpChan, + stopwatch: stopwatch, + } +} diff --git a/plugins/vpp/aclplugin/vppcalls/doc.go b/plugins/vpp/aclplugin/vppcalls/doc.go index 508aa3c68b..374748917b 100644 --- a/plugins/vpp/aclplugin/vppcalls/doc.go +++ b/plugins/vpp/aclplugin/vppcalls/doc.go @@ -1,2 +1,3 @@ -// Package vppcalls contains wrappers over VPP ACL binary APIs. +// Package vppcalls contains wrappers over VPP ACL binary APIs and helpers to dump ACLs configured in VPP - per +// interface and total. package vppcalls diff --git a/plugins/vpp/aclplugin/vppdump/dump_vppcalls.go b/plugins/vpp/aclplugin/vppcalls/dump_vppcalls.go similarity index 58% rename from plugins/vpp/aclplugin/vppdump/dump_vppcalls.go rename to plugins/vpp/aclplugin/vppcalls/dump_vppcalls.go index 561f98fa99..c94ec1737e 100644 --- a/plugins/vpp/aclplugin/vppdump/dump_vppcalls.go +++ b/plugins/vpp/aclplugin/vppcalls/dump_vppcalls.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package vppdump +package vppcalls import ( "bytes" @@ -20,10 +20,7 @@ import ( "net" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging" "github.com/ligato/cn-infra/logging/logrus" - "github.com/ligato/cn-infra/logging/measure" acl_api "github.com/ligato/vpp-agent/plugins/vpp/binapi/acl" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" "github.com/ligato/vpp-agent/plugins/vpp/model/acl" @@ -37,17 +34,16 @@ const ( ICMPv6Proto = 58 ) -// ACLIdentifier contains fields for ACL index and Tag (used as a name in the configuration) -type ACLIdentifier struct { - ACLIndex uint32 `json:"acl_index"` - Tag string `json:"acl_tag"` +// ACLDetails is combination of proto-modelled ACL data and VPP provided metadata +type ACLDetails struct { + ACL *acl.AccessLists_Acl `json:"acl"` + Meta *ACLMeta `json:"acl_meta"` } -// ACLEntry is cumulative object with ACL identification and details with all ruleData and -// interfaces belonging to the ACL -type ACLEntry struct { - Identifier *ACLIdentifier - ACLDetails *acl.AccessLists_Acl `json:"acl_details"` +// ACLMeta holds VPP-specific metadata +type ACLMeta struct { + Index uint32 `json:"acl_index"` + Tag string `json:"acl_tag"` } // ACLToInterface is definition of interface and all ACLs which are bound to @@ -58,13 +54,12 @@ type ACLToInterface struct { EgressACL []uint32 } -func DumpIPACL(swIfIndices ifaceidx.SwIfIndex, log logging.Logger, vppChannel govppapi.Channel, - stopwatch *measure.Stopwatch) ([]*ACLEntry, error) { - - ruleIPData := make(map[ACLIdentifier][]*acl.AccessLists_Acl_Rule) +// DumpIPACL implements ACL handler. +func (handler *ACLVppHandler) DumpIPACL(swIfIndices ifaceidx.SwIfIndex) ([]*ACLDetails, error) { + ruleIPData := make(map[ACLMeta][]*acl.AccessLists_Acl_Rule) // get all ACLs with IP ruleData - IPRuleACLs, err := DumpIPAcls(log, vppChannel, stopwatch) + IPRuleACLs, err := handler.DumpIPAcls() if len(IPRuleACLs) < 1 || err != nil { return nil, err } @@ -77,11 +72,9 @@ func DumpIPACL(swIfIndices ifaceidx.SwIfIndex, log logging.Logger, vppChannel go if len(IPRules) > 0 { for _, IPRule := range IPRules { - ruleDetails, err := getIPRuleDetails(IPRule) + ruleDetails, err := handler.getIPRuleDetails(IPRule) if err != nil { - log.Error(err) - wasErr = err - break + return nil, fmt.Errorf("failed to get IP Rule %v details: %v", IPRule, err) } rulesDetails = append(rulesDetails, ruleDetails) } @@ -92,28 +85,27 @@ func DumpIPACL(swIfIndices ifaceidx.SwIfIndex, log logging.Logger, vppChannel go // Prepare separate list of all active ACL indices on the VPP var indices []uint32 for identifier := range ruleIPData { - indices = append(indices, identifier.ACLIndex) + indices = append(indices, identifier.Index) } // Get all ACL indices with ingress and egress interfaces - interfaceData, err := DumpIPACLInterfaces(indices, swIfIndices, log, vppChannel, stopwatch) + interfaceData, err := handler.DumpIPACLInterfaces(indices, swIfIndices) if err != nil { return nil, err } - var ACLs []*ACLEntry + var ACLs []*ACLDetails // Build a list of ACL ruleData with ruleData, interfaces, index and tag (name) for identifier, rules := range ruleIPData { - log.Info("acl index : %v", identifier.ACLIndex) - ACLs = append(ACLs, &ACLEntry{ - Identifier: &ACLIdentifier{ - ACLIndex: identifier.ACLIndex, - Tag: identifier.Tag, - }, - ACLDetails: &acl.AccessLists_Acl{ + ACLs = append(ACLs, &ACLDetails{ + ACL: &acl.AccessLists_Acl{ AclName: identifier.Tag, Rules: rules, - Interfaces: interfaceData[identifier.ACLIndex], + Interfaces: interfaceData[identifier.Index], + }, + Meta: &ACLMeta{ + Index: identifier.Index, + Tag: identifier.Tag, }, }) } @@ -121,71 +113,67 @@ func DumpIPACL(swIfIndices ifaceidx.SwIfIndex, log logging.Logger, vppChannel go return ACLs, wasErr } -func DumpMACIPACL(swIfIndices ifaceidx.SwIfIndex, log logging.Logger, vppChannel govppapi.Channel, - stopwatch *measure.Stopwatch) ([]*ACLEntry, error) { - - ruleMACIPData := make(map[ACLIdentifier][]*acl.AccessLists_Acl_Rule) +// DumpMACIPACL implements ACL handler. +func (handler *ACLVppHandler) DumpMACIPACL(swIfIndices ifaceidx.SwIfIndex) ([]*ACLDetails, error) { + ruleMACIPData := make(map[ACLMeta][]*acl.AccessLists_Acl_Rule) // get all ACLs with MACIP ruleData - MACIPRuleACLs, err := DumpMacIPAcls(log, vppChannel, stopwatch) + MACIPRuleACLs, err := handler.DumpMacIPAcls() if len(MACIPRuleACLs) < 1 || err != nil { return nil, err } // resolve MACIP rules for every ACL var wasErr error - for identifier, MACIPRules := range MACIPRuleACLs { + for metadata, MACIPRules := range MACIPRuleACLs { var rulesDetails []*acl.AccessLists_Acl_Rule if len(MACIPRules) > 0 { for _, MACIPRule := range MACIPRules { - ruleDetails, err := getMACIPRuleDetails(MACIPRule) + ruleDetails, err := handler.getMACIPRuleDetails(MACIPRule) if err != nil { - log.Error(err) - wasErr = err - break + return nil, fmt.Errorf("failed to get MACIP Rule %v details: %v", MACIPRule, err) } rulesDetails = append(rulesDetails, ruleDetails) } } - ruleMACIPData[identifier] = rulesDetails + ruleMACIPData[metadata] = rulesDetails } // Prepare separate list of all active ACL indices on the VPP var indices []uint32 for identifier := range ruleMACIPData { - indices = append(indices, identifier.ACLIndex) + indices = append(indices, identifier.Index) } // Get all ACL indices with ingress and egress interfaces - interfaceData, err := DumpMACIPACLInterfaces(indices, swIfIndices, log, vppChannel, stopwatch) + interfaceData, err := handler.DumpMACIPACLInterfaces(indices, swIfIndices) if err != nil { return nil, err } - var ACLs []*ACLEntry + var ACLs []*ACLDetails // Build a list of ACL ruleData with ruleData, interfaces, index and tag (name) - for identifier, rules := range ruleMACIPData { - ACLs = append(ACLs, &ACLEntry{ - Identifier: &ACLIdentifier{ - ACLIndex: identifier.ACLIndex, - Tag: identifier.Tag, - }, - ACLDetails: &acl.AccessLists_Acl{ - AclName: identifier.Tag, + for metadata, rules := range ruleMACIPData { + ACLs = append(ACLs, &ACLDetails{ + ACL: &acl.AccessLists_Acl{ + AclName: metadata.Tag, Rules: rules, - Interfaces: interfaceData[identifier.ACLIndex], + Interfaces: interfaceData[metadata.Index], + }, + Meta: &ACLMeta{ + Index: metadata.Index, + Tag: metadata.Tag, }, }) } return ACLs, wasErr } -// DumpACLInterfaces returns a map of IP ACL indices with interfaces -func DumpIPACLInterfaces(indices []uint32, swIfIndices ifaceidx.SwIfIndex, log logging.Logger, vppChannel govppapi.Channel, - stopwatch *measure.Stopwatch) (map[uint32]*acl.AccessLists_Acl_Interfaces, error) { +// DumpIPACLInterfaces implements ACL handler. +func (handler *ACLVppHandler) DumpIPACLInterfaces(indices []uint32, swIfIndices ifaceidx.SwIfIndex) (map[uint32]*acl.AccessLists_Acl_Interfaces, error) { defer func(start time.Time) { - stopwatch.TimeLog(&acl_api.ACLInterfaceListDump{}).LogTimeEntry(time.Since(start)) + handler.stopwatch.TimeLog(&acl_api.ACLInterfaceListDump{}).LogTimeEntry(time.Since(start)) }(time.Now()) // list of ACL-to-interfaces @@ -200,7 +188,7 @@ func DumpIPACLInterfaces(indices []uint32, swIfIndices ifaceidx.SwIfIndex, log l msgIP := &acl_api.ACLInterfaceListDump{ SwIfIndex: 0xffffffff, // dump all } - reqIP := vppChannel.SendMultiRequest(msgIP) + reqIP := handler.dumpChannel.SendMultiRequest(msgIP) for { replyIP := &acl_api.ACLInterfaceListDetails{} stop, err := reqIP.ReceiveReply(replyIP) @@ -208,9 +196,7 @@ func DumpIPACLInterfaces(indices []uint32, swIfIndices ifaceidx.SwIfIndex, log l break } if err != nil { - log.Error(err) - wasErr = err - break + return aclsWithInterfaces, fmt.Errorf("ACL interface list dump reply error: %v", err) } if replyIP.Count > 0 { @@ -238,7 +224,6 @@ func DumpIPACLInterfaces(indices []uint32, swIfIndices ifaceidx.SwIfIndex, log l if ingressACLIdx == aclIdx { name, _, found := swIfIndices.LookupName(data.SwIfIdx) if !found { - log.Warnf("ACL requires ingress interface with Idx %v which was not found in the mapping", data.SwIfIdx) continue } ingress = append(ingress, name) @@ -249,7 +234,6 @@ func DumpIPACLInterfaces(indices []uint32, swIfIndices ifaceidx.SwIfIndex, log l if egressACLIdx == aclIdx { name, _, found := swIfIndices.LookupName(data.SwIfIdx) if !found { - log.Warnf("ACL requires egress interface with Idx %v which was not found in the mapping", data.SwIfIdx) continue } egress = append(egress, name) @@ -266,12 +250,10 @@ func DumpIPACLInterfaces(indices []uint32, swIfIndices ifaceidx.SwIfIndex, log l return aclsWithInterfaces, wasErr } -// DumpMACIPACLInterfaces returns a map of MACIP ACL indices with interfaces -func DumpMACIPACLInterfaces(indices []uint32, swIfIndices ifaceidx.SwIfIndex, log logging.Logger, vppChannel govppapi.Channel, - stopwatch *measure.Stopwatch) ( - map[uint32]*acl.AccessLists_Acl_Interfaces, error) { +// DumpMACIPACLInterfaces implements ACL handler. +func (handler *ACLVppHandler) DumpMACIPACLInterfaces(indices []uint32, swIfIndices ifaceidx.SwIfIndex) (map[uint32]*acl.AccessLists_Acl_Interfaces, error) { defer func(start time.Time) { - stopwatch.TimeLog(acl_api.ACLInterfaceListDump{}).LogTimeEntry(time.Since(start)) + handler.stopwatch.TimeLog(acl_api.ACLInterfaceListDump{}).LogTimeEntry(time.Since(start)) }(time.Now()) // list of ACL-to-interfaces @@ -286,7 +268,7 @@ func DumpMACIPACLInterfaces(indices []uint32, swIfIndices ifaceidx.SwIfIndex, lo msgMACIP := &acl_api.MacipACLInterfaceListDump{ SwIfIndex: 0xffffffff, // dump all } - reqMACIP := vppChannel.SendMultiRequest(msgMACIP) + reqMACIP := handler.dumpChannel.SendMultiRequest(msgMACIP) for { replyMACIP := &acl_api.MacipACLInterfaceListDetails{} stop, err := reqMACIP.ReceiveReply(replyMACIP) @@ -294,9 +276,7 @@ func DumpMACIPACLInterfaces(indices []uint32, swIfIndices ifaceidx.SwIfIndex, lo break } if err != nil { - log.Error(err) - wasErr = err - break + return aclsWithInterfaces, fmt.Errorf("MACIP ACL interface list dump reply error: %v", err) } if replyMACIP.Count > 0 { data := &ACLToInterface{ @@ -317,7 +297,6 @@ func DumpMACIPACLInterfaces(indices []uint32, swIfIndices ifaceidx.SwIfIndex, lo if ingressACLIdx == aclIdx { name, _, found := swIfIndices.LookupName(data.SwIfIdx) if !found { - log.Warnf("ACL requires ingress interface with Idx %v which was not found in the mapping", data.SwIfIdx) continue } ingress = append(ingress, name) @@ -333,87 +312,218 @@ func DumpMACIPACLInterfaces(indices []uint32, swIfIndices ifaceidx.SwIfIndex, lo return aclsWithInterfaces, wasErr } -// DumpIPAcls returns a list of all configured ACLs with IP-type ruleData. -func DumpIPAcls(log logging.Logger, vch govppapi.Channel, - stopwatch *measure.Stopwatch) (map[ACLIdentifier][]acl_api.ACLRule, error) { +// DumpIPAcls implements ACL handler. +func (handler *ACLVppHandler) DumpIPAcls() (map[ACLMeta][]acl_api.ACLRule, error) { defer func(start time.Time) { - stopwatch.TimeLog(acl_api.ACLDump{}).LogTimeEntry(time.Since(start)) + handler.stopwatch.TimeLog(acl_api.ACLDump{}).LogTimeEntry(time.Since(start)) }(time.Now()) - aclIPRules := make(map[ACLIdentifier][]acl_api.ACLRule) + aclIPRules := make(map[ACLMeta][]acl_api.ACLRule) var wasErr error - req := &acl_api.ACLDump{} - req.ACLIndex = 0xffffffff - reqContext := vch.SendMultiRequest(req) + req := &acl_api.ACLDump{ + ACLIndex: 0xffffffff, + } + reqContext := handler.dumpChannel.SendMultiRequest(req) for { msg := &acl_api.ACLDetails{} stop, err := reqContext.ReceiveReply(msg) if err != nil { - log.Error(err) - wasErr = err - break + return aclIPRules, fmt.Errorf("ACL dump reply error: %v", err) } if stop { break } - identifier := ACLIdentifier{ - ACLIndex: msg.ACLIndex, - Tag: string(bytes.SplitN(msg.Tag, []byte{0x00}, 2)[0]), + metadata := ACLMeta{ + Index: msg.ACLIndex, + Tag: string(bytes.SplitN(msg.Tag, []byte{0x00}, 2)[0]), } - aclIPRules[identifier] = msg.R + aclIPRules[metadata] = msg.R } return aclIPRules, wasErr } -// DumpMacIPAcls returns a list of all configured ACL with IPMAC-type ruleData. -func DumpMacIPAcls(log logging.Logger, vppChannel govppapi.Channel, - stopwatch *measure.Stopwatch) (map[ACLIdentifier][]acl_api.MacipACLRule, error) { +// DumpMacIPAcls implements ACL handler. +func (handler *ACLVppHandler) DumpMacIPAcls() (map[ACLMeta][]acl_api.MacipACLRule, error) { defer func(start time.Time) { - stopwatch.TimeLog(acl_api.MacipACLDump{}).LogTimeEntry(time.Since(start)) + handler.stopwatch.TimeLog(acl_api.MacipACLDump{}).LogTimeEntry(time.Since(start)) }(time.Now()) - aclMACIPRules := make(map[ACLIdentifier][]acl_api.MacipACLRule) + aclMACIPRules := make(map[ACLMeta][]acl_api.MacipACLRule) var wasErr error - req := &acl_api.MacipACLDump{} - req.ACLIndex = 0xffffffff - reqContext := vppChannel.SendMultiRequest(req) + req := &acl_api.MacipACLDump{ + ACLIndex: 0xffffffff, + } + reqContext := handler.dumpChannel.SendMultiRequest(req) for { msg := &acl_api.MacipACLDetails{} stop, err := reqContext.ReceiveReply(msg) if err != nil { - log.Error(err) - wasErr = err - break + return aclMACIPRules, fmt.Errorf("ACL MACIP dump reply error: %v", err) } if stop { break } - identifier := ACLIdentifier{ - ACLIndex: msg.ACLIndex, - Tag: string(bytes.SplitN(msg.Tag, []byte{0x00}, 2)[0]), + metadata := ACLMeta{ + Index: msg.ACLIndex, + Tag: string(bytes.SplitN(msg.Tag, []byte{0x00}, 2)[0]), } - aclMACIPRules[identifier] = msg.R + aclMACIPRules[metadata] = msg.R } return aclMACIPRules, wasErr } -func getIPRuleDetails(rule acl_api.ACLRule) (*acl.AccessLists_Acl_Rule, error) { +// DumpInterfaceIPAcls implements ACL handler. +func (handler *ACLVppHandler) DumpInterfaceIPAcls(swIndex uint32) (acl.AccessLists, error) { + allACLs := acl.AccessLists{ + Acls: []*acl.AccessLists_Acl{}, + } + + res, err := handler.DumpInterfaceIPACLs(swIndex) + if err != nil { + return allACLs, err + } + + if res.SwIfIndex != swIndex { + return allACLs, fmt.Errorf("returned interface index %d does not match request", res.SwIfIndex) + } + + for aidx := range res.Acls { + ipACL, err := handler.getIPACLDetails(uint32(aidx)) + if err != nil { + return allACLs, err + } + allACLs.Acls = append(allACLs.Acls, ipACL) + } + return allACLs, nil +} + +// DumpInterfaceMACIPAcls implements ACL handler. +func (handler *ACLVppHandler) DumpInterfaceMACIPAcls(swIndex uint32) (acl.AccessLists, error) { + allACLs := acl.AccessLists{ + Acls: []*acl.AccessLists_Acl{}, + } + + resMacIP, err := handler.DumpInterfaceMACIPACLs(swIndex) + if err != nil { + return allACLs, err + } + + if resMacIP.SwIfIndex != swIndex { + return allACLs, fmt.Errorf("returned interface index %d does not match request", resMacIP.SwIfIndex) + } + + for aidx := range resMacIP.Acls { + macipACL, err := handler.getMACIPACLDetails(uint32(aidx)) + if err != nil { + return allACLs, err + } + allACLs.Acls = append(allACLs.Acls, macipACL) + } + return allACLs, nil +} + +// DumpInterfaceIPACLs implements ACL handler. +func (handler *ACLVppHandler) DumpInterfaceIPACLs(swIndex uint32) (*acl_api.ACLInterfaceListDetails, error) { + defer func(t time.Time) { + handler.stopwatch.TimeLog(acl_api.ACLInterfaceListDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + req := &acl_api.ACLInterfaceListDump{ + SwIfIndex: swIndex, + } + reply := &acl_api.ACLInterfaceListDetails{} + + if err := handler.dumpChannel.SendRequest(req).ReceiveReply(reply); err != nil { + return nil, err + } + + return reply, nil +} + +// DumpInterfaceMACIPACLs implements ACL handler. +func (handler *ACLVppHandler) DumpInterfaceMACIPACLs(swIndex uint32) (*acl_api.MacipACLInterfaceListDetails, error) { + defer func(t time.Time) { + handler.stopwatch.TimeLog(acl_api.MacipACLInterfaceListDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + req := &acl_api.MacipACLInterfaceListDump{ + SwIfIndex: swIndex, + } + reply := &acl_api.MacipACLInterfaceListDetails{} + + if err := handler.dumpChannel.SendRequest(req).ReceiveReply(reply); err != nil { + return nil, err + } + + return reply, nil +} + +// DumpInterfaces implements ACL handler. +func (handler *ACLVppHandler) DumpInterfaces() ([]*acl_api.ACLInterfaceListDetails, []*acl_api.MacipACLInterfaceListDetails, error) { + defer func(t time.Time) { + handler.stopwatch.TimeLog(acl_api.ACLInterfaceListDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + msgIPACL := &acl_api.ACLInterfaceListDump{ + SwIfIndex: 0xffffffff, // dump all + } + + reqIPACL := handler.dumpChannel.SendMultiRequest(msgIPACL) + + var IPaclInterfaces []*acl_api.ACLInterfaceListDetails + for { + reply := &acl_api.ACLInterfaceListDetails{} + stop, err := reqIPACL.ReceiveReply(reply) + if stop { + break + } + if err != nil { + logrus.DefaultLogger().Error(err) + return nil, nil, err + } + IPaclInterfaces = append(IPaclInterfaces, reply) + } + + msgMACIPACL := &acl_api.ACLInterfaceListDump{ + SwIfIndex: 0xffffffff, // dump all + } + + reqMACIPACL := handler.dumpChannel.SendMultiRequest(msgMACIPACL) + + var MACIPaclInterfaces []*acl_api.MacipACLInterfaceListDetails + for { + reply := &acl_api.MacipACLInterfaceListDetails{} + stop, err := reqMACIPACL.ReceiveReply(reply) + if stop { + break + } + if err != nil { + logrus.DefaultLogger().Error(err) + return nil, nil, err + } + MACIPaclInterfaces = append(MACIPaclInterfaces, reply) + } + + return IPaclInterfaces, MACIPaclInterfaces, nil +} + +func (handler *ACLVppHandler) getIPRuleDetails(rule acl_api.ACLRule) (*acl.AccessLists_Acl_Rule, error) { // Resolve rule actions - aclAction, err := resolveRuleAction(rule.IsPermit) + aclAction, err := handler.resolveRuleAction(rule.IsPermit) if err != nil { return nil, err } // Resolve rule matches match := &acl.AccessLists_Acl_Rule_Match{ - IpRule: getIPRuleMatches(rule), + IpRule: handler.getIPRuleMatches(rule), } return &acl.AccessLists_Acl_Rule{ @@ -424,13 +534,13 @@ func getIPRuleDetails(rule acl_api.ACLRule) (*acl.AccessLists_Acl_Rule, error) { // getIPACLDetails gets details for a given IP ACL from VPP and translates // them from the binary VPP API format into the ACL Plugin's NB format. -func getIPACLDetails(vppChannel govppapi.Channel, idx uint32) (aclRule *acl.AccessLists_Acl, err error) { +func (handler *ACLVppHandler) getIPACLDetails(idx uint32) (aclRule *acl.AccessLists_Acl, err error) { req := &acl_api.ACLDump{ ACLIndex: uint32(idx), } reply := &acl_api.ACLDetails{} - if err := vppChannel.SendRequest(req).ReceiveReply(reply); err != nil { + if err := handler.dumpChannel.SendRequest(req).ReceiveReply(reply); err != nil { return nil, err } @@ -438,13 +548,13 @@ func getIPACLDetails(vppChannel govppapi.Channel, idx uint32) (aclRule *acl.Acce for _, r := range reply.R { rule := &acl.AccessLists_Acl_Rule{} - ipRule, _ := getIPRuleDetails(r) + ipRule, _ := handler.getIPRuleDetails(r) match := &acl.AccessLists_Acl_Rule_Match{ IpRule: ipRule.GetMatch().GetIpRule(), } - aclAction, err := resolveRuleAction(r.IsPermit) + aclAction, err := handler.resolveRuleAction(r.IsPermit) if err != nil { return nil, err } @@ -457,16 +567,16 @@ func getIPACLDetails(vppChannel govppapi.Channel, idx uint32) (aclRule *acl.Acce return &acl.AccessLists_Acl{Rules: ruleData, AclName: string(bytes.SplitN(reply.Tag, []byte{0x00}, 2)[0])}, nil } -func getMACIPRuleDetails(rule acl_api.MacipACLRule) (*acl.AccessLists_Acl_Rule, error) { +func (handler *ACLVppHandler) getMACIPRuleDetails(rule acl_api.MacipACLRule) (*acl.AccessLists_Acl_Rule, error) { // Resolve rule actions - aclAction, err := resolveRuleAction(rule.IsPermit) + aclAction, err := handler.resolveRuleAction(rule.IsPermit) if err != nil { return nil, err } // Resolve rule matches match := &acl.AccessLists_Acl_Rule_Match{ - MacipRule: getMACIPRuleMatches(rule), + MacipRule: handler.getMACIPRuleMatches(rule), } return &acl.AccessLists_Acl_Rule{ @@ -477,13 +587,13 @@ func getMACIPRuleDetails(rule acl_api.MacipACLRule) (*acl.AccessLists_Acl_Rule, // getMACIPACLDetails gets details for a given MACIP ACL from VPP and translates // them from the binary VPP API format into the ACL Plugin's NB format. -func getMACIPACLDetails(vppChannel govppapi.Channel, idx uint32) (aclRule *acl.AccessLists_Acl, err error) { +func (handler *ACLVppHandler) getMACIPACLDetails(idx uint32) (aclRule *acl.AccessLists_Acl, err error) { req := &acl_api.MacipACLDump{ ACLIndex: uint32(idx), } reply := &acl_api.MacipACLDetails{} - if err := vppChannel.SendRequest(req).ReceiveReply(reply); err != nil { + if err := handler.dumpChannel.SendRequest(req).ReceiveReply(reply); err != nil { return nil, err } @@ -491,13 +601,13 @@ func getMACIPACLDetails(vppChannel govppapi.Channel, idx uint32) (aclRule *acl.A for _, r := range reply.R { rule := &acl.AccessLists_Acl_Rule{} - ipRule, _ := getMACIPRuleDetails(r) + ipRule, _ := handler.getMACIPRuleDetails(r) match := &acl.AccessLists_Acl_Rule_Match{ IpRule: ipRule.GetMatch().GetIpRule(), } - aclAction, err := resolveRuleAction(r.IsPermit) + aclAction, err := handler.resolveRuleAction(r.IsPermit) if err != nil { return nil, err } @@ -512,9 +622,9 @@ func getMACIPACLDetails(vppChannel govppapi.Channel, idx uint32) (aclRule *acl.A // getIPRuleMatches translates an IP rule from the binary VPP API format into the // ACL Plugin's NB format -func getIPRuleMatches(r acl_api.ACLRule) *acl.AccessLists_Acl_Rule_Match_IpRule { +func (handler *ACLVppHandler) getIPRuleMatches(r acl_api.ACLRule) *acl.AccessLists_Acl_Rule_Match_IpRule { var srcIP, dstIP string - if r.IsIpv6 == 1 { + if r.IsIPv6 == 1 { srcIP = net.IP(r.SrcIPAddr).To16().String() dstIP = net.IP(r.DstIPAddr).To16().String() } else { @@ -531,20 +641,20 @@ func getIPRuleMatches(r acl_api.ACLRule) *acl.AccessLists_Acl_Rule_Match_IpRule switch r.Proto { case TCPProto: - ipRule.Tcp = getTCPMatchRule(r) + ipRule.Tcp = handler.getTCPMatchRule(r) case UDPProto: - ipRule.Udp = getUDPMatchRule(r) + ipRule.Udp = handler.getUDPMatchRule(r) case ICMPv4Proto, ICMPv6Proto: - ipRule.Icmp = getIcmpMatchRule(r) + ipRule.Icmp = handler.getIcmpMatchRule(r) } return ipRule } // getMACIPRuleMatches translates an MACIP rule from the binary VPP API format into the // ACL Plugin's NB format -func getMACIPRuleMatches(rule acl_api.MacipACLRule) *acl.AccessLists_Acl_Rule_Match_MacIpRule { +func (handler *ACLVppHandler) getMACIPRuleMatches(rule acl_api.MacipACLRule) *acl.AccessLists_Acl_Rule_Match_MacIpRule { var srcAddr string - if rule.IsIpv6 == 1 { + if rule.IsIPv6 == 1 { srcAddr = net.IP(rule.SrcIPAddr).To16().String() } else { srcAddr = net.IP(rule.SrcIPAddr[:4]).To4().String() @@ -559,7 +669,7 @@ func getMACIPRuleMatches(rule acl_api.MacipACLRule) *acl.AccessLists_Acl_Rule_Ma // getTCPMatchRule translates a TCP match rule from the binary VPP API format // into the ACL Plugin's NB format -func getTCPMatchRule(r acl_api.ACLRule) *acl.AccessLists_Acl_Rule_Match_IpRule_Tcp { +func (handler *ACLVppHandler) getTCPMatchRule(r acl_api.ACLRule) *acl.AccessLists_Acl_Rule_Match_IpRule_Tcp { dstPortRange := &acl.AccessLists_Acl_Rule_Match_IpRule_PortRange{ LowerPort: uint32(r.DstportOrIcmpcodeFirst), UpperPort: uint32(r.DstportOrIcmpcodeLast), @@ -579,7 +689,7 @@ func getTCPMatchRule(r acl_api.ACLRule) *acl.AccessLists_Acl_Rule_Match_IpRule_T // getUDPMatchRule translates a UDP match rule from the binary VPP API format // into the ACL Plugin's NB format -func getUDPMatchRule(r acl_api.ACLRule) *acl.AccessLists_Acl_Rule_Match_IpRule_Udp { +func (handler *ACLVppHandler) getUDPMatchRule(r acl_api.ACLRule) *acl.AccessLists_Acl_Rule_Match_IpRule_Udp { dstPortRange := &acl.AccessLists_Acl_Rule_Match_IpRule_PortRange{ LowerPort: uint32(r.DstportOrIcmpcodeFirst), UpperPort: uint32(r.DstportOrIcmpcodeLast), @@ -597,9 +707,9 @@ func getUDPMatchRule(r acl_api.ACLRule) *acl.AccessLists_Acl_Rule_Match_IpRule_U // getIcmpMatchRule translates an ICMP match rule from the binary VPP API // format into the ACL Plugin's NB format -func getIcmpMatchRule(r acl_api.ACLRule) *acl.AccessLists_Acl_Rule_Match_IpRule_Icmp { +func (handler *ACLVppHandler) getIcmpMatchRule(r acl_api.ACLRule) *acl.AccessLists_Acl_Rule_Match_IpRule_Icmp { icmp := &acl.AccessLists_Acl_Rule_Match_IpRule_Icmp{ - Icmpv6: r.IsIpv6 > 0, + Icmpv6: r.IsIPv6 > 0, IcmpCodeRange: &acl.AccessLists_Acl_Rule_Match_IpRule_Icmp_Range{}, IcmpTypeRange: &acl.AccessLists_Acl_Rule_Match_IpRule_Icmp_Range{}, } @@ -607,7 +717,7 @@ func getIcmpMatchRule(r acl_api.ACLRule) *acl.AccessLists_Acl_Rule_Match_IpRule_ } // Returns rule action representation in model according to the vpp input -func resolveRuleAction(isPermit uint8) (acl.AclAction, error) { +func (handler *ACLVppHandler) resolveRuleAction(isPermit uint8) (acl.AclAction, error) { switch isPermit { case 0: return acl.AclAction_DENY, nil @@ -619,143 +729,3 @@ func resolveRuleAction(isPermit uint8) (acl.AclAction, error) { return acl.AclAction_DENY, fmt.Errorf("invalid match rule %d", isPermit) } } - -// DumpInterfaceAcls finds interface in VPP and returns its ACL configuration -//func DumpInterfaceIPAclsDetails(log logging.Logger, swIndex uint32, vppChannel api.Channel, stopwatch *measure.Stopwatch) (acl.AccessLists, error) { -func DumpInterfaceIPAcls(log logging.Logger, swIndex uint32, vppChannel govppapi.Channel, stopwatch *measure.Stopwatch) (acl.AccessLists, error) { - alAcls := acl.AccessLists{ - Acls: []*acl.AccessLists_Acl{}, - } - - res, err := DumpInterfaceIPACLs(swIndex, vppChannel, stopwatch) - log.Infof("Res: %+v\n", res) - if err != nil { - return alAcls, err - } - - if res.SwIfIndex != swIndex { - return alAcls, fmt.Errorf("returned interface index %d does not match request", res.SwIfIndex) - } - - for aidx := range res.Acls { - ipACL, err := getIPACLDetails(vppChannel, uint32(aidx)) - if err != nil { - log.Error(err) - } else { - alAcls.Acls = append(alAcls.Acls, ipACL) - } - } - return alAcls, nil -} - -// DumpInterfaceMACIPAcls finds interface in VPP and returns its MACIP ACL configuration -func DumpInterfaceMACIPAcls(log logging.Logger, swIndex uint32, vppChannel govppapi.Channel, stopwatch *measure.Stopwatch) (acl.AccessLists, error) { - alAcls := acl.AccessLists{ - Acls: []*acl.AccessLists_Acl{}, - } - - resMacIp, err := DumpInterfaceMACIPACLs(swIndex, vppChannel, stopwatch) - log.Infof("Res: %+v\n", resMacIp) - if err != nil { - return alAcls, err - } - - if resMacIp.SwIfIndex != swIndex { - return alAcls, fmt.Errorf("returned interface index %d does not match request", resMacIp.SwIfIndex) - } - - for aidx := range resMacIp.Acls { - macipACL, err := getMACIPACLDetails(vppChannel, uint32(aidx)) - if err != nil { - log.Error(err) - } else { - alAcls.Acls = append(alAcls.Acls, macipACL) - } - } - return alAcls, nil -} - -// DumpInterface finds interface in VPP and returns its IP ACL configuration. -func DumpInterfaceIPACLs(swIndex uint32, vppChannel govppapi.Channel, stopwatch *measure.Stopwatch) (*acl_api.ACLInterfaceListDetails, error) { - defer func(t time.Time) { - stopwatch.TimeLog(acl_api.ACLInterfaceListDump{}).LogTimeEntry(time.Since(t)) - }(time.Now()) - - req := &acl_api.ACLInterfaceListDump{ - SwIfIndex: swIndex, - } - - reply := &acl_api.ACLInterfaceListDetails{} - if err := vppChannel.SendRequest(req).ReceiveReply(reply); err != nil { - return nil, err - } - - return reply, nil -} - -// DumpInterface finds interface in VPP and returns its MACIP ACL configuration. -func DumpInterfaceMACIPACLs(swIndex uint32, vppChannel govppapi.Channel, stopwatch *measure.Stopwatch) (*acl_api.MacipACLInterfaceListDetails, error) { - defer func(t time.Time) { - stopwatch.TimeLog(acl_api.MacipACLInterfaceListDump{}).LogTimeEntry(time.Since(t)) - }(time.Now()) - - req := &acl_api.MacipACLInterfaceListDump{ - SwIfIndex: swIndex, - } - - reply := &acl_api.MacipACLInterfaceListDetails{} - if err := vppChannel.SendRequest(req).ReceiveReply(reply); err != nil { - return nil, err - } - - return reply, nil -} - -// DumpInterfaces finds all interfaces in VPP and returns their ACL configurations -func DumpInterfaces(vppChannel govppapi.Channel, stopwatch *measure.Stopwatch) ([]*acl_api.ACLInterfaceListDetails, []*acl_api.MacipACLInterfaceListDetails, error) { - defer func(t time.Time) { - stopwatch.TimeLog(acl_api.ACLInterfaceListDump{}).LogTimeEntry(time.Since(t)) - }(time.Now()) - - msgIPACL := &acl_api.ACLInterfaceListDump{ - SwIfIndex: 0xffffffff, // dump all - } - - reqIPACL := vppChannel.SendMultiRequest(msgIPACL) - - var IPaclInterfaces []*acl_api.ACLInterfaceListDetails - for { - reply := &acl_api.ACLInterfaceListDetails{} - stop, err := reqIPACL.ReceiveReply(reply) - if stop { - break - } - if err != nil { - logrus.DefaultLogger().Error(err) - return nil, nil, err - } - IPaclInterfaces = append(IPaclInterfaces, reply) - } - - msgMACIPACL := &acl_api.ACLInterfaceListDump{ - SwIfIndex: 0xffffffff, // dump all - } - - reqMACIPACL := vppChannel.SendMultiRequest(msgMACIPACL) - - var MACIPaclInterfaces []*acl_api.MacipACLInterfaceListDetails - for { - reply := &acl_api.MacipACLInterfaceListDetails{} - stop, err := reqMACIPACL.ReceiveReply(reply) - if stop { - break - } - if err != nil { - logrus.DefaultLogger().Error(err) - return nil, nil, err - } - MACIPaclInterfaces = append(MACIPaclInterfaces, reply) - } - - return IPaclInterfaces, MACIPaclInterfaces, nil -} diff --git a/plugins/vpp/aclplugin/vppdump/dump_vppcalls_test.go b/plugins/vpp/aclplugin/vppcalls/dump_vppcalls_test.go similarity index 83% rename from plugins/vpp/aclplugin/vppdump/dump_vppcalls_test.go rename to plugins/vpp/aclplugin/vppcalls/dump_vppcalls_test.go index 9f8f94fb33..fc588c2138 100644 --- a/plugins/vpp/aclplugin/vppdump/dump_vppcalls_test.go +++ b/plugins/vpp/aclplugin/vppcalls/dump_vppcalls_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package vppdump +package vppcalls import ( "testing" @@ -28,7 +28,11 @@ import ( // Test translation of IP rule into ACL Plugin's format func TestGetIPRuleMatch(t *testing.T) { - icmpV4Rule := getIPRuleMatches(acl_api.ACLRule{ + ctx := vppcallmock.SetupTestCtx(t) + defer ctx.TeardownTestCtx() + aclHandler := NewACLVppHandler(ctx.MockChannel, nil, nil) + + icmpV4Rule := aclHandler.getIPRuleMatches(acl_api.ACLRule{ SrcIPAddr: []byte{10, 0, 0, 1}, SrcIPPrefixLen: 24, DstIPAddr: []byte{20, 0, 0, 1}, @@ -39,8 +43,8 @@ func TestGetIPRuleMatch(t *testing.T) { t.Fatal("should have icmp match") } - icmpV6Rule := getIPRuleMatches(acl_api.ACLRule{ - IsIpv6: 1, + icmpV6Rule := aclHandler.getIPRuleMatches(acl_api.ACLRule{ + IsIPv6: 1, SrcIPAddr: []byte{'d', 'e', 'd', 'd', 1}, SrcIPPrefixLen: 64, DstIPAddr: []byte{'d', 'e', 'd', 'd', 2}, @@ -51,7 +55,7 @@ func TestGetIPRuleMatch(t *testing.T) { t.Fatal("should have icmpv6 match") } - tcpRule := getIPRuleMatches(acl_api.ACLRule{ + tcpRule := aclHandler.getIPRuleMatches(acl_api.ACLRule{ SrcIPAddr: []byte{10, 0, 0, 1}, SrcIPPrefixLen: 24, DstIPAddr: []byte{20, 0, 0, 1}, @@ -62,7 +66,7 @@ func TestGetIPRuleMatch(t *testing.T) { t.Fatal("should have tcp match") } - udpRule := getIPRuleMatches(acl_api.ACLRule{ + udpRule := aclHandler.getIPRuleMatches(acl_api.ACLRule{ SrcIPAddr: []byte{10, 0, 0, 1}, SrcIPPrefixLen: 24, DstIPAddr: []byte{20, 0, 0, 1}, @@ -76,7 +80,11 @@ func TestGetIPRuleMatch(t *testing.T) { // Test translation of MACIP rule into ACL Plugin's format func TestGetMACIPRuleMatches(t *testing.T) { - macipV4Rule := getMACIPRuleMatches(acl_api.MacipACLRule{ + ctx := vppcallmock.SetupTestCtx(t) + defer ctx.TeardownTestCtx() + aclHandler := NewACLVppHandler(ctx.MockChannel, nil, nil) + + macipV4Rule := aclHandler.getMACIPRuleMatches(acl_api.MacipACLRule{ IsPermit: 1, SrcMac: []byte{2, 'd', 'e', 'a', 'd', 2}, SrcMacMask: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, @@ -86,9 +94,9 @@ func TestGetMACIPRuleMatches(t *testing.T) { if macipV4Rule.GetSourceMacAddress() == "" { t.Fatal("should have mac match") } - macipV6Rule := getMACIPRuleMatches(acl_api.MacipACLRule{ + macipV6Rule := aclHandler.getMACIPRuleMatches(acl_api.MacipACLRule{ IsPermit: 0, - IsIpv6: 1, + IsIPv6: 1, SrcMac: []byte{2, 'd', 'e', 'a', 'd', 2}, SrcMacMask: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, SrcIPAddr: []byte{'d', 'e', 'a', 'd', 1}, @@ -132,10 +140,12 @@ func TestDumpIPACL(t *testing.T) { }) ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) + aclHandler := NewACLVppHandler(ctx.MockChannel, ctx.MockChannel, nil) + swIfIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "test", nil)) swIfIndexes.RegisterName("if0", 1, nil) - ifaces, err := DumpIPACL(swIfIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + ifaces, err := aclHandler.DumpIPACL(swIfIndexes) Expect(err).To(Succeed()) Expect(ifaces).To(HaveLen(3)) //Expect(ifaces[0].Identifier.ACLIndex).To(Equal(uint32(0))) @@ -176,10 +186,12 @@ func TestDumpMACIPACL(t *testing.T) { }) ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) + aclHandler := NewACLVppHandler(ctx.MockChannel, ctx.MockChannel, nil) + swIfIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "test", nil)) swIfIndexes.RegisterName("if0", 1, nil) - ifaces, err := DumpMACIPACL(swIfIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + ifaces, err := aclHandler.DumpMACIPACL(swIfIndexes) Expect(err).To(Succeed()) Expect(ifaces).To(HaveLen(3)) //Expect(ifaces[0].Identifier.ACLIndex).To(Equal(uint32(0))) @@ -201,11 +213,13 @@ func TestDumpACLInterfaces(t *testing.T) { }) ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) + aclHandler := NewACLVppHandler(ctx.MockChannel, ctx.MockChannel, nil) + swIfIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "test", nil)) swIfIndexes.RegisterName("if0", 1, nil) indexes := []uint32{0, 2} - ifaces, err := DumpIPACLInterfaces(indexes, swIfIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + ifaces, err := aclHandler.DumpIPACLInterfaces(indexes, swIfIndexes) Expect(err).To(Succeed()) Expect(ifaces).To(HaveLen(2)) Expect(ifaces[0].Ingress).To(Equal([]string{"if0"})) @@ -224,11 +238,13 @@ func TestDumpMACIPACLInterfaces(t *testing.T) { }) ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) + aclHandler := NewACLVppHandler(ctx.MockChannel, ctx.MockChannel, nil) + swIfIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "test-sw_if_indexes", ifaceidx.IndexMetadata)) swIfIndexes.RegisterName("if0", 1, nil) indexes := []uint32{0, 1} - ifaces, err := DumpMACIPACLInterfaces(indexes, swIfIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + ifaces, err := aclHandler.DumpMACIPACLInterfaces(indexes, swIfIndexes) Expect(err).To(Succeed()) Expect(ifaces).To(HaveLen(2)) Expect(ifaces[0].Ingress).To(Equal([]string{"if0"})) @@ -249,7 +265,9 @@ func TestDumpIPAcls(t *testing.T) { }) ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - IPRuleACLs, err := DumpIPAcls(logrus.DefaultLogger(), ctx.MockChannel, nil) + aclHandler := NewACLVppHandler(ctx.MockChannel, ctx.MockChannel, nil) + + IPRuleACLs, err := aclHandler.DumpIPAcls() Expect(err).To(Succeed()) Expect(IPRuleACLs).To(HaveLen(1)) } @@ -266,7 +284,9 @@ func TestDumpMacIPAcls(t *testing.T) { }) ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - MacIPRuleACLs, err := DumpMacIPAcls(logrus.DefaultLogger(), ctx.MockChannel, nil) + aclHandler := NewACLVppHandler(ctx.MockChannel, ctx.MockChannel, nil) + + MacIPRuleACLs, err := aclHandler.DumpMacIPAcls() Expect(err).To(Succeed()) Expect(MacIPRuleACLs).To(HaveLen(1)) } @@ -292,7 +312,9 @@ func TestDumpInterfaceIPAcls(t *testing.T) { R: []acl_api.ACLRule{{IsPermit: 2}, {IsPermit: 0}}, }) - ACLs, err := DumpInterfaceIPAcls(logrus.DefaultLogger(), 0, ctx.MockChannel, nil) + aclHandler := NewACLVppHandler(ctx.MockChannel, ctx.MockChannel, nil) + + ACLs, err := aclHandler.DumpInterfaceIPAcls(0) Expect(err).To(Succeed()) Expect(ACLs.Acls).To(HaveLen(2)) } @@ -317,7 +339,9 @@ func TestDumpInterfaceMACIPAcls(t *testing.T) { R: []acl_api.MacipACLRule{{IsPermit: 2}, {IsPermit: 1}}, }) - ACLs, err := DumpInterfaceMACIPAcls(logrus.DefaultLogger(), 0, ctx.MockChannel, nil) + aclHandler := NewACLVppHandler(ctx.MockChannel, ctx.MockChannel, nil) + + ACLs, err := aclHandler.DumpInterfaceMACIPAcls(0) Expect(err).To(Succeed()) Expect(ACLs.Acls).To(HaveLen(2)) } @@ -326,18 +350,20 @@ func TestDumpInterface(t *testing.T) { ctx := vppcallmock.SetupTestCtx(t) defer ctx.TeardownTestCtx() + aclHandler := NewACLVppHandler(ctx.MockChannel, ctx.MockChannel, nil) + ctx.MockVpp.MockReply(&acl_api.ACLInterfaceListDetails{ SwIfIndex: 0, Count: 2, NInput: 1, Acls: []uint32{0, 1}, }) - IPacls, err := DumpInterfaceIPACLs(0, ctx.MockChannel, nil) + IPacls, err := aclHandler.DumpInterfaceIPACLs(0) Expect(err).To(BeNil()) Expect(IPacls.Acls).To(HaveLen(2)) ctx.MockVpp.MockReply(&acl_api.ACLInterfaceListDetails{}) - IPacls, err = DumpInterfaceIPACLs(0, ctx.MockChannel, nil) + IPacls, err = aclHandler.DumpInterfaceIPACLs(0) Expect(err).To(BeNil()) Expect(IPacls.Acls).To(HaveLen(0)) @@ -346,12 +372,12 @@ func TestDumpInterface(t *testing.T) { Count: 2, Acls: []uint32{0, 1}, }) - MACIPacls, err := DumpInterfaceMACIPACLs(0, ctx.MockChannel, nil) + MACIPacls, err := aclHandler.DumpInterfaceMACIPACLs(0) Expect(err).To(BeNil()) Expect(MACIPacls.Acls).To(HaveLen(2)) ctx.MockVpp.MockReply(&acl_api.MacipACLInterfaceListDetails{}) - MACIPacls, err = DumpInterfaceMACIPACLs(0, ctx.MockChannel, nil) + MACIPacls, err = aclHandler.DumpInterfaceMACIPACLs(0) Expect(err).To(BeNil()) Expect(MACIPacls.Acls).To(HaveLen(0)) } @@ -392,7 +418,9 @@ func TestDumpInterfaces(t *testing.T) { }) ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - IPacls, MACIPacls, err := DumpInterfaces(ctx.MockChannel, nil) + aclHandler := NewACLVppHandler(ctx.MockChannel, ctx.MockChannel, nil) + + IPacls, MACIPacls, err := aclHandler.DumpInterfaces() Expect(err).To(BeNil()) Expect(IPacls).To(HaveLen(3)) Expect(MACIPacls).To(HaveLen(2)) diff --git a/plugins/vpp/aclplugin/vppcalls/interfaces_vppcalls.go b/plugins/vpp/aclplugin/vppcalls/interfaces_vppcalls.go index 4e23f2109e..bc69d12056 100644 --- a/plugins/vpp/aclplugin/vppcalls/interfaces_vppcalls.go +++ b/plugins/vpp/aclplugin/vppcalls/interfaces_vppcalls.go @@ -18,12 +18,8 @@ import ( "fmt" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging" "github.com/ligato/cn-infra/logging/measure" - "github.com/ligato/vpp-agent/plugins/vpp/aclplugin/vppdump" acl_api "github.com/ligato/vpp-agent/plugins/vpp/binapi/acl" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" ) // ACLInterfaceLogicalReq groups multiple fields to not enumerate all of them in one function call @@ -33,76 +29,113 @@ type ACLInterfaceLogicalReq struct { ingress bool } -// ACLInterfacesVppCalls aggregates vpp calls related to the IP ACL interfaces -type ACLInterfacesVppCalls struct { - log logging.Logger - vppChan govppapi.Channel - swIfIndexes ifaceidx.SwIfIndex - stopwatch *measure.Stopwatch - setACLStopwatch measure.StopWatchEntry -} - -// NewACLInterfacesVppCalls constructs IP ACL interfaces vpp calls object -func NewACLInterfacesVppCalls(log logging.Logger, vppChan govppapi.Channel, swIfIndexes ifaceidx.SwIfIndex, stopwatch *measure.Stopwatch) *ACLInterfacesVppCalls { - return &ACLInterfacesVppCalls{ - log: log, - vppChan: vppChan, - swIfIndexes: swIfIndexes, - setACLStopwatch: measure.GetTimeLog(acl_api.ACLInterfaceSetACLList{}, stopwatch), - } -} - -// SetACLToInterfacesAsIngress sets ACL to all provided interfaces as ingress -func (acl *ACLInterfacesVppCalls) SetACLToInterfacesAsIngress(ACLIndex uint32, ifIndices []uint32) error { - acl.log.Debugf("Setting up IP ingress ACL from interfaces: %v ", ifIndices) - - return acl.requestSetACLToInterfaces(&ACLInterfaceLogicalReq{ +// SetACLToInterfacesAsIngress implements ACL handler. +func (handler *ACLVppHandler) SetACLToInterfacesAsIngress(ACLIndex uint32, ifIndices []uint32) error { + return handler.requestSetACLToInterfaces(&ACLInterfaceLogicalReq{ aclIndex: ACLIndex, ifIndices: ifIndices, ingress: true, }) } -// RemoveIPIngressACLFromInterfaces removes ACL from interfaces -func (acl *ACLInterfacesVppCalls) RemoveIPIngressACLFromInterfaces(ACLIndex uint32, ifIndices []uint32) error { - acl.log.Debugf("Removing IP ingress ACL from interfaces: %v ", ifIndices) - - return acl.requestRemoveInterfacesFromACL(&ACLInterfaceLogicalReq{ +// RemoveIPIngressACLFromInterfaces implements ACL handler. +func (handler *ACLVppHandler) RemoveIPIngressACLFromInterfaces(ACLIndex uint32, ifIndices []uint32) error { + return handler.requestRemoveInterfacesFromACL(&ACLInterfaceLogicalReq{ aclIndex: ACLIndex, ifIndices: ifIndices, ingress: true, }) } -// SetACLToInterfacesAsEgress sets ACL to all provided interfaces as egress -func (acl *ACLInterfacesVppCalls) SetACLToInterfacesAsEgress(ACLIndex uint32, ifIndices []uint32) error { - acl.log.Debugf("Setting up IP egress ACL from interfaces: %v ", ifIndices) - - return acl.requestSetACLToInterfaces(&ACLInterfaceLogicalReq{ +// SetACLToInterfacesAsEgress implements ACL handler. +func (handler *ACLVppHandler) SetACLToInterfacesAsEgress(ACLIndex uint32, ifIndices []uint32) error { + return handler.requestSetACLToInterfaces(&ACLInterfaceLogicalReq{ aclIndex: ACLIndex, ifIndices: ifIndices, ingress: false, }) } -// RemoveIPEgressACLFromInterfaces removes ACL from interfaces -func (acl *ACLInterfacesVppCalls) RemoveIPEgressACLFromInterfaces(ACLIndex uint32, ifIndices []uint32) error { - acl.log.Debugf("Removing IP egress ACL from interfaces: %v ", ifIndices) - - return acl.requestRemoveInterfacesFromACL(&ACLInterfaceLogicalReq{ +// RemoveIPEgressACLFromInterfaces implements ACL handler. +func (handler *ACLVppHandler) RemoveIPEgressACLFromInterfaces(ACLIndex uint32, ifIndices []uint32) error { + return handler.requestRemoveInterfacesFromACL(&ACLInterfaceLogicalReq{ aclIndex: ACLIndex, ifIndices: ifIndices, ingress: false, }) } -func (acl *ACLInterfacesVppCalls) requestSetACLToInterfaces(logicalReq *ACLInterfaceLogicalReq) error { +// SetMacIPACLToInterface implements ACL handler. +func (handler *ACLVppHandler) SetMacIPACLToInterface(aclIndex uint32, ifIndices []uint32) error { + setACLStopwatch := measure.GetTimeLog(acl_api.MacipACLInterfaceAddDel{}, handler.stopwatch) + for _, ingressIfIdx := range ifIndices { + // Measure MacipACLInterfaceAddDel time + start := time.Now() + + req := &acl_api.MacipACLInterfaceAddDel{ + ACLIndex: aclIndex, + IsAdd: 1, + SwIfIndex: ingressIfIdx, + } + + reply := &acl_api.MacipACLInterfaceAddDelReply{} + + err := handler.callsChannel.SendRequest(req).ReceiveReply(reply) + if err != nil { + return fmt.Errorf("failed to set interface %d to L2 ACL %d: %v", ingressIfIdx, aclIndex, err) + } + if reply.Retval != 0 { + return fmt.Errorf("set interface %d to L2 ACL %d returned %d", ingressIfIdx, aclIndex, reply.Retval) + } + + // Log MacipACLInterfaceAddDel time measurement results. + if setACLStopwatch != nil { + setACLStopwatch.LogTimeEntry(time.Since(start)) + } + } + + return nil +} + +// RemoveMacIPIngressACLFromInterfaces implements ACL handler. +func (handler *ACLVppHandler) RemoveMacIPIngressACLFromInterfaces(removedACLIndex uint32, ifIndices []uint32) error { + setACLStopwatch := measure.GetTimeLog(acl_api.MacipACLInterfaceAddDel{}, handler.stopwatch) + for _, ifIdx := range ifIndices { + // Measure MacipACLInterfaceAddDel time. + start := time.Now() + + req := &acl_api.MacipACLInterfaceAddDel{ + ACLIndex: removedACLIndex, + SwIfIndex: ifIdx, + IsAdd: 0, + } + + reply := &acl_api.MacipACLInterfaceAddDelReply{} + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { + return fmt.Errorf("failed to remove L2 ACL %d from interface %d: %v", removedACLIndex, ifIdx, err) + } + if reply.Retval != 0 { + return fmt.Errorf("remove L2 ACL %d from interface %d returned error %d", removedACLIndex, + removedACLIndex, reply.Retval) + } + + // Log MacipACLInterfaceAddDel time measurement results. + if setACLStopwatch != nil { + setACLStopwatch.LogTimeEntry(time.Since(start)) + } + } + return nil +} + +func (handler *ACLVppHandler) requestSetACLToInterfaces(logicalReq *ACLInterfaceLogicalReq) error { + setACLStopwatch := measure.GetTimeLog(acl_api.ACLInterfaceSetACLList{}, handler.stopwatch) for _, aclIfIdx := range logicalReq.ifIndices { // Create acl list with new entry var ACLs []uint32 // All previously assigned ACLs have to be dumped and added to acl list - aclInterfaceDetails, err := vppdump.DumpInterfaceIPACLs(aclIfIdx, acl.vppChan, acl.stopwatch) + aclInterfaceDetails, err := handler.DumpInterfaceIPACLs(aclIfIdx) if err != nil { return err } @@ -133,14 +166,15 @@ func (acl *ACLInterfacesVppCalls) requestSetACLToInterfaces(logicalReq *ACLInter // Measure ACLInterfaceSetACLList time start := time.Now() - msg := &acl_api.ACLInterfaceSetACLList{} - msg.Acls = ACLs - msg.Count = uint8(len(ACLs)) - msg.SwIfIndex = aclIfIdx - msg.NInput = nInput - + msg := &acl_api.ACLInterfaceSetACLList{ + Acls: ACLs, + Count: uint8(len(ACLs)), + SwIfIndex: aclIfIdx, + NInput: nInput, + } reply := &acl_api.ACLInterfaceSetACLListReply{} - err = acl.vppChan.SendRequest(msg).ReceiveReply(reply) + + err = handler.callsChannel.SendRequest(msg).ReceiveReply(reply) if err != nil { return err } @@ -148,25 +182,24 @@ func (acl *ACLInterfacesVppCalls) requestSetACLToInterfaces(logicalReq *ACLInter return fmt.Errorf("setting up interface ACL list returned %v", reply.Retval) } - acl.log.WithFields(logging.Fields{"SwIdx index": msg.SwIfIndex, "AclIdx": logicalReq.aclIndex}).Debug("Interface set to ACL") - // Log ACLInterfaceSetACLList time measurement results - if acl.setACLStopwatch != nil { - acl.setACLStopwatch.LogTimeEntry(time.Since(start)) + if setACLStopwatch != nil { + setACLStopwatch.LogTimeEntry(time.Since(start)) } } return nil } -func (acl *ACLInterfacesVppCalls) requestRemoveInterfacesFromACL(logicalReq *ACLInterfaceLogicalReq) error { +func (handler *ACLVppHandler) requestRemoveInterfacesFromACL(logicalReq *ACLInterfaceLogicalReq) error { + setACLStopwatch := measure.GetTimeLog(acl_api.ACLInterfaceSetACLList{}, handler.stopwatch) var wasErr error for _, aclIfIdx := range logicalReq.ifIndices { // Create empty ACL list var ACLs []uint32 // All assigned ACLs have to be dumped - aclInterfaceDetails, err := vppdump.DumpInterfaceIPACLs(aclIfIdx, acl.vppChan, acl.stopwatch) + aclInterfaceDetails, err := handler.DumpInterfaceIPACLs(aclIfIdx) if err != nil { return err } @@ -192,14 +225,15 @@ func (acl *ACLInterfacesVppCalls) requestRemoveInterfacesFromACL(logicalReq *ACL // Measure ACLInterfaceSetACLList time start := time.Now() - msg := &acl_api.ACLInterfaceSetACLList{} - msg.Acls = ACLs - msg.Count = uint8(len(ACLs)) - msg.SwIfIndex = aclIfIdx - msg.NInput = nInput + msg := &acl_api.ACLInterfaceSetACLList{ + Acls: ACLs, + Count: uint8(len(ACLs)), + SwIfIndex: aclIfIdx, + NInput: nInput, + } reply := &acl_api.ACLInterfaceSetACLListReply{} - err = acl.vppChan.SendRequest(msg).ReceiveReply(reply) + err = handler.callsChannel.SendRequest(msg).ReceiveReply(reply) if err != nil { wasErr = err } @@ -207,75 +241,11 @@ func (acl *ACLInterfacesVppCalls) requestRemoveInterfacesFromACL(logicalReq *ACL wasErr = fmt.Errorf("setting up interface ACL list returned %v", reply.Retval) } - acl.log.WithFields(logging.Fields{"SwIdx index": msg.SwIfIndex, "AclIdx": logicalReq.aclIndex}).Debug("Interface removed from ACL") - // Log ACLInterfaceSetACLList time measurement results - if acl.setACLStopwatch != nil { - acl.setACLStopwatch.LogTimeEntry(time.Since(start)) + if setACLStopwatch != nil { + setACLStopwatch.LogTimeEntry(time.Since(start)) } } return wasErr } - -// SetMacIPAclToInterface adds L2 ACL to interface. -func (acl *ACLInterfacesVppCalls) SetMacIPAclToInterface(aclIndex uint32, ifIndices []uint32) error { - for _, ingressIfIdx := range ifIndices { - // Measure MacipACLInterfaceAddDel time - start := time.Now() - - req := &acl_api.MacipACLInterfaceAddDel{} - req.ACLIndex = aclIndex - req.IsAdd = 1 - req.SwIfIndex = ingressIfIdx - - reply := &acl_api.MacipACLInterfaceAddDelReply{} - - err := acl.vppChan.SendRequest(req).ReceiveReply(reply) - if err != nil { - return fmt.Errorf("failed to set interface %v to L2 ACL %v", ingressIfIdx, aclIndex) - } - if reply.Retval != 0 { - return fmt.Errorf("set interface %v to L2 ACL %v returned %v", ingressIfIdx, aclIndex, reply.Retval) - } - acl.log.Debugf("Interface %v set to L2 ACL %v as ingress", ingressIfIdx, aclIndex) - - // Log MacipACLInterfaceAddDel time measurement results. - if acl.setACLStopwatch != nil { - acl.setACLStopwatch.LogTimeEntry(time.Since(start)) - } - } - - return nil -} - -// RemoveMacIPIngressACLFromInterfaces removes L2 ACL from interfaces. -func (acl *ACLInterfacesVppCalls) RemoveMacIPIngressACLFromInterfaces(removedACLIndex uint32, ifIndices []uint32) error { - for _, ifIdx := range ifIndices { - // Measure MacipACLInterfaceAddDel time. - start := time.Now() - - req := &acl_api.MacipACLInterfaceAddDel{} - req.ACLIndex = removedACLIndex - req.SwIfIndex = ifIdx - req.IsAdd = 0 - - reply := &acl_api.MacipACLInterfaceAddDelReply{} - - err := acl.vppChan.SendRequest(req).ReceiveReply(reply) - if err != nil { - return fmt.Errorf("failed to remove L2 ACL %v from interface %v", removedACLIndex, ifIdx) - } - if reply.Retval != 0 { - return fmt.Errorf("remove L2 ACL %v from interface %v returned error %v", removedACLIndex, - removedACLIndex, reply.Retval) - } - acl.log.Debugf("L2 ACL %v removed from interface %v (ingress)", removedACLIndex, ifIdx) - - // Log MacipACLInterfaceAddDel time measurement results. - if acl.setACLStopwatch != nil { - acl.setACLStopwatch.LogTimeEntry(time.Since(start)) - } - } - return nil -} diff --git a/plugins/vpp/aclplugin/vppcalls/interfaces_vppcalls_test.go b/plugins/vpp/aclplugin/vppcalls/interfaces_vppcalls_test.go index 6334df7060..f29ed00201 100644 --- a/plugins/vpp/aclplugin/vppcalls/interfaces_vppcalls_test.go +++ b/plugins/vpp/aclplugin/vppcalls/interfaces_vppcalls_test.go @@ -17,10 +17,7 @@ package vppcalls import ( "testing" - "github.com/ligato/cn-infra/logging/logrus" - "github.com/ligato/vpp-agent/idxvpp/nametoidx" acl_api "github.com/ligato/vpp-agent/plugins/vpp/binapi/acl" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" ) @@ -30,53 +27,52 @@ func TestRequestSetACLToInterfaces(t *testing.T) { ctx := vppcallmock.SetupTestCtx(t) defer ctx.TeardownTestCtx() - ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "test-plugin", nil)) - interfaces := NewACLInterfacesVppCalls(logrus.DefaultLogger(), ctx.MockChannel, ifIndexes, nil) + aclHandler := NewACLVppHandler(ctx.MockChannel, ctx.MockChannel, nil) ctx.MockVpp.MockReply(&acl_api.ACLInterfaceListDetails{ - 0, - 1, - 1, - []uint32{0, 1}, + SwIfIndex: 0, + Count: 1, + NInput: 1, + Acls: []uint32{0, 1}, }) ctx.MockVpp.MockReply(&acl_api.ACLInterfaceSetACLListReply{}) - err := interfaces.SetACLToInterfacesAsIngress(0, []uint32{0}) + err := aclHandler.SetACLToInterfacesAsIngress(0, []uint32{0}) Expect(err).To(BeNil()) ctx.MockVpp.MockReply(&acl_api.ACLInterfaceListDetails{ - 0, - 1, - 1, - []uint32{0, 1}, + SwIfIndex: 0, + Count: 1, + NInput: 1, + Acls: []uint32{0, 1}, }) ctx.MockVpp.MockReply(&acl_api.ACLInterfaceSetACLListReply{}) - err = interfaces.SetACLToInterfacesAsEgress(0, []uint32{0}) + err = aclHandler.SetACLToInterfacesAsEgress(0, []uint32{0}) Expect(err).To(BeNil()) // error cases ctx.MockVpp.MockReply(&acl_api.ACLInterfaceSetACLListReply{}) - err = interfaces.SetACLToInterfacesAsIngress(0, []uint32{0}) + err = aclHandler.SetACLToInterfacesAsIngress(0, []uint32{0}) Expect(err).To(Not(BeNil())) ctx.MockVpp.MockReply(&acl_api.ACLInterfaceListDetails{ - 0, - 1, - 1, - []uint32{0, 1}, + SwIfIndex: 0, + Count: 1, + NInput: 1, + Acls: []uint32{0, 1}, }) ctx.MockVpp.MockReply(&acl_api.MacipACLAddReplaceReply{}) - err = interfaces.SetACLToInterfacesAsIngress(0, []uint32{0}) + err = aclHandler.SetACLToInterfacesAsIngress(0, []uint32{0}) Expect(err).To(Not(BeNil())) ctx.MockVpp.MockReply(&acl_api.ACLInterfaceListDetails{ - 0, - 1, - 1, - []uint32{0, 1}, + SwIfIndex: 0, + Count: 1, + NInput: 1, + Acls: []uint32{0, 1}, }) ctx.MockVpp.MockReply(&acl_api.ACLInterfaceSetACLListReply{Retval: -1}) - err = interfaces.SetACLToInterfacesAsIngress(0, []uint32{0}) + err = aclHandler.SetACLToInterfacesAsIngress(0, []uint32{0}) Expect(err).To(Not(BeNil())) } @@ -85,53 +81,52 @@ func TestRequestRemoveInterfacesFromACL(t *testing.T) { ctx := vppcallmock.SetupTestCtx(t) defer ctx.TeardownTestCtx() - ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "test-plugin", nil)) - interfaces := NewACLInterfacesVppCalls(logrus.DefaultLogger(), ctx.MockChannel, ifIndexes, nil) + aclHandler := NewACLVppHandler(ctx.MockChannel, ctx.MockChannel, nil) ctx.MockVpp.MockReply(&acl_api.ACLInterfaceListDetails{ - 0, - 1, - 1, - []uint32{0, 1}, + SwIfIndex: 0, + Count: 1, + NInput: 1, + Acls: []uint32{0, 1}, }) ctx.MockVpp.MockReply(&acl_api.ACLInterfaceSetACLListReply{}) - err := interfaces.RemoveIPIngressACLFromInterfaces(0, []uint32{0}) + err := aclHandler.RemoveIPIngressACLFromInterfaces(0, []uint32{0}) Expect(err).To(BeNil()) ctx.MockVpp.MockReply(&acl_api.ACLInterfaceListDetails{ - 0, - 1, - 1, - []uint32{0, 1}, + SwIfIndex: 0, + Count: 1, + NInput: 1, + Acls: []uint32{0, 1}, }) ctx.MockVpp.MockReply(&acl_api.ACLInterfaceSetACLListReply{}) - err = interfaces.RemoveIPEgressACLFromInterfaces(0, []uint32{0}) + err = aclHandler.RemoveIPEgressACLFromInterfaces(0, []uint32{0}) Expect(err).To(BeNil()) // error cases ctx.MockVpp.MockReply(&acl_api.ACLInterfaceSetACLListReply{}) - err = interfaces.RemoveIPEgressACLFromInterfaces(0, []uint32{0}) + err = aclHandler.RemoveIPEgressACLFromInterfaces(0, []uint32{0}) Expect(err).To(Not(BeNil())) ctx.MockVpp.MockReply(&acl_api.ACLInterfaceListDetails{ - 0, - 1, - 1, - []uint32{0, 1}, + SwIfIndex: 0, + Count: 1, + NInput: 1, + Acls: []uint32{0, 1}, }) ctx.MockVpp.MockReply(&acl_api.MacipACLAddReplaceReply{}) - err = interfaces.RemoveIPEgressACLFromInterfaces(0, []uint32{0}) + err = aclHandler.RemoveIPEgressACLFromInterfaces(0, []uint32{0}) Expect(err).To(Not(BeNil())) ctx.MockVpp.MockReply(&acl_api.ACLInterfaceListDetails{ - 0, - 1, - 1, - []uint32{0, 1}, + SwIfIndex: 0, + Count: 1, + NInput: 1, + Acls: []uint32{0, 1}, }) ctx.MockVpp.MockReply(&acl_api.ACLInterfaceSetACLListReply{Retval: -1}) - err = interfaces.RemoveIPEgressACLFromInterfaces(0, []uint32{0}) + err = aclHandler.RemoveIPEgressACLFromInterfaces(0, []uint32{0}) Expect(err).To(Not(BeNil())) } @@ -140,21 +135,20 @@ func TestSetMacIPAclToInterface(t *testing.T) { ctx := vppcallmock.SetupTestCtx(t) defer ctx.TeardownTestCtx() - ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "test-plugin", nil)) - interfaces := NewACLInterfacesVppCalls(logrus.DefaultLogger(), ctx.MockChannel, ifIndexes, nil) + aclHandler := NewACLVppHandler(ctx.MockChannel, ctx.MockChannel, nil) ctx.MockVpp.MockReply(&acl_api.MacipACLInterfaceAddDelReply{}) - err := interfaces.SetMacIPAclToInterface(0, []uint32{0}) + err := aclHandler.SetMacIPACLToInterface(0, []uint32{0}) Expect(err).To(BeNil()) // error cases ctx.MockVpp.MockReply(&acl_api.MacipACLAddReplaceReply{}) - err = interfaces.SetMacIPAclToInterface(0, []uint32{0}) + err = aclHandler.SetMacIPACLToInterface(0, []uint32{0}) Expect(err).To(Not(BeNil())) ctx.MockVpp.MockReply(&acl_api.MacipACLInterfaceAddDelReply{Retval: -1}) - err = interfaces.SetMacIPAclToInterface(0, []uint32{0}) + err = aclHandler.SetMacIPACLToInterface(0, []uint32{0}) Expect(err).To(Not(BeNil())) } @@ -163,26 +157,19 @@ func TestRemoveMacIPIngressACLFromInterfaces(t *testing.T) { ctx := vppcallmock.SetupTestCtx(t) defer ctx.TeardownTestCtx() - ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "test-plugin", nil)) - interfaces := ACLInterfacesVppCalls{ - logrus.DefaultLogger(), - ctx.MockChannel, - ifIndexes, - nil, - nil, - } + aclHandler := NewACLVppHandler(ctx.MockChannel, ctx.MockChannel, nil) ctx.MockVpp.MockReply(&acl_api.MacipACLInterfaceAddDelReply{}) - err := interfaces.RemoveMacIPIngressACLFromInterfaces(1, []uint32{0}) + err := aclHandler.RemoveMacIPIngressACLFromInterfaces(1, []uint32{0}) Expect(err).To(BeNil()) // error cases ctx.MockVpp.MockReply(&acl_api.MacipACLAddReplaceReply{}) - err = interfaces.RemoveMacIPIngressACLFromInterfaces(0, []uint32{0}) + err = aclHandler.RemoveMacIPIngressACLFromInterfaces(0, []uint32{0}) Expect(err).To(Not(BeNil())) ctx.MockVpp.MockReply(&acl_api.MacipACLInterfaceAddDelReply{Retval: -1}) - err = interfaces.RemoveMacIPIngressACLFromInterfaces(0, []uint32{0}) + err = aclHandler.RemoveMacIPIngressACLFromInterfaces(0, []uint32{0}) Expect(err).To(Not(BeNil())) } diff --git a/plugins/vpp/aclplugin/vppdump/doc.go b/plugins/vpp/aclplugin/vppdump/doc.go deleted file mode 100644 index c7b54c339d..0000000000 --- a/plugins/vpp/aclplugin/vppdump/doc.go +++ /dev/null @@ -1,3 +0,0 @@ -// Package vppdump provides helpers to dump ACLs configured in VPP - per -// interface and total. -package vppdump diff --git a/plugins/vpp/binapi/acl/acl.go b/plugins/vpp/binapi/acl/acl.ba.go similarity index 85% rename from plugins/vpp/binapi/acl/acl.go rename to plugins/vpp/binapi/acl/acl.ba.go index c47b30eaa7..195c8e91ed 100644 --- a/plugins/vpp/binapi/acl/acl.go +++ b/plugins/vpp/binapi/acl/acl.ba.go @@ -1,12 +1,31 @@ -// Code generated by govpp binapi-generator DO NOT EDIT. -// Package acl represents the VPP binary API of the 'acl' VPP module. -// Generated from '/usr/share/vpp/api/acl.api.json' +// Code generated by GoVPP binapi-generator. DO NOT EDIT. +// source: /usr/share/vpp/api/acl.api.json + +/* +Package acl is a generated VPP binary API of the 'acl' VPP module. + +It is generated from this file: + acl.api.json + +It contains these VPP binary API objects: + 34 messages + 2 types + 17 services +*/ package acl import "git.fd.io/govpp.git/api" +import "github.com/lunixbochs/struc" +import "bytes" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = struc.Pack +var _ = bytes.NewBuffer -// ACLRule represents the VPP binary API data type 'acl_rule'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 922: +/* Types */ + +// ACLRule represents the VPP binary API type 'acl_rule'. +// Generated from 'acl.api.json', line 922: // // "acl_rule", // [ @@ -69,7 +88,7 @@ import "git.fd.io/govpp.git/api" // type ACLRule struct { IsPermit uint8 - IsIpv6 uint8 + IsIPv6 uint8 SrcIPAddr []byte `struc:"[16]byte"` SrcIPPrefixLen uint8 DstIPAddr []byte `struc:"[16]byte"` @@ -90,8 +109,8 @@ func (*ACLRule) GetCrcString() string { return "6f99bf4d" } -// MacipACLRule represents the VPP binary API data type 'macip_acl_rule'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 982: +// MacipACLRule represents the VPP binary API type 'macip_acl_rule'. +// Generated from 'acl.api.json', line 982: // // "macip_acl_rule", // [ @@ -127,7 +146,7 @@ func (*ACLRule) GetCrcString() string { // type MacipACLRule struct { IsPermit uint8 - IsIpv6 uint8 + IsIPv6 uint8 SrcMac []byte `struc:"[6]byte"` SrcMacMask []byte `struc:"[6]byte"` SrcIPAddr []byte `struc:"[16]byte"` @@ -141,8 +160,10 @@ func (*MacipACLRule) GetCrcString() string { return "70589f1e" } +/* Messages */ + // ACLPluginGetVersion represents the VPP binary API message 'acl_plugin_get_version'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 4: +// Generated from 'acl.api.json', line 4: // // "acl_plugin_get_version", // [ @@ -161,24 +182,23 @@ func (*MacipACLRule) GetCrcString() string { // "crc": "0x51077d14" // } // -type ACLPluginGetVersion struct { -} +type ACLPluginGetVersion struct{} func (*ACLPluginGetVersion) GetMessageName() string { return "acl_plugin_get_version" } -func (*ACLPluginGetVersion) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ACLPluginGetVersion) GetCrcString() string { return "51077d14" } +func (*ACLPluginGetVersion) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewACLPluginGetVersion() api.Message { return &ACLPluginGetVersion{} } // ACLPluginGetVersionReply represents the VPP binary API message 'acl_plugin_get_version_reply'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 22: +// Generated from 'acl.api.json', line 22: // // "acl_plugin_get_version_reply", // [ @@ -209,18 +229,18 @@ type ACLPluginGetVersionReply struct { func (*ACLPluginGetVersionReply) GetMessageName() string { return "acl_plugin_get_version_reply" } -func (*ACLPluginGetVersionReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ACLPluginGetVersionReply) GetCrcString() string { return "9b32cf86" } +func (*ACLPluginGetVersionReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewACLPluginGetVersionReply() api.Message { return &ACLPluginGetVersionReply{} } // ACLPluginControlPing represents the VPP binary API message 'acl_plugin_control_ping'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 44: +// Generated from 'acl.api.json', line 44: // // "acl_plugin_control_ping", // [ @@ -239,24 +259,23 @@ func NewACLPluginGetVersionReply() api.Message { // "crc": "0x51077d14" // } // -type ACLPluginControlPing struct { -} +type ACLPluginControlPing struct{} func (*ACLPluginControlPing) GetMessageName() string { return "acl_plugin_control_ping" } -func (*ACLPluginControlPing) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ACLPluginControlPing) GetCrcString() string { return "51077d14" } +func (*ACLPluginControlPing) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewACLPluginControlPing() api.Message { return &ACLPluginControlPing{} } // ACLPluginControlPingReply represents the VPP binary API message 'acl_plugin_control_ping_reply'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 62: +// Generated from 'acl.api.json', line 62: // // "acl_plugin_control_ping_reply", // [ @@ -286,24 +305,24 @@ func NewACLPluginControlPing() api.Message { type ACLPluginControlPingReply struct { Retval int32 ClientIndex uint32 - VpePid uint32 + VpePID uint32 } func (*ACLPluginControlPingReply) GetMessageName() string { return "acl_plugin_control_ping_reply" } -func (*ACLPluginControlPingReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ACLPluginControlPingReply) GetCrcString() string { return "f6b0b8ca" } +func (*ACLPluginControlPingReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewACLPluginControlPingReply() api.Message { return &ACLPluginControlPingReply{} } // ACLAddReplace represents the VPP binary API message 'acl_add_replace'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 88: +// Generated from 'acl.api.json', line 88: // // "acl_add_replace", // [ @@ -351,18 +370,18 @@ type ACLAddReplace struct { func (*ACLAddReplace) GetMessageName() string { return "acl_add_replace" } -func (*ACLAddReplace) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ACLAddReplace) GetCrcString() string { return "e839997e" } +func (*ACLAddReplace) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewACLAddReplace() api.Message { return &ACLAddReplace{} } // ACLAddReplaceReply represents the VPP binary API message 'acl_add_replace_reply'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 125: +// Generated from 'acl.api.json', line 125: // // "acl_add_replace_reply", // [ @@ -393,18 +412,18 @@ type ACLAddReplaceReply struct { func (*ACLAddReplaceReply) GetMessageName() string { return "acl_add_replace_reply" } -func (*ACLAddReplaceReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ACLAddReplaceReply) GetCrcString() string { return "ac407b0c" } +func (*ACLAddReplaceReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewACLAddReplaceReply() api.Message { return &ACLAddReplaceReply{} } // ACLDel represents the VPP binary API message 'acl_del'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 147: +// Generated from 'acl.api.json', line 147: // // "acl_del", // [ @@ -434,18 +453,18 @@ type ACLDel struct { func (*ACLDel) GetMessageName() string { return "acl_del" } -func (*ACLDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ACLDel) GetCrcString() string { return "ef34fea4" } +func (*ACLDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewACLDel() api.Message { return &ACLDel{} } // ACLDelReply represents the VPP binary API message 'acl_del_reply'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 169: +// Generated from 'acl.api.json', line 169: // // "acl_del_reply", // [ @@ -471,18 +490,18 @@ type ACLDelReply struct { func (*ACLDelReply) GetMessageName() string { return "acl_del_reply" } -func (*ACLDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ACLDelReply) GetCrcString() string { return "e8d4e804" } +func (*ACLDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewACLDelReply() api.Message { return &ACLDelReply{} } // ACLInterfaceAddDel represents the VPP binary API message 'acl_interface_add_del'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 187: +// Generated from 'acl.api.json', line 187: // // "acl_interface_add_del", // [ @@ -527,18 +546,18 @@ type ACLInterfaceAddDel struct { func (*ACLInterfaceAddDel) GetMessageName() string { return "acl_interface_add_del" } -func (*ACLInterfaceAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ACLInterfaceAddDel) GetCrcString() string { return "0b2aedd1" } +func (*ACLInterfaceAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewACLInterfaceAddDel() api.Message { return &ACLInterfaceAddDel{} } // ACLInterfaceAddDelReply represents the VPP binary API message 'acl_interface_add_del_reply'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 221: +// Generated from 'acl.api.json', line 221: // // "acl_interface_add_del_reply", // [ @@ -564,18 +583,18 @@ type ACLInterfaceAddDelReply struct { func (*ACLInterfaceAddDelReply) GetMessageName() string { return "acl_interface_add_del_reply" } -func (*ACLInterfaceAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ACLInterfaceAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*ACLInterfaceAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewACLInterfaceAddDelReply() api.Message { return &ACLInterfaceAddDelReply{} } // ACLInterfaceSetACLList represents the VPP binary API message 'acl_interface_set_acl_list'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 239: +// Generated from 'acl.api.json', line 239: // // "acl_interface_set_acl_list", // [ @@ -622,18 +641,18 @@ type ACLInterfaceSetACLList struct { func (*ACLInterfaceSetACLList) GetMessageName() string { return "acl_interface_set_acl_list" } -func (*ACLInterfaceSetACLList) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ACLInterfaceSetACLList) GetCrcString() string { return "8baece38" } +func (*ACLInterfaceSetACLList) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewACLInterfaceSetACLList() api.Message { return &ACLInterfaceSetACLList{} } // ACLInterfaceSetACLListReply represents the VPP binary API message 'acl_interface_set_acl_list_reply'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 275: +// Generated from 'acl.api.json', line 275: // // "acl_interface_set_acl_list_reply", // [ @@ -659,18 +678,18 @@ type ACLInterfaceSetACLListReply struct { func (*ACLInterfaceSetACLListReply) GetMessageName() string { return "acl_interface_set_acl_list_reply" } -func (*ACLInterfaceSetACLListReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ACLInterfaceSetACLListReply) GetCrcString() string { return "e8d4e804" } +func (*ACLInterfaceSetACLListReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewACLInterfaceSetACLListReply() api.Message { return &ACLInterfaceSetACLListReply{} } // ACLDump represents the VPP binary API message 'acl_dump'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 293: +// Generated from 'acl.api.json', line 293: // // "acl_dump", // [ @@ -700,18 +719,18 @@ type ACLDump struct { func (*ACLDump) GetMessageName() string { return "acl_dump" } -func (*ACLDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ACLDump) GetCrcString() string { return "ef34fea4" } +func (*ACLDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewACLDump() api.Message { return &ACLDump{} } // ACLDetails represents the VPP binary API message 'acl_details'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 315: +// Generated from 'acl.api.json', line 315: // // "acl_details", // [ @@ -755,18 +774,18 @@ type ACLDetails struct { func (*ACLDetails) GetMessageName() string { return "acl_details" } -func (*ACLDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ACLDetails) GetCrcString() string { return "5bd895be" } +func (*ACLDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewACLDetails() api.Message { return &ACLDetails{} } // ACLInterfaceListDump represents the VPP binary API message 'acl_interface_list_dump'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 348: +// Generated from 'acl.api.json', line 348: // // "acl_interface_list_dump", // [ @@ -796,18 +815,18 @@ type ACLInterfaceListDump struct { func (*ACLInterfaceListDump) GetMessageName() string { return "acl_interface_list_dump" } -func (*ACLInterfaceListDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ACLInterfaceListDump) GetCrcString() string { return "529cb13f" } +func (*ACLInterfaceListDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewACLInterfaceListDump() api.Message { return &ACLInterfaceListDump{} } // ACLInterfaceListDetails represents the VPP binary API message 'acl_interface_list_details'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 370: +// Generated from 'acl.api.json', line 370: // // "acl_interface_list_details", // [ @@ -850,18 +869,18 @@ type ACLInterfaceListDetails struct { func (*ACLInterfaceListDetails) GetMessageName() string { return "acl_interface_list_details" } -func (*ACLInterfaceListDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ACLInterfaceListDetails) GetCrcString() string { return "d5e80809" } +func (*ACLInterfaceListDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewACLInterfaceListDetails() api.Message { return &ACLInterfaceListDetails{} } // MacipACLAdd represents the VPP binary API message 'macip_acl_add'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 402: +// Generated from 'acl.api.json', line 402: // // "macip_acl_add", // [ @@ -904,18 +923,18 @@ type MacipACLAdd struct { func (*MacipACLAdd) GetMessageName() string { return "macip_acl_add" } -func (*MacipACLAdd) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*MacipACLAdd) GetCrcString() string { return "b3d3d65a" } +func (*MacipACLAdd) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewMacipACLAdd() api.Message { return &MacipACLAdd{} } // MacipACLAddReply represents the VPP binary API message 'macip_acl_add_reply'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 435: +// Generated from 'acl.api.json', line 435: // // "macip_acl_add_reply", // [ @@ -946,18 +965,18 @@ type MacipACLAddReply struct { func (*MacipACLAddReply) GetMessageName() string { return "macip_acl_add_reply" } -func (*MacipACLAddReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*MacipACLAddReply) GetCrcString() string { return "ac407b0c" } +func (*MacipACLAddReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewMacipACLAddReply() api.Message { return &MacipACLAddReply{} } // MacipACLAddReplace represents the VPP binary API message 'macip_acl_add_replace'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 457: +// Generated from 'acl.api.json', line 457: // // "macip_acl_add_replace", // [ @@ -1005,18 +1024,18 @@ type MacipACLAddReplace struct { func (*MacipACLAddReplace) GetMessageName() string { return "macip_acl_add_replace" } -func (*MacipACLAddReplace) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*MacipACLAddReplace) GetCrcString() string { return "a0e8c01b" } +func (*MacipACLAddReplace) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewMacipACLAddReplace() api.Message { return &MacipACLAddReplace{} } // MacipACLAddReplaceReply represents the VPP binary API message 'macip_acl_add_replace_reply'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 494: +// Generated from 'acl.api.json', line 494: // // "macip_acl_add_replace_reply", // [ @@ -1047,18 +1066,18 @@ type MacipACLAddReplaceReply struct { func (*MacipACLAddReplaceReply) GetMessageName() string { return "macip_acl_add_replace_reply" } -func (*MacipACLAddReplaceReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*MacipACLAddReplaceReply) GetCrcString() string { return "ac407b0c" } +func (*MacipACLAddReplaceReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewMacipACLAddReplaceReply() api.Message { return &MacipACLAddReplaceReply{} } // MacipACLDel represents the VPP binary API message 'macip_acl_del'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 516: +// Generated from 'acl.api.json', line 516: // // "macip_acl_del", // [ @@ -1088,18 +1107,18 @@ type MacipACLDel struct { func (*MacipACLDel) GetMessageName() string { return "macip_acl_del" } -func (*MacipACLDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*MacipACLDel) GetCrcString() string { return "ef34fea4" } +func (*MacipACLDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewMacipACLDel() api.Message { return &MacipACLDel{} } // MacipACLDelReply represents the VPP binary API message 'macip_acl_del_reply'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 538: +// Generated from 'acl.api.json', line 538: // // "macip_acl_del_reply", // [ @@ -1125,18 +1144,18 @@ type MacipACLDelReply struct { func (*MacipACLDelReply) GetMessageName() string { return "macip_acl_del_reply" } -func (*MacipACLDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*MacipACLDelReply) GetCrcString() string { return "e8d4e804" } +func (*MacipACLDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewMacipACLDelReply() api.Message { return &MacipACLDelReply{} } // MacipACLInterfaceAddDel represents the VPP binary API message 'macip_acl_interface_add_del'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 556: +// Generated from 'acl.api.json', line 556: // // "macip_acl_interface_add_del", // [ @@ -1176,18 +1195,18 @@ type MacipACLInterfaceAddDel struct { func (*MacipACLInterfaceAddDel) GetMessageName() string { return "macip_acl_interface_add_del" } -func (*MacipACLInterfaceAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*MacipACLInterfaceAddDel) GetCrcString() string { return "6a6be97c" } +func (*MacipACLInterfaceAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewMacipACLInterfaceAddDel() api.Message { return &MacipACLInterfaceAddDel{} } // MacipACLInterfaceAddDelReply represents the VPP binary API message 'macip_acl_interface_add_del_reply'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 586: +// Generated from 'acl.api.json', line 586: // // "macip_acl_interface_add_del_reply", // [ @@ -1213,18 +1232,18 @@ type MacipACLInterfaceAddDelReply struct { func (*MacipACLInterfaceAddDelReply) GetMessageName() string { return "macip_acl_interface_add_del_reply" } -func (*MacipACLInterfaceAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*MacipACLInterfaceAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*MacipACLInterfaceAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewMacipACLInterfaceAddDelReply() api.Message { return &MacipACLInterfaceAddDelReply{} } // MacipACLDump represents the VPP binary API message 'macip_acl_dump'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 604: +// Generated from 'acl.api.json', line 604: // // "macip_acl_dump", // [ @@ -1254,18 +1273,18 @@ type MacipACLDump struct { func (*MacipACLDump) GetMessageName() string { return "macip_acl_dump" } -func (*MacipACLDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*MacipACLDump) GetCrcString() string { return "ef34fea4" } +func (*MacipACLDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewMacipACLDump() api.Message { return &MacipACLDump{} } // MacipACLDetails represents the VPP binary API message 'macip_acl_details'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 626: +// Generated from 'acl.api.json', line 626: // // "macip_acl_details", // [ @@ -1309,18 +1328,18 @@ type MacipACLDetails struct { func (*MacipACLDetails) GetMessageName() string { return "macip_acl_details" } -func (*MacipACLDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*MacipACLDetails) GetCrcString() string { return "dd2b55ba" } +func (*MacipACLDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewMacipACLDetails() api.Message { return &MacipACLDetails{} } // MacipACLInterfaceGet represents the VPP binary API message 'macip_acl_interface_get'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 659: +// Generated from 'acl.api.json', line 659: // // "macip_acl_interface_get", // [ @@ -1339,24 +1358,23 @@ func NewMacipACLDetails() api.Message { // "crc": "0x51077d14" // } // -type MacipACLInterfaceGet struct { -} +type MacipACLInterfaceGet struct{} func (*MacipACLInterfaceGet) GetMessageName() string { return "macip_acl_interface_get" } -func (*MacipACLInterfaceGet) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*MacipACLInterfaceGet) GetCrcString() string { return "51077d14" } +func (*MacipACLInterfaceGet) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewMacipACLInterfaceGet() api.Message { return &MacipACLInterfaceGet{} } // MacipACLInterfaceGetReply represents the VPP binary API message 'macip_acl_interface_get_reply'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 677: +// Generated from 'acl.api.json', line 677: // // "macip_acl_interface_get_reply", // [ @@ -1389,18 +1407,18 @@ type MacipACLInterfaceGetReply struct { func (*MacipACLInterfaceGetReply) GetMessageName() string { return "macip_acl_interface_get_reply" } -func (*MacipACLInterfaceGetReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*MacipACLInterfaceGetReply) GetCrcString() string { return "accf9b05" } +func (*MacipACLInterfaceGetReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewMacipACLInterfaceGetReply() api.Message { return &MacipACLInterfaceGetReply{} } // MacipACLInterfaceListDump represents the VPP binary API message 'macip_acl_interface_list_dump'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 701: +// Generated from 'acl.api.json', line 701: // // "macip_acl_interface_list_dump", // [ @@ -1430,18 +1448,18 @@ type MacipACLInterfaceListDump struct { func (*MacipACLInterfaceListDump) GetMessageName() string { return "macip_acl_interface_list_dump" } -func (*MacipACLInterfaceListDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*MacipACLInterfaceListDump) GetCrcString() string { return "529cb13f" } +func (*MacipACLInterfaceListDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewMacipACLInterfaceListDump() api.Message { return &MacipACLInterfaceListDump{} } // MacipACLInterfaceListDetails represents the VPP binary API message 'macip_acl_interface_list_details'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 723: +// Generated from 'acl.api.json', line 723: // // "macip_acl_interface_list_details", // [ @@ -1479,18 +1497,18 @@ type MacipACLInterfaceListDetails struct { func (*MacipACLInterfaceListDetails) GetMessageName() string { return "macip_acl_interface_list_details" } -func (*MacipACLInterfaceListDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*MacipACLInterfaceListDetails) GetCrcString() string { return "29783fa0" } +func (*MacipACLInterfaceListDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewMacipACLInterfaceListDetails() api.Message { return &MacipACLInterfaceListDetails{} } // ACLInterfaceSetEtypeWhitelist represents the VPP binary API message 'acl_interface_set_etype_whitelist'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 751: +// Generated from 'acl.api.json', line 751: // // "acl_interface_set_etype_whitelist", // [ @@ -1537,18 +1555,18 @@ type ACLInterfaceSetEtypeWhitelist struct { func (*ACLInterfaceSetEtypeWhitelist) GetMessageName() string { return "acl_interface_set_etype_whitelist" } -func (*ACLInterfaceSetEtypeWhitelist) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ACLInterfaceSetEtypeWhitelist) GetCrcString() string { return "f515efc5" } +func (*ACLInterfaceSetEtypeWhitelist) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewACLInterfaceSetEtypeWhitelist() api.Message { return &ACLInterfaceSetEtypeWhitelist{} } // ACLInterfaceSetEtypeWhitelistReply represents the VPP binary API message 'acl_interface_set_etype_whitelist_reply'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 787: +// Generated from 'acl.api.json', line 787: // // "acl_interface_set_etype_whitelist_reply", // [ @@ -1574,18 +1592,18 @@ type ACLInterfaceSetEtypeWhitelistReply struct { func (*ACLInterfaceSetEtypeWhitelistReply) GetMessageName() string { return "acl_interface_set_etype_whitelist_reply" } -func (*ACLInterfaceSetEtypeWhitelistReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ACLInterfaceSetEtypeWhitelistReply) GetCrcString() string { return "e8d4e804" } +func (*ACLInterfaceSetEtypeWhitelistReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewACLInterfaceSetEtypeWhitelistReply() api.Message { return &ACLInterfaceSetEtypeWhitelistReply{} } // ACLInterfaceEtypeWhitelistDump represents the VPP binary API message 'acl_interface_etype_whitelist_dump'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 805: +// Generated from 'acl.api.json', line 805: // // "acl_interface_etype_whitelist_dump", // [ @@ -1615,18 +1633,18 @@ type ACLInterfaceEtypeWhitelistDump struct { func (*ACLInterfaceEtypeWhitelistDump) GetMessageName() string { return "acl_interface_etype_whitelist_dump" } -func (*ACLInterfaceEtypeWhitelistDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ACLInterfaceEtypeWhitelistDump) GetCrcString() string { return "529cb13f" } +func (*ACLInterfaceEtypeWhitelistDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewACLInterfaceEtypeWhitelistDump() api.Message { return &ACLInterfaceEtypeWhitelistDump{} } // ACLInterfaceEtypeWhitelistDetails represents the VPP binary API message 'acl_interface_etype_whitelist_details'. -// Generated from '/usr/share/vpp/api/acl.api.json', line 827: +// Generated from 'acl.api.json', line 827: // // "acl_interface_etype_whitelist_details", // [ @@ -1669,12 +1687,71 @@ type ACLInterfaceEtypeWhitelistDetails struct { func (*ACLInterfaceEtypeWhitelistDetails) GetMessageName() string { return "acl_interface_etype_whitelist_details" } -func (*ACLInterfaceEtypeWhitelistDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ACLInterfaceEtypeWhitelistDetails) GetCrcString() string { return "6a5d4e81" } +func (*ACLInterfaceEtypeWhitelistDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewACLInterfaceEtypeWhitelistDetails() api.Message { return &ACLInterfaceEtypeWhitelistDetails{} } + +/* Services */ + +type Services interface { + DumpACL(*ACLDump) (*ACLDetails, error) + DumpACLInterfaceEtypeWhitelist(*ACLInterfaceEtypeWhitelistDump) (*ACLInterfaceEtypeWhitelistDetails, error) + DumpACLInterfaceList(*ACLInterfaceListDump) (*ACLInterfaceListDetails, error) + DumpMacipACL(*MacipACLDump) (*MacipACLDetails, error) + DumpMacipACLInterfaceList(*MacipACLInterfaceListDump) (*MacipACLInterfaceListDetails, error) + ACLAddReplace(*ACLAddReplace) (*ACLAddReplaceReply, error) + ACLDel(*ACLDel) (*ACLDelReply, error) + ACLInterfaceAddDel(*ACLInterfaceAddDel) (*ACLInterfaceAddDelReply, error) + ACLInterfaceSetACLList(*ACLInterfaceSetACLList) (*ACLInterfaceSetACLListReply, error) + ACLInterfaceSetEtypeWhitelist(*ACLInterfaceSetEtypeWhitelist) (*ACLInterfaceSetEtypeWhitelistReply, error) + ACLPluginControlPing(*ACLPluginControlPing) (*ACLPluginControlPingReply, error) + ACLPluginGetVersion(*ACLPluginGetVersion) (*ACLPluginGetVersionReply, error) + MacipACLAdd(*MacipACLAdd) (*MacipACLAddReply, error) + MacipACLAddReplace(*MacipACLAddReplace) (*MacipACLAddReplaceReply, error) + MacipACLDel(*MacipACLDel) (*MacipACLDelReply, error) + MacipACLInterfaceAddDel(*MacipACLInterfaceAddDel) (*MacipACLInterfaceAddDelReply, error) + MacipACLInterfaceGet(*MacipACLInterfaceGet) (*MacipACLInterfaceGetReply, error) +} + +func init() { + api.RegisterMessage((*ACLPluginGetVersion)(nil), "acl.ACLPluginGetVersion") + api.RegisterMessage((*ACLPluginGetVersionReply)(nil), "acl.ACLPluginGetVersionReply") + api.RegisterMessage((*ACLPluginControlPing)(nil), "acl.ACLPluginControlPing") + api.RegisterMessage((*ACLPluginControlPingReply)(nil), "acl.ACLPluginControlPingReply") + api.RegisterMessage((*ACLAddReplace)(nil), "acl.ACLAddReplace") + api.RegisterMessage((*ACLAddReplaceReply)(nil), "acl.ACLAddReplaceReply") + api.RegisterMessage((*ACLDel)(nil), "acl.ACLDel") + api.RegisterMessage((*ACLDelReply)(nil), "acl.ACLDelReply") + api.RegisterMessage((*ACLInterfaceAddDel)(nil), "acl.ACLInterfaceAddDel") + api.RegisterMessage((*ACLInterfaceAddDelReply)(nil), "acl.ACLInterfaceAddDelReply") + api.RegisterMessage((*ACLInterfaceSetACLList)(nil), "acl.ACLInterfaceSetACLList") + api.RegisterMessage((*ACLInterfaceSetACLListReply)(nil), "acl.ACLInterfaceSetACLListReply") + api.RegisterMessage((*ACLDump)(nil), "acl.ACLDump") + api.RegisterMessage((*ACLDetails)(nil), "acl.ACLDetails") + api.RegisterMessage((*ACLInterfaceListDump)(nil), "acl.ACLInterfaceListDump") + api.RegisterMessage((*ACLInterfaceListDetails)(nil), "acl.ACLInterfaceListDetails") + api.RegisterMessage((*MacipACLAdd)(nil), "acl.MacipACLAdd") + api.RegisterMessage((*MacipACLAddReply)(nil), "acl.MacipACLAddReply") + api.RegisterMessage((*MacipACLAddReplace)(nil), "acl.MacipACLAddReplace") + api.RegisterMessage((*MacipACLAddReplaceReply)(nil), "acl.MacipACLAddReplaceReply") + api.RegisterMessage((*MacipACLDel)(nil), "acl.MacipACLDel") + api.RegisterMessage((*MacipACLDelReply)(nil), "acl.MacipACLDelReply") + api.RegisterMessage((*MacipACLInterfaceAddDel)(nil), "acl.MacipACLInterfaceAddDel") + api.RegisterMessage((*MacipACLInterfaceAddDelReply)(nil), "acl.MacipACLInterfaceAddDelReply") + api.RegisterMessage((*MacipACLDump)(nil), "acl.MacipACLDump") + api.RegisterMessage((*MacipACLDetails)(nil), "acl.MacipACLDetails") + api.RegisterMessage((*MacipACLInterfaceGet)(nil), "acl.MacipACLInterfaceGet") + api.RegisterMessage((*MacipACLInterfaceGetReply)(nil), "acl.MacipACLInterfaceGetReply") + api.RegisterMessage((*MacipACLInterfaceListDump)(nil), "acl.MacipACLInterfaceListDump") + api.RegisterMessage((*MacipACLInterfaceListDetails)(nil), "acl.MacipACLInterfaceListDetails") + api.RegisterMessage((*ACLInterfaceSetEtypeWhitelist)(nil), "acl.ACLInterfaceSetEtypeWhitelist") + api.RegisterMessage((*ACLInterfaceSetEtypeWhitelistReply)(nil), "acl.ACLInterfaceSetEtypeWhitelistReply") + api.RegisterMessage((*ACLInterfaceEtypeWhitelistDump)(nil), "acl.ACLInterfaceEtypeWhitelistDump") + api.RegisterMessage((*ACLInterfaceEtypeWhitelistDetails)(nil), "acl.ACLInterfaceEtypeWhitelistDetails") +} diff --git a/plugins/vpp/binapi/acl/pkgreflect.go b/plugins/vpp/binapi/acl/pkgreflect.go index f5001d5a22..93a79a71fc 100644 --- a/plugins/vpp/binapi/acl/pkgreflect.go +++ b/plugins/vpp/binapi/acl/pkgreflect.go @@ -41,6 +41,7 @@ var Types = map[string]reflect.Type{ "MacipACLInterfaceListDetails": reflect.TypeOf((*MacipACLInterfaceListDetails)(nil)).Elem(), "MacipACLInterfaceListDump": reflect.TypeOf((*MacipACLInterfaceListDump)(nil)).Elem(), "MacipACLRule": reflect.TypeOf((*MacipACLRule)(nil)).Elem(), + "Services": reflect.TypeOf((*Services)(nil)).Elem(), } var Functions = map[string]reflect.Value{ diff --git a/plugins/vpp/binapi/af_packet/af_packet.go b/plugins/vpp/binapi/af_packet/af_packet.ba.go similarity index 80% rename from plugins/vpp/binapi/af_packet/af_packet.go rename to plugins/vpp/binapi/af_packet/af_packet.ba.go index 0e08c372ac..0255708bd0 100644 --- a/plugins/vpp/binapi/af_packet/af_packet.go +++ b/plugins/vpp/binapi/af_packet/af_packet.ba.go @@ -1,12 +1,30 @@ -// Code generated by govpp binapi-generator DO NOT EDIT. -// Package af_packet represents the VPP binary API of the 'af_packet' VPP module. -// Generated from '/usr/share/vpp/api/af_packet.api.json' +// Code generated by GoVPP binapi-generator. DO NOT EDIT. +// source: /usr/share/vpp/api/af_packet.api.json + +/* +Package af_packet is a generated VPP binary API of the 'af_packet' VPP module. + +It is generated from this file: + af_packet.api.json + +It contains these VPP binary API objects: + 8 messages + 4 services +*/ package af_packet import "git.fd.io/govpp.git/api" +import "github.com/lunixbochs/struc" +import "bytes" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = struc.Pack +var _ = bytes.NewBuffer + +/* Messages */ // AfPacketCreate represents the VPP binary API message 'af_packet_create'. -// Generated from '/usr/share/vpp/api/af_packet.api.json', line 4: +// Generated from 'af_packet.api.json', line 4: // // "af_packet_create", // [ @@ -48,18 +66,18 @@ type AfPacketCreate struct { func (*AfPacketCreate) GetMessageName() string { return "af_packet_create" } -func (*AfPacketCreate) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*AfPacketCreate) GetCrcString() string { return "6d5d30d6" } +func (*AfPacketCreate) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewAfPacketCreate() api.Message { return &AfPacketCreate{} } // AfPacketCreateReply represents the VPP binary API message 'af_packet_create_reply'. -// Generated from '/usr/share/vpp/api/af_packet.api.json', line 36: +// Generated from 'af_packet.api.json', line 36: // // "af_packet_create_reply", // [ @@ -90,18 +108,18 @@ type AfPacketCreateReply struct { func (*AfPacketCreateReply) GetMessageName() string { return "af_packet_create_reply" } -func (*AfPacketCreateReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*AfPacketCreateReply) GetCrcString() string { return "fda5941f" } +func (*AfPacketCreateReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewAfPacketCreateReply() api.Message { return &AfPacketCreateReply{} } // AfPacketDelete represents the VPP binary API message 'af_packet_delete'. -// Generated from '/usr/share/vpp/api/af_packet.api.json', line 58: +// Generated from 'af_packet.api.json', line 58: // // "af_packet_delete", // [ @@ -132,18 +150,18 @@ type AfPacketDelete struct { func (*AfPacketDelete) GetMessageName() string { return "af_packet_delete" } -func (*AfPacketDelete) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*AfPacketDelete) GetCrcString() string { return "3efceda3" } +func (*AfPacketDelete) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewAfPacketDelete() api.Message { return &AfPacketDelete{} } // AfPacketDeleteReply represents the VPP binary API message 'af_packet_delete_reply'. -// Generated from '/usr/share/vpp/api/af_packet.api.json', line 81: +// Generated from 'af_packet.api.json', line 81: // // "af_packet_delete_reply", // [ @@ -169,18 +187,18 @@ type AfPacketDeleteReply struct { func (*AfPacketDeleteReply) GetMessageName() string { return "af_packet_delete_reply" } -func (*AfPacketDeleteReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*AfPacketDeleteReply) GetCrcString() string { return "e8d4e804" } +func (*AfPacketDeleteReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewAfPacketDeleteReply() api.Message { return &AfPacketDeleteReply{} } // AfPacketSetL4CksumOffload represents the VPP binary API message 'af_packet_set_l4_cksum_offload'. -// Generated from '/usr/share/vpp/api/af_packet.api.json', line 99: +// Generated from 'af_packet.api.json', line 99: // // "af_packet_set_l4_cksum_offload", // [ @@ -215,18 +233,18 @@ type AfPacketSetL4CksumOffload struct { func (*AfPacketSetL4CksumOffload) GetMessageName() string { return "af_packet_set_l4_cksum_offload" } -func (*AfPacketSetL4CksumOffload) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*AfPacketSetL4CksumOffload) GetCrcString() string { return "86538585" } +func (*AfPacketSetL4CksumOffload) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewAfPacketSetL4CksumOffload() api.Message { return &AfPacketSetL4CksumOffload{} } // AfPacketSetL4CksumOffloadReply represents the VPP binary API message 'af_packet_set_l4_cksum_offload_reply'. -// Generated from '/usr/share/vpp/api/af_packet.api.json', line 125: +// Generated from 'af_packet.api.json', line 125: // // "af_packet_set_l4_cksum_offload_reply", // [ @@ -252,18 +270,18 @@ type AfPacketSetL4CksumOffloadReply struct { func (*AfPacketSetL4CksumOffloadReply) GetMessageName() string { return "af_packet_set_l4_cksum_offload_reply" } -func (*AfPacketSetL4CksumOffloadReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*AfPacketSetL4CksumOffloadReply) GetCrcString() string { return "e8d4e804" } +func (*AfPacketSetL4CksumOffloadReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewAfPacketSetL4CksumOffloadReply() api.Message { return &AfPacketSetL4CksumOffloadReply{} } // AfPacketDump represents the VPP binary API message 'af_packet_dump'. -// Generated from '/usr/share/vpp/api/af_packet.api.json', line 143: +// Generated from 'af_packet.api.json', line 143: // // "af_packet_dump", // [ @@ -282,24 +300,23 @@ func NewAfPacketSetL4CksumOffloadReply() api.Message { // "crc": "0x51077d14" // } // -type AfPacketDump struct { -} +type AfPacketDump struct{} func (*AfPacketDump) GetMessageName() string { return "af_packet_dump" } -func (*AfPacketDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*AfPacketDump) GetCrcString() string { return "51077d14" } +func (*AfPacketDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewAfPacketDump() api.Message { return &AfPacketDump{} } // AfPacketDetails represents the VPP binary API message 'af_packet_details'. -// Generated from '/usr/share/vpp/api/af_packet.api.json', line 161: +// Generated from 'af_packet.api.json', line 161: // // "af_packet_details", // [ @@ -331,12 +348,32 @@ type AfPacketDetails struct { func (*AfPacketDetails) GetMessageName() string { return "af_packet_details" } -func (*AfPacketDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*AfPacketDetails) GetCrcString() string { return "057205fa" } +func (*AfPacketDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewAfPacketDetails() api.Message { return &AfPacketDetails{} } + +/* Services */ + +type Services interface { + DumpAfPacket(*AfPacketDump) (*AfPacketDetails, error) + AfPacketCreate(*AfPacketCreate) (*AfPacketCreateReply, error) + AfPacketDelete(*AfPacketDelete) (*AfPacketDeleteReply, error) + AfPacketSetL4CksumOffload(*AfPacketSetL4CksumOffload) (*AfPacketSetL4CksumOffloadReply, error) +} + +func init() { + api.RegisterMessage((*AfPacketCreate)(nil), "af_packet.AfPacketCreate") + api.RegisterMessage((*AfPacketCreateReply)(nil), "af_packet.AfPacketCreateReply") + api.RegisterMessage((*AfPacketDelete)(nil), "af_packet.AfPacketDelete") + api.RegisterMessage((*AfPacketDeleteReply)(nil), "af_packet.AfPacketDeleteReply") + api.RegisterMessage((*AfPacketSetL4CksumOffload)(nil), "af_packet.AfPacketSetL4CksumOffload") + api.RegisterMessage((*AfPacketSetL4CksumOffloadReply)(nil), "af_packet.AfPacketSetL4CksumOffloadReply") + api.RegisterMessage((*AfPacketDump)(nil), "af_packet.AfPacketDump") + api.RegisterMessage((*AfPacketDetails)(nil), "af_packet.AfPacketDetails") +} diff --git a/plugins/vpp/binapi/af_packet/pkgreflect.go b/plugins/vpp/binapi/af_packet/pkgreflect.go index 8731b4eaa6..672639d753 100644 --- a/plugins/vpp/binapi/af_packet/pkgreflect.go +++ b/plugins/vpp/binapi/af_packet/pkgreflect.go @@ -13,6 +13,7 @@ var Types = map[string]reflect.Type{ "AfPacketDump": reflect.TypeOf((*AfPacketDump)(nil)).Elem(), "AfPacketSetL4CksumOffload": reflect.TypeOf((*AfPacketSetL4CksumOffload)(nil)).Elem(), "AfPacketSetL4CksumOffloadReply": reflect.TypeOf((*AfPacketSetL4CksumOffloadReply)(nil)).Elem(), + "Services": reflect.TypeOf((*Services)(nil)).Elem(), } var Functions = map[string]reflect.Value{ diff --git a/plugins/vpp/binapi/bfd/bfd.go b/plugins/vpp/binapi/bfd/bfd.ba.go similarity index 85% rename from plugins/vpp/binapi/bfd/bfd.go rename to plugins/vpp/binapi/bfd/bfd.ba.go index 08cc5fc4fd..a52d293692 100644 --- a/plugins/vpp/binapi/bfd/bfd.go +++ b/plugins/vpp/binapi/bfd/bfd.ba.go @@ -1,12 +1,30 @@ -// Code generated by govpp binapi-generator DO NOT EDIT. -// Package bfd represents the VPP binary API of the 'bfd' VPP module. -// Generated from '/usr/share/vpp/api/bfd.api.json' +// Code generated by GoVPP binapi-generator. DO NOT EDIT. +// source: /usr/share/vpp/api/bfd.api.json + +/* +Package bfd is a generated VPP binary API of the 'bfd' VPP module. + +It is generated from this file: + bfd.api.json + +It contains these VPP binary API objects: + 26 messages + 13 services +*/ package bfd import "git.fd.io/govpp.git/api" +import "github.com/lunixbochs/struc" +import "bytes" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = struc.Pack +var _ = bytes.NewBuffer + +/* Messages */ // BfdUDPSetEchoSource represents the VPP binary API message 'bfd_udp_set_echo_source'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 4: +// Generated from 'bfd.api.json', line 4: // // "bfd_udp_set_echo_source", // [ @@ -36,18 +54,18 @@ type BfdUDPSetEchoSource struct { func (*BfdUDPSetEchoSource) GetMessageName() string { return "bfd_udp_set_echo_source" } -func (*BfdUDPSetEchoSource) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*BfdUDPSetEchoSource) GetCrcString() string { return "529cb13f" } +func (*BfdUDPSetEchoSource) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewBfdUDPSetEchoSource() api.Message { return &BfdUDPSetEchoSource{} } // BfdUDPSetEchoSourceReply represents the VPP binary API message 'bfd_udp_set_echo_source_reply'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 26: +// Generated from 'bfd.api.json', line 26: // // "bfd_udp_set_echo_source_reply", // [ @@ -73,18 +91,18 @@ type BfdUDPSetEchoSourceReply struct { func (*BfdUDPSetEchoSourceReply) GetMessageName() string { return "bfd_udp_set_echo_source_reply" } -func (*BfdUDPSetEchoSourceReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*BfdUDPSetEchoSourceReply) GetCrcString() string { return "e8d4e804" } +func (*BfdUDPSetEchoSourceReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewBfdUDPSetEchoSourceReply() api.Message { return &BfdUDPSetEchoSourceReply{} } // BfdUDPDelEchoSource represents the VPP binary API message 'bfd_udp_del_echo_source'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 44: +// Generated from 'bfd.api.json', line 44: // // "bfd_udp_del_echo_source", // [ @@ -103,24 +121,23 @@ func NewBfdUDPSetEchoSourceReply() api.Message { // "crc": "0x51077d14" // } // -type BfdUDPDelEchoSource struct { -} +type BfdUDPDelEchoSource struct{} func (*BfdUDPDelEchoSource) GetMessageName() string { return "bfd_udp_del_echo_source" } -func (*BfdUDPDelEchoSource) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*BfdUDPDelEchoSource) GetCrcString() string { return "51077d14" } +func (*BfdUDPDelEchoSource) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewBfdUDPDelEchoSource() api.Message { return &BfdUDPDelEchoSource{} } // BfdUDPDelEchoSourceReply represents the VPP binary API message 'bfd_udp_del_echo_source_reply'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 62: +// Generated from 'bfd.api.json', line 62: // // "bfd_udp_del_echo_source_reply", // [ @@ -146,18 +163,18 @@ type BfdUDPDelEchoSourceReply struct { func (*BfdUDPDelEchoSourceReply) GetMessageName() string { return "bfd_udp_del_echo_source_reply" } -func (*BfdUDPDelEchoSourceReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*BfdUDPDelEchoSourceReply) GetCrcString() string { return "e8d4e804" } +func (*BfdUDPDelEchoSourceReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewBfdUDPDelEchoSourceReply() api.Message { return &BfdUDPDelEchoSourceReply{} } // BfdUDPAdd represents the VPP binary API message 'bfd_udp_add'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 80: +// Generated from 'bfd.api.json', line 80: // // "bfd_udp_add", // [ @@ -224,7 +241,7 @@ type BfdUDPAdd struct { RequiredMinRx uint32 LocalAddr []byte `struc:"[16]byte"` PeerAddr []byte `struc:"[16]byte"` - IsIpv6 uint8 + IsIPv6 uint8 DetectMult uint8 IsAuthenticated uint8 BfdKeyID uint8 @@ -234,18 +251,18 @@ type BfdUDPAdd struct { func (*BfdUDPAdd) GetMessageName() string { return "bfd_udp_add" } -func (*BfdUDPAdd) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*BfdUDPAdd) GetCrcString() string { return "61cf1850" } +func (*BfdUDPAdd) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewBfdUDPAdd() api.Message { return &BfdUDPAdd{} } // BfdUDPAddReply represents the VPP binary API message 'bfd_udp_add_reply'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 140: +// Generated from 'bfd.api.json', line 140: // // "bfd_udp_add_reply", // [ @@ -271,18 +288,18 @@ type BfdUDPAddReply struct { func (*BfdUDPAddReply) GetMessageName() string { return "bfd_udp_add_reply" } -func (*BfdUDPAddReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*BfdUDPAddReply) GetCrcString() string { return "e8d4e804" } +func (*BfdUDPAddReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewBfdUDPAddReply() api.Message { return &BfdUDPAddReply{} } // BfdUDPMod represents the VPP binary API message 'bfd_udp_mod'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 158: +// Generated from 'bfd.api.json', line 158: // // "bfd_udp_mod", // [ @@ -337,25 +354,25 @@ type BfdUDPMod struct { RequiredMinRx uint32 LocalAddr []byte `struc:"[16]byte"` PeerAddr []byte `struc:"[16]byte"` - IsIpv6 uint8 + IsIPv6 uint8 DetectMult uint8 } func (*BfdUDPMod) GetMessageName() string { return "bfd_udp_mod" } -func (*BfdUDPMod) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*BfdUDPMod) GetCrcString() string { return "6049bf47" } +func (*BfdUDPMod) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewBfdUDPMod() api.Message { return &BfdUDPMod{} } // BfdUDPModReply represents the VPP binary API message 'bfd_udp_mod_reply'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 206: +// Generated from 'bfd.api.json', line 206: // // "bfd_udp_mod_reply", // [ @@ -381,18 +398,18 @@ type BfdUDPModReply struct { func (*BfdUDPModReply) GetMessageName() string { return "bfd_udp_mod_reply" } -func (*BfdUDPModReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*BfdUDPModReply) GetCrcString() string { return "e8d4e804" } +func (*BfdUDPModReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewBfdUDPModReply() api.Message { return &BfdUDPModReply{} } // BfdUDPDel represents the VPP binary API message 'bfd_udp_del'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 224: +// Generated from 'bfd.api.json', line 224: // // "bfd_udp_del", // [ @@ -433,24 +450,24 @@ type BfdUDPDel struct { SwIfIndex uint32 LocalAddr []byte `struc:"[16]byte"` PeerAddr []byte `struc:"[16]byte"` - IsIpv6 uint8 + IsIPv6 uint8 } func (*BfdUDPDel) GetMessageName() string { return "bfd_udp_del" } -func (*BfdUDPDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*BfdUDPDel) GetCrcString() string { return "c9e9cc5a" } +func (*BfdUDPDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewBfdUDPDel() api.Message { return &BfdUDPDel{} } // BfdUDPDelReply represents the VPP binary API message 'bfd_udp_del_reply'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 260: +// Generated from 'bfd.api.json', line 260: // // "bfd_udp_del_reply", // [ @@ -476,18 +493,18 @@ type BfdUDPDelReply struct { func (*BfdUDPDelReply) GetMessageName() string { return "bfd_udp_del_reply" } -func (*BfdUDPDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*BfdUDPDelReply) GetCrcString() string { return "e8d4e804" } +func (*BfdUDPDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewBfdUDPDelReply() api.Message { return &BfdUDPDelReply{} } // BfdUDPSessionDump represents the VPP binary API message 'bfd_udp_session_dump'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 278: +// Generated from 'bfd.api.json', line 278: // // "bfd_udp_session_dump", // [ @@ -506,24 +523,23 @@ func NewBfdUDPDelReply() api.Message { // "crc": "0x51077d14" // } // -type BfdUDPSessionDump struct { -} +type BfdUDPSessionDump struct{} func (*BfdUDPSessionDump) GetMessageName() string { return "bfd_udp_session_dump" } -func (*BfdUDPSessionDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*BfdUDPSessionDump) GetCrcString() string { return "51077d14" } +func (*BfdUDPSessionDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewBfdUDPSessionDump() api.Message { return &BfdUDPSessionDump{} } // BfdUDPSessionDetails represents the VPP binary API message 'bfd_udp_session_details'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 296: +// Generated from 'bfd.api.json', line 296: // // "bfd_udp_session_details", // [ @@ -588,7 +604,7 @@ type BfdUDPSessionDetails struct { SwIfIndex uint32 LocalAddr []byte `struc:"[16]byte"` PeerAddr []byte `struc:"[16]byte"` - IsIpv6 uint8 + IsIPv6 uint8 State uint8 IsAuthenticated uint8 BfdKeyID uint8 @@ -601,18 +617,18 @@ type BfdUDPSessionDetails struct { func (*BfdUDPSessionDetails) GetMessageName() string { return "bfd_udp_session_details" } -func (*BfdUDPSessionDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*BfdUDPSessionDetails) GetCrcString() string { return "837bb0ed" } +func (*BfdUDPSessionDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewBfdUDPSessionDetails() api.Message { return &BfdUDPSessionDetails{} } // BfdUDPSessionSetFlags represents the VPP binary API message 'bfd_udp_session_set_flags'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 356: +// Generated from 'bfd.api.json', line 356: // // "bfd_udp_session_set_flags", // [ @@ -657,25 +673,25 @@ type BfdUDPSessionSetFlags struct { SwIfIndex uint32 LocalAddr []byte `struc:"[16]byte"` PeerAddr []byte `struc:"[16]byte"` - IsIpv6 uint8 + IsIPv6 uint8 AdminUpDown uint8 } func (*BfdUDPSessionSetFlags) GetMessageName() string { return "bfd_udp_session_set_flags" } -func (*BfdUDPSessionSetFlags) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*BfdUDPSessionSetFlags) GetCrcString() string { return "667d6e7c" } +func (*BfdUDPSessionSetFlags) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewBfdUDPSessionSetFlags() api.Message { return &BfdUDPSessionSetFlags{} } // BfdUDPSessionSetFlagsReply represents the VPP binary API message 'bfd_udp_session_set_flags_reply'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 396: +// Generated from 'bfd.api.json', line 396: // // "bfd_udp_session_set_flags_reply", // [ @@ -701,18 +717,18 @@ type BfdUDPSessionSetFlagsReply struct { func (*BfdUDPSessionSetFlagsReply) GetMessageName() string { return "bfd_udp_session_set_flags_reply" } -func (*BfdUDPSessionSetFlagsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*BfdUDPSessionSetFlagsReply) GetCrcString() string { return "e8d4e804" } +func (*BfdUDPSessionSetFlagsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewBfdUDPSessionSetFlagsReply() api.Message { return &BfdUDPSessionSetFlagsReply{} } // WantBfdEvents represents the VPP binary API message 'want_bfd_events'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 414: +// Generated from 'bfd.api.json', line 414: // // "want_bfd_events", // [ @@ -741,24 +757,24 @@ func NewBfdUDPSessionSetFlagsReply() api.Message { // type WantBfdEvents struct { EnableDisable uint32 - Pid uint32 + PID uint32 } func (*WantBfdEvents) GetMessageName() string { return "want_bfd_events" } -func (*WantBfdEvents) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*WantBfdEvents) GetCrcString() string { return "476f5a08" } +func (*WantBfdEvents) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewWantBfdEvents() api.Message { return &WantBfdEvents{} } // WantBfdEventsReply represents the VPP binary API message 'want_bfd_events_reply'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 440: +// Generated from 'bfd.api.json', line 440: // // "want_bfd_events_reply", // [ @@ -784,18 +800,18 @@ type WantBfdEventsReply struct { func (*WantBfdEventsReply) GetMessageName() string { return "want_bfd_events_reply" } -func (*WantBfdEventsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*WantBfdEventsReply) GetCrcString() string { return "e8d4e804" } +func (*WantBfdEventsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewWantBfdEventsReply() api.Message { return &WantBfdEventsReply{} } // BfdAuthSetKey represents the VPP binary API message 'bfd_auth_set_key'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 458: +// Generated from 'bfd.api.json', line 458: // // "bfd_auth_set_key", // [ @@ -841,18 +857,18 @@ type BfdAuthSetKey struct { func (*BfdAuthSetKey) GetMessageName() string { return "bfd_auth_set_key" } -func (*BfdAuthSetKey) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*BfdAuthSetKey) GetCrcString() string { return "690b8877" } +func (*BfdAuthSetKey) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewBfdAuthSetKey() api.Message { return &BfdAuthSetKey{} } // BfdAuthSetKeyReply represents the VPP binary API message 'bfd_auth_set_key_reply'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 493: +// Generated from 'bfd.api.json', line 493: // // "bfd_auth_set_key_reply", // [ @@ -878,18 +894,18 @@ type BfdAuthSetKeyReply struct { func (*BfdAuthSetKeyReply) GetMessageName() string { return "bfd_auth_set_key_reply" } -func (*BfdAuthSetKeyReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*BfdAuthSetKeyReply) GetCrcString() string { return "e8d4e804" } +func (*BfdAuthSetKeyReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewBfdAuthSetKeyReply() api.Message { return &BfdAuthSetKeyReply{} } // BfdAuthDelKey represents the VPP binary API message 'bfd_auth_del_key'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 511: +// Generated from 'bfd.api.json', line 511: // // "bfd_auth_del_key", // [ @@ -919,18 +935,18 @@ type BfdAuthDelKey struct { func (*BfdAuthDelKey) GetMessageName() string { return "bfd_auth_del_key" } -func (*BfdAuthDelKey) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*BfdAuthDelKey) GetCrcString() string { return "65310b22" } +func (*BfdAuthDelKey) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewBfdAuthDelKey() api.Message { return &BfdAuthDelKey{} } // BfdAuthDelKeyReply represents the VPP binary API message 'bfd_auth_del_key_reply'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 533: +// Generated from 'bfd.api.json', line 533: // // "bfd_auth_del_key_reply", // [ @@ -956,18 +972,18 @@ type BfdAuthDelKeyReply struct { func (*BfdAuthDelKeyReply) GetMessageName() string { return "bfd_auth_del_key_reply" } -func (*BfdAuthDelKeyReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*BfdAuthDelKeyReply) GetCrcString() string { return "e8d4e804" } +func (*BfdAuthDelKeyReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewBfdAuthDelKeyReply() api.Message { return &BfdAuthDelKeyReply{} } // BfdAuthKeysDump represents the VPP binary API message 'bfd_auth_keys_dump'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 551: +// Generated from 'bfd.api.json', line 551: // // "bfd_auth_keys_dump", // [ @@ -986,24 +1002,23 @@ func NewBfdAuthDelKeyReply() api.Message { // "crc": "0x51077d14" // } // -type BfdAuthKeysDump struct { -} +type BfdAuthKeysDump struct{} func (*BfdAuthKeysDump) GetMessageName() string { return "bfd_auth_keys_dump" } -func (*BfdAuthKeysDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*BfdAuthKeysDump) GetCrcString() string { return "51077d14" } +func (*BfdAuthKeysDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewBfdAuthKeysDump() api.Message { return &BfdAuthKeysDump{} } // BfdAuthKeysDetails represents the VPP binary API message 'bfd_auth_keys_details'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 569: +// Generated from 'bfd.api.json', line 569: // // "bfd_auth_keys_details", // [ @@ -1039,18 +1054,18 @@ type BfdAuthKeysDetails struct { func (*BfdAuthKeysDetails) GetMessageName() string { return "bfd_auth_keys_details" } -func (*BfdAuthKeysDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*BfdAuthKeysDetails) GetCrcString() string { return "84130e9f" } +func (*BfdAuthKeysDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewBfdAuthKeysDetails() api.Message { return &BfdAuthKeysDetails{} } // BfdUDPAuthActivate represents the VPP binary API message 'bfd_udp_auth_activate'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 595: +// Generated from 'bfd.api.json', line 595: // // "bfd_udp_auth_activate", // [ @@ -1103,7 +1118,7 @@ type BfdUDPAuthActivate struct { SwIfIndex uint32 LocalAddr []byte `struc:"[16]byte"` PeerAddr []byte `struc:"[16]byte"` - IsIpv6 uint8 + IsIPv6 uint8 IsDelayed uint8 BfdKeyID uint8 ConfKeyID uint32 @@ -1112,18 +1127,18 @@ type BfdUDPAuthActivate struct { func (*BfdUDPAuthActivate) GetMessageName() string { return "bfd_udp_auth_activate" } -func (*BfdUDPAuthActivate) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*BfdUDPAuthActivate) GetCrcString() string { return "1bae0947" } +func (*BfdUDPAuthActivate) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewBfdUDPAuthActivate() api.Message { return &BfdUDPAuthActivate{} } // BfdUDPAuthActivateReply represents the VPP binary API message 'bfd_udp_auth_activate_reply'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 643: +// Generated from 'bfd.api.json', line 643: // // "bfd_udp_auth_activate_reply", // [ @@ -1149,18 +1164,18 @@ type BfdUDPAuthActivateReply struct { func (*BfdUDPAuthActivateReply) GetMessageName() string { return "bfd_udp_auth_activate_reply" } -func (*BfdUDPAuthActivateReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*BfdUDPAuthActivateReply) GetCrcString() string { return "e8d4e804" } +func (*BfdUDPAuthActivateReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewBfdUDPAuthActivateReply() api.Message { return &BfdUDPAuthActivateReply{} } // BfdUDPAuthDeactivate represents the VPP binary API message 'bfd_udp_auth_deactivate'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 661: +// Generated from 'bfd.api.json', line 661: // // "bfd_udp_auth_deactivate", // [ @@ -1205,25 +1220,25 @@ type BfdUDPAuthDeactivate struct { SwIfIndex uint32 LocalAddr []byte `struc:"[16]byte"` PeerAddr []byte `struc:"[16]byte"` - IsIpv6 uint8 + IsIPv6 uint8 IsDelayed uint8 } func (*BfdUDPAuthDeactivate) GetMessageName() string { return "bfd_udp_auth_deactivate" } -func (*BfdUDPAuthDeactivate) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*BfdUDPAuthDeactivate) GetCrcString() string { return "10661991" } +func (*BfdUDPAuthDeactivate) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewBfdUDPAuthDeactivate() api.Message { return &BfdUDPAuthDeactivate{} } // BfdUDPAuthDeactivateReply represents the VPP binary API message 'bfd_udp_auth_deactivate_reply'. -// Generated from '/usr/share/vpp/api/bfd.api.json', line 701: +// Generated from 'bfd.api.json', line 701: // // "bfd_udp_auth_deactivate_reply", // [ @@ -1249,12 +1264,59 @@ type BfdUDPAuthDeactivateReply struct { func (*BfdUDPAuthDeactivateReply) GetMessageName() string { return "bfd_udp_auth_deactivate_reply" } -func (*BfdUDPAuthDeactivateReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*BfdUDPAuthDeactivateReply) GetCrcString() string { return "e8d4e804" } +func (*BfdUDPAuthDeactivateReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewBfdUDPAuthDeactivateReply() api.Message { return &BfdUDPAuthDeactivateReply{} } + +/* Services */ + +type Services interface { + DumpBfdAuthKeys(*BfdAuthKeysDump) (*BfdAuthKeysDetails, error) + DumpBfdUDPSession(*BfdUDPSessionDump) (*BfdUDPSessionDetails, error) + BfdAuthDelKey(*BfdAuthDelKey) (*BfdAuthDelKeyReply, error) + BfdAuthSetKey(*BfdAuthSetKey) (*BfdAuthSetKeyReply, error) + BfdUDPAdd(*BfdUDPAdd) (*BfdUDPAddReply, error) + BfdUDPAuthActivate(*BfdUDPAuthActivate) (*BfdUDPAuthActivateReply, error) + BfdUDPAuthDeactivate(*BfdUDPAuthDeactivate) (*BfdUDPAuthDeactivateReply, error) + BfdUDPDel(*BfdUDPDel) (*BfdUDPDelReply, error) + BfdUDPDelEchoSource(*BfdUDPDelEchoSource) (*BfdUDPDelEchoSourceReply, error) + BfdUDPMod(*BfdUDPMod) (*BfdUDPModReply, error) + BfdUDPSessionSetFlags(*BfdUDPSessionSetFlags) (*BfdUDPSessionSetFlagsReply, error) + BfdUDPSetEchoSource(*BfdUDPSetEchoSource) (*BfdUDPSetEchoSourceReply, error) + WantBfdEvents(*WantBfdEvents) (*WantBfdEventsReply, error) +} + +func init() { + api.RegisterMessage((*BfdUDPSetEchoSource)(nil), "bfd.BfdUDPSetEchoSource") + api.RegisterMessage((*BfdUDPSetEchoSourceReply)(nil), "bfd.BfdUDPSetEchoSourceReply") + api.RegisterMessage((*BfdUDPDelEchoSource)(nil), "bfd.BfdUDPDelEchoSource") + api.RegisterMessage((*BfdUDPDelEchoSourceReply)(nil), "bfd.BfdUDPDelEchoSourceReply") + api.RegisterMessage((*BfdUDPAdd)(nil), "bfd.BfdUDPAdd") + api.RegisterMessage((*BfdUDPAddReply)(nil), "bfd.BfdUDPAddReply") + api.RegisterMessage((*BfdUDPMod)(nil), "bfd.BfdUDPMod") + api.RegisterMessage((*BfdUDPModReply)(nil), "bfd.BfdUDPModReply") + api.RegisterMessage((*BfdUDPDel)(nil), "bfd.BfdUDPDel") + api.RegisterMessage((*BfdUDPDelReply)(nil), "bfd.BfdUDPDelReply") + api.RegisterMessage((*BfdUDPSessionDump)(nil), "bfd.BfdUDPSessionDump") + api.RegisterMessage((*BfdUDPSessionDetails)(nil), "bfd.BfdUDPSessionDetails") + api.RegisterMessage((*BfdUDPSessionSetFlags)(nil), "bfd.BfdUDPSessionSetFlags") + api.RegisterMessage((*BfdUDPSessionSetFlagsReply)(nil), "bfd.BfdUDPSessionSetFlagsReply") + api.RegisterMessage((*WantBfdEvents)(nil), "bfd.WantBfdEvents") + api.RegisterMessage((*WantBfdEventsReply)(nil), "bfd.WantBfdEventsReply") + api.RegisterMessage((*BfdAuthSetKey)(nil), "bfd.BfdAuthSetKey") + api.RegisterMessage((*BfdAuthSetKeyReply)(nil), "bfd.BfdAuthSetKeyReply") + api.RegisterMessage((*BfdAuthDelKey)(nil), "bfd.BfdAuthDelKey") + api.RegisterMessage((*BfdAuthDelKeyReply)(nil), "bfd.BfdAuthDelKeyReply") + api.RegisterMessage((*BfdAuthKeysDump)(nil), "bfd.BfdAuthKeysDump") + api.RegisterMessage((*BfdAuthKeysDetails)(nil), "bfd.BfdAuthKeysDetails") + api.RegisterMessage((*BfdUDPAuthActivate)(nil), "bfd.BfdUDPAuthActivate") + api.RegisterMessage((*BfdUDPAuthActivateReply)(nil), "bfd.BfdUDPAuthActivateReply") + api.RegisterMessage((*BfdUDPAuthDeactivate)(nil), "bfd.BfdUDPAuthDeactivate") + api.RegisterMessage((*BfdUDPAuthDeactivateReply)(nil), "bfd.BfdUDPAuthDeactivateReply") +} diff --git a/plugins/vpp/binapi/bfd/pkgreflect.go b/plugins/vpp/binapi/bfd/pkgreflect.go index 954b650d1c..4d70693065 100644 --- a/plugins/vpp/binapi/bfd/pkgreflect.go +++ b/plugins/vpp/binapi/bfd/pkgreflect.go @@ -29,6 +29,7 @@ var Types = map[string]reflect.Type{ "BfdUDPSessionSetFlagsReply": reflect.TypeOf((*BfdUDPSessionSetFlagsReply)(nil)).Elem(), "BfdUDPSetEchoSource": reflect.TypeOf((*BfdUDPSetEchoSource)(nil)).Elem(), "BfdUDPSetEchoSourceReply": reflect.TypeOf((*BfdUDPSetEchoSourceReply)(nil)).Elem(), + "Services": reflect.TypeOf((*Services)(nil)).Elem(), "WantBfdEvents": reflect.TypeOf((*WantBfdEvents)(nil)).Elem(), "WantBfdEventsReply": reflect.TypeOf((*WantBfdEventsReply)(nil)).Elem(), } diff --git a/plugins/vpp/binapi/dhcp/dhcp.ba.go b/plugins/vpp/binapi/dhcp/dhcp.ba.go new file mode 100644 index 0000000000..7726cce201 --- /dev/null +++ b/plugins/vpp/binapi/dhcp/dhcp.ba.go @@ -0,0 +1,1594 @@ +// Code generated by GoVPP binapi-generator. DO NOT EDIT. +// source: /usr/share/vpp/api/dhcp.api.json + +/* +Package dhcp is a generated VPP binary API of the 'dhcp' VPP module. + +It is generated from this file: + dhcp.api.json + +It contains these VPP binary API objects: + 25 messages + 5 types + 11 services +*/ +package dhcp + +import "git.fd.io/govpp.git/api" +import "github.com/lunixbochs/struc" +import "bytes" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = struc.Pack +var _ = bytes.NewBuffer + +/* Types */ + +// DHCPClient represents the VPP binary API type 'dhcp_client'. +// Generated from 'dhcp.api.json', line 825: +// +// "dhcp_client", +// [ +// "u32", +// "sw_if_index" +// ], +// [ +// "u8", +// "hostname", +// 64 +// ], +// [ +// "u8", +// "id", +// 64 +// ], +// [ +// "u8", +// "want_dhcp_event" +// ], +// [ +// "u8", +// "set_broadcast_flag" +// ], +// [ +// "u32", +// "pid" +// ], +// { +// "crc": "0x527f7935" +// } +// +type DHCPClient struct { + SwIfIndex uint32 + Hostname []byte `struc:"[64]byte"` + ID []byte `struc:"[64]byte"` + WantDHCPEvent uint8 + SetBroadcastFlag uint8 + PID uint32 +} + +func (*DHCPClient) GetTypeName() string { + return "dhcp_client" +} +func (*DHCPClient) GetCrcString() string { + return "527f7935" +} + +// DHCPLease represents the VPP binary API type 'dhcp_lease'. +// Generated from 'dhcp.api.json', line 857: +// +// "dhcp_lease", +// [ +// "u32", +// "sw_if_index" +// ], +// [ +// "u8", +// "state" +// ], +// [ +// "u8", +// "hostname", +// 64 +// ], +// [ +// "u8", +// "is_ipv6" +// ], +// [ +// "u8", +// "mask_width" +// ], +// [ +// "u8", +// "host_address", +// 16 +// ], +// [ +// "u8", +// "router_address", +// 16 +// ], +// [ +// "u8", +// "host_mac", +// 6 +// ], +// { +// "crc": "0x61090276" +// } +// +type DHCPLease struct { + SwIfIndex uint32 + State uint8 + Hostname []byte `struc:"[64]byte"` + IsIPv6 uint8 + MaskWidth uint8 + HostAddress []byte `struc:"[16]byte"` + RouterAddress []byte `struc:"[16]byte"` + HostMac []byte `struc:"[6]byte"` +} + +func (*DHCPLease) GetTypeName() string { + return "dhcp_lease" +} +func (*DHCPLease) GetCrcString() string { + return "61090276" +} + +// DHCPServer represents the VPP binary API type 'dhcp_server'. +// Generated from 'dhcp.api.json', line 899: +// +// "dhcp_server", +// [ +// "u32", +// "server_vrf_id" +// ], +// [ +// "u8", +// "dhcp_server", +// 16 +// ], +// { +// "crc": "0xf16506c4" +// } +// +type DHCPServer struct { + ServerVrfID uint32 + DHCPServer []byte `struc:"[16]byte"` +} + +func (*DHCPServer) GetTypeName() string { + return "dhcp_server" +} +func (*DHCPServer) GetCrcString() string { + return "f16506c4" +} + +// DHCP6AddressInfo represents the VPP binary API type 'dhcp6_address_info'. +// Generated from 'dhcp.api.json', line 914: +// +// "dhcp6_address_info", +// [ +// "u8", +// "address", +// 16 +// ], +// [ +// "u32", +// "valid_time" +// ], +// [ +// "u32", +// "preferred_time" +// ], +// { +// "crc": "0xf3d501e2" +// } +// +type DHCP6AddressInfo struct { + Address []byte `struc:"[16]byte"` + ValidTime uint32 + PreferredTime uint32 +} + +func (*DHCP6AddressInfo) GetTypeName() string { + return "dhcp6_address_info" +} +func (*DHCP6AddressInfo) GetCrcString() string { + return "f3d501e2" +} + +// DHCP6PdPrefixInfo represents the VPP binary API type 'dhcp6_pd_prefix_info'. +// Generated from 'dhcp.api.json', line 933: +// +// "dhcp6_pd_prefix_info", +// [ +// "u8", +// "prefix", +// 16 +// ], +// [ +// "u8", +// "prefix_length" +// ], +// [ +// "u32", +// "valid_time" +// ], +// [ +// "u32", +// "preferred_time" +// ], +// { +// "crc": "0xc459690e" +// } +// +type DHCP6PdPrefixInfo struct { + Prefix []byte `struc:"[16]byte"` + PrefixLength uint8 + ValidTime uint32 + PreferredTime uint32 +} + +func (*DHCP6PdPrefixInfo) GetTypeName() string { + return "dhcp6_pd_prefix_info" +} +func (*DHCP6PdPrefixInfo) GetCrcString() string { + return "c459690e" +} + +/* Messages */ + +// DHCPProxyConfig represents the VPP binary API message 'dhcp_proxy_config'. +// Generated from 'dhcp.api.json', line 4: +// +// "dhcp_proxy_config", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "client_index" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "u32", +// "rx_vrf_id" +// ], +// [ +// "u32", +// "server_vrf_id" +// ], +// [ +// "u8", +// "is_ipv6" +// ], +// [ +// "u8", +// "is_add" +// ], +// [ +// "u8", +// "dhcp_server", +// 16 +// ], +// [ +// "u8", +// "dhcp_src_address", +// 16 +// ], +// { +// "crc": "0x6af4b645" +// } +// +type DHCPProxyConfig struct { + RxVrfID uint32 + ServerVrfID uint32 + IsIPv6 uint8 + IsAdd uint8 + DHCPServer []byte `struc:"[16]byte"` + DHCPSrcAddress []byte `struc:"[16]byte"` +} + +func (*DHCPProxyConfig) GetMessageName() string { + return "dhcp_proxy_config" +} +func (*DHCPProxyConfig) GetCrcString() string { + return "6af4b645" +} +func (*DHCPProxyConfig) GetMessageType() api.MessageType { + return api.RequestMessage +} +func NewDHCPProxyConfig() api.Message { + return &DHCPProxyConfig{} +} + +// DHCPProxyConfigReply represents the VPP binary API message 'dhcp_proxy_config_reply'. +// Generated from 'dhcp.api.json', line 48: +// +// "dhcp_proxy_config_reply", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "i32", +// "retval" +// ], +// { +// "crc": "0xe8d4e804" +// } +// +type DHCPProxyConfigReply struct { + Retval int32 +} + +func (*DHCPProxyConfigReply) GetMessageName() string { + return "dhcp_proxy_config_reply" +} +func (*DHCPProxyConfigReply) GetCrcString() string { + return "e8d4e804" +} +func (*DHCPProxyConfigReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} +func NewDHCPProxyConfigReply() api.Message { + return &DHCPProxyConfigReply{} +} + +// DHCPProxySetVss represents the VPP binary API message 'dhcp_proxy_set_vss'. +// Generated from 'dhcp.api.json', line 66: +// +// "dhcp_proxy_set_vss", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "client_index" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "u32", +// "tbl_id" +// ], +// [ +// "u8", +// "vss_type" +// ], +// [ +// "u8", +// "vpn_ascii_id", +// 129 +// ], +// [ +// "u32", +// "oui" +// ], +// [ +// "u32", +// "vpn_index" +// ], +// [ +// "u8", +// "is_ipv6" +// ], +// [ +// "u8", +// "is_add" +// ], +// { +// "crc": "0x606535aa" +// } +// +type DHCPProxySetVss struct { + TblID uint32 + VssType uint8 + VPNAsciiID []byte `struc:"[129]byte"` + Oui uint32 + VPNIndex uint32 + IsIPv6 uint8 + IsAdd uint8 +} + +func (*DHCPProxySetVss) GetMessageName() string { + return "dhcp_proxy_set_vss" +} +func (*DHCPProxySetVss) GetCrcString() string { + return "606535aa" +} +func (*DHCPProxySetVss) GetMessageType() api.MessageType { + return api.RequestMessage +} +func NewDHCPProxySetVss() api.Message { + return &DHCPProxySetVss{} +} + +// DHCPProxySetVssReply represents the VPP binary API message 'dhcp_proxy_set_vss_reply'. +// Generated from 'dhcp.api.json', line 113: +// +// "dhcp_proxy_set_vss_reply", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "i32", +// "retval" +// ], +// { +// "crc": "0xe8d4e804" +// } +// +type DHCPProxySetVssReply struct { + Retval int32 +} + +func (*DHCPProxySetVssReply) GetMessageName() string { + return "dhcp_proxy_set_vss_reply" +} +func (*DHCPProxySetVssReply) GetCrcString() string { + return "e8d4e804" +} +func (*DHCPProxySetVssReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} +func NewDHCPProxySetVssReply() api.Message { + return &DHCPProxySetVssReply{} +} + +// DHCPClientConfig represents the VPP binary API message 'dhcp_client_config'. +// Generated from 'dhcp.api.json', line 131: +// +// "dhcp_client_config", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "client_index" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "u8", +// "is_add" +// ], +// [ +// "vl_api_dhcp_client_t", +// "client" +// ], +// { +// "crc": "0xc32ccdfe" +// } +// +type DHCPClientConfig struct { + IsAdd uint8 + Client DHCPClient +} + +func (*DHCPClientConfig) GetMessageName() string { + return "dhcp_client_config" +} +func (*DHCPClientConfig) GetCrcString() string { + return "c32ccdfe" +} +func (*DHCPClientConfig) GetMessageType() api.MessageType { + return api.RequestMessage +} +func NewDHCPClientConfig() api.Message { + return &DHCPClientConfig{} +} + +// DHCPClientConfigReply represents the VPP binary API message 'dhcp_client_config_reply'. +// Generated from 'dhcp.api.json', line 157: +// +// "dhcp_client_config_reply", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "i32", +// "retval" +// ], +// { +// "crc": "0xe8d4e804" +// } +// +type DHCPClientConfigReply struct { + Retval int32 +} + +func (*DHCPClientConfigReply) GetMessageName() string { + return "dhcp_client_config_reply" +} +func (*DHCPClientConfigReply) GetCrcString() string { + return "e8d4e804" +} +func (*DHCPClientConfigReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} +func NewDHCPClientConfigReply() api.Message { + return &DHCPClientConfigReply{} +} + +// DHCPComplEvent represents the VPP binary API message 'dhcp_compl_event'. +// Generated from 'dhcp.api.json', line 175: +// +// "dhcp_compl_event", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "client_index" +// ], +// [ +// "u32", +// "pid" +// ], +// [ +// "vl_api_dhcp_lease_t", +// "lease" +// ], +// { +// "crc": "0x2105c31b" +// } +// +type DHCPComplEvent struct { + PID uint32 + Lease DHCPLease +} + +func (*DHCPComplEvent) GetMessageName() string { + return "dhcp_compl_event" +} +func (*DHCPComplEvent) GetCrcString() string { + return "2105c31b" +} +func (*DHCPComplEvent) GetMessageType() api.MessageType { + return api.EventMessage +} +func NewDHCPComplEvent() api.Message { + return &DHCPComplEvent{} +} + +// DHCPClientDump represents the VPP binary API message 'dhcp_client_dump'. +// Generated from 'dhcp.api.json', line 197: +// +// "dhcp_client_dump", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "client_index" +// ], +// [ +// "u32", +// "context" +// ], +// { +// "crc": "0x51077d14" +// } +// +type DHCPClientDump struct{} + +func (*DHCPClientDump) GetMessageName() string { + return "dhcp_client_dump" +} +func (*DHCPClientDump) GetCrcString() string { + return "51077d14" +} +func (*DHCPClientDump) GetMessageType() api.MessageType { + return api.RequestMessage +} +func NewDHCPClientDump() api.Message { + return &DHCPClientDump{} +} + +// DHCPClientDetails represents the VPP binary API message 'dhcp_client_details'. +// Generated from 'dhcp.api.json', line 215: +// +// "dhcp_client_details", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "vl_api_dhcp_client_t", +// "client" +// ], +// [ +// "vl_api_dhcp_lease_t", +// "lease" +// ], +// { +// "crc": "0x7ea3a745" +// } +// +type DHCPClientDetails struct { + Client DHCPClient + Lease DHCPLease +} + +func (*DHCPClientDetails) GetMessageName() string { + return "dhcp_client_details" +} +func (*DHCPClientDetails) GetCrcString() string { + return "7ea3a745" +} +func (*DHCPClientDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} +func NewDHCPClientDetails() api.Message { + return &DHCPClientDetails{} +} + +// DHCPProxyDump represents the VPP binary API message 'dhcp_proxy_dump'. +// Generated from 'dhcp.api.json', line 237: +// +// "dhcp_proxy_dump", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "client_index" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "u8", +// "is_ip6" +// ], +// { +// "crc": "0x6fe91190" +// } +// +type DHCPProxyDump struct { + IsIP6 uint8 +} + +func (*DHCPProxyDump) GetMessageName() string { + return "dhcp_proxy_dump" +} +func (*DHCPProxyDump) GetCrcString() string { + return "6fe91190" +} +func (*DHCPProxyDump) GetMessageType() api.MessageType { + return api.RequestMessage +} +func NewDHCPProxyDump() api.Message { + return &DHCPProxyDump{} +} + +// DHCPProxyDetails represents the VPP binary API message 'dhcp_proxy_details'. +// Generated from 'dhcp.api.json', line 259: +// +// "dhcp_proxy_details", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "u32", +// "rx_vrf_id" +// ], +// [ +// "u32", +// "vss_oui" +// ], +// [ +// "u32", +// "vss_fib_id" +// ], +// [ +// "u8", +// "vss_type" +// ], +// [ +// "u8", +// "vss_vpn_ascii_id", +// 129 +// ], +// [ +// "u8", +// "is_ipv6" +// ], +// [ +// "u8", +// "dhcp_src_address", +// 16 +// ], +// [ +// "u8", +// "count" +// ], +// [ +// "vl_api_dhcp_server_t", +// "servers", +// 0, +// "count" +// ], +// { +// "crc": "0xa5f2ad84" +// } +// +type DHCPProxyDetails struct { + RxVrfID uint32 + VssOui uint32 + VssFibID uint32 + VssType uint8 + VssVPNAsciiID []byte `struc:"[129]byte"` + IsIPv6 uint8 + DHCPSrcAddress []byte `struc:"[16]byte"` + Count uint8 `struc:"sizeof=Servers"` + Servers []DHCPServer +} + +func (*DHCPProxyDetails) GetMessageName() string { + return "dhcp_proxy_details" +} +func (*DHCPProxyDetails) GetCrcString() string { + return "a5f2ad84" +} +func (*DHCPProxyDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} +func NewDHCPProxyDetails() api.Message { + return &DHCPProxyDetails{} +} + +// DHCP6DuidLlSet represents the VPP binary API message 'dhcp6_duid_ll_set'. +// Generated from 'dhcp.api.json', line 313: +// +// "dhcp6_duid_ll_set", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "client_index" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "u8", +// "duid_ll", +// 10 +// ], +// { +// "crc": "0x0f6ca323" +// } +// +type DHCP6DuidLlSet struct { + DuidLl []byte `struc:"[10]byte"` +} + +func (*DHCP6DuidLlSet) GetMessageName() string { + return "dhcp6_duid_ll_set" +} +func (*DHCP6DuidLlSet) GetCrcString() string { + return "0f6ca323" +} +func (*DHCP6DuidLlSet) GetMessageType() api.MessageType { + return api.RequestMessage +} +func NewDHCP6DuidLlSet() api.Message { + return &DHCP6DuidLlSet{} +} + +// DHCP6DuidLlSetReply represents the VPP binary API message 'dhcp6_duid_ll_set_reply'. +// Generated from 'dhcp.api.json', line 336: +// +// "dhcp6_duid_ll_set_reply", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "i32", +// "retval" +// ], +// { +// "crc": "0xe8d4e804" +// } +// +type DHCP6DuidLlSetReply struct { + Retval int32 +} + +func (*DHCP6DuidLlSetReply) GetMessageName() string { + return "dhcp6_duid_ll_set_reply" +} +func (*DHCP6DuidLlSetReply) GetCrcString() string { + return "e8d4e804" +} +func (*DHCP6DuidLlSetReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} +func NewDHCP6DuidLlSetReply() api.Message { + return &DHCP6DuidLlSetReply{} +} + +// DHCP6ClientsEnableDisable represents the VPP binary API message 'dhcp6_clients_enable_disable'. +// Generated from 'dhcp.api.json', line 354: +// +// "dhcp6_clients_enable_disable", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "client_index" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "u8", +// "enable" +// ], +// { +// "crc": "0x8050327d" +// } +// +type DHCP6ClientsEnableDisable struct { + Enable uint8 +} + +func (*DHCP6ClientsEnableDisable) GetMessageName() string { + return "dhcp6_clients_enable_disable" +} +func (*DHCP6ClientsEnableDisable) GetCrcString() string { + return "8050327d" +} +func (*DHCP6ClientsEnableDisable) GetMessageType() api.MessageType { + return api.RequestMessage +} +func NewDHCP6ClientsEnableDisable() api.Message { + return &DHCP6ClientsEnableDisable{} +} + +// DHCP6ClientsEnableDisableReply represents the VPP binary API message 'dhcp6_clients_enable_disable_reply'. +// Generated from 'dhcp.api.json', line 376: +// +// "dhcp6_clients_enable_disable_reply", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "i32", +// "retval" +// ], +// { +// "crc": "0xe8d4e804" +// } +// +type DHCP6ClientsEnableDisableReply struct { + Retval int32 +} + +func (*DHCP6ClientsEnableDisableReply) GetMessageName() string { + return "dhcp6_clients_enable_disable_reply" +} +func (*DHCP6ClientsEnableDisableReply) GetCrcString() string { + return "e8d4e804" +} +func (*DHCP6ClientsEnableDisableReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} +func NewDHCP6ClientsEnableDisableReply() api.Message { + return &DHCP6ClientsEnableDisableReply{} +} + +// DHCP6SendClientMessage represents the VPP binary API message 'dhcp6_send_client_message'. +// Generated from 'dhcp.api.json', line 394: +// +// "dhcp6_send_client_message", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "client_index" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "u32", +// "sw_if_index" +// ], +// [ +// "u32", +// "server_index" +// ], +// [ +// "u32", +// "irt" +// ], +// [ +// "u32", +// "mrt" +// ], +// [ +// "u32", +// "mrc" +// ], +// [ +// "u32", +// "mrd" +// ], +// [ +// "u8", +// "stop" +// ], +// [ +// "u8", +// "msg_type" +// ], +// [ +// "u32", +// "T1" +// ], +// [ +// "u32", +// "T2" +// ], +// [ +// "u32", +// "n_addresses" +// ], +// [ +// "vl_api_dhcp6_address_info_t", +// "addresses", +// 0, +// "n_addresses" +// ], +// { +// "crc": "0xa13ae8c4" +// } +// +type DHCP6SendClientMessage struct { + SwIfIndex uint32 + ServerIndex uint32 + Irt uint32 + Mrt uint32 + Mrc uint32 + Mrd uint32 + Stop uint8 + MsgType uint8 + T1 uint32 + T2 uint32 + NAddresses uint32 `struc:"sizeof=Addresses"` + Addresses []DHCP6AddressInfo +} + +func (*DHCP6SendClientMessage) GetMessageName() string { + return "dhcp6_send_client_message" +} +func (*DHCP6SendClientMessage) GetCrcString() string { + return "a13ae8c4" +} +func (*DHCP6SendClientMessage) GetMessageType() api.MessageType { + return api.RequestMessage +} +func NewDHCP6SendClientMessage() api.Message { + return &DHCP6SendClientMessage{} +} + +// DHCP6SendClientMessageReply represents the VPP binary API message 'dhcp6_send_client_message_reply'. +// Generated from 'dhcp.api.json', line 462: +// +// "dhcp6_send_client_message_reply", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "i32", +// "retval" +// ], +// { +// "crc": "0xe8d4e804" +// } +// +type DHCP6SendClientMessageReply struct { + Retval int32 +} + +func (*DHCP6SendClientMessageReply) GetMessageName() string { + return "dhcp6_send_client_message_reply" +} +func (*DHCP6SendClientMessageReply) GetCrcString() string { + return "e8d4e804" +} +func (*DHCP6SendClientMessageReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} +func NewDHCP6SendClientMessageReply() api.Message { + return &DHCP6SendClientMessageReply{} +} + +// DHCP6PdSendClientMessage represents the VPP binary API message 'dhcp6_pd_send_client_message'. +// Generated from 'dhcp.api.json', line 480: +// +// "dhcp6_pd_send_client_message", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "client_index" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "u32", +// "sw_if_index" +// ], +// [ +// "u32", +// "server_index" +// ], +// [ +// "u32", +// "irt" +// ], +// [ +// "u32", +// "mrt" +// ], +// [ +// "u32", +// "mrc" +// ], +// [ +// "u32", +// "mrd" +// ], +// [ +// "u8", +// "stop" +// ], +// [ +// "u8", +// "msg_type" +// ], +// [ +// "u32", +// "T1" +// ], +// [ +// "u32", +// "T2" +// ], +// [ +// "u32", +// "n_prefixes" +// ], +// [ +// "vl_api_dhcp6_pd_prefix_info_t", +// "prefixes", +// 0, +// "n_prefixes" +// ], +// { +// "crc": "0x5a063fbc" +// } +// +type DHCP6PdSendClientMessage struct { + SwIfIndex uint32 + ServerIndex uint32 + Irt uint32 + Mrt uint32 + Mrc uint32 + Mrd uint32 + Stop uint8 + MsgType uint8 + T1 uint32 + T2 uint32 + NPrefixes uint32 `struc:"sizeof=Prefixes"` + Prefixes []DHCP6PdPrefixInfo +} + +func (*DHCP6PdSendClientMessage) GetMessageName() string { + return "dhcp6_pd_send_client_message" +} +func (*DHCP6PdSendClientMessage) GetCrcString() string { + return "5a063fbc" +} +func (*DHCP6PdSendClientMessage) GetMessageType() api.MessageType { + return api.RequestMessage +} +func NewDHCP6PdSendClientMessage() api.Message { + return &DHCP6PdSendClientMessage{} +} + +// DHCP6PdSendClientMessageReply represents the VPP binary API message 'dhcp6_pd_send_client_message_reply'. +// Generated from 'dhcp.api.json', line 548: +// +// "dhcp6_pd_send_client_message_reply", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "i32", +// "retval" +// ], +// { +// "crc": "0xe8d4e804" +// } +// +type DHCP6PdSendClientMessageReply struct { + Retval int32 +} + +func (*DHCP6PdSendClientMessageReply) GetMessageName() string { + return "dhcp6_pd_send_client_message_reply" +} +func (*DHCP6PdSendClientMessageReply) GetCrcString() string { + return "e8d4e804" +} +func (*DHCP6PdSendClientMessageReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} +func NewDHCP6PdSendClientMessageReply() api.Message { + return &DHCP6PdSendClientMessageReply{} +} + +// WantDHCP6ReplyEvents represents the VPP binary API message 'want_dhcp6_reply_events'. +// Generated from 'dhcp.api.json', line 566: +// +// "want_dhcp6_reply_events", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "client_index" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "u8", +// "enable_disable" +// ], +// [ +// "u32", +// "pid" +// ], +// { +// "crc": "0x05b454b5" +// } +// +type WantDHCP6ReplyEvents struct { + EnableDisable uint8 + PID uint32 +} + +func (*WantDHCP6ReplyEvents) GetMessageName() string { + return "want_dhcp6_reply_events" +} +func (*WantDHCP6ReplyEvents) GetCrcString() string { + return "05b454b5" +} +func (*WantDHCP6ReplyEvents) GetMessageType() api.MessageType { + return api.RequestMessage +} +func NewWantDHCP6ReplyEvents() api.Message { + return &WantDHCP6ReplyEvents{} +} + +// WantDHCP6ReplyEventsReply represents the VPP binary API message 'want_dhcp6_reply_events_reply'. +// Generated from 'dhcp.api.json', line 592: +// +// "want_dhcp6_reply_events_reply", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "i32", +// "retval" +// ], +// { +// "crc": "0xe8d4e804" +// } +// +type WantDHCP6ReplyEventsReply struct { + Retval int32 +} + +func (*WantDHCP6ReplyEventsReply) GetMessageName() string { + return "want_dhcp6_reply_events_reply" +} +func (*WantDHCP6ReplyEventsReply) GetCrcString() string { + return "e8d4e804" +} +func (*WantDHCP6ReplyEventsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} +func NewWantDHCP6ReplyEventsReply() api.Message { + return &WantDHCP6ReplyEventsReply{} +} + +// WantDHCP6PdReplyEvents represents the VPP binary API message 'want_dhcp6_pd_reply_events'. +// Generated from 'dhcp.api.json', line 610: +// +// "want_dhcp6_pd_reply_events", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "client_index" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "u8", +// "enable_disable" +// ], +// [ +// "u32", +// "pid" +// ], +// { +// "crc": "0x05b454b5" +// } +// +type WantDHCP6PdReplyEvents struct { + EnableDisable uint8 + PID uint32 +} + +func (*WantDHCP6PdReplyEvents) GetMessageName() string { + return "want_dhcp6_pd_reply_events" +} +func (*WantDHCP6PdReplyEvents) GetCrcString() string { + return "05b454b5" +} +func (*WantDHCP6PdReplyEvents) GetMessageType() api.MessageType { + return api.RequestMessage +} +func NewWantDHCP6PdReplyEvents() api.Message { + return &WantDHCP6PdReplyEvents{} +} + +// WantDHCP6PdReplyEventsReply represents the VPP binary API message 'want_dhcp6_pd_reply_events_reply'. +// Generated from 'dhcp.api.json', line 636: +// +// "want_dhcp6_pd_reply_events_reply", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "i32", +// "retval" +// ], +// { +// "crc": "0xe8d4e804" +// } +// +type WantDHCP6PdReplyEventsReply struct { + Retval int32 +} + +func (*WantDHCP6PdReplyEventsReply) GetMessageName() string { + return "want_dhcp6_pd_reply_events_reply" +} +func (*WantDHCP6PdReplyEventsReply) GetCrcString() string { + return "e8d4e804" +} +func (*WantDHCP6PdReplyEventsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} +func NewWantDHCP6PdReplyEventsReply() api.Message { + return &WantDHCP6PdReplyEventsReply{} +} + +// DHCP6ReplyEvent represents the VPP binary API message 'dhcp6_reply_event'. +// Generated from 'dhcp.api.json', line 654: +// +// "dhcp6_reply_event", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "client_index" +// ], +// [ +// "u32", +// "pid" +// ], +// [ +// "u32", +// "sw_if_index" +// ], +// [ +// "u32", +// "server_index" +// ], +// [ +// "u8", +// "msg_type" +// ], +// [ +// "u32", +// "T1" +// ], +// [ +// "u32", +// "T2" +// ], +// [ +// "u16", +// "inner_status_code" +// ], +// [ +// "u16", +// "status_code" +// ], +// [ +// "u8", +// "preference" +// ], +// [ +// "u32", +// "n_addresses" +// ], +// [ +// "vl_api_dhcp6_address_info_t", +// "addresses", +// 0, +// "n_addresses" +// ], +// { +// "crc": "0xac4563f9" +// } +// +type DHCP6ReplyEvent struct { + PID uint32 + SwIfIndex uint32 + ServerIndex uint32 + MsgType uint8 + T1 uint32 + T2 uint32 + InnerStatusCode uint16 + StatusCode uint16 + Preference uint8 + NAddresses uint32 `struc:"sizeof=Addresses"` + Addresses []DHCP6AddressInfo +} + +func (*DHCP6ReplyEvent) GetMessageName() string { + return "dhcp6_reply_event" +} +func (*DHCP6ReplyEvent) GetCrcString() string { + return "ac4563f9" +} +func (*DHCP6ReplyEvent) GetMessageType() api.MessageType { + return api.EventMessage +} +func NewDHCP6ReplyEvent() api.Message { + return &DHCP6ReplyEvent{} +} + +// DHCP6PdReplyEvent represents the VPP binary API message 'dhcp6_pd_reply_event'. +// Generated from 'dhcp.api.json', line 714: +// +// "dhcp6_pd_reply_event", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "client_index" +// ], +// [ +// "u32", +// "pid" +// ], +// [ +// "u32", +// "sw_if_index" +// ], +// [ +// "u32", +// "server_index" +// ], +// [ +// "u8", +// "msg_type" +// ], +// [ +// "u32", +// "T1" +// ], +// [ +// "u32", +// "T2" +// ], +// [ +// "u16", +// "inner_status_code" +// ], +// [ +// "u16", +// "status_code" +// ], +// [ +// "u8", +// "preference" +// ], +// [ +// "u32", +// "n_prefixes" +// ], +// [ +// "vl_api_dhcp6_pd_prefix_info_t", +// "prefixes", +// 0, +// "n_prefixes" +// ], +// { +// "crc": "0x48e73c36" +// } +// +type DHCP6PdReplyEvent struct { + PID uint32 + SwIfIndex uint32 + ServerIndex uint32 + MsgType uint8 + T1 uint32 + T2 uint32 + InnerStatusCode uint16 + StatusCode uint16 + Preference uint8 + NPrefixes uint32 `struc:"sizeof=Prefixes"` + Prefixes []DHCP6PdPrefixInfo +} + +func (*DHCP6PdReplyEvent) GetMessageName() string { + return "dhcp6_pd_reply_event" +} +func (*DHCP6PdReplyEvent) GetCrcString() string { + return "48e73c36" +} +func (*DHCP6PdReplyEvent) GetMessageType() api.MessageType { + return api.EventMessage +} +func NewDHCP6PdReplyEvent() api.Message { + return &DHCP6PdReplyEvent{} +} + +/* Services */ + +type Services interface { + DumpDHCPClient(*DHCPClientDump) (*DHCPClientDetails, error) + DumpDHCPProxy(*DHCPProxyDump) (*DHCPProxyDetails, error) + DHCP6ClientsEnableDisable(*DHCP6ClientsEnableDisable) (*DHCP6ClientsEnableDisableReply, error) + DHCP6DuidLlSet(*DHCP6DuidLlSet) (*DHCP6DuidLlSetReply, error) + DHCP6PdSendClientMessage(*DHCP6PdSendClientMessage) (*DHCP6PdSendClientMessageReply, error) + DHCP6SendClientMessage(*DHCP6SendClientMessage) (*DHCP6SendClientMessageReply, error) + DHCPClientConfig(*DHCPClientConfig) (*DHCPClientConfigReply, error) + DHCPProxyConfig(*DHCPProxyConfig) (*DHCPProxyConfigReply, error) + DHCPProxySetVss(*DHCPProxySetVss) (*DHCPProxySetVssReply, error) + WantDHCP6PdReplyEvents(*WantDHCP6PdReplyEvents) (*WantDHCP6PdReplyEventsReply, error) + WantDHCP6ReplyEvents(*WantDHCP6ReplyEvents) (*WantDHCP6ReplyEventsReply, error) +} + +func init() { + api.RegisterMessage((*DHCPProxyConfig)(nil), "dhcp.DHCPProxyConfig") + api.RegisterMessage((*DHCPProxyConfigReply)(nil), "dhcp.DHCPProxyConfigReply") + api.RegisterMessage((*DHCPProxySetVss)(nil), "dhcp.DHCPProxySetVss") + api.RegisterMessage((*DHCPProxySetVssReply)(nil), "dhcp.DHCPProxySetVssReply") + api.RegisterMessage((*DHCPClientConfig)(nil), "dhcp.DHCPClientConfig") + api.RegisterMessage((*DHCPClientConfigReply)(nil), "dhcp.DHCPClientConfigReply") + api.RegisterMessage((*DHCPComplEvent)(nil), "dhcp.DHCPComplEvent") + api.RegisterMessage((*DHCPClientDump)(nil), "dhcp.DHCPClientDump") + api.RegisterMessage((*DHCPClientDetails)(nil), "dhcp.DHCPClientDetails") + api.RegisterMessage((*DHCPProxyDump)(nil), "dhcp.DHCPProxyDump") + api.RegisterMessage((*DHCPProxyDetails)(nil), "dhcp.DHCPProxyDetails") + api.RegisterMessage((*DHCP6DuidLlSet)(nil), "dhcp.DHCP6DuidLlSet") + api.RegisterMessage((*DHCP6DuidLlSetReply)(nil), "dhcp.DHCP6DuidLlSetReply") + api.RegisterMessage((*DHCP6ClientsEnableDisable)(nil), "dhcp.DHCP6ClientsEnableDisable") + api.RegisterMessage((*DHCP6ClientsEnableDisableReply)(nil), "dhcp.DHCP6ClientsEnableDisableReply") + api.RegisterMessage((*DHCP6SendClientMessage)(nil), "dhcp.DHCP6SendClientMessage") + api.RegisterMessage((*DHCP6SendClientMessageReply)(nil), "dhcp.DHCP6SendClientMessageReply") + api.RegisterMessage((*DHCP6PdSendClientMessage)(nil), "dhcp.DHCP6PdSendClientMessage") + api.RegisterMessage((*DHCP6PdSendClientMessageReply)(nil), "dhcp.DHCP6PdSendClientMessageReply") + api.RegisterMessage((*WantDHCP6ReplyEvents)(nil), "dhcp.WantDHCP6ReplyEvents") + api.RegisterMessage((*WantDHCP6ReplyEventsReply)(nil), "dhcp.WantDHCP6ReplyEventsReply") + api.RegisterMessage((*WantDHCP6PdReplyEvents)(nil), "dhcp.WantDHCP6PdReplyEvents") + api.RegisterMessage((*WantDHCP6PdReplyEventsReply)(nil), "dhcp.WantDHCP6PdReplyEventsReply") + api.RegisterMessage((*DHCP6ReplyEvent)(nil), "dhcp.DHCP6ReplyEvent") + api.RegisterMessage((*DHCP6PdReplyEvent)(nil), "dhcp.DHCP6PdReplyEvent") +} diff --git a/plugins/vpp/binapi/dhcp/dhcp.go b/plugins/vpp/binapi/dhcp/dhcp.go deleted file mode 100644 index 8bf93d7c29..0000000000 --- a/plugins/vpp/binapi/dhcp/dhcp.go +++ /dev/null @@ -1,1189 +0,0 @@ -// Code generated by govpp binapi-generator DO NOT EDIT. -// Package dhcp represents the VPP binary API of the 'dhcp' VPP module. -// Generated from '/usr/share/vpp/api/dhcp.api.json' -package dhcp - -import "git.fd.io/govpp.git/api" - -// DhcpClient represents the VPP binary API data type 'dhcp_client'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 626: -// -// "dhcp_client", -// [ -// "u32", -// "sw_if_index" -// ], -// [ -// "u8", -// "hostname", -// 64 -// ], -// [ -// "u8", -// "id", -// 64 -// ], -// [ -// "u8", -// "want_dhcp_event" -// ], -// [ -// "u8", -// "set_broadcast_flag" -// ], -// [ -// "u32", -// "pid" -// ], -// { -// "crc": "0x527f7935" -// } -// -type DhcpClient struct { - SwIfIndex uint32 - Hostname []byte `struc:"[64]byte"` - ID []byte `struc:"[64]byte"` - WantDhcpEvent uint8 - SetBroadcastFlag uint8 - Pid uint32 -} - -func (*DhcpClient) GetTypeName() string { - return "dhcp_client" -} -func (*DhcpClient) GetCrcString() string { - return "527f7935" -} - -// DhcpLease represents the VPP binary API data type 'dhcp_lease'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 658: -// -// "dhcp_lease", -// [ -// "u32", -// "sw_if_index" -// ], -// [ -// "u8", -// "state" -// ], -// [ -// "u8", -// "hostname", -// 64 -// ], -// [ -// "u8", -// "is_ipv6" -// ], -// [ -// "u8", -// "mask_width" -// ], -// [ -// "u8", -// "host_address", -// 16 -// ], -// [ -// "u8", -// "router_address", -// 16 -// ], -// [ -// "u8", -// "host_mac", -// 6 -// ], -// { -// "crc": "0x61090276" -// } -// -type DhcpLease struct { - SwIfIndex uint32 - State uint8 - Hostname []byte `struc:"[64]byte"` - IsIpv6 uint8 - MaskWidth uint8 - HostAddress []byte `struc:"[16]byte"` - RouterAddress []byte `struc:"[16]byte"` - HostMac []byte `struc:"[6]byte"` -} - -func (*DhcpLease) GetTypeName() string { - return "dhcp_lease" -} -func (*DhcpLease) GetCrcString() string { - return "61090276" -} - -// DhcpServer represents the VPP binary API data type 'dhcp_server'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 700: -// -// "dhcp_server", -// [ -// "u32", -// "server_vrf_id" -// ], -// [ -// "u8", -// "dhcp_server", -// 16 -// ], -// { -// "crc": "0xf16506c4" -// } -// -type DhcpServer struct { - ServerVrfID uint32 - DhcpServer []byte `struc:"[16]byte"` -} - -func (*DhcpServer) GetTypeName() string { - return "dhcp_server" -} -func (*DhcpServer) GetCrcString() string { - return "f16506c4" -} - -// Dhcp6PdPrefixInfo represents the VPP binary API data type 'dhcp6_pd_prefix_info'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 715: -// -// "dhcp6_pd_prefix_info", -// [ -// "u8", -// "prefix", -// 16 -// ], -// [ -// "u8", -// "prefix_length" -// ], -// [ -// "u32", -// "valid_time" -// ], -// [ -// "u32", -// "preferred_time" -// ], -// { -// "crc": "0xc459690e" -// } -// -type Dhcp6PdPrefixInfo struct { - Prefix []byte `struc:"[16]byte"` - PrefixLength uint8 - ValidTime uint32 - PreferredTime uint32 -} - -func (*Dhcp6PdPrefixInfo) GetTypeName() string { - return "dhcp6_pd_prefix_info" -} -func (*Dhcp6PdPrefixInfo) GetCrcString() string { - return "c459690e" -} - -// DhcpProxyConfig represents the VPP binary API message 'dhcp_proxy_config'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 4: -// -// "dhcp_proxy_config", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "client_index" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "u32", -// "rx_vrf_id" -// ], -// [ -// "u32", -// "server_vrf_id" -// ], -// [ -// "u8", -// "is_ipv6" -// ], -// [ -// "u8", -// "is_add" -// ], -// [ -// "u8", -// "dhcp_server", -// 16 -// ], -// [ -// "u8", -// "dhcp_src_address", -// 16 -// ], -// { -// "crc": "0x6af4b645" -// } -// -type DhcpProxyConfig struct { - RxVrfID uint32 - ServerVrfID uint32 - IsIpv6 uint8 - IsAdd uint8 - DhcpServer []byte `struc:"[16]byte"` - DhcpSrcAddress []byte `struc:"[16]byte"` -} - -func (*DhcpProxyConfig) GetMessageName() string { - return "dhcp_proxy_config" -} -func (*DhcpProxyConfig) GetMessageType() api.MessageType { - return api.RequestMessage -} -func (*DhcpProxyConfig) GetCrcString() string { - return "6af4b645" -} -func NewDhcpProxyConfig() api.Message { - return &DhcpProxyConfig{} -} - -// DhcpProxyConfigReply represents the VPP binary API message 'dhcp_proxy_config_reply'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 48: -// -// "dhcp_proxy_config_reply", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "i32", -// "retval" -// ], -// { -// "crc": "0xe8d4e804" -// } -// -type DhcpProxyConfigReply struct { - Retval int32 -} - -func (*DhcpProxyConfigReply) GetMessageName() string { - return "dhcp_proxy_config_reply" -} -func (*DhcpProxyConfigReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} -func (*DhcpProxyConfigReply) GetCrcString() string { - return "e8d4e804" -} -func NewDhcpProxyConfigReply() api.Message { - return &DhcpProxyConfigReply{} -} - -// DhcpProxySetVss represents the VPP binary API message 'dhcp_proxy_set_vss'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 66: -// -// "dhcp_proxy_set_vss", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "client_index" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "u32", -// "tbl_id" -// ], -// [ -// "u8", -// "vss_type" -// ], -// [ -// "u8", -// "vpn_ascii_id", -// 129 -// ], -// [ -// "u32", -// "oui" -// ], -// [ -// "u32", -// "vpn_index" -// ], -// [ -// "u8", -// "is_ipv6" -// ], -// [ -// "u8", -// "is_add" -// ], -// { -// "crc": "0x606535aa" -// } -// -type DhcpProxySetVss struct { - TblID uint32 - VssType uint8 - VpnASCIIID []byte `struc:"[129]byte"` - Oui uint32 - VpnIndex uint32 - IsIpv6 uint8 - IsAdd uint8 -} - -func (*DhcpProxySetVss) GetMessageName() string { - return "dhcp_proxy_set_vss" -} -func (*DhcpProxySetVss) GetMessageType() api.MessageType { - return api.RequestMessage -} -func (*DhcpProxySetVss) GetCrcString() string { - return "606535aa" -} -func NewDhcpProxySetVss() api.Message { - return &DhcpProxySetVss{} -} - -// DhcpProxySetVssReply represents the VPP binary API message 'dhcp_proxy_set_vss_reply'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 113: -// -// "dhcp_proxy_set_vss_reply", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "i32", -// "retval" -// ], -// { -// "crc": "0xe8d4e804" -// } -// -type DhcpProxySetVssReply struct { - Retval int32 -} - -func (*DhcpProxySetVssReply) GetMessageName() string { - return "dhcp_proxy_set_vss_reply" -} -func (*DhcpProxySetVssReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} -func (*DhcpProxySetVssReply) GetCrcString() string { - return "e8d4e804" -} -func NewDhcpProxySetVssReply() api.Message { - return &DhcpProxySetVssReply{} -} - -// DhcpClientConfig represents the VPP binary API message 'dhcp_client_config'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 131: -// -// "dhcp_client_config", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "client_index" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "u8", -// "is_add" -// ], -// [ -// "vl_api_dhcp_client_t", -// "client" -// ], -// { -// "crc": "0xc32ccdfe" -// } -// -type DhcpClientConfig struct { - IsAdd uint8 - Client DhcpClient -} - -func (*DhcpClientConfig) GetMessageName() string { - return "dhcp_client_config" -} -func (*DhcpClientConfig) GetMessageType() api.MessageType { - return api.RequestMessage -} -func (*DhcpClientConfig) GetCrcString() string { - return "c32ccdfe" -} -func NewDhcpClientConfig() api.Message { - return &DhcpClientConfig{} -} - -// DhcpClientConfigReply represents the VPP binary API message 'dhcp_client_config_reply'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 157: -// -// "dhcp_client_config_reply", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "i32", -// "retval" -// ], -// { -// "crc": "0xe8d4e804" -// } -// -type DhcpClientConfigReply struct { - Retval int32 -} - -func (*DhcpClientConfigReply) GetMessageName() string { - return "dhcp_client_config_reply" -} -func (*DhcpClientConfigReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} -func (*DhcpClientConfigReply) GetCrcString() string { - return "e8d4e804" -} -func NewDhcpClientConfigReply() api.Message { - return &DhcpClientConfigReply{} -} - -// DhcpComplEvent represents the VPP binary API message 'dhcp_compl_event'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 175: -// -// "dhcp_compl_event", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "client_index" -// ], -// [ -// "u32", -// "pid" -// ], -// [ -// "vl_api_dhcp_lease_t", -// "lease" -// ], -// { -// "crc": "0x2105c31b" -// } -// -type DhcpComplEvent struct { - Pid uint32 - Lease DhcpLease -} - -func (*DhcpComplEvent) GetMessageName() string { - return "dhcp_compl_event" -} -func (*DhcpComplEvent) GetMessageType() api.MessageType { - return api.EventMessage -} -func (*DhcpComplEvent) GetCrcString() string { - return "2105c31b" -} -func NewDhcpComplEvent() api.Message { - return &DhcpComplEvent{} -} - -// DhcpClientDump represents the VPP binary API message 'dhcp_client_dump'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 197: -// -// "dhcp_client_dump", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "client_index" -// ], -// [ -// "u32", -// "context" -// ], -// { -// "crc": "0x51077d14" -// } -// -type DhcpClientDump struct { -} - -func (*DhcpClientDump) GetMessageName() string { - return "dhcp_client_dump" -} -func (*DhcpClientDump) GetMessageType() api.MessageType { - return api.RequestMessage -} -func (*DhcpClientDump) GetCrcString() string { - return "51077d14" -} -func NewDhcpClientDump() api.Message { - return &DhcpClientDump{} -} - -// DhcpClientDetails represents the VPP binary API message 'dhcp_client_details'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 215: -// -// "dhcp_client_details", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "vl_api_dhcp_client_t", -// "client" -// ], -// [ -// "vl_api_dhcp_lease_t", -// "lease" -// ], -// { -// "crc": "0x7ea3a745" -// } -// -type DhcpClientDetails struct { - Client DhcpClient - Lease DhcpLease -} - -func (*DhcpClientDetails) GetMessageName() string { - return "dhcp_client_details" -} -func (*DhcpClientDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} -func (*DhcpClientDetails) GetCrcString() string { - return "7ea3a745" -} -func NewDhcpClientDetails() api.Message { - return &DhcpClientDetails{} -} - -// DhcpProxyDump represents the VPP binary API message 'dhcp_proxy_dump'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 237: -// -// "dhcp_proxy_dump", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "client_index" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "u8", -// "is_ip6" -// ], -// { -// "crc": "0x6fe91190" -// } -// -type DhcpProxyDump struct { - IsIP6 uint8 -} - -func (*DhcpProxyDump) GetMessageName() string { - return "dhcp_proxy_dump" -} -func (*DhcpProxyDump) GetMessageType() api.MessageType { - return api.RequestMessage -} -func (*DhcpProxyDump) GetCrcString() string { - return "6fe91190" -} -func NewDhcpProxyDump() api.Message { - return &DhcpProxyDump{} -} - -// DhcpProxyDetails represents the VPP binary API message 'dhcp_proxy_details'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 259: -// -// "dhcp_proxy_details", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "u32", -// "rx_vrf_id" -// ], -// [ -// "u32", -// "vss_oui" -// ], -// [ -// "u32", -// "vss_fib_id" -// ], -// [ -// "u8", -// "vss_type" -// ], -// [ -// "u8", -// "vss_vpn_ascii_id", -// 129 -// ], -// [ -// "u8", -// "is_ipv6" -// ], -// [ -// "u8", -// "dhcp_src_address", -// 16 -// ], -// [ -// "u8", -// "count" -// ], -// [ -// "vl_api_dhcp_server_t", -// "servers", -// 0, -// "count" -// ], -// { -// "crc": "0xa5f2ad84" -// } -// -type DhcpProxyDetails struct { - RxVrfID uint32 - VssOui uint32 - VssFibID uint32 - VssType uint8 - VssVpnASCIIID []byte `struc:"[129]byte"` - IsIpv6 uint8 - DhcpSrcAddress []byte `struc:"[16]byte"` - Count uint8 `struc:"sizeof=Servers"` - Servers []DhcpServer -} - -func (*DhcpProxyDetails) GetMessageName() string { - return "dhcp_proxy_details" -} -func (*DhcpProxyDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} -func (*DhcpProxyDetails) GetCrcString() string { - return "a5f2ad84" -} -func NewDhcpProxyDetails() api.Message { - return &DhcpProxyDetails{} -} - -// Dhcp6DuidLlSet represents the VPP binary API message 'dhcp6_duid_ll_set'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 313: -// -// "dhcp6_duid_ll_set", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "client_index" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "u8", -// "duid_ll", -// 10 -// ], -// { -// "crc": "0x0f6ca323" -// } -// -type Dhcp6DuidLlSet struct { - DuidLl []byte `struc:"[10]byte"` -} - -func (*Dhcp6DuidLlSet) GetMessageName() string { - return "dhcp6_duid_ll_set" -} -func (*Dhcp6DuidLlSet) GetMessageType() api.MessageType { - return api.RequestMessage -} -func (*Dhcp6DuidLlSet) GetCrcString() string { - return "0f6ca323" -} -func NewDhcp6DuidLlSet() api.Message { - return &Dhcp6DuidLlSet{} -} - -// Dhcp6DuidLlSetReply represents the VPP binary API message 'dhcp6_duid_ll_set_reply'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 336: -// -// "dhcp6_duid_ll_set_reply", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "i32", -// "retval" -// ], -// { -// "crc": "0xe8d4e804" -// } -// -type Dhcp6DuidLlSetReply struct { - Retval int32 -} - -func (*Dhcp6DuidLlSetReply) GetMessageName() string { - return "dhcp6_duid_ll_set_reply" -} -func (*Dhcp6DuidLlSetReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} -func (*Dhcp6DuidLlSetReply) GetCrcString() string { - return "e8d4e804" -} -func NewDhcp6DuidLlSetReply() api.Message { - return &Dhcp6DuidLlSetReply{} -} - -// Dhcp6ClientsEnableDisable represents the VPP binary API message 'dhcp6_clients_enable_disable'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 354: -// -// "dhcp6_clients_enable_disable", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "client_index" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "u8", -// "enable" -// ], -// { -// "crc": "0x8050327d" -// } -// -type Dhcp6ClientsEnableDisable struct { - Enable uint8 -} - -func (*Dhcp6ClientsEnableDisable) GetMessageName() string { - return "dhcp6_clients_enable_disable" -} -func (*Dhcp6ClientsEnableDisable) GetMessageType() api.MessageType { - return api.RequestMessage -} -func (*Dhcp6ClientsEnableDisable) GetCrcString() string { - return "8050327d" -} -func NewDhcp6ClientsEnableDisable() api.Message { - return &Dhcp6ClientsEnableDisable{} -} - -// Dhcp6ClientsEnableDisableReply represents the VPP binary API message 'dhcp6_clients_enable_disable_reply'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 376: -// -// "dhcp6_clients_enable_disable_reply", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "i32", -// "retval" -// ], -// { -// "crc": "0xe8d4e804" -// } -// -type Dhcp6ClientsEnableDisableReply struct { - Retval int32 -} - -func (*Dhcp6ClientsEnableDisableReply) GetMessageName() string { - return "dhcp6_clients_enable_disable_reply" -} -func (*Dhcp6ClientsEnableDisableReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} -func (*Dhcp6ClientsEnableDisableReply) GetCrcString() string { - return "e8d4e804" -} -func NewDhcp6ClientsEnableDisableReply() api.Message { - return &Dhcp6ClientsEnableDisableReply{} -} - -// Dhcp6PdSendClientMessage represents the VPP binary API message 'dhcp6_pd_send_client_message'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 394: -// -// "dhcp6_pd_send_client_message", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "client_index" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "u32", -// "sw_if_index" -// ], -// [ -// "u32", -// "server_index" -// ], -// [ -// "u32", -// "irt" -// ], -// [ -// "u32", -// "mrt" -// ], -// [ -// "u32", -// "mrc" -// ], -// [ -// "u32", -// "mrd" -// ], -// [ -// "u8", -// "stop" -// ], -// [ -// "u8", -// "msg_type" -// ], -// [ -// "u32", -// "T1" -// ], -// [ -// "u32", -// "T2" -// ], -// [ -// "u32", -// "n_prefixes" -// ], -// [ -// "vl_api_dhcp6_pd_prefix_info_t", -// "prefixes", -// 0, -// "n_prefixes" -// ], -// { -// "crc": "0x5a063fbc" -// } -// -type Dhcp6PdSendClientMessage struct { - SwIfIndex uint32 - ServerIndex uint32 - Irt uint32 - Mrt uint32 - Mrc uint32 - Mrd uint32 - Stop uint8 - MsgType uint8 - T1 uint32 - T2 uint32 - NPrefixes uint32 `struc:"sizeof=Prefixes"` - Prefixes []Dhcp6PdPrefixInfo -} - -func (*Dhcp6PdSendClientMessage) GetMessageName() string { - return "dhcp6_pd_send_client_message" -} -func (*Dhcp6PdSendClientMessage) GetMessageType() api.MessageType { - return api.RequestMessage -} -func (*Dhcp6PdSendClientMessage) GetCrcString() string { - return "5a063fbc" -} -func NewDhcp6PdSendClientMessage() api.Message { - return &Dhcp6PdSendClientMessage{} -} - -// Dhcp6PdSendClientMessageReply represents the VPP binary API message 'dhcp6_pd_send_client_message_reply'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 462: -// -// "dhcp6_pd_send_client_message_reply", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "i32", -// "retval" -// ], -// { -// "crc": "0xe8d4e804" -// } -// -type Dhcp6PdSendClientMessageReply struct { - Retval int32 -} - -func (*Dhcp6PdSendClientMessageReply) GetMessageName() string { - return "dhcp6_pd_send_client_message_reply" -} -func (*Dhcp6PdSendClientMessageReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} -func (*Dhcp6PdSendClientMessageReply) GetCrcString() string { - return "e8d4e804" -} -func NewDhcp6PdSendClientMessageReply() api.Message { - return &Dhcp6PdSendClientMessageReply{} -} - -// WantDhcp6PdReplyEvents represents the VPP binary API message 'want_dhcp6_pd_reply_events'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 480: -// -// "want_dhcp6_pd_reply_events", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "client_index" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "u8", -// "enable_disable" -// ], -// [ -// "u32", -// "pid" -// ], -// { -// "crc": "0x05b454b5" -// } -// -type WantDhcp6PdReplyEvents struct { - EnableDisable uint8 - Pid uint32 -} - -func (*WantDhcp6PdReplyEvents) GetMessageName() string { - return "want_dhcp6_pd_reply_events" -} -func (*WantDhcp6PdReplyEvents) GetMessageType() api.MessageType { - return api.RequestMessage -} -func (*WantDhcp6PdReplyEvents) GetCrcString() string { - return "05b454b5" -} -func NewWantDhcp6PdReplyEvents() api.Message { - return &WantDhcp6PdReplyEvents{} -} - -// WantDhcp6PdReplyEventsReply represents the VPP binary API message 'want_dhcp6_pd_reply_events_reply'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 506: -// -// "want_dhcp6_pd_reply_events_reply", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "i32", -// "retval" -// ], -// { -// "crc": "0xe8d4e804" -// } -// -type WantDhcp6PdReplyEventsReply struct { - Retval int32 -} - -func (*WantDhcp6PdReplyEventsReply) GetMessageName() string { - return "want_dhcp6_pd_reply_events_reply" -} -func (*WantDhcp6PdReplyEventsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} -func (*WantDhcp6PdReplyEventsReply) GetCrcString() string { - return "e8d4e804" -} -func NewWantDhcp6PdReplyEventsReply() api.Message { - return &WantDhcp6PdReplyEventsReply{} -} - -// Dhcp6PdReplyEvent represents the VPP binary API message 'dhcp6_pd_reply_event'. -// Generated from '/usr/share/vpp/api/dhcp.api.json', line 524: -// -// "dhcp6_pd_reply_event", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "client_index" -// ], -// [ -// "u32", -// "pid" -// ], -// [ -// "u32", -// "sw_if_index" -// ], -// [ -// "u32", -// "server_index" -// ], -// [ -// "u8", -// "msg_type" -// ], -// [ -// "u32", -// "T1" -// ], -// [ -// "u32", -// "T2" -// ], -// [ -// "u16", -// "inner_status_code" -// ], -// [ -// "u16", -// "status_code" -// ], -// [ -// "u8", -// "preference" -// ], -// [ -// "u32", -// "n_prefixes" -// ], -// [ -// "vl_api_dhcp6_pd_prefix_info_t", -// "prefixes", -// 0, -// "n_prefixes" -// ], -// { -// "crc": "0x48e73c36" -// } -// -type Dhcp6PdReplyEvent struct { - Pid uint32 - SwIfIndex uint32 - ServerIndex uint32 - MsgType uint8 - T1 uint32 - T2 uint32 - InnerStatusCode uint16 - StatusCode uint16 - Preference uint8 - NPrefixes uint32 `struc:"sizeof=Prefixes"` - Prefixes []Dhcp6PdPrefixInfo -} - -func (*Dhcp6PdReplyEvent) GetMessageName() string { - return "dhcp6_pd_reply_event" -} -func (*Dhcp6PdReplyEvent) GetMessageType() api.MessageType { - return api.EventMessage -} -func (*Dhcp6PdReplyEvent) GetCrcString() string { - return "48e73c36" -} -func NewDhcp6PdReplyEvent() api.Message { - return &Dhcp6PdReplyEvent{} -} diff --git a/plugins/vpp/binapi/dhcp/pkgreflect.go b/plugins/vpp/binapi/dhcp/pkgreflect.go index 5d7ade88b1..fc14944f15 100644 --- a/plugins/vpp/binapi/dhcp/pkgreflect.go +++ b/plugins/vpp/binapi/dhcp/pkgreflect.go @@ -5,53 +5,65 @@ package dhcp import "reflect" var Types = map[string]reflect.Type{ - "Dhcp6ClientsEnableDisable": reflect.TypeOf((*Dhcp6ClientsEnableDisable)(nil)).Elem(), - "Dhcp6ClientsEnableDisableReply": reflect.TypeOf((*Dhcp6ClientsEnableDisableReply)(nil)).Elem(), - "Dhcp6DuidLlSet": reflect.TypeOf((*Dhcp6DuidLlSet)(nil)).Elem(), - "Dhcp6DuidLlSetReply": reflect.TypeOf((*Dhcp6DuidLlSetReply)(nil)).Elem(), - "Dhcp6PdPrefixInfo": reflect.TypeOf((*Dhcp6PdPrefixInfo)(nil)).Elem(), - "Dhcp6PdReplyEvent": reflect.TypeOf((*Dhcp6PdReplyEvent)(nil)).Elem(), - "Dhcp6PdSendClientMessage": reflect.TypeOf((*Dhcp6PdSendClientMessage)(nil)).Elem(), - "Dhcp6PdSendClientMessageReply": reflect.TypeOf((*Dhcp6PdSendClientMessageReply)(nil)).Elem(), - "DhcpClient": reflect.TypeOf((*DhcpClient)(nil)).Elem(), - "DhcpClientConfig": reflect.TypeOf((*DhcpClientConfig)(nil)).Elem(), - "DhcpClientConfigReply": reflect.TypeOf((*DhcpClientConfigReply)(nil)).Elem(), - "DhcpClientDetails": reflect.TypeOf((*DhcpClientDetails)(nil)).Elem(), - "DhcpClientDump": reflect.TypeOf((*DhcpClientDump)(nil)).Elem(), - "DhcpComplEvent": reflect.TypeOf((*DhcpComplEvent)(nil)).Elem(), - "DhcpLease": reflect.TypeOf((*DhcpLease)(nil)).Elem(), - "DhcpProxyConfig": reflect.TypeOf((*DhcpProxyConfig)(nil)).Elem(), - "DhcpProxyConfigReply": reflect.TypeOf((*DhcpProxyConfigReply)(nil)).Elem(), - "DhcpProxyDetails": reflect.TypeOf((*DhcpProxyDetails)(nil)).Elem(), - "DhcpProxyDump": reflect.TypeOf((*DhcpProxyDump)(nil)).Elem(), - "DhcpProxySetVss": reflect.TypeOf((*DhcpProxySetVss)(nil)).Elem(), - "DhcpProxySetVssReply": reflect.TypeOf((*DhcpProxySetVssReply)(nil)).Elem(), - "DhcpServer": reflect.TypeOf((*DhcpServer)(nil)).Elem(), - "WantDhcp6PdReplyEvents": reflect.TypeOf((*WantDhcp6PdReplyEvents)(nil)).Elem(), - "WantDhcp6PdReplyEventsReply": reflect.TypeOf((*WantDhcp6PdReplyEventsReply)(nil)).Elem(), + "DHCP6AddressInfo": reflect.TypeOf((*DHCP6AddressInfo)(nil)).Elem(), + "DHCP6ClientsEnableDisable": reflect.TypeOf((*DHCP6ClientsEnableDisable)(nil)).Elem(), + "DHCP6ClientsEnableDisableReply": reflect.TypeOf((*DHCP6ClientsEnableDisableReply)(nil)).Elem(), + "DHCP6DuidLlSet": reflect.TypeOf((*DHCP6DuidLlSet)(nil)).Elem(), + "DHCP6DuidLlSetReply": reflect.TypeOf((*DHCP6DuidLlSetReply)(nil)).Elem(), + "DHCP6PdPrefixInfo": reflect.TypeOf((*DHCP6PdPrefixInfo)(nil)).Elem(), + "DHCP6PdReplyEvent": reflect.TypeOf((*DHCP6PdReplyEvent)(nil)).Elem(), + "DHCP6PdSendClientMessage": reflect.TypeOf((*DHCP6PdSendClientMessage)(nil)).Elem(), + "DHCP6PdSendClientMessageReply": reflect.TypeOf((*DHCP6PdSendClientMessageReply)(nil)).Elem(), + "DHCP6ReplyEvent": reflect.TypeOf((*DHCP6ReplyEvent)(nil)).Elem(), + "DHCP6SendClientMessage": reflect.TypeOf((*DHCP6SendClientMessage)(nil)).Elem(), + "DHCP6SendClientMessageReply": reflect.TypeOf((*DHCP6SendClientMessageReply)(nil)).Elem(), + "DHCPClient": reflect.TypeOf((*DHCPClient)(nil)).Elem(), + "DHCPClientConfig": reflect.TypeOf((*DHCPClientConfig)(nil)).Elem(), + "DHCPClientConfigReply": reflect.TypeOf((*DHCPClientConfigReply)(nil)).Elem(), + "DHCPClientDetails": reflect.TypeOf((*DHCPClientDetails)(nil)).Elem(), + "DHCPClientDump": reflect.TypeOf((*DHCPClientDump)(nil)).Elem(), + "DHCPComplEvent": reflect.TypeOf((*DHCPComplEvent)(nil)).Elem(), + "DHCPLease": reflect.TypeOf((*DHCPLease)(nil)).Elem(), + "DHCPProxyConfig": reflect.TypeOf((*DHCPProxyConfig)(nil)).Elem(), + "DHCPProxyConfigReply": reflect.TypeOf((*DHCPProxyConfigReply)(nil)).Elem(), + "DHCPProxyDetails": reflect.TypeOf((*DHCPProxyDetails)(nil)).Elem(), + "DHCPProxyDump": reflect.TypeOf((*DHCPProxyDump)(nil)).Elem(), + "DHCPProxySetVss": reflect.TypeOf((*DHCPProxySetVss)(nil)).Elem(), + "DHCPProxySetVssReply": reflect.TypeOf((*DHCPProxySetVssReply)(nil)).Elem(), + "DHCPServer": reflect.TypeOf((*DHCPServer)(nil)).Elem(), + "Services": reflect.TypeOf((*Services)(nil)).Elem(), + "WantDHCP6PdReplyEvents": reflect.TypeOf((*WantDHCP6PdReplyEvents)(nil)).Elem(), + "WantDHCP6PdReplyEventsReply": reflect.TypeOf((*WantDHCP6PdReplyEventsReply)(nil)).Elem(), + "WantDHCP6ReplyEvents": reflect.TypeOf((*WantDHCP6ReplyEvents)(nil)).Elem(), + "WantDHCP6ReplyEventsReply": reflect.TypeOf((*WantDHCP6ReplyEventsReply)(nil)).Elem(), } var Functions = map[string]reflect.Value{ - "NewDhcp6ClientsEnableDisable": reflect.ValueOf(NewDhcp6ClientsEnableDisable), - "NewDhcp6ClientsEnableDisableReply": reflect.ValueOf(NewDhcp6ClientsEnableDisableReply), - "NewDhcp6DuidLlSet": reflect.ValueOf(NewDhcp6DuidLlSet), - "NewDhcp6DuidLlSetReply": reflect.ValueOf(NewDhcp6DuidLlSetReply), - "NewDhcp6PdReplyEvent": reflect.ValueOf(NewDhcp6PdReplyEvent), - "NewDhcp6PdSendClientMessage": reflect.ValueOf(NewDhcp6PdSendClientMessage), - "NewDhcp6PdSendClientMessageReply": reflect.ValueOf(NewDhcp6PdSendClientMessageReply), - "NewDhcpClientConfig": reflect.ValueOf(NewDhcpClientConfig), - "NewDhcpClientConfigReply": reflect.ValueOf(NewDhcpClientConfigReply), - "NewDhcpClientDetails": reflect.ValueOf(NewDhcpClientDetails), - "NewDhcpClientDump": reflect.ValueOf(NewDhcpClientDump), - "NewDhcpComplEvent": reflect.ValueOf(NewDhcpComplEvent), - "NewDhcpProxyConfig": reflect.ValueOf(NewDhcpProxyConfig), - "NewDhcpProxyConfigReply": reflect.ValueOf(NewDhcpProxyConfigReply), - "NewDhcpProxyDetails": reflect.ValueOf(NewDhcpProxyDetails), - "NewDhcpProxyDump": reflect.ValueOf(NewDhcpProxyDump), - "NewDhcpProxySetVss": reflect.ValueOf(NewDhcpProxySetVss), - "NewDhcpProxySetVssReply": reflect.ValueOf(NewDhcpProxySetVssReply), - "NewWantDhcp6PdReplyEvents": reflect.ValueOf(NewWantDhcp6PdReplyEvents), - "NewWantDhcp6PdReplyEventsReply": reflect.ValueOf(NewWantDhcp6PdReplyEventsReply), + "NewDHCP6ClientsEnableDisable": reflect.ValueOf(NewDHCP6ClientsEnableDisable), + "NewDHCP6ClientsEnableDisableReply": reflect.ValueOf(NewDHCP6ClientsEnableDisableReply), + "NewDHCP6DuidLlSet": reflect.ValueOf(NewDHCP6DuidLlSet), + "NewDHCP6DuidLlSetReply": reflect.ValueOf(NewDHCP6DuidLlSetReply), + "NewDHCP6PdReplyEvent": reflect.ValueOf(NewDHCP6PdReplyEvent), + "NewDHCP6PdSendClientMessage": reflect.ValueOf(NewDHCP6PdSendClientMessage), + "NewDHCP6PdSendClientMessageReply": reflect.ValueOf(NewDHCP6PdSendClientMessageReply), + "NewDHCP6ReplyEvent": reflect.ValueOf(NewDHCP6ReplyEvent), + "NewDHCP6SendClientMessage": reflect.ValueOf(NewDHCP6SendClientMessage), + "NewDHCP6SendClientMessageReply": reflect.ValueOf(NewDHCP6SendClientMessageReply), + "NewDHCPClientConfig": reflect.ValueOf(NewDHCPClientConfig), + "NewDHCPClientConfigReply": reflect.ValueOf(NewDHCPClientConfigReply), + "NewDHCPClientDetails": reflect.ValueOf(NewDHCPClientDetails), + "NewDHCPClientDump": reflect.ValueOf(NewDHCPClientDump), + "NewDHCPComplEvent": reflect.ValueOf(NewDHCPComplEvent), + "NewDHCPProxyConfig": reflect.ValueOf(NewDHCPProxyConfig), + "NewDHCPProxyConfigReply": reflect.ValueOf(NewDHCPProxyConfigReply), + "NewDHCPProxyDetails": reflect.ValueOf(NewDHCPProxyDetails), + "NewDHCPProxyDump": reflect.ValueOf(NewDHCPProxyDump), + "NewDHCPProxySetVss": reflect.ValueOf(NewDHCPProxySetVss), + "NewDHCPProxySetVssReply": reflect.ValueOf(NewDHCPProxySetVssReply), + "NewWantDHCP6PdReplyEvents": reflect.ValueOf(NewWantDHCP6PdReplyEvents), + "NewWantDHCP6PdReplyEventsReply": reflect.ValueOf(NewWantDHCP6PdReplyEventsReply), + "NewWantDHCP6ReplyEvents": reflect.ValueOf(NewWantDHCP6ReplyEvents), + "NewWantDHCP6ReplyEventsReply": reflect.ValueOf(NewWantDHCP6ReplyEventsReply), } var Variables = map[string]reflect.Value{ diff --git a/plugins/vpp/binapi/fixapi.patch b/plugins/vpp/binapi/fixapi-ip.patch similarity index 61% rename from plugins/vpp/binapi/fixapi.patch rename to plugins/vpp/binapi/fixapi-ip.patch index e2ca28b906..0779ce1357 100644 --- a/plugins/vpp/binapi/fixapi.patch +++ b/plugins/vpp/binapi/fixapi-ip.patch @@ -1,8 +1,8 @@ -diff --git b/plugins/vpp/binapi/ip/ip.go a/plugins/vpp/binapi/ip/ip.go -index 1bcfcef9..a14d15b5 100644 ---- b/plugins/vpp/binapi/ip/ip.go -+++ a/plugins/vpp/binapi/ip/ip.go -@@ -152,8 +152,8 @@ +diff --git b/plugins/vpp/binapi/ip/ip.ba.go a/plugins/vpp/binapi/ip/ip.ba.go +index 6564081d..a68ca172 100644 +--- b/plugins/vpp/binapi/ip/ip.ba.go ++++ a/plugins/vpp/binapi/ip/ip.ba.go +@@ -340,8 +340,8 @@ type FibPath struct { NextHopID uint32 RpfID uint32 ViaLabel uint32 @@ -11,5 +11,5 @@ index 1bcfcef9..a14d15b5 100644 + NLabels uint8 `struc:"sizeof=LabelStack"` // MANUALLY FIXED, see https://jira.fd.io/browse/VPP-1261 + LabelStack []FibMplsLabel } - + func (*FibPath) GetTypeName() string { diff --git a/plugins/vpp/binapi/fixapi-sr.patch b/plugins/vpp/binapi/fixapi-sr.patch new file mode 100644 index 0000000000..b0c2f7e61d --- /dev/null +++ b/plugins/vpp/binapi/fixapi-sr.patch @@ -0,0 +1,16 @@ +diff --git b/plugins/vpp/binapi/sr/sr.ba.go a/plugins/vpp/binapi/sr/sr.ba.go +index e7e0a021..42153a48 100644 +--- b/plugins/vpp/binapi/sr/sr.ba.go ++++ a/plugins/vpp/binapi/sr/sr.ba.go +@@ -70,9 +70,9 @@ func (*Srv6Sid) GetCrcString() string { + // } + // + type Srv6SidList struct { +- NumSids uint8 ++ NumSids uint8 `struc:"sizeof=Sids"` + Weight uint32 +- Sids []Srv6Sid `struc:"[16]Srv6Sid"` ++ Sids []Srv6Sid + } + + func (*Srv6SidList) GetTypeName() string { diff --git a/plugins/vpp/binapi/interfaces/interfaces.go b/plugins/vpp/binapi/interfaces/interfaces.ba.go similarity index 82% rename from plugins/vpp/binapi/interfaces/interfaces.go rename to plugins/vpp/binapi/interfaces/interfaces.ba.go index fab81bea24..f6083ea362 100644 --- a/plugins/vpp/binapi/interfaces/interfaces.go +++ b/plugins/vpp/binapi/interfaces/interfaces.ba.go @@ -1,12 +1,31 @@ -// Code generated by govpp binapi-generator DO NOT EDIT. -// Package interfaces represents the VPP binary API of the 'interfaces' VPP module. -// Generated from '/usr/share/vpp/api/interface.api.json' +// Code generated by GoVPP binapi-generator. DO NOT EDIT. +// source: /usr/share/vpp/api/interface.api.json + +/* +Package interfaces is a generated VPP binary API of the 'interface' VPP module. + +It is generated from this file: + interface.api.json + +It contains these VPP binary API objects: + 47 messages + 3 types + 23 services +*/ package interfaces import "git.fd.io/govpp.git/api" +import "github.com/lunixbochs/struc" +import "bytes" -// VlibCounter represents the VPP binary API data type 'vlib_counter'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 1301: +// Reference imports to suppress errors if they are not otherwise used. +var _ = struc.Pack +var _ = bytes.NewBuffer + +/* Types */ + +// VlibCounter represents the VPP binary API type 'vlib_counter'. +// Generated from 'interface.api.json', line 1348: // // "vlib_counter", // [ @@ -33,8 +52,8 @@ func (*VlibCounter) GetCrcString() string { return "ce2325a2" } -// VnetCombinedCounter represents the VPP binary API data type 'vnet_combined_counter'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 1315: +// VnetCombinedCounter represents the VPP binary API type 'vnet_combined_counter'. +// Generated from 'interface.api.json', line 1362: // // "vnet_combined_counter", // [ @@ -136,8 +155,8 @@ func (*VnetCombinedCounter) GetCrcString() string { return "20905ca4" } -// VnetSimpleCounter represents the VPP binary API data type 'vnet_simple_counter'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 1389: +// VnetSimpleCounter represents the VPP binary API type 'vnet_simple_counter'. +// Generated from 'interface.api.json', line 1436: // // "vnet_simple_counter", // [ @@ -204,8 +223,10 @@ func (*VnetSimpleCounter) GetCrcString() string { return "8bd65e2d" } +/* Messages */ + // SwInterfaceSetFlags represents the VPP binary API message 'sw_interface_set_flags'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 4: +// Generated from 'interface.api.json', line 4: // // "sw_interface_set_flags", // [ @@ -240,18 +261,18 @@ type SwInterfaceSetFlags struct { func (*SwInterfaceSetFlags) GetMessageName() string { return "sw_interface_set_flags" } -func (*SwInterfaceSetFlags) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceSetFlags) GetCrcString() string { return "555485f5" } +func (*SwInterfaceSetFlags) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceSetFlags() api.Message { return &SwInterfaceSetFlags{} } // SwInterfaceSetFlagsReply represents the VPP binary API message 'sw_interface_set_flags_reply'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 30: +// Generated from 'interface.api.json', line 30: // // "sw_interface_set_flags_reply", // [ @@ -277,18 +298,18 @@ type SwInterfaceSetFlagsReply struct { func (*SwInterfaceSetFlagsReply) GetMessageName() string { return "sw_interface_set_flags_reply" } -func (*SwInterfaceSetFlagsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceSetFlagsReply) GetCrcString() string { return "e8d4e804" } +func (*SwInterfaceSetFlagsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceSetFlagsReply() api.Message { return &SwInterfaceSetFlagsReply{} } // HwInterfaceSetMtu represents the VPP binary API message 'hw_interface_set_mtu'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 48: +// Generated from 'interface.api.json', line 48: // // "hw_interface_set_mtu", // [ @@ -323,18 +344,18 @@ type HwInterfaceSetMtu struct { func (*HwInterfaceSetMtu) GetMessageName() string { return "hw_interface_set_mtu" } -func (*HwInterfaceSetMtu) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*HwInterfaceSetMtu) GetCrcString() string { return "132da1e7" } +func (*HwInterfaceSetMtu) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewHwInterfaceSetMtu() api.Message { return &HwInterfaceSetMtu{} } // HwInterfaceSetMtuReply represents the VPP binary API message 'hw_interface_set_mtu_reply'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 74: +// Generated from 'interface.api.json', line 74: // // "hw_interface_set_mtu_reply", // [ @@ -360,18 +381,18 @@ type HwInterfaceSetMtuReply struct { func (*HwInterfaceSetMtuReply) GetMessageName() string { return "hw_interface_set_mtu_reply" } -func (*HwInterfaceSetMtuReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*HwInterfaceSetMtuReply) GetCrcString() string { return "e8d4e804" } +func (*HwInterfaceSetMtuReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewHwInterfaceSetMtuReply() api.Message { return &HwInterfaceSetMtuReply{} } // SwInterfaceSetMtu represents the VPP binary API message 'sw_interface_set_mtu'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 92: +// Generated from 'interface.api.json', line 92: // // "sw_interface_set_mtu", // [ @@ -407,18 +428,18 @@ type SwInterfaceSetMtu struct { func (*SwInterfaceSetMtu) GetMessageName() string { return "sw_interface_set_mtu" } -func (*SwInterfaceSetMtu) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceSetMtu) GetCrcString() string { return "d0008db8" } +func (*SwInterfaceSetMtu) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceSetMtu() api.Message { return &SwInterfaceSetMtu{} } // SwInterfaceSetMtuReply represents the VPP binary API message 'sw_interface_set_mtu_reply'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 119: +// Generated from 'interface.api.json', line 119: // // "sw_interface_set_mtu_reply", // [ @@ -444,18 +465,101 @@ type SwInterfaceSetMtuReply struct { func (*SwInterfaceSetMtuReply) GetMessageName() string { return "sw_interface_set_mtu_reply" } -func (*SwInterfaceSetMtuReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceSetMtuReply) GetCrcString() string { return "e8d4e804" } +func (*SwInterfaceSetMtuReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceSetMtuReply() api.Message { return &SwInterfaceSetMtuReply{} } +// SwInterfaceSetIPDirectedBroadcast represents the VPP binary API message 'sw_interface_set_ip_directed_broadcast'. +// Generated from 'interface.api.json', line 137: +// +// "sw_interface_set_ip_directed_broadcast", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "client_index" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "u32", +// "sw_if_index" +// ], +// [ +// "u8", +// "enable" +// ], +// { +// "crc": "0xa36fadc0" +// } +// +type SwInterfaceSetIPDirectedBroadcast struct { + SwIfIndex uint32 + Enable uint8 +} + +func (*SwInterfaceSetIPDirectedBroadcast) GetMessageName() string { + return "sw_interface_set_ip_directed_broadcast" +} +func (*SwInterfaceSetIPDirectedBroadcast) GetCrcString() string { + return "a36fadc0" +} +func (*SwInterfaceSetIPDirectedBroadcast) GetMessageType() api.MessageType { + return api.RequestMessage +} +func NewSwInterfaceSetIPDirectedBroadcast() api.Message { + return &SwInterfaceSetIPDirectedBroadcast{} +} + +// SwInterfaceSetIPDirectedBroadcastReply represents the VPP binary API message 'sw_interface_set_ip_directed_broadcast_reply'. +// Generated from 'interface.api.json', line 163: +// +// "sw_interface_set_ip_directed_broadcast_reply", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "i32", +// "retval" +// ], +// { +// "crc": "0xe8d4e804" +// } +// +type SwInterfaceSetIPDirectedBroadcastReply struct { + Retval int32 +} + +func (*SwInterfaceSetIPDirectedBroadcastReply) GetMessageName() string { + return "sw_interface_set_ip_directed_broadcast_reply" +} +func (*SwInterfaceSetIPDirectedBroadcastReply) GetCrcString() string { + return "e8d4e804" +} +func (*SwInterfaceSetIPDirectedBroadcastReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} +func NewSwInterfaceSetIPDirectedBroadcastReply() api.Message { + return &SwInterfaceSetIPDirectedBroadcastReply{} +} + // SwInterfaceEvent represents the VPP binary API message 'sw_interface_event'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 137: +// Generated from 'interface.api.json', line 181: // // "sw_interface_event", // [ @@ -491,7 +595,7 @@ func NewSwInterfaceSetMtuReply() api.Message { // } // type SwInterfaceEvent struct { - Pid uint32 + PID uint32 SwIfIndex uint32 AdminUpDown uint8 LinkUpDown uint8 @@ -501,18 +605,18 @@ type SwInterfaceEvent struct { func (*SwInterfaceEvent) GetMessageName() string { return "sw_interface_event" } -func (*SwInterfaceEvent) GetMessageType() api.MessageType { - return api.EventMessage -} func (*SwInterfaceEvent) GetCrcString() string { return "bf9938e4" } +func (*SwInterfaceEvent) GetMessageType() api.MessageType { + return api.EventMessage +} func NewSwInterfaceEvent() api.Message { return &SwInterfaceEvent{} } // WantInterfaceEvents represents the VPP binary API message 'want_interface_events'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 171: +// Generated from 'interface.api.json', line 215: // // "want_interface_events", // [ @@ -541,24 +645,24 @@ func NewSwInterfaceEvent() api.Message { // type WantInterfaceEvents struct { EnableDisable uint32 - Pid uint32 + PID uint32 } func (*WantInterfaceEvents) GetMessageName() string { return "want_interface_events" } -func (*WantInterfaceEvents) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*WantInterfaceEvents) GetCrcString() string { return "476f5a08" } +func (*WantInterfaceEvents) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewWantInterfaceEvents() api.Message { return &WantInterfaceEvents{} } // WantInterfaceEventsReply represents the VPP binary API message 'want_interface_events_reply'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 197: +// Generated from 'interface.api.json', line 241: // // "want_interface_events_reply", // [ @@ -584,18 +688,18 @@ type WantInterfaceEventsReply struct { func (*WantInterfaceEventsReply) GetMessageName() string { return "want_interface_events_reply" } -func (*WantInterfaceEventsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*WantInterfaceEventsReply) GetCrcString() string { return "e8d4e804" } +func (*WantInterfaceEventsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewWantInterfaceEventsReply() api.Message { return &WantInterfaceEventsReply{} } // SwInterfaceDetails represents the VPP binary API message 'sw_interface_details'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 215: +// Generated from 'interface.api.json', line 259: // // "sw_interface_details", // [ @@ -777,18 +881,18 @@ type SwInterfaceDetails struct { func (*SwInterfaceDetails) GetMessageName() string { return "sw_interface_details" } -func (*SwInterfaceDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceDetails) GetCrcString() string { return "09b4b510" } +func (*SwInterfaceDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceDetails() api.Message { return &SwInterfaceDetails{} } // SwInterfaceDump represents the VPP binary API message 'sw_interface_dump'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 359: +// Generated from 'interface.api.json', line 403: // // "sw_interface_dump", // [ @@ -824,18 +928,18 @@ type SwInterfaceDump struct { func (*SwInterfaceDump) GetMessageName() string { return "sw_interface_dump" } -func (*SwInterfaceDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceDump) GetCrcString() string { return "63f5e3b7" } +func (*SwInterfaceDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceDump() api.Message { return &SwInterfaceDump{} } // SwInterfaceAddDelAddress represents the VPP binary API message 'sw_interface_add_del_address'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 386: +// Generated from 'interface.api.json', line 430: // // "sw_interface_add_del_address", // [ @@ -882,7 +986,7 @@ func NewSwInterfaceDump() api.Message { type SwInterfaceAddDelAddress struct { SwIfIndex uint32 IsAdd uint8 - IsIpv6 uint8 + IsIPv6 uint8 DelAll uint8 AddressLength uint8 Address []byte `struc:"[16]byte"` @@ -891,18 +995,18 @@ type SwInterfaceAddDelAddress struct { func (*SwInterfaceAddDelAddress) GetMessageName() string { return "sw_interface_add_del_address" } -func (*SwInterfaceAddDelAddress) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceAddDelAddress) GetCrcString() string { return "7b583179" } +func (*SwInterfaceAddDelAddress) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceAddDelAddress() api.Message { return &SwInterfaceAddDelAddress{} } // SwInterfaceAddDelAddressReply represents the VPP binary API message 'sw_interface_add_del_address_reply'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 429: +// Generated from 'interface.api.json', line 473: // // "sw_interface_add_del_address_reply", // [ @@ -928,18 +1032,18 @@ type SwInterfaceAddDelAddressReply struct { func (*SwInterfaceAddDelAddressReply) GetMessageName() string { return "sw_interface_add_del_address_reply" } -func (*SwInterfaceAddDelAddressReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceAddDelAddressReply) GetCrcString() string { return "e8d4e804" } +func (*SwInterfaceAddDelAddressReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceAddDelAddressReply() api.Message { return &SwInterfaceAddDelAddressReply{} } // SwInterfaceSetTable represents the VPP binary API message 'sw_interface_set_table'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 447: +// Generated from 'interface.api.json', line 491: // // "sw_interface_set_table", // [ @@ -972,25 +1076,25 @@ func NewSwInterfaceAddDelAddressReply() api.Message { // type SwInterfaceSetTable struct { SwIfIndex uint32 - IsIpv6 uint8 + IsIPv6 uint8 VrfID uint32 } func (*SwInterfaceSetTable) GetMessageName() string { return "sw_interface_set_table" } -func (*SwInterfaceSetTable) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceSetTable) GetCrcString() string { return "acb25d89" } +func (*SwInterfaceSetTable) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceSetTable() api.Message { return &SwInterfaceSetTable{} } // SwInterfaceSetTableReply represents the VPP binary API message 'sw_interface_set_table_reply'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 477: +// Generated from 'interface.api.json', line 521: // // "sw_interface_set_table_reply", // [ @@ -1016,18 +1120,18 @@ type SwInterfaceSetTableReply struct { func (*SwInterfaceSetTableReply) GetMessageName() string { return "sw_interface_set_table_reply" } -func (*SwInterfaceSetTableReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceSetTableReply) GetCrcString() string { return "e8d4e804" } +func (*SwInterfaceSetTableReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceSetTableReply() api.Message { return &SwInterfaceSetTableReply{} } // SwInterfaceGetTable represents the VPP binary API message 'sw_interface_get_table'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 495: +// Generated from 'interface.api.json', line 539: // // "sw_interface_get_table", // [ @@ -1056,24 +1160,24 @@ func NewSwInterfaceSetTableReply() api.Message { // type SwInterfaceGetTable struct { SwIfIndex uint32 - IsIpv6 uint8 + IsIPv6 uint8 } func (*SwInterfaceGetTable) GetMessageName() string { return "sw_interface_get_table" } -func (*SwInterfaceGetTable) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceGetTable) GetCrcString() string { return "6b7bcd0a" } +func (*SwInterfaceGetTable) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceGetTable() api.Message { return &SwInterfaceGetTable{} } // SwInterfaceGetTableReply represents the VPP binary API message 'sw_interface_get_table_reply'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 521: +// Generated from 'interface.api.json', line 565: // // "sw_interface_get_table_reply", // [ @@ -1104,18 +1208,18 @@ type SwInterfaceGetTableReply struct { func (*SwInterfaceGetTableReply) GetMessageName() string { return "sw_interface_get_table_reply" } -func (*SwInterfaceGetTableReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceGetTableReply) GetCrcString() string { return "a6eb0109" } +func (*SwInterfaceGetTableReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceGetTableReply() api.Message { return &SwInterfaceGetTableReply{} } // SwInterfaceSetUnnumbered represents the VPP binary API message 'sw_interface_set_unnumbered'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 543: +// Generated from 'interface.api.json', line 587: // // "sw_interface_set_unnumbered", // [ @@ -1155,18 +1259,18 @@ type SwInterfaceSetUnnumbered struct { func (*SwInterfaceSetUnnumbered) GetMessageName() string { return "sw_interface_set_unnumbered" } -func (*SwInterfaceSetUnnumbered) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceSetUnnumbered) GetCrcString() string { return "a2c1bbda" } +func (*SwInterfaceSetUnnumbered) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceSetUnnumbered() api.Message { return &SwInterfaceSetUnnumbered{} } // SwInterfaceSetUnnumberedReply represents the VPP binary API message 'sw_interface_set_unnumbered_reply'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 573: +// Generated from 'interface.api.json', line 617: // // "sw_interface_set_unnumbered_reply", // [ @@ -1192,18 +1296,18 @@ type SwInterfaceSetUnnumberedReply struct { func (*SwInterfaceSetUnnumberedReply) GetMessageName() string { return "sw_interface_set_unnumbered_reply" } -func (*SwInterfaceSetUnnumberedReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceSetUnnumberedReply) GetCrcString() string { return "e8d4e804" } +func (*SwInterfaceSetUnnumberedReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceSetUnnumberedReply() api.Message { return &SwInterfaceSetUnnumberedReply{} } // SwInterfaceClearStats represents the VPP binary API message 'sw_interface_clear_stats'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 591: +// Generated from 'interface.api.json', line 635: // // "sw_interface_clear_stats", // [ @@ -1233,18 +1337,18 @@ type SwInterfaceClearStats struct { func (*SwInterfaceClearStats) GetMessageName() string { return "sw_interface_clear_stats" } -func (*SwInterfaceClearStats) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceClearStats) GetCrcString() string { return "529cb13f" } +func (*SwInterfaceClearStats) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceClearStats() api.Message { return &SwInterfaceClearStats{} } // SwInterfaceClearStatsReply represents the VPP binary API message 'sw_interface_clear_stats_reply'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 613: +// Generated from 'interface.api.json', line 657: // // "sw_interface_clear_stats_reply", // [ @@ -1270,18 +1374,18 @@ type SwInterfaceClearStatsReply struct { func (*SwInterfaceClearStatsReply) GetMessageName() string { return "sw_interface_clear_stats_reply" } -func (*SwInterfaceClearStatsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceClearStatsReply) GetCrcString() string { return "e8d4e804" } +func (*SwInterfaceClearStatsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceClearStatsReply() api.Message { return &SwInterfaceClearStatsReply{} } // SwInterfaceTagAddDel represents the VPP binary API message 'sw_interface_tag_add_del'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 631: +// Generated from 'interface.api.json', line 675: // // "sw_interface_tag_add_del", // [ @@ -1322,18 +1426,18 @@ type SwInterfaceTagAddDel struct { func (*SwInterfaceTagAddDel) GetMessageName() string { return "sw_interface_tag_add_del" } -func (*SwInterfaceTagAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceTagAddDel) GetCrcString() string { return "14cc636c" } +func (*SwInterfaceTagAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceTagAddDel() api.Message { return &SwInterfaceTagAddDel{} } // SwInterfaceTagAddDelReply represents the VPP binary API message 'sw_interface_tag_add_del_reply'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 662: +// Generated from 'interface.api.json', line 706: // // "sw_interface_tag_add_del_reply", // [ @@ -1359,18 +1463,18 @@ type SwInterfaceTagAddDelReply struct { func (*SwInterfaceTagAddDelReply) GetMessageName() string { return "sw_interface_tag_add_del_reply" } -func (*SwInterfaceTagAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceTagAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*SwInterfaceTagAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceTagAddDelReply() api.Message { return &SwInterfaceTagAddDelReply{} } // SwInterfaceSetMacAddress represents the VPP binary API message 'sw_interface_set_mac_address'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 680: +// Generated from 'interface.api.json', line 724: // // "sw_interface_set_mac_address", // [ @@ -1406,18 +1510,18 @@ type SwInterfaceSetMacAddress struct { func (*SwInterfaceSetMacAddress) GetMessageName() string { return "sw_interface_set_mac_address" } -func (*SwInterfaceSetMacAddress) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceSetMacAddress) GetCrcString() string { return "eed5dfca" } +func (*SwInterfaceSetMacAddress) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceSetMacAddress() api.Message { return &SwInterfaceSetMacAddress{} } // SwInterfaceSetMacAddressReply represents the VPP binary API message 'sw_interface_set_mac_address_reply'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 707: +// Generated from 'interface.api.json', line 751: // // "sw_interface_set_mac_address_reply", // [ @@ -1443,18 +1547,18 @@ type SwInterfaceSetMacAddressReply struct { func (*SwInterfaceSetMacAddressReply) GetMessageName() string { return "sw_interface_set_mac_address_reply" } -func (*SwInterfaceSetMacAddressReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceSetMacAddressReply) GetCrcString() string { return "e8d4e804" } +func (*SwInterfaceSetMacAddressReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceSetMacAddressReply() api.Message { return &SwInterfaceSetMacAddressReply{} } // SwInterfaceGetMacAddress represents the VPP binary API message 'sw_interface_get_mac_address'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 725: +// Generated from 'interface.api.json', line 769: // // "sw_interface_get_mac_address", // [ @@ -1484,18 +1588,18 @@ type SwInterfaceGetMacAddress struct { func (*SwInterfaceGetMacAddress) GetMessageName() string { return "sw_interface_get_mac_address" } -func (*SwInterfaceGetMacAddress) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceGetMacAddress) GetCrcString() string { return "529cb13f" } +func (*SwInterfaceGetMacAddress) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceGetMacAddress() api.Message { return &SwInterfaceGetMacAddress{} } // SwInterfaceGetMacAddressReply represents the VPP binary API message 'sw_interface_get_mac_address_reply'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 747: +// Generated from 'interface.api.json', line 791: // // "sw_interface_get_mac_address_reply", // [ @@ -1527,18 +1631,18 @@ type SwInterfaceGetMacAddressReply struct { func (*SwInterfaceGetMacAddressReply) GetMessageName() string { return "sw_interface_get_mac_address_reply" } -func (*SwInterfaceGetMacAddressReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceGetMacAddressReply) GetCrcString() string { return "8ea538d3" } +func (*SwInterfaceGetMacAddressReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceGetMacAddressReply() api.Message { return &SwInterfaceGetMacAddressReply{} } // SwInterfaceSetRxMode represents the VPP binary API message 'sw_interface_set_rx_mode'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 770: +// Generated from 'interface.api.json', line 814: // // "sw_interface_set_rx_mode", // [ @@ -1583,18 +1687,18 @@ type SwInterfaceSetRxMode struct { func (*SwInterfaceSetRxMode) GetMessageName() string { return "sw_interface_set_rx_mode" } -func (*SwInterfaceSetRxMode) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceSetRxMode) GetCrcString() string { return "2a1cc58c" } +func (*SwInterfaceSetRxMode) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceSetRxMode() api.Message { return &SwInterfaceSetRxMode{} } // SwInterfaceSetRxModeReply represents the VPP binary API message 'sw_interface_set_rx_mode_reply'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 804: +// Generated from 'interface.api.json', line 848: // // "sw_interface_set_rx_mode_reply", // [ @@ -1620,18 +1724,18 @@ type SwInterfaceSetRxModeReply struct { func (*SwInterfaceSetRxModeReply) GetMessageName() string { return "sw_interface_set_rx_mode_reply" } -func (*SwInterfaceSetRxModeReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceSetRxModeReply) GetCrcString() string { return "e8d4e804" } +func (*SwInterfaceSetRxModeReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceSetRxModeReply() api.Message { return &SwInterfaceSetRxModeReply{} } // InterfaceNameRenumber represents the VPP binary API message 'interface_name_renumber'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 822: +// Generated from 'interface.api.json', line 866: // // "interface_name_renumber", // [ @@ -1666,18 +1770,18 @@ type InterfaceNameRenumber struct { func (*InterfaceNameRenumber) GetMessageName() string { return "interface_name_renumber" } -func (*InterfaceNameRenumber) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*InterfaceNameRenumber) GetCrcString() string { return "39194269" } +func (*InterfaceNameRenumber) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewInterfaceNameRenumber() api.Message { return &InterfaceNameRenumber{} } // InterfaceNameRenumberReply represents the VPP binary API message 'interface_name_renumber_reply'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 848: +// Generated from 'interface.api.json', line 892: // // "interface_name_renumber_reply", // [ @@ -1703,18 +1807,18 @@ type InterfaceNameRenumberReply struct { func (*InterfaceNameRenumberReply) GetMessageName() string { return "interface_name_renumber_reply" } -func (*InterfaceNameRenumberReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*InterfaceNameRenumberReply) GetCrcString() string { return "e8d4e804" } +func (*InterfaceNameRenumberReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewInterfaceNameRenumberReply() api.Message { return &InterfaceNameRenumberReply{} } // CreateSubif represents the VPP binary API message 'create_subif'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 866: +// Generated from 'interface.api.json', line 910: // // "create_subif", // [ @@ -1799,18 +1903,18 @@ type CreateSubif struct { func (*CreateSubif) GetMessageName() string { return "create_subif" } -func (*CreateSubif) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*CreateSubif) GetCrcString() string { return "86cfe408" } +func (*CreateSubif) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewCreateSubif() api.Message { return &CreateSubif{} } // CreateSubifReply represents the VPP binary API message 'create_subif_reply'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 932: +// Generated from 'interface.api.json', line 976: // // "create_subif_reply", // [ @@ -1841,18 +1945,18 @@ type CreateSubifReply struct { func (*CreateSubifReply) GetMessageName() string { return "create_subif_reply" } -func (*CreateSubifReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*CreateSubifReply) GetCrcString() string { return "fda5941f" } +func (*CreateSubifReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewCreateSubifReply() api.Message { return &CreateSubifReply{} } // CreateVlanSubif represents the VPP binary API message 'create_vlan_subif'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 954: +// Generated from 'interface.api.json', line 998: // // "create_vlan_subif", // [ @@ -1887,18 +1991,18 @@ type CreateVlanSubif struct { func (*CreateVlanSubif) GetMessageName() string { return "create_vlan_subif" } -func (*CreateVlanSubif) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*CreateVlanSubif) GetCrcString() string { return "70cadeda" } +func (*CreateVlanSubif) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewCreateVlanSubif() api.Message { return &CreateVlanSubif{} } // CreateVlanSubifReply represents the VPP binary API message 'create_vlan_subif_reply'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 980: +// Generated from 'interface.api.json', line 1024: // // "create_vlan_subif_reply", // [ @@ -1929,18 +2033,18 @@ type CreateVlanSubifReply struct { func (*CreateVlanSubifReply) GetMessageName() string { return "create_vlan_subif_reply" } -func (*CreateVlanSubifReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*CreateVlanSubifReply) GetCrcString() string { return "fda5941f" } +func (*CreateVlanSubifReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewCreateVlanSubifReply() api.Message { return &CreateVlanSubifReply{} } // DeleteSubif represents the VPP binary API message 'delete_subif'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 1002: +// Generated from 'interface.api.json', line 1046: // // "delete_subif", // [ @@ -1970,18 +2074,18 @@ type DeleteSubif struct { func (*DeleteSubif) GetMessageName() string { return "delete_subif" } -func (*DeleteSubif) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*DeleteSubif) GetCrcString() string { return "529cb13f" } +func (*DeleteSubif) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewDeleteSubif() api.Message { return &DeleteSubif{} } // DeleteSubifReply represents the VPP binary API message 'delete_subif_reply'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 1024: +// Generated from 'interface.api.json', line 1068: // // "delete_subif_reply", // [ @@ -2007,18 +2111,18 @@ type DeleteSubifReply struct { func (*DeleteSubifReply) GetMessageName() string { return "delete_subif_reply" } -func (*DeleteSubifReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*DeleteSubifReply) GetCrcString() string { return "e8d4e804" } +func (*DeleteSubifReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewDeleteSubifReply() api.Message { return &DeleteSubifReply{} } // CreateLoopback represents the VPP binary API message 'create_loopback'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 1042: +// Generated from 'interface.api.json', line 1086: // // "create_loopback", // [ @@ -2049,18 +2153,18 @@ type CreateLoopback struct { func (*CreateLoopback) GetMessageName() string { return "create_loopback" } -func (*CreateLoopback) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*CreateLoopback) GetCrcString() string { return "3b54129c" } +func (*CreateLoopback) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewCreateLoopback() api.Message { return &CreateLoopback{} } // CreateLoopbackReply represents the VPP binary API message 'create_loopback_reply'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 1065: +// Generated from 'interface.api.json', line 1109: // // "create_loopback_reply", // [ @@ -2091,18 +2195,18 @@ type CreateLoopbackReply struct { func (*CreateLoopbackReply) GetMessageName() string { return "create_loopback_reply" } -func (*CreateLoopbackReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*CreateLoopbackReply) GetCrcString() string { return "fda5941f" } +func (*CreateLoopbackReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewCreateLoopbackReply() api.Message { return &CreateLoopbackReply{} } // CreateLoopbackInstance represents the VPP binary API message 'create_loopback_instance'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 1087: +// Generated from 'interface.api.json', line 1131: // // "create_loopback_instance", // [ @@ -2143,18 +2247,18 @@ type CreateLoopbackInstance struct { func (*CreateLoopbackInstance) GetMessageName() string { return "create_loopback_instance" } -func (*CreateLoopbackInstance) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*CreateLoopbackInstance) GetCrcString() string { return "7bbd53b6" } +func (*CreateLoopbackInstance) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewCreateLoopbackInstance() api.Message { return &CreateLoopbackInstance{} } // CreateLoopbackInstanceReply represents the VPP binary API message 'create_loopback_instance_reply'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 1118: +// Generated from 'interface.api.json', line 1162: // // "create_loopback_instance_reply", // [ @@ -2185,18 +2289,18 @@ type CreateLoopbackInstanceReply struct { func (*CreateLoopbackInstanceReply) GetMessageName() string { return "create_loopback_instance_reply" } -func (*CreateLoopbackInstanceReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*CreateLoopbackInstanceReply) GetCrcString() string { return "fda5941f" } +func (*CreateLoopbackInstanceReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewCreateLoopbackInstanceReply() api.Message { return &CreateLoopbackInstanceReply{} } // DeleteLoopback represents the VPP binary API message 'delete_loopback'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 1140: +// Generated from 'interface.api.json', line 1184: // // "delete_loopback", // [ @@ -2226,18 +2330,18 @@ type DeleteLoopback struct { func (*DeleteLoopback) GetMessageName() string { return "delete_loopback" } -func (*DeleteLoopback) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*DeleteLoopback) GetCrcString() string { return "529cb13f" } +func (*DeleteLoopback) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewDeleteLoopback() api.Message { return &DeleteLoopback{} } // DeleteLoopbackReply represents the VPP binary API message 'delete_loopback_reply'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 1162: +// Generated from 'interface.api.json', line 1206: // // "delete_loopback_reply", // [ @@ -2263,18 +2367,18 @@ type DeleteLoopbackReply struct { func (*DeleteLoopbackReply) GetMessageName() string { return "delete_loopback_reply" } -func (*DeleteLoopbackReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*DeleteLoopbackReply) GetCrcString() string { return "e8d4e804" } +func (*DeleteLoopbackReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewDeleteLoopbackReply() api.Message { return &DeleteLoopbackReply{} } // CollectDetailedInterfaceStats represents the VPP binary API message 'collect_detailed_interface_stats'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 1180: +// Generated from 'interface.api.json', line 1224: // // "collect_detailed_interface_stats", // [ @@ -2309,18 +2413,18 @@ type CollectDetailedInterfaceStats struct { func (*CollectDetailedInterfaceStats) GetMessageName() string { return "collect_detailed_interface_stats" } -func (*CollectDetailedInterfaceStats) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*CollectDetailedInterfaceStats) GetCrcString() string { return "69d24598" } +func (*CollectDetailedInterfaceStats) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewCollectDetailedInterfaceStats() api.Message { return &CollectDetailedInterfaceStats{} } // CollectDetailedInterfaceStatsReply represents the VPP binary API message 'collect_detailed_interface_stats_reply'. -// Generated from '/usr/share/vpp/api/interface.api.json', line 1206: +// Generated from 'interface.api.json', line 1250: // // "collect_detailed_interface_stats_reply", // [ @@ -2346,12 +2450,90 @@ type CollectDetailedInterfaceStatsReply struct { func (*CollectDetailedInterfaceStatsReply) GetMessageName() string { return "collect_detailed_interface_stats_reply" } -func (*CollectDetailedInterfaceStatsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*CollectDetailedInterfaceStatsReply) GetCrcString() string { return "e8d4e804" } +func (*CollectDetailedInterfaceStatsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewCollectDetailedInterfaceStatsReply() api.Message { return &CollectDetailedInterfaceStatsReply{} } + +/* Services */ + +type Services interface { + DumpSwInterface(*SwInterfaceDump) (*SwInterfaceDetails, error) + CollectDetailedInterfaceStats(*CollectDetailedInterfaceStats) (*CollectDetailedInterfaceStatsReply, error) + CreateLoopback(*CreateLoopback) (*CreateLoopbackReply, error) + CreateLoopbackInstance(*CreateLoopbackInstance) (*CreateLoopbackInstanceReply, error) + CreateSubif(*CreateSubif) (*CreateSubifReply, error) + CreateVlanSubif(*CreateVlanSubif) (*CreateVlanSubifReply, error) + DeleteLoopback(*DeleteLoopback) (*DeleteLoopbackReply, error) + DeleteSubif(*DeleteSubif) (*DeleteSubifReply, error) + HwInterfaceSetMtu(*HwInterfaceSetMtu) (*HwInterfaceSetMtuReply, error) + InterfaceNameRenumber(*InterfaceNameRenumber) (*InterfaceNameRenumberReply, error) + SwInterfaceAddDelAddress(*SwInterfaceAddDelAddress) (*SwInterfaceAddDelAddressReply, error) + SwInterfaceClearStats(*SwInterfaceClearStats) (*SwInterfaceClearStatsReply, error) + SwInterfaceGetMacAddress(*SwInterfaceGetMacAddress) (*SwInterfaceGetMacAddressReply, error) + SwInterfaceGetTable(*SwInterfaceGetTable) (*SwInterfaceGetTableReply, error) + SwInterfaceSetFlags(*SwInterfaceSetFlags) (*SwInterfaceSetFlagsReply, error) + SwInterfaceSetIPDirectedBroadcast(*SwInterfaceSetIPDirectedBroadcast) (*SwInterfaceSetIPDirectedBroadcastReply, error) + SwInterfaceSetMacAddress(*SwInterfaceSetMacAddress) (*SwInterfaceSetMacAddressReply, error) + SwInterfaceSetMtu(*SwInterfaceSetMtu) (*SwInterfaceSetMtuReply, error) + SwInterfaceSetRxMode(*SwInterfaceSetRxMode) (*SwInterfaceSetRxModeReply, error) + SwInterfaceSetTable(*SwInterfaceSetTable) (*SwInterfaceSetTableReply, error) + SwInterfaceSetUnnumbered(*SwInterfaceSetUnnumbered) (*SwInterfaceSetUnnumberedReply, error) + SwInterfaceTagAddDel(*SwInterfaceTagAddDel) (*SwInterfaceTagAddDelReply, error) + WantInterfaceEvents(*WantInterfaceEvents) (*WantInterfaceEventsReply, error) +} + +func init() { + api.RegisterMessage((*SwInterfaceSetFlags)(nil), "interface.SwInterfaceSetFlags") + api.RegisterMessage((*SwInterfaceSetFlagsReply)(nil), "interface.SwInterfaceSetFlagsReply") + api.RegisterMessage((*HwInterfaceSetMtu)(nil), "interface.HwInterfaceSetMtu") + api.RegisterMessage((*HwInterfaceSetMtuReply)(nil), "interface.HwInterfaceSetMtuReply") + api.RegisterMessage((*SwInterfaceSetMtu)(nil), "interface.SwInterfaceSetMtu") + api.RegisterMessage((*SwInterfaceSetMtuReply)(nil), "interface.SwInterfaceSetMtuReply") + api.RegisterMessage((*SwInterfaceSetIPDirectedBroadcast)(nil), "interface.SwInterfaceSetIPDirectedBroadcast") + api.RegisterMessage((*SwInterfaceSetIPDirectedBroadcastReply)(nil), "interface.SwInterfaceSetIPDirectedBroadcastReply") + api.RegisterMessage((*SwInterfaceEvent)(nil), "interface.SwInterfaceEvent") + api.RegisterMessage((*WantInterfaceEvents)(nil), "interface.WantInterfaceEvents") + api.RegisterMessage((*WantInterfaceEventsReply)(nil), "interface.WantInterfaceEventsReply") + api.RegisterMessage((*SwInterfaceDetails)(nil), "interface.SwInterfaceDetails") + api.RegisterMessage((*SwInterfaceDump)(nil), "interface.SwInterfaceDump") + api.RegisterMessage((*SwInterfaceAddDelAddress)(nil), "interface.SwInterfaceAddDelAddress") + api.RegisterMessage((*SwInterfaceAddDelAddressReply)(nil), "interface.SwInterfaceAddDelAddressReply") + api.RegisterMessage((*SwInterfaceSetTable)(nil), "interface.SwInterfaceSetTable") + api.RegisterMessage((*SwInterfaceSetTableReply)(nil), "interface.SwInterfaceSetTableReply") + api.RegisterMessage((*SwInterfaceGetTable)(nil), "interface.SwInterfaceGetTable") + api.RegisterMessage((*SwInterfaceGetTableReply)(nil), "interface.SwInterfaceGetTableReply") + api.RegisterMessage((*SwInterfaceSetUnnumbered)(nil), "interface.SwInterfaceSetUnnumbered") + api.RegisterMessage((*SwInterfaceSetUnnumberedReply)(nil), "interface.SwInterfaceSetUnnumberedReply") + api.RegisterMessage((*SwInterfaceClearStats)(nil), "interface.SwInterfaceClearStats") + api.RegisterMessage((*SwInterfaceClearStatsReply)(nil), "interface.SwInterfaceClearStatsReply") + api.RegisterMessage((*SwInterfaceTagAddDel)(nil), "interface.SwInterfaceTagAddDel") + api.RegisterMessage((*SwInterfaceTagAddDelReply)(nil), "interface.SwInterfaceTagAddDelReply") + api.RegisterMessage((*SwInterfaceSetMacAddress)(nil), "interface.SwInterfaceSetMacAddress") + api.RegisterMessage((*SwInterfaceSetMacAddressReply)(nil), "interface.SwInterfaceSetMacAddressReply") + api.RegisterMessage((*SwInterfaceGetMacAddress)(nil), "interface.SwInterfaceGetMacAddress") + api.RegisterMessage((*SwInterfaceGetMacAddressReply)(nil), "interface.SwInterfaceGetMacAddressReply") + api.RegisterMessage((*SwInterfaceSetRxMode)(nil), "interface.SwInterfaceSetRxMode") + api.RegisterMessage((*SwInterfaceSetRxModeReply)(nil), "interface.SwInterfaceSetRxModeReply") + api.RegisterMessage((*InterfaceNameRenumber)(nil), "interface.InterfaceNameRenumber") + api.RegisterMessage((*InterfaceNameRenumberReply)(nil), "interface.InterfaceNameRenumberReply") + api.RegisterMessage((*CreateSubif)(nil), "interface.CreateSubif") + api.RegisterMessage((*CreateSubifReply)(nil), "interface.CreateSubifReply") + api.RegisterMessage((*CreateVlanSubif)(nil), "interface.CreateVlanSubif") + api.RegisterMessage((*CreateVlanSubifReply)(nil), "interface.CreateVlanSubifReply") + api.RegisterMessage((*DeleteSubif)(nil), "interface.DeleteSubif") + api.RegisterMessage((*DeleteSubifReply)(nil), "interface.DeleteSubifReply") + api.RegisterMessage((*CreateLoopback)(nil), "interface.CreateLoopback") + api.RegisterMessage((*CreateLoopbackReply)(nil), "interface.CreateLoopbackReply") + api.RegisterMessage((*CreateLoopbackInstance)(nil), "interface.CreateLoopbackInstance") + api.RegisterMessage((*CreateLoopbackInstanceReply)(nil), "interface.CreateLoopbackInstanceReply") + api.RegisterMessage((*DeleteLoopback)(nil), "interface.DeleteLoopback") + api.RegisterMessage((*DeleteLoopbackReply)(nil), "interface.DeleteLoopbackReply") + api.RegisterMessage((*CollectDetailedInterfaceStats)(nil), "interface.CollectDetailedInterfaceStats") + api.RegisterMessage((*CollectDetailedInterfaceStatsReply)(nil), "interface.CollectDetailedInterfaceStatsReply") +} diff --git a/plugins/vpp/binapi/interfaces/pkgreflect.go b/plugins/vpp/binapi/interfaces/pkgreflect.go index c48192ab74..7f75cecba5 100644 --- a/plugins/vpp/binapi/interfaces/pkgreflect.go +++ b/plugins/vpp/binapi/interfaces/pkgreflect.go @@ -23,6 +23,7 @@ var Types = map[string]reflect.Type{ "HwInterfaceSetMtuReply": reflect.TypeOf((*HwInterfaceSetMtuReply)(nil)).Elem(), "InterfaceNameRenumber": reflect.TypeOf((*InterfaceNameRenumber)(nil)).Elem(), "InterfaceNameRenumberReply": reflect.TypeOf((*InterfaceNameRenumberReply)(nil)).Elem(), + "Services": reflect.TypeOf((*Services)(nil)).Elem(), "SwInterfaceAddDelAddress": reflect.TypeOf((*SwInterfaceAddDelAddress)(nil)).Elem(), "SwInterfaceAddDelAddressReply": reflect.TypeOf((*SwInterfaceAddDelAddressReply)(nil)).Elem(), "SwInterfaceClearStats": reflect.TypeOf((*SwInterfaceClearStats)(nil)).Elem(), @@ -36,6 +37,8 @@ var Types = map[string]reflect.Type{ "SwInterfaceGetTableReply": reflect.TypeOf((*SwInterfaceGetTableReply)(nil)).Elem(), "SwInterfaceSetFlags": reflect.TypeOf((*SwInterfaceSetFlags)(nil)).Elem(), "SwInterfaceSetFlagsReply": reflect.TypeOf((*SwInterfaceSetFlagsReply)(nil)).Elem(), + "SwInterfaceSetIPDirectedBroadcast": reflect.TypeOf((*SwInterfaceSetIPDirectedBroadcast)(nil)).Elem(), + "SwInterfaceSetIPDirectedBroadcastReply": reflect.TypeOf((*SwInterfaceSetIPDirectedBroadcastReply)(nil)).Elem(), "SwInterfaceSetMacAddress": reflect.TypeOf((*SwInterfaceSetMacAddress)(nil)).Elem(), "SwInterfaceSetMacAddressReply": reflect.TypeOf((*SwInterfaceSetMacAddressReply)(nil)).Elem(), "SwInterfaceSetMtu": reflect.TypeOf((*SwInterfaceSetMtu)(nil)).Elem(), @@ -87,6 +90,8 @@ var Functions = map[string]reflect.Value{ "NewSwInterfaceGetTableReply": reflect.ValueOf(NewSwInterfaceGetTableReply), "NewSwInterfaceSetFlags": reflect.ValueOf(NewSwInterfaceSetFlags), "NewSwInterfaceSetFlagsReply": reflect.ValueOf(NewSwInterfaceSetFlagsReply), + "NewSwInterfaceSetIPDirectedBroadcast": reflect.ValueOf(NewSwInterfaceSetIPDirectedBroadcast), + "NewSwInterfaceSetIPDirectedBroadcastReply": reflect.ValueOf(NewSwInterfaceSetIPDirectedBroadcastReply), "NewSwInterfaceSetMacAddress": reflect.ValueOf(NewSwInterfaceSetMacAddress), "NewSwInterfaceSetMacAddressReply": reflect.ValueOf(NewSwInterfaceSetMacAddressReply), "NewSwInterfaceSetMtu": reflect.ValueOf(NewSwInterfaceSetMtu), diff --git a/plugins/vpp/binapi/ip/ip.go b/plugins/vpp/binapi/ip/ip.ba.go similarity index 84% rename from plugins/vpp/binapi/ip/ip.go rename to plugins/vpp/binapi/ip/ip.ba.go index e07738eb32..bb4d982263 100644 --- a/plugins/vpp/binapi/ip/ip.go +++ b/plugins/vpp/binapi/ip/ip.ba.go @@ -1,12 +1,200 @@ -// Code generated by govpp binapi-generator DO NOT EDIT. -// Package ip represents the VPP binary API of the 'ip' VPP module. -// Generated from '/usr/share/vpp/api/ip.api.json' +// Code generated by GoVPP binapi-generator. DO NOT EDIT. +// source: /usr/share/vpp/api/ip.api.json + +/* +Package ip is a generated VPP binary API of the 'ip' VPP module. + +It is generated from this file: + ip.api.json + +It contains these VPP binary API objects: + 87 messages + 9 types + 1 enum + 1 union + 42 services +*/ package ip import "git.fd.io/govpp.git/api" +import "github.com/lunixbochs/struc" +import "bytes" -// FibMplsLabel represents the VPP binary API data type 'fib_mpls_label'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2713: +// Reference imports to suppress errors if they are not otherwise used. +var _ = struc.Pack +var _ = bytes.NewBuffer + +/* Enums */ + +// AddressFamily represents the VPP binary API enum 'address_family'. +// Generated from 'ip.api.json', line 2727: +// +// "address_family", +// [ +// "ADDRESS_IP4", +// 0 +// ], +// [ +// "ADDRESS_IP6", +// 1 +// ], +// { +// "enumtype": "u32" +// } +// +type AddressFamily uint32 + +const ( + ADDRESS_IP4 AddressFamily = 0 + ADDRESS_IP6 AddressFamily = 1 +) + +/* Types */ + +// IP4Address represents the VPP binary API type 'ip4_address'. +// Generated from 'ip.api.json', line 2743: +// +// "ip4_address", +// [ +// "u8", +// "address", +// 4 +// ], +// { +// "crc": "0xfc4baa28" +// } +// +type IP4Address struct { + Address []byte `struc:"[4]byte"` +} + +func (*IP4Address) GetTypeName() string { + return "ip4_address" +} +func (*IP4Address) GetCrcString() string { + return "fc4baa28" +} + +// IP6Address represents the VPP binary API type 'ip6_address'. +// Generated from 'ip.api.json', line 2754: +// +// "ip6_address", +// [ +// "u8", +// "address", +// 16 +// ], +// { +// "crc": "0xad99ccc2" +// } +// +type IP6Address struct { + Address []byte `struc:"[16]byte"` +} + +func (*IP6Address) GetTypeName() string { + return "ip6_address" +} +func (*IP6Address) GetCrcString() string { + return "ad99ccc2" +} + +// Address represents the VPP binary API type 'address'. +// Generated from 'ip.api.json', line 2765: +// +// "address", +// [ +// "vl_api_address_family_t", +// "af" +// ], +// [ +// "vl_api_address_union_t", +// "un" +// ], +// { +// "crc": "0x09f11671" +// } +// +type Address struct { + Af AddressFamily + Un AddressUnion +} + +func (*Address) GetTypeName() string { + return "address" +} +func (*Address) GetCrcString() string { + return "09f11671" +} + +// Prefix represents the VPP binary API type 'prefix'. +// Generated from 'ip.api.json', line 2779: +// +// "prefix", +// [ +// "vl_api_address_t", +// "address" +// ], +// [ +// "u8", +// "address_length" +// ], +// { +// "crc": "0x0403aebc" +// } +// +type Prefix struct { + Address Address + AddressLength uint8 +} + +func (*Prefix) GetTypeName() string { + return "prefix" +} +func (*Prefix) GetCrcString() string { + return "0403aebc" +} + +// Mprefix represents the VPP binary API type 'mprefix'. +// Generated from 'ip.api.json', line 2793: +// +// "mprefix", +// [ +// "vl_api_address_family_t", +// "af" +// ], +// [ +// "u16", +// "grp_address_length" +// ], +// [ +// "vl_api_address_union_t", +// "grp_address" +// ], +// [ +// "vl_api_address_union_t", +// "src_address" +// ], +// { +// "crc": "0x1c4cba05" +// } +// +type Mprefix struct { + Af AddressFamily + GrpAddressLength uint16 + GrpAddress AddressUnion + SrcAddress AddressUnion +} + +func (*Mprefix) GetTypeName() string { + return "mprefix" +} +func (*Mprefix) GetCrcString() string { + return "1c4cba05" +} + +// FibMplsLabel represents the VPP binary API type 'fib_mpls_label'. +// Generated from 'ip.api.json', line 2815: // // "fib_mpls_label", // [ @@ -43,8 +231,8 @@ func (*FibMplsLabel) GetCrcString() string { return "c93bf35c" } -// FibPath represents the VPP binary API data type 'fib_path'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2735: +// FibPath represents the VPP binary API type 'fib_path'. +// Generated from 'ip.api.json', line 2837: // // "fib_path", // [ @@ -163,8 +351,8 @@ func (*FibPath) GetCrcString() string { return "abe483ef" } -// IP6RaPrefixInfo represents the VPP binary API data type 'ip6_ra_prefix_info'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2823: +// IP6RaPrefixInfo represents the VPP binary API type 'ip6_ra_prefix_info'. +// Generated from 'ip.api.json', line 2925: // // "ip6_ra_prefix_info", // [ @@ -207,8 +395,8 @@ func (*IP6RaPrefixInfo) GetCrcString() string { return "83d7c6e5" } -// ProxyArp represents the VPP binary API data type 'proxy_arp'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2850: +// ProxyArp represents the VPP binary API type 'proxy_arp'. +// Generated from 'ip.api.json', line 2952: // // "proxy_arp", // [ @@ -242,8 +430,65 @@ func (*ProxyArp) GetCrcString() string { return "6d88106e" } +/* Unions */ + +// AddressUnion represents the VPP binary API union 'address_union'. +// Generated from 'ip.api.json', line 2562: +// +// "address_union", +// [ +// "vl_api_ip4_address_t", +// "ip4" +// ], +// [ +// "vl_api_ip6_address_t", +// "ip6" +// ], +// { +// "crc": "0xd68a2fb4" +// } +// +type AddressUnion struct { + Union_data [16]byte +} + +func (*AddressUnion) GetTypeName() string { + return "address_union" +} +func (*AddressUnion) GetCrcString() string { + return "d68a2fb4" +} + +func (u *AddressUnion) SetIP4(a IP4Address) { + var b = new(bytes.Buffer) + if err := struc.Pack(b, &a); err != nil { + return + } + copy(u.Union_data[:], b.Bytes()) +} +func (u *AddressUnion) GetIP4() (a IP4Address) { + var b = bytes.NewReader(u.Union_data[:]) + struc.Unpack(b, &a) + return +} + +func (u *AddressUnion) SetIP6(a IP6Address) { + var b = new(bytes.Buffer) + if err := struc.Pack(b, &a); err != nil { + return + } + copy(u.Union_data[:], b.Bytes()) +} +func (u *AddressUnion) GetIP6() (a IP6Address) { + var b = bytes.NewReader(u.Union_data[:]) + struc.Unpack(b, &a) + return +} + +/* Messages */ + // IPTableAddDel represents the VPP binary API message 'ip_table_add_del'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 4: +// Generated from 'ip.api.json', line 4: // // "ip_table_add_del", // [ @@ -281,7 +526,7 @@ func (*ProxyArp) GetCrcString() string { // type IPTableAddDel struct { TableID uint32 - IsIpv6 uint8 + IsIPv6 uint8 IsAdd uint8 Name []byte `struc:"[64]byte"` } @@ -289,18 +534,18 @@ type IPTableAddDel struct { func (*IPTableAddDel) GetMessageName() string { return "ip_table_add_del" } -func (*IPTableAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPTableAddDel) GetCrcString() string { return "0240c89d" } +func (*IPTableAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPTableAddDel() api.Message { return &IPTableAddDel{} } // IPTableAddDelReply represents the VPP binary API message 'ip_table_add_del_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 39: +// Generated from 'ip.api.json', line 39: // // "ip_table_add_del_reply", // [ @@ -326,18 +571,18 @@ type IPTableAddDelReply struct { func (*IPTableAddDelReply) GetMessageName() string { return "ip_table_add_del_reply" } -func (*IPTableAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IPTableAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*IPTableAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIPTableAddDelReply() api.Message { return &IPTableAddDelReply{} } // IPFibDump represents the VPP binary API message 'ip_fib_dump'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 57: +// Generated from 'ip.api.json', line 57: // // "ip_fib_dump", // [ @@ -356,24 +601,23 @@ func NewIPTableAddDelReply() api.Message { // "crc": "0x51077d14" // } // -type IPFibDump struct { -} +type IPFibDump struct{} func (*IPFibDump) GetMessageName() string { return "ip_fib_dump" } -func (*IPFibDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPFibDump) GetCrcString() string { return "51077d14" } +func (*IPFibDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPFibDump() api.Message { return &IPFibDump{} } // IPFibDetails represents the VPP binary API message 'ip_fib_details'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 75: +// Generated from 'ip.api.json', line 75: // // "ip_fib_details", // [ @@ -428,18 +672,18 @@ type IPFibDetails struct { func (*IPFibDetails) GetMessageName() string { return "ip_fib_details" } -func (*IPFibDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IPFibDetails) GetCrcString() string { return "99dfd73b" } +func (*IPFibDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIPFibDetails() api.Message { return &IPFibDetails{} } // IP6FibDump represents the VPP binary API message 'ip6_fib_dump'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 117: +// Generated from 'ip.api.json', line 117: // // "ip6_fib_dump", // [ @@ -458,24 +702,23 @@ func NewIPFibDetails() api.Message { // "crc": "0x51077d14" // } // -type IP6FibDump struct { -} +type IP6FibDump struct{} func (*IP6FibDump) GetMessageName() string { return "ip6_fib_dump" } -func (*IP6FibDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IP6FibDump) GetCrcString() string { return "51077d14" } +func (*IP6FibDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIP6FibDump() api.Message { return &IP6FibDump{} } // IP6FibDetails represents the VPP binary API message 'ip6_fib_details'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 135: +// Generated from 'ip.api.json', line 135: // // "ip6_fib_details", // [ @@ -530,18 +773,18 @@ type IP6FibDetails struct { func (*IP6FibDetails) GetMessageName() string { return "ip6_fib_details" } -func (*IP6FibDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IP6FibDetails) GetCrcString() string { return "abd0060e" } +func (*IP6FibDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIP6FibDetails() api.Message { return &IP6FibDetails{} } // IPNeighborDump represents the VPP binary API message 'ip_neighbor_dump'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 177: +// Generated from 'ip.api.json', line 177: // // "ip_neighbor_dump", // [ @@ -570,24 +813,24 @@ func NewIP6FibDetails() api.Message { // type IPNeighborDump struct { SwIfIndex uint32 - IsIpv6 uint8 + IsIPv6 uint8 } func (*IPNeighborDump) GetMessageName() string { return "ip_neighbor_dump" } -func (*IPNeighborDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPNeighborDump) GetCrcString() string { return "6b7bcd0a" } +func (*IPNeighborDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPNeighborDump() api.Message { return &IPNeighborDump{} } // IPNeighborDetails represents the VPP binary API message 'ip_neighbor_details'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 203: +// Generated from 'ip.api.json', line 203: // // "ip_neighbor_details", // [ @@ -627,7 +870,7 @@ func NewIPNeighborDump() api.Message { type IPNeighborDetails struct { SwIfIndex uint32 IsStatic uint8 - IsIpv6 uint8 + IsIPv6 uint8 MacAddress []byte `struc:"[6]byte"` IPAddress []byte `struc:"[16]byte"` } @@ -635,18 +878,18 @@ type IPNeighborDetails struct { func (*IPNeighborDetails) GetMessageName() string { return "ip_neighbor_details" } -func (*IPNeighborDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IPNeighborDetails) GetCrcString() string { return "85e32a72" } +func (*IPNeighborDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIPNeighborDetails() api.Message { return &IPNeighborDetails{} } // IPNeighborAddDel represents the VPP binary API message 'ip_neighbor_add_del'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 239: +// Generated from 'ip.api.json', line 239: // // "ip_neighbor_add_del", // [ @@ -698,7 +941,7 @@ func NewIPNeighborDetails() api.Message { type IPNeighborAddDel struct { SwIfIndex uint32 IsAdd uint8 - IsIpv6 uint8 + IsIPv6 uint8 IsStatic uint8 IsNoAdjFib uint8 MacAddress []byte `struc:"[6]byte"` @@ -708,18 +951,18 @@ type IPNeighborAddDel struct { func (*IPNeighborAddDel) GetMessageName() string { return "ip_neighbor_add_del" } -func (*IPNeighborAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPNeighborAddDel) GetCrcString() string { return "4711eb25" } +func (*IPNeighborAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPNeighborAddDel() api.Message { return &IPNeighborAddDel{} } // IPNeighborAddDelReply represents the VPP binary API message 'ip_neighbor_add_del_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 287: +// Generated from 'ip.api.json', line 287: // // "ip_neighbor_add_del_reply", // [ @@ -745,18 +988,18 @@ type IPNeighborAddDelReply struct { func (*IPNeighborAddDelReply) GetMessageName() string { return "ip_neighbor_add_del_reply" } -func (*IPNeighborAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IPNeighborAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*IPNeighborAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIPNeighborAddDelReply() api.Message { return &IPNeighborAddDelReply{} } // SetIPFlowHash represents the VPP binary API message 'set_ip_flow_hash'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 305: +// Generated from 'ip.api.json', line 305: // // "set_ip_flow_hash", // [ @@ -809,7 +1052,7 @@ func NewIPNeighborAddDelReply() api.Message { // type SetIPFlowHash struct { VrfID uint32 - IsIpv6 uint8 + IsIPv6 uint8 Src uint8 Dst uint8 Sport uint8 @@ -821,18 +1064,18 @@ type SetIPFlowHash struct { func (*SetIPFlowHash) GetMessageName() string { return "set_ip_flow_hash" } -func (*SetIPFlowHash) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SetIPFlowHash) GetCrcString() string { return "32ebf737" } +func (*SetIPFlowHash) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSetIPFlowHash() api.Message { return &SetIPFlowHash{} } // SetIPFlowHashReply represents the VPP binary API message 'set_ip_flow_hash_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 355: +// Generated from 'ip.api.json', line 355: // // "set_ip_flow_hash_reply", // [ @@ -858,18 +1101,18 @@ type SetIPFlowHashReply struct { func (*SetIPFlowHashReply) GetMessageName() string { return "set_ip_flow_hash_reply" } -func (*SetIPFlowHashReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SetIPFlowHashReply) GetCrcString() string { return "e8d4e804" } +func (*SetIPFlowHashReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSetIPFlowHashReply() api.Message { return &SetIPFlowHashReply{} } // SwInterfaceIP6ndRaConfig represents the VPP binary API message 'sw_interface_ip6nd_ra_config'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 373: +// Generated from 'ip.api.json', line 373: // // "sw_interface_ip6nd_ra_config", // [ @@ -964,18 +1207,18 @@ type SwInterfaceIP6ndRaConfig struct { func (*SwInterfaceIP6ndRaConfig) GetMessageName() string { return "sw_interface_ip6nd_ra_config" } -func (*SwInterfaceIP6ndRaConfig) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceIP6ndRaConfig) GetCrcString() string { return "c3f02daa" } +func (*SwInterfaceIP6ndRaConfig) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceIP6ndRaConfig() api.Message { return &SwInterfaceIP6ndRaConfig{} } // SwInterfaceIP6ndRaConfigReply represents the VPP binary API message 'sw_interface_ip6nd_ra_config_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 447: +// Generated from 'ip.api.json', line 447: // // "sw_interface_ip6nd_ra_config_reply", // [ @@ -1001,18 +1244,18 @@ type SwInterfaceIP6ndRaConfigReply struct { func (*SwInterfaceIP6ndRaConfigReply) GetMessageName() string { return "sw_interface_ip6nd_ra_config_reply" } -func (*SwInterfaceIP6ndRaConfigReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceIP6ndRaConfigReply) GetCrcString() string { return "e8d4e804" } +func (*SwInterfaceIP6ndRaConfigReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceIP6ndRaConfigReply() api.Message { return &SwInterfaceIP6ndRaConfigReply{} } // SwInterfaceIP6ndRaPrefix represents the VPP binary API message 'sw_interface_ip6nd_ra_prefix'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 465: +// Generated from 'ip.api.json', line 465: // // "sw_interface_ip6nd_ra_prefix", // [ @@ -1093,18 +1336,18 @@ type SwInterfaceIP6ndRaPrefix struct { func (*SwInterfaceIP6ndRaPrefix) GetMessageName() string { return "sw_interface_ip6nd_ra_prefix" } -func (*SwInterfaceIP6ndRaPrefix) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceIP6ndRaPrefix) GetCrcString() string { return "ca763c9a" } +func (*SwInterfaceIP6ndRaPrefix) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceIP6ndRaPrefix() api.Message { return &SwInterfaceIP6ndRaPrefix{} } // SwInterfaceIP6ndRaPrefixReply represents the VPP binary API message 'sw_interface_ip6nd_ra_prefix_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 528: +// Generated from 'ip.api.json', line 528: // // "sw_interface_ip6nd_ra_prefix_reply", // [ @@ -1130,18 +1373,18 @@ type SwInterfaceIP6ndRaPrefixReply struct { func (*SwInterfaceIP6ndRaPrefixReply) GetMessageName() string { return "sw_interface_ip6nd_ra_prefix_reply" } -func (*SwInterfaceIP6ndRaPrefixReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceIP6ndRaPrefixReply) GetCrcString() string { return "e8d4e804" } +func (*SwInterfaceIP6ndRaPrefixReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceIP6ndRaPrefixReply() api.Message { return &SwInterfaceIP6ndRaPrefixReply{} } // IP6ndProxyAddDel represents the VPP binary API message 'ip6nd_proxy_add_del'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 546: +// Generated from 'ip.api.json', line 546: // // "ip6nd_proxy_add_del", // [ @@ -1182,18 +1425,18 @@ type IP6ndProxyAddDel struct { func (*IP6ndProxyAddDel) GetMessageName() string { return "ip6nd_proxy_add_del" } -func (*IP6ndProxyAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IP6ndProxyAddDel) GetCrcString() string { return "d95f0fa0" } +func (*IP6ndProxyAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIP6ndProxyAddDel() api.Message { return &IP6ndProxyAddDel{} } // IP6ndProxyAddDelReply represents the VPP binary API message 'ip6nd_proxy_add_del_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 577: +// Generated from 'ip.api.json', line 577: // // "ip6nd_proxy_add_del_reply", // [ @@ -1219,18 +1462,18 @@ type IP6ndProxyAddDelReply struct { func (*IP6ndProxyAddDelReply) GetMessageName() string { return "ip6nd_proxy_add_del_reply" } -func (*IP6ndProxyAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IP6ndProxyAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*IP6ndProxyAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIP6ndProxyAddDelReply() api.Message { return &IP6ndProxyAddDelReply{} } // IP6ndProxyDetails represents the VPP binary API message 'ip6nd_proxy_details'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 595: +// Generated from 'ip.api.json', line 595: // // "ip6nd_proxy_details", // [ @@ -1266,18 +1509,18 @@ type IP6ndProxyDetails struct { func (*IP6ndProxyDetails) GetMessageName() string { return "ip6nd_proxy_details" } -func (*IP6ndProxyDetails) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IP6ndProxyDetails) GetCrcString() string { return "d73bf1ab" } +func (*IP6ndProxyDetails) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIP6ndProxyDetails() api.Message { return &IP6ndProxyDetails{} } // IP6ndProxyDump represents the VPP binary API message 'ip6nd_proxy_dump'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 622: +// Generated from 'ip.api.json', line 622: // // "ip6nd_proxy_dump", // [ @@ -1296,24 +1539,23 @@ func NewIP6ndProxyDetails() api.Message { // "crc": "0x51077d14" // } // -type IP6ndProxyDump struct { -} +type IP6ndProxyDump struct{} func (*IP6ndProxyDump) GetMessageName() string { return "ip6nd_proxy_dump" } -func (*IP6ndProxyDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IP6ndProxyDump) GetCrcString() string { return "51077d14" } +func (*IP6ndProxyDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIP6ndProxyDump() api.Message { return &IP6ndProxyDump{} } // IP6ndSendRouterSolicitation represents the VPP binary API message 'ip6nd_send_router_solicitation'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 640: +// Generated from 'ip.api.json', line 640: // // "ip6nd_send_router_solicitation", // [ @@ -1368,18 +1610,18 @@ type IP6ndSendRouterSolicitation struct { func (*IP6ndSendRouterSolicitation) GetMessageName() string { return "ip6nd_send_router_solicitation" } -func (*IP6ndSendRouterSolicitation) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IP6ndSendRouterSolicitation) GetCrcString() string { return "bd968917" } +func (*IP6ndSendRouterSolicitation) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIP6ndSendRouterSolicitation() api.Message { return &IP6ndSendRouterSolicitation{} } // IP6ndSendRouterSolicitationReply represents the VPP binary API message 'ip6nd_send_router_solicitation_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 682: +// Generated from 'ip.api.json', line 682: // // "ip6nd_send_router_solicitation_reply", // [ @@ -1405,18 +1647,18 @@ type IP6ndSendRouterSolicitationReply struct { func (*IP6ndSendRouterSolicitationReply) GetMessageName() string { return "ip6nd_send_router_solicitation_reply" } -func (*IP6ndSendRouterSolicitationReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IP6ndSendRouterSolicitationReply) GetCrcString() string { return "e8d4e804" } +func (*IP6ndSendRouterSolicitationReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIP6ndSendRouterSolicitationReply() api.Message { return &IP6ndSendRouterSolicitationReply{} } // SwInterfaceIP6EnableDisable represents the VPP binary API message 'sw_interface_ip6_enable_disable'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 700: +// Generated from 'ip.api.json', line 700: // // "sw_interface_ip6_enable_disable", // [ @@ -1451,18 +1693,18 @@ type SwInterfaceIP6EnableDisable struct { func (*SwInterfaceIP6EnableDisable) GetMessageName() string { return "sw_interface_ip6_enable_disable" } -func (*SwInterfaceIP6EnableDisable) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceIP6EnableDisable) GetCrcString() string { return "a36fadc0" } +func (*SwInterfaceIP6EnableDisable) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceIP6EnableDisable() api.Message { return &SwInterfaceIP6EnableDisable{} } // SwInterfaceIP6EnableDisableReply represents the VPP binary API message 'sw_interface_ip6_enable_disable_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 726: +// Generated from 'ip.api.json', line 726: // // "sw_interface_ip6_enable_disable_reply", // [ @@ -1488,18 +1730,18 @@ type SwInterfaceIP6EnableDisableReply struct { func (*SwInterfaceIP6EnableDisableReply) GetMessageName() string { return "sw_interface_ip6_enable_disable_reply" } -func (*SwInterfaceIP6EnableDisableReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceIP6EnableDisableReply) GetCrcString() string { return "e8d4e804" } +func (*SwInterfaceIP6EnableDisableReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceIP6EnableDisableReply() api.Message { return &SwInterfaceIP6EnableDisableReply{} } // SwInterfaceIP6SetLinkLocalAddress represents the VPP binary API message 'sw_interface_ip6_set_link_local_address'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 744: +// Generated from 'ip.api.json', line 744: // // "sw_interface_ip6_set_link_local_address", // [ @@ -1535,18 +1777,18 @@ type SwInterfaceIP6SetLinkLocalAddress struct { func (*SwInterfaceIP6SetLinkLocalAddress) GetMessageName() string { return "sw_interface_ip6_set_link_local_address" } -func (*SwInterfaceIP6SetLinkLocalAddress) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceIP6SetLinkLocalAddress) GetCrcString() string { return "d73bf1ab" } +func (*SwInterfaceIP6SetLinkLocalAddress) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceIP6SetLinkLocalAddress() api.Message { return &SwInterfaceIP6SetLinkLocalAddress{} } // SwInterfaceIP6SetLinkLocalAddressReply represents the VPP binary API message 'sw_interface_ip6_set_link_local_address_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 771: +// Generated from 'ip.api.json', line 771: // // "sw_interface_ip6_set_link_local_address_reply", // [ @@ -1572,18 +1814,18 @@ type SwInterfaceIP6SetLinkLocalAddressReply struct { func (*SwInterfaceIP6SetLinkLocalAddressReply) GetMessageName() string { return "sw_interface_ip6_set_link_local_address_reply" } -func (*SwInterfaceIP6SetLinkLocalAddressReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceIP6SetLinkLocalAddressReply) GetCrcString() string { return "e8d4e804" } +func (*SwInterfaceIP6SetLinkLocalAddressReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceIP6SetLinkLocalAddressReply() api.Message { return &SwInterfaceIP6SetLinkLocalAddressReply{} } // IPAddDelRoute represents the VPP binary API message 'ip_add_del_route'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 789: +// Generated from 'ip.api.json', line 789: // // "ip_add_del_route", // [ @@ -1724,7 +1966,7 @@ type IPAddDelRoute struct { IsDrop uint8 IsUnreach uint8 IsProhibit uint8 - IsIpv6 uint8 + IsIPv6 uint8 IsLocal uint8 IsClassify uint8 IsMultipath uint8 @@ -1747,18 +1989,18 @@ type IPAddDelRoute struct { func (*IPAddDelRoute) GetMessageName() string { return "ip_add_del_route" } -func (*IPAddDelRoute) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPAddDelRoute) GetCrcString() string { return "4219d62d" } +func (*IPAddDelRoute) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPAddDelRoute() api.Message { return &IPAddDelRoute{} } // IPAddDelRouteReply represents the VPP binary API message 'ip_add_del_route_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 919: +// Generated from 'ip.api.json', line 919: // // "ip_add_del_route_reply", // [ @@ -1784,18 +2026,18 @@ type IPAddDelRouteReply struct { func (*IPAddDelRouteReply) GetMessageName() string { return "ip_add_del_route_reply" } -func (*IPAddDelRouteReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IPAddDelRouteReply) GetCrcString() string { return "e8d4e804" } +func (*IPAddDelRouteReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIPAddDelRouteReply() api.Message { return &IPAddDelRouteReply{} } // IPMrouteAddDel represents the VPP binary API message 'ip_mroute_add_del'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 937: +// Generated from 'ip.api.json', line 937: // // "ip_mroute_add_del", // [ @@ -1883,7 +2125,7 @@ type IPMrouteAddDel struct { GrpAddressLength uint16 NextHopAfi uint8 IsAdd uint8 - IsIpv6 uint8 + IsIPv6 uint8 IsLocal uint8 GrpAddress []byte `struc:"[16]byte"` SrcAddress []byte `struc:"[16]byte"` @@ -1893,18 +2135,18 @@ type IPMrouteAddDel struct { func (*IPMrouteAddDel) GetMessageName() string { return "ip_mroute_add_del" } -func (*IPMrouteAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPMrouteAddDel) GetCrcString() string { return "f44c17b1" } +func (*IPMrouteAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPMrouteAddDel() api.Message { return &IPMrouteAddDel{} } // IPMrouteAddDelReply represents the VPP binary API message 'ip_mroute_add_del_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1014: +// Generated from 'ip.api.json', line 1014: // // "ip_mroute_add_del_reply", // [ @@ -1930,18 +2172,18 @@ type IPMrouteAddDelReply struct { func (*IPMrouteAddDelReply) GetMessageName() string { return "ip_mroute_add_del_reply" } -func (*IPMrouteAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IPMrouteAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*IPMrouteAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIPMrouteAddDelReply() api.Message { return &IPMrouteAddDelReply{} } // IPMfibDump represents the VPP binary API message 'ip_mfib_dump'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1032: +// Generated from 'ip.api.json', line 1032: // // "ip_mfib_dump", // [ @@ -1960,24 +2202,23 @@ func NewIPMrouteAddDelReply() api.Message { // "crc": "0x51077d14" // } // -type IPMfibDump struct { -} +type IPMfibDump struct{} func (*IPMfibDump) GetMessageName() string { return "ip_mfib_dump" } -func (*IPMfibDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPMfibDump) GetCrcString() string { return "51077d14" } +func (*IPMfibDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPMfibDump() api.Message { return &IPMfibDump{} } // IPMfibDetails represents the VPP binary API message 'ip_mfib_details'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1050: +// Generated from 'ip.api.json', line 1050: // // "ip_mfib_details", // [ @@ -2042,18 +2283,18 @@ type IPMfibDetails struct { func (*IPMfibDetails) GetMessageName() string { return "ip_mfib_details" } -func (*IPMfibDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IPMfibDetails) GetCrcString() string { return "5e530d5e" } +func (*IPMfibDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIPMfibDetails() api.Message { return &IPMfibDetails{} } // IP6MfibDump represents the VPP binary API message 'ip6_mfib_dump'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1100: +// Generated from 'ip.api.json', line 1100: // // "ip6_mfib_dump", // [ @@ -2072,24 +2313,23 @@ func NewIPMfibDetails() api.Message { // "crc": "0x51077d14" // } // -type IP6MfibDump struct { -} +type IP6MfibDump struct{} func (*IP6MfibDump) GetMessageName() string { return "ip6_mfib_dump" } -func (*IP6MfibDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IP6MfibDump) GetCrcString() string { return "51077d14" } +func (*IP6MfibDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIP6MfibDump() api.Message { return &IP6MfibDump{} } // IP6MfibDetails represents the VPP binary API message 'ip6_mfib_details'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1118: +// Generated from 'ip.api.json', line 1118: // // "ip6_mfib_details", // [ @@ -2144,18 +2384,18 @@ type IP6MfibDetails struct { func (*IP6MfibDetails) GetMessageName() string { return "ip6_mfib_details" } -func (*IP6MfibDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IP6MfibDetails) GetCrcString() string { return "e02dcb4b" } +func (*IP6MfibDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIP6MfibDetails() api.Message { return &IP6MfibDetails{} } // IPAddressDetails represents the VPP binary API message 'ip_address_details'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1160: +// Generated from 'ip.api.json', line 1160: // // "ip_address_details", // [ @@ -2195,24 +2435,24 @@ type IPAddressDetails struct { IP []byte `struc:"[16]byte"` PrefixLength uint8 SwIfIndex uint32 - IsIpv6 uint8 + IsIPv6 uint8 } func (*IPAddressDetails) GetMessageName() string { return "ip_address_details" } -func (*IPAddressDetails) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPAddressDetails) GetCrcString() string { return "bc7442f2" } +func (*IPAddressDetails) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPAddressDetails() api.Message { return &IPAddressDetails{} } // IPAddressDump represents the VPP binary API message 'ip_address_dump'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1195: +// Generated from 'ip.api.json', line 1195: // // "ip_address_dump", // [ @@ -2241,24 +2481,24 @@ func NewIPAddressDetails() api.Message { // type IPAddressDump struct { SwIfIndex uint32 - IsIpv6 uint8 + IsIPv6 uint8 } func (*IPAddressDump) GetMessageName() string { return "ip_address_dump" } -func (*IPAddressDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPAddressDump) GetCrcString() string { return "6b7bcd0a" } +func (*IPAddressDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPAddressDump() api.Message { return &IPAddressDump{} } // IPUnnumberedDetails represents the VPP binary API message 'ip_unnumbered_details'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1221: +// Generated from 'ip.api.json', line 1221: // // "ip_unnumbered_details", // [ @@ -2293,18 +2533,18 @@ type IPUnnumberedDetails struct { func (*IPUnnumberedDetails) GetMessageName() string { return "ip_unnumbered_details" } -func (*IPUnnumberedDetails) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPUnnumberedDetails) GetCrcString() string { return "05b717ca" } +func (*IPUnnumberedDetails) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPUnnumberedDetails() api.Message { return &IPUnnumberedDetails{} } // IPUnnumberedDump represents the VPP binary API message 'ip_unnumbered_dump'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1247: +// Generated from 'ip.api.json', line 1247: // // "ip_unnumbered_dump", // [ @@ -2334,18 +2574,18 @@ type IPUnnumberedDump struct { func (*IPUnnumberedDump) GetMessageName() string { return "ip_unnumbered_dump" } -func (*IPUnnumberedDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPUnnumberedDump) GetCrcString() string { return "529cb13f" } +func (*IPUnnumberedDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPUnnumberedDump() api.Message { return &IPUnnumberedDump{} } // IPDetails represents the VPP binary API message 'ip_details'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1269: +// Generated from 'ip.api.json', line 1269: // // "ip_details", // [ @@ -2354,41 +2594,40 @@ func NewIPUnnumberedDump() api.Message { // ], // [ // "u32", -// "sw_if_index" +// "context" // ], // [ // "u32", -// "context" +// "sw_if_index" // ], // [ // "u8", // "is_ipv6" // ], // { -// "crc": "0x452ffc5a" +// "crc": "0x8bb37ec4" // } // type IPDetails struct { SwIfIndex uint32 - Context uint32 - IsIpv6 uint8 + IsIPv6 uint8 } func (*IPDetails) GetMessageName() string { return "ip_details" } -func (*IPDetails) GetMessageType() api.MessageType { - return api.OtherMessage -} func (*IPDetails) GetCrcString() string { - return "452ffc5a" + return "8bb37ec4" +} +func (*IPDetails) GetMessageType() api.MessageType { + return api.ReplyMessage } func NewIPDetails() api.Message { return &IPDetails{} } // IPDump represents the VPP binary API message 'ip_dump'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1291: +// Generated from 'ip.api.json', line 1291: // // "ip_dump", // [ @@ -2412,24 +2651,24 @@ func NewIPDetails() api.Message { // } // type IPDump struct { - IsIpv6 uint8 + IsIPv6 uint8 } func (*IPDump) GetMessageName() string { return "ip_dump" } -func (*IPDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPDump) GetCrcString() string { return "de883da4" } +func (*IPDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPDump() api.Message { return &IPDump{} } // MfibSignalDump represents the VPP binary API message 'mfib_signal_dump'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1313: +// Generated from 'ip.api.json', line 1313: // // "mfib_signal_dump", // [ @@ -2448,24 +2687,23 @@ func NewIPDump() api.Message { // "crc": "0x51077d14" // } // -type MfibSignalDump struct { -} +type MfibSignalDump struct{} func (*MfibSignalDump) GetMessageName() string { return "mfib_signal_dump" } -func (*MfibSignalDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*MfibSignalDump) GetCrcString() string { return "51077d14" } +func (*MfibSignalDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewMfibSignalDump() api.Message { return &MfibSignalDump{} } // MfibSignalDetails represents the VPP binary API message 'mfib_signal_details'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1331: +// Generated from 'ip.api.json', line 1331: // // "mfib_signal_details", // [ @@ -2528,18 +2766,18 @@ type MfibSignalDetails struct { func (*MfibSignalDetails) GetMessageName() string { return "mfib_signal_details" } -func (*MfibSignalDetails) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*MfibSignalDetails) GetCrcString() string { return "791bbeab" } +func (*MfibSignalDetails) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewMfibSignalDetails() api.Message { return &MfibSignalDetails{} } // IPPuntPolice represents the VPP binary API message 'ip_punt_police'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1380: +// Generated from 'ip.api.json', line 1380: // // "ip_punt_police", // [ @@ -2579,18 +2817,18 @@ type IPPuntPolice struct { func (*IPPuntPolice) GetMessageName() string { return "ip_punt_police" } -func (*IPPuntPolice) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPPuntPolice) GetCrcString() string { return "38691592" } +func (*IPPuntPolice) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPPuntPolice() api.Message { return &IPPuntPolice{} } // IPPuntPoliceReply represents the VPP binary API message 'ip_punt_police_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1410: +// Generated from 'ip.api.json', line 1410: // // "ip_punt_police_reply", // [ @@ -2616,18 +2854,18 @@ type IPPuntPoliceReply struct { func (*IPPuntPoliceReply) GetMessageName() string { return "ip_punt_police_reply" } -func (*IPPuntPoliceReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IPPuntPoliceReply) GetCrcString() string { return "e8d4e804" } +func (*IPPuntPoliceReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIPPuntPoliceReply() api.Message { return &IPPuntPoliceReply{} } // IPPuntRedirect represents the VPP binary API message 'ip_punt_redirect'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1428: +// Generated from 'ip.api.json', line 1428: // // "ip_punt_redirect", // [ @@ -2678,18 +2916,18 @@ type IPPuntRedirect struct { func (*IPPuntRedirect) GetMessageName() string { return "ip_punt_redirect" } -func (*IPPuntRedirect) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPPuntRedirect) GetCrcString() string { return "996b6603" } +func (*IPPuntRedirect) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPPuntRedirect() api.Message { return &IPPuntRedirect{} } // IPPuntRedirectReply represents the VPP binary API message 'ip_punt_redirect_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1467: +// Generated from 'ip.api.json', line 1467: // // "ip_punt_redirect_reply", // [ @@ -2715,18 +2953,18 @@ type IPPuntRedirectReply struct { func (*IPPuntRedirectReply) GetMessageName() string { return "ip_punt_redirect_reply" } -func (*IPPuntRedirectReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IPPuntRedirectReply) GetCrcString() string { return "e8d4e804" } +func (*IPPuntRedirectReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIPPuntRedirectReply() api.Message { return &IPPuntRedirectReply{} } // IPContainerProxyAddDel represents the VPP binary API message 'ip_container_proxy_add_del'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1485: +// Generated from 'ip.api.json', line 1485: // // "ip_container_proxy_add_del", // [ @@ -2777,18 +3015,18 @@ type IPContainerProxyAddDel struct { func (*IPContainerProxyAddDel) GetMessageName() string { return "ip_container_proxy_add_del" } -func (*IPContainerProxyAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPContainerProxyAddDel) GetCrcString() string { return "0a355d39" } +func (*IPContainerProxyAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPContainerProxyAddDel() api.Message { return &IPContainerProxyAddDel{} } // IPContainerProxyAddDelReply represents the VPP binary API message 'ip_container_proxy_add_del_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1524: +// Generated from 'ip.api.json', line 1524: // // "ip_container_proxy_add_del_reply", // [ @@ -2814,18 +3052,18 @@ type IPContainerProxyAddDelReply struct { func (*IPContainerProxyAddDelReply) GetMessageName() string { return "ip_container_proxy_add_del_reply" } -func (*IPContainerProxyAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IPContainerProxyAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*IPContainerProxyAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIPContainerProxyAddDelReply() api.Message { return &IPContainerProxyAddDelReply{} } // IPSourceAndPortRangeCheckAddDel represents the VPP binary API message 'ip_source_and_port_range_check_add_del'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1542: +// Generated from 'ip.api.json', line 1542: // // "ip_source_and_port_range_check_add_del", // [ @@ -2880,7 +3118,7 @@ func NewIPContainerProxyAddDelReply() api.Message { // } // type IPSourceAndPortRangeCheckAddDel struct { - IsIpv6 uint8 + IsIPv6 uint8 IsAdd uint8 MaskLength uint8 Address []byte `struc:"[16]byte"` @@ -2893,18 +3131,18 @@ type IPSourceAndPortRangeCheckAddDel struct { func (*IPSourceAndPortRangeCheckAddDel) GetMessageName() string { return "ip_source_and_port_range_check_add_del" } -func (*IPSourceAndPortRangeCheckAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPSourceAndPortRangeCheckAddDel) GetCrcString() string { return "03d6b03a" } +func (*IPSourceAndPortRangeCheckAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPSourceAndPortRangeCheckAddDel() api.Message { return &IPSourceAndPortRangeCheckAddDel{} } // IPSourceAndPortRangeCheckAddDelReply represents the VPP binary API message 'ip_source_and_port_range_check_add_del_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1595: +// Generated from 'ip.api.json', line 1595: // // "ip_source_and_port_range_check_add_del_reply", // [ @@ -2930,18 +3168,18 @@ type IPSourceAndPortRangeCheckAddDelReply struct { func (*IPSourceAndPortRangeCheckAddDelReply) GetMessageName() string { return "ip_source_and_port_range_check_add_del_reply" } -func (*IPSourceAndPortRangeCheckAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IPSourceAndPortRangeCheckAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*IPSourceAndPortRangeCheckAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIPSourceAndPortRangeCheckAddDelReply() api.Message { return &IPSourceAndPortRangeCheckAddDelReply{} } // IPSourceAndPortRangeCheckInterfaceAddDel represents the VPP binary API message 'ip_source_and_port_range_check_interface_add_del'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1613: +// Generated from 'ip.api.json', line 1613: // // "ip_source_and_port_range_check_interface_add_del", // [ @@ -2996,18 +3234,18 @@ type IPSourceAndPortRangeCheckInterfaceAddDel struct { func (*IPSourceAndPortRangeCheckInterfaceAddDel) GetMessageName() string { return "ip_source_and_port_range_check_interface_add_del" } -func (*IPSourceAndPortRangeCheckInterfaceAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPSourceAndPortRangeCheckInterfaceAddDel) GetCrcString() string { return "6966bc44" } +func (*IPSourceAndPortRangeCheckInterfaceAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPSourceAndPortRangeCheckInterfaceAddDel() api.Message { return &IPSourceAndPortRangeCheckInterfaceAddDel{} } // IPSourceAndPortRangeCheckInterfaceAddDelReply represents the VPP binary API message 'ip_source_and_port_range_check_interface_add_del_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1655: +// Generated from 'ip.api.json', line 1655: // // "ip_source_and_port_range_check_interface_add_del_reply", // [ @@ -3033,18 +3271,18 @@ type IPSourceAndPortRangeCheckInterfaceAddDelReply struct { func (*IPSourceAndPortRangeCheckInterfaceAddDelReply) GetMessageName() string { return "ip_source_and_port_range_check_interface_add_del_reply" } -func (*IPSourceAndPortRangeCheckInterfaceAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IPSourceAndPortRangeCheckInterfaceAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*IPSourceAndPortRangeCheckInterfaceAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIPSourceAndPortRangeCheckInterfaceAddDelReply() api.Message { return &IPSourceAndPortRangeCheckInterfaceAddDelReply{} } // IPScanNeighborEnableDisable represents the VPP binary API message 'ip_scan_neighbor_enable_disable'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1673: +// Generated from 'ip.api.json', line 1673: // // "ip_scan_neighbor_enable_disable", // [ @@ -3099,18 +3337,18 @@ type IPScanNeighborEnableDisable struct { func (*IPScanNeighborEnableDisable) GetMessageName() string { return "ip_scan_neighbor_enable_disable" } -func (*IPScanNeighborEnableDisable) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPScanNeighborEnableDisable) GetCrcString() string { return "0a6bf57a" } +func (*IPScanNeighborEnableDisable) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPScanNeighborEnableDisable() api.Message { return &IPScanNeighborEnableDisable{} } // IPScanNeighborEnableDisableReply represents the VPP binary API message 'ip_scan_neighbor_enable_disable_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1715: +// Generated from 'ip.api.json', line 1715: // // "ip_scan_neighbor_enable_disable_reply", // [ @@ -3136,18 +3374,18 @@ type IPScanNeighborEnableDisableReply struct { func (*IPScanNeighborEnableDisableReply) GetMessageName() string { return "ip_scan_neighbor_enable_disable_reply" } -func (*IPScanNeighborEnableDisableReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IPScanNeighborEnableDisableReply) GetCrcString() string { return "e8d4e804" } +func (*IPScanNeighborEnableDisableReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIPScanNeighborEnableDisableReply() api.Message { return &IPScanNeighborEnableDisableReply{} } // IPProbeNeighbor represents the VPP binary API message 'ip_probe_neighbor'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1733: +// Generated from 'ip.api.json', line 1733: // // "ip_probe_neighbor", // [ @@ -3182,24 +3420,24 @@ func NewIPScanNeighborEnableDisableReply() api.Message { type IPProbeNeighbor struct { SwIfIndex uint32 DstAddress []byte `struc:"[16]byte"` - IsIpv6 uint8 + IsIPv6 uint8 } func (*IPProbeNeighbor) GetMessageName() string { return "ip_probe_neighbor" } -func (*IPProbeNeighbor) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPProbeNeighbor) GetCrcString() string { return "1e44bfd7" } +func (*IPProbeNeighbor) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPProbeNeighbor() api.Message { return &IPProbeNeighbor{} } // IPProbeNeighborReply represents the VPP binary API message 'ip_probe_neighbor_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1764: +// Generated from 'ip.api.json', line 1764: // // "ip_probe_neighbor_reply", // [ @@ -3225,18 +3463,18 @@ type IPProbeNeighborReply struct { func (*IPProbeNeighborReply) GetMessageName() string { return "ip_probe_neighbor_reply" } -func (*IPProbeNeighborReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IPProbeNeighborReply) GetCrcString() string { return "e8d4e804" } +func (*IPProbeNeighborReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIPProbeNeighborReply() api.Message { return &IPProbeNeighborReply{} } // WantIP4ArpEvents represents the VPP binary API message 'want_ip4_arp_events'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1782: +// Generated from 'ip.api.json', line 1782: // // "want_ip4_arp_events", // [ @@ -3269,25 +3507,25 @@ func NewIPProbeNeighborReply() api.Message { // type WantIP4ArpEvents struct { EnableDisable uint8 - Pid uint32 + PID uint32 Address uint32 } func (*WantIP4ArpEvents) GetMessageName() string { return "want_ip4_arp_events" } -func (*WantIP4ArpEvents) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*WantIP4ArpEvents) GetCrcString() string { return "77e06379" } +func (*WantIP4ArpEvents) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewWantIP4ArpEvents() api.Message { return &WantIP4ArpEvents{} } // WantIP4ArpEventsReply represents the VPP binary API message 'want_ip4_arp_events_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1812: +// Generated from 'ip.api.json', line 1812: // // "want_ip4_arp_events_reply", // [ @@ -3313,18 +3551,18 @@ type WantIP4ArpEventsReply struct { func (*WantIP4ArpEventsReply) GetMessageName() string { return "want_ip4_arp_events_reply" } -func (*WantIP4ArpEventsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*WantIP4ArpEventsReply) GetCrcString() string { return "e8d4e804" } +func (*WantIP4ArpEventsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewWantIP4ArpEventsReply() api.Message { return &WantIP4ArpEventsReply{} } // IP4ArpEvent represents the VPP binary API message 'ip4_arp_event'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1830: +// Generated from 'ip.api.json', line 1830: // // "ip4_arp_event", // [ @@ -3362,7 +3600,7 @@ func NewWantIP4ArpEventsReply() api.Message { // type IP4ArpEvent struct { Address uint32 - Pid uint32 + PID uint32 SwIfIndex uint32 NewMac []byte `struc:"[6]byte"` MacIP uint8 @@ -3371,18 +3609,18 @@ type IP4ArpEvent struct { func (*IP4ArpEvent) GetMessageName() string { return "ip4_arp_event" } -func (*IP4ArpEvent) GetMessageType() api.MessageType { - return api.EventMessage -} func (*IP4ArpEvent) GetCrcString() string { return "ef7235f7" } +func (*IP4ArpEvent) GetMessageType() api.MessageType { + return api.EventMessage +} func NewIP4ArpEvent() api.Message { return &IP4ArpEvent{} } // WantIP6NdEvents represents the VPP binary API message 'want_ip6_nd_events'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1865: +// Generated from 'ip.api.json', line 1865: // // "want_ip6_nd_events", // [ @@ -3416,25 +3654,25 @@ func NewIP4ArpEvent() api.Message { // type WantIP6NdEvents struct { EnableDisable uint8 - Pid uint32 + PID uint32 Address []byte `struc:"[16]byte"` } func (*WantIP6NdEvents) GetMessageName() string { return "want_ip6_nd_events" } -func (*WantIP6NdEvents) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*WantIP6NdEvents) GetCrcString() string { return "1cf65fbb" } +func (*WantIP6NdEvents) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewWantIP6NdEvents() api.Message { return &WantIP6NdEvents{} } // WantIP6NdEventsReply represents the VPP binary API message 'want_ip6_nd_events_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1896: +// Generated from 'ip.api.json', line 1896: // // "want_ip6_nd_events_reply", // [ @@ -3460,18 +3698,18 @@ type WantIP6NdEventsReply struct { func (*WantIP6NdEventsReply) GetMessageName() string { return "want_ip6_nd_events_reply" } -func (*WantIP6NdEventsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*WantIP6NdEventsReply) GetCrcString() string { return "e8d4e804" } +func (*WantIP6NdEventsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewWantIP6NdEventsReply() api.Message { return &WantIP6NdEventsReply{} } // IP6NdEvent represents the VPP binary API message 'ip6_nd_event'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1914: +// Generated from 'ip.api.json', line 1914: // // "ip6_nd_event", // [ @@ -3509,7 +3747,7 @@ func NewWantIP6NdEventsReply() api.Message { // } // type IP6NdEvent struct { - Pid uint32 + PID uint32 SwIfIndex uint32 Address []byte `struc:"[16]byte"` NewMac []byte `struc:"[6]byte"` @@ -3519,18 +3757,18 @@ type IP6NdEvent struct { func (*IP6NdEvent) GetMessageName() string { return "ip6_nd_event" } -func (*IP6NdEvent) GetMessageType() api.MessageType { - return api.EventMessage -} func (*IP6NdEvent) GetCrcString() string { return "96ab2fdd" } +func (*IP6NdEvent) GetMessageType() api.MessageType { + return api.EventMessage +} func NewIP6NdEvent() api.Message { return &IP6NdEvent{} } // WantIP6RaEvents represents the VPP binary API message 'want_ip6_ra_events'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1950: +// Generated from 'ip.api.json', line 1950: // // "want_ip6_ra_events", // [ @@ -3559,24 +3797,24 @@ func NewIP6NdEvent() api.Message { // type WantIP6RaEvents struct { EnableDisable uint8 - Pid uint32 + PID uint32 } func (*WantIP6RaEvents) GetMessageName() string { return "want_ip6_ra_events" } -func (*WantIP6RaEvents) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*WantIP6RaEvents) GetCrcString() string { return "05b454b5" } +func (*WantIP6RaEvents) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewWantIP6RaEvents() api.Message { return &WantIP6RaEvents{} } // WantIP6RaEventsReply represents the VPP binary API message 'want_ip6_ra_events_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1976: +// Generated from 'ip.api.json', line 1976: // // "want_ip6_ra_events_reply", // [ @@ -3602,18 +3840,18 @@ type WantIP6RaEventsReply struct { func (*WantIP6RaEventsReply) GetMessageName() string { return "want_ip6_ra_events_reply" } -func (*WantIP6RaEventsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*WantIP6RaEventsReply) GetCrcString() string { return "e8d4e804" } +func (*WantIP6RaEventsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewWantIP6RaEventsReply() api.Message { return &WantIP6RaEventsReply{} } // IP6RaEvent represents the VPP binary API message 'ip6_ra_event'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 1994: +// Generated from 'ip.api.json', line 1994: // // "ip6_ra_event", // [ @@ -3672,7 +3910,7 @@ func NewWantIP6RaEventsReply() api.Message { // } // type IP6RaEvent struct { - Pid uint32 + PID uint32 SwIfIndex uint32 RouterAddress []byte `struc:"[16]byte"` CurrentHopLimit uint8 @@ -3687,18 +3925,18 @@ type IP6RaEvent struct { func (*IP6RaEvent) GetMessageName() string { return "ip6_ra_event" } -func (*IP6RaEvent) GetMessageType() api.MessageType { - return api.EventMessage -} func (*IP6RaEvent) GetCrcString() string { return "c5e54257" } +func (*IP6RaEvent) GetMessageType() api.MessageType { + return api.EventMessage +} func NewIP6RaEvent() api.Message { return &IP6RaEvent{} } // ProxyArpAddDel represents the VPP binary API message 'proxy_arp_add_del'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2051: +// Generated from 'ip.api.json', line 2051: // // "proxy_arp_add_del", // [ @@ -3733,18 +3971,18 @@ type ProxyArpAddDel struct { func (*ProxyArpAddDel) GetMessageName() string { return "proxy_arp_add_del" } -func (*ProxyArpAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ProxyArpAddDel) GetCrcString() string { return "227988d9" } +func (*ProxyArpAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewProxyArpAddDel() api.Message { return &ProxyArpAddDel{} } // ProxyArpAddDelReply represents the VPP binary API message 'proxy_arp_add_del_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2077: +// Generated from 'ip.api.json', line 2077: // // "proxy_arp_add_del_reply", // [ @@ -3770,18 +4008,18 @@ type ProxyArpAddDelReply struct { func (*ProxyArpAddDelReply) GetMessageName() string { return "proxy_arp_add_del_reply" } -func (*ProxyArpAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ProxyArpAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*ProxyArpAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewProxyArpAddDelReply() api.Message { return &ProxyArpAddDelReply{} } // ProxyArpDump represents the VPP binary API message 'proxy_arp_dump'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2095: +// Generated from 'ip.api.json', line 2095: // // "proxy_arp_dump", // [ @@ -3800,24 +4038,23 @@ func NewProxyArpAddDelReply() api.Message { // "crc": "0x51077d14" // } // -type ProxyArpDump struct { -} +type ProxyArpDump struct{} func (*ProxyArpDump) GetMessageName() string { return "proxy_arp_dump" } -func (*ProxyArpDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ProxyArpDump) GetCrcString() string { return "51077d14" } +func (*ProxyArpDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewProxyArpDump() api.Message { return &ProxyArpDump{} } // ProxyArpDetails represents the VPP binary API message 'proxy_arp_details'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2113: +// Generated from 'ip.api.json', line 2113: // // "proxy_arp_details", // [ @@ -3843,18 +4080,18 @@ type ProxyArpDetails struct { func (*ProxyArpDetails) GetMessageName() string { return "proxy_arp_details" } -func (*ProxyArpDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ProxyArpDetails) GetCrcString() string { return "9b707c77" } +func (*ProxyArpDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewProxyArpDetails() api.Message { return &ProxyArpDetails{} } // ProxyArpIntfcEnableDisable represents the VPP binary API message 'proxy_arp_intfc_enable_disable'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2131: +// Generated from 'ip.api.json', line 2131: // // "proxy_arp_intfc_enable_disable", // [ @@ -3889,18 +4126,18 @@ type ProxyArpIntfcEnableDisable struct { func (*ProxyArpIntfcEnableDisable) GetMessageName() string { return "proxy_arp_intfc_enable_disable" } -func (*ProxyArpIntfcEnableDisable) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ProxyArpIntfcEnableDisable) GetCrcString() string { return "69d24598" } +func (*ProxyArpIntfcEnableDisable) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewProxyArpIntfcEnableDisable() api.Message { return &ProxyArpIntfcEnableDisable{} } // ProxyArpIntfcEnableDisableReply represents the VPP binary API message 'proxy_arp_intfc_enable_disable_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2157: +// Generated from 'ip.api.json', line 2157: // // "proxy_arp_intfc_enable_disable_reply", // [ @@ -3926,18 +4163,18 @@ type ProxyArpIntfcEnableDisableReply struct { func (*ProxyArpIntfcEnableDisableReply) GetMessageName() string { return "proxy_arp_intfc_enable_disable_reply" } -func (*ProxyArpIntfcEnableDisableReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ProxyArpIntfcEnableDisableReply) GetCrcString() string { return "e8d4e804" } +func (*ProxyArpIntfcEnableDisableReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewProxyArpIntfcEnableDisableReply() api.Message { return &ProxyArpIntfcEnableDisableReply{} } // ProxyArpIntfcDump represents the VPP binary API message 'proxy_arp_intfc_dump'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2175: +// Generated from 'ip.api.json', line 2175: // // "proxy_arp_intfc_dump", // [ @@ -3956,24 +4193,23 @@ func NewProxyArpIntfcEnableDisableReply() api.Message { // "crc": "0x51077d14" // } // -type ProxyArpIntfcDump struct { -} +type ProxyArpIntfcDump struct{} func (*ProxyArpIntfcDump) GetMessageName() string { return "proxy_arp_intfc_dump" } -func (*ProxyArpIntfcDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ProxyArpIntfcDump) GetCrcString() string { return "51077d14" } +func (*ProxyArpIntfcDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewProxyArpIntfcDump() api.Message { return &ProxyArpIntfcDump{} } // ProxyArpIntfcDetails represents the VPP binary API message 'proxy_arp_intfc_details'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2193: +// Generated from 'ip.api.json', line 2193: // // "proxy_arp_intfc_details", // [ @@ -3999,18 +4235,18 @@ type ProxyArpIntfcDetails struct { func (*ProxyArpIntfcDetails) GetMessageName() string { return "proxy_arp_intfc_details" } -func (*ProxyArpIntfcDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ProxyArpIntfcDetails) GetCrcString() string { return "f6458e5f" } +func (*ProxyArpIntfcDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewProxyArpIntfcDetails() api.Message { return &ProxyArpIntfcDetails{} } // ResetFib represents the VPP binary API message 'reset_fib'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2211: +// Generated from 'ip.api.json', line 2211: // // "reset_fib", // [ @@ -4039,24 +4275,24 @@ func NewProxyArpIntfcDetails() api.Message { // type ResetFib struct { VrfID uint32 - IsIpv6 uint8 + IsIPv6 uint8 } func (*ResetFib) GetMessageName() string { return "reset_fib" } -func (*ResetFib) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ResetFib) GetCrcString() string { return "8553ebd9" } +func (*ResetFib) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewResetFib() api.Message { return &ResetFib{} } // ResetFibReply represents the VPP binary API message 'reset_fib_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2237: +// Generated from 'ip.api.json', line 2237: // // "reset_fib_reply", // [ @@ -4082,18 +4318,18 @@ type ResetFibReply struct { func (*ResetFibReply) GetMessageName() string { return "reset_fib_reply" } -func (*ResetFibReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ResetFibReply) GetCrcString() string { return "e8d4e804" } +func (*ResetFibReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewResetFibReply() api.Message { return &ResetFibReply{} } // SetArpNeighborLimit represents the VPP binary API message 'set_arp_neighbor_limit'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2255: +// Generated from 'ip.api.json', line 2255: // // "set_arp_neighbor_limit", // [ @@ -4121,25 +4357,25 @@ func NewResetFibReply() api.Message { // } // type SetArpNeighborLimit struct { - IsIpv6 uint8 + IsIPv6 uint8 ArpNeighborLimit uint32 } func (*SetArpNeighborLimit) GetMessageName() string { return "set_arp_neighbor_limit" } -func (*SetArpNeighborLimit) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SetArpNeighborLimit) GetCrcString() string { return "97d01fd6" } +func (*SetArpNeighborLimit) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSetArpNeighborLimit() api.Message { return &SetArpNeighborLimit{} } // SetArpNeighborLimitReply represents the VPP binary API message 'set_arp_neighbor_limit_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2281: +// Generated from 'ip.api.json', line 2281: // // "set_arp_neighbor_limit_reply", // [ @@ -4165,18 +4401,18 @@ type SetArpNeighborLimitReply struct { func (*SetArpNeighborLimitReply) GetMessageName() string { return "set_arp_neighbor_limit_reply" } -func (*SetArpNeighborLimitReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SetArpNeighborLimitReply) GetCrcString() string { return "e8d4e804" } +func (*SetArpNeighborLimitReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSetArpNeighborLimitReply() api.Message { return &SetArpNeighborLimitReply{} } // IoamEnable represents the VPP binary API message 'ioam_enable'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2299: +// Generated from 'ip.api.json', line 2299: // // "ioam_enable", // [ @@ -4231,18 +4467,18 @@ type IoamEnable struct { func (*IoamEnable) GetMessageName() string { return "ioam_enable" } -func (*IoamEnable) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IoamEnable) GetCrcString() string { return "9392e032" } +func (*IoamEnable) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIoamEnable() api.Message { return &IoamEnable{} } // IoamEnableReply represents the VPP binary API message 'ioam_enable_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2341: +// Generated from 'ip.api.json', line 2341: // // "ioam_enable_reply", // [ @@ -4268,18 +4504,18 @@ type IoamEnableReply struct { func (*IoamEnableReply) GetMessageName() string { return "ioam_enable_reply" } -func (*IoamEnableReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IoamEnableReply) GetCrcString() string { return "e8d4e804" } +func (*IoamEnableReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIoamEnableReply() api.Message { return &IoamEnableReply{} } // IoamDisable represents the VPP binary API message 'ioam_disable'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2359: +// Generated from 'ip.api.json', line 2359: // // "ioam_disable", // [ @@ -4309,18 +4545,18 @@ type IoamDisable struct { func (*IoamDisable) GetMessageName() string { return "ioam_disable" } -func (*IoamDisable) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IoamDisable) GetCrcString() string { return "6b16a45e" } +func (*IoamDisable) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIoamDisable() api.Message { return &IoamDisable{} } // IoamDisableReply represents the VPP binary API message 'ioam_disable_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2381: +// Generated from 'ip.api.json', line 2381: // // "ioam_disable_reply", // [ @@ -4346,18 +4582,18 @@ type IoamDisableReply struct { func (*IoamDisableReply) GetMessageName() string { return "ioam_disable_reply" } -func (*IoamDisableReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IoamDisableReply) GetCrcString() string { return "e8d4e804" } +func (*IoamDisableReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIoamDisableReply() api.Message { return &IoamDisableReply{} } // IPReassemblySet represents the VPP binary API message 'ip_reassembly_set'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2399: +// Generated from 'ip.api.json', line 2399: // // "ip_reassembly_set", // [ @@ -4402,18 +4638,18 @@ type IPReassemblySet struct { func (*IPReassemblySet) GetMessageName() string { return "ip_reassembly_set" } -func (*IPReassemblySet) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPReassemblySet) GetCrcString() string { return "1db184de" } +func (*IPReassemblySet) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPReassemblySet() api.Message { return &IPReassemblySet{} } // IPReassemblySetReply represents the VPP binary API message 'ip_reassembly_set_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2433: +// Generated from 'ip.api.json', line 2433: // // "ip_reassembly_set_reply", // [ @@ -4439,18 +4675,18 @@ type IPReassemblySetReply struct { func (*IPReassemblySetReply) GetMessageName() string { return "ip_reassembly_set_reply" } -func (*IPReassemblySetReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IPReassemblySetReply) GetCrcString() string { return "e8d4e804" } +func (*IPReassemblySetReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIPReassemblySetReply() api.Message { return &IPReassemblySetReply{} } // IPReassemblyGet represents the VPP binary API message 'ip_reassembly_get'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2451: +// Generated from 'ip.api.json', line 2451: // // "ip_reassembly_get", // [ @@ -4480,18 +4716,18 @@ type IPReassemblyGet struct { func (*IPReassemblyGet) GetMessageName() string { return "ip_reassembly_get" } -func (*IPReassemblyGet) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPReassemblyGet) GetCrcString() string { return "6fe91190" } +func (*IPReassemblyGet) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPReassemblyGet() api.Message { return &IPReassemblyGet{} } // IPReassemblyGetReply represents the VPP binary API message 'ip_reassembly_get_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2473: +// Generated from 'ip.api.json', line 2473: // // "ip_reassembly_get_reply", // [ @@ -4541,18 +4777,18 @@ type IPReassemblyGetReply struct { func (*IPReassemblyGetReply) GetMessageName() string { return "ip_reassembly_get_reply" } -func (*IPReassemblyGetReply) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPReassemblyGetReply) GetCrcString() string { return "d746fc57" } +func (*IPReassemblyGetReply) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPReassemblyGetReply() api.Message { return &IPReassemblyGetReply{} } // IPReassemblyEnableDisable represents the VPP binary API message 'ip_reassembly_enable_disable'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2511: +// Generated from 'ip.api.json', line 2511: // // "ip_reassembly_enable_disable", // [ @@ -4592,18 +4828,18 @@ type IPReassemblyEnableDisable struct { func (*IPReassemblyEnableDisable) GetMessageName() string { return "ip_reassembly_enable_disable" } -func (*IPReassemblyEnableDisable) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IPReassemblyEnableDisable) GetCrcString() string { return "bb8dc5d0" } +func (*IPReassemblyEnableDisable) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIPReassemblyEnableDisable() api.Message { return &IPReassemblyEnableDisable{} } // IPReassemblyEnableDisableReply represents the VPP binary API message 'ip_reassembly_enable_disable_reply'. -// Generated from '/usr/share/vpp/api/ip.api.json', line 2541: +// Generated from 'ip.api.json', line 2541: // // "ip_reassembly_enable_disable_reply", // [ @@ -4629,12 +4865,149 @@ type IPReassemblyEnableDisableReply struct { func (*IPReassemblyEnableDisableReply) GetMessageName() string { return "ip_reassembly_enable_disable_reply" } -func (*IPReassemblyEnableDisableReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IPReassemblyEnableDisableReply) GetCrcString() string { return "e8d4e804" } +func (*IPReassemblyEnableDisableReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIPReassemblyEnableDisableReply() api.Message { return &IPReassemblyEnableDisableReply{} } + +/* Services */ + +type Services interface { + DumpIP6Fib(*IP6FibDump) (*IP6FibDetails, error) + DumpIP6Mfib(*IP6MfibDump) (*IP6MfibDetails, error) + DumpIP6ndProxy(*IP6ndProxyDump) (*IP6ndProxyDetails, error) + DumpIPAddress(*IPAddressDump) (*IPAddressDetails, error) + DumpIP(*IPDump) (*IPDetails, error) + DumpIPFib(*IPFibDump) (*IPFibDetails, error) + DumpIPMfib(*IPMfibDump) (*IPMfibDetails, error) + DumpIPNeighbor(*IPNeighborDump) (*IPNeighborDetails, error) + DumpIPUnnumbered(*IPUnnumberedDump) (*IPUnnumberedDetails, error) + DumpMfibSignal(*MfibSignalDump) (*MfibSignalDetails, error) + DumpProxyArp(*ProxyArpDump) (*ProxyArpDetails, error) + DumpProxyArpIntfc(*ProxyArpIntfcDump) (*ProxyArpIntfcDetails, error) + IoamDisable(*IoamDisable) (*IoamDisableReply, error) + IoamEnable(*IoamEnable) (*IoamEnableReply, error) + IP6ndProxyAddDel(*IP6ndProxyAddDel) (*IP6ndProxyAddDelReply, error) + IP6ndSendRouterSolicitation(*IP6ndSendRouterSolicitation) (*IP6ndSendRouterSolicitationReply, error) + IPAddDelRoute(*IPAddDelRoute) (*IPAddDelRouteReply, error) + IPContainerProxyAddDel(*IPContainerProxyAddDel) (*IPContainerProxyAddDelReply, error) + IPMrouteAddDel(*IPMrouteAddDel) (*IPMrouteAddDelReply, error) + IPNeighborAddDel(*IPNeighborAddDel) (*IPNeighborAddDelReply, error) + IPProbeNeighbor(*IPProbeNeighbor) (*IPProbeNeighborReply, error) + IPPuntPolice(*IPPuntPolice) (*IPPuntPoliceReply, error) + IPPuntRedirect(*IPPuntRedirect) (*IPPuntRedirectReply, error) + IPReassemblyEnableDisable(*IPReassemblyEnableDisable) (*IPReassemblyEnableDisableReply, error) + IPReassemblyGet(*IPReassemblyGet) (*IPReassemblyGetReply, error) + IPReassemblySet(*IPReassemblySet) (*IPReassemblySetReply, error) + IPScanNeighborEnableDisable(*IPScanNeighborEnableDisable) (*IPScanNeighborEnableDisableReply, error) + IPSourceAndPortRangeCheckAddDel(*IPSourceAndPortRangeCheckAddDel) (*IPSourceAndPortRangeCheckAddDelReply, error) + IPSourceAndPortRangeCheckInterfaceAddDel(*IPSourceAndPortRangeCheckInterfaceAddDel) (*IPSourceAndPortRangeCheckInterfaceAddDelReply, error) + IPTableAddDel(*IPTableAddDel) (*IPTableAddDelReply, error) + ProxyArpAddDel(*ProxyArpAddDel) (*ProxyArpAddDelReply, error) + ProxyArpIntfcEnableDisable(*ProxyArpIntfcEnableDisable) (*ProxyArpIntfcEnableDisableReply, error) + ResetFib(*ResetFib) (*ResetFibReply, error) + SetArpNeighborLimit(*SetArpNeighborLimit) (*SetArpNeighborLimitReply, error) + SetIPFlowHash(*SetIPFlowHash) (*SetIPFlowHashReply, error) + SwInterfaceIP6EnableDisable(*SwInterfaceIP6EnableDisable) (*SwInterfaceIP6EnableDisableReply, error) + SwInterfaceIP6SetLinkLocalAddress(*SwInterfaceIP6SetLinkLocalAddress) (*SwInterfaceIP6SetLinkLocalAddressReply, error) + SwInterfaceIP6ndRaConfig(*SwInterfaceIP6ndRaConfig) (*SwInterfaceIP6ndRaConfigReply, error) + SwInterfaceIP6ndRaPrefix(*SwInterfaceIP6ndRaPrefix) (*SwInterfaceIP6ndRaPrefixReply, error) + WantIP4ArpEvents(*WantIP4ArpEvents) (*WantIP4ArpEventsReply, error) + WantIP6NdEvents(*WantIP6NdEvents) (*WantIP6NdEventsReply, error) + WantIP6RaEvents(*WantIP6RaEvents) (*WantIP6RaEventsReply, error) +} + +func init() { + api.RegisterMessage((*IPTableAddDel)(nil), "ip.IPTableAddDel") + api.RegisterMessage((*IPTableAddDelReply)(nil), "ip.IPTableAddDelReply") + api.RegisterMessage((*IPFibDump)(nil), "ip.IPFibDump") + api.RegisterMessage((*IPFibDetails)(nil), "ip.IPFibDetails") + api.RegisterMessage((*IP6FibDump)(nil), "ip.IP6FibDump") + api.RegisterMessage((*IP6FibDetails)(nil), "ip.IP6FibDetails") + api.RegisterMessage((*IPNeighborDump)(nil), "ip.IPNeighborDump") + api.RegisterMessage((*IPNeighborDetails)(nil), "ip.IPNeighborDetails") + api.RegisterMessage((*IPNeighborAddDel)(nil), "ip.IPNeighborAddDel") + api.RegisterMessage((*IPNeighborAddDelReply)(nil), "ip.IPNeighborAddDelReply") + api.RegisterMessage((*SetIPFlowHash)(nil), "ip.SetIPFlowHash") + api.RegisterMessage((*SetIPFlowHashReply)(nil), "ip.SetIPFlowHashReply") + api.RegisterMessage((*SwInterfaceIP6ndRaConfig)(nil), "ip.SwInterfaceIP6ndRaConfig") + api.RegisterMessage((*SwInterfaceIP6ndRaConfigReply)(nil), "ip.SwInterfaceIP6ndRaConfigReply") + api.RegisterMessage((*SwInterfaceIP6ndRaPrefix)(nil), "ip.SwInterfaceIP6ndRaPrefix") + api.RegisterMessage((*SwInterfaceIP6ndRaPrefixReply)(nil), "ip.SwInterfaceIP6ndRaPrefixReply") + api.RegisterMessage((*IP6ndProxyAddDel)(nil), "ip.IP6ndProxyAddDel") + api.RegisterMessage((*IP6ndProxyAddDelReply)(nil), "ip.IP6ndProxyAddDelReply") + api.RegisterMessage((*IP6ndProxyDetails)(nil), "ip.IP6ndProxyDetails") + api.RegisterMessage((*IP6ndProxyDump)(nil), "ip.IP6ndProxyDump") + api.RegisterMessage((*IP6ndSendRouterSolicitation)(nil), "ip.IP6ndSendRouterSolicitation") + api.RegisterMessage((*IP6ndSendRouterSolicitationReply)(nil), "ip.IP6ndSendRouterSolicitationReply") + api.RegisterMessage((*SwInterfaceIP6EnableDisable)(nil), "ip.SwInterfaceIP6EnableDisable") + api.RegisterMessage((*SwInterfaceIP6EnableDisableReply)(nil), "ip.SwInterfaceIP6EnableDisableReply") + api.RegisterMessage((*SwInterfaceIP6SetLinkLocalAddress)(nil), "ip.SwInterfaceIP6SetLinkLocalAddress") + api.RegisterMessage((*SwInterfaceIP6SetLinkLocalAddressReply)(nil), "ip.SwInterfaceIP6SetLinkLocalAddressReply") + api.RegisterMessage((*IPAddDelRoute)(nil), "ip.IPAddDelRoute") + api.RegisterMessage((*IPAddDelRouteReply)(nil), "ip.IPAddDelRouteReply") + api.RegisterMessage((*IPMrouteAddDel)(nil), "ip.IPMrouteAddDel") + api.RegisterMessage((*IPMrouteAddDelReply)(nil), "ip.IPMrouteAddDelReply") + api.RegisterMessage((*IPMfibDump)(nil), "ip.IPMfibDump") + api.RegisterMessage((*IPMfibDetails)(nil), "ip.IPMfibDetails") + api.RegisterMessage((*IP6MfibDump)(nil), "ip.IP6MfibDump") + api.RegisterMessage((*IP6MfibDetails)(nil), "ip.IP6MfibDetails") + api.RegisterMessage((*IPAddressDetails)(nil), "ip.IPAddressDetails") + api.RegisterMessage((*IPAddressDump)(nil), "ip.IPAddressDump") + api.RegisterMessage((*IPUnnumberedDetails)(nil), "ip.IPUnnumberedDetails") + api.RegisterMessage((*IPUnnumberedDump)(nil), "ip.IPUnnumberedDump") + api.RegisterMessage((*IPDetails)(nil), "ip.IPDetails") + api.RegisterMessage((*IPDump)(nil), "ip.IPDump") + api.RegisterMessage((*MfibSignalDump)(nil), "ip.MfibSignalDump") + api.RegisterMessage((*MfibSignalDetails)(nil), "ip.MfibSignalDetails") + api.RegisterMessage((*IPPuntPolice)(nil), "ip.IPPuntPolice") + api.RegisterMessage((*IPPuntPoliceReply)(nil), "ip.IPPuntPoliceReply") + api.RegisterMessage((*IPPuntRedirect)(nil), "ip.IPPuntRedirect") + api.RegisterMessage((*IPPuntRedirectReply)(nil), "ip.IPPuntRedirectReply") + api.RegisterMessage((*IPContainerProxyAddDel)(nil), "ip.IPContainerProxyAddDel") + api.RegisterMessage((*IPContainerProxyAddDelReply)(nil), "ip.IPContainerProxyAddDelReply") + api.RegisterMessage((*IPSourceAndPortRangeCheckAddDel)(nil), "ip.IPSourceAndPortRangeCheckAddDel") + api.RegisterMessage((*IPSourceAndPortRangeCheckAddDelReply)(nil), "ip.IPSourceAndPortRangeCheckAddDelReply") + api.RegisterMessage((*IPSourceAndPortRangeCheckInterfaceAddDel)(nil), "ip.IPSourceAndPortRangeCheckInterfaceAddDel") + api.RegisterMessage((*IPSourceAndPortRangeCheckInterfaceAddDelReply)(nil), "ip.IPSourceAndPortRangeCheckInterfaceAddDelReply") + api.RegisterMessage((*IPScanNeighborEnableDisable)(nil), "ip.IPScanNeighborEnableDisable") + api.RegisterMessage((*IPScanNeighborEnableDisableReply)(nil), "ip.IPScanNeighborEnableDisableReply") + api.RegisterMessage((*IPProbeNeighbor)(nil), "ip.IPProbeNeighbor") + api.RegisterMessage((*IPProbeNeighborReply)(nil), "ip.IPProbeNeighborReply") + api.RegisterMessage((*WantIP4ArpEvents)(nil), "ip.WantIP4ArpEvents") + api.RegisterMessage((*WantIP4ArpEventsReply)(nil), "ip.WantIP4ArpEventsReply") + api.RegisterMessage((*IP4ArpEvent)(nil), "ip.IP4ArpEvent") + api.RegisterMessage((*WantIP6NdEvents)(nil), "ip.WantIP6NdEvents") + api.RegisterMessage((*WantIP6NdEventsReply)(nil), "ip.WantIP6NdEventsReply") + api.RegisterMessage((*IP6NdEvent)(nil), "ip.IP6NdEvent") + api.RegisterMessage((*WantIP6RaEvents)(nil), "ip.WantIP6RaEvents") + api.RegisterMessage((*WantIP6RaEventsReply)(nil), "ip.WantIP6RaEventsReply") + api.RegisterMessage((*IP6RaEvent)(nil), "ip.IP6RaEvent") + api.RegisterMessage((*ProxyArpAddDel)(nil), "ip.ProxyArpAddDel") + api.RegisterMessage((*ProxyArpAddDelReply)(nil), "ip.ProxyArpAddDelReply") + api.RegisterMessage((*ProxyArpDump)(nil), "ip.ProxyArpDump") + api.RegisterMessage((*ProxyArpDetails)(nil), "ip.ProxyArpDetails") + api.RegisterMessage((*ProxyArpIntfcEnableDisable)(nil), "ip.ProxyArpIntfcEnableDisable") + api.RegisterMessage((*ProxyArpIntfcEnableDisableReply)(nil), "ip.ProxyArpIntfcEnableDisableReply") + api.RegisterMessage((*ProxyArpIntfcDump)(nil), "ip.ProxyArpIntfcDump") + api.RegisterMessage((*ProxyArpIntfcDetails)(nil), "ip.ProxyArpIntfcDetails") + api.RegisterMessage((*ResetFib)(nil), "ip.ResetFib") + api.RegisterMessage((*ResetFibReply)(nil), "ip.ResetFibReply") + api.RegisterMessage((*SetArpNeighborLimit)(nil), "ip.SetArpNeighborLimit") + api.RegisterMessage((*SetArpNeighborLimitReply)(nil), "ip.SetArpNeighborLimitReply") + api.RegisterMessage((*IoamEnable)(nil), "ip.IoamEnable") + api.RegisterMessage((*IoamEnableReply)(nil), "ip.IoamEnableReply") + api.RegisterMessage((*IoamDisable)(nil), "ip.IoamDisable") + api.RegisterMessage((*IoamDisableReply)(nil), "ip.IoamDisableReply") + api.RegisterMessage((*IPReassemblySet)(nil), "ip.IPReassemblySet") + api.RegisterMessage((*IPReassemblySetReply)(nil), "ip.IPReassemblySetReply") + api.RegisterMessage((*IPReassemblyGet)(nil), "ip.IPReassemblyGet") + api.RegisterMessage((*IPReassemblyGetReply)(nil), "ip.IPReassemblyGetReply") + api.RegisterMessage((*IPReassemblyEnableDisable)(nil), "ip.IPReassemblyEnableDisable") + api.RegisterMessage((*IPReassemblyEnableDisableReply)(nil), "ip.IPReassemblyEnableDisableReply") +} diff --git a/plugins/vpp/binapi/ip/pkgreflect.go b/plugins/vpp/binapi/ip/pkgreflect.go index a8bbb7826b..6ea0aeb234 100644 --- a/plugins/vpp/binapi/ip/pkgreflect.go +++ b/plugins/vpp/binapi/ip/pkgreflect.go @@ -5,9 +5,14 @@ package ip import "reflect" var Types = map[string]reflect.Type{ + "Address": reflect.TypeOf((*Address)(nil)).Elem(), + "AddressFamily": reflect.TypeOf((*AddressFamily)(nil)).Elem(), + "AddressUnion": reflect.TypeOf((*AddressUnion)(nil)).Elem(), "FibMplsLabel": reflect.TypeOf((*FibMplsLabel)(nil)).Elem(), "FibPath": reflect.TypeOf((*FibPath)(nil)).Elem(), + "IP4Address": reflect.TypeOf((*IP4Address)(nil)).Elem(), "IP4ArpEvent": reflect.TypeOf((*IP4ArpEvent)(nil)).Elem(), + "IP6Address": reflect.TypeOf((*IP6Address)(nil)).Elem(), "IP6FibDetails": reflect.TypeOf((*IP6FibDetails)(nil)).Elem(), "IP6FibDump": reflect.TypeOf((*IP6FibDump)(nil)).Elem(), "IP6MfibDetails": reflect.TypeOf((*IP6MfibDetails)(nil)).Elem(), @@ -67,6 +72,8 @@ var Types = map[string]reflect.Type{ "IoamEnableReply": reflect.TypeOf((*IoamEnableReply)(nil)).Elem(), "MfibSignalDetails": reflect.TypeOf((*MfibSignalDetails)(nil)).Elem(), "MfibSignalDump": reflect.TypeOf((*MfibSignalDump)(nil)).Elem(), + "Mprefix": reflect.TypeOf((*Mprefix)(nil)).Elem(), + "Prefix": reflect.TypeOf((*Prefix)(nil)).Elem(), "ProxyArp": reflect.TypeOf((*ProxyArp)(nil)).Elem(), "ProxyArpAddDel": reflect.TypeOf((*ProxyArpAddDel)(nil)).Elem(), "ProxyArpAddDelReply": reflect.TypeOf((*ProxyArpAddDelReply)(nil)).Elem(), @@ -78,6 +85,7 @@ var Types = map[string]reflect.Type{ "ProxyArpIntfcEnableDisableReply": reflect.TypeOf((*ProxyArpIntfcEnableDisableReply)(nil)).Elem(), "ResetFib": reflect.TypeOf((*ResetFib)(nil)).Elem(), "ResetFibReply": reflect.TypeOf((*ResetFibReply)(nil)).Elem(), + "Services": reflect.TypeOf((*Services)(nil)).Elem(), "SetArpNeighborLimit": reflect.TypeOf((*SetArpNeighborLimit)(nil)).Elem(), "SetArpNeighborLimitReply": reflect.TypeOf((*SetArpNeighborLimitReply)(nil)).Elem(), "SetIPFlowHash": reflect.TypeOf((*SetIPFlowHash)(nil)).Elem(), @@ -192,5 +200,7 @@ var Variables = map[string]reflect.Value{ } var Consts = map[string]reflect.Value{ + "ADDRESS_IP4": reflect.ValueOf(ADDRESS_IP4), + "ADDRESS_IP6": reflect.ValueOf(ADDRESS_IP6), } diff --git a/plugins/vpp/binapi/ipsec/ipsec.go b/plugins/vpp/binapi/ipsec/ipsec.ba.go similarity index 87% rename from plugins/vpp/binapi/ipsec/ipsec.go rename to plugins/vpp/binapi/ipsec/ipsec.ba.go index 3c87a17a21..6f44f00676 100644 --- a/plugins/vpp/binapi/ipsec/ipsec.go +++ b/plugins/vpp/binapi/ipsec/ipsec.ba.go @@ -1,12 +1,30 @@ -// Code generated by govpp binapi-generator DO NOT EDIT. -// Package ipsec represents the VPP binary API of the 'ipsec' VPP module. -// Generated from '/usr/share/vpp/api/ipsec.api.json' +// Code generated by GoVPP binapi-generator. DO NOT EDIT. +// source: /usr/share/vpp/api/ipsec.api.json + +/* +Package ipsec is a generated VPP binary API of the 'ipsec' VPP module. + +It is generated from this file: + ipsec.api.json + +It contains these VPP binary API objects: + 46 messages + 23 services +*/ package ipsec import "git.fd.io/govpp.git/api" +import "github.com/lunixbochs/struc" +import "bytes" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = struc.Pack +var _ = bytes.NewBuffer + +/* Messages */ // IpsecSpdAddDel represents the VPP binary API message 'ipsec_spd_add_del'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 4: +// Generated from 'ipsec.api.json', line 4: // // "ipsec_spd_add_del", // [ @@ -41,18 +59,18 @@ type IpsecSpdAddDel struct { func (*IpsecSpdAddDel) GetMessageName() string { return "ipsec_spd_add_del" } -func (*IpsecSpdAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IpsecSpdAddDel) GetCrcString() string { return "9ffdf5da" } +func (*IpsecSpdAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIpsecSpdAddDel() api.Message { return &IpsecSpdAddDel{} } // IpsecSpdAddDelReply represents the VPP binary API message 'ipsec_spd_add_del_reply'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 30: +// Generated from 'ipsec.api.json', line 30: // // "ipsec_spd_add_del_reply", // [ @@ -78,18 +96,18 @@ type IpsecSpdAddDelReply struct { func (*IpsecSpdAddDelReply) GetMessageName() string { return "ipsec_spd_add_del_reply" } -func (*IpsecSpdAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IpsecSpdAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*IpsecSpdAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIpsecSpdAddDelReply() api.Message { return &IpsecSpdAddDelReply{} } // IpsecInterfaceAddDelSpd represents the VPP binary API message 'ipsec_interface_add_del_spd'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 48: +// Generated from 'ipsec.api.json', line 48: // // "ipsec_interface_add_del_spd", // [ @@ -129,18 +147,18 @@ type IpsecInterfaceAddDelSpd struct { func (*IpsecInterfaceAddDelSpd) GetMessageName() string { return "ipsec_interface_add_del_spd" } -func (*IpsecInterfaceAddDelSpd) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IpsecInterfaceAddDelSpd) GetCrcString() string { return "1e3b8286" } +func (*IpsecInterfaceAddDelSpd) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIpsecInterfaceAddDelSpd() api.Message { return &IpsecInterfaceAddDelSpd{} } // IpsecInterfaceAddDelSpdReply represents the VPP binary API message 'ipsec_interface_add_del_spd_reply'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 78: +// Generated from 'ipsec.api.json', line 78: // // "ipsec_interface_add_del_spd_reply", // [ @@ -166,18 +184,18 @@ type IpsecInterfaceAddDelSpdReply struct { func (*IpsecInterfaceAddDelSpdReply) GetMessageName() string { return "ipsec_interface_add_del_spd_reply" } -func (*IpsecInterfaceAddDelSpdReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IpsecInterfaceAddDelSpdReply) GetCrcString() string { return "e8d4e804" } +func (*IpsecInterfaceAddDelSpdReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIpsecInterfaceAddDelSpdReply() api.Message { return &IpsecInterfaceAddDelSpdReply{} } // IpsecSpdAddDelEntry represents the VPP binary API message 'ipsec_spd_add_del_entry'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 96: +// Generated from 'ipsec.api.json', line 96: // // "ipsec_spd_add_del_entry", // [ @@ -273,7 +291,7 @@ type IpsecSpdAddDelEntry struct { SpdID uint32 Priority int32 IsOutbound uint8 - IsIpv6 uint8 + IsIPv6 uint8 IsIPAny uint8 RemoteAddressStart []byte `struc:"[16]byte"` RemoteAddressStop []byte `struc:"[16]byte"` @@ -291,18 +309,18 @@ type IpsecSpdAddDelEntry struct { func (*IpsecSpdAddDelEntry) GetMessageName() string { return "ipsec_spd_add_del_entry" } -func (*IpsecSpdAddDelEntry) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IpsecSpdAddDelEntry) GetCrcString() string { return "7687a364" } +func (*IpsecSpdAddDelEntry) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIpsecSpdAddDelEntry() api.Message { return &IpsecSpdAddDelEntry{} } // IpsecSpdAddDelEntryReply represents the VPP binary API message 'ipsec_spd_add_del_entry_reply'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 186: +// Generated from 'ipsec.api.json', line 186: // // "ipsec_spd_add_del_entry_reply", // [ @@ -328,18 +346,18 @@ type IpsecSpdAddDelEntryReply struct { func (*IpsecSpdAddDelEntryReply) GetMessageName() string { return "ipsec_spd_add_del_entry_reply" } -func (*IpsecSpdAddDelEntryReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IpsecSpdAddDelEntryReply) GetCrcString() string { return "e8d4e804" } +func (*IpsecSpdAddDelEntryReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIpsecSpdAddDelEntryReply() api.Message { return &IpsecSpdAddDelEntryReply{} } // IpsecSadAddDelEntry represents the VPP binary API message 'ipsec_sad_add_del_entry'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 204: +// Generated from 'ipsec.api.json', line 204: // // "ipsec_sad_add_del_entry", // [ @@ -444,7 +462,7 @@ type IpsecSadAddDelEntry struct { UseExtendedSequenceNumber uint8 UseAntiReplay uint8 IsTunnel uint8 - IsTunnelIpv6 uint8 + IsTunnelIPv6 uint8 TunnelSrcAddress []byte `struc:"[16]byte"` TunnelDstAddress []byte `struc:"[16]byte"` UDPEncap uint8 @@ -453,18 +471,18 @@ type IpsecSadAddDelEntry struct { func (*IpsecSadAddDelEntry) GetMessageName() string { return "ipsec_sad_add_del_entry" } -func (*IpsecSadAddDelEntry) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IpsecSadAddDelEntry) GetCrcString() string { return "306782b4" } +func (*IpsecSadAddDelEntry) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIpsecSadAddDelEntry() api.Message { return &IpsecSadAddDelEntry{} } // IpsecSadAddDelEntryReply represents the VPP binary API message 'ipsec_sad_add_del_entry_reply'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 294: +// Generated from 'ipsec.api.json', line 294: // // "ipsec_sad_add_del_entry_reply", // [ @@ -490,18 +508,18 @@ type IpsecSadAddDelEntryReply struct { func (*IpsecSadAddDelEntryReply) GetMessageName() string { return "ipsec_sad_add_del_entry_reply" } -func (*IpsecSadAddDelEntryReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IpsecSadAddDelEntryReply) GetCrcString() string { return "e8d4e804" } +func (*IpsecSadAddDelEntryReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIpsecSadAddDelEntryReply() api.Message { return &IpsecSadAddDelEntryReply{} } // IpsecSaSetKey represents the VPP binary API message 'ipsec_sa_set_key'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 312: +// Generated from 'ipsec.api.json', line 312: // // "ipsec_sa_set_key", // [ @@ -553,18 +571,18 @@ type IpsecSaSetKey struct { func (*IpsecSaSetKey) GetMessageName() string { return "ipsec_sa_set_key" } -func (*IpsecSaSetKey) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IpsecSaSetKey) GetCrcString() string { return "93b4f08a" } +func (*IpsecSaSetKey) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIpsecSaSetKey() api.Message { return &IpsecSaSetKey{} } // IpsecSaSetKeyReply represents the VPP binary API message 'ipsec_sa_set_key_reply'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 352: +// Generated from 'ipsec.api.json', line 352: // // "ipsec_sa_set_key_reply", // [ @@ -590,18 +608,18 @@ type IpsecSaSetKeyReply struct { func (*IpsecSaSetKeyReply) GetMessageName() string { return "ipsec_sa_set_key_reply" } -func (*IpsecSaSetKeyReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IpsecSaSetKeyReply) GetCrcString() string { return "e8d4e804" } +func (*IpsecSaSetKeyReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIpsecSaSetKeyReply() api.Message { return &IpsecSaSetKeyReply{} } // Ikev2ProfileAddDel represents the VPP binary API message 'ikev2_profile_add_del'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 370: +// Generated from 'ipsec.api.json', line 370: // // "ikev2_profile_add_del", // [ @@ -637,18 +655,18 @@ type Ikev2ProfileAddDel struct { func (*Ikev2ProfileAddDel) GetMessageName() string { return "ikev2_profile_add_del" } -func (*Ikev2ProfileAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Ikev2ProfileAddDel) GetCrcString() string { return "405b222e" } +func (*Ikev2ProfileAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIkev2ProfileAddDel() api.Message { return &Ikev2ProfileAddDel{} } // Ikev2ProfileAddDelReply represents the VPP binary API message 'ikev2_profile_add_del_reply'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 397: +// Generated from 'ipsec.api.json', line 397: // // "ikev2_profile_add_del_reply", // [ @@ -674,18 +692,18 @@ type Ikev2ProfileAddDelReply struct { func (*Ikev2ProfileAddDelReply) GetMessageName() string { return "ikev2_profile_add_del_reply" } -func (*Ikev2ProfileAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Ikev2ProfileAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*Ikev2ProfileAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIkev2ProfileAddDelReply() api.Message { return &Ikev2ProfileAddDelReply{} } // Ikev2ProfileSetAuth represents the VPP binary API message 'ikev2_profile_set_auth'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 415: +// Generated from 'ipsec.api.json', line 415: // // "ikev2_profile_set_auth", // [ @@ -738,18 +756,18 @@ type Ikev2ProfileSetAuth struct { func (*Ikev2ProfileSetAuth) GetMessageName() string { return "ikev2_profile_set_auth" } -func (*Ikev2ProfileSetAuth) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Ikev2ProfileSetAuth) GetCrcString() string { return "bd76f369" } +func (*Ikev2ProfileSetAuth) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIkev2ProfileSetAuth() api.Message { return &Ikev2ProfileSetAuth{} } // Ikev2ProfileSetAuthReply represents the VPP binary API message 'ikev2_profile_set_auth_reply'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 456: +// Generated from 'ipsec.api.json', line 456: // // "ikev2_profile_set_auth_reply", // [ @@ -775,18 +793,18 @@ type Ikev2ProfileSetAuthReply struct { func (*Ikev2ProfileSetAuthReply) GetMessageName() string { return "ikev2_profile_set_auth_reply" } -func (*Ikev2ProfileSetAuthReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Ikev2ProfileSetAuthReply) GetCrcString() string { return "e8d4e804" } +func (*Ikev2ProfileSetAuthReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIkev2ProfileSetAuthReply() api.Message { return &Ikev2ProfileSetAuthReply{} } // Ikev2ProfileSetID represents the VPP binary API message 'ikev2_profile_set_id'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 474: +// Generated from 'ipsec.api.json', line 474: // // "ikev2_profile_set_id", // [ @@ -839,18 +857,18 @@ type Ikev2ProfileSetID struct { func (*Ikev2ProfileSetID) GetMessageName() string { return "ikev2_profile_set_id" } -func (*Ikev2ProfileSetID) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Ikev2ProfileSetID) GetCrcString() string { return "ca88c0ef" } +func (*Ikev2ProfileSetID) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIkev2ProfileSetID() api.Message { return &Ikev2ProfileSetID{} } // Ikev2ProfileSetIDReply represents the VPP binary API message 'ikev2_profile_set_id_reply'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 515: +// Generated from 'ipsec.api.json', line 515: // // "ikev2_profile_set_id_reply", // [ @@ -876,18 +894,18 @@ type Ikev2ProfileSetIDReply struct { func (*Ikev2ProfileSetIDReply) GetMessageName() string { return "ikev2_profile_set_id_reply" } -func (*Ikev2ProfileSetIDReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Ikev2ProfileSetIDReply) GetCrcString() string { return "e8d4e804" } +func (*Ikev2ProfileSetIDReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIkev2ProfileSetIDReply() api.Message { return &Ikev2ProfileSetIDReply{} } // Ikev2ProfileSetTs represents the VPP binary API message 'ikev2_profile_set_ts'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 533: +// Generated from 'ipsec.api.json', line 533: // // "ikev2_profile_set_ts", // [ @@ -948,18 +966,18 @@ type Ikev2ProfileSetTs struct { func (*Ikev2ProfileSetTs) GetMessageName() string { return "ikev2_profile_set_ts" } -func (*Ikev2ProfileSetTs) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Ikev2ProfileSetTs) GetCrcString() string { return "481aad89" } +func (*Ikev2ProfileSetTs) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIkev2ProfileSetTs() api.Message { return &Ikev2ProfileSetTs{} } // Ikev2ProfileSetTsReply represents the VPP binary API message 'ikev2_profile_set_ts_reply'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 580: +// Generated from 'ipsec.api.json', line 580: // // "ikev2_profile_set_ts_reply", // [ @@ -985,18 +1003,18 @@ type Ikev2ProfileSetTsReply struct { func (*Ikev2ProfileSetTsReply) GetMessageName() string { return "ikev2_profile_set_ts_reply" } -func (*Ikev2ProfileSetTsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Ikev2ProfileSetTsReply) GetCrcString() string { return "e8d4e804" } +func (*Ikev2ProfileSetTsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIkev2ProfileSetTsReply() api.Message { return &Ikev2ProfileSetTsReply{} } // Ikev2SetLocalKey represents the VPP binary API message 'ikev2_set_local_key'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 598: +// Generated from 'ipsec.api.json', line 598: // // "ikev2_set_local_key", // [ @@ -1027,18 +1045,18 @@ type Ikev2SetLocalKey struct { func (*Ikev2SetLocalKey) GetMessageName() string { return "ikev2_set_local_key" } -func (*Ikev2SetLocalKey) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Ikev2SetLocalKey) GetCrcString() string { return "e4996cd5" } +func (*Ikev2SetLocalKey) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIkev2SetLocalKey() api.Message { return &Ikev2SetLocalKey{} } // Ikev2SetLocalKeyReply represents the VPP binary API message 'ikev2_set_local_key_reply'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 621: +// Generated from 'ipsec.api.json', line 621: // // "ikev2_set_local_key_reply", // [ @@ -1064,18 +1082,18 @@ type Ikev2SetLocalKeyReply struct { func (*Ikev2SetLocalKeyReply) GetMessageName() string { return "ikev2_set_local_key_reply" } -func (*Ikev2SetLocalKeyReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Ikev2SetLocalKeyReply) GetCrcString() string { return "e8d4e804" } +func (*Ikev2SetLocalKeyReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIkev2SetLocalKeyReply() api.Message { return &Ikev2SetLocalKeyReply{} } // Ikev2SetResponder represents the VPP binary API message 'ikev2_set_responder'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 639: +// Generated from 'ipsec.api.json', line 639: // // "ikev2_set_responder", // [ @@ -1117,18 +1135,18 @@ type Ikev2SetResponder struct { func (*Ikev2SetResponder) GetMessageName() string { return "ikev2_set_responder" } -func (*Ikev2SetResponder) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Ikev2SetResponder) GetCrcString() string { return "a99996f3" } +func (*Ikev2SetResponder) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIkev2SetResponder() api.Message { return &Ikev2SetResponder{} } // Ikev2SetResponderReply represents the VPP binary API message 'ikev2_set_responder_reply'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 671: +// Generated from 'ipsec.api.json', line 671: // // "ikev2_set_responder_reply", // [ @@ -1154,18 +1172,18 @@ type Ikev2SetResponderReply struct { func (*Ikev2SetResponderReply) GetMessageName() string { return "ikev2_set_responder_reply" } -func (*Ikev2SetResponderReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Ikev2SetResponderReply) GetCrcString() string { return "e8d4e804" } +func (*Ikev2SetResponderReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIkev2SetResponderReply() api.Message { return &Ikev2SetResponderReply{} } // Ikev2SetIkeTransforms represents the VPP binary API message 'ikev2_set_ike_transforms'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 689: +// Generated from 'ipsec.api.json', line 689: // // "ikev2_set_ike_transforms", // [ @@ -1216,18 +1234,18 @@ type Ikev2SetIkeTransforms struct { func (*Ikev2SetIkeTransforms) GetMessageName() string { return "ikev2_set_ike_transforms" } -func (*Ikev2SetIkeTransforms) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Ikev2SetIkeTransforms) GetCrcString() string { return "919f5efd" } +func (*Ikev2SetIkeTransforms) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIkev2SetIkeTransforms() api.Message { return &Ikev2SetIkeTransforms{} } // Ikev2SetIkeTransformsReply represents the VPP binary API message 'ikev2_set_ike_transforms_reply'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 728: +// Generated from 'ipsec.api.json', line 728: // // "ikev2_set_ike_transforms_reply", // [ @@ -1253,18 +1271,18 @@ type Ikev2SetIkeTransformsReply struct { func (*Ikev2SetIkeTransformsReply) GetMessageName() string { return "ikev2_set_ike_transforms_reply" } -func (*Ikev2SetIkeTransformsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Ikev2SetIkeTransformsReply) GetCrcString() string { return "e8d4e804" } +func (*Ikev2SetIkeTransformsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIkev2SetIkeTransformsReply() api.Message { return &Ikev2SetIkeTransformsReply{} } // Ikev2SetEspTransforms represents the VPP binary API message 'ikev2_set_esp_transforms'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 746: +// Generated from 'ipsec.api.json', line 746: // // "ikev2_set_esp_transforms", // [ @@ -1315,18 +1333,18 @@ type Ikev2SetEspTransforms struct { func (*Ikev2SetEspTransforms) GetMessageName() string { return "ikev2_set_esp_transforms" } -func (*Ikev2SetEspTransforms) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Ikev2SetEspTransforms) GetCrcString() string { return "919f5efd" } +func (*Ikev2SetEspTransforms) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIkev2SetEspTransforms() api.Message { return &Ikev2SetEspTransforms{} } // Ikev2SetEspTransformsReply represents the VPP binary API message 'ikev2_set_esp_transforms_reply'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 785: +// Generated from 'ipsec.api.json', line 785: // // "ikev2_set_esp_transforms_reply", // [ @@ -1352,18 +1370,18 @@ type Ikev2SetEspTransformsReply struct { func (*Ikev2SetEspTransformsReply) GetMessageName() string { return "ikev2_set_esp_transforms_reply" } -func (*Ikev2SetEspTransformsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Ikev2SetEspTransformsReply) GetCrcString() string { return "e8d4e804" } +func (*Ikev2SetEspTransformsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIkev2SetEspTransformsReply() api.Message { return &Ikev2SetEspTransformsReply{} } // Ikev2SetSaLifetime represents the VPP binary API message 'ikev2_set_sa_lifetime'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 803: +// Generated from 'ipsec.api.json', line 803: // // "ikev2_set_sa_lifetime", // [ @@ -1414,18 +1432,18 @@ type Ikev2SetSaLifetime struct { func (*Ikev2SetSaLifetime) GetMessageName() string { return "ikev2_set_sa_lifetime" } -func (*Ikev2SetSaLifetime) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Ikev2SetSaLifetime) GetCrcString() string { return "46d31203" } +func (*Ikev2SetSaLifetime) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIkev2SetSaLifetime() api.Message { return &Ikev2SetSaLifetime{} } // Ikev2SetSaLifetimeReply represents the VPP binary API message 'ikev2_set_sa_lifetime_reply'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 842: +// Generated from 'ipsec.api.json', line 842: // // "ikev2_set_sa_lifetime_reply", // [ @@ -1451,18 +1469,18 @@ type Ikev2SetSaLifetimeReply struct { func (*Ikev2SetSaLifetimeReply) GetMessageName() string { return "ikev2_set_sa_lifetime_reply" } -func (*Ikev2SetSaLifetimeReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Ikev2SetSaLifetimeReply) GetCrcString() string { return "e8d4e804" } +func (*Ikev2SetSaLifetimeReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIkev2SetSaLifetimeReply() api.Message { return &Ikev2SetSaLifetimeReply{} } // Ikev2InitiateSaInit represents the VPP binary API message 'ikev2_initiate_sa_init'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 860: +// Generated from 'ipsec.api.json', line 860: // // "ikev2_initiate_sa_init", // [ @@ -1493,18 +1511,18 @@ type Ikev2InitiateSaInit struct { func (*Ikev2InitiateSaInit) GetMessageName() string { return "ikev2_initiate_sa_init" } -func (*Ikev2InitiateSaInit) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Ikev2InitiateSaInit) GetCrcString() string { return "0cb71b0e" } +func (*Ikev2InitiateSaInit) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIkev2InitiateSaInit() api.Message { return &Ikev2InitiateSaInit{} } // Ikev2InitiateSaInitReply represents the VPP binary API message 'ikev2_initiate_sa_init_reply'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 883: +// Generated from 'ipsec.api.json', line 883: // // "ikev2_initiate_sa_init_reply", // [ @@ -1530,18 +1548,18 @@ type Ikev2InitiateSaInitReply struct { func (*Ikev2InitiateSaInitReply) GetMessageName() string { return "ikev2_initiate_sa_init_reply" } -func (*Ikev2InitiateSaInitReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Ikev2InitiateSaInitReply) GetCrcString() string { return "e8d4e804" } +func (*Ikev2InitiateSaInitReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIkev2InitiateSaInitReply() api.Message { return &Ikev2InitiateSaInitReply{} } // Ikev2InitiateDelIkeSa represents the VPP binary API message 'ikev2_initiate_del_ike_sa'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 901: +// Generated from 'ipsec.api.json', line 901: // // "ikev2_initiate_del_ike_sa", // [ @@ -1571,18 +1589,18 @@ type Ikev2InitiateDelIkeSa struct { func (*Ikev2InitiateDelIkeSa) GetMessageName() string { return "ikev2_initiate_del_ike_sa" } -func (*Ikev2InitiateDelIkeSa) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Ikev2InitiateDelIkeSa) GetCrcString() string { return "8d125bdd" } +func (*Ikev2InitiateDelIkeSa) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIkev2InitiateDelIkeSa() api.Message { return &Ikev2InitiateDelIkeSa{} } // Ikev2InitiateDelIkeSaReply represents the VPP binary API message 'ikev2_initiate_del_ike_sa_reply'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 923: +// Generated from 'ipsec.api.json', line 923: // // "ikev2_initiate_del_ike_sa_reply", // [ @@ -1608,18 +1626,18 @@ type Ikev2InitiateDelIkeSaReply struct { func (*Ikev2InitiateDelIkeSaReply) GetMessageName() string { return "ikev2_initiate_del_ike_sa_reply" } -func (*Ikev2InitiateDelIkeSaReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Ikev2InitiateDelIkeSaReply) GetCrcString() string { return "e8d4e804" } +func (*Ikev2InitiateDelIkeSaReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIkev2InitiateDelIkeSaReply() api.Message { return &Ikev2InitiateDelIkeSaReply{} } // Ikev2InitiateDelChildSa represents the VPP binary API message 'ikev2_initiate_del_child_sa'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 941: +// Generated from 'ipsec.api.json', line 941: // // "ikev2_initiate_del_child_sa", // [ @@ -1649,18 +1667,18 @@ type Ikev2InitiateDelChildSa struct { func (*Ikev2InitiateDelChildSa) GetMessageName() string { return "ikev2_initiate_del_child_sa" } -func (*Ikev2InitiateDelChildSa) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Ikev2InitiateDelChildSa) GetCrcString() string { return "7f004d2e" } +func (*Ikev2InitiateDelChildSa) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIkev2InitiateDelChildSa() api.Message { return &Ikev2InitiateDelChildSa{} } // Ikev2InitiateDelChildSaReply represents the VPP binary API message 'ikev2_initiate_del_child_sa_reply'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 963: +// Generated from 'ipsec.api.json', line 963: // // "ikev2_initiate_del_child_sa_reply", // [ @@ -1686,18 +1704,18 @@ type Ikev2InitiateDelChildSaReply struct { func (*Ikev2InitiateDelChildSaReply) GetMessageName() string { return "ikev2_initiate_del_child_sa_reply" } -func (*Ikev2InitiateDelChildSaReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Ikev2InitiateDelChildSaReply) GetCrcString() string { return "e8d4e804" } +func (*Ikev2InitiateDelChildSaReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIkev2InitiateDelChildSaReply() api.Message { return &Ikev2InitiateDelChildSaReply{} } // Ikev2InitiateRekeyChildSa represents the VPP binary API message 'ikev2_initiate_rekey_child_sa'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 981: +// Generated from 'ipsec.api.json', line 981: // // "ikev2_initiate_rekey_child_sa", // [ @@ -1727,18 +1745,18 @@ type Ikev2InitiateRekeyChildSa struct { func (*Ikev2InitiateRekeyChildSa) GetMessageName() string { return "ikev2_initiate_rekey_child_sa" } -func (*Ikev2InitiateRekeyChildSa) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Ikev2InitiateRekeyChildSa) GetCrcString() string { return "7f004d2e" } +func (*Ikev2InitiateRekeyChildSa) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIkev2InitiateRekeyChildSa() api.Message { return &Ikev2InitiateRekeyChildSa{} } // Ikev2InitiateRekeyChildSaReply represents the VPP binary API message 'ikev2_initiate_rekey_child_sa_reply'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 1003: +// Generated from 'ipsec.api.json', line 1003: // // "ikev2_initiate_rekey_child_sa_reply", // [ @@ -1764,18 +1782,18 @@ type Ikev2InitiateRekeyChildSaReply struct { func (*Ikev2InitiateRekeyChildSaReply) GetMessageName() string { return "ikev2_initiate_rekey_child_sa_reply" } -func (*Ikev2InitiateRekeyChildSaReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Ikev2InitiateRekeyChildSaReply) GetCrcString() string { return "e8d4e804" } +func (*Ikev2InitiateRekeyChildSaReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIkev2InitiateRekeyChildSaReply() api.Message { return &Ikev2InitiateRekeyChildSaReply{} } // IpsecSpdDump represents the VPP binary API message 'ipsec_spd_dump'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 1021: +// Generated from 'ipsec.api.json', line 1021: // // "ipsec_spd_dump", // [ @@ -1810,18 +1828,18 @@ type IpsecSpdDump struct { func (*IpsecSpdDump) GetMessageName() string { return "ipsec_spd_dump" } -func (*IpsecSpdDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IpsecSpdDump) GetCrcString() string { return "afefbf7d" } +func (*IpsecSpdDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIpsecSpdDump() api.Message { return &IpsecSpdDump{} } // IpsecSpdDetails represents the VPP binary API message 'ipsec_spd_details'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 1047: +// Generated from 'ipsec.api.json', line 1047: // // "ipsec_spd_details", // [ @@ -1912,7 +1930,7 @@ type IpsecSpdDetails struct { SpdID uint32 Priority int32 IsOutbound uint8 - IsIpv6 uint8 + IsIPv6 uint8 LocalStartAddr []byte `struc:"[16]byte"` LocalStopAddr []byte `struc:"[16]byte"` LocalStartPort uint16 @@ -1931,18 +1949,18 @@ type IpsecSpdDetails struct { func (*IpsecSpdDetails) GetMessageName() string { return "ipsec_spd_details" } -func (*IpsecSpdDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IpsecSpdDetails) GetCrcString() string { return "1560895d" } +func (*IpsecSpdDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIpsecSpdDetails() api.Message { return &IpsecSpdDetails{} } // IpsecTunnelIfAddDel represents the VPP binary API message 'ipsec_tunnel_if_add_del'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 1133: +// Generated from 'ipsec.api.json', line 1133: // // "ipsec_tunnel_if_add_del", // [ @@ -2068,18 +2086,18 @@ type IpsecTunnelIfAddDel struct { func (*IpsecTunnelIfAddDel) GetMessageName() string { return "ipsec_tunnel_if_add_del" } -func (*IpsecTunnelIfAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IpsecTunnelIfAddDel) GetCrcString() string { return "56b8943b" } +func (*IpsecTunnelIfAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIpsecTunnelIfAddDel() api.Message { return &IpsecTunnelIfAddDel{} } // IpsecTunnelIfAddDelReply represents the VPP binary API message 'ipsec_tunnel_if_add_del_reply'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 1233: +// Generated from 'ipsec.api.json', line 1233: // // "ipsec_tunnel_if_add_del_reply", // [ @@ -2110,18 +2128,18 @@ type IpsecTunnelIfAddDelReply struct { func (*IpsecTunnelIfAddDelReply) GetMessageName() string { return "ipsec_tunnel_if_add_del_reply" } -func (*IpsecTunnelIfAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IpsecTunnelIfAddDelReply) GetCrcString() string { return "fda5941f" } +func (*IpsecTunnelIfAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIpsecTunnelIfAddDelReply() api.Message { return &IpsecTunnelIfAddDelReply{} } // IpsecSaDump represents the VPP binary API message 'ipsec_sa_dump'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 1255: +// Generated from 'ipsec.api.json', line 1255: // // "ipsec_sa_dump", // [ @@ -2151,18 +2169,18 @@ type IpsecSaDump struct { func (*IpsecSaDump) GetMessageName() string { return "ipsec_sa_dump" } -func (*IpsecSaDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IpsecSaDump) GetCrcString() string { return "2076c2f4" } +func (*IpsecSaDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIpsecSaDump() api.Message { return &IpsecSaDump{} } // IpsecSaDetails represents the VPP binary API message 'ipsec_sa_details'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 1277: +// Generated from 'ipsec.api.json', line 1277: // // "ipsec_sa_details", // [ @@ -2297,18 +2315,18 @@ type IpsecSaDetails struct { func (*IpsecSaDetails) GetMessageName() string { return "ipsec_sa_details" } -func (*IpsecSaDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IpsecSaDetails) GetCrcString() string { return "dc927a3b" } +func (*IpsecSaDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIpsecSaDetails() api.Message { return &IpsecSaDetails{} } // IpsecTunnelIfSetKey represents the VPP binary API message 'ipsec_tunnel_if_set_key'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 1383: +// Generated from 'ipsec.api.json', line 1383: // // "ipsec_tunnel_if_set_key", // [ @@ -2359,18 +2377,18 @@ type IpsecTunnelIfSetKey struct { func (*IpsecTunnelIfSetKey) GetMessageName() string { return "ipsec_tunnel_if_set_key" } -func (*IpsecTunnelIfSetKey) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IpsecTunnelIfSetKey) GetCrcString() string { return "326169a8" } +func (*IpsecTunnelIfSetKey) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIpsecTunnelIfSetKey() api.Message { return &IpsecTunnelIfSetKey{} } // IpsecTunnelIfSetKeyReply represents the VPP binary API message 'ipsec_tunnel_if_set_key_reply'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 1422: +// Generated from 'ipsec.api.json', line 1422: // // "ipsec_tunnel_if_set_key_reply", // [ @@ -2396,18 +2414,18 @@ type IpsecTunnelIfSetKeyReply struct { func (*IpsecTunnelIfSetKeyReply) GetMessageName() string { return "ipsec_tunnel_if_set_key_reply" } -func (*IpsecTunnelIfSetKeyReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IpsecTunnelIfSetKeyReply) GetCrcString() string { return "e8d4e804" } +func (*IpsecTunnelIfSetKeyReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIpsecTunnelIfSetKeyReply() api.Message { return &IpsecTunnelIfSetKeyReply{} } // IpsecTunnelIfSetSa represents the VPP binary API message 'ipsec_tunnel_if_set_sa'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 1440: +// Generated from 'ipsec.api.json', line 1440: // // "ipsec_tunnel_if_set_sa", // [ @@ -2447,18 +2465,18 @@ type IpsecTunnelIfSetSa struct { func (*IpsecTunnelIfSetSa) GetMessageName() string { return "ipsec_tunnel_if_set_sa" } -func (*IpsecTunnelIfSetSa) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*IpsecTunnelIfSetSa) GetCrcString() string { return "6ab567f2" } +func (*IpsecTunnelIfSetSa) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewIpsecTunnelIfSetSa() api.Message { return &IpsecTunnelIfSetSa{} } // IpsecTunnelIfSetSaReply represents the VPP binary API message 'ipsec_tunnel_if_set_sa_reply'. -// Generated from '/usr/share/vpp/api/ipsec.api.json', line 1470: +// Generated from 'ipsec.api.json', line 1470: // // "ipsec_tunnel_if_set_sa_reply", // [ @@ -2484,12 +2502,89 @@ type IpsecTunnelIfSetSaReply struct { func (*IpsecTunnelIfSetSaReply) GetMessageName() string { return "ipsec_tunnel_if_set_sa_reply" } -func (*IpsecTunnelIfSetSaReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*IpsecTunnelIfSetSaReply) GetCrcString() string { return "e8d4e804" } +func (*IpsecTunnelIfSetSaReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewIpsecTunnelIfSetSaReply() api.Message { return &IpsecTunnelIfSetSaReply{} } + +/* Services */ + +type Services interface { + DumpIpsecSa(*IpsecSaDump) (*IpsecSaDetails, error) + DumpIpsecSpd(*IpsecSpdDump) (*IpsecSpdDetails, error) + Ikev2InitiateDelChildSa(*Ikev2InitiateDelChildSa) (*Ikev2InitiateDelChildSaReply, error) + Ikev2InitiateDelIkeSa(*Ikev2InitiateDelIkeSa) (*Ikev2InitiateDelIkeSaReply, error) + Ikev2InitiateRekeyChildSa(*Ikev2InitiateRekeyChildSa) (*Ikev2InitiateRekeyChildSaReply, error) + Ikev2InitiateSaInit(*Ikev2InitiateSaInit) (*Ikev2InitiateSaInitReply, error) + Ikev2ProfileAddDel(*Ikev2ProfileAddDel) (*Ikev2ProfileAddDelReply, error) + Ikev2ProfileSetAuth(*Ikev2ProfileSetAuth) (*Ikev2ProfileSetAuthReply, error) + Ikev2ProfileSetID(*Ikev2ProfileSetID) (*Ikev2ProfileSetIDReply, error) + Ikev2ProfileSetTs(*Ikev2ProfileSetTs) (*Ikev2ProfileSetTsReply, error) + Ikev2SetEspTransforms(*Ikev2SetEspTransforms) (*Ikev2SetEspTransformsReply, error) + Ikev2SetIkeTransforms(*Ikev2SetIkeTransforms) (*Ikev2SetIkeTransformsReply, error) + Ikev2SetLocalKey(*Ikev2SetLocalKey) (*Ikev2SetLocalKeyReply, error) + Ikev2SetResponder(*Ikev2SetResponder) (*Ikev2SetResponderReply, error) + Ikev2SetSaLifetime(*Ikev2SetSaLifetime) (*Ikev2SetSaLifetimeReply, error) + IpsecInterfaceAddDelSpd(*IpsecInterfaceAddDelSpd) (*IpsecInterfaceAddDelSpdReply, error) + IpsecSaSetKey(*IpsecSaSetKey) (*IpsecSaSetKeyReply, error) + IpsecSadAddDelEntry(*IpsecSadAddDelEntry) (*IpsecSadAddDelEntryReply, error) + IpsecSpdAddDel(*IpsecSpdAddDel) (*IpsecSpdAddDelReply, error) + IpsecSpdAddDelEntry(*IpsecSpdAddDelEntry) (*IpsecSpdAddDelEntryReply, error) + IpsecTunnelIfAddDel(*IpsecTunnelIfAddDel) (*IpsecTunnelIfAddDelReply, error) + IpsecTunnelIfSetKey(*IpsecTunnelIfSetKey) (*IpsecTunnelIfSetKeyReply, error) + IpsecTunnelIfSetSa(*IpsecTunnelIfSetSa) (*IpsecTunnelIfSetSaReply, error) +} + +func init() { + api.RegisterMessage((*IpsecSpdAddDel)(nil), "ipsec.IpsecSpdAddDel") + api.RegisterMessage((*IpsecSpdAddDelReply)(nil), "ipsec.IpsecSpdAddDelReply") + api.RegisterMessage((*IpsecInterfaceAddDelSpd)(nil), "ipsec.IpsecInterfaceAddDelSpd") + api.RegisterMessage((*IpsecInterfaceAddDelSpdReply)(nil), "ipsec.IpsecInterfaceAddDelSpdReply") + api.RegisterMessage((*IpsecSpdAddDelEntry)(nil), "ipsec.IpsecSpdAddDelEntry") + api.RegisterMessage((*IpsecSpdAddDelEntryReply)(nil), "ipsec.IpsecSpdAddDelEntryReply") + api.RegisterMessage((*IpsecSadAddDelEntry)(nil), "ipsec.IpsecSadAddDelEntry") + api.RegisterMessage((*IpsecSadAddDelEntryReply)(nil), "ipsec.IpsecSadAddDelEntryReply") + api.RegisterMessage((*IpsecSaSetKey)(nil), "ipsec.IpsecSaSetKey") + api.RegisterMessage((*IpsecSaSetKeyReply)(nil), "ipsec.IpsecSaSetKeyReply") + api.RegisterMessage((*Ikev2ProfileAddDel)(nil), "ipsec.Ikev2ProfileAddDel") + api.RegisterMessage((*Ikev2ProfileAddDelReply)(nil), "ipsec.Ikev2ProfileAddDelReply") + api.RegisterMessage((*Ikev2ProfileSetAuth)(nil), "ipsec.Ikev2ProfileSetAuth") + api.RegisterMessage((*Ikev2ProfileSetAuthReply)(nil), "ipsec.Ikev2ProfileSetAuthReply") + api.RegisterMessage((*Ikev2ProfileSetID)(nil), "ipsec.Ikev2ProfileSetID") + api.RegisterMessage((*Ikev2ProfileSetIDReply)(nil), "ipsec.Ikev2ProfileSetIDReply") + api.RegisterMessage((*Ikev2ProfileSetTs)(nil), "ipsec.Ikev2ProfileSetTs") + api.RegisterMessage((*Ikev2ProfileSetTsReply)(nil), "ipsec.Ikev2ProfileSetTsReply") + api.RegisterMessage((*Ikev2SetLocalKey)(nil), "ipsec.Ikev2SetLocalKey") + api.RegisterMessage((*Ikev2SetLocalKeyReply)(nil), "ipsec.Ikev2SetLocalKeyReply") + api.RegisterMessage((*Ikev2SetResponder)(nil), "ipsec.Ikev2SetResponder") + api.RegisterMessage((*Ikev2SetResponderReply)(nil), "ipsec.Ikev2SetResponderReply") + api.RegisterMessage((*Ikev2SetIkeTransforms)(nil), "ipsec.Ikev2SetIkeTransforms") + api.RegisterMessage((*Ikev2SetIkeTransformsReply)(nil), "ipsec.Ikev2SetIkeTransformsReply") + api.RegisterMessage((*Ikev2SetEspTransforms)(nil), "ipsec.Ikev2SetEspTransforms") + api.RegisterMessage((*Ikev2SetEspTransformsReply)(nil), "ipsec.Ikev2SetEspTransformsReply") + api.RegisterMessage((*Ikev2SetSaLifetime)(nil), "ipsec.Ikev2SetSaLifetime") + api.RegisterMessage((*Ikev2SetSaLifetimeReply)(nil), "ipsec.Ikev2SetSaLifetimeReply") + api.RegisterMessage((*Ikev2InitiateSaInit)(nil), "ipsec.Ikev2InitiateSaInit") + api.RegisterMessage((*Ikev2InitiateSaInitReply)(nil), "ipsec.Ikev2InitiateSaInitReply") + api.RegisterMessage((*Ikev2InitiateDelIkeSa)(nil), "ipsec.Ikev2InitiateDelIkeSa") + api.RegisterMessage((*Ikev2InitiateDelIkeSaReply)(nil), "ipsec.Ikev2InitiateDelIkeSaReply") + api.RegisterMessage((*Ikev2InitiateDelChildSa)(nil), "ipsec.Ikev2InitiateDelChildSa") + api.RegisterMessage((*Ikev2InitiateDelChildSaReply)(nil), "ipsec.Ikev2InitiateDelChildSaReply") + api.RegisterMessage((*Ikev2InitiateRekeyChildSa)(nil), "ipsec.Ikev2InitiateRekeyChildSa") + api.RegisterMessage((*Ikev2InitiateRekeyChildSaReply)(nil), "ipsec.Ikev2InitiateRekeyChildSaReply") + api.RegisterMessage((*IpsecSpdDump)(nil), "ipsec.IpsecSpdDump") + api.RegisterMessage((*IpsecSpdDetails)(nil), "ipsec.IpsecSpdDetails") + api.RegisterMessage((*IpsecTunnelIfAddDel)(nil), "ipsec.IpsecTunnelIfAddDel") + api.RegisterMessage((*IpsecTunnelIfAddDelReply)(nil), "ipsec.IpsecTunnelIfAddDelReply") + api.RegisterMessage((*IpsecSaDump)(nil), "ipsec.IpsecSaDump") + api.RegisterMessage((*IpsecSaDetails)(nil), "ipsec.IpsecSaDetails") + api.RegisterMessage((*IpsecTunnelIfSetKey)(nil), "ipsec.IpsecTunnelIfSetKey") + api.RegisterMessage((*IpsecTunnelIfSetKeyReply)(nil), "ipsec.IpsecTunnelIfSetKeyReply") + api.RegisterMessage((*IpsecTunnelIfSetSa)(nil), "ipsec.IpsecTunnelIfSetSa") + api.RegisterMessage((*IpsecTunnelIfSetSaReply)(nil), "ipsec.IpsecTunnelIfSetSaReply") +} diff --git a/plugins/vpp/binapi/ipsec/pkgreflect.go b/plugins/vpp/binapi/ipsec/pkgreflect.go index e075041666..8c08df99ca 100644 --- a/plugins/vpp/binapi/ipsec/pkgreflect.go +++ b/plugins/vpp/binapi/ipsec/pkgreflect.go @@ -51,6 +51,7 @@ var Types = map[string]reflect.Type{ "IpsecTunnelIfSetKeyReply": reflect.TypeOf((*IpsecTunnelIfSetKeyReply)(nil)).Elem(), "IpsecTunnelIfSetSa": reflect.TypeOf((*IpsecTunnelIfSetSa)(nil)).Elem(), "IpsecTunnelIfSetSaReply": reflect.TypeOf((*IpsecTunnelIfSetSaReply)(nil)).Elem(), + "Services": reflect.TypeOf((*Services)(nil)).Elem(), } var Functions = map[string]reflect.Value{ diff --git a/plugins/vpp/binapi/l2/l2.go b/plugins/vpp/binapi/l2/l2.ba.go similarity index 86% rename from plugins/vpp/binapi/l2/l2.go rename to plugins/vpp/binapi/l2/l2.ba.go index 3513ade067..bc8c890d29 100644 --- a/plugins/vpp/binapi/l2/l2.go +++ b/plugins/vpp/binapi/l2/l2.ba.go @@ -1,12 +1,31 @@ -// Code generated by govpp binapi-generator DO NOT EDIT. -// Package l2 represents the VPP binary API of the 'l2' VPP module. -// Generated from '/usr/share/vpp/api/l2.api.json' +// Code generated by GoVPP binapi-generator. DO NOT EDIT. +// source: /usr/share/vpp/api/l2.api.json + +/* +Package l2 is a generated VPP binary API of the 'l2' VPP module. + +It is generated from this file: + l2.api.json + +It contains these VPP binary API objects: + 43 messages + 2 types + 21 services +*/ package l2 import "git.fd.io/govpp.git/api" +import "github.com/lunixbochs/struc" +import "bytes" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = struc.Pack +var _ = bytes.NewBuffer + +/* Types */ -// MacEntry represents the VPP binary API data type 'mac_entry'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 1206: +// MacEntry represents the VPP binary API type 'mac_entry'. +// Generated from 'l2.api.json', line 1206: // // "mac_entry", // [ @@ -44,8 +63,8 @@ func (*MacEntry) GetCrcString() string { return "971135b8" } -// BridgeDomainSwIf represents the VPP binary API data type 'bridge_domain_sw_if'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 1229: +// BridgeDomainSwIf represents the VPP binary API type 'bridge_domain_sw_if'. +// Generated from 'l2.api.json', line 1229: // // "bridge_domain_sw_if", // [ @@ -77,8 +96,10 @@ func (*BridgeDomainSwIf) GetCrcString() string { return "a06dd426" } +/* Messages */ + // L2XconnectDetails represents the VPP binary API message 'l2_xconnect_details'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 4: +// Generated from 'l2.api.json', line 4: // // "l2_xconnect_details", // [ @@ -109,18 +130,18 @@ type L2XconnectDetails struct { func (*L2XconnectDetails) GetMessageName() string { return "l2_xconnect_details" } -func (*L2XconnectDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*L2XconnectDetails) GetCrcString() string { return "722e2378" } +func (*L2XconnectDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewL2XconnectDetails() api.Message { return &L2XconnectDetails{} } // L2XconnectDump represents the VPP binary API message 'l2_xconnect_dump'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 26: +// Generated from 'l2.api.json', line 26: // // "l2_xconnect_dump", // [ @@ -139,24 +160,23 @@ func NewL2XconnectDetails() api.Message { // "crc": "0x51077d14" // } // -type L2XconnectDump struct { -} +type L2XconnectDump struct{} func (*L2XconnectDump) GetMessageName() string { return "l2_xconnect_dump" } -func (*L2XconnectDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*L2XconnectDump) GetCrcString() string { return "51077d14" } +func (*L2XconnectDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewL2XconnectDump() api.Message { return &L2XconnectDump{} } // L2FibTableDetails represents the VPP binary API message 'l2_fib_table_details'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 44: +// Generated from 'l2.api.json', line 44: // // "l2_fib_table_details", // [ @@ -208,18 +228,18 @@ type L2FibTableDetails struct { func (*L2FibTableDetails) GetMessageName() string { return "l2_fib_table_details" } -func (*L2FibTableDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*L2FibTableDetails) GetCrcString() string { return "c7392706" } +func (*L2FibTableDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewL2FibTableDetails() api.Message { return &L2FibTableDetails{} } // L2FibTableDump represents the VPP binary API message 'l2_fib_table_dump'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 83: +// Generated from 'l2.api.json', line 83: // // "l2_fib_table_dump", // [ @@ -249,18 +269,18 @@ type L2FibTableDump struct { func (*L2FibTableDump) GetMessageName() string { return "l2_fib_table_dump" } -func (*L2FibTableDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*L2FibTableDump) GetCrcString() string { return "c25fdce6" } +func (*L2FibTableDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewL2FibTableDump() api.Message { return &L2FibTableDump{} } // L2FibClearTable represents the VPP binary API message 'l2_fib_clear_table'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 105: +// Generated from 'l2.api.json', line 105: // // "l2_fib_clear_table", // [ @@ -279,24 +299,23 @@ func NewL2FibTableDump() api.Message { // "crc": "0x51077d14" // } // -type L2FibClearTable struct { -} +type L2FibClearTable struct{} func (*L2FibClearTable) GetMessageName() string { return "l2_fib_clear_table" } -func (*L2FibClearTable) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*L2FibClearTable) GetCrcString() string { return "51077d14" } +func (*L2FibClearTable) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewL2FibClearTable() api.Message { return &L2FibClearTable{} } // L2FibClearTableReply represents the VPP binary API message 'l2_fib_clear_table_reply'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 123: +// Generated from 'l2.api.json', line 123: // // "l2_fib_clear_table_reply", // [ @@ -322,18 +341,18 @@ type L2FibClearTableReply struct { func (*L2FibClearTableReply) GetMessageName() string { return "l2_fib_clear_table_reply" } -func (*L2FibClearTableReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*L2FibClearTableReply) GetCrcString() string { return "e8d4e804" } +func (*L2FibClearTableReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewL2FibClearTableReply() api.Message { return &L2FibClearTableReply{} } // L2fibFlushAll represents the VPP binary API message 'l2fib_flush_all'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 141: +// Generated from 'l2.api.json', line 141: // // "l2fib_flush_all", // [ @@ -352,24 +371,23 @@ func NewL2FibClearTableReply() api.Message { // "crc": "0x51077d14" // } // -type L2fibFlushAll struct { -} +type L2fibFlushAll struct{} func (*L2fibFlushAll) GetMessageName() string { return "l2fib_flush_all" } -func (*L2fibFlushAll) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*L2fibFlushAll) GetCrcString() string { return "51077d14" } +func (*L2fibFlushAll) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewL2fibFlushAll() api.Message { return &L2fibFlushAll{} } // L2fibFlushAllReply represents the VPP binary API message 'l2fib_flush_all_reply'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 159: +// Generated from 'l2.api.json', line 159: // // "l2fib_flush_all_reply", // [ @@ -395,18 +413,18 @@ type L2fibFlushAllReply struct { func (*L2fibFlushAllReply) GetMessageName() string { return "l2fib_flush_all_reply" } -func (*L2fibFlushAllReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*L2fibFlushAllReply) GetCrcString() string { return "e8d4e804" } +func (*L2fibFlushAllReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewL2fibFlushAllReply() api.Message { return &L2fibFlushAllReply{} } // L2fibFlushBd represents the VPP binary API message 'l2fib_flush_bd'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 177: +// Generated from 'l2.api.json', line 177: // // "l2fib_flush_bd", // [ @@ -436,18 +454,18 @@ type L2fibFlushBd struct { func (*L2fibFlushBd) GetMessageName() string { return "l2fib_flush_bd" } -func (*L2fibFlushBd) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*L2fibFlushBd) GetCrcString() string { return "c25fdce6" } +func (*L2fibFlushBd) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewL2fibFlushBd() api.Message { return &L2fibFlushBd{} } // L2fibFlushBdReply represents the VPP binary API message 'l2fib_flush_bd_reply'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 199: +// Generated from 'l2.api.json', line 199: // // "l2fib_flush_bd_reply", // [ @@ -473,18 +491,18 @@ type L2fibFlushBdReply struct { func (*L2fibFlushBdReply) GetMessageName() string { return "l2fib_flush_bd_reply" } -func (*L2fibFlushBdReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*L2fibFlushBdReply) GetCrcString() string { return "e8d4e804" } +func (*L2fibFlushBdReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewL2fibFlushBdReply() api.Message { return &L2fibFlushBdReply{} } // L2fibFlushInt represents the VPP binary API message 'l2fib_flush_int'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 217: +// Generated from 'l2.api.json', line 217: // // "l2fib_flush_int", // [ @@ -514,18 +532,18 @@ type L2fibFlushInt struct { func (*L2fibFlushInt) GetMessageName() string { return "l2fib_flush_int" } -func (*L2fibFlushInt) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*L2fibFlushInt) GetCrcString() string { return "529cb13f" } +func (*L2fibFlushInt) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewL2fibFlushInt() api.Message { return &L2fibFlushInt{} } // L2fibFlushIntReply represents the VPP binary API message 'l2fib_flush_int_reply'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 239: +// Generated from 'l2.api.json', line 239: // // "l2fib_flush_int_reply", // [ @@ -551,18 +569,18 @@ type L2fibFlushIntReply struct { func (*L2fibFlushIntReply) GetMessageName() string { return "l2fib_flush_int_reply" } -func (*L2fibFlushIntReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*L2fibFlushIntReply) GetCrcString() string { return "e8d4e804" } +func (*L2fibFlushIntReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewL2fibFlushIntReply() api.Message { return &L2fibFlushIntReply{} } // L2fibAddDel represents the VPP binary API message 'l2fib_add_del'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 257: +// Generated from 'l2.api.json', line 257: // // "l2fib_add_del", // [ @@ -623,18 +641,18 @@ type L2fibAddDel struct { func (*L2fibAddDel) GetMessageName() string { return "l2fib_add_del" } -func (*L2fibAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*L2fibAddDel) GetCrcString() string { return "34ced3eb" } +func (*L2fibAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewL2fibAddDel() api.Message { return &L2fibAddDel{} } // L2fibAddDelReply represents the VPP binary API message 'l2fib_add_del_reply'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 304: +// Generated from 'l2.api.json', line 304: // // "l2fib_add_del_reply", // [ @@ -660,18 +678,18 @@ type L2fibAddDelReply struct { func (*L2fibAddDelReply) GetMessageName() string { return "l2fib_add_del_reply" } -func (*L2fibAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*L2fibAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*L2fibAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewL2fibAddDelReply() api.Message { return &L2fibAddDelReply{} } // WantL2MacsEvents represents the VPP binary API message 'want_l2_macs_events'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 322: +// Generated from 'l2.api.json', line 322: // // "want_l2_macs_events", // [ @@ -715,24 +733,24 @@ type WantL2MacsEvents struct { ScanDelay uint8 MaxMacsInEvent uint8 EnableDisable uint8 - Pid uint32 + PID uint32 } func (*WantL2MacsEvents) GetMessageName() string { return "want_l2_macs_events" } -func (*WantL2MacsEvents) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*WantL2MacsEvents) GetCrcString() string { return "94e63394" } +func (*WantL2MacsEvents) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewWantL2MacsEvents() api.Message { return &WantL2MacsEvents{} } // WantL2MacsEventsReply represents the VPP binary API message 'want_l2_macs_events_reply'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 360: +// Generated from 'l2.api.json', line 360: // // "want_l2_macs_events_reply", // [ @@ -758,18 +776,18 @@ type WantL2MacsEventsReply struct { func (*WantL2MacsEventsReply) GetMessageName() string { return "want_l2_macs_events_reply" } -func (*WantL2MacsEventsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*WantL2MacsEventsReply) GetCrcString() string { return "e8d4e804" } +func (*WantL2MacsEventsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewWantL2MacsEventsReply() api.Message { return &WantL2MacsEventsReply{} } // L2MacsEvent represents the VPP binary API message 'l2_macs_event'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 378: +// Generated from 'l2.api.json', line 378: // // "l2_macs_event", // [ @@ -799,7 +817,7 @@ func NewWantL2MacsEventsReply() api.Message { // } // type L2MacsEvent struct { - Pid uint32 + PID uint32 NMacs uint32 `struc:"sizeof=Mac"` Mac []MacEntry } @@ -807,18 +825,18 @@ type L2MacsEvent struct { func (*L2MacsEvent) GetMessageName() string { return "l2_macs_event" } -func (*L2MacsEvent) GetMessageType() api.MessageType { - return api.EventMessage -} func (*L2MacsEvent) GetCrcString() string { return "4e5ab0c8" } +func (*L2MacsEvent) GetMessageType() api.MessageType { + return api.EventMessage +} func NewL2MacsEvent() api.Message { return &L2MacsEvent{} } // L2Flags represents the VPP binary API message 'l2_flags'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 406: +// Generated from 'l2.api.json', line 406: // // "l2_flags", // [ @@ -858,18 +876,18 @@ type L2Flags struct { func (*L2Flags) GetMessageName() string { return "l2_flags" } -func (*L2Flags) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*L2Flags) GetCrcString() string { return "0e889fb9" } +func (*L2Flags) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewL2Flags() api.Message { return &L2Flags{} } // L2FlagsReply represents the VPP binary API message 'l2_flags_reply'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 436: +// Generated from 'l2.api.json', line 436: // // "l2_flags_reply", // [ @@ -900,18 +918,18 @@ type L2FlagsReply struct { func (*L2FlagsReply) GetMessageName() string { return "l2_flags_reply" } -func (*L2FlagsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*L2FlagsReply) GetCrcString() string { return "29b2a2b3" } +func (*L2FlagsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewL2FlagsReply() api.Message { return &L2FlagsReply{} } // BridgeDomainSetMacAge represents the VPP binary API message 'bridge_domain_set_mac_age'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 458: +// Generated from 'l2.api.json', line 458: // // "bridge_domain_set_mac_age", // [ @@ -946,18 +964,18 @@ type BridgeDomainSetMacAge struct { func (*BridgeDomainSetMacAge) GetMessageName() string { return "bridge_domain_set_mac_age" } -func (*BridgeDomainSetMacAge) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*BridgeDomainSetMacAge) GetCrcString() string { return "b537ad7b" } +func (*BridgeDomainSetMacAge) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewBridgeDomainSetMacAge() api.Message { return &BridgeDomainSetMacAge{} } // BridgeDomainSetMacAgeReply represents the VPP binary API message 'bridge_domain_set_mac_age_reply'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 484: +// Generated from 'l2.api.json', line 484: // // "bridge_domain_set_mac_age_reply", // [ @@ -983,18 +1001,18 @@ type BridgeDomainSetMacAgeReply struct { func (*BridgeDomainSetMacAgeReply) GetMessageName() string { return "bridge_domain_set_mac_age_reply" } -func (*BridgeDomainSetMacAgeReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*BridgeDomainSetMacAgeReply) GetCrcString() string { return "e8d4e804" } +func (*BridgeDomainSetMacAgeReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewBridgeDomainSetMacAgeReply() api.Message { return &BridgeDomainSetMacAgeReply{} } // BridgeDomainAddDel represents the VPP binary API message 'bridge_domain_add_del'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 502: +// Generated from 'l2.api.json', line 502: // // "bridge_domain_add_del", // [ @@ -1065,18 +1083,18 @@ type BridgeDomainAddDel struct { func (*BridgeDomainAddDel) GetMessageName() string { return "bridge_domain_add_del" } -func (*BridgeDomainAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*BridgeDomainAddDel) GetCrcString() string { return "6f668fd9" } +func (*BridgeDomainAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewBridgeDomainAddDel() api.Message { return &BridgeDomainAddDel{} } // BridgeDomainAddDelReply represents the VPP binary API message 'bridge_domain_add_del_reply'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 557: +// Generated from 'l2.api.json', line 557: // // "bridge_domain_add_del_reply", // [ @@ -1102,18 +1120,18 @@ type BridgeDomainAddDelReply struct { func (*BridgeDomainAddDelReply) GetMessageName() string { return "bridge_domain_add_del_reply" } -func (*BridgeDomainAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*BridgeDomainAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*BridgeDomainAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewBridgeDomainAddDelReply() api.Message { return &BridgeDomainAddDelReply{} } // BridgeDomainDump represents the VPP binary API message 'bridge_domain_dump'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 575: +// Generated from 'l2.api.json', line 575: // // "bridge_domain_dump", // [ @@ -1143,18 +1161,18 @@ type BridgeDomainDump struct { func (*BridgeDomainDump) GetMessageName() string { return "bridge_domain_dump" } -func (*BridgeDomainDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*BridgeDomainDump) GetCrcString() string { return "c25fdce6" } +func (*BridgeDomainDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewBridgeDomainDump() api.Message { return &BridgeDomainDump{} } // BridgeDomainDetails represents the VPP binary API message 'bridge_domain_details'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 597: +// Generated from 'l2.api.json', line 597: // // "bridge_domain_details", // [ @@ -1233,18 +1251,18 @@ type BridgeDomainDetails struct { func (*BridgeDomainDetails) GetMessageName() string { return "bridge_domain_details" } -func (*BridgeDomainDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*BridgeDomainDetails) GetCrcString() string { return "5527b45f" } +func (*BridgeDomainDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewBridgeDomainDetails() api.Message { return &BridgeDomainDetails{} } // BridgeFlags represents the VPP binary API message 'bridge_flags'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 658: +// Generated from 'l2.api.json', line 658: // // "bridge_flags", // [ @@ -1284,18 +1302,18 @@ type BridgeFlags struct { func (*BridgeFlags) GetMessageName() string { return "bridge_flags" } -func (*BridgeFlags) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*BridgeFlags) GetCrcString() string { return "6b81f158" } +func (*BridgeFlags) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewBridgeFlags() api.Message { return &BridgeFlags{} } // BridgeFlagsReply represents the VPP binary API message 'bridge_flags_reply'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 688: +// Generated from 'l2.api.json', line 688: // // "bridge_flags_reply", // [ @@ -1326,18 +1344,18 @@ type BridgeFlagsReply struct { func (*BridgeFlagsReply) GetMessageName() string { return "bridge_flags_reply" } -func (*BridgeFlagsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*BridgeFlagsReply) GetCrcString() string { return "29b2a2b3" } +func (*BridgeFlagsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewBridgeFlagsReply() api.Message { return &BridgeFlagsReply{} } // L2InterfaceVlanTagRewrite represents the VPP binary API message 'l2_interface_vlan_tag_rewrite'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 710: +// Generated from 'l2.api.json', line 710: // // "l2_interface_vlan_tag_rewrite", // [ @@ -1387,18 +1405,18 @@ type L2InterfaceVlanTagRewrite struct { func (*L2InterfaceVlanTagRewrite) GetMessageName() string { return "l2_interface_vlan_tag_rewrite" } -func (*L2InterfaceVlanTagRewrite) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*L2InterfaceVlanTagRewrite) GetCrcString() string { return "b90be6b4" } +func (*L2InterfaceVlanTagRewrite) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewL2InterfaceVlanTagRewrite() api.Message { return &L2InterfaceVlanTagRewrite{} } // L2InterfaceVlanTagRewriteReply represents the VPP binary API message 'l2_interface_vlan_tag_rewrite_reply'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 748: +// Generated from 'l2.api.json', line 748: // // "l2_interface_vlan_tag_rewrite_reply", // [ @@ -1424,18 +1442,18 @@ type L2InterfaceVlanTagRewriteReply struct { func (*L2InterfaceVlanTagRewriteReply) GetMessageName() string { return "l2_interface_vlan_tag_rewrite_reply" } -func (*L2InterfaceVlanTagRewriteReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*L2InterfaceVlanTagRewriteReply) GetCrcString() string { return "e8d4e804" } +func (*L2InterfaceVlanTagRewriteReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewL2InterfaceVlanTagRewriteReply() api.Message { return &L2InterfaceVlanTagRewriteReply{} } // L2InterfacePbbTagRewrite represents the VPP binary API message 'l2_interface_pbb_tag_rewrite'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 766: +// Generated from 'l2.api.json', line 766: // // "l2_interface_pbb_tag_rewrite", // [ @@ -1497,18 +1515,18 @@ type L2InterfacePbbTagRewrite struct { func (*L2InterfacePbbTagRewrite) GetMessageName() string { return "l2_interface_pbb_tag_rewrite" } -func (*L2InterfacePbbTagRewrite) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*L2InterfacePbbTagRewrite) GetCrcString() string { return "6cf815f9" } +func (*L2InterfacePbbTagRewrite) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewL2InterfacePbbTagRewrite() api.Message { return &L2InterfacePbbTagRewrite{} } // L2InterfacePbbTagRewriteReply represents the VPP binary API message 'l2_interface_pbb_tag_rewrite_reply'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 814: +// Generated from 'l2.api.json', line 814: // // "l2_interface_pbb_tag_rewrite_reply", // [ @@ -1534,18 +1552,18 @@ type L2InterfacePbbTagRewriteReply struct { func (*L2InterfacePbbTagRewriteReply) GetMessageName() string { return "l2_interface_pbb_tag_rewrite_reply" } -func (*L2InterfacePbbTagRewriteReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*L2InterfacePbbTagRewriteReply) GetCrcString() string { return "e8d4e804" } +func (*L2InterfacePbbTagRewriteReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewL2InterfacePbbTagRewriteReply() api.Message { return &L2InterfacePbbTagRewriteReply{} } // L2PatchAddDel represents the VPP binary API message 'l2_patch_add_del'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 832: +// Generated from 'l2.api.json', line 832: // // "l2_patch_add_del", // [ @@ -1585,18 +1603,18 @@ type L2PatchAddDel struct { func (*L2PatchAddDel) GetMessageName() string { return "l2_patch_add_del" } -func (*L2PatchAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*L2PatchAddDel) GetCrcString() string { return "62506e63" } +func (*L2PatchAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewL2PatchAddDel() api.Message { return &L2PatchAddDel{} } // L2PatchAddDelReply represents the VPP binary API message 'l2_patch_add_del_reply'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 862: +// Generated from 'l2.api.json', line 862: // // "l2_patch_add_del_reply", // [ @@ -1622,18 +1640,18 @@ type L2PatchAddDelReply struct { func (*L2PatchAddDelReply) GetMessageName() string { return "l2_patch_add_del_reply" } -func (*L2PatchAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*L2PatchAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*L2PatchAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewL2PatchAddDelReply() api.Message { return &L2PatchAddDelReply{} } // SwInterfaceSetL2Xconnect represents the VPP binary API message 'sw_interface_set_l2_xconnect'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 880: +// Generated from 'l2.api.json', line 880: // // "sw_interface_set_l2_xconnect", // [ @@ -1673,18 +1691,18 @@ type SwInterfaceSetL2Xconnect struct { func (*SwInterfaceSetL2Xconnect) GetMessageName() string { return "sw_interface_set_l2_xconnect" } -func (*SwInterfaceSetL2Xconnect) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceSetL2Xconnect) GetCrcString() string { return "95de3988" } +func (*SwInterfaceSetL2Xconnect) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceSetL2Xconnect() api.Message { return &SwInterfaceSetL2Xconnect{} } // SwInterfaceSetL2XconnectReply represents the VPP binary API message 'sw_interface_set_l2_xconnect_reply'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 910: +// Generated from 'l2.api.json', line 910: // // "sw_interface_set_l2_xconnect_reply", // [ @@ -1710,18 +1728,18 @@ type SwInterfaceSetL2XconnectReply struct { func (*SwInterfaceSetL2XconnectReply) GetMessageName() string { return "sw_interface_set_l2_xconnect_reply" } -func (*SwInterfaceSetL2XconnectReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceSetL2XconnectReply) GetCrcString() string { return "e8d4e804" } +func (*SwInterfaceSetL2XconnectReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceSetL2XconnectReply() api.Message { return &SwInterfaceSetL2XconnectReply{} } // SwInterfaceSetL2Bridge represents the VPP binary API message 'sw_interface_set_l2_bridge'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 928: +// Generated from 'l2.api.json', line 928: // // "sw_interface_set_l2_bridge", // [ @@ -1771,18 +1789,18 @@ type SwInterfaceSetL2Bridge struct { func (*SwInterfaceSetL2Bridge) GetMessageName() string { return "sw_interface_set_l2_bridge" } -func (*SwInterfaceSetL2Bridge) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceSetL2Bridge) GetCrcString() string { return "95b4e4cf" } +func (*SwInterfaceSetL2Bridge) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceSetL2Bridge() api.Message { return &SwInterfaceSetL2Bridge{} } // SwInterfaceSetL2BridgeReply represents the VPP binary API message 'sw_interface_set_l2_bridge_reply'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 966: +// Generated from 'l2.api.json', line 966: // // "sw_interface_set_l2_bridge_reply", // [ @@ -1808,18 +1826,18 @@ type SwInterfaceSetL2BridgeReply struct { func (*SwInterfaceSetL2BridgeReply) GetMessageName() string { return "sw_interface_set_l2_bridge_reply" } -func (*SwInterfaceSetL2BridgeReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceSetL2BridgeReply) GetCrcString() string { return "e8d4e804" } +func (*SwInterfaceSetL2BridgeReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceSetL2BridgeReply() api.Message { return &SwInterfaceSetL2BridgeReply{} } // BdIPMacAddDel represents the VPP binary API message 'bd_ip_mac_add_del'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 984: +// Generated from 'l2.api.json', line 984: // // "bd_ip_mac_add_del", // [ @@ -1863,7 +1881,7 @@ func NewSwInterfaceSetL2BridgeReply() api.Message { type BdIPMacAddDel struct { BdID uint32 IsAdd uint8 - IsIpv6 uint8 + IsIPv6 uint8 IPAddress []byte `struc:"[16]byte"` MacAddress []byte `struc:"[6]byte"` } @@ -1871,18 +1889,18 @@ type BdIPMacAddDel struct { func (*BdIPMacAddDel) GetMessageName() string { return "bd_ip_mac_add_del" } -func (*BdIPMacAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*BdIPMacAddDel) GetCrcString() string { return "79f42817" } +func (*BdIPMacAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewBdIPMacAddDel() api.Message { return &BdIPMacAddDel{} } // BdIPMacAddDelReply represents the VPP binary API message 'bd_ip_mac_add_del_reply'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 1024: +// Generated from 'l2.api.json', line 1024: // // "bd_ip_mac_add_del_reply", // [ @@ -1908,18 +1926,18 @@ type BdIPMacAddDelReply struct { func (*BdIPMacAddDelReply) GetMessageName() string { return "bd_ip_mac_add_del_reply" } -func (*BdIPMacAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*BdIPMacAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*BdIPMacAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewBdIPMacAddDelReply() api.Message { return &BdIPMacAddDelReply{} } // L2InterfaceEfpFilter represents the VPP binary API message 'l2_interface_efp_filter'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 1042: +// Generated from 'l2.api.json', line 1042: // // "l2_interface_efp_filter", // [ @@ -1939,33 +1957,33 @@ func NewBdIPMacAddDelReply() api.Message { // "sw_if_index" // ], // [ -// "u32", +// "u8", // "enable_disable" // ], // { -// "crc": "0xdabbaf12" +// "crc": "0x69d24598" // } // type L2InterfaceEfpFilter struct { SwIfIndex uint32 - EnableDisable uint32 + EnableDisable uint8 } func (*L2InterfaceEfpFilter) GetMessageName() string { return "l2_interface_efp_filter" } +func (*L2InterfaceEfpFilter) GetCrcString() string { + return "69d24598" +} func (*L2InterfaceEfpFilter) GetMessageType() api.MessageType { return api.RequestMessage } -func (*L2InterfaceEfpFilter) GetCrcString() string { - return "dabbaf12" -} func NewL2InterfaceEfpFilter() api.Message { return &L2InterfaceEfpFilter{} } // L2InterfaceEfpFilterReply represents the VPP binary API message 'l2_interface_efp_filter_reply'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 1068: +// Generated from 'l2.api.json', line 1068: // // "l2_interface_efp_filter_reply", // [ @@ -1991,18 +2009,18 @@ type L2InterfaceEfpFilterReply struct { func (*L2InterfaceEfpFilterReply) GetMessageName() string { return "l2_interface_efp_filter_reply" } -func (*L2InterfaceEfpFilterReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*L2InterfaceEfpFilterReply) GetCrcString() string { return "e8d4e804" } +func (*L2InterfaceEfpFilterReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewL2InterfaceEfpFilterReply() api.Message { return &L2InterfaceEfpFilterReply{} } // SwInterfaceSetVpath represents the VPP binary API message 'sw_interface_set_vpath'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 1086: +// Generated from 'l2.api.json', line 1086: // // "sw_interface_set_vpath", // [ @@ -2037,18 +2055,18 @@ type SwInterfaceSetVpath struct { func (*SwInterfaceSetVpath) GetMessageName() string { return "sw_interface_set_vpath" } -func (*SwInterfaceSetVpath) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceSetVpath) GetCrcString() string { return "a36fadc0" } +func (*SwInterfaceSetVpath) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceSetVpath() api.Message { return &SwInterfaceSetVpath{} } // SwInterfaceSetVpathReply represents the VPP binary API message 'sw_interface_set_vpath_reply'. -// Generated from '/usr/share/vpp/api/l2.api.json', line 1112: +// Generated from 'l2.api.json', line 1112: // // "sw_interface_set_vpath_reply", // [ @@ -2074,12 +2092,84 @@ type SwInterfaceSetVpathReply struct { func (*SwInterfaceSetVpathReply) GetMessageName() string { return "sw_interface_set_vpath_reply" } -func (*SwInterfaceSetVpathReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceSetVpathReply) GetCrcString() string { return "e8d4e804" } +func (*SwInterfaceSetVpathReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceSetVpathReply() api.Message { return &SwInterfaceSetVpathReply{} } + +/* Services */ + +type Services interface { + DumpBridgeDomain(*BridgeDomainDump) (*BridgeDomainDetails, error) + DumpL2FibTable(*L2FibTableDump) (*L2FibTableDetails, error) + DumpL2Xconnect(*L2XconnectDump) (*L2XconnectDetails, error) + BdIPMacAddDel(*BdIPMacAddDel) (*BdIPMacAddDelReply, error) + BridgeDomainAddDel(*BridgeDomainAddDel) (*BridgeDomainAddDelReply, error) + BridgeDomainSetMacAge(*BridgeDomainSetMacAge) (*BridgeDomainSetMacAgeReply, error) + BridgeFlags(*BridgeFlags) (*BridgeFlagsReply, error) + L2FibClearTable(*L2FibClearTable) (*L2FibClearTableReply, error) + L2Flags(*L2Flags) (*L2FlagsReply, error) + L2InterfaceEfpFilter(*L2InterfaceEfpFilter) (*L2InterfaceEfpFilterReply, error) + L2InterfacePbbTagRewrite(*L2InterfacePbbTagRewrite) (*L2InterfacePbbTagRewriteReply, error) + L2InterfaceVlanTagRewrite(*L2InterfaceVlanTagRewrite) (*L2InterfaceVlanTagRewriteReply, error) + L2PatchAddDel(*L2PatchAddDel) (*L2PatchAddDelReply, error) + L2fibAddDel(*L2fibAddDel) (*L2fibAddDelReply, error) + L2fibFlushAll(*L2fibFlushAll) (*L2fibFlushAllReply, error) + L2fibFlushBd(*L2fibFlushBd) (*L2fibFlushBdReply, error) + L2fibFlushInt(*L2fibFlushInt) (*L2fibFlushIntReply, error) + SwInterfaceSetL2Bridge(*SwInterfaceSetL2Bridge) (*SwInterfaceSetL2BridgeReply, error) + SwInterfaceSetL2Xconnect(*SwInterfaceSetL2Xconnect) (*SwInterfaceSetL2XconnectReply, error) + SwInterfaceSetVpath(*SwInterfaceSetVpath) (*SwInterfaceSetVpathReply, error) + WantL2MacsEvents(*WantL2MacsEvents) (*WantL2MacsEventsReply, error) +} + +func init() { + api.RegisterMessage((*L2XconnectDetails)(nil), "l2.L2XconnectDetails") + api.RegisterMessage((*L2XconnectDump)(nil), "l2.L2XconnectDump") + api.RegisterMessage((*L2FibTableDetails)(nil), "l2.L2FibTableDetails") + api.RegisterMessage((*L2FibTableDump)(nil), "l2.L2FibTableDump") + api.RegisterMessage((*L2FibClearTable)(nil), "l2.L2FibClearTable") + api.RegisterMessage((*L2FibClearTableReply)(nil), "l2.L2FibClearTableReply") + api.RegisterMessage((*L2fibFlushAll)(nil), "l2.L2fibFlushAll") + api.RegisterMessage((*L2fibFlushAllReply)(nil), "l2.L2fibFlushAllReply") + api.RegisterMessage((*L2fibFlushBd)(nil), "l2.L2fibFlushBd") + api.RegisterMessage((*L2fibFlushBdReply)(nil), "l2.L2fibFlushBdReply") + api.RegisterMessage((*L2fibFlushInt)(nil), "l2.L2fibFlushInt") + api.RegisterMessage((*L2fibFlushIntReply)(nil), "l2.L2fibFlushIntReply") + api.RegisterMessage((*L2fibAddDel)(nil), "l2.L2fibAddDel") + api.RegisterMessage((*L2fibAddDelReply)(nil), "l2.L2fibAddDelReply") + api.RegisterMessage((*WantL2MacsEvents)(nil), "l2.WantL2MacsEvents") + api.RegisterMessage((*WantL2MacsEventsReply)(nil), "l2.WantL2MacsEventsReply") + api.RegisterMessage((*L2MacsEvent)(nil), "l2.L2MacsEvent") + api.RegisterMessage((*L2Flags)(nil), "l2.L2Flags") + api.RegisterMessage((*L2FlagsReply)(nil), "l2.L2FlagsReply") + api.RegisterMessage((*BridgeDomainSetMacAge)(nil), "l2.BridgeDomainSetMacAge") + api.RegisterMessage((*BridgeDomainSetMacAgeReply)(nil), "l2.BridgeDomainSetMacAgeReply") + api.RegisterMessage((*BridgeDomainAddDel)(nil), "l2.BridgeDomainAddDel") + api.RegisterMessage((*BridgeDomainAddDelReply)(nil), "l2.BridgeDomainAddDelReply") + api.RegisterMessage((*BridgeDomainDump)(nil), "l2.BridgeDomainDump") + api.RegisterMessage((*BridgeDomainDetails)(nil), "l2.BridgeDomainDetails") + api.RegisterMessage((*BridgeFlags)(nil), "l2.BridgeFlags") + api.RegisterMessage((*BridgeFlagsReply)(nil), "l2.BridgeFlagsReply") + api.RegisterMessage((*L2InterfaceVlanTagRewrite)(nil), "l2.L2InterfaceVlanTagRewrite") + api.RegisterMessage((*L2InterfaceVlanTagRewriteReply)(nil), "l2.L2InterfaceVlanTagRewriteReply") + api.RegisterMessage((*L2InterfacePbbTagRewrite)(nil), "l2.L2InterfacePbbTagRewrite") + api.RegisterMessage((*L2InterfacePbbTagRewriteReply)(nil), "l2.L2InterfacePbbTagRewriteReply") + api.RegisterMessage((*L2PatchAddDel)(nil), "l2.L2PatchAddDel") + api.RegisterMessage((*L2PatchAddDelReply)(nil), "l2.L2PatchAddDelReply") + api.RegisterMessage((*SwInterfaceSetL2Xconnect)(nil), "l2.SwInterfaceSetL2Xconnect") + api.RegisterMessage((*SwInterfaceSetL2XconnectReply)(nil), "l2.SwInterfaceSetL2XconnectReply") + api.RegisterMessage((*SwInterfaceSetL2Bridge)(nil), "l2.SwInterfaceSetL2Bridge") + api.RegisterMessage((*SwInterfaceSetL2BridgeReply)(nil), "l2.SwInterfaceSetL2BridgeReply") + api.RegisterMessage((*BdIPMacAddDel)(nil), "l2.BdIPMacAddDel") + api.RegisterMessage((*BdIPMacAddDelReply)(nil), "l2.BdIPMacAddDelReply") + api.RegisterMessage((*L2InterfaceEfpFilter)(nil), "l2.L2InterfaceEfpFilter") + api.RegisterMessage((*L2InterfaceEfpFilterReply)(nil), "l2.L2InterfaceEfpFilterReply") + api.RegisterMessage((*SwInterfaceSetVpath)(nil), "l2.SwInterfaceSetVpath") + api.RegisterMessage((*SwInterfaceSetVpathReply)(nil), "l2.SwInterfaceSetVpathReply") +} diff --git a/plugins/vpp/binapi/l2/pkgreflect.go b/plugins/vpp/binapi/l2/pkgreflect.go index d6ee442ee1..a7bd49dae9 100644 --- a/plugins/vpp/binapi/l2/pkgreflect.go +++ b/plugins/vpp/binapi/l2/pkgreflect.go @@ -42,6 +42,7 @@ var Types = map[string]reflect.Type{ "L2fibFlushInt": reflect.TypeOf((*L2fibFlushInt)(nil)).Elem(), "L2fibFlushIntReply": reflect.TypeOf((*L2fibFlushIntReply)(nil)).Elem(), "MacEntry": reflect.TypeOf((*MacEntry)(nil)).Elem(), + "Services": reflect.TypeOf((*Services)(nil)).Elem(), "SwInterfaceSetL2Bridge": reflect.TypeOf((*SwInterfaceSetL2Bridge)(nil)).Elem(), "SwInterfaceSetL2BridgeReply": reflect.TypeOf((*SwInterfaceSetL2BridgeReply)(nil)).Elem(), "SwInterfaceSetL2Xconnect": reflect.TypeOf((*SwInterfaceSetL2Xconnect)(nil)).Elem(), diff --git a/plugins/vpp/binapi/memif/memif.go b/plugins/vpp/binapi/memif/memif.ba.go similarity index 83% rename from plugins/vpp/binapi/memif/memif.go rename to plugins/vpp/binapi/memif/memif.ba.go index 0df0fcc5e0..9b0d7e4209 100644 --- a/plugins/vpp/binapi/memif/memif.go +++ b/plugins/vpp/binapi/memif/memif.ba.go @@ -1,12 +1,30 @@ -// Code generated by govpp binapi-generator DO NOT EDIT. -// Package memif represents the VPP binary API of the 'memif' VPP module. -// Generated from '/usr/share/vpp/api/memif.api.json' +// Code generated by GoVPP binapi-generator. DO NOT EDIT. +// source: /usr/share/vpp/api/memif.api.json + +/* +Package memif is a generated VPP binary API of the 'memif' VPP module. + +It is generated from this file: + memif.api.json + +It contains these VPP binary API objects: + 10 messages + 5 services +*/ package memif import "git.fd.io/govpp.git/api" +import "github.com/lunixbochs/struc" +import "bytes" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = struc.Pack +var _ = bytes.NewBuffer + +/* Messages */ // MemifSocketFilenameAddDel represents the VPP binary API message 'memif_socket_filename_add_del'. -// Generated from '/usr/share/vpp/api/memif.api.json', line 4: +// Generated from 'memif.api.json', line 4: // // "memif_socket_filename_add_del", // [ @@ -47,18 +65,18 @@ type MemifSocketFilenameAddDel struct { func (*MemifSocketFilenameAddDel) GetMessageName() string { return "memif_socket_filename_add_del" } -func (*MemifSocketFilenameAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*MemifSocketFilenameAddDel) GetCrcString() string { return "30e3929d" } +func (*MemifSocketFilenameAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewMemifSocketFilenameAddDel() api.Message { return &MemifSocketFilenameAddDel{} } // MemifSocketFilenameAddDelReply represents the VPP binary API message 'memif_socket_filename_add_del_reply'. -// Generated from '/usr/share/vpp/api/memif.api.json', line 35: +// Generated from 'memif.api.json', line 35: // // "memif_socket_filename_add_del_reply", // [ @@ -84,18 +102,18 @@ type MemifSocketFilenameAddDelReply struct { func (*MemifSocketFilenameAddDelReply) GetMessageName() string { return "memif_socket_filename_add_del_reply" } -func (*MemifSocketFilenameAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*MemifSocketFilenameAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*MemifSocketFilenameAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewMemifSocketFilenameAddDelReply() api.Message { return &MemifSocketFilenameAddDelReply{} } // MemifCreate represents the VPP binary API message 'memif_create'. -// Generated from '/usr/share/vpp/api/memif.api.json', line 53: +// Generated from 'memif.api.json', line 53: // // "memif_create", // [ @@ -172,18 +190,18 @@ type MemifCreate struct { func (*MemifCreate) GetMessageName() string { return "memif_create" } -func (*MemifCreate) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*MemifCreate) GetCrcString() string { return "6597cdb2" } +func (*MemifCreate) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewMemifCreate() api.Message { return &MemifCreate{} } // MemifCreateReply represents the VPP binary API message 'memif_create_reply'. -// Generated from '/usr/share/vpp/api/memif.api.json', line 113: +// Generated from 'memif.api.json', line 113: // // "memif_create_reply", // [ @@ -214,18 +232,18 @@ type MemifCreateReply struct { func (*MemifCreateReply) GetMessageName() string { return "memif_create_reply" } -func (*MemifCreateReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*MemifCreateReply) GetCrcString() string { return "fda5941f" } +func (*MemifCreateReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewMemifCreateReply() api.Message { return &MemifCreateReply{} } // MemifDelete represents the VPP binary API message 'memif_delete'. -// Generated from '/usr/share/vpp/api/memif.api.json', line 135: +// Generated from 'memif.api.json', line 135: // // "memif_delete", // [ @@ -255,18 +273,18 @@ type MemifDelete struct { func (*MemifDelete) GetMessageName() string { return "memif_delete" } -func (*MemifDelete) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*MemifDelete) GetCrcString() string { return "529cb13f" } +func (*MemifDelete) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewMemifDelete() api.Message { return &MemifDelete{} } // MemifDeleteReply represents the VPP binary API message 'memif_delete_reply'. -// Generated from '/usr/share/vpp/api/memif.api.json', line 157: +// Generated from 'memif.api.json', line 157: // // "memif_delete_reply", // [ @@ -292,18 +310,18 @@ type MemifDeleteReply struct { func (*MemifDeleteReply) GetMessageName() string { return "memif_delete_reply" } -func (*MemifDeleteReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*MemifDeleteReply) GetCrcString() string { return "e8d4e804" } +func (*MemifDeleteReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewMemifDeleteReply() api.Message { return &MemifDeleteReply{} } // MemifSocketFilenameDetails represents the VPP binary API message 'memif_socket_filename_details'. -// Generated from '/usr/share/vpp/api/memif.api.json', line 175: +// Generated from 'memif.api.json', line 175: // // "memif_socket_filename_details", // [ @@ -335,18 +353,18 @@ type MemifSocketFilenameDetails struct { func (*MemifSocketFilenameDetails) GetMessageName() string { return "memif_socket_filename_details" } -func (*MemifSocketFilenameDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*MemifSocketFilenameDetails) GetCrcString() string { return "e347e32f" } +func (*MemifSocketFilenameDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewMemifSocketFilenameDetails() api.Message { return &MemifSocketFilenameDetails{} } // MemifSocketFilenameDump represents the VPP binary API message 'memif_socket_filename_dump'. -// Generated from '/usr/share/vpp/api/memif.api.json', line 198: +// Generated from 'memif.api.json', line 198: // // "memif_socket_filename_dump", // [ @@ -365,24 +383,23 @@ func NewMemifSocketFilenameDetails() api.Message { // "crc": "0x51077d14" // } // -type MemifSocketFilenameDump struct { -} +type MemifSocketFilenameDump struct{} func (*MemifSocketFilenameDump) GetMessageName() string { return "memif_socket_filename_dump" } -func (*MemifSocketFilenameDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*MemifSocketFilenameDump) GetCrcString() string { return "51077d14" } +func (*MemifSocketFilenameDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewMemifSocketFilenameDump() api.Message { return &MemifSocketFilenameDump{} } // MemifDetails represents the VPP binary API message 'memif_details'. -// Generated from '/usr/share/vpp/api/memif.api.json', line 216: +// Generated from 'memif.api.json', line 216: // // "memif_details", // [ @@ -460,18 +477,18 @@ type MemifDetails struct { func (*MemifDetails) GetMessageName() string { return "memif_details" } -func (*MemifDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*MemifDetails) GetCrcString() string { return "4f5a3397" } +func (*MemifDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewMemifDetails() api.Message { return &MemifDetails{} } // MemifDump represents the VPP binary API message 'memif_dump'. -// Generated from '/usr/share/vpp/api/memif.api.json', line 276: +// Generated from 'memif.api.json', line 276: // // "memif_dump", // [ @@ -490,18 +507,40 @@ func NewMemifDetails() api.Message { // "crc": "0x51077d14" // } // -type MemifDump struct { -} +type MemifDump struct{} func (*MemifDump) GetMessageName() string { return "memif_dump" } -func (*MemifDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*MemifDump) GetCrcString() string { return "51077d14" } +func (*MemifDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewMemifDump() api.Message { return &MemifDump{} } + +/* Services */ + +type Services interface { + DumpMemif(*MemifDump) (*MemifDetails, error) + DumpMemifSocketFilename(*MemifSocketFilenameDump) (*MemifSocketFilenameDetails, error) + MemifCreate(*MemifCreate) (*MemifCreateReply, error) + MemifDelete(*MemifDelete) (*MemifDeleteReply, error) + MemifSocketFilenameAddDel(*MemifSocketFilenameAddDel) (*MemifSocketFilenameAddDelReply, error) +} + +func init() { + api.RegisterMessage((*MemifSocketFilenameAddDel)(nil), "memif.MemifSocketFilenameAddDel") + api.RegisterMessage((*MemifSocketFilenameAddDelReply)(nil), "memif.MemifSocketFilenameAddDelReply") + api.RegisterMessage((*MemifCreate)(nil), "memif.MemifCreate") + api.RegisterMessage((*MemifCreateReply)(nil), "memif.MemifCreateReply") + api.RegisterMessage((*MemifDelete)(nil), "memif.MemifDelete") + api.RegisterMessage((*MemifDeleteReply)(nil), "memif.MemifDeleteReply") + api.RegisterMessage((*MemifSocketFilenameDetails)(nil), "memif.MemifSocketFilenameDetails") + api.RegisterMessage((*MemifSocketFilenameDump)(nil), "memif.MemifSocketFilenameDump") + api.RegisterMessage((*MemifDetails)(nil), "memif.MemifDetails") + api.RegisterMessage((*MemifDump)(nil), "memif.MemifDump") +} diff --git a/plugins/vpp/binapi/memif/pkgreflect.go b/plugins/vpp/binapi/memif/pkgreflect.go index 3b48cb9b0f..a7715093b2 100644 --- a/plugins/vpp/binapi/memif/pkgreflect.go +++ b/plugins/vpp/binapi/memif/pkgreflect.go @@ -15,6 +15,7 @@ var Types = map[string]reflect.Type{ "MemifSocketFilenameAddDelReply": reflect.TypeOf((*MemifSocketFilenameAddDelReply)(nil)).Elem(), "MemifSocketFilenameDetails": reflect.TypeOf((*MemifSocketFilenameDetails)(nil)).Elem(), "MemifSocketFilenameDump": reflect.TypeOf((*MemifSocketFilenameDump)(nil)).Elem(), + "Services": reflect.TypeOf((*Services)(nil)).Elem(), } var Functions = map[string]reflect.Value{ diff --git a/plugins/vpp/binapi/nat/nat.go b/plugins/vpp/binapi/nat/nat.ba.go similarity index 86% rename from plugins/vpp/binapi/nat/nat.go rename to plugins/vpp/binapi/nat/nat.ba.go index 2b1fed0f5e..942719b482 100644 --- a/plugins/vpp/binapi/nat/nat.go +++ b/plugins/vpp/binapi/nat/nat.ba.go @@ -1,12 +1,31 @@ -// Code generated by govpp binapi-generator DO NOT EDIT. -// Package nat represents the VPP binary API of the 'nat' VPP module. -// Generated from '/usr/share/vpp/api/nat.api.json' +// Code generated by GoVPP binapi-generator. DO NOT EDIT. +// source: /usr/share/vpp/api/nat.api.json + +/* +Package nat is a generated VPP binary API of the 'nat' VPP module. + +It is generated from this file: + nat.api.json + +It contains these VPP binary API objects: + 116 messages + 1 type + 58 services +*/ package nat import "git.fd.io/govpp.git/api" +import "github.com/lunixbochs/struc" +import "bytes" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = struc.Pack +var _ = bytes.NewBuffer -// Nat44LbAddrPort represents the VPP binary API data type 'nat44_lb_addr_port'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 3424: +/* Types */ + +// Nat44LbAddrPort represents the VPP binary API type 'nat44_lb_addr_port'. +// Generated from 'nat.api.json', line 3416: // // "nat44_lb_addr_port", // [ @@ -22,25 +41,32 @@ import "git.fd.io/govpp.git/api" // "u8", // "probability" // ], +// [ +// "u32", +// "vrf_id" +// ], // { -// "crc": "0x513cf9d0" +// "crc": "0x15ce9cd1" // } // type Nat44LbAddrPort struct { Addr []byte `struc:"[4]byte"` Port uint16 Probability uint8 + VrfID uint32 } func (*Nat44LbAddrPort) GetTypeName() string { return "nat44_lb_addr_port" } func (*Nat44LbAddrPort) GetCrcString() string { - return "513cf9d0" + return "15ce9cd1" } +/* Messages */ + // NatControlPing represents the VPP binary API message 'nat_control_ping'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 4: +// Generated from 'nat.api.json', line 4: // // "nat_control_ping", // [ @@ -59,24 +85,23 @@ func (*Nat44LbAddrPort) GetCrcString() string { // "crc": "0x51077d14" // } // -type NatControlPing struct { -} +type NatControlPing struct{} func (*NatControlPing) GetMessageName() string { return "nat_control_ping" } -func (*NatControlPing) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*NatControlPing) GetCrcString() string { return "51077d14" } +func (*NatControlPing) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNatControlPing() api.Message { return &NatControlPing{} } // NatControlPingReply represents the VPP binary API message 'nat_control_ping_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 22: +// Generated from 'nat.api.json', line 22: // // "nat_control_ping_reply", // [ @@ -106,24 +131,24 @@ func NewNatControlPing() api.Message { type NatControlPingReply struct { Retval int32 ClientIndex uint32 - VpePid uint32 + VpePID uint32 } func (*NatControlPingReply) GetMessageName() string { return "nat_control_ping_reply" } -func (*NatControlPingReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*NatControlPingReply) GetCrcString() string { return "f6b0b8ca" } +func (*NatControlPingReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNatControlPingReply() api.Message { return &NatControlPingReply{} } // NatShowConfig represents the VPP binary API message 'nat_show_config'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 48: +// Generated from 'nat.api.json', line 48: // // "nat_show_config", // [ @@ -142,24 +167,23 @@ func NewNatControlPingReply() api.Message { // "crc": "0x51077d14" // } // -type NatShowConfig struct { -} +type NatShowConfig struct{} func (*NatShowConfig) GetMessageName() string { return "nat_show_config" } -func (*NatShowConfig) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*NatShowConfig) GetCrcString() string { return "51077d14" } +func (*NatShowConfig) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNatShowConfig() api.Message { return &NatShowConfig{} } // NatShowConfigReply represents the VPP binary API message 'nat_show_config_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 66: +// Generated from 'nat.api.json', line 66: // // "nat_show_config_reply", // [ @@ -235,18 +259,18 @@ type NatShowConfigReply struct { func (*NatShowConfigReply) GetMessageName() string { return "nat_show_config_reply" } -func (*NatShowConfigReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*NatShowConfigReply) GetCrcString() string { return "7685fc1c" } +func (*NatShowConfigReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNatShowConfigReply() api.Message { return &NatShowConfigReply{} } // NatSetWorkers represents the VPP binary API message 'nat_set_workers'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 124: +// Generated from 'nat.api.json', line 124: // // "nat_set_workers", // [ @@ -276,18 +300,18 @@ type NatSetWorkers struct { func (*NatSetWorkers) GetMessageName() string { return "nat_set_workers" } -func (*NatSetWorkers) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*NatSetWorkers) GetCrcString() string { return "da926638" } +func (*NatSetWorkers) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNatSetWorkers() api.Message { return &NatSetWorkers{} } // NatSetWorkersReply represents the VPP binary API message 'nat_set_workers_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 146: +// Generated from 'nat.api.json', line 146: // // "nat_set_workers_reply", // [ @@ -313,18 +337,18 @@ type NatSetWorkersReply struct { func (*NatSetWorkersReply) GetMessageName() string { return "nat_set_workers_reply" } -func (*NatSetWorkersReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*NatSetWorkersReply) GetCrcString() string { return "e8d4e804" } +func (*NatSetWorkersReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNatSetWorkersReply() api.Message { return &NatSetWorkersReply{} } // NatWorkerDump represents the VPP binary API message 'nat_worker_dump'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 164: +// Generated from 'nat.api.json', line 164: // // "nat_worker_dump", // [ @@ -343,24 +367,23 @@ func NewNatSetWorkersReply() api.Message { // "crc": "0x51077d14" // } // -type NatWorkerDump struct { -} +type NatWorkerDump struct{} func (*NatWorkerDump) GetMessageName() string { return "nat_worker_dump" } -func (*NatWorkerDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*NatWorkerDump) GetCrcString() string { return "51077d14" } +func (*NatWorkerDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNatWorkerDump() api.Message { return &NatWorkerDump{} } // NatWorkerDetails represents the VPP binary API message 'nat_worker_details'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 182: +// Generated from 'nat.api.json', line 182: // // "nat_worker_details", // [ @@ -397,18 +420,18 @@ type NatWorkerDetails struct { func (*NatWorkerDetails) GetMessageName() string { return "nat_worker_details" } -func (*NatWorkerDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*NatWorkerDetails) GetCrcString() string { return "2e3f9d4b" } +func (*NatWorkerDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNatWorkerDetails() api.Message { return &NatWorkerDetails{} } // NatIpfixEnableDisable represents the VPP binary API message 'nat_ipfix_enable_disable'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 209: +// Generated from 'nat.api.json', line 209: // // "nat_ipfix_enable_disable", // [ @@ -448,18 +471,18 @@ type NatIpfixEnableDisable struct { func (*NatIpfixEnableDisable) GetMessageName() string { return "nat_ipfix_enable_disable" } -func (*NatIpfixEnableDisable) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*NatIpfixEnableDisable) GetCrcString() string { return "745dd24b" } +func (*NatIpfixEnableDisable) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNatIpfixEnableDisable() api.Message { return &NatIpfixEnableDisable{} } // NatIpfixEnableDisableReply represents the VPP binary API message 'nat_ipfix_enable_disable_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 239: +// Generated from 'nat.api.json', line 239: // // "nat_ipfix_enable_disable_reply", // [ @@ -485,18 +508,18 @@ type NatIpfixEnableDisableReply struct { func (*NatIpfixEnableDisableReply) GetMessageName() string { return "nat_ipfix_enable_disable_reply" } -func (*NatIpfixEnableDisableReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*NatIpfixEnableDisableReply) GetCrcString() string { return "e8d4e804" } +func (*NatIpfixEnableDisableReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNatIpfixEnableDisableReply() api.Message { return &NatIpfixEnableDisableReply{} } // NatSetReass represents the VPP binary API message 'nat_set_reass'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 257: +// Generated from 'nat.api.json', line 257: // // "nat_set_reass", // [ @@ -546,18 +569,18 @@ type NatSetReass struct { func (*NatSetReass) GetMessageName() string { return "nat_set_reass" } -func (*NatSetReass) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*NatSetReass) GetCrcString() string { return "cb126174" } +func (*NatSetReass) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNatSetReass() api.Message { return &NatSetReass{} } // NatSetReassReply represents the VPP binary API message 'nat_set_reass_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 295: +// Generated from 'nat.api.json', line 295: // // "nat_set_reass_reply", // [ @@ -583,18 +606,18 @@ type NatSetReassReply struct { func (*NatSetReassReply) GetMessageName() string { return "nat_set_reass_reply" } -func (*NatSetReassReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*NatSetReassReply) GetCrcString() string { return "e8d4e804" } +func (*NatSetReassReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNatSetReassReply() api.Message { return &NatSetReassReply{} } // NatGetReass represents the VPP binary API message 'nat_get_reass'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 313: +// Generated from 'nat.api.json', line 313: // // "nat_get_reass", // [ @@ -613,24 +636,23 @@ func NewNatSetReassReply() api.Message { // "crc": "0x51077d14" // } // -type NatGetReass struct { -} +type NatGetReass struct{} func (*NatGetReass) GetMessageName() string { return "nat_get_reass" } -func (*NatGetReass) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*NatGetReass) GetCrcString() string { return "51077d14" } +func (*NatGetReass) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNatGetReass() api.Message { return &NatGetReass{} } // NatGetReassReply represents the VPP binary API message 'nat_get_reass_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 331: +// Generated from 'nat.api.json', line 331: // // "nat_get_reass_reply", // [ @@ -696,18 +718,18 @@ type NatGetReassReply struct { func (*NatGetReassReply) GetMessageName() string { return "nat_get_reass_reply" } -func (*NatGetReassReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*NatGetReassReply) GetCrcString() string { return "8102a0fb" } +func (*NatGetReassReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNatGetReassReply() api.Message { return &NatGetReassReply{} } // NatReassDump represents the VPP binary API message 'nat_reass_dump'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 381: +// Generated from 'nat.api.json', line 381: // // "nat_reass_dump", // [ @@ -726,24 +748,23 @@ func NewNatGetReassReply() api.Message { // "crc": "0x51077d14" // } // -type NatReassDump struct { -} +type NatReassDump struct{} func (*NatReassDump) GetMessageName() string { return "nat_reass_dump" } -func (*NatReassDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*NatReassDump) GetCrcString() string { return "51077d14" } +func (*NatReassDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNatReassDump() api.Message { return &NatReassDump{} } // NatReassDetails represents the VPP binary API message 'nat_reass_details'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 399: +// Generated from 'nat.api.json', line 399: // // "nat_reass_details", // [ @@ -796,18 +817,18 @@ type NatReassDetails struct { func (*NatReassDetails) GetMessageName() string { return "nat_reass_details" } -func (*NatReassDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*NatReassDetails) GetCrcString() string { return "ee46e2d4" } +func (*NatReassDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNatReassDetails() api.Message { return &NatReassDetails{} } // Nat44AddDelAddressRange represents the VPP binary API message 'nat44_add_del_address_range'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 439: +// Generated from 'nat.api.json', line 439: // // "nat44_add_del_address_range", // [ @@ -859,18 +880,18 @@ type Nat44AddDelAddressRange struct { func (*Nat44AddDelAddressRange) GetMessageName() string { return "nat44_add_del_address_range" } -func (*Nat44AddDelAddressRange) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat44AddDelAddressRange) GetCrcString() string { return "4a7d5c11" } +func (*Nat44AddDelAddressRange) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat44AddDelAddressRange() api.Message { return &Nat44AddDelAddressRange{} } // Nat44AddDelAddressRangeReply represents the VPP binary API message 'nat44_add_del_address_range_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 479: +// Generated from 'nat.api.json', line 479: // // "nat44_add_del_address_range_reply", // [ @@ -896,18 +917,18 @@ type Nat44AddDelAddressRangeReply struct { func (*Nat44AddDelAddressRangeReply) GetMessageName() string { return "nat44_add_del_address_range_reply" } -func (*Nat44AddDelAddressRangeReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat44AddDelAddressRangeReply) GetCrcString() string { return "e8d4e804" } +func (*Nat44AddDelAddressRangeReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat44AddDelAddressRangeReply() api.Message { return &Nat44AddDelAddressRangeReply{} } // Nat44AddressDump represents the VPP binary API message 'nat44_address_dump'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 497: +// Generated from 'nat.api.json', line 497: // // "nat44_address_dump", // [ @@ -926,24 +947,23 @@ func NewNat44AddDelAddressRangeReply() api.Message { // "crc": "0x51077d14" // } // -type Nat44AddressDump struct { -} +type Nat44AddressDump struct{} func (*Nat44AddressDump) GetMessageName() string { return "nat44_address_dump" } -func (*Nat44AddressDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat44AddressDump) GetCrcString() string { return "51077d14" } +func (*Nat44AddressDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat44AddressDump() api.Message { return &Nat44AddressDump{} } // Nat44AddressDetails represents the VPP binary API message 'nat44_address_details'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 515: +// Generated from 'nat.api.json', line 515: // // "nat44_address_details", // [ @@ -980,18 +1000,18 @@ type Nat44AddressDetails struct { func (*Nat44AddressDetails) GetMessageName() string { return "nat44_address_details" } -func (*Nat44AddressDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat44AddressDetails) GetCrcString() string { return "512feae8" } +func (*Nat44AddressDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat44AddressDetails() api.Message { return &Nat44AddressDetails{} } // Nat44InterfaceAddDelFeature represents the VPP binary API message 'nat44_interface_add_del_feature'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 542: +// Generated from 'nat.api.json', line 542: // // "nat44_interface_add_del_feature", // [ @@ -1031,18 +1051,18 @@ type Nat44InterfaceAddDelFeature struct { func (*Nat44InterfaceAddDelFeature) GetMessageName() string { return "nat44_interface_add_del_feature" } -func (*Nat44InterfaceAddDelFeature) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat44InterfaceAddDelFeature) GetCrcString() string { return "9b1ac600" } +func (*Nat44InterfaceAddDelFeature) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat44InterfaceAddDelFeature() api.Message { return &Nat44InterfaceAddDelFeature{} } // Nat44InterfaceAddDelFeatureReply represents the VPP binary API message 'nat44_interface_add_del_feature_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 572: +// Generated from 'nat.api.json', line 572: // // "nat44_interface_add_del_feature_reply", // [ @@ -1068,18 +1088,18 @@ type Nat44InterfaceAddDelFeatureReply struct { func (*Nat44InterfaceAddDelFeatureReply) GetMessageName() string { return "nat44_interface_add_del_feature_reply" } -func (*Nat44InterfaceAddDelFeatureReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat44InterfaceAddDelFeatureReply) GetCrcString() string { return "e8d4e804" } +func (*Nat44InterfaceAddDelFeatureReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat44InterfaceAddDelFeatureReply() api.Message { return &Nat44InterfaceAddDelFeatureReply{} } // Nat44InterfaceDump represents the VPP binary API message 'nat44_interface_dump'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 590: +// Generated from 'nat.api.json', line 590: // // "nat44_interface_dump", // [ @@ -1098,24 +1118,23 @@ func NewNat44InterfaceAddDelFeatureReply() api.Message { // "crc": "0x51077d14" // } // -type Nat44InterfaceDump struct { -} +type Nat44InterfaceDump struct{} func (*Nat44InterfaceDump) GetMessageName() string { return "nat44_interface_dump" } -func (*Nat44InterfaceDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat44InterfaceDump) GetCrcString() string { return "51077d14" } +func (*Nat44InterfaceDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat44InterfaceDump() api.Message { return &Nat44InterfaceDump{} } // Nat44InterfaceDetails represents the VPP binary API message 'nat44_interface_details'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 608: +// Generated from 'nat.api.json', line 608: // // "nat44_interface_details", // [ @@ -1146,18 +1165,18 @@ type Nat44InterfaceDetails struct { func (*Nat44InterfaceDetails) GetMessageName() string { return "nat44_interface_details" } -func (*Nat44InterfaceDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat44InterfaceDetails) GetCrcString() string { return "2b15e8e4" } +func (*Nat44InterfaceDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat44InterfaceDetails() api.Message { return &Nat44InterfaceDetails{} } // Nat44InterfaceAddDelOutputFeature represents the VPP binary API message 'nat44_interface_add_del_output_feature'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 630: +// Generated from 'nat.api.json', line 630: // // "nat44_interface_add_del_output_feature", // [ @@ -1197,18 +1216,18 @@ type Nat44InterfaceAddDelOutputFeature struct { func (*Nat44InterfaceAddDelOutputFeature) GetMessageName() string { return "nat44_interface_add_del_output_feature" } -func (*Nat44InterfaceAddDelOutputFeature) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat44InterfaceAddDelOutputFeature) GetCrcString() string { return "9b1ac600" } +func (*Nat44InterfaceAddDelOutputFeature) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat44InterfaceAddDelOutputFeature() api.Message { return &Nat44InterfaceAddDelOutputFeature{} } // Nat44InterfaceAddDelOutputFeatureReply represents the VPP binary API message 'nat44_interface_add_del_output_feature_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 660: +// Generated from 'nat.api.json', line 660: // // "nat44_interface_add_del_output_feature_reply", // [ @@ -1234,18 +1253,18 @@ type Nat44InterfaceAddDelOutputFeatureReply struct { func (*Nat44InterfaceAddDelOutputFeatureReply) GetMessageName() string { return "nat44_interface_add_del_output_feature_reply" } -func (*Nat44InterfaceAddDelOutputFeatureReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat44InterfaceAddDelOutputFeatureReply) GetCrcString() string { return "e8d4e804" } +func (*Nat44InterfaceAddDelOutputFeatureReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat44InterfaceAddDelOutputFeatureReply() api.Message { return &Nat44InterfaceAddDelOutputFeatureReply{} } // Nat44InterfaceOutputFeatureDump represents the VPP binary API message 'nat44_interface_output_feature_dump'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 678: +// Generated from 'nat.api.json', line 678: // // "nat44_interface_output_feature_dump", // [ @@ -1264,24 +1283,23 @@ func NewNat44InterfaceAddDelOutputFeatureReply() api.Message { // "crc": "0x51077d14" // } // -type Nat44InterfaceOutputFeatureDump struct { -} +type Nat44InterfaceOutputFeatureDump struct{} func (*Nat44InterfaceOutputFeatureDump) GetMessageName() string { return "nat44_interface_output_feature_dump" } -func (*Nat44InterfaceOutputFeatureDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat44InterfaceOutputFeatureDump) GetCrcString() string { return "51077d14" } +func (*Nat44InterfaceOutputFeatureDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat44InterfaceOutputFeatureDump() api.Message { return &Nat44InterfaceOutputFeatureDump{} } // Nat44InterfaceOutputFeatureDetails represents the VPP binary API message 'nat44_interface_output_feature_details'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 696: +// Generated from 'nat.api.json', line 696: // // "nat44_interface_output_feature_details", // [ @@ -1312,18 +1330,18 @@ type Nat44InterfaceOutputFeatureDetails struct { func (*Nat44InterfaceOutputFeatureDetails) GetMessageName() string { return "nat44_interface_output_feature_details" } -func (*Nat44InterfaceOutputFeatureDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat44InterfaceOutputFeatureDetails) GetCrcString() string { return "2b15e8e4" } +func (*Nat44InterfaceOutputFeatureDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat44InterfaceOutputFeatureDetails() api.Message { return &Nat44InterfaceOutputFeatureDetails{} } // Nat44AddDelStaticMapping represents the VPP binary API message 'nat44_add_del_static_mapping'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 718: +// Generated from 'nat.api.json', line 718: // // "nat44_add_del_static_mapping", // [ @@ -1416,18 +1434,18 @@ type Nat44AddDelStaticMapping struct { func (*Nat44AddDelStaticMapping) GetMessageName() string { return "nat44_add_del_static_mapping" } -func (*Nat44AddDelStaticMapping) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat44AddDelStaticMapping) GetCrcString() string { return "9f35331e" } +func (*Nat44AddDelStaticMapping) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat44AddDelStaticMapping() api.Message { return &Nat44AddDelStaticMapping{} } // Nat44AddDelStaticMappingReply represents the VPP binary API message 'nat44_add_del_static_mapping_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 791: +// Generated from 'nat.api.json', line 791: // // "nat44_add_del_static_mapping_reply", // [ @@ -1453,18 +1471,18 @@ type Nat44AddDelStaticMappingReply struct { func (*Nat44AddDelStaticMappingReply) GetMessageName() string { return "nat44_add_del_static_mapping_reply" } -func (*Nat44AddDelStaticMappingReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat44AddDelStaticMappingReply) GetCrcString() string { return "e8d4e804" } +func (*Nat44AddDelStaticMappingReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat44AddDelStaticMappingReply() api.Message { return &Nat44AddDelStaticMappingReply{} } // Nat44StaticMappingDump represents the VPP binary API message 'nat44_static_mapping_dump'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 809: +// Generated from 'nat.api.json', line 809: // // "nat44_static_mapping_dump", // [ @@ -1483,24 +1501,23 @@ func NewNat44AddDelStaticMappingReply() api.Message { // "crc": "0x51077d14" // } // -type Nat44StaticMappingDump struct { -} +type Nat44StaticMappingDump struct{} func (*Nat44StaticMappingDump) GetMessageName() string { return "nat44_static_mapping_dump" } -func (*Nat44StaticMappingDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat44StaticMappingDump) GetCrcString() string { return "51077d14" } +func (*Nat44StaticMappingDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat44StaticMappingDump() api.Message { return &Nat44StaticMappingDump{} } // Nat44StaticMappingDetails represents the VPP binary API message 'nat44_static_mapping_details'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 827: +// Generated from 'nat.api.json', line 827: // // "nat44_static_mapping_details", // [ @@ -1584,18 +1601,18 @@ type Nat44StaticMappingDetails struct { func (*Nat44StaticMappingDetails) GetMessageName() string { return "nat44_static_mapping_details" } -func (*Nat44StaticMappingDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat44StaticMappingDetails) GetCrcString() string { return "cf257b56" } +func (*Nat44StaticMappingDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat44StaticMappingDetails() api.Message { return &Nat44StaticMappingDetails{} } // Nat44AddDelIdentityMapping represents the VPP binary API message 'nat44_add_del_identity_mapping'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 892: +// Generated from 'nat.api.json', line 892: // // "nat44_add_del_identity_mapping", // [ @@ -1662,18 +1679,18 @@ type Nat44AddDelIdentityMapping struct { func (*Nat44AddDelIdentityMapping) GetMessageName() string { return "nat44_add_del_identity_mapping" } -func (*Nat44AddDelIdentityMapping) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat44AddDelIdentityMapping) GetCrcString() string { return "8ead5659" } +func (*Nat44AddDelIdentityMapping) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat44AddDelIdentityMapping() api.Message { return &Nat44AddDelIdentityMapping{} } // Nat44AddDelIdentityMappingReply represents the VPP binary API message 'nat44_add_del_identity_mapping_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 944: +// Generated from 'nat.api.json', line 944: // // "nat44_add_del_identity_mapping_reply", // [ @@ -1699,18 +1716,18 @@ type Nat44AddDelIdentityMappingReply struct { func (*Nat44AddDelIdentityMappingReply) GetMessageName() string { return "nat44_add_del_identity_mapping_reply" } -func (*Nat44AddDelIdentityMappingReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat44AddDelIdentityMappingReply) GetCrcString() string { return "e8d4e804" } +func (*Nat44AddDelIdentityMappingReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat44AddDelIdentityMappingReply() api.Message { return &Nat44AddDelIdentityMappingReply{} } // Nat44IdentityMappingDump represents the VPP binary API message 'nat44_identity_mapping_dump'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 962: +// Generated from 'nat.api.json', line 962: // // "nat44_identity_mapping_dump", // [ @@ -1729,24 +1746,23 @@ func NewNat44AddDelIdentityMappingReply() api.Message { // "crc": "0x51077d14" // } // -type Nat44IdentityMappingDump struct { -} +type Nat44IdentityMappingDump struct{} func (*Nat44IdentityMappingDump) GetMessageName() string { return "nat44_identity_mapping_dump" } -func (*Nat44IdentityMappingDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat44IdentityMappingDump) GetCrcString() string { return "51077d14" } +func (*Nat44IdentityMappingDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat44IdentityMappingDump() api.Message { return &Nat44IdentityMappingDump{} } // Nat44IdentityMappingDetails represents the VPP binary API message 'nat44_identity_mapping_details'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 980: +// Generated from 'nat.api.json', line 980: // // "nat44_identity_mapping_details", // [ @@ -1804,18 +1820,18 @@ type Nat44IdentityMappingDetails struct { func (*Nat44IdentityMappingDetails) GetMessageName() string { return "nat44_identity_mapping_details" } -func (*Nat44IdentityMappingDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat44IdentityMappingDetails) GetCrcString() string { return "1f1d00d6" } +func (*Nat44IdentityMappingDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat44IdentityMappingDetails() api.Message { return &Nat44IdentityMappingDetails{} } // Nat44AddDelInterfaceAddr represents the VPP binary API message 'nat44_add_del_interface_addr'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1024: +// Generated from 'nat.api.json', line 1024: // // "nat44_add_del_interface_addr", // [ @@ -1855,18 +1871,18 @@ type Nat44AddDelInterfaceAddr struct { func (*Nat44AddDelInterfaceAddr) GetMessageName() string { return "nat44_add_del_interface_addr" } -func (*Nat44AddDelInterfaceAddr) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat44AddDelInterfaceAddr) GetCrcString() string { return "61105dfa" } +func (*Nat44AddDelInterfaceAddr) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat44AddDelInterfaceAddr() api.Message { return &Nat44AddDelInterfaceAddr{} } // Nat44AddDelInterfaceAddrReply represents the VPP binary API message 'nat44_add_del_interface_addr_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1054: +// Generated from 'nat.api.json', line 1054: // // "nat44_add_del_interface_addr_reply", // [ @@ -1892,18 +1908,18 @@ type Nat44AddDelInterfaceAddrReply struct { func (*Nat44AddDelInterfaceAddrReply) GetMessageName() string { return "nat44_add_del_interface_addr_reply" } -func (*Nat44AddDelInterfaceAddrReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat44AddDelInterfaceAddrReply) GetCrcString() string { return "e8d4e804" } +func (*Nat44AddDelInterfaceAddrReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat44AddDelInterfaceAddrReply() api.Message { return &Nat44AddDelInterfaceAddrReply{} } // Nat44InterfaceAddrDump represents the VPP binary API message 'nat44_interface_addr_dump'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1072: +// Generated from 'nat.api.json', line 1072: // // "nat44_interface_addr_dump", // [ @@ -1922,24 +1938,23 @@ func NewNat44AddDelInterfaceAddrReply() api.Message { // "crc": "0x51077d14" // } // -type Nat44InterfaceAddrDump struct { -} +type Nat44InterfaceAddrDump struct{} func (*Nat44InterfaceAddrDump) GetMessageName() string { return "nat44_interface_addr_dump" } -func (*Nat44InterfaceAddrDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat44InterfaceAddrDump) GetCrcString() string { return "51077d14" } +func (*Nat44InterfaceAddrDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat44InterfaceAddrDump() api.Message { return &Nat44InterfaceAddrDump{} } // Nat44InterfaceAddrDetails represents the VPP binary API message 'nat44_interface_addr_details'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1090: +// Generated from 'nat.api.json', line 1090: // // "nat44_interface_addr_details", // [ @@ -1970,18 +1985,18 @@ type Nat44InterfaceAddrDetails struct { func (*Nat44InterfaceAddrDetails) GetMessageName() string { return "nat44_interface_addr_details" } -func (*Nat44InterfaceAddrDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat44InterfaceAddrDetails) GetCrcString() string { return "4cdc575d" } +func (*Nat44InterfaceAddrDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat44InterfaceAddrDetails() api.Message { return &Nat44InterfaceAddrDetails{} } // Nat44UserDump represents the VPP binary API message 'nat44_user_dump'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1112: +// Generated from 'nat.api.json', line 1112: // // "nat44_user_dump", // [ @@ -2000,24 +2015,23 @@ func NewNat44InterfaceAddrDetails() api.Message { // "crc": "0x51077d14" // } // -type Nat44UserDump struct { -} +type Nat44UserDump struct{} func (*Nat44UserDump) GetMessageName() string { return "nat44_user_dump" } -func (*Nat44UserDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat44UserDump) GetCrcString() string { return "51077d14" } +func (*Nat44UserDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat44UserDump() api.Message { return &Nat44UserDump{} } // Nat44UserDetails represents the VPP binary API message 'nat44_user_details'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1130: +// Generated from 'nat.api.json', line 1130: // // "nat44_user_details", // [ @@ -2059,18 +2073,18 @@ type Nat44UserDetails struct { func (*Nat44UserDetails) GetMessageName() string { return "nat44_user_details" } -func (*Nat44UserDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat44UserDetails) GetCrcString() string { return "abb91460" } +func (*Nat44UserDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat44UserDetails() api.Message { return &Nat44UserDetails{} } // Nat44UserSessionDump represents the VPP binary API message 'nat44_user_session_dump'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1161: +// Generated from 'nat.api.json', line 1161: // // "nat44_user_session_dump", // [ @@ -2106,18 +2120,18 @@ type Nat44UserSessionDump struct { func (*Nat44UserSessionDump) GetMessageName() string { return "nat44_user_session_dump" } -func (*Nat44UserSessionDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat44UserSessionDump) GetCrcString() string { return "bca4d2c2" } +func (*Nat44UserSessionDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat44UserSessionDump() api.Message { return &Nat44UserSessionDump{} } // Nat44UserSessionDetails represents the VPP binary API message 'nat44_user_session_details'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1188: +// Generated from 'nat.api.json', line 1188: // // "nat44_user_session_details", // [ @@ -2217,18 +2231,18 @@ type Nat44UserSessionDetails struct { func (*Nat44UserSessionDetails) GetMessageName() string { return "nat44_user_session_details" } -func (*Nat44UserSessionDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat44UserSessionDetails) GetCrcString() string { return "2250ec64" } +func (*Nat44UserSessionDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat44UserSessionDetails() api.Message { return &Nat44UserSessionDetails{} } // Nat44AddDelLbStaticMapping represents the VPP binary API message 'nat44_add_del_lb_static_mapping'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1266: +// Generated from 'nat.api.json', line 1266: // // "nat44_add_del_lb_static_mapping", // [ @@ -2261,10 +2275,6 @@ func NewNat44UserSessionDetails() api.Message { // "protocol" // ], // [ -// "u32", -// "vrf_id" -// ], -// [ // "u8", // "twice_nat" // ], @@ -2292,7 +2302,7 @@ func NewNat44UserSessionDetails() api.Message { // "local_num" // ], // { -// "crc": "0xad5e6e06" +// "crc": "0x532bc14c" // } // type Nat44AddDelLbStaticMapping struct { @@ -2300,7 +2310,6 @@ type Nat44AddDelLbStaticMapping struct { ExternalAddr []byte `struc:"[4]byte"` ExternalPort uint16 Protocol uint8 - VrfID uint32 TwiceNat uint8 SelfTwiceNat uint8 Out2inOnly uint8 @@ -2312,18 +2321,18 @@ type Nat44AddDelLbStaticMapping struct { func (*Nat44AddDelLbStaticMapping) GetMessageName() string { return "nat44_add_del_lb_static_mapping" } +func (*Nat44AddDelLbStaticMapping) GetCrcString() string { + return "532bc14c" +} func (*Nat44AddDelLbStaticMapping) GetMessageType() api.MessageType { return api.RequestMessage } -func (*Nat44AddDelLbStaticMapping) GetCrcString() string { - return "ad5e6e06" -} func NewNat44AddDelLbStaticMapping() api.Message { return &Nat44AddDelLbStaticMapping{} } // Nat44AddDelLbStaticMappingReply represents the VPP binary API message 'nat44_add_del_lb_static_mapping_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1332: +// Generated from 'nat.api.json', line 1328: // // "nat44_add_del_lb_static_mapping_reply", // [ @@ -2349,18 +2358,18 @@ type Nat44AddDelLbStaticMappingReply struct { func (*Nat44AddDelLbStaticMappingReply) GetMessageName() string { return "nat44_add_del_lb_static_mapping_reply" } -func (*Nat44AddDelLbStaticMappingReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat44AddDelLbStaticMappingReply) GetCrcString() string { return "e8d4e804" } +func (*Nat44AddDelLbStaticMappingReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat44AddDelLbStaticMappingReply() api.Message { return &Nat44AddDelLbStaticMappingReply{} } // Nat44LbStaticMappingDump represents the VPP binary API message 'nat44_lb_static_mapping_dump'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1350: +// Generated from 'nat.api.json', line 1346: // // "nat44_lb_static_mapping_dump", // [ @@ -2379,24 +2388,23 @@ func NewNat44AddDelLbStaticMappingReply() api.Message { // "crc": "0x51077d14" // } // -type Nat44LbStaticMappingDump struct { -} +type Nat44LbStaticMappingDump struct{} func (*Nat44LbStaticMappingDump) GetMessageName() string { return "nat44_lb_static_mapping_dump" } -func (*Nat44LbStaticMappingDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat44LbStaticMappingDump) GetCrcString() string { return "51077d14" } +func (*Nat44LbStaticMappingDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat44LbStaticMappingDump() api.Message { return &Nat44LbStaticMappingDump{} } // Nat44LbStaticMappingDetails represents the VPP binary API message 'nat44_lb_static_mapping_details'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1368: +// Generated from 'nat.api.json', line 1364: // // "nat44_lb_static_mapping_details", // [ @@ -2421,10 +2429,6 @@ func NewNat44LbStaticMappingDump() api.Message { // "protocol" // ], // [ -// "u32", -// "vrf_id" -// ], -// [ // "u8", // "twice_nat" // ], @@ -2452,14 +2456,13 @@ func NewNat44LbStaticMappingDump() api.Message { // "local_num" // ], // { -// "crc": "0xc0e5e366" +// "crc": "0x6a287c74" // } // type Nat44LbStaticMappingDetails struct { ExternalAddr []byte `struc:"[4]byte"` ExternalPort uint16 Protocol uint8 - VrfID uint32 TwiceNat uint8 SelfTwiceNat uint8 Out2inOnly uint8 @@ -2471,18 +2474,18 @@ type Nat44LbStaticMappingDetails struct { func (*Nat44LbStaticMappingDetails) GetMessageName() string { return "nat44_lb_static_mapping_details" } +func (*Nat44LbStaticMappingDetails) GetCrcString() string { + return "6a287c74" +} func (*Nat44LbStaticMappingDetails) GetMessageType() api.MessageType { return api.ReplyMessage } -func (*Nat44LbStaticMappingDetails) GetCrcString() string { - return "c0e5e366" -} func NewNat44LbStaticMappingDetails() api.Message { return &Nat44LbStaticMappingDetails{} } // Nat44DelSession represents the VPP binary API message 'nat44_del_session'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1426: +// Generated from 'nat.api.json', line 1418: // // "nat44_del_session", // [ @@ -2549,18 +2552,18 @@ type Nat44DelSession struct { func (*Nat44DelSession) GetMessageName() string { return "nat44_del_session" } -func (*Nat44DelSession) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat44DelSession) GetCrcString() string { return "04154d0c" } +func (*Nat44DelSession) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat44DelSession() api.Message { return &Nat44DelSession{} } // Nat44DelSessionReply represents the VPP binary API message 'nat44_del_session_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1478: +// Generated from 'nat.api.json', line 1470: // // "nat44_del_session_reply", // [ @@ -2586,18 +2589,18 @@ type Nat44DelSessionReply struct { func (*Nat44DelSessionReply) GetMessageName() string { return "nat44_del_session_reply" } -func (*Nat44DelSessionReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat44DelSessionReply) GetCrcString() string { return "e8d4e804" } +func (*Nat44DelSessionReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat44DelSessionReply() api.Message { return &Nat44DelSessionReply{} } // Nat44ForwardingEnableDisable represents the VPP binary API message 'nat44_forwarding_enable_disable'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1496: +// Generated from 'nat.api.json', line 1488: // // "nat44_forwarding_enable_disable", // [ @@ -2627,18 +2630,18 @@ type Nat44ForwardingEnableDisable struct { func (*Nat44ForwardingEnableDisable) GetMessageName() string { return "nat44_forwarding_enable_disable" } -func (*Nat44ForwardingEnableDisable) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat44ForwardingEnableDisable) GetCrcString() string { return "8050327d" } +func (*Nat44ForwardingEnableDisable) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat44ForwardingEnableDisable() api.Message { return &Nat44ForwardingEnableDisable{} } // Nat44ForwardingEnableDisableReply represents the VPP binary API message 'nat44_forwarding_enable_disable_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1518: +// Generated from 'nat.api.json', line 1510: // // "nat44_forwarding_enable_disable_reply", // [ @@ -2664,18 +2667,18 @@ type Nat44ForwardingEnableDisableReply struct { func (*Nat44ForwardingEnableDisableReply) GetMessageName() string { return "nat44_forwarding_enable_disable_reply" } -func (*Nat44ForwardingEnableDisableReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat44ForwardingEnableDisableReply) GetCrcString() string { return "e8d4e804" } +func (*Nat44ForwardingEnableDisableReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat44ForwardingEnableDisableReply() api.Message { return &Nat44ForwardingEnableDisableReply{} } // Nat44ForwardingIsEnabled represents the VPP binary API message 'nat44_forwarding_is_enabled'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1536: +// Generated from 'nat.api.json', line 1528: // // "nat44_forwarding_is_enabled", // [ @@ -2694,24 +2697,23 @@ func NewNat44ForwardingEnableDisableReply() api.Message { // "crc": "0x51077d14" // } // -type Nat44ForwardingIsEnabled struct { -} +type Nat44ForwardingIsEnabled struct{} func (*Nat44ForwardingIsEnabled) GetMessageName() string { return "nat44_forwarding_is_enabled" } -func (*Nat44ForwardingIsEnabled) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat44ForwardingIsEnabled) GetCrcString() string { return "51077d14" } +func (*Nat44ForwardingIsEnabled) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat44ForwardingIsEnabled() api.Message { return &Nat44ForwardingIsEnabled{} } // Nat44ForwardingIsEnabledReply represents the VPP binary API message 'nat44_forwarding_is_enabled_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1554: +// Generated from 'nat.api.json', line 1546: // // "nat44_forwarding_is_enabled_reply", // [ @@ -2737,18 +2739,18 @@ type Nat44ForwardingIsEnabledReply struct { func (*Nat44ForwardingIsEnabledReply) GetMessageName() string { return "nat44_forwarding_is_enabled_reply" } -func (*Nat44ForwardingIsEnabledReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat44ForwardingIsEnabledReply) GetCrcString() string { return "9c4a7828" } +func (*Nat44ForwardingIsEnabledReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat44ForwardingIsEnabledReply() api.Message { return &Nat44ForwardingIsEnabledReply{} } // NatDetAddDelMap represents the VPP binary API message 'nat_det_add_del_map'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1572: +// Generated from 'nat.api.json', line 1564: // // "nat_det_add_del_map", // [ @@ -2810,18 +2812,18 @@ type NatDetAddDelMap struct { func (*NatDetAddDelMap) GetMessageName() string { return "nat_det_add_del_map" } -func (*NatDetAddDelMap) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*NatDetAddDelMap) GetCrcString() string { return "5bd37d5b" } +func (*NatDetAddDelMap) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNatDetAddDelMap() api.Message { return &NatDetAddDelMap{} } // NatDetAddDelMapReply represents the VPP binary API message 'nat_det_add_del_map_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1620: +// Generated from 'nat.api.json', line 1612: // // "nat_det_add_del_map_reply", // [ @@ -2847,18 +2849,18 @@ type NatDetAddDelMapReply struct { func (*NatDetAddDelMapReply) GetMessageName() string { return "nat_det_add_del_map_reply" } -func (*NatDetAddDelMapReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*NatDetAddDelMapReply) GetCrcString() string { return "e8d4e804" } +func (*NatDetAddDelMapReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNatDetAddDelMapReply() api.Message { return &NatDetAddDelMapReply{} } // NatDetForward represents the VPP binary API message 'nat_det_forward'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1638: +// Generated from 'nat.api.json', line 1630: // // "nat_det_forward", // [ @@ -2894,18 +2896,18 @@ type NatDetForward struct { func (*NatDetForward) GetMessageName() string { return "nat_det_forward" } -func (*NatDetForward) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*NatDetForward) GetCrcString() string { return "037d399b" } +func (*NatDetForward) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNatDetForward() api.Message { return &NatDetForward{} } // NatDetForwardReply represents the VPP binary API message 'nat_det_forward_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1665: +// Generated from 'nat.api.json', line 1657: // // "nat_det_forward_reply", // [ @@ -2947,18 +2949,18 @@ type NatDetForwardReply struct { func (*NatDetForwardReply) GetMessageName() string { return "nat_det_forward_reply" } -func (*NatDetForwardReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*NatDetForwardReply) GetCrcString() string { return "bf9b96ea" } +func (*NatDetForwardReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNatDetForwardReply() api.Message { return &NatDetForwardReply{} } // NatDetReverse represents the VPP binary API message 'nat_det_reverse'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1696: +// Generated from 'nat.api.json', line 1688: // // "nat_det_reverse", // [ @@ -2994,18 +2996,18 @@ type NatDetReverse struct { func (*NatDetReverse) GetMessageName() string { return "nat_det_reverse" } -func (*NatDetReverse) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*NatDetReverse) GetCrcString() string { return "80ab12d2" } +func (*NatDetReverse) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNatDetReverse() api.Message { return &NatDetReverse{} } // NatDetReverseReply represents the VPP binary API message 'nat_det_reverse_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1723: +// Generated from 'nat.api.json', line 1715: // // "nat_det_reverse_reply", // [ @@ -3042,18 +3044,18 @@ type NatDetReverseReply struct { func (*NatDetReverseReply) GetMessageName() string { return "nat_det_reverse_reply" } -func (*NatDetReverseReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*NatDetReverseReply) GetCrcString() string { return "26139a2f" } +func (*NatDetReverseReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNatDetReverseReply() api.Message { return &NatDetReverseReply{} } // NatDetMapDump represents the VPP binary API message 'nat_det_map_dump'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1750: +// Generated from 'nat.api.json', line 1742: // // "nat_det_map_dump", // [ @@ -3072,24 +3074,23 @@ func NewNatDetReverseReply() api.Message { // "crc": "0x51077d14" // } // -type NatDetMapDump struct { -} +type NatDetMapDump struct{} func (*NatDetMapDump) GetMessageName() string { return "nat_det_map_dump" } -func (*NatDetMapDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*NatDetMapDump) GetCrcString() string { return "51077d14" } +func (*NatDetMapDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNatDetMapDump() api.Message { return &NatDetMapDump{} } // NatDetMapDetails represents the VPP binary API message 'nat_det_map_details'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1768: +// Generated from 'nat.api.json', line 1760: // // "nat_det_map_details", // [ @@ -3152,18 +3153,18 @@ type NatDetMapDetails struct { func (*NatDetMapDetails) GetMessageName() string { return "nat_det_map_details" } -func (*NatDetMapDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*NatDetMapDetails) GetCrcString() string { return "886138a8" } +func (*NatDetMapDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNatDetMapDetails() api.Message { return &NatDetMapDetails{} } // NatDetSetTimeouts represents the VPP binary API message 'nat_det_set_timeouts'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1816: +// Generated from 'nat.api.json', line 1808: // // "nat_det_set_timeouts", // [ @@ -3208,18 +3209,18 @@ type NatDetSetTimeouts struct { func (*NatDetSetTimeouts) GetMessageName() string { return "nat_det_set_timeouts" } -func (*NatDetSetTimeouts) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*NatDetSetTimeouts) GetCrcString() string { return "d4746b16" } +func (*NatDetSetTimeouts) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNatDetSetTimeouts() api.Message { return &NatDetSetTimeouts{} } // NatDetSetTimeoutsReply represents the VPP binary API message 'nat_det_set_timeouts_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1850: +// Generated from 'nat.api.json', line 1842: // // "nat_det_set_timeouts_reply", // [ @@ -3245,18 +3246,18 @@ type NatDetSetTimeoutsReply struct { func (*NatDetSetTimeoutsReply) GetMessageName() string { return "nat_det_set_timeouts_reply" } -func (*NatDetSetTimeoutsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*NatDetSetTimeoutsReply) GetCrcString() string { return "e8d4e804" } +func (*NatDetSetTimeoutsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNatDetSetTimeoutsReply() api.Message { return &NatDetSetTimeoutsReply{} } // NatDetGetTimeouts represents the VPP binary API message 'nat_det_get_timeouts'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1868: +// Generated from 'nat.api.json', line 1860: // // "nat_det_get_timeouts", // [ @@ -3275,24 +3276,23 @@ func NewNatDetSetTimeoutsReply() api.Message { // "crc": "0x51077d14" // } // -type NatDetGetTimeouts struct { -} +type NatDetGetTimeouts struct{} func (*NatDetGetTimeouts) GetMessageName() string { return "nat_det_get_timeouts" } -func (*NatDetGetTimeouts) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*NatDetGetTimeouts) GetCrcString() string { return "51077d14" } +func (*NatDetGetTimeouts) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNatDetGetTimeouts() api.Message { return &NatDetGetTimeouts{} } // NatDetGetTimeoutsReply represents the VPP binary API message 'nat_det_get_timeouts_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1886: +// Generated from 'nat.api.json', line 1878: // // "nat_det_get_timeouts_reply", // [ @@ -3338,18 +3338,18 @@ type NatDetGetTimeoutsReply struct { func (*NatDetGetTimeoutsReply) GetMessageName() string { return "nat_det_get_timeouts_reply" } -func (*NatDetGetTimeoutsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*NatDetGetTimeoutsReply) GetCrcString() string { return "3c4df4e1" } +func (*NatDetGetTimeoutsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNatDetGetTimeoutsReply() api.Message { return &NatDetGetTimeoutsReply{} } // NatDetCloseSessionOut represents the VPP binary API message 'nat_det_close_session_out'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1920: +// Generated from 'nat.api.json', line 1912: // // "nat_det_close_session_out", // [ @@ -3396,18 +3396,18 @@ type NatDetCloseSessionOut struct { func (*NatDetCloseSessionOut) GetMessageName() string { return "nat_det_close_session_out" } -func (*NatDetCloseSessionOut) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*NatDetCloseSessionOut) GetCrcString() string { return "2e165938" } +func (*NatDetCloseSessionOut) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNatDetCloseSessionOut() api.Message { return &NatDetCloseSessionOut{} } // NatDetCloseSessionOutReply represents the VPP binary API message 'nat_det_close_session_out_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1956: +// Generated from 'nat.api.json', line 1948: // // "nat_det_close_session_out_reply", // [ @@ -3433,18 +3433,18 @@ type NatDetCloseSessionOutReply struct { func (*NatDetCloseSessionOutReply) GetMessageName() string { return "nat_det_close_session_out_reply" } -func (*NatDetCloseSessionOutReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*NatDetCloseSessionOutReply) GetCrcString() string { return "e8d4e804" } +func (*NatDetCloseSessionOutReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNatDetCloseSessionOutReply() api.Message { return &NatDetCloseSessionOutReply{} } // NatDetCloseSessionIn represents the VPP binary API message 'nat_det_close_session_in'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 1974: +// Generated from 'nat.api.json', line 1966: // // "nat_det_close_session_in", // [ @@ -3496,18 +3496,18 @@ type NatDetCloseSessionIn struct { func (*NatDetCloseSessionIn) GetMessageName() string { return "nat_det_close_session_in" } -func (*NatDetCloseSessionIn) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*NatDetCloseSessionIn) GetCrcString() string { return "147e430c" } +func (*NatDetCloseSessionIn) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNatDetCloseSessionIn() api.Message { return &NatDetCloseSessionIn{} } // NatDetCloseSessionInReply represents the VPP binary API message 'nat_det_close_session_in_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2014: +// Generated from 'nat.api.json', line 2006: // // "nat_det_close_session_in_reply", // [ @@ -3533,18 +3533,18 @@ type NatDetCloseSessionInReply struct { func (*NatDetCloseSessionInReply) GetMessageName() string { return "nat_det_close_session_in_reply" } -func (*NatDetCloseSessionInReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*NatDetCloseSessionInReply) GetCrcString() string { return "e8d4e804" } +func (*NatDetCloseSessionInReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNatDetCloseSessionInReply() api.Message { return &NatDetCloseSessionInReply{} } // NatDetSessionDump represents the VPP binary API message 'nat_det_session_dump'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2032: +// Generated from 'nat.api.json', line 2024: // // "nat_det_session_dump", // [ @@ -3580,18 +3580,18 @@ type NatDetSessionDump struct { func (*NatDetSessionDump) GetMessageName() string { return "nat_det_session_dump" } -func (*NatDetSessionDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*NatDetSessionDump) GetCrcString() string { return "ddfb6b28" } +func (*NatDetSessionDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNatDetSessionDump() api.Message { return &NatDetSessionDump{} } // NatDetSessionDetails represents the VPP binary API message 'nat_det_session_details'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2059: +// Generated from 'nat.api.json', line 2051: // // "nat_det_session_details", // [ @@ -3647,18 +3647,18 @@ type NatDetSessionDetails struct { func (*NatDetSessionDetails) GetMessageName() string { return "nat_det_session_details" } -func (*NatDetSessionDetails) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*NatDetSessionDetails) GetCrcString() string { return "699b5164" } +func (*NatDetSessionDetails) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNatDetSessionDetails() api.Message { return &NatDetSessionDetails{} } // Nat64AddDelPoolAddrRange represents the VPP binary API message 'nat64_add_del_pool_addr_range'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2102: +// Generated from 'nat.api.json', line 2094: // // "nat64_add_del_pool_addr_range", // [ @@ -3705,18 +3705,18 @@ type Nat64AddDelPoolAddrRange struct { func (*Nat64AddDelPoolAddrRange) GetMessageName() string { return "nat64_add_del_pool_addr_range" } -func (*Nat64AddDelPoolAddrRange) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat64AddDelPoolAddrRange) GetCrcString() string { return "5eb50214" } +func (*Nat64AddDelPoolAddrRange) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat64AddDelPoolAddrRange() api.Message { return &Nat64AddDelPoolAddrRange{} } // Nat64AddDelPoolAddrRangeReply represents the VPP binary API message 'nat64_add_del_pool_addr_range_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2138: +// Generated from 'nat.api.json', line 2130: // // "nat64_add_del_pool_addr_range_reply", // [ @@ -3742,18 +3742,18 @@ type Nat64AddDelPoolAddrRangeReply struct { func (*Nat64AddDelPoolAddrRangeReply) GetMessageName() string { return "nat64_add_del_pool_addr_range_reply" } -func (*Nat64AddDelPoolAddrRangeReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat64AddDelPoolAddrRangeReply) GetCrcString() string { return "e8d4e804" } +func (*Nat64AddDelPoolAddrRangeReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat64AddDelPoolAddrRangeReply() api.Message { return &Nat64AddDelPoolAddrRangeReply{} } // Nat64PoolAddrDump represents the VPP binary API message 'nat64_pool_addr_dump'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2156: +// Generated from 'nat.api.json', line 2148: // // "nat64_pool_addr_dump", // [ @@ -3772,24 +3772,23 @@ func NewNat64AddDelPoolAddrRangeReply() api.Message { // "crc": "0x51077d14" // } // -type Nat64PoolAddrDump struct { -} +type Nat64PoolAddrDump struct{} func (*Nat64PoolAddrDump) GetMessageName() string { return "nat64_pool_addr_dump" } -func (*Nat64PoolAddrDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat64PoolAddrDump) GetCrcString() string { return "51077d14" } +func (*Nat64PoolAddrDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat64PoolAddrDump() api.Message { return &Nat64PoolAddrDump{} } // Nat64PoolAddrDetails represents the VPP binary API message 'nat64_pool_addr_details'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2174: +// Generated from 'nat.api.json', line 2166: // // "nat64_pool_addr_details", // [ @@ -3821,18 +3820,18 @@ type Nat64PoolAddrDetails struct { func (*Nat64PoolAddrDetails) GetMessageName() string { return "nat64_pool_addr_details" } -func (*Nat64PoolAddrDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat64PoolAddrDetails) GetCrcString() string { return "8d10231c" } +func (*Nat64PoolAddrDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat64PoolAddrDetails() api.Message { return &Nat64PoolAddrDetails{} } // Nat64AddDelInterface represents the VPP binary API message 'nat64_add_del_interface'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2197: +// Generated from 'nat.api.json', line 2189: // // "nat64_add_del_interface", // [ @@ -3872,18 +3871,18 @@ type Nat64AddDelInterface struct { func (*Nat64AddDelInterface) GetMessageName() string { return "nat64_add_del_interface" } -func (*Nat64AddDelInterface) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat64AddDelInterface) GetCrcString() string { return "efbda9ce" } +func (*Nat64AddDelInterface) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat64AddDelInterface() api.Message { return &Nat64AddDelInterface{} } // Nat64AddDelInterfaceReply represents the VPP binary API message 'nat64_add_del_interface_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2227: +// Generated from 'nat.api.json', line 2219: // // "nat64_add_del_interface_reply", // [ @@ -3909,18 +3908,18 @@ type Nat64AddDelInterfaceReply struct { func (*Nat64AddDelInterfaceReply) GetMessageName() string { return "nat64_add_del_interface_reply" } -func (*Nat64AddDelInterfaceReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat64AddDelInterfaceReply) GetCrcString() string { return "e8d4e804" } +func (*Nat64AddDelInterfaceReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat64AddDelInterfaceReply() api.Message { return &Nat64AddDelInterfaceReply{} } // Nat64InterfaceDump represents the VPP binary API message 'nat64_interface_dump'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2245: +// Generated from 'nat.api.json', line 2237: // // "nat64_interface_dump", // [ @@ -3939,24 +3938,23 @@ func NewNat64AddDelInterfaceReply() api.Message { // "crc": "0x51077d14" // } // -type Nat64InterfaceDump struct { -} +type Nat64InterfaceDump struct{} func (*Nat64InterfaceDump) GetMessageName() string { return "nat64_interface_dump" } -func (*Nat64InterfaceDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat64InterfaceDump) GetCrcString() string { return "51077d14" } +func (*Nat64InterfaceDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat64InterfaceDump() api.Message { return &Nat64InterfaceDump{} } // Nat64InterfaceDetails represents the VPP binary API message 'nat64_interface_details'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2263: +// Generated from 'nat.api.json', line 2255: // // "nat64_interface_details", // [ @@ -3987,18 +3985,18 @@ type Nat64InterfaceDetails struct { func (*Nat64InterfaceDetails) GetMessageName() string { return "nat64_interface_details" } -func (*Nat64InterfaceDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat64InterfaceDetails) GetCrcString() string { return "2b15e8e4" } +func (*Nat64InterfaceDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat64InterfaceDetails() api.Message { return &Nat64InterfaceDetails{} } // Nat64AddDelStaticBib represents the VPP binary API message 'nat64_add_del_static_bib'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2285: +// Generated from 'nat.api.json', line 2277: // // "nat64_add_del_static_bib", // [ @@ -4060,18 +4058,18 @@ type Nat64AddDelStaticBib struct { func (*Nat64AddDelStaticBib) GetMessageName() string { return "nat64_add_del_static_bib" } -func (*Nat64AddDelStaticBib) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat64AddDelStaticBib) GetCrcString() string { return "e36c7813" } +func (*Nat64AddDelStaticBib) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat64AddDelStaticBib() api.Message { return &Nat64AddDelStaticBib{} } // Nat64AddDelStaticBibReply represents the VPP binary API message 'nat64_add_del_static_bib_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2333: +// Generated from 'nat.api.json', line 2325: // // "nat64_add_del_static_bib_reply", // [ @@ -4097,18 +4095,18 @@ type Nat64AddDelStaticBibReply struct { func (*Nat64AddDelStaticBibReply) GetMessageName() string { return "nat64_add_del_static_bib_reply" } -func (*Nat64AddDelStaticBibReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat64AddDelStaticBibReply) GetCrcString() string { return "e8d4e804" } +func (*Nat64AddDelStaticBibReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat64AddDelStaticBibReply() api.Message { return &Nat64AddDelStaticBibReply{} } // Nat64BibDump represents the VPP binary API message 'nat64_bib_dump'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2351: +// Generated from 'nat.api.json', line 2343: // // "nat64_bib_dump", // [ @@ -4138,18 +4136,18 @@ type Nat64BibDump struct { func (*Nat64BibDump) GetMessageName() string { return "nat64_bib_dump" } -func (*Nat64BibDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat64BibDump) GetCrcString() string { return "cfcb6b75" } +func (*Nat64BibDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat64BibDump() api.Message { return &Nat64BibDump{} } // Nat64BibDetails represents the VPP binary API message 'nat64_bib_details'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2373: +// Generated from 'nat.api.json', line 2365: // // "nat64_bib_details", // [ @@ -4212,18 +4210,18 @@ type Nat64BibDetails struct { func (*Nat64BibDetails) GetMessageName() string { return "nat64_bib_details" } -func (*Nat64BibDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat64BibDetails) GetCrcString() string { return "372e7a98" } +func (*Nat64BibDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat64BibDetails() api.Message { return &Nat64BibDetails{} } // Nat64SetTimeouts represents the VPP binary API message 'nat64_set_timeouts'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2421: +// Generated from 'nat.api.json', line 2413: // // "nat64_set_timeouts", // [ @@ -4273,18 +4271,18 @@ type Nat64SetTimeouts struct { func (*Nat64SetTimeouts) GetMessageName() string { return "nat64_set_timeouts" } -func (*Nat64SetTimeouts) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat64SetTimeouts) GetCrcString() string { return "1cc51cf1" } +func (*Nat64SetTimeouts) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat64SetTimeouts() api.Message { return &Nat64SetTimeouts{} } // Nat64SetTimeoutsReply represents the VPP binary API message 'nat64_set_timeouts_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2459: +// Generated from 'nat.api.json', line 2451: // // "nat64_set_timeouts_reply", // [ @@ -4310,18 +4308,18 @@ type Nat64SetTimeoutsReply struct { func (*Nat64SetTimeoutsReply) GetMessageName() string { return "nat64_set_timeouts_reply" } -func (*Nat64SetTimeoutsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat64SetTimeoutsReply) GetCrcString() string { return "e8d4e804" } +func (*Nat64SetTimeoutsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat64SetTimeoutsReply() api.Message { return &Nat64SetTimeoutsReply{} } // Nat64GetTimeouts represents the VPP binary API message 'nat64_get_timeouts'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2477: +// Generated from 'nat.api.json', line 2469: // // "nat64_get_timeouts", // [ @@ -4340,24 +4338,23 @@ func NewNat64SetTimeoutsReply() api.Message { // "crc": "0x51077d14" // } // -type Nat64GetTimeouts struct { -} +type Nat64GetTimeouts struct{} func (*Nat64GetTimeouts) GetMessageName() string { return "nat64_get_timeouts" } -func (*Nat64GetTimeouts) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat64GetTimeouts) GetCrcString() string { return "51077d14" } +func (*Nat64GetTimeouts) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat64GetTimeouts() api.Message { return &Nat64GetTimeouts{} } // Nat64GetTimeoutsReply represents the VPP binary API message 'nat64_get_timeouts_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2495: +// Generated from 'nat.api.json', line 2487: // // "nat64_get_timeouts_reply", // [ @@ -4408,18 +4405,18 @@ type Nat64GetTimeoutsReply struct { func (*Nat64GetTimeoutsReply) GetMessageName() string { return "nat64_get_timeouts_reply" } -func (*Nat64GetTimeoutsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat64GetTimeoutsReply) GetCrcString() string { return "cdd081d0" } +func (*Nat64GetTimeoutsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat64GetTimeoutsReply() api.Message { return &Nat64GetTimeoutsReply{} } // Nat64StDump represents the VPP binary API message 'nat64_st_dump'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2533: +// Generated from 'nat.api.json', line 2525: // // "nat64_st_dump", // [ @@ -4449,18 +4446,18 @@ type Nat64StDump struct { func (*Nat64StDump) GetMessageName() string { return "nat64_st_dump" } -func (*Nat64StDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat64StDump) GetCrcString() string { return "cfcb6b75" } +func (*Nat64StDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat64StDump() api.Message { return &Nat64StDump{} } // Nat64StDetails represents the VPP binary API message 'nat64_st_details'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2555: +// Generated from 'nat.api.json', line 2547: // // "nat64_st_details", // [ @@ -4530,18 +4527,18 @@ type Nat64StDetails struct { func (*Nat64StDetails) GetMessageName() string { return "nat64_st_details" } -func (*Nat64StDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat64StDetails) GetCrcString() string { return "1aaf4631" } +func (*Nat64StDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat64StDetails() api.Message { return &Nat64StDetails{} } // Nat64AddDelPrefix represents the VPP binary API message 'nat64_add_del_prefix'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2609: +// Generated from 'nat.api.json', line 2601: // // "nat64_add_del_prefix", // [ @@ -4587,18 +4584,18 @@ type Nat64AddDelPrefix struct { func (*Nat64AddDelPrefix) GetMessageName() string { return "nat64_add_del_prefix" } -func (*Nat64AddDelPrefix) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat64AddDelPrefix) GetCrcString() string { return "f4ae7173" } +func (*Nat64AddDelPrefix) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat64AddDelPrefix() api.Message { return &Nat64AddDelPrefix{} } // Nat64AddDelPrefixReply represents the VPP binary API message 'nat64_add_del_prefix_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2644: +// Generated from 'nat.api.json', line 2636: // // "nat64_add_del_prefix_reply", // [ @@ -4624,18 +4621,18 @@ type Nat64AddDelPrefixReply struct { func (*Nat64AddDelPrefixReply) GetMessageName() string { return "nat64_add_del_prefix_reply" } -func (*Nat64AddDelPrefixReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat64AddDelPrefixReply) GetCrcString() string { return "e8d4e804" } +func (*Nat64AddDelPrefixReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat64AddDelPrefixReply() api.Message { return &Nat64AddDelPrefixReply{} } // Nat64PrefixDump represents the VPP binary API message 'nat64_prefix_dump'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2662: +// Generated from 'nat.api.json', line 2654: // // "nat64_prefix_dump", // [ @@ -4654,24 +4651,23 @@ func NewNat64AddDelPrefixReply() api.Message { // "crc": "0x51077d14" // } // -type Nat64PrefixDump struct { -} +type Nat64PrefixDump struct{} func (*Nat64PrefixDump) GetMessageName() string { return "nat64_prefix_dump" } -func (*Nat64PrefixDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat64PrefixDump) GetCrcString() string { return "51077d14" } +func (*Nat64PrefixDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat64PrefixDump() api.Message { return &Nat64PrefixDump{} } // Nat64PrefixDetails represents the VPP binary API message 'nat64_prefix_details'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2680: +// Generated from 'nat.api.json', line 2672: // // "nat64_prefix_details", // [ @@ -4708,18 +4704,18 @@ type Nat64PrefixDetails struct { func (*Nat64PrefixDetails) GetMessageName() string { return "nat64_prefix_details" } -func (*Nat64PrefixDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat64PrefixDetails) GetCrcString() string { return "fb08875c" } +func (*Nat64PrefixDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat64PrefixDetails() api.Message { return &Nat64PrefixDetails{} } // Nat64AddDelInterfaceAddr represents the VPP binary API message 'nat64_add_del_interface_addr'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2707: +// Generated from 'nat.api.json', line 2699: // // "nat64_add_del_interface_addr", // [ @@ -4759,18 +4755,18 @@ type Nat64AddDelInterfaceAddr struct { func (*Nat64AddDelInterfaceAddr) GetMessageName() string { return "nat64_add_del_interface_addr" } -func (*Nat64AddDelInterfaceAddr) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat64AddDelInterfaceAddr) GetCrcString() string { return "9b1ac600" } +func (*Nat64AddDelInterfaceAddr) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat64AddDelInterfaceAddr() api.Message { return &Nat64AddDelInterfaceAddr{} } // Nat64AddDelInterfaceAddrReply represents the VPP binary API message 'nat64_add_del_interface_addr_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2737: +// Generated from 'nat.api.json', line 2729: // // "nat64_add_del_interface_addr_reply", // [ @@ -4796,18 +4792,18 @@ type Nat64AddDelInterfaceAddrReply struct { func (*Nat64AddDelInterfaceAddrReply) GetMessageName() string { return "nat64_add_del_interface_addr_reply" } -func (*Nat64AddDelInterfaceAddrReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat64AddDelInterfaceAddrReply) GetCrcString() string { return "e8d4e804" } +func (*Nat64AddDelInterfaceAddrReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat64AddDelInterfaceAddrReply() api.Message { return &Nat64AddDelInterfaceAddrReply{} } // DsliteAddDelPoolAddrRange represents the VPP binary API message 'dslite_add_del_pool_addr_range'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2755: +// Generated from 'nat.api.json', line 2747: // // "dslite_add_del_pool_addr_range", // [ @@ -4849,18 +4845,18 @@ type DsliteAddDelPoolAddrRange struct { func (*DsliteAddDelPoolAddrRange) GetMessageName() string { return "dslite_add_del_pool_addr_range" } -func (*DsliteAddDelPoolAddrRange) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*DsliteAddDelPoolAddrRange) GetCrcString() string { return "258bff2a" } +func (*DsliteAddDelPoolAddrRange) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewDsliteAddDelPoolAddrRange() api.Message { return &DsliteAddDelPoolAddrRange{} } // DsliteAddDelPoolAddrRangeReply represents the VPP binary API message 'dslite_add_del_pool_addr_range_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2787: +// Generated from 'nat.api.json', line 2779: // // "dslite_add_del_pool_addr_range_reply", // [ @@ -4886,18 +4882,18 @@ type DsliteAddDelPoolAddrRangeReply struct { func (*DsliteAddDelPoolAddrRangeReply) GetMessageName() string { return "dslite_add_del_pool_addr_range_reply" } -func (*DsliteAddDelPoolAddrRangeReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*DsliteAddDelPoolAddrRangeReply) GetCrcString() string { return "e8d4e804" } +func (*DsliteAddDelPoolAddrRangeReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewDsliteAddDelPoolAddrRangeReply() api.Message { return &DsliteAddDelPoolAddrRangeReply{} } // DsliteAddressDump represents the VPP binary API message 'dslite_address_dump'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2805: +// Generated from 'nat.api.json', line 2797: // // "dslite_address_dump", // [ @@ -4916,24 +4912,23 @@ func NewDsliteAddDelPoolAddrRangeReply() api.Message { // "crc": "0x51077d14" // } // -type DsliteAddressDump struct { -} +type DsliteAddressDump struct{} func (*DsliteAddressDump) GetMessageName() string { return "dslite_address_dump" } -func (*DsliteAddressDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*DsliteAddressDump) GetCrcString() string { return "51077d14" } +func (*DsliteAddressDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewDsliteAddressDump() api.Message { return &DsliteAddressDump{} } // DsliteAddressDetails represents the VPP binary API message 'dslite_address_details'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2823: +// Generated from 'nat.api.json', line 2815: // // "dslite_address_details", // [ @@ -4960,18 +4955,18 @@ type DsliteAddressDetails struct { func (*DsliteAddressDetails) GetMessageName() string { return "dslite_address_details" } -func (*DsliteAddressDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*DsliteAddressDetails) GetCrcString() string { return "ade70e23" } +func (*DsliteAddressDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewDsliteAddressDetails() api.Message { return &DsliteAddressDetails{} } // DsliteSetAftrAddr represents the VPP binary API message 'dslite_set_aftr_addr'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2842: +// Generated from 'nat.api.json', line 2834: // // "dslite_set_aftr_addr", // [ @@ -5008,18 +5003,18 @@ type DsliteSetAftrAddr struct { func (*DsliteSetAftrAddr) GetMessageName() string { return "dslite_set_aftr_addr" } -func (*DsliteSetAftrAddr) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*DsliteSetAftrAddr) GetCrcString() string { return "2e9c01ef" } +func (*DsliteSetAftrAddr) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewDsliteSetAftrAddr() api.Message { return &DsliteSetAftrAddr{} } // DsliteSetAftrAddrReply represents the VPP binary API message 'dslite_set_aftr_addr_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2870: +// Generated from 'nat.api.json', line 2862: // // "dslite_set_aftr_addr_reply", // [ @@ -5045,18 +5040,18 @@ type DsliteSetAftrAddrReply struct { func (*DsliteSetAftrAddrReply) GetMessageName() string { return "dslite_set_aftr_addr_reply" } -func (*DsliteSetAftrAddrReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*DsliteSetAftrAddrReply) GetCrcString() string { return "e8d4e804" } +func (*DsliteSetAftrAddrReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewDsliteSetAftrAddrReply() api.Message { return &DsliteSetAftrAddrReply{} } // DsliteGetAftrAddr represents the VPP binary API message 'dslite_get_aftr_addr'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2888: +// Generated from 'nat.api.json', line 2880: // // "dslite_get_aftr_addr", // [ @@ -5075,24 +5070,23 @@ func NewDsliteSetAftrAddrReply() api.Message { // "crc": "0x51077d14" // } // -type DsliteGetAftrAddr struct { -} +type DsliteGetAftrAddr struct{} func (*DsliteGetAftrAddr) GetMessageName() string { return "dslite_get_aftr_addr" } -func (*DsliteGetAftrAddr) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*DsliteGetAftrAddr) GetCrcString() string { return "51077d14" } +func (*DsliteGetAftrAddr) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewDsliteGetAftrAddr() api.Message { return &DsliteGetAftrAddr{} } // DsliteGetAftrAddrReply represents the VPP binary API message 'dslite_get_aftr_addr_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2906: +// Generated from 'nat.api.json', line 2898: // // "dslite_get_aftr_addr_reply", // [ @@ -5130,18 +5124,18 @@ type DsliteGetAftrAddrReply struct { func (*DsliteGetAftrAddrReply) GetMessageName() string { return "dslite_get_aftr_addr_reply" } -func (*DsliteGetAftrAddrReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*DsliteGetAftrAddrReply) GetCrcString() string { return "2c4c3037" } +func (*DsliteGetAftrAddrReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewDsliteGetAftrAddrReply() api.Message { return &DsliteGetAftrAddrReply{} } // DsliteSetB4Addr represents the VPP binary API message 'dslite_set_b4_addr'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2934: +// Generated from 'nat.api.json', line 2926: // // "dslite_set_b4_addr", // [ @@ -5178,18 +5172,18 @@ type DsliteSetB4Addr struct { func (*DsliteSetB4Addr) GetMessageName() string { return "dslite_set_b4_addr" } -func (*DsliteSetB4Addr) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*DsliteSetB4Addr) GetCrcString() string { return "2e9c01ef" } +func (*DsliteSetB4Addr) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewDsliteSetB4Addr() api.Message { return &DsliteSetB4Addr{} } // DsliteSetB4AddrReply represents the VPP binary API message 'dslite_set_b4_addr_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2962: +// Generated from 'nat.api.json', line 2954: // // "dslite_set_b4_addr_reply", // [ @@ -5215,18 +5209,18 @@ type DsliteSetB4AddrReply struct { func (*DsliteSetB4AddrReply) GetMessageName() string { return "dslite_set_b4_addr_reply" } -func (*DsliteSetB4AddrReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*DsliteSetB4AddrReply) GetCrcString() string { return "e8d4e804" } +func (*DsliteSetB4AddrReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewDsliteSetB4AddrReply() api.Message { return &DsliteSetB4AddrReply{} } // DsliteGetB4Addr represents the VPP binary API message 'dslite_get_b4_addr'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2980: +// Generated from 'nat.api.json', line 2972: // // "dslite_get_b4_addr", // [ @@ -5245,24 +5239,23 @@ func NewDsliteSetB4AddrReply() api.Message { // "crc": "0x51077d14" // } // -type DsliteGetB4Addr struct { -} +type DsliteGetB4Addr struct{} func (*DsliteGetB4Addr) GetMessageName() string { return "dslite_get_b4_addr" } -func (*DsliteGetB4Addr) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*DsliteGetB4Addr) GetCrcString() string { return "51077d14" } +func (*DsliteGetB4Addr) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewDsliteGetB4Addr() api.Message { return &DsliteGetB4Addr{} } // DsliteGetB4AddrReply represents the VPP binary API message 'dslite_get_b4_addr_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 2998: +// Generated from 'nat.api.json', line 2990: // // "dslite_get_b4_addr_reply", // [ @@ -5300,18 +5293,18 @@ type DsliteGetB4AddrReply struct { func (*DsliteGetB4AddrReply) GetMessageName() string { return "dslite_get_b4_addr_reply" } -func (*DsliteGetB4AddrReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*DsliteGetB4AddrReply) GetCrcString() string { return "2c4c3037" } +func (*DsliteGetB4AddrReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewDsliteGetB4AddrReply() api.Message { return &DsliteGetB4AddrReply{} } // Nat66AddDelInterface represents the VPP binary API message 'nat66_add_del_interface'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 3026: +// Generated from 'nat.api.json', line 3018: // // "nat66_add_del_interface", // [ @@ -5351,18 +5344,18 @@ type Nat66AddDelInterface struct { func (*Nat66AddDelInterface) GetMessageName() string { return "nat66_add_del_interface" } -func (*Nat66AddDelInterface) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat66AddDelInterface) GetCrcString() string { return "9b1ac600" } +func (*Nat66AddDelInterface) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat66AddDelInterface() api.Message { return &Nat66AddDelInterface{} } // Nat66AddDelInterfaceReply represents the VPP binary API message 'nat66_add_del_interface_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 3056: +// Generated from 'nat.api.json', line 3048: // // "nat66_add_del_interface_reply", // [ @@ -5388,18 +5381,18 @@ type Nat66AddDelInterfaceReply struct { func (*Nat66AddDelInterfaceReply) GetMessageName() string { return "nat66_add_del_interface_reply" } -func (*Nat66AddDelInterfaceReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat66AddDelInterfaceReply) GetCrcString() string { return "e8d4e804" } +func (*Nat66AddDelInterfaceReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat66AddDelInterfaceReply() api.Message { return &Nat66AddDelInterfaceReply{} } // Nat66InterfaceDump represents the VPP binary API message 'nat66_interface_dump'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 3074: +// Generated from 'nat.api.json', line 3066: // // "nat66_interface_dump", // [ @@ -5418,24 +5411,23 @@ func NewNat66AddDelInterfaceReply() api.Message { // "crc": "0x51077d14" // } // -type Nat66InterfaceDump struct { -} +type Nat66InterfaceDump struct{} func (*Nat66InterfaceDump) GetMessageName() string { return "nat66_interface_dump" } -func (*Nat66InterfaceDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat66InterfaceDump) GetCrcString() string { return "51077d14" } +func (*Nat66InterfaceDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat66InterfaceDump() api.Message { return &Nat66InterfaceDump{} } // Nat66InterfaceDetails represents the VPP binary API message 'nat66_interface_details'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 3092: +// Generated from 'nat.api.json', line 3084: // // "nat66_interface_details", // [ @@ -5466,18 +5458,18 @@ type Nat66InterfaceDetails struct { func (*Nat66InterfaceDetails) GetMessageName() string { return "nat66_interface_details" } -func (*Nat66InterfaceDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat66InterfaceDetails) GetCrcString() string { return "2b15e8e4" } +func (*Nat66InterfaceDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat66InterfaceDetails() api.Message { return &Nat66InterfaceDetails{} } // Nat66AddDelStaticMapping represents the VPP binary API message 'nat66_add_del_static_mapping'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 3114: +// Generated from 'nat.api.json', line 3106: // // "nat66_add_del_static_mapping", // [ @@ -5524,18 +5516,18 @@ type Nat66AddDelStaticMapping struct { func (*Nat66AddDelStaticMapping) GetMessageName() string { return "nat66_add_del_static_mapping" } -func (*Nat66AddDelStaticMapping) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat66AddDelStaticMapping) GetCrcString() string { return "67a1dbe1" } +func (*Nat66AddDelStaticMapping) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat66AddDelStaticMapping() api.Message { return &Nat66AddDelStaticMapping{} } // Nat66AddDelStaticMappingReply represents the VPP binary API message 'nat66_add_del_static_mapping_reply'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 3150: +// Generated from 'nat.api.json', line 3142: // // "nat66_add_del_static_mapping_reply", // [ @@ -5561,18 +5553,18 @@ type Nat66AddDelStaticMappingReply struct { func (*Nat66AddDelStaticMappingReply) GetMessageName() string { return "nat66_add_del_static_mapping_reply" } -func (*Nat66AddDelStaticMappingReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat66AddDelStaticMappingReply) GetCrcString() string { return "e8d4e804" } +func (*Nat66AddDelStaticMappingReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat66AddDelStaticMappingReply() api.Message { return &Nat66AddDelStaticMappingReply{} } // Nat66StaticMappingDump represents the VPP binary API message 'nat66_static_mapping_dump'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 3168: +// Generated from 'nat.api.json', line 3160: // // "nat66_static_mapping_dump", // [ @@ -5591,24 +5583,23 @@ func NewNat66AddDelStaticMappingReply() api.Message { // "crc": "0x51077d14" // } // -type Nat66StaticMappingDump struct { -} +type Nat66StaticMappingDump struct{} func (*Nat66StaticMappingDump) GetMessageName() string { return "nat66_static_mapping_dump" } -func (*Nat66StaticMappingDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Nat66StaticMappingDump) GetCrcString() string { return "51077d14" } +func (*Nat66StaticMappingDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewNat66StaticMappingDump() api.Message { return &Nat66StaticMappingDump{} } // Nat66StaticMappingDetails represents the VPP binary API message 'nat66_static_mapping_details'. -// Generated from '/usr/share/vpp/api/nat.api.json', line 3186: +// Generated from 'nat.api.json', line 3178: // // "nat66_static_mapping_details", // [ @@ -5656,12 +5647,194 @@ type Nat66StaticMappingDetails struct { func (*Nat66StaticMappingDetails) GetMessageName() string { return "nat66_static_mapping_details" } -func (*Nat66StaticMappingDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*Nat66StaticMappingDetails) GetCrcString() string { return "f61e499a" } +func (*Nat66StaticMappingDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewNat66StaticMappingDetails() api.Message { return &Nat66StaticMappingDetails{} } + +/* Services */ + +type Services interface { + DumpDsliteAddress(*DsliteAddressDump) (*DsliteAddressDetails, error) + DumpNat44Address(*Nat44AddressDump) (*Nat44AddressDetails, error) + DumpNat44IdentityMapping(*Nat44IdentityMappingDump) (*Nat44IdentityMappingDetails, error) + DumpNat44InterfaceAddr(*Nat44InterfaceAddrDump) (*Nat44InterfaceAddrDetails, error) + DumpNat44Interface(*Nat44InterfaceDump) (*Nat44InterfaceDetails, error) + DumpNat44InterfaceOutputFeature(*Nat44InterfaceOutputFeatureDump) (*Nat44InterfaceOutputFeatureDetails, error) + DumpNat44LbStaticMapping(*Nat44LbStaticMappingDump) (*Nat44LbStaticMappingDetails, error) + DumpNat44StaticMapping(*Nat44StaticMappingDump) (*Nat44StaticMappingDetails, error) + DumpNat44User(*Nat44UserDump) (*Nat44UserDetails, error) + DumpNat44UserSession(*Nat44UserSessionDump) (*Nat44UserSessionDetails, error) + DumpNat64Bib(*Nat64BibDump) (*Nat64BibDetails, error) + DumpNat64Interface(*Nat64InterfaceDump) (*Nat64InterfaceDetails, error) + DumpNat64PoolAddr(*Nat64PoolAddrDump) (*Nat64PoolAddrDetails, error) + DumpNat64Prefix(*Nat64PrefixDump) (*Nat64PrefixDetails, error) + DumpNat64St(*Nat64StDump) (*Nat64StDetails, error) + DumpNat66Interface(*Nat66InterfaceDump) (*Nat66InterfaceDetails, error) + DumpNat66StaticMapping(*Nat66StaticMappingDump) (*Nat66StaticMappingDetails, error) + DumpNatDetMap(*NatDetMapDump) (*NatDetMapDetails, error) + DumpNatDetSession(*NatDetSessionDump) (*NatDetSessionDetails, error) + DumpNatReass(*NatReassDump) (*NatReassDetails, error) + DumpNatWorker(*NatWorkerDump) (*NatWorkerDetails, error) + DsliteAddDelPoolAddrRange(*DsliteAddDelPoolAddrRange) (*DsliteAddDelPoolAddrRangeReply, error) + DsliteGetAftrAddr(*DsliteGetAftrAddr) (*DsliteGetAftrAddrReply, error) + DsliteGetB4Addr(*DsliteGetB4Addr) (*DsliteGetB4AddrReply, error) + DsliteSetAftrAddr(*DsliteSetAftrAddr) (*DsliteSetAftrAddrReply, error) + DsliteSetB4Addr(*DsliteSetB4Addr) (*DsliteSetB4AddrReply, error) + Nat44AddDelAddressRange(*Nat44AddDelAddressRange) (*Nat44AddDelAddressRangeReply, error) + Nat44AddDelIdentityMapping(*Nat44AddDelIdentityMapping) (*Nat44AddDelIdentityMappingReply, error) + Nat44AddDelInterfaceAddr(*Nat44AddDelInterfaceAddr) (*Nat44AddDelInterfaceAddrReply, error) + Nat44AddDelLbStaticMapping(*Nat44AddDelLbStaticMapping) (*Nat44AddDelLbStaticMappingReply, error) + Nat44AddDelStaticMapping(*Nat44AddDelStaticMapping) (*Nat44AddDelStaticMappingReply, error) + Nat44DelSession(*Nat44DelSession) (*Nat44DelSessionReply, error) + Nat44ForwardingEnableDisable(*Nat44ForwardingEnableDisable) (*Nat44ForwardingEnableDisableReply, error) + Nat44ForwardingIsEnabled(*Nat44ForwardingIsEnabled) (*Nat44ForwardingIsEnabledReply, error) + Nat44InterfaceAddDelFeature(*Nat44InterfaceAddDelFeature) (*Nat44InterfaceAddDelFeatureReply, error) + Nat44InterfaceAddDelOutputFeature(*Nat44InterfaceAddDelOutputFeature) (*Nat44InterfaceAddDelOutputFeatureReply, error) + Nat64AddDelInterface(*Nat64AddDelInterface) (*Nat64AddDelInterfaceReply, error) + Nat64AddDelInterfaceAddr(*Nat64AddDelInterfaceAddr) (*Nat64AddDelInterfaceAddrReply, error) + Nat64AddDelPoolAddrRange(*Nat64AddDelPoolAddrRange) (*Nat64AddDelPoolAddrRangeReply, error) + Nat64AddDelPrefix(*Nat64AddDelPrefix) (*Nat64AddDelPrefixReply, error) + Nat64AddDelStaticBib(*Nat64AddDelStaticBib) (*Nat64AddDelStaticBibReply, error) + Nat64GetTimeouts(*Nat64GetTimeouts) (*Nat64GetTimeoutsReply, error) + Nat64SetTimeouts(*Nat64SetTimeouts) (*Nat64SetTimeoutsReply, error) + Nat66AddDelInterface(*Nat66AddDelInterface) (*Nat66AddDelInterfaceReply, error) + Nat66AddDelStaticMapping(*Nat66AddDelStaticMapping) (*Nat66AddDelStaticMappingReply, error) + NatControlPing(*NatControlPing) (*NatControlPingReply, error) + NatDetAddDelMap(*NatDetAddDelMap) (*NatDetAddDelMapReply, error) + NatDetCloseSessionIn(*NatDetCloseSessionIn) (*NatDetCloseSessionInReply, error) + NatDetCloseSessionOut(*NatDetCloseSessionOut) (*NatDetCloseSessionOutReply, error) + NatDetForward(*NatDetForward) (*NatDetForwardReply, error) + NatDetGetTimeouts(*NatDetGetTimeouts) (*NatDetGetTimeoutsReply, error) + NatDetReverse(*NatDetReverse) (*NatDetReverseReply, error) + NatDetSetTimeouts(*NatDetSetTimeouts) (*NatDetSetTimeoutsReply, error) + NatGetReass(*NatGetReass) (*NatGetReassReply, error) + NatIpfixEnableDisable(*NatIpfixEnableDisable) (*NatIpfixEnableDisableReply, error) + NatSetReass(*NatSetReass) (*NatSetReassReply, error) + NatSetWorkers(*NatSetWorkers) (*NatSetWorkersReply, error) + NatShowConfig(*NatShowConfig) (*NatShowConfigReply, error) +} + +func init() { + api.RegisterMessage((*NatControlPing)(nil), "nat.NatControlPing") + api.RegisterMessage((*NatControlPingReply)(nil), "nat.NatControlPingReply") + api.RegisterMessage((*NatShowConfig)(nil), "nat.NatShowConfig") + api.RegisterMessage((*NatShowConfigReply)(nil), "nat.NatShowConfigReply") + api.RegisterMessage((*NatSetWorkers)(nil), "nat.NatSetWorkers") + api.RegisterMessage((*NatSetWorkersReply)(nil), "nat.NatSetWorkersReply") + api.RegisterMessage((*NatWorkerDump)(nil), "nat.NatWorkerDump") + api.RegisterMessage((*NatWorkerDetails)(nil), "nat.NatWorkerDetails") + api.RegisterMessage((*NatIpfixEnableDisable)(nil), "nat.NatIpfixEnableDisable") + api.RegisterMessage((*NatIpfixEnableDisableReply)(nil), "nat.NatIpfixEnableDisableReply") + api.RegisterMessage((*NatSetReass)(nil), "nat.NatSetReass") + api.RegisterMessage((*NatSetReassReply)(nil), "nat.NatSetReassReply") + api.RegisterMessage((*NatGetReass)(nil), "nat.NatGetReass") + api.RegisterMessage((*NatGetReassReply)(nil), "nat.NatGetReassReply") + api.RegisterMessage((*NatReassDump)(nil), "nat.NatReassDump") + api.RegisterMessage((*NatReassDetails)(nil), "nat.NatReassDetails") + api.RegisterMessage((*Nat44AddDelAddressRange)(nil), "nat.Nat44AddDelAddressRange") + api.RegisterMessage((*Nat44AddDelAddressRangeReply)(nil), "nat.Nat44AddDelAddressRangeReply") + api.RegisterMessage((*Nat44AddressDump)(nil), "nat.Nat44AddressDump") + api.RegisterMessage((*Nat44AddressDetails)(nil), "nat.Nat44AddressDetails") + api.RegisterMessage((*Nat44InterfaceAddDelFeature)(nil), "nat.Nat44InterfaceAddDelFeature") + api.RegisterMessage((*Nat44InterfaceAddDelFeatureReply)(nil), "nat.Nat44InterfaceAddDelFeatureReply") + api.RegisterMessage((*Nat44InterfaceDump)(nil), "nat.Nat44InterfaceDump") + api.RegisterMessage((*Nat44InterfaceDetails)(nil), "nat.Nat44InterfaceDetails") + api.RegisterMessage((*Nat44InterfaceAddDelOutputFeature)(nil), "nat.Nat44InterfaceAddDelOutputFeature") + api.RegisterMessage((*Nat44InterfaceAddDelOutputFeatureReply)(nil), "nat.Nat44InterfaceAddDelOutputFeatureReply") + api.RegisterMessage((*Nat44InterfaceOutputFeatureDump)(nil), "nat.Nat44InterfaceOutputFeatureDump") + api.RegisterMessage((*Nat44InterfaceOutputFeatureDetails)(nil), "nat.Nat44InterfaceOutputFeatureDetails") + api.RegisterMessage((*Nat44AddDelStaticMapping)(nil), "nat.Nat44AddDelStaticMapping") + api.RegisterMessage((*Nat44AddDelStaticMappingReply)(nil), "nat.Nat44AddDelStaticMappingReply") + api.RegisterMessage((*Nat44StaticMappingDump)(nil), "nat.Nat44StaticMappingDump") + api.RegisterMessage((*Nat44StaticMappingDetails)(nil), "nat.Nat44StaticMappingDetails") + api.RegisterMessage((*Nat44AddDelIdentityMapping)(nil), "nat.Nat44AddDelIdentityMapping") + api.RegisterMessage((*Nat44AddDelIdentityMappingReply)(nil), "nat.Nat44AddDelIdentityMappingReply") + api.RegisterMessage((*Nat44IdentityMappingDump)(nil), "nat.Nat44IdentityMappingDump") + api.RegisterMessage((*Nat44IdentityMappingDetails)(nil), "nat.Nat44IdentityMappingDetails") + api.RegisterMessage((*Nat44AddDelInterfaceAddr)(nil), "nat.Nat44AddDelInterfaceAddr") + api.RegisterMessage((*Nat44AddDelInterfaceAddrReply)(nil), "nat.Nat44AddDelInterfaceAddrReply") + api.RegisterMessage((*Nat44InterfaceAddrDump)(nil), "nat.Nat44InterfaceAddrDump") + api.RegisterMessage((*Nat44InterfaceAddrDetails)(nil), "nat.Nat44InterfaceAddrDetails") + api.RegisterMessage((*Nat44UserDump)(nil), "nat.Nat44UserDump") + api.RegisterMessage((*Nat44UserDetails)(nil), "nat.Nat44UserDetails") + api.RegisterMessage((*Nat44UserSessionDump)(nil), "nat.Nat44UserSessionDump") + api.RegisterMessage((*Nat44UserSessionDetails)(nil), "nat.Nat44UserSessionDetails") + api.RegisterMessage((*Nat44AddDelLbStaticMapping)(nil), "nat.Nat44AddDelLbStaticMapping") + api.RegisterMessage((*Nat44AddDelLbStaticMappingReply)(nil), "nat.Nat44AddDelLbStaticMappingReply") + api.RegisterMessage((*Nat44LbStaticMappingDump)(nil), "nat.Nat44LbStaticMappingDump") + api.RegisterMessage((*Nat44LbStaticMappingDetails)(nil), "nat.Nat44LbStaticMappingDetails") + api.RegisterMessage((*Nat44DelSession)(nil), "nat.Nat44DelSession") + api.RegisterMessage((*Nat44DelSessionReply)(nil), "nat.Nat44DelSessionReply") + api.RegisterMessage((*Nat44ForwardingEnableDisable)(nil), "nat.Nat44ForwardingEnableDisable") + api.RegisterMessage((*Nat44ForwardingEnableDisableReply)(nil), "nat.Nat44ForwardingEnableDisableReply") + api.RegisterMessage((*Nat44ForwardingIsEnabled)(nil), "nat.Nat44ForwardingIsEnabled") + api.RegisterMessage((*Nat44ForwardingIsEnabledReply)(nil), "nat.Nat44ForwardingIsEnabledReply") + api.RegisterMessage((*NatDetAddDelMap)(nil), "nat.NatDetAddDelMap") + api.RegisterMessage((*NatDetAddDelMapReply)(nil), "nat.NatDetAddDelMapReply") + api.RegisterMessage((*NatDetForward)(nil), "nat.NatDetForward") + api.RegisterMessage((*NatDetForwardReply)(nil), "nat.NatDetForwardReply") + api.RegisterMessage((*NatDetReverse)(nil), "nat.NatDetReverse") + api.RegisterMessage((*NatDetReverseReply)(nil), "nat.NatDetReverseReply") + api.RegisterMessage((*NatDetMapDump)(nil), "nat.NatDetMapDump") + api.RegisterMessage((*NatDetMapDetails)(nil), "nat.NatDetMapDetails") + api.RegisterMessage((*NatDetSetTimeouts)(nil), "nat.NatDetSetTimeouts") + api.RegisterMessage((*NatDetSetTimeoutsReply)(nil), "nat.NatDetSetTimeoutsReply") + api.RegisterMessage((*NatDetGetTimeouts)(nil), "nat.NatDetGetTimeouts") + api.RegisterMessage((*NatDetGetTimeoutsReply)(nil), "nat.NatDetGetTimeoutsReply") + api.RegisterMessage((*NatDetCloseSessionOut)(nil), "nat.NatDetCloseSessionOut") + api.RegisterMessage((*NatDetCloseSessionOutReply)(nil), "nat.NatDetCloseSessionOutReply") + api.RegisterMessage((*NatDetCloseSessionIn)(nil), "nat.NatDetCloseSessionIn") + api.RegisterMessage((*NatDetCloseSessionInReply)(nil), "nat.NatDetCloseSessionInReply") + api.RegisterMessage((*NatDetSessionDump)(nil), "nat.NatDetSessionDump") + api.RegisterMessage((*NatDetSessionDetails)(nil), "nat.NatDetSessionDetails") + api.RegisterMessage((*Nat64AddDelPoolAddrRange)(nil), "nat.Nat64AddDelPoolAddrRange") + api.RegisterMessage((*Nat64AddDelPoolAddrRangeReply)(nil), "nat.Nat64AddDelPoolAddrRangeReply") + api.RegisterMessage((*Nat64PoolAddrDump)(nil), "nat.Nat64PoolAddrDump") + api.RegisterMessage((*Nat64PoolAddrDetails)(nil), "nat.Nat64PoolAddrDetails") + api.RegisterMessage((*Nat64AddDelInterface)(nil), "nat.Nat64AddDelInterface") + api.RegisterMessage((*Nat64AddDelInterfaceReply)(nil), "nat.Nat64AddDelInterfaceReply") + api.RegisterMessage((*Nat64InterfaceDump)(nil), "nat.Nat64InterfaceDump") + api.RegisterMessage((*Nat64InterfaceDetails)(nil), "nat.Nat64InterfaceDetails") + api.RegisterMessage((*Nat64AddDelStaticBib)(nil), "nat.Nat64AddDelStaticBib") + api.RegisterMessage((*Nat64AddDelStaticBibReply)(nil), "nat.Nat64AddDelStaticBibReply") + api.RegisterMessage((*Nat64BibDump)(nil), "nat.Nat64BibDump") + api.RegisterMessage((*Nat64BibDetails)(nil), "nat.Nat64BibDetails") + api.RegisterMessage((*Nat64SetTimeouts)(nil), "nat.Nat64SetTimeouts") + api.RegisterMessage((*Nat64SetTimeoutsReply)(nil), "nat.Nat64SetTimeoutsReply") + api.RegisterMessage((*Nat64GetTimeouts)(nil), "nat.Nat64GetTimeouts") + api.RegisterMessage((*Nat64GetTimeoutsReply)(nil), "nat.Nat64GetTimeoutsReply") + api.RegisterMessage((*Nat64StDump)(nil), "nat.Nat64StDump") + api.RegisterMessage((*Nat64StDetails)(nil), "nat.Nat64StDetails") + api.RegisterMessage((*Nat64AddDelPrefix)(nil), "nat.Nat64AddDelPrefix") + api.RegisterMessage((*Nat64AddDelPrefixReply)(nil), "nat.Nat64AddDelPrefixReply") + api.RegisterMessage((*Nat64PrefixDump)(nil), "nat.Nat64PrefixDump") + api.RegisterMessage((*Nat64PrefixDetails)(nil), "nat.Nat64PrefixDetails") + api.RegisterMessage((*Nat64AddDelInterfaceAddr)(nil), "nat.Nat64AddDelInterfaceAddr") + api.RegisterMessage((*Nat64AddDelInterfaceAddrReply)(nil), "nat.Nat64AddDelInterfaceAddrReply") + api.RegisterMessage((*DsliteAddDelPoolAddrRange)(nil), "nat.DsliteAddDelPoolAddrRange") + api.RegisterMessage((*DsliteAddDelPoolAddrRangeReply)(nil), "nat.DsliteAddDelPoolAddrRangeReply") + api.RegisterMessage((*DsliteAddressDump)(nil), "nat.DsliteAddressDump") + api.RegisterMessage((*DsliteAddressDetails)(nil), "nat.DsliteAddressDetails") + api.RegisterMessage((*DsliteSetAftrAddr)(nil), "nat.DsliteSetAftrAddr") + api.RegisterMessage((*DsliteSetAftrAddrReply)(nil), "nat.DsliteSetAftrAddrReply") + api.RegisterMessage((*DsliteGetAftrAddr)(nil), "nat.DsliteGetAftrAddr") + api.RegisterMessage((*DsliteGetAftrAddrReply)(nil), "nat.DsliteGetAftrAddrReply") + api.RegisterMessage((*DsliteSetB4Addr)(nil), "nat.DsliteSetB4Addr") + api.RegisterMessage((*DsliteSetB4AddrReply)(nil), "nat.DsliteSetB4AddrReply") + api.RegisterMessage((*DsliteGetB4Addr)(nil), "nat.DsliteGetB4Addr") + api.RegisterMessage((*DsliteGetB4AddrReply)(nil), "nat.DsliteGetB4AddrReply") + api.RegisterMessage((*Nat66AddDelInterface)(nil), "nat.Nat66AddDelInterface") + api.RegisterMessage((*Nat66AddDelInterfaceReply)(nil), "nat.Nat66AddDelInterfaceReply") + api.RegisterMessage((*Nat66InterfaceDump)(nil), "nat.Nat66InterfaceDump") + api.RegisterMessage((*Nat66InterfaceDetails)(nil), "nat.Nat66InterfaceDetails") + api.RegisterMessage((*Nat66AddDelStaticMapping)(nil), "nat.Nat66AddDelStaticMapping") + api.RegisterMessage((*Nat66AddDelStaticMappingReply)(nil), "nat.Nat66AddDelStaticMappingReply") + api.RegisterMessage((*Nat66StaticMappingDump)(nil), "nat.Nat66StaticMappingDump") + api.RegisterMessage((*Nat66StaticMappingDetails)(nil), "nat.Nat66StaticMappingDetails") +} diff --git a/plugins/vpp/binapi/nat/pkgreflect.go b/plugins/vpp/binapi/nat/pkgreflect.go index dd998f4545..9f48e5eba9 100644 --- a/plugins/vpp/binapi/nat/pkgreflect.go +++ b/plugins/vpp/binapi/nat/pkgreflect.go @@ -122,6 +122,7 @@ var Types = map[string]reflect.Type{ "NatShowConfigReply": reflect.TypeOf((*NatShowConfigReply)(nil)).Elem(), "NatWorkerDetails": reflect.TypeOf((*NatWorkerDetails)(nil)).Elem(), "NatWorkerDump": reflect.TypeOf((*NatWorkerDump)(nil)).Elem(), + "Services": reflect.TypeOf((*Services)(nil)).Elem(), } var Functions = map[string]reflect.Value{ diff --git a/plugins/vpp/binapi/session/pkgreflect.go b/plugins/vpp/binapi/session/pkgreflect.go index 7a4a816fe6..83aea6c3b9 100644 --- a/plugins/vpp/binapi/session/pkgreflect.go +++ b/plugins/vpp/binapi/session/pkgreflect.go @@ -7,6 +7,8 @@ import "reflect" var Types = map[string]reflect.Type{ "AcceptSession": reflect.TypeOf((*AcceptSession)(nil)).Elem(), "AcceptSessionReply": reflect.TypeOf((*AcceptSessionReply)(nil)).Elem(), + "AppCutThroughRegistrationAdd": reflect.TypeOf((*AppCutThroughRegistrationAdd)(nil)).Elem(), + "AppCutThroughRegistrationAddReply": reflect.TypeOf((*AppCutThroughRegistrationAddReply)(nil)).Elem(), "AppNamespaceAddDel": reflect.TypeOf((*AppNamespaceAddDel)(nil)).Elem(), "AppNamespaceAddDelReply": reflect.TypeOf((*AppNamespaceAddDelReply)(nil)).Elem(), "ApplicationAttach": reflect.TypeOf((*ApplicationAttach)(nil)).Elem(), @@ -33,6 +35,7 @@ var Types = map[string]reflect.Type{ "MapAnotherSegmentReply": reflect.TypeOf((*MapAnotherSegmentReply)(nil)).Elem(), "ResetSession": reflect.TypeOf((*ResetSession)(nil)).Elem(), "ResetSessionReply": reflect.TypeOf((*ResetSessionReply)(nil)).Elem(), + "Services": reflect.TypeOf((*Services)(nil)).Elem(), "SessionEnableDisable": reflect.TypeOf((*SessionEnableDisable)(nil)).Elem(), "SessionEnableDisableReply": reflect.TypeOf((*SessionEnableDisableReply)(nil)).Elem(), "SessionRuleAddDel": reflect.TypeOf((*SessionRuleAddDel)(nil)).Elem(), @@ -50,6 +53,8 @@ var Types = map[string]reflect.Type{ var Functions = map[string]reflect.Value{ "NewAcceptSession": reflect.ValueOf(NewAcceptSession), "NewAcceptSessionReply": reflect.ValueOf(NewAcceptSessionReply), + "NewAppCutThroughRegistrationAdd": reflect.ValueOf(NewAppCutThroughRegistrationAdd), + "NewAppCutThroughRegistrationAddReply": reflect.ValueOf(NewAppCutThroughRegistrationAddReply), "NewAppNamespaceAddDel": reflect.ValueOf(NewAppNamespaceAddDel), "NewAppNamespaceAddDelReply": reflect.ValueOf(NewAppNamespaceAddDelReply), "NewApplicationAttach": reflect.ValueOf(NewApplicationAttach), diff --git a/plugins/vpp/binapi/session/session.go b/plugins/vpp/binapi/session/session.ba.go similarity index 82% rename from plugins/vpp/binapi/session/session.go rename to plugins/vpp/binapi/session/session.ba.go index 3d9fed413a..5bbc41981f 100644 --- a/plugins/vpp/binapi/session/session.go +++ b/plugins/vpp/binapi/session/session.ba.go @@ -1,12 +1,30 @@ -// Code generated by govpp binapi-generator DO NOT EDIT. -// Package session represents the VPP binary API of the 'session' VPP module. -// Generated from '/usr/share/vpp/api/session.api.json' +// Code generated by GoVPP binapi-generator. DO NOT EDIT. +// source: /usr/share/vpp/api/session.api.json + +/* +Package session is a generated VPP binary API of the 'session' VPP module. + +It is generated from this file: + session.api.json + +It contains these VPP binary API objects: + 42 messages + 21 services +*/ package session import "git.fd.io/govpp.git/api" +import "github.com/lunixbochs/struc" +import "bytes" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = struc.Pack +var _ = bytes.NewBuffer + +/* Messages */ // ApplicationAttach represents the VPP binary API message 'application_attach'. -// Generated from '/usr/share/vpp/api/session.api.json', line 4: +// Generated from 'session.api.json', line 4: // // "application_attach", // [ @@ -53,18 +71,18 @@ type ApplicationAttach struct { func (*ApplicationAttach) GetMessageName() string { return "application_attach" } -func (*ApplicationAttach) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ApplicationAttach) GetCrcString() string { return "81d4f974" } +func (*ApplicationAttach) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewApplicationAttach() api.Message { return &ApplicationAttach{} } // ApplicationAttachReply represents the VPP binary API message 'application_attach_reply'. -// Generated from '/usr/share/vpp/api/session.api.json', line 40: +// Generated from 'session.api.json', line 40: // // "application_attach_reply", // [ @@ -84,6 +102,14 @@ func NewApplicationAttach() api.Message { // "app_event_queue_address" // ], // [ +// "u8", +// "n_fds" +// ], +// [ +// "u8", +// "fd_flags" +// ], +// [ // "u32", // "segment_size" // ], @@ -97,12 +123,14 @@ func NewApplicationAttach() api.Message { // 128 // ], // { -// "crc": "0xb3bf3789" +// "crc": "0x8d501943" // } // type ApplicationAttachReply struct { Retval int32 AppEventQueueAddress uint64 + NFds uint8 + FdFlags uint8 SegmentSize uint32 SegmentNameLength uint8 SegmentName []byte `struc:"[128]byte"` @@ -111,18 +139,18 @@ type ApplicationAttachReply struct { func (*ApplicationAttachReply) GetMessageName() string { return "application_attach_reply" } +func (*ApplicationAttachReply) GetCrcString() string { + return "8d501943" +} func (*ApplicationAttachReply) GetMessageType() api.MessageType { return api.ReplyMessage } -func (*ApplicationAttachReply) GetCrcString() string { - return "b3bf3789" -} func NewApplicationAttachReply() api.Message { return &ApplicationAttachReply{} } // ApplicationTLSCertAdd represents the VPP binary API message 'application_tls_cert_add'. -// Generated from '/usr/share/vpp/api/session.api.json', line 75: +// Generated from 'session.api.json', line 83: // // "application_tls_cert_add", // [ @@ -164,18 +192,18 @@ type ApplicationTLSCertAdd struct { func (*ApplicationTLSCertAdd) GetMessageName() string { return "application_tls_cert_add" } -func (*ApplicationTLSCertAdd) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ApplicationTLSCertAdd) GetCrcString() string { return "3f5cfe45" } +func (*ApplicationTLSCertAdd) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewApplicationTLSCertAdd() api.Message { return &ApplicationTLSCertAdd{} } // ApplicationTLSCertAddReply represents the VPP binary API message 'application_tls_cert_add_reply'. -// Generated from '/usr/share/vpp/api/session.api.json', line 107: +// Generated from 'session.api.json', line 115: // // "application_tls_cert_add_reply", // [ @@ -201,18 +229,18 @@ type ApplicationTLSCertAddReply struct { func (*ApplicationTLSCertAddReply) GetMessageName() string { return "application_tls_cert_add_reply" } -func (*ApplicationTLSCertAddReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ApplicationTLSCertAddReply) GetCrcString() string { return "e8d4e804" } +func (*ApplicationTLSCertAddReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewApplicationTLSCertAddReply() api.Message { return &ApplicationTLSCertAddReply{} } // ApplicationTLSKeyAdd represents the VPP binary API message 'application_tls_key_add'. -// Generated from '/usr/share/vpp/api/session.api.json', line 125: +// Generated from 'session.api.json', line 133: // // "application_tls_key_add", // [ @@ -254,18 +282,18 @@ type ApplicationTLSKeyAdd struct { func (*ApplicationTLSKeyAdd) GetMessageName() string { return "application_tls_key_add" } -func (*ApplicationTLSKeyAdd) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ApplicationTLSKeyAdd) GetCrcString() string { return "5eaf70cd" } +func (*ApplicationTLSKeyAdd) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewApplicationTLSKeyAdd() api.Message { return &ApplicationTLSKeyAdd{} } // ApplicationTLSKeyAddReply represents the VPP binary API message 'application_tls_key_add_reply'. -// Generated from '/usr/share/vpp/api/session.api.json', line 157: +// Generated from 'session.api.json', line 165: // // "application_tls_key_add_reply", // [ @@ -291,18 +319,18 @@ type ApplicationTLSKeyAddReply struct { func (*ApplicationTLSKeyAddReply) GetMessageName() string { return "application_tls_key_add_reply" } -func (*ApplicationTLSKeyAddReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ApplicationTLSKeyAddReply) GetCrcString() string { return "e8d4e804" } +func (*ApplicationTLSKeyAddReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewApplicationTLSKeyAddReply() api.Message { return &ApplicationTLSKeyAddReply{} } // ApplicationDetach represents the VPP binary API message 'application_detach'. -// Generated from '/usr/share/vpp/api/session.api.json', line 175: +// Generated from 'session.api.json', line 183: // // "application_detach", // [ @@ -321,24 +349,23 @@ func NewApplicationTLSKeyAddReply() api.Message { // "crc": "0x51077d14" // } // -type ApplicationDetach struct { -} +type ApplicationDetach struct{} func (*ApplicationDetach) GetMessageName() string { return "application_detach" } -func (*ApplicationDetach) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ApplicationDetach) GetCrcString() string { return "51077d14" } +func (*ApplicationDetach) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewApplicationDetach() api.Message { return &ApplicationDetach{} } // ApplicationDetachReply represents the VPP binary API message 'application_detach_reply'. -// Generated from '/usr/share/vpp/api/session.api.json', line 193: +// Generated from 'session.api.json', line 201: // // "application_detach_reply", // [ @@ -364,18 +391,18 @@ type ApplicationDetachReply struct { func (*ApplicationDetachReply) GetMessageName() string { return "application_detach_reply" } -func (*ApplicationDetachReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ApplicationDetachReply) GetCrcString() string { return "e8d4e804" } +func (*ApplicationDetachReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewApplicationDetachReply() api.Message { return &ApplicationDetachReply{} } // MapAnotherSegment represents the VPP binary API message 'map_another_segment'. -// Generated from '/usr/share/vpp/api/session.api.json', line 211: +// Generated from 'session.api.json', line 219: // // "map_another_segment", // [ @@ -391,6 +418,10 @@ func NewApplicationDetachReply() api.Message { // "context" // ], // [ +// "u8", +// "fd_flags" +// ], +// [ // "u32", // "segment_size" // ], @@ -400,10 +431,11 @@ func NewApplicationDetachReply() api.Message { // 128 // ], // { -// "crc": "0x9db38ca6" +// "crc": "0x2b743078" // } // type MapAnotherSegment struct { + FdFlags uint8 SegmentSize uint32 SegmentName []byte `struc:"[128]byte"` } @@ -411,18 +443,18 @@ type MapAnotherSegment struct { func (*MapAnotherSegment) GetMessageName() string { return "map_another_segment" } +func (*MapAnotherSegment) GetCrcString() string { + return "2b743078" +} func (*MapAnotherSegment) GetMessageType() api.MessageType { return api.RequestMessage } -func (*MapAnotherSegment) GetCrcString() string { - return "9db38ca6" -} func NewMapAnotherSegment() api.Message { return &MapAnotherSegment{} } // MapAnotherSegmentReply represents the VPP binary API message 'map_another_segment_reply'. -// Generated from '/usr/share/vpp/api/session.api.json', line 238: +// Generated from 'session.api.json', line 250: // // "map_another_segment_reply", // [ @@ -448,18 +480,18 @@ type MapAnotherSegmentReply struct { func (*MapAnotherSegmentReply) GetMessageName() string { return "map_another_segment_reply" } -func (*MapAnotherSegmentReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*MapAnotherSegmentReply) GetCrcString() string { return "e8d4e804" } +func (*MapAnotherSegmentReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewMapAnotherSegmentReply() api.Message { return &MapAnotherSegmentReply{} } // UnmapSegment represents the VPP binary API message 'unmap_segment'. -// Generated from '/usr/share/vpp/api/session.api.json', line 256: +// Generated from 'session.api.json', line 268: // // "unmap_segment", // [ @@ -490,18 +522,18 @@ type UnmapSegment struct { func (*UnmapSegment) GetMessageName() string { return "unmap_segment" } -func (*UnmapSegment) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*UnmapSegment) GetCrcString() string { return "15ffd8c6" } +func (*UnmapSegment) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewUnmapSegment() api.Message { return &UnmapSegment{} } // UnmapSegmentReply represents the VPP binary API message 'unmap_segment_reply'. -// Generated from '/usr/share/vpp/api/session.api.json', line 279: +// Generated from 'session.api.json', line 291: // // "unmap_segment_reply", // [ @@ -527,18 +559,18 @@ type UnmapSegmentReply struct { func (*UnmapSegmentReply) GetMessageName() string { return "unmap_segment_reply" } -func (*UnmapSegmentReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*UnmapSegmentReply) GetCrcString() string { return "e8d4e804" } +func (*UnmapSegmentReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewUnmapSegmentReply() api.Message { return &UnmapSegmentReply{} } // BindURI represents the VPP binary API message 'bind_uri'. -// Generated from '/usr/share/vpp/api/session.api.json', line 297: +// Generated from 'session.api.json', line 309: // // "bind_uri", // [ @@ -574,18 +606,18 @@ type BindURI struct { func (*BindURI) GetMessageName() string { return "bind_uri" } -func (*BindURI) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*BindURI) GetCrcString() string { return "fae140cb" } +func (*BindURI) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewBindURI() api.Message { return &BindURI{} } // BindURIReply represents the VPP binary API message 'bind_uri_reply'. -// Generated from '/usr/share/vpp/api/session.api.json', line 324: +// Generated from 'session.api.json', line 336: // // "bind_uri_reply", // [ @@ -647,18 +679,18 @@ type BindURIReply struct { func (*BindURIReply) GetMessageName() string { return "bind_uri_reply" } -func (*BindURIReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*BindURIReply) GetCrcString() string { return "528af6c0" } +func (*BindURIReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewBindURIReply() api.Message { return &BindURIReply{} } // UnbindURI represents the VPP binary API message 'unbind_uri'. -// Generated from '/usr/share/vpp/api/session.api.json', line 371: +// Generated from 'session.api.json', line 383: // // "unbind_uri", // [ @@ -689,18 +721,18 @@ type UnbindURI struct { func (*UnbindURI) GetMessageName() string { return "unbind_uri" } -func (*UnbindURI) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*UnbindURI) GetCrcString() string { return "294cf07d" } +func (*UnbindURI) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewUnbindURI() api.Message { return &UnbindURI{} } // UnbindURIReply represents the VPP binary API message 'unbind_uri_reply'. -// Generated from '/usr/share/vpp/api/session.api.json', line 394: +// Generated from 'session.api.json', line 406: // // "unbind_uri_reply", // [ @@ -726,18 +758,18 @@ type UnbindURIReply struct { func (*UnbindURIReply) GetMessageName() string { return "unbind_uri_reply" } -func (*UnbindURIReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*UnbindURIReply) GetCrcString() string { return "e8d4e804" } +func (*UnbindURIReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewUnbindURIReply() api.Message { return &UnbindURIReply{} } // ConnectURI represents the VPP binary API message 'connect_uri'. -// Generated from '/usr/share/vpp/api/session.api.json', line 412: +// Generated from 'session.api.json', line 424: // // "connect_uri", // [ @@ -779,18 +811,18 @@ type ConnectURI struct { func (*ConnectURI) GetMessageName() string { return "connect_uri" } -func (*ConnectURI) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ConnectURI) GetCrcString() string { return "a36143d6" } +func (*ConnectURI) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewConnectURI() api.Message { return &ConnectURI{} } // ConnectURIReply represents the VPP binary API message 'connect_uri_reply'. -// Generated from '/usr/share/vpp/api/session.api.json', line 444: +// Generated from 'session.api.json', line 456: // // "connect_uri_reply", // [ @@ -816,18 +848,18 @@ type ConnectURIReply struct { func (*ConnectURIReply) GetMessageName() string { return "connect_uri_reply" } -func (*ConnectURIReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ConnectURIReply) GetCrcString() string { return "e8d4e804" } +func (*ConnectURIReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewConnectURIReply() api.Message { return &ConnectURIReply{} } // AcceptSession represents the VPP binary API message 'accept_session'. -// Generated from '/usr/share/vpp/api/session.api.json', line 462: +// Generated from 'session.api.json', line 474: // // "accept_session", // [ @@ -898,18 +930,18 @@ type AcceptSession struct { func (*AcceptSession) GetMessageName() string { return "accept_session" } -func (*AcceptSession) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*AcceptSession) GetCrcString() string { return "bd57a498" } +func (*AcceptSession) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewAcceptSession() api.Message { return &AcceptSession{} } // AcceptSessionReply represents the VPP binary API message 'accept_session_reply'. -// Generated from '/usr/share/vpp/api/session.api.json', line 517: +// Generated from 'session.api.json', line 529: // // "accept_session_reply", // [ @@ -940,18 +972,18 @@ type AcceptSessionReply struct { func (*AcceptSessionReply) GetMessageName() string { return "accept_session_reply" } -func (*AcceptSessionReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*AcceptSessionReply) GetCrcString() string { return "d6960a03" } +func (*AcceptSessionReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewAcceptSessionReply() api.Message { return &AcceptSessionReply{} } // DisconnectSession represents the VPP binary API message 'disconnect_session'. -// Generated from '/usr/share/vpp/api/session.api.json', line 539: +// Generated from 'session.api.json', line 551: // // "disconnect_session", // [ @@ -981,18 +1013,18 @@ type DisconnectSession struct { func (*DisconnectSession) GetMessageName() string { return "disconnect_session" } -func (*DisconnectSession) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*DisconnectSession) GetCrcString() string { return "7279205b" } +func (*DisconnectSession) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewDisconnectSession() api.Message { return &DisconnectSession{} } // DisconnectSessionReply represents the VPP binary API message 'disconnect_session_reply'. -// Generated from '/usr/share/vpp/api/session.api.json', line 561: +// Generated from 'session.api.json', line 573: // // "disconnect_session_reply", // [ @@ -1023,18 +1055,18 @@ type DisconnectSessionReply struct { func (*DisconnectSessionReply) GetMessageName() string { return "disconnect_session_reply" } -func (*DisconnectSessionReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*DisconnectSessionReply) GetCrcString() string { return "d6960a03" } +func (*DisconnectSessionReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewDisconnectSessionReply() api.Message { return &DisconnectSessionReply{} } // ResetSession represents the VPP binary API message 'reset_session'. -// Generated from '/usr/share/vpp/api/session.api.json', line 583: +// Generated from 'session.api.json', line 595: // // "reset_session", // [ @@ -1064,18 +1096,18 @@ type ResetSession struct { func (*ResetSession) GetMessageName() string { return "reset_session" } -func (*ResetSession) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ResetSession) GetCrcString() string { return "7279205b" } +func (*ResetSession) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewResetSession() api.Message { return &ResetSession{} } // ResetSessionReply represents the VPP binary API message 'reset_session_reply'. -// Generated from '/usr/share/vpp/api/session.api.json', line 605: +// Generated from 'session.api.json', line 617: // // "reset_session_reply", // [ @@ -1110,18 +1142,18 @@ type ResetSessionReply struct { func (*ResetSessionReply) GetMessageName() string { return "reset_session_reply" } -func (*ResetSessionReply) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ResetSessionReply) GetCrcString() string { return "faf37b87" } +func (*ResetSessionReply) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewResetSessionReply() api.Message { return &ResetSessionReply{} } // BindSock represents the VPP binary API message 'bind_sock'. -// Generated from '/usr/share/vpp/api/session.api.json', line 631: +// Generated from 'session.api.json', line 643: // // "bind_sock", // [ @@ -1178,18 +1210,18 @@ type BindSock struct { func (*BindSock) GetMessageName() string { return "bind_sock" } -func (*BindSock) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*BindSock) GetCrcString() string { return "6a6a40d0" } +func (*BindSock) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewBindSock() api.Message { return &BindSock{} } // UnbindSock represents the VPP binary API message 'unbind_sock'. -// Generated from '/usr/share/vpp/api/session.api.json', line 675: +// Generated from 'session.api.json', line 687: // // "unbind_sock", // [ @@ -1219,18 +1251,18 @@ type UnbindSock struct { func (*UnbindSock) GetMessageName() string { return "unbind_sock" } -func (*UnbindSock) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*UnbindSock) GetCrcString() string { return "7279205b" } +func (*UnbindSock) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewUnbindSock() api.Message { return &UnbindSock{} } // UnbindSockReply represents the VPP binary API message 'unbind_sock_reply'. -// Generated from '/usr/share/vpp/api/session.api.json', line 697: +// Generated from 'session.api.json', line 709: // // "unbind_sock_reply", // [ @@ -1256,18 +1288,18 @@ type UnbindSockReply struct { func (*UnbindSockReply) GetMessageName() string { return "unbind_sock_reply" } -func (*UnbindSockReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*UnbindSockReply) GetCrcString() string { return "e8d4e804" } +func (*UnbindSockReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewUnbindSockReply() api.Message { return &UnbindSockReply{} } // ConnectSock represents the VPP binary API message 'connect_sock'. -// Generated from '/usr/share/vpp/api/session.api.json', line 715: +// Generated from 'session.api.json', line 727: // // "connect_sock", // [ @@ -1341,18 +1373,18 @@ type ConnectSock struct { func (*ConnectSock) GetMessageName() string { return "connect_sock" } -func (*ConnectSock) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ConnectSock) GetCrcString() string { return "02c6e3c3" } +func (*ConnectSock) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewConnectSock() api.Message { return &ConnectSock{} } // ConnectSockReply represents the VPP binary API message 'connect_sock_reply'. -// Generated from '/usr/share/vpp/api/session.api.json', line 773: +// Generated from 'session.api.json', line 785: // // "connect_sock_reply", // [ @@ -1378,18 +1410,18 @@ type ConnectSockReply struct { func (*ConnectSockReply) GetMessageName() string { return "connect_sock_reply" } -func (*ConnectSockReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ConnectSockReply) GetCrcString() string { return "e8d4e804" } +func (*ConnectSockReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewConnectSockReply() api.Message { return &ConnectSockReply{} } // BindSockReply represents the VPP binary API message 'bind_sock_reply'. -// Generated from '/usr/share/vpp/api/session.api.json', line 791: +// Generated from 'session.api.json', line 803: // // "bind_sock_reply", // [ @@ -1467,18 +1499,18 @@ type BindSockReply struct { func (*BindSockReply) GetMessageName() string { return "bind_sock_reply" } -func (*BindSockReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*BindSockReply) GetCrcString() string { return "5ca8f50a" } +func (*BindSockReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewBindSockReply() api.Message { return &BindSockReply{} } // ConnectSession represents the VPP binary API message 'connect_session'. -// Generated from '/usr/share/vpp/api/session.api.json', line 851: +// Generated from 'session.api.json', line 863: // // "connect_session", // [ @@ -1497,24 +1529,23 @@ func NewBindSockReply() api.Message { // "crc": "0x51077d14" // } // -type ConnectSession struct { -} +type ConnectSession struct{} func (*ConnectSession) GetMessageName() string { return "connect_session" } -func (*ConnectSession) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ConnectSession) GetCrcString() string { return "51077d14" } +func (*ConnectSession) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewConnectSession() api.Message { return &ConnectSession{} } // ConnectSessionReply represents the VPP binary API message 'connect_session_reply'. -// Generated from '/usr/share/vpp/api/session.api.json', line 869: +// Generated from 'session.api.json', line 881: // // "connect_session_reply", // [ @@ -1597,18 +1628,111 @@ type ConnectSessionReply struct { func (*ConnectSessionReply) GetMessageName() string { return "connect_session_reply" } -func (*ConnectSessionReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ConnectSessionReply) GetCrcString() string { return "fad9041d" } +func (*ConnectSessionReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewConnectSessionReply() api.Message { return &ConnectSessionReply{} } +// AppCutThroughRegistrationAdd represents the VPP binary API message 'app_cut_through_registration_add'. +// Generated from 'session.api.json', line 945: +// +// "app_cut_through_registration_add", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "client_index" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "u64", +// "evt_q_address" +// ], +// [ +// "u64", +// "peer_evt_q_address" +// ], +// [ +// "u8", +// "n_fds" +// ], +// [ +// "u8", +// "fd_flags" +// ], +// { +// "crc": "0x75093c85" +// } +// +type AppCutThroughRegistrationAdd struct { + EvtQAddress uint64 + PeerEvtQAddress uint64 + NFds uint8 + FdFlags uint8 +} + +func (*AppCutThroughRegistrationAdd) GetMessageName() string { + return "app_cut_through_registration_add" +} +func (*AppCutThroughRegistrationAdd) GetCrcString() string { + return "75093c85" +} +func (*AppCutThroughRegistrationAdd) GetMessageType() api.MessageType { + return api.RequestMessage +} +func NewAppCutThroughRegistrationAdd() api.Message { + return &AppCutThroughRegistrationAdd{} +} + +// AppCutThroughRegistrationAddReply represents the VPP binary API message 'app_cut_through_registration_add_reply'. +// Generated from 'session.api.json', line 979: +// +// "app_cut_through_registration_add_reply", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "i32", +// "retval" +// ], +// { +// "crc": "0xe8d4e804" +// } +// +type AppCutThroughRegistrationAddReply struct { + Retval int32 +} + +func (*AppCutThroughRegistrationAddReply) GetMessageName() string { + return "app_cut_through_registration_add_reply" +} +func (*AppCutThroughRegistrationAddReply) GetCrcString() string { + return "e8d4e804" +} +func (*AppCutThroughRegistrationAddReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} +func NewAppCutThroughRegistrationAddReply() api.Message { + return &AppCutThroughRegistrationAddReply{} +} + // SessionEnableDisable represents the VPP binary API message 'session_enable_disable'. -// Generated from '/usr/share/vpp/api/session.api.json', line 933: +// Generated from 'session.api.json', line 997: // // "session_enable_disable", // [ @@ -1638,18 +1762,18 @@ type SessionEnableDisable struct { func (*SessionEnableDisable) GetMessageName() string { return "session_enable_disable" } -func (*SessionEnableDisable) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SessionEnableDisable) GetCrcString() string { return "30ac9be7" } +func (*SessionEnableDisable) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSessionEnableDisable() api.Message { return &SessionEnableDisable{} } // SessionEnableDisableReply represents the VPP binary API message 'session_enable_disable_reply'. -// Generated from '/usr/share/vpp/api/session.api.json', line 955: +// Generated from 'session.api.json', line 1019: // // "session_enable_disable_reply", // [ @@ -1675,18 +1799,18 @@ type SessionEnableDisableReply struct { func (*SessionEnableDisableReply) GetMessageName() string { return "session_enable_disable_reply" } -func (*SessionEnableDisableReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SessionEnableDisableReply) GetCrcString() string { return "e8d4e804" } +func (*SessionEnableDisableReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSessionEnableDisableReply() api.Message { return &SessionEnableDisableReply{} } // AppNamespaceAddDel represents the VPP binary API message 'app_namespace_add_del'. -// Generated from '/usr/share/vpp/api/session.api.json', line 973: +// Generated from 'session.api.json', line 1037: // // "app_namespace_add_del", // [ @@ -1742,18 +1866,18 @@ type AppNamespaceAddDel struct { func (*AppNamespaceAddDel) GetMessageName() string { return "app_namespace_add_del" } -func (*AppNamespaceAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*AppNamespaceAddDel) GetCrcString() string { return "dd074c65" } +func (*AppNamespaceAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewAppNamespaceAddDel() api.Message { return &AppNamespaceAddDel{} } // AppNamespaceAddDelReply represents the VPP binary API message 'app_namespace_add_del_reply'. -// Generated from '/usr/share/vpp/api/session.api.json', line 1016: +// Generated from 'session.api.json', line 1080: // // "app_namespace_add_del_reply", // [ @@ -1784,18 +1908,18 @@ type AppNamespaceAddDelReply struct { func (*AppNamespaceAddDelReply) GetMessageName() string { return "app_namespace_add_del_reply" } -func (*AppNamespaceAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*AppNamespaceAddDelReply) GetCrcString() string { return "85137120" } +func (*AppNamespaceAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewAppNamespaceAddDelReply() api.Message { return &AppNamespaceAddDelReply{} } // SessionRuleAddDel represents the VPP binary API message 'session_rule_add_del'. -// Generated from '/usr/share/vpp/api/session.api.json', line 1038: +// Generated from 'session.api.json', line 1102: // // "session_rule_add_del", // [ @@ -1888,18 +2012,18 @@ type SessionRuleAddDel struct { func (*SessionRuleAddDel) GetMessageName() string { return "session_rule_add_del" } -func (*SessionRuleAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SessionRuleAddDel) GetCrcString() string { return "4ab2eb06" } +func (*SessionRuleAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSessionRuleAddDel() api.Message { return &SessionRuleAddDel{} } // SessionRuleAddDelReply represents the VPP binary API message 'session_rule_add_del_reply'. -// Generated from '/usr/share/vpp/api/session.api.json', line 1111: +// Generated from 'session.api.json', line 1175: // // "session_rule_add_del_reply", // [ @@ -1925,18 +2049,18 @@ type SessionRuleAddDelReply struct { func (*SessionRuleAddDelReply) GetMessageName() string { return "session_rule_add_del_reply" } -func (*SessionRuleAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SessionRuleAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*SessionRuleAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSessionRuleAddDelReply() api.Message { return &SessionRuleAddDelReply{} } // SessionRulesDump represents the VPP binary API message 'session_rules_dump'. -// Generated from '/usr/share/vpp/api/session.api.json', line 1129: +// Generated from 'session.api.json', line 1193: // // "session_rules_dump", // [ @@ -1955,24 +2079,23 @@ func NewSessionRuleAddDelReply() api.Message { // "crc": "0x51077d14" // } // -type SessionRulesDump struct { -} +type SessionRulesDump struct{} func (*SessionRulesDump) GetMessageName() string { return "session_rules_dump" } -func (*SessionRulesDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SessionRulesDump) GetCrcString() string { return "51077d14" } +func (*SessionRulesDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSessionRulesDump() api.Message { return &SessionRulesDump{} } // SessionRulesDetails represents the VPP binary API message 'session_rules_details'. -// Generated from '/usr/share/vpp/api/session.api.json', line 1147: +// Generated from 'session.api.json', line 1211: // // "session_rules_details", // [ @@ -2056,12 +2179,83 @@ type SessionRulesDetails struct { func (*SessionRulesDetails) GetMessageName() string { return "session_rules_details" } -func (*SessionRulesDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SessionRulesDetails) GetCrcString() string { return "a52b0e96" } +func (*SessionRulesDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSessionRulesDetails() api.Message { return &SessionRulesDetails{} } + +/* Services */ + +type Services interface { + DumpSessionRules(*SessionRulesDump) (*SessionRulesDetails, error) + AcceptSession(*AcceptSession) (*AcceptSessionReply, error) + AppCutThroughRegistrationAdd(*AppCutThroughRegistrationAdd) (*AppCutThroughRegistrationAddReply, error) + AppNamespaceAddDel(*AppNamespaceAddDel) (*AppNamespaceAddDelReply, error) + ApplicationAttach(*ApplicationAttach) (*ApplicationAttachReply, error) + ApplicationDetach(*ApplicationDetach) (*ApplicationDetachReply, error) + ApplicationTLSCertAdd(*ApplicationTLSCertAdd) (*ApplicationTLSCertAddReply, error) + ApplicationTLSKeyAdd(*ApplicationTLSKeyAdd) (*ApplicationTLSKeyAddReply, error) + BindSock(*BindSock) (*BindSockReply, error) + BindURI(*BindURI) (*BindURIReply, error) + ConnectSession(*ConnectSession) (*ConnectSessionReply, error) + ConnectSock(*ConnectSock) (*ConnectSockReply, error) + ConnectURI(*ConnectURI) (*ConnectURIReply, error) + DisconnectSession(*DisconnectSession) (*DisconnectSessionReply, error) + MapAnotherSegment(*MapAnotherSegment) (*MapAnotherSegmentReply, error) + ResetSession(*ResetSession) (*ResetSessionReply, error) + SessionEnableDisable(*SessionEnableDisable) (*SessionEnableDisableReply, error) + SessionRuleAddDel(*SessionRuleAddDel) (*SessionRuleAddDelReply, error) + UnbindSock(*UnbindSock) (*UnbindSockReply, error) + UnbindURI(*UnbindURI) (*UnbindURIReply, error) + UnmapSegment(*UnmapSegment) (*UnmapSegmentReply, error) +} + +func init() { + api.RegisterMessage((*ApplicationAttach)(nil), "session.ApplicationAttach") + api.RegisterMessage((*ApplicationAttachReply)(nil), "session.ApplicationAttachReply") + api.RegisterMessage((*ApplicationTLSCertAdd)(nil), "session.ApplicationTLSCertAdd") + api.RegisterMessage((*ApplicationTLSCertAddReply)(nil), "session.ApplicationTLSCertAddReply") + api.RegisterMessage((*ApplicationTLSKeyAdd)(nil), "session.ApplicationTLSKeyAdd") + api.RegisterMessage((*ApplicationTLSKeyAddReply)(nil), "session.ApplicationTLSKeyAddReply") + api.RegisterMessage((*ApplicationDetach)(nil), "session.ApplicationDetach") + api.RegisterMessage((*ApplicationDetachReply)(nil), "session.ApplicationDetachReply") + api.RegisterMessage((*MapAnotherSegment)(nil), "session.MapAnotherSegment") + api.RegisterMessage((*MapAnotherSegmentReply)(nil), "session.MapAnotherSegmentReply") + api.RegisterMessage((*UnmapSegment)(nil), "session.UnmapSegment") + api.RegisterMessage((*UnmapSegmentReply)(nil), "session.UnmapSegmentReply") + api.RegisterMessage((*BindURI)(nil), "session.BindURI") + api.RegisterMessage((*BindURIReply)(nil), "session.BindURIReply") + api.RegisterMessage((*UnbindURI)(nil), "session.UnbindURI") + api.RegisterMessage((*UnbindURIReply)(nil), "session.UnbindURIReply") + api.RegisterMessage((*ConnectURI)(nil), "session.ConnectURI") + api.RegisterMessage((*ConnectURIReply)(nil), "session.ConnectURIReply") + api.RegisterMessage((*AcceptSession)(nil), "session.AcceptSession") + api.RegisterMessage((*AcceptSessionReply)(nil), "session.AcceptSessionReply") + api.RegisterMessage((*DisconnectSession)(nil), "session.DisconnectSession") + api.RegisterMessage((*DisconnectSessionReply)(nil), "session.DisconnectSessionReply") + api.RegisterMessage((*ResetSession)(nil), "session.ResetSession") + api.RegisterMessage((*ResetSessionReply)(nil), "session.ResetSessionReply") + api.RegisterMessage((*BindSock)(nil), "session.BindSock") + api.RegisterMessage((*UnbindSock)(nil), "session.UnbindSock") + api.RegisterMessage((*UnbindSockReply)(nil), "session.UnbindSockReply") + api.RegisterMessage((*ConnectSock)(nil), "session.ConnectSock") + api.RegisterMessage((*ConnectSockReply)(nil), "session.ConnectSockReply") + api.RegisterMessage((*BindSockReply)(nil), "session.BindSockReply") + api.RegisterMessage((*ConnectSession)(nil), "session.ConnectSession") + api.RegisterMessage((*ConnectSessionReply)(nil), "session.ConnectSessionReply") + api.RegisterMessage((*AppCutThroughRegistrationAdd)(nil), "session.AppCutThroughRegistrationAdd") + api.RegisterMessage((*AppCutThroughRegistrationAddReply)(nil), "session.AppCutThroughRegistrationAddReply") + api.RegisterMessage((*SessionEnableDisable)(nil), "session.SessionEnableDisable") + api.RegisterMessage((*SessionEnableDisableReply)(nil), "session.SessionEnableDisableReply") + api.RegisterMessage((*AppNamespaceAddDel)(nil), "session.AppNamespaceAddDel") + api.RegisterMessage((*AppNamespaceAddDelReply)(nil), "session.AppNamespaceAddDelReply") + api.RegisterMessage((*SessionRuleAddDel)(nil), "session.SessionRuleAddDel") + api.RegisterMessage((*SessionRuleAddDelReply)(nil), "session.SessionRuleAddDelReply") + api.RegisterMessage((*SessionRulesDump)(nil), "session.SessionRulesDump") + api.RegisterMessage((*SessionRulesDetails)(nil), "session.SessionRulesDetails") +} diff --git a/plugins/vpp/binapi/sr/pkgreflect.go b/plugins/vpp/binapi/sr/pkgreflect.go index 95792a035d..02983ddb0b 100644 --- a/plugins/vpp/binapi/sr/pkgreflect.go +++ b/plugins/vpp/binapi/sr/pkgreflect.go @@ -5,11 +5,14 @@ package sr import "reflect" var Types = map[string]reflect.Type{ + "Services": reflect.TypeOf((*Services)(nil)).Elem(), "SrIP6Address": reflect.TypeOf((*SrIP6Address)(nil)).Elem(), "SrLocalsidAddDel": reflect.TypeOf((*SrLocalsidAddDel)(nil)).Elem(), "SrLocalsidAddDelReply": reflect.TypeOf((*SrLocalsidAddDelReply)(nil)).Elem(), "SrLocalsidsDetails": reflect.TypeOf((*SrLocalsidsDetails)(nil)).Elem(), "SrLocalsidsDump": reflect.TypeOf((*SrLocalsidsDump)(nil)).Elem(), + "SrPoliciesDetails": reflect.TypeOf((*SrPoliciesDetails)(nil)).Elem(), + "SrPoliciesDump": reflect.TypeOf((*SrPoliciesDump)(nil)).Elem(), "SrPolicyAdd": reflect.TypeOf((*SrPolicyAdd)(nil)).Elem(), "SrPolicyAddReply": reflect.TypeOf((*SrPolicyAddReply)(nil)).Elem(), "SrPolicyDel": reflect.TypeOf((*SrPolicyDel)(nil)).Elem(), @@ -20,6 +23,10 @@ var Types = map[string]reflect.Type{ "SrSetEncapSourceReply": reflect.TypeOf((*SrSetEncapSourceReply)(nil)).Elem(), "SrSteeringAddDel": reflect.TypeOf((*SrSteeringAddDel)(nil)).Elem(), "SrSteeringAddDelReply": reflect.TypeOf((*SrSteeringAddDelReply)(nil)).Elem(), + "SrSteeringPolDetails": reflect.TypeOf((*SrSteeringPolDetails)(nil)).Elem(), + "SrSteeringPolDump": reflect.TypeOf((*SrSteeringPolDump)(nil)).Elem(), + "Srv6Sid": reflect.TypeOf((*Srv6Sid)(nil)).Elem(), + "Srv6SidList": reflect.TypeOf((*Srv6SidList)(nil)).Elem(), } var Functions = map[string]reflect.Value{ @@ -27,6 +34,8 @@ var Functions = map[string]reflect.Value{ "NewSrLocalsidAddDelReply": reflect.ValueOf(NewSrLocalsidAddDelReply), "NewSrLocalsidsDetails": reflect.ValueOf(NewSrLocalsidsDetails), "NewSrLocalsidsDump": reflect.ValueOf(NewSrLocalsidsDump), + "NewSrPoliciesDetails": reflect.ValueOf(NewSrPoliciesDetails), + "NewSrPoliciesDump": reflect.ValueOf(NewSrPoliciesDump), "NewSrPolicyAdd": reflect.ValueOf(NewSrPolicyAdd), "NewSrPolicyAddReply": reflect.ValueOf(NewSrPolicyAddReply), "NewSrPolicyDel": reflect.ValueOf(NewSrPolicyDel), @@ -37,6 +46,8 @@ var Functions = map[string]reflect.Value{ "NewSrSetEncapSourceReply": reflect.ValueOf(NewSrSetEncapSourceReply), "NewSrSteeringAddDel": reflect.ValueOf(NewSrSteeringAddDel), "NewSrSteeringAddDelReply": reflect.ValueOf(NewSrSteeringAddDelReply), + "NewSrSteeringPolDetails": reflect.ValueOf(NewSrSteeringPolDetails), + "NewSrSteeringPolDump": reflect.ValueOf(NewSrSteeringPolDump), } var Variables = map[string]reflect.Value{ diff --git a/plugins/vpp/binapi/sr/sr.go b/plugins/vpp/binapi/sr/sr.ba.go similarity index 59% rename from plugins/vpp/binapi/sr/sr.go rename to plugins/vpp/binapi/sr/sr.ba.go index 127f163cb4..81b4f6c721 100644 --- a/plugins/vpp/binapi/sr/sr.go +++ b/plugins/vpp/binapi/sr/sr.ba.go @@ -1,12 +1,89 @@ -// Code generated by govpp binapi-generator DO NOT EDIT. -// Package sr represents the VPP binary API of the 'sr' VPP module. -// Generated from '/usr/share/vpp/api/sr.api.json' +// Code generated by GoVPP binapi-generator. DO NOT EDIT. +// source: /usr/share/vpp/api/sr.api.json + +/* +Package sr is a generated VPP binary API of the 'sr' VPP module. + +It is generated from this file: + sr.api.json + +It contains these VPP binary API objects: + 18 messages + 3 types + 9 services +*/ package sr import "git.fd.io/govpp.git/api" +import "github.com/lunixbochs/struc" +import "bytes" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = struc.Pack +var _ = bytes.NewBuffer + +/* Types */ + +// Srv6Sid represents the VPP binary API type 'srv6_sid'. +// Generated from 'sr.api.json', line 577: +// +// "srv6_sid", +// [ +// "u8", +// "addr", +// 16 +// ], +// { +// "crc": "0x6ee67284" +// } +// +type Srv6Sid struct { + Addr []byte `struc:"[16]byte"` +} + +func (*Srv6Sid) GetTypeName() string { + return "srv6_sid" +} +func (*Srv6Sid) GetCrcString() string { + return "6ee67284" +} + +// Srv6SidList represents the VPP binary API type 'srv6_sid_list'. +// Generated from 'sr.api.json', line 588: +// +// "srv6_sid_list", +// [ +// "u8", +// "num_sids" +// ], +// [ +// "u32", +// "weight" +// ], +// [ +// "vl_api_srv6_sid_t", +// "sids", +// 16 +// ], +// { +// "crc": "0x4066af74" +// } +// +type Srv6SidList struct { + NumSids uint8 `struc:"sizeof=Sids"` + Weight uint32 + Sids []Srv6Sid +} + +func (*Srv6SidList) GetTypeName() string { + return "srv6_sid_list" +} +func (*Srv6SidList) GetCrcString() string { + return "4066af74" +} -// SrIP6Address represents the VPP binary API data type 'sr_ip6_address'. -// Generated from '/usr/share/vpp/api/sr.api.json', line 455: +// SrIP6Address represents the VPP binary API type 'sr_ip6_address'. +// Generated from 'sr.api.json', line 607: // // "sr_ip6_address", // [ @@ -29,8 +106,10 @@ func (*SrIP6Address) GetCrcString() string { return "bea0c5e6" } +/* Messages */ + // SrLocalsidAddDel represents the VPP binary API message 'sr_localsid_add_del'. -// Generated from '/usr/share/vpp/api/sr.api.json', line 4: +// Generated from 'sr.api.json', line 4: // // "sr_localsid_add_del", // [ @@ -50,9 +129,8 @@ func (*SrIP6Address) GetCrcString() string { // "is_del" // ], // [ -// "u8", -// "localsid_addr", -// 16 +// "vl_api_srv6_sid_t", +// "localsid" // ], // [ // "u8", @@ -76,39 +154,45 @@ func (*SrIP6Address) GetCrcString() string { // ], // [ // "u8", -// "nh_addr", +// "nh_addr6", // 16 // ], +// [ +// "u8", +// "nh_addr4", +// 4 +// ], // { -// "crc": "0xa833a891" +// "crc": "0x20d478a0" // } // type SrLocalsidAddDel struct { - IsDel uint8 - LocalsidAddr []byte `struc:"[16]byte"` - EndPsp uint8 - Behavior uint8 - SwIfIndex uint32 - VlanIndex uint32 - FibTable uint32 - NhAddr []byte `struc:"[16]byte"` + IsDel uint8 + Localsid Srv6Sid + EndPsp uint8 + Behavior uint8 + SwIfIndex uint32 + VlanIndex uint32 + FibTable uint32 + NhAddr6 []byte `struc:"[16]byte"` + NhAddr4 []byte `struc:"[4]byte"` } func (*SrLocalsidAddDel) GetMessageName() string { return "sr_localsid_add_del" } +func (*SrLocalsidAddDel) GetCrcString() string { + return "20d478a0" +} func (*SrLocalsidAddDel) GetMessageType() api.MessageType { return api.RequestMessage } -func (*SrLocalsidAddDel) GetCrcString() string { - return "a833a891" -} func NewSrLocalsidAddDel() api.Message { return &SrLocalsidAddDel{} } // SrLocalsidAddDelReply represents the VPP binary API message 'sr_localsid_add_del_reply'. -// Generated from '/usr/share/vpp/api/sr.api.json', line 56: +// Generated from 'sr.api.json', line 60: // // "sr_localsid_add_del_reply", // [ @@ -134,18 +218,18 @@ type SrLocalsidAddDelReply struct { func (*SrLocalsidAddDelReply) GetMessageName() string { return "sr_localsid_add_del_reply" } -func (*SrLocalsidAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SrLocalsidAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*SrLocalsidAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSrLocalsidAddDelReply() api.Message { return &SrLocalsidAddDelReply{} } // SrPolicyAdd represents the VPP binary API message 'sr_policy_add'. -// Generated from '/usr/share/vpp/api/sr.api.json', line 74: +// Generated from 'sr.api.json', line 78: // // "sr_policy_add", // [ @@ -182,44 +266,37 @@ func NewSrLocalsidAddDelReply() api.Message { // "fib_table" // ], // [ -// "u8", -// "n_segments" -// ], -// [ -// "vl_api_sr_ip6_address_t", -// "segments", -// 0, -// "n_segments" +// "vl_api_srv6_sid_list_t", +// "sids" // ], // { -// "crc": "0x6869ac7f" +// "crc": "0xa1676c1f" // } // type SrPolicyAdd struct { - BsidAddr []byte `struc:"[16]byte"` - Weight uint32 - IsEncap uint8 - Type uint8 - FibTable uint32 - NSegments uint8 `struc:"sizeof=Segments"` - Segments []SrIP6Address + BsidAddr []byte `struc:"[16]byte"` + Weight uint32 + IsEncap uint8 + Type uint8 + FibTable uint32 + Sids Srv6SidList } func (*SrPolicyAdd) GetMessageName() string { return "sr_policy_add" } +func (*SrPolicyAdd) GetCrcString() string { + return "a1676c1f" +} func (*SrPolicyAdd) GetMessageType() api.MessageType { return api.RequestMessage } -func (*SrPolicyAdd) GetCrcString() string { - return "6869ac7f" -} func NewSrPolicyAdd() api.Message { return &SrPolicyAdd{} } // SrPolicyAddReply represents the VPP binary API message 'sr_policy_add_reply'. -// Generated from '/usr/share/vpp/api/sr.api.json', line 123: +// Generated from 'sr.api.json', line 121: // // "sr_policy_add_reply", // [ @@ -245,18 +322,18 @@ type SrPolicyAddReply struct { func (*SrPolicyAddReply) GetMessageName() string { return "sr_policy_add_reply" } -func (*SrPolicyAddReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SrPolicyAddReply) GetCrcString() string { return "e8d4e804" } +func (*SrPolicyAddReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSrPolicyAddReply() api.Message { return &SrPolicyAddReply{} } // SrPolicyMod represents the VPP binary API message 'sr_policy_mod'. -// Generated from '/usr/share/vpp/api/sr.api.json', line 141: +// Generated from 'sr.api.json', line 139: // // "sr_policy_mod", // [ @@ -297,17 +374,11 @@ func NewSrPolicyAddReply() api.Message { // "weight" // ], // [ -// "u8", -// "n_segments" -// ], -// [ -// "vl_api_sr_ip6_address_t", -// "segments", -// 0, -// "n_segments" +// "vl_api_srv6_sid_list_t", +// "sids" // ], // { -// "crc": "0xad91f4b2" +// "crc": "0x51252136" // } // type SrPolicyMod struct { @@ -317,25 +388,24 @@ type SrPolicyMod struct { Operation uint8 SlIndex uint32 Weight uint32 - NSegments uint8 `struc:"sizeof=Segments"` - Segments []SrIP6Address + Sids Srv6SidList } func (*SrPolicyMod) GetMessageName() string { return "sr_policy_mod" } +func (*SrPolicyMod) GetCrcString() string { + return "51252136" +} func (*SrPolicyMod) GetMessageType() api.MessageType { return api.RequestMessage } -func (*SrPolicyMod) GetCrcString() string { - return "ad91f4b2" -} func NewSrPolicyMod() api.Message { return &SrPolicyMod{} } // SrPolicyModReply represents the VPP binary API message 'sr_policy_mod_reply'. -// Generated from '/usr/share/vpp/api/sr.api.json', line 194: +// Generated from 'sr.api.json', line 186: // // "sr_policy_mod_reply", // [ @@ -361,18 +431,18 @@ type SrPolicyModReply struct { func (*SrPolicyModReply) GetMessageName() string { return "sr_policy_mod_reply" } -func (*SrPolicyModReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SrPolicyModReply) GetCrcString() string { return "e8d4e804" } +func (*SrPolicyModReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSrPolicyModReply() api.Message { return &SrPolicyModReply{} } // SrPolicyDel represents the VPP binary API message 'sr_policy_del'. -// Generated from '/usr/share/vpp/api/sr.api.json', line 212: +// Generated from 'sr.api.json', line 204: // // "sr_policy_del", // [ @@ -388,38 +458,37 @@ func NewSrPolicyModReply() api.Message { // "context" // ], // [ -// "u8", -// "bsid_addr", -// 16 +// "vl_api_srv6_sid_t", +// "bsid_addr" // ], // [ // "u32", // "sr_policy_index" // ], // { -// "crc": "0x0388e561" +// "crc": "0x168e1a98" // } // type SrPolicyDel struct { - BsidAddr []byte `struc:"[16]byte"` + BsidAddr Srv6Sid SrPolicyIndex uint32 } func (*SrPolicyDel) GetMessageName() string { return "sr_policy_del" } +func (*SrPolicyDel) GetCrcString() string { + return "168e1a98" +} func (*SrPolicyDel) GetMessageType() api.MessageType { return api.RequestMessage } -func (*SrPolicyDel) GetCrcString() string { - return "0388e561" -} func NewSrPolicyDel() api.Message { return &SrPolicyDel{} } // SrPolicyDelReply represents the VPP binary API message 'sr_policy_del_reply'. -// Generated from '/usr/share/vpp/api/sr.api.json', line 239: +// Generated from 'sr.api.json', line 230: // // "sr_policy_del_reply", // [ @@ -445,18 +514,18 @@ type SrPolicyDelReply struct { func (*SrPolicyDelReply) GetMessageName() string { return "sr_policy_del_reply" } -func (*SrPolicyDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SrPolicyDelReply) GetCrcString() string { return "e8d4e804" } +func (*SrPolicyDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSrPolicyDelReply() api.Message { return &SrPolicyDelReply{} } // SrSetEncapSource represents the VPP binary API message 'sr_set_encap_source'. -// Generated from '/usr/share/vpp/api/sr.api.json', line 257: +// Generated from 'sr.api.json', line 248: // // "sr_set_encap_source", // [ @@ -487,18 +556,18 @@ type SrSetEncapSource struct { func (*SrSetEncapSource) GetMessageName() string { return "sr_set_encap_source" } -func (*SrSetEncapSource) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SrSetEncapSource) GetCrcString() string { return "d05bb4de" } +func (*SrSetEncapSource) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSrSetEncapSource() api.Message { return &SrSetEncapSource{} } // SrSetEncapSourceReply represents the VPP binary API message 'sr_set_encap_source_reply'. -// Generated from '/usr/share/vpp/api/sr.api.json', line 280: +// Generated from 'sr.api.json', line 271: // // "sr_set_encap_source_reply", // [ @@ -524,18 +593,18 @@ type SrSetEncapSourceReply struct { func (*SrSetEncapSourceReply) GetMessageName() string { return "sr_set_encap_source_reply" } -func (*SrSetEncapSourceReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SrSetEncapSourceReply) GetCrcString() string { return "e8d4e804" } +func (*SrSetEncapSourceReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSrSetEncapSourceReply() api.Message { return &SrSetEncapSourceReply{} } // SrSteeringAddDel represents the VPP binary API message 'sr_steering_add_del'. -// Generated from '/usr/share/vpp/api/sr.api.json', line 298: +// Generated from 'sr.api.json', line 289: // // "sr_steering_add_del", // [ @@ -602,18 +671,18 @@ type SrSteeringAddDel struct { func (*SrSteeringAddDel) GetMessageName() string { return "sr_steering_add_del" } -func (*SrSteeringAddDel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SrSteeringAddDel) GetCrcString() string { return "28b5dcab" } +func (*SrSteeringAddDel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSrSteeringAddDel() api.Message { return &SrSteeringAddDel{} } // SrSteeringAddDelReply represents the VPP binary API message 'sr_steering_add_del_reply'. -// Generated from '/usr/share/vpp/api/sr.api.json', line 350: +// Generated from 'sr.api.json', line 341: // // "sr_steering_add_del_reply", // [ @@ -639,18 +708,18 @@ type SrSteeringAddDelReply struct { func (*SrSteeringAddDelReply) GetMessageName() string { return "sr_steering_add_del_reply" } -func (*SrSteeringAddDelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SrSteeringAddDelReply) GetCrcString() string { return "e8d4e804" } +func (*SrSteeringAddDelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSrSteeringAddDelReply() api.Message { return &SrSteeringAddDelReply{} } // SrLocalsidsDump represents the VPP binary API message 'sr_localsids_dump'. -// Generated from '/usr/share/vpp/api/sr.api.json', line 368: +// Generated from 'sr.api.json', line 359: // // "sr_localsids_dump", // [ @@ -669,24 +738,23 @@ func NewSrSteeringAddDelReply() api.Message { // "crc": "0x51077d14" // } // -type SrLocalsidsDump struct { -} +type SrLocalsidsDump struct{} func (*SrLocalsidsDump) GetMessageName() string { return "sr_localsids_dump" } -func (*SrLocalsidsDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SrLocalsidsDump) GetCrcString() string { return "51077d14" } +func (*SrLocalsidsDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSrLocalsidsDump() api.Message { return &SrLocalsidsDump{} } // SrLocalsidsDetails represents the VPP binary API message 'sr_localsids_details'. -// Generated from '/usr/share/vpp/api/sr.api.json', line 386: +// Generated from 'sr.api.json', line 377: // // "sr_localsids_details", // [ @@ -698,9 +766,8 @@ func NewSrLocalsidsDump() api.Message { // "context" // ], // [ -// "u8", -// "address", -// 16 +// "vl_api_srv6_sid_t", +// "addr" // ], // [ // "u8", @@ -715,36 +782,279 @@ func NewSrLocalsidsDump() api.Message { // "fib_table" // ], // [ +// "u32", +// "vlan_index" +// ], +// [ // "u8", -// "xconnect_next_hop", +// "xconnect_nh_addr6", // 16 // ], // [ +// "u8", +// "xconnect_nh_addr4", +// 4 +// ], +// [ // "u32", // "xconnect_iface_or_vrf_table" // ], // { -// "crc": "0xb6556a9c" +// "crc": "0x7ff35765" // } // type SrLocalsidsDetails struct { - Address []byte `struc:"[16]byte"` + Addr Srv6Sid EndPsp uint8 Behavior uint16 FibTable uint32 - XconnectNextHop []byte `struc:"[16]byte"` + VlanIndex uint32 + XconnectNhAddr6 []byte `struc:"[16]byte"` + XconnectNhAddr4 []byte `struc:"[4]byte"` XconnectIfaceOrVrfTable uint32 } func (*SrLocalsidsDetails) GetMessageName() string { return "sr_localsids_details" } +func (*SrLocalsidsDetails) GetCrcString() string { + return "7ff35765" +} func (*SrLocalsidsDetails) GetMessageType() api.MessageType { return api.ReplyMessage } -func (*SrLocalsidsDetails) GetCrcString() string { - return "b6556a9c" -} func NewSrLocalsidsDetails() api.Message { return &SrLocalsidsDetails{} } + +// SrPoliciesDump represents the VPP binary API message 'sr_policies_dump'. +// Generated from 'sr.api.json', line 425: +// +// "sr_policies_dump", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "client_index" +// ], +// [ +// "u32", +// "context" +// ], +// { +// "crc": "0x51077d14" +// } +// +type SrPoliciesDump struct{} + +func (*SrPoliciesDump) GetMessageName() string { + return "sr_policies_dump" +} +func (*SrPoliciesDump) GetCrcString() string { + return "51077d14" +} +func (*SrPoliciesDump) GetMessageType() api.MessageType { + return api.RequestMessage +} +func NewSrPoliciesDump() api.Message { + return &SrPoliciesDump{} +} + +// SrPoliciesDetails represents the VPP binary API message 'sr_policies_details'. +// Generated from 'sr.api.json', line 443: +// +// "sr_policies_details", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "vl_api_srv6_sid_t", +// "bsid" +// ], +// [ +// "u8", +// "type" +// ], +// [ +// "u8", +// "is_encap" +// ], +// [ +// "u32", +// "fib_table" +// ], +// [ +// "u8", +// "num_sid_lists" +// ], +// [ +// "vl_api_srv6_sid_list_t", +// "sid_lists", +// 0, +// "num_sid_lists" +// ], +// { +// "crc": "0xae838a76" +// } +// +type SrPoliciesDetails struct { + Bsid Srv6Sid + Type uint8 + IsEncap uint8 + FibTable uint32 + NumSidLists uint8 `struc:"sizeof=SidLists"` + SidLists []Srv6SidList +} + +func (*SrPoliciesDetails) GetMessageName() string { + return "sr_policies_details" +} +func (*SrPoliciesDetails) GetCrcString() string { + return "ae838a76" +} +func (*SrPoliciesDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} +func NewSrPoliciesDetails() api.Message { + return &SrPoliciesDetails{} +} + +// SrSteeringPolDump represents the VPP binary API message 'sr_steering_pol_dump'. +// Generated from 'sr.api.json', line 483: +// +// "sr_steering_pol_dump", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "client_index" +// ], +// [ +// "u32", +// "context" +// ], +// { +// "crc": "0x51077d14" +// } +// +type SrSteeringPolDump struct{} + +func (*SrSteeringPolDump) GetMessageName() string { + return "sr_steering_pol_dump" +} +func (*SrSteeringPolDump) GetCrcString() string { + return "51077d14" +} +func (*SrSteeringPolDump) GetMessageType() api.MessageType { + return api.RequestMessage +} +func NewSrSteeringPolDump() api.Message { + return &SrSteeringPolDump{} +} + +// SrSteeringPolDetails represents the VPP binary API message 'sr_steering_pol_details'. +// Generated from 'sr.api.json', line 501: +// +// "sr_steering_pol_details", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "u8", +// "traffic_type" +// ], +// [ +// "u32", +// "fib_table" +// ], +// [ +// "u8", +// "prefix_addr", +// 16 +// ], +// [ +// "u32", +// "mask_width" +// ], +// [ +// "u32", +// "sw_if_index" +// ], +// [ +// "vl_api_srv6_sid_t", +// "bsid" +// ], +// { +// "crc": "0x1c756f85" +// } +// +type SrSteeringPolDetails struct { + TrafficType uint8 + FibTable uint32 + PrefixAddr []byte `struc:"[16]byte"` + MaskWidth uint32 + SwIfIndex uint32 + Bsid Srv6Sid +} + +func (*SrSteeringPolDetails) GetMessageName() string { + return "sr_steering_pol_details" +} +func (*SrSteeringPolDetails) GetCrcString() string { + return "1c756f85" +} +func (*SrSteeringPolDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} +func NewSrSteeringPolDetails() api.Message { + return &SrSteeringPolDetails{} +} + +/* Services */ + +type Services interface { + DumpSrLocalsids(*SrLocalsidsDump) (*SrLocalsidsDetails, error) + DumpSrPolicies(*SrPoliciesDump) (*SrPoliciesDetails, error) + DumpSrSteeringPol(*SrSteeringPolDump) (*SrSteeringPolDetails, error) + SrLocalsidAddDel(*SrLocalsidAddDel) (*SrLocalsidAddDelReply, error) + SrPolicyAdd(*SrPolicyAdd) (*SrPolicyAddReply, error) + SrPolicyDel(*SrPolicyDel) (*SrPolicyDelReply, error) + SrPolicyMod(*SrPolicyMod) (*SrPolicyModReply, error) + SrSetEncapSource(*SrSetEncapSource) (*SrSetEncapSourceReply, error) + SrSteeringAddDel(*SrSteeringAddDel) (*SrSteeringAddDelReply, error) +} + +func init() { + api.RegisterMessage((*SrLocalsidAddDel)(nil), "sr.SrLocalsidAddDel") + api.RegisterMessage((*SrLocalsidAddDelReply)(nil), "sr.SrLocalsidAddDelReply") + api.RegisterMessage((*SrPolicyAdd)(nil), "sr.SrPolicyAdd") + api.RegisterMessage((*SrPolicyAddReply)(nil), "sr.SrPolicyAddReply") + api.RegisterMessage((*SrPolicyMod)(nil), "sr.SrPolicyMod") + api.RegisterMessage((*SrPolicyModReply)(nil), "sr.SrPolicyModReply") + api.RegisterMessage((*SrPolicyDel)(nil), "sr.SrPolicyDel") + api.RegisterMessage((*SrPolicyDelReply)(nil), "sr.SrPolicyDelReply") + api.RegisterMessage((*SrSetEncapSource)(nil), "sr.SrSetEncapSource") + api.RegisterMessage((*SrSetEncapSourceReply)(nil), "sr.SrSetEncapSourceReply") + api.RegisterMessage((*SrSteeringAddDel)(nil), "sr.SrSteeringAddDel") + api.RegisterMessage((*SrSteeringAddDelReply)(nil), "sr.SrSteeringAddDelReply") + api.RegisterMessage((*SrLocalsidsDump)(nil), "sr.SrLocalsidsDump") + api.RegisterMessage((*SrLocalsidsDetails)(nil), "sr.SrLocalsidsDetails") + api.RegisterMessage((*SrPoliciesDump)(nil), "sr.SrPoliciesDump") + api.RegisterMessage((*SrPoliciesDetails)(nil), "sr.SrPoliciesDetails") + api.RegisterMessage((*SrSteeringPolDump)(nil), "sr.SrSteeringPolDump") + api.RegisterMessage((*SrSteeringPolDetails)(nil), "sr.SrSteeringPolDetails") +} diff --git a/plugins/vpp/binapi/stats/pkgreflect.go b/plugins/vpp/binapi/stats/pkgreflect.go index cc2de7c265..fb15fcdf52 100644 --- a/plugins/vpp/binapi/stats/pkgreflect.go +++ b/plugins/vpp/binapi/stats/pkgreflect.go @@ -5,16 +5,22 @@ package stats import "reflect" var Types = map[string]reflect.Type{ + "BierNeighborCounter": reflect.TypeOf((*BierNeighborCounter)(nil)).Elem(), + "BierTableID": reflect.TypeOf((*BierTableID)(nil)).Elem(), + "FibMplsLabel": reflect.TypeOf((*FibMplsLabel)(nil)).Elem(), + "FibPath": reflect.TypeOf((*FibPath)(nil)).Elem(), "IP4FibCounter": reflect.TypeOf((*IP4FibCounter)(nil)).Elem(), "IP4MfibCounter": reflect.TypeOf((*IP4MfibCounter)(nil)).Elem(), "IP4NbrCounter": reflect.TypeOf((*IP4NbrCounter)(nil)).Elem(), "IP6FibCounter": reflect.TypeOf((*IP6FibCounter)(nil)).Elem(), "IP6MfibCounter": reflect.TypeOf((*IP6MfibCounter)(nil)).Elem(), "IP6NbrCounter": reflect.TypeOf((*IP6NbrCounter)(nil)).Elem(), + "Services": reflect.TypeOf((*Services)(nil)).Elem(), "StatsGetPollerDelay": reflect.TypeOf((*StatsGetPollerDelay)(nil)).Elem(), "StatsGetPollerDelayReply": reflect.TypeOf((*StatsGetPollerDelayReply)(nil)).Elem(), "UDPEncapCounter": reflect.TypeOf((*UDPEncapCounter)(nil)).Elem(), "VlibCounter": reflect.TypeOf((*VlibCounter)(nil)).Elem(), + "VnetBierNeighborCounters": reflect.TypeOf((*VnetBierNeighborCounters)(nil)).Elem(), "VnetCombinedCounter": reflect.TypeOf((*VnetCombinedCounter)(nil)).Elem(), "VnetGetSummaryStats": reflect.TypeOf((*VnetGetSummaryStats)(nil)).Elem(), "VnetGetSummaryStatsReply": reflect.TypeOf((*VnetGetSummaryStatsReply)(nil)).Elem(), @@ -30,6 +36,8 @@ var Types = map[string]reflect.Type{ "VnetPerInterfaceSimpleCounters": reflect.TypeOf((*VnetPerInterfaceSimpleCounters)(nil)).Elem(), "VnetSimpleCounter": reflect.TypeOf((*VnetSimpleCounter)(nil)).Elem(), "VnetUDPEncapCounters": reflect.TypeOf((*VnetUDPEncapCounters)(nil)).Elem(), + "WantBierNeighborStats": reflect.TypeOf((*WantBierNeighborStats)(nil)).Elem(), + "WantBierNeighborStatsReply": reflect.TypeOf((*WantBierNeighborStatsReply)(nil)).Elem(), "WantIP4FibStats": reflect.TypeOf((*WantIP4FibStats)(nil)).Elem(), "WantIP4FibStatsReply": reflect.TypeOf((*WantIP4FibStatsReply)(nil)).Elem(), "WantIP4MfibStats": reflect.TypeOf((*WantIP4MfibStats)(nil)).Elem(), @@ -59,6 +67,7 @@ var Types = map[string]reflect.Type{ var Functions = map[string]reflect.Value{ "NewStatsGetPollerDelay": reflect.ValueOf(NewStatsGetPollerDelay), "NewStatsGetPollerDelayReply": reflect.ValueOf(NewStatsGetPollerDelayReply), + "NewVnetBierNeighborCounters": reflect.ValueOf(NewVnetBierNeighborCounters), "NewVnetGetSummaryStats": reflect.ValueOf(NewVnetGetSummaryStats), "NewVnetGetSummaryStatsReply": reflect.ValueOf(NewVnetGetSummaryStatsReply), "NewVnetIP4FibCounters": reflect.ValueOf(NewVnetIP4FibCounters), @@ -72,6 +81,8 @@ var Functions = map[string]reflect.Value{ "NewVnetPerInterfaceCombinedCounters": reflect.ValueOf(NewVnetPerInterfaceCombinedCounters), "NewVnetPerInterfaceSimpleCounters": reflect.ValueOf(NewVnetPerInterfaceSimpleCounters), "NewVnetUDPEncapCounters": reflect.ValueOf(NewVnetUDPEncapCounters), + "NewWantBierNeighborStats": reflect.ValueOf(NewWantBierNeighborStats), + "NewWantBierNeighborStatsReply": reflect.ValueOf(NewWantBierNeighborStatsReply), "NewWantIP4FibStats": reflect.ValueOf(NewWantIP4FibStats), "NewWantIP4FibStatsReply": reflect.ValueOf(NewWantIP4FibStatsReply), "NewWantIP4MfibStats": reflect.ValueOf(NewWantIP4MfibStats), diff --git a/plugins/vpp/binapi/stats/stats.go b/plugins/vpp/binapi/stats/stats.ba.go similarity index 74% rename from plugins/vpp/binapi/stats/stats.go rename to plugins/vpp/binapi/stats/stats.ba.go index 658b7d2853..1826493e3c 100644 --- a/plugins/vpp/binapi/stats/stats.go +++ b/plugins/vpp/binapi/stats/stats.ba.go @@ -1,12 +1,31 @@ -// Code generated by govpp binapi-generator DO NOT EDIT. -// Package stats represents the VPP binary API of the 'stats' VPP module. -// Generated from '/usr/share/vpp/api/stats.api.json' +// Code generated by GoVPP binapi-generator. DO NOT EDIT. +// source: /usr/share/vpp/api/stats.api.json + +/* +Package stats is a generated VPP binary API of the 'stats' VPP module. + +It is generated from this file: + stats.api.json + +It contains these VPP binary API objects: + 42 messages + 14 types + 15 services +*/ package stats import "git.fd.io/govpp.git/api" +import "github.com/lunixbochs/struc" +import "bytes" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = struc.Pack +var _ = bytes.NewBuffer -// VlibCounter represents the VPP binary API data type 'vlib_counter'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 1004: +/* Types */ + +// VlibCounter represents the VPP binary API type 'vlib_counter'. +// Generated from 'stats.api.json', line 1078: // // "vlib_counter", // [ @@ -33,8 +52,8 @@ func (*VlibCounter) GetCrcString() string { return "ce2325a2" } -// VnetCombinedCounter represents the VPP binary API data type 'vnet_combined_counter'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 1018: +// VnetCombinedCounter represents the VPP binary API type 'vnet_combined_counter'. +// Generated from 'stats.api.json', line 1092: // // "vnet_combined_counter", // [ @@ -136,8 +155,8 @@ func (*VnetCombinedCounter) GetCrcString() string { return "20905ca4" } -// VnetSimpleCounter represents the VPP binary API data type 'vnet_simple_counter'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 1092: +// VnetSimpleCounter represents the VPP binary API type 'vnet_simple_counter'. +// Generated from 'stats.api.json', line 1166: // // "vnet_simple_counter", // [ @@ -204,8 +223,199 @@ func (*VnetSimpleCounter) GetCrcString() string { return "8bd65e2d" } -// IP4FibCounter represents the VPP binary API data type 'ip4_fib_counter'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 1138: +// FibMplsLabel represents the VPP binary API type 'fib_mpls_label'. +// Generated from 'stats.api.json', line 1212: +// +// "fib_mpls_label", +// [ +// "u8", +// "is_uniform" +// ], +// [ +// "u32", +// "label" +// ], +// [ +// "u8", +// "ttl" +// ], +// [ +// "u8", +// "exp" +// ], +// { +// "crc": "0xc93bf35c" +// } +// +type FibMplsLabel struct { + IsUniform uint8 + Label uint32 + TTL uint8 + Exp uint8 +} + +func (*FibMplsLabel) GetTypeName() string { + return "fib_mpls_label" +} +func (*FibMplsLabel) GetCrcString() string { + return "c93bf35c" +} + +// FibPath represents the VPP binary API type 'fib_path'. +// Generated from 'stats.api.json', line 1234: +// +// "fib_path", +// [ +// "u32", +// "sw_if_index" +// ], +// [ +// "u32", +// "table_id" +// ], +// [ +// "u8", +// "weight" +// ], +// [ +// "u8", +// "preference" +// ], +// [ +// "u8", +// "is_local" +// ], +// [ +// "u8", +// "is_drop" +// ], +// [ +// "u8", +// "is_udp_encap" +// ], +// [ +// "u8", +// "is_unreach" +// ], +// [ +// "u8", +// "is_prohibit" +// ], +// [ +// "u8", +// "is_resolve_host" +// ], +// [ +// "u8", +// "is_resolve_attached" +// ], +// [ +// "u8", +// "is_dvr" +// ], +// [ +// "u8", +// "is_source_lookup" +// ], +// [ +// "u8", +// "afi" +// ], +// [ +// "u8", +// "next_hop", +// 16 +// ], +// [ +// "u32", +// "next_hop_id" +// ], +// [ +// "u32", +// "rpf_id" +// ], +// [ +// "u32", +// "via_label" +// ], +// [ +// "u8", +// "n_labels" +// ], +// [ +// "vl_api_fib_mpls_label_t", +// "label_stack", +// 16 +// ], +// { +// "crc": "0xabe483ef" +// } +// +type FibPath struct { + SwIfIndex uint32 + TableID uint32 + Weight uint8 + Preference uint8 + IsLocal uint8 + IsDrop uint8 + IsUDPEncap uint8 + IsUnreach uint8 + IsProhibit uint8 + IsResolveHost uint8 + IsResolveAttached uint8 + IsDvr uint8 + IsSourceLookup uint8 + Afi uint8 + NextHop []byte `struc:"[16]byte"` + NextHopID uint32 + RpfID uint32 + ViaLabel uint32 + NLabels uint8 + LabelStack []FibMplsLabel `struc:"[16]FibMplsLabel"` +} + +func (*FibPath) GetTypeName() string { + return "fib_path" +} +func (*FibPath) GetCrcString() string { + return "abe483ef" +} + +// BierTableID represents the VPP binary API type 'bier_table_id'. +// Generated from 'stats.api.json', line 1322: +// +// "bier_table_id", +// [ +// "u8", +// "bt_set" +// ], +// [ +// "u8", +// "bt_sub_domain" +// ], +// [ +// "u8", +// "bt_hdr_len_id" +// ], +// { +// "crc": "0x435c691d" +// } +// +type BierTableID struct { + BtSet uint8 + BtSubDomain uint8 + BtHdrLenID uint8 +} + +func (*BierTableID) GetTypeName() string { + return "bier_table_id" +} +func (*BierTableID) GetCrcString() string { + return "435c691d" +} + +// IP4FibCounter represents the VPP binary API type 'ip4_fib_counter'. +// Generated from 'stats.api.json', line 1340: // // "ip4_fib_counter", // [ @@ -242,8 +452,8 @@ func (*IP4FibCounter) GetCrcString() string { return "a6ceb0c9" } -// IP4MfibCounter represents the VPP binary API data type 'ip4_mfib_counter'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 1160: +// IP4MfibCounter represents the VPP binary API type 'ip4_mfib_counter'. +// Generated from 'stats.api.json', line 1362: // // "ip4_mfib_counter", // [ @@ -287,8 +497,8 @@ func (*IP4MfibCounter) GetCrcString() string { return "2cee4721" } -// IP4NbrCounter represents the VPP binary API data type 'ip4_nbr_counter'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 1188: +// IP4NbrCounter represents the VPP binary API type 'ip4_nbr_counter'. +// Generated from 'stats.api.json', line 1390: // // "ip4_nbr_counter", // [ @@ -325,8 +535,8 @@ func (*IP4NbrCounter) GetCrcString() string { return "b9f974d6" } -// IP6FibCounter represents the VPP binary API data type 'ip6_fib_counter'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 1210: +// IP6FibCounter represents the VPP binary API type 'ip6_fib_counter'. +// Generated from 'stats.api.json', line 1412: // // "ip6_fib_counter", // [ @@ -364,8 +574,8 @@ func (*IP6FibCounter) GetCrcString() string { return "f1197efb" } -// IP6MfibCounter represents the VPP binary API data type 'ip6_mfib_counter'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 1233: +// IP6MfibCounter represents the VPP binary API type 'ip6_mfib_counter'. +// Generated from 'stats.api.json', line 1435: // // "ip6_mfib_counter", // [ @@ -409,8 +619,8 @@ func (*IP6MfibCounter) GetCrcString() string { return "90a9590e" } -// IP6NbrCounter represents the VPP binary API data type 'ip6_nbr_counter'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 1261: +// IP6NbrCounter represents the VPP binary API type 'ip6_nbr_counter'. +// Generated from 'stats.api.json', line 1463: // // "ip6_nbr_counter", // [ @@ -448,8 +658,8 @@ func (*IP6NbrCounter) GetCrcString() string { return "2d755474" } -// UDPEncapCounter represents the VPP binary API data type 'udp_encap_counter'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 1284: +// UDPEncapCounter represents the VPP binary API type 'udp_encap_counter'. +// Generated from 'stats.api.json', line 1486: // // "udp_encap_counter", // [ @@ -481,8 +691,48 @@ func (*UDPEncapCounter) GetCrcString() string { return "7107035f" } +// BierNeighborCounter represents the VPP binary API type 'bier_neighbor_counter'. +// Generated from 'stats.api.json', line 1504: +// +// "bier_neighbor_counter", +// [ +// "vl_api_bier_table_id_t", +// "tbl_id" +// ], +// [ +// "vl_api_fib_path_t", +// "path" +// ], +// [ +// "u64", +// "packets" +// ], +// [ +// "u64", +// "bytes" +// ], +// { +// "crc": "0x91fe1748" +// } +// +type BierNeighborCounter struct { + TblID BierTableID + Path FibPath + Packets uint64 + Bytes uint64 +} + +func (*BierNeighborCounter) GetTypeName() string { + return "bier_neighbor_counter" +} +func (*BierNeighborCounter) GetCrcString() string { + return "91fe1748" +} + +/* Messages */ + // WantStats represents the VPP binary API message 'want_stats'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 4: +// Generated from 'stats.api.json', line 4: // // "want_stats", // [ @@ -511,24 +761,24 @@ func (*UDPEncapCounter) GetCrcString() string { // type WantStats struct { EnableDisable uint32 - Pid uint32 + PID uint32 } func (*WantStats) GetMessageName() string { return "want_stats" } -func (*WantStats) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*WantStats) GetCrcString() string { return "476f5a08" } +func (*WantStats) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewWantStats() api.Message { return &WantStats{} } // WantStatsReply represents the VPP binary API message 'want_stats_reply'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 30: +// Generated from 'stats.api.json', line 30: // // "want_stats_reply", // [ @@ -554,18 +804,18 @@ type WantStatsReply struct { func (*WantStatsReply) GetMessageName() string { return "want_stats_reply" } -func (*WantStatsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*WantStatsReply) GetCrcString() string { return "e8d4e804" } +func (*WantStatsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewWantStatsReply() api.Message { return &WantStatsReply{} } // WantInterfaceSimpleStats represents the VPP binary API message 'want_interface_simple_stats'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 48: +// Generated from 'stats.api.json', line 48: // // "want_interface_simple_stats", // [ @@ -594,24 +844,24 @@ func NewWantStatsReply() api.Message { // type WantInterfaceSimpleStats struct { EnableDisable uint32 - Pid uint32 + PID uint32 } func (*WantInterfaceSimpleStats) GetMessageName() string { return "want_interface_simple_stats" } -func (*WantInterfaceSimpleStats) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*WantInterfaceSimpleStats) GetCrcString() string { return "476f5a08" } +func (*WantInterfaceSimpleStats) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewWantInterfaceSimpleStats() api.Message { return &WantInterfaceSimpleStats{} } // WantInterfaceSimpleStatsReply represents the VPP binary API message 'want_interface_simple_stats_reply'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 74: +// Generated from 'stats.api.json', line 74: // // "want_interface_simple_stats_reply", // [ @@ -637,18 +887,18 @@ type WantInterfaceSimpleStatsReply struct { func (*WantInterfaceSimpleStatsReply) GetMessageName() string { return "want_interface_simple_stats_reply" } -func (*WantInterfaceSimpleStatsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*WantInterfaceSimpleStatsReply) GetCrcString() string { return "e8d4e804" } +func (*WantInterfaceSimpleStatsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewWantInterfaceSimpleStatsReply() api.Message { return &WantInterfaceSimpleStatsReply{} } // WantPerInterfaceSimpleStats represents the VPP binary API message 'want_per_interface_simple_stats'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 92: +// Generated from 'stats.api.json', line 92: // // "want_per_interface_simple_stats", // [ @@ -687,7 +937,7 @@ func NewWantInterfaceSimpleStatsReply() api.Message { // type WantPerInterfaceSimpleStats struct { EnableDisable uint32 - Pid uint32 + PID uint32 Num uint32 `struc:"sizeof=SwIfs"` SwIfs []uint32 } @@ -695,18 +945,18 @@ type WantPerInterfaceSimpleStats struct { func (*WantPerInterfaceSimpleStats) GetMessageName() string { return "want_per_interface_simple_stats" } -func (*WantPerInterfaceSimpleStats) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*WantPerInterfaceSimpleStats) GetCrcString() string { return "729d04f1" } +func (*WantPerInterfaceSimpleStats) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewWantPerInterfaceSimpleStats() api.Message { return &WantPerInterfaceSimpleStats{} } // WantPerInterfaceSimpleStatsReply represents the VPP binary API message 'want_per_interface_simple_stats_reply'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 128: +// Generated from 'stats.api.json', line 128: // // "want_per_interface_simple_stats_reply", // [ @@ -732,18 +982,18 @@ type WantPerInterfaceSimpleStatsReply struct { func (*WantPerInterfaceSimpleStatsReply) GetMessageName() string { return "want_per_interface_simple_stats_reply" } -func (*WantPerInterfaceSimpleStatsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*WantPerInterfaceSimpleStatsReply) GetCrcString() string { return "e8d4e804" } +func (*WantPerInterfaceSimpleStatsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewWantPerInterfaceSimpleStatsReply() api.Message { return &WantPerInterfaceSimpleStatsReply{} } // WantInterfaceCombinedStats represents the VPP binary API message 'want_interface_combined_stats'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 146: +// Generated from 'stats.api.json', line 146: // // "want_interface_combined_stats", // [ @@ -772,24 +1022,24 @@ func NewWantPerInterfaceSimpleStatsReply() api.Message { // type WantInterfaceCombinedStats struct { EnableDisable uint32 - Pid uint32 + PID uint32 } func (*WantInterfaceCombinedStats) GetMessageName() string { return "want_interface_combined_stats" } -func (*WantInterfaceCombinedStats) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*WantInterfaceCombinedStats) GetCrcString() string { return "476f5a08" } +func (*WantInterfaceCombinedStats) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewWantInterfaceCombinedStats() api.Message { return &WantInterfaceCombinedStats{} } // WantInterfaceCombinedStatsReply represents the VPP binary API message 'want_interface_combined_stats_reply'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 172: +// Generated from 'stats.api.json', line 172: // // "want_interface_combined_stats_reply", // [ @@ -815,18 +1065,18 @@ type WantInterfaceCombinedStatsReply struct { func (*WantInterfaceCombinedStatsReply) GetMessageName() string { return "want_interface_combined_stats_reply" } -func (*WantInterfaceCombinedStatsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*WantInterfaceCombinedStatsReply) GetCrcString() string { return "e8d4e804" } +func (*WantInterfaceCombinedStatsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewWantInterfaceCombinedStatsReply() api.Message { return &WantInterfaceCombinedStatsReply{} } // WantPerInterfaceCombinedStats represents the VPP binary API message 'want_per_interface_combined_stats'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 190: +// Generated from 'stats.api.json', line 190: // // "want_per_interface_combined_stats", // [ @@ -865,7 +1115,7 @@ func NewWantInterfaceCombinedStatsReply() api.Message { // type WantPerInterfaceCombinedStats struct { EnableDisable uint32 - Pid uint32 + PID uint32 Num uint32 `struc:"sizeof=SwIfs"` SwIfs []uint32 } @@ -873,18 +1123,18 @@ type WantPerInterfaceCombinedStats struct { func (*WantPerInterfaceCombinedStats) GetMessageName() string { return "want_per_interface_combined_stats" } -func (*WantPerInterfaceCombinedStats) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*WantPerInterfaceCombinedStats) GetCrcString() string { return "729d04f1" } +func (*WantPerInterfaceCombinedStats) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewWantPerInterfaceCombinedStats() api.Message { return &WantPerInterfaceCombinedStats{} } // WantPerInterfaceCombinedStatsReply represents the VPP binary API message 'want_per_interface_combined_stats_reply'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 226: +// Generated from 'stats.api.json', line 226: // // "want_per_interface_combined_stats_reply", // [ @@ -910,18 +1160,18 @@ type WantPerInterfaceCombinedStatsReply struct { func (*WantPerInterfaceCombinedStatsReply) GetMessageName() string { return "want_per_interface_combined_stats_reply" } -func (*WantPerInterfaceCombinedStatsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*WantPerInterfaceCombinedStatsReply) GetCrcString() string { return "e8d4e804" } +func (*WantPerInterfaceCombinedStatsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewWantPerInterfaceCombinedStatsReply() api.Message { return &WantPerInterfaceCombinedStatsReply{} } // WantIP4FibStats represents the VPP binary API message 'want_ip4_fib_stats'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 244: +// Generated from 'stats.api.json', line 244: // // "want_ip4_fib_stats", // [ @@ -950,24 +1200,24 @@ func NewWantPerInterfaceCombinedStatsReply() api.Message { // type WantIP4FibStats struct { EnableDisable uint32 - Pid uint32 + PID uint32 } func (*WantIP4FibStats) GetMessageName() string { return "want_ip4_fib_stats" } -func (*WantIP4FibStats) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*WantIP4FibStats) GetCrcString() string { return "476f5a08" } +func (*WantIP4FibStats) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewWantIP4FibStats() api.Message { return &WantIP4FibStats{} } // WantIP4FibStatsReply represents the VPP binary API message 'want_ip4_fib_stats_reply'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 270: +// Generated from 'stats.api.json', line 270: // // "want_ip4_fib_stats_reply", // [ @@ -993,18 +1243,18 @@ type WantIP4FibStatsReply struct { func (*WantIP4FibStatsReply) GetMessageName() string { return "want_ip4_fib_stats_reply" } -func (*WantIP4FibStatsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*WantIP4FibStatsReply) GetCrcString() string { return "e8d4e804" } +func (*WantIP4FibStatsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewWantIP4FibStatsReply() api.Message { return &WantIP4FibStatsReply{} } // WantIP6FibStats represents the VPP binary API message 'want_ip6_fib_stats'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 288: +// Generated from 'stats.api.json', line 288: // // "want_ip6_fib_stats", // [ @@ -1033,24 +1283,24 @@ func NewWantIP4FibStatsReply() api.Message { // type WantIP6FibStats struct { EnableDisable uint32 - Pid uint32 + PID uint32 } func (*WantIP6FibStats) GetMessageName() string { return "want_ip6_fib_stats" } -func (*WantIP6FibStats) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*WantIP6FibStats) GetCrcString() string { return "476f5a08" } +func (*WantIP6FibStats) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewWantIP6FibStats() api.Message { return &WantIP6FibStats{} } // WantIP6FibStatsReply represents the VPP binary API message 'want_ip6_fib_stats_reply'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 314: +// Generated from 'stats.api.json', line 314: // // "want_ip6_fib_stats_reply", // [ @@ -1076,18 +1326,18 @@ type WantIP6FibStatsReply struct { func (*WantIP6FibStatsReply) GetMessageName() string { return "want_ip6_fib_stats_reply" } -func (*WantIP6FibStatsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*WantIP6FibStatsReply) GetCrcString() string { return "e8d4e804" } +func (*WantIP6FibStatsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewWantIP6FibStatsReply() api.Message { return &WantIP6FibStatsReply{} } // WantIP4MfibStats represents the VPP binary API message 'want_ip4_mfib_stats'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 332: +// Generated from 'stats.api.json', line 332: // // "want_ip4_mfib_stats", // [ @@ -1116,24 +1366,24 @@ func NewWantIP6FibStatsReply() api.Message { // type WantIP4MfibStats struct { EnableDisable uint32 - Pid uint32 + PID uint32 } func (*WantIP4MfibStats) GetMessageName() string { return "want_ip4_mfib_stats" } -func (*WantIP4MfibStats) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*WantIP4MfibStats) GetCrcString() string { return "476f5a08" } +func (*WantIP4MfibStats) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewWantIP4MfibStats() api.Message { return &WantIP4MfibStats{} } // WantIP4MfibStatsReply represents the VPP binary API message 'want_ip4_mfib_stats_reply'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 358: +// Generated from 'stats.api.json', line 358: // // "want_ip4_mfib_stats_reply", // [ @@ -1159,18 +1409,18 @@ type WantIP4MfibStatsReply struct { func (*WantIP4MfibStatsReply) GetMessageName() string { return "want_ip4_mfib_stats_reply" } -func (*WantIP4MfibStatsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*WantIP4MfibStatsReply) GetCrcString() string { return "e8d4e804" } +func (*WantIP4MfibStatsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewWantIP4MfibStatsReply() api.Message { return &WantIP4MfibStatsReply{} } // WantIP6MfibStats represents the VPP binary API message 'want_ip6_mfib_stats'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 376: +// Generated from 'stats.api.json', line 376: // // "want_ip6_mfib_stats", // [ @@ -1199,24 +1449,24 @@ func NewWantIP4MfibStatsReply() api.Message { // type WantIP6MfibStats struct { EnableDisable uint32 - Pid uint32 + PID uint32 } func (*WantIP6MfibStats) GetMessageName() string { return "want_ip6_mfib_stats" } -func (*WantIP6MfibStats) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*WantIP6MfibStats) GetCrcString() string { return "476f5a08" } +func (*WantIP6MfibStats) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewWantIP6MfibStats() api.Message { return &WantIP6MfibStats{} } // WantIP6MfibStatsReply represents the VPP binary API message 'want_ip6_mfib_stats_reply'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 402: +// Generated from 'stats.api.json', line 402: // // "want_ip6_mfib_stats_reply", // [ @@ -1242,18 +1492,18 @@ type WantIP6MfibStatsReply struct { func (*WantIP6MfibStatsReply) GetMessageName() string { return "want_ip6_mfib_stats_reply" } -func (*WantIP6MfibStatsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*WantIP6MfibStatsReply) GetCrcString() string { return "e8d4e804" } +func (*WantIP6MfibStatsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewWantIP6MfibStatsReply() api.Message { return &WantIP6MfibStatsReply{} } // WantIP4NbrStats represents the VPP binary API message 'want_ip4_nbr_stats'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 420: +// Generated from 'stats.api.json', line 420: // // "want_ip4_nbr_stats", // [ @@ -1282,24 +1532,24 @@ func NewWantIP6MfibStatsReply() api.Message { // type WantIP4NbrStats struct { EnableDisable uint32 - Pid uint32 + PID uint32 } func (*WantIP4NbrStats) GetMessageName() string { return "want_ip4_nbr_stats" } -func (*WantIP4NbrStats) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*WantIP4NbrStats) GetCrcString() string { return "476f5a08" } +func (*WantIP4NbrStats) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewWantIP4NbrStats() api.Message { return &WantIP4NbrStats{} } // WantIP4NbrStatsReply represents the VPP binary API message 'want_ip4_nbr_stats_reply'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 446: +// Generated from 'stats.api.json', line 446: // // "want_ip4_nbr_stats_reply", // [ @@ -1325,18 +1575,18 @@ type WantIP4NbrStatsReply struct { func (*WantIP4NbrStatsReply) GetMessageName() string { return "want_ip4_nbr_stats_reply" } -func (*WantIP4NbrStatsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*WantIP4NbrStatsReply) GetCrcString() string { return "e8d4e804" } +func (*WantIP4NbrStatsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewWantIP4NbrStatsReply() api.Message { return &WantIP4NbrStatsReply{} } // WantIP6NbrStats represents the VPP binary API message 'want_ip6_nbr_stats'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 464: +// Generated from 'stats.api.json', line 464: // // "want_ip6_nbr_stats", // [ @@ -1365,24 +1615,24 @@ func NewWantIP4NbrStatsReply() api.Message { // type WantIP6NbrStats struct { EnableDisable uint32 - Pid uint32 + PID uint32 } func (*WantIP6NbrStats) GetMessageName() string { return "want_ip6_nbr_stats" } -func (*WantIP6NbrStats) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*WantIP6NbrStats) GetCrcString() string { return "476f5a08" } +func (*WantIP6NbrStats) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewWantIP6NbrStats() api.Message { return &WantIP6NbrStats{} } // WantIP6NbrStatsReply represents the VPP binary API message 'want_ip6_nbr_stats_reply'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 490: +// Generated from 'stats.api.json', line 490: // // "want_ip6_nbr_stats_reply", // [ @@ -1408,18 +1658,18 @@ type WantIP6NbrStatsReply struct { func (*WantIP6NbrStatsReply) GetMessageName() string { return "want_ip6_nbr_stats_reply" } -func (*WantIP6NbrStatsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*WantIP6NbrStatsReply) GetCrcString() string { return "e8d4e804" } +func (*WantIP6NbrStatsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewWantIP6NbrStatsReply() api.Message { return &WantIP6NbrStatsReply{} } // VnetIP4FibCounters represents the VPP binary API message 'vnet_ip4_fib_counters'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 508: +// Generated from 'stats.api.json', line 508: // // "vnet_ip4_fib_counters", // [ @@ -1453,18 +1703,18 @@ type VnetIP4FibCounters struct { func (*VnetIP4FibCounters) GetMessageName() string { return "vnet_ip4_fib_counters" } -func (*VnetIP4FibCounters) GetMessageType() api.MessageType { - return api.OtherMessage -} func (*VnetIP4FibCounters) GetCrcString() string { return "57e3feec" } +func (*VnetIP4FibCounters) GetMessageType() api.MessageType { + return api.OtherMessage +} func NewVnetIP4FibCounters() api.Message { return &VnetIP4FibCounters{} } // VnetIP4MfibCounters represents the VPP binary API message 'vnet_ip4_mfib_counters'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 532: +// Generated from 'stats.api.json', line 532: // // "vnet_ip4_mfib_counters", // [ @@ -1498,18 +1748,18 @@ type VnetIP4MfibCounters struct { func (*VnetIP4MfibCounters) GetMessageName() string { return "vnet_ip4_mfib_counters" } -func (*VnetIP4MfibCounters) GetMessageType() api.MessageType { - return api.OtherMessage -} func (*VnetIP4MfibCounters) GetCrcString() string { return "946eb588" } +func (*VnetIP4MfibCounters) GetMessageType() api.MessageType { + return api.OtherMessage +} func NewVnetIP4MfibCounters() api.Message { return &VnetIP4MfibCounters{} } // VnetIP4NbrCounters represents the VPP binary API message 'vnet_ip4_nbr_counters'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 556: +// Generated from 'stats.api.json', line 556: // // "vnet_ip4_nbr_counters", // [ @@ -1548,18 +1798,18 @@ type VnetIP4NbrCounters struct { func (*VnetIP4NbrCounters) GetMessageName() string { return "vnet_ip4_nbr_counters" } -func (*VnetIP4NbrCounters) GetMessageType() api.MessageType { - return api.OtherMessage -} func (*VnetIP4NbrCounters) GetCrcString() string { return "214c4811" } +func (*VnetIP4NbrCounters) GetMessageType() api.MessageType { + return api.OtherMessage +} func NewVnetIP4NbrCounters() api.Message { return &VnetIP4NbrCounters{} } // VnetIP6FibCounters represents the VPP binary API message 'vnet_ip6_fib_counters'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 584: +// Generated from 'stats.api.json', line 584: // // "vnet_ip6_fib_counters", // [ @@ -1593,18 +1843,18 @@ type VnetIP6FibCounters struct { func (*VnetIP6FibCounters) GetMessageName() string { return "vnet_ip6_fib_counters" } -func (*VnetIP6FibCounters) GetMessageType() api.MessageType { - return api.OtherMessage -} func (*VnetIP6FibCounters) GetCrcString() string { return "13aed73d" } +func (*VnetIP6FibCounters) GetMessageType() api.MessageType { + return api.OtherMessage +} func NewVnetIP6FibCounters() api.Message { return &VnetIP6FibCounters{} } // VnetIP6MfibCounters represents the VPP binary API message 'vnet_ip6_mfib_counters'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 608: +// Generated from 'stats.api.json', line 608: // // "vnet_ip6_mfib_counters", // [ @@ -1638,18 +1888,18 @@ type VnetIP6MfibCounters struct { func (*VnetIP6MfibCounters) GetMessageName() string { return "vnet_ip6_mfib_counters" } -func (*VnetIP6MfibCounters) GetMessageType() api.MessageType { - return api.OtherMessage -} func (*VnetIP6MfibCounters) GetCrcString() string { return "65fe1ae3" } +func (*VnetIP6MfibCounters) GetMessageType() api.MessageType { + return api.OtherMessage +} func NewVnetIP6MfibCounters() api.Message { return &VnetIP6MfibCounters{} } // VnetIP6NbrCounters represents the VPP binary API message 'vnet_ip6_nbr_counters'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 632: +// Generated from 'stats.api.json', line 632: // // "vnet_ip6_nbr_counters", // [ @@ -1688,18 +1938,18 @@ type VnetIP6NbrCounters struct { func (*VnetIP6NbrCounters) GetMessageName() string { return "vnet_ip6_nbr_counters" } -func (*VnetIP6NbrCounters) GetMessageType() api.MessageType { - return api.OtherMessage -} func (*VnetIP6NbrCounters) GetCrcString() string { return "650161c0" } +func (*VnetIP6NbrCounters) GetMessageType() api.MessageType { + return api.OtherMessage +} func NewVnetIP6NbrCounters() api.Message { return &VnetIP6NbrCounters{} } // VnetInterfaceSimpleCounters represents the VPP binary API message 'vnet_interface_simple_counters'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 660: +// Generated from 'stats.api.json', line 660: // // "vnet_interface_simple_counters", // [ @@ -1738,18 +1988,18 @@ type VnetInterfaceSimpleCounters struct { func (*VnetInterfaceSimpleCounters) GetMessageName() string { return "vnet_interface_simple_counters" } -func (*VnetInterfaceSimpleCounters) GetMessageType() api.MessageType { - return api.OtherMessage -} func (*VnetInterfaceSimpleCounters) GetCrcString() string { return "9bc4a808" } +func (*VnetInterfaceSimpleCounters) GetMessageType() api.MessageType { + return api.OtherMessage +} func NewVnetInterfaceSimpleCounters() api.Message { return &VnetInterfaceSimpleCounters{} } // VnetInterfaceCombinedCounters represents the VPP binary API message 'vnet_interface_combined_counters'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 688: +// Generated from 'stats.api.json', line 688: // // "vnet_interface_combined_counters", // [ @@ -1788,18 +2038,18 @@ type VnetInterfaceCombinedCounters struct { func (*VnetInterfaceCombinedCounters) GetMessageName() string { return "vnet_interface_combined_counters" } -func (*VnetInterfaceCombinedCounters) GetMessageType() api.MessageType { - return api.OtherMessage -} func (*VnetInterfaceCombinedCounters) GetCrcString() string { return "2c595002" } +func (*VnetInterfaceCombinedCounters) GetMessageType() api.MessageType { + return api.OtherMessage +} func NewVnetInterfaceCombinedCounters() api.Message { return &VnetInterfaceCombinedCounters{} } // VnetPerInterfaceSimpleCounters represents the VPP binary API message 'vnet_per_interface_simple_counters'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 716: +// Generated from 'stats.api.json', line 716: // // "vnet_per_interface_simple_counters", // [ @@ -1833,18 +2083,18 @@ type VnetPerInterfaceSimpleCounters struct { func (*VnetPerInterfaceSimpleCounters) GetMessageName() string { return "vnet_per_interface_simple_counters" } -func (*VnetPerInterfaceSimpleCounters) GetMessageType() api.MessageType { - return api.OtherMessage -} func (*VnetPerInterfaceSimpleCounters) GetCrcString() string { return "d1fba9ba" } +func (*VnetPerInterfaceSimpleCounters) GetMessageType() api.MessageType { + return api.OtherMessage +} func NewVnetPerInterfaceSimpleCounters() api.Message { return &VnetPerInterfaceSimpleCounters{} } // VnetPerInterfaceCombinedCounters represents the VPP binary API message 'vnet_per_interface_combined_counters'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 740: +// Generated from 'stats.api.json', line 740: // // "vnet_per_interface_combined_counters", // [ @@ -1878,18 +2128,18 @@ type VnetPerInterfaceCombinedCounters struct { func (*VnetPerInterfaceCombinedCounters) GetMessageName() string { return "vnet_per_interface_combined_counters" } -func (*VnetPerInterfaceCombinedCounters) GetMessageType() api.MessageType { - return api.OtherMessage -} func (*VnetPerInterfaceCombinedCounters) GetCrcString() string { return "dc578375" } +func (*VnetPerInterfaceCombinedCounters) GetMessageType() api.MessageType { + return api.OtherMessage +} func NewVnetPerInterfaceCombinedCounters() api.Message { return &VnetPerInterfaceCombinedCounters{} } // VnetGetSummaryStats represents the VPP binary API message 'vnet_get_summary_stats'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 764: +// Generated from 'stats.api.json', line 764: // // "vnet_get_summary_stats", // [ @@ -1908,24 +2158,23 @@ func NewVnetPerInterfaceCombinedCounters() api.Message { // "crc": "0x51077d14" // } // -type VnetGetSummaryStats struct { -} +type VnetGetSummaryStats struct{} func (*VnetGetSummaryStats) GetMessageName() string { return "vnet_get_summary_stats" } -func (*VnetGetSummaryStats) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*VnetGetSummaryStats) GetCrcString() string { return "51077d14" } +func (*VnetGetSummaryStats) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewVnetGetSummaryStats() api.Message { return &VnetGetSummaryStats{} } // VnetGetSummaryStatsReply represents the VPP binary API message 'vnet_get_summary_stats_reply'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 782: +// Generated from 'stats.api.json', line 782: // // "vnet_get_summary_stats_reply", // [ @@ -1943,43 +2192,43 @@ func NewVnetGetSummaryStats() api.Message { // [ // "u64", // "total_pkts", -// 2 +// 8 // ], // [ // "u64", // "total_bytes", -// 2 +// 8 // ], // [ // "f64", // "vector_rate" // ], // { -// "crc": "0x32b87c56" +// "crc": "0x82b5e46c" // } // type VnetGetSummaryStatsReply struct { Retval int32 - TotalPkts []uint64 `struc:"[2]uint64"` - TotalBytes []uint64 `struc:"[2]uint64"` + TotalPkts []uint64 `struc:"[8]uint64"` + TotalBytes []uint64 `struc:"[8]uint64"` VectorRate float64 } func (*VnetGetSummaryStatsReply) GetMessageName() string { return "vnet_get_summary_stats_reply" } +func (*VnetGetSummaryStatsReply) GetCrcString() string { + return "82b5e46c" +} func (*VnetGetSummaryStatsReply) GetMessageType() api.MessageType { return api.ReplyMessage } -func (*VnetGetSummaryStatsReply) GetCrcString() string { - return "32b87c56" -} func NewVnetGetSummaryStatsReply() api.Message { return &VnetGetSummaryStatsReply{} } // StatsGetPollerDelay represents the VPP binary API message 'stats_get_poller_delay'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 814: +// Generated from 'stats.api.json', line 814: // // "stats_get_poller_delay", // [ @@ -1998,24 +2247,23 @@ func NewVnetGetSummaryStatsReply() api.Message { // "crc": "0x51077d14" // } // -type StatsGetPollerDelay struct { -} +type StatsGetPollerDelay struct{} func (*StatsGetPollerDelay) GetMessageName() string { return "stats_get_poller_delay" } -func (*StatsGetPollerDelay) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*StatsGetPollerDelay) GetCrcString() string { return "51077d14" } +func (*StatsGetPollerDelay) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewStatsGetPollerDelay() api.Message { return &StatsGetPollerDelay{} } // StatsGetPollerDelayReply represents the VPP binary API message 'stats_get_poller_delay_reply'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 832: +// Generated from 'stats.api.json', line 832: // // "stats_get_poller_delay_reply", // [ @@ -2046,18 +2294,18 @@ type StatsGetPollerDelayReply struct { func (*StatsGetPollerDelayReply) GetMessageName() string { return "stats_get_poller_delay_reply" } -func (*StatsGetPollerDelayReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*StatsGetPollerDelayReply) GetCrcString() string { return "8c445a33" } +func (*StatsGetPollerDelayReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewStatsGetPollerDelayReply() api.Message { return &StatsGetPollerDelayReply{} } // WantUDPEncapStats represents the VPP binary API message 'want_udp_encap_stats'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 854: +// Generated from 'stats.api.json', line 854: // // "want_udp_encap_stats", // [ @@ -2086,24 +2334,24 @@ func NewStatsGetPollerDelayReply() api.Message { // type WantUDPEncapStats struct { Enable uint32 - Pid uint32 + PID uint32 } func (*WantUDPEncapStats) GetMessageName() string { return "want_udp_encap_stats" } -func (*WantUDPEncapStats) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*WantUDPEncapStats) GetCrcString() string { return "cfaccc1f" } +func (*WantUDPEncapStats) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewWantUDPEncapStats() api.Message { return &WantUDPEncapStats{} } // WantUDPEncapStatsReply represents the VPP binary API message 'want_udp_encap_stats_reply'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 880: +// Generated from 'stats.api.json', line 880: // // "want_udp_encap_stats_reply", // [ @@ -2129,18 +2377,18 @@ type WantUDPEncapStatsReply struct { func (*WantUDPEncapStatsReply) GetMessageName() string { return "want_udp_encap_stats_reply" } -func (*WantUDPEncapStatsReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*WantUDPEncapStatsReply) GetCrcString() string { return "e8d4e804" } +func (*WantUDPEncapStatsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewWantUDPEncapStatsReply() api.Message { return &WantUDPEncapStatsReply{} } // VnetUDPEncapCounters represents the VPP binary API message 'vnet_udp_encap_counters'. -// Generated from '/usr/share/vpp/api/stats.api.json', line 898: +// Generated from 'stats.api.json', line 898: // // "vnet_udp_encap_counters", // [ @@ -2174,12 +2422,205 @@ type VnetUDPEncapCounters struct { func (*VnetUDPEncapCounters) GetMessageName() string { return "vnet_udp_encap_counters" } -func (*VnetUDPEncapCounters) GetMessageType() api.MessageType { - return api.OtherMessage -} func (*VnetUDPEncapCounters) GetCrcString() string { return "1ab5e649" } +func (*VnetUDPEncapCounters) GetMessageType() api.MessageType { + return api.OtherMessage +} func NewVnetUDPEncapCounters() api.Message { return &VnetUDPEncapCounters{} } + +// WantBierNeighborStats represents the VPP binary API message 'want_bier_neighbor_stats'. +// Generated from 'stats.api.json', line 922: +// +// "want_bier_neighbor_stats", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "client_index" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "u32", +// "enable" +// ], +// [ +// "u32", +// "pid" +// ], +// { +// "crc": "0xcfaccc1f" +// } +// +type WantBierNeighborStats struct { + Enable uint32 + PID uint32 +} + +func (*WantBierNeighborStats) GetMessageName() string { + return "want_bier_neighbor_stats" +} +func (*WantBierNeighborStats) GetCrcString() string { + return "cfaccc1f" +} +func (*WantBierNeighborStats) GetMessageType() api.MessageType { + return api.RequestMessage +} +func NewWantBierNeighborStats() api.Message { + return &WantBierNeighborStats{} +} + +// WantBierNeighborStatsReply represents the VPP binary API message 'want_bier_neighbor_stats_reply'. +// Generated from 'stats.api.json', line 948: +// +// "want_bier_neighbor_stats_reply", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "context" +// ], +// [ +// "i32", +// "retval" +// ], +// { +// "crc": "0xe8d4e804" +// } +// +type WantBierNeighborStatsReply struct { + Retval int32 +} + +func (*WantBierNeighborStatsReply) GetMessageName() string { + return "want_bier_neighbor_stats_reply" +} +func (*WantBierNeighborStatsReply) GetCrcString() string { + return "e8d4e804" +} +func (*WantBierNeighborStatsReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} +func NewWantBierNeighborStatsReply() api.Message { + return &WantBierNeighborStatsReply{} +} + +// VnetBierNeighborCounters represents the VPP binary API message 'vnet_bier_neighbor_counters'. +// Generated from 'stats.api.json', line 966: +// +// "vnet_bier_neighbor_counters", +// [ +// "u16", +// "_vl_msg_id" +// ], +// [ +// "u32", +// "timestamp" +// ], +// [ +// "u32", +// "count" +// ], +// [ +// "vl_api_bier_neighbor_counter_t", +// "c", +// 0, +// "count" +// ], +// { +// "crc": "0xee0481ce" +// } +// +type VnetBierNeighborCounters struct { + Timestamp uint32 + Count uint32 `struc:"sizeof=C"` + C []BierNeighborCounter +} + +func (*VnetBierNeighborCounters) GetMessageName() string { + return "vnet_bier_neighbor_counters" +} +func (*VnetBierNeighborCounters) GetCrcString() string { + return "ee0481ce" +} +func (*VnetBierNeighborCounters) GetMessageType() api.MessageType { + return api.OtherMessage +} +func NewVnetBierNeighborCounters() api.Message { + return &VnetBierNeighborCounters{} +} + +/* Services */ + +type Services interface { + StatsGetPollerDelay(*StatsGetPollerDelay) (*StatsGetPollerDelayReply, error) + VnetGetSummaryStats(*VnetGetSummaryStats) (*VnetGetSummaryStatsReply, error) + WantBierNeighborStats(*WantBierNeighborStats) (*WantBierNeighborStatsReply, error) + WantInterfaceCombinedStats(*WantInterfaceCombinedStats) (*WantInterfaceCombinedStatsReply, error) + WantInterfaceSimpleStats(*WantInterfaceSimpleStats) (*WantInterfaceSimpleStatsReply, error) + WantIP4FibStats(*WantIP4FibStats) (*WantIP4FibStatsReply, error) + WantIP4MfibStats(*WantIP4MfibStats) (*WantIP4MfibStatsReply, error) + WantIP4NbrStats(*WantIP4NbrStats) (*WantIP4NbrStatsReply, error) + WantIP6FibStats(*WantIP6FibStats) (*WantIP6FibStatsReply, error) + WantIP6MfibStats(*WantIP6MfibStats) (*WantIP6MfibStatsReply, error) + WantIP6NbrStats(*WantIP6NbrStats) (*WantIP6NbrStatsReply, error) + WantPerInterfaceCombinedStats(*WantPerInterfaceCombinedStats) (*WantPerInterfaceCombinedStatsReply, error) + WantPerInterfaceSimpleStats(*WantPerInterfaceSimpleStats) (*WantPerInterfaceSimpleStatsReply, error) + WantStats(*WantStats) (*WantStatsReply, error) + WantUDPEncapStats(*WantUDPEncapStats) (*WantUDPEncapStatsReply, error) +} + +func init() { + api.RegisterMessage((*WantStats)(nil), "stats.WantStats") + api.RegisterMessage((*WantStatsReply)(nil), "stats.WantStatsReply") + api.RegisterMessage((*WantInterfaceSimpleStats)(nil), "stats.WantInterfaceSimpleStats") + api.RegisterMessage((*WantInterfaceSimpleStatsReply)(nil), "stats.WantInterfaceSimpleStatsReply") + api.RegisterMessage((*WantPerInterfaceSimpleStats)(nil), "stats.WantPerInterfaceSimpleStats") + api.RegisterMessage((*WantPerInterfaceSimpleStatsReply)(nil), "stats.WantPerInterfaceSimpleStatsReply") + api.RegisterMessage((*WantInterfaceCombinedStats)(nil), "stats.WantInterfaceCombinedStats") + api.RegisterMessage((*WantInterfaceCombinedStatsReply)(nil), "stats.WantInterfaceCombinedStatsReply") + api.RegisterMessage((*WantPerInterfaceCombinedStats)(nil), "stats.WantPerInterfaceCombinedStats") + api.RegisterMessage((*WantPerInterfaceCombinedStatsReply)(nil), "stats.WantPerInterfaceCombinedStatsReply") + api.RegisterMessage((*WantIP4FibStats)(nil), "stats.WantIP4FibStats") + api.RegisterMessage((*WantIP4FibStatsReply)(nil), "stats.WantIP4FibStatsReply") + api.RegisterMessage((*WantIP6FibStats)(nil), "stats.WantIP6FibStats") + api.RegisterMessage((*WantIP6FibStatsReply)(nil), "stats.WantIP6FibStatsReply") + api.RegisterMessage((*WantIP4MfibStats)(nil), "stats.WantIP4MfibStats") + api.RegisterMessage((*WantIP4MfibStatsReply)(nil), "stats.WantIP4MfibStatsReply") + api.RegisterMessage((*WantIP6MfibStats)(nil), "stats.WantIP6MfibStats") + api.RegisterMessage((*WantIP6MfibStatsReply)(nil), "stats.WantIP6MfibStatsReply") + api.RegisterMessage((*WantIP4NbrStats)(nil), "stats.WantIP4NbrStats") + api.RegisterMessage((*WantIP4NbrStatsReply)(nil), "stats.WantIP4NbrStatsReply") + api.RegisterMessage((*WantIP6NbrStats)(nil), "stats.WantIP6NbrStats") + api.RegisterMessage((*WantIP6NbrStatsReply)(nil), "stats.WantIP6NbrStatsReply") + api.RegisterMessage((*VnetIP4FibCounters)(nil), "stats.VnetIP4FibCounters") + api.RegisterMessage((*VnetIP4MfibCounters)(nil), "stats.VnetIP4MfibCounters") + api.RegisterMessage((*VnetIP4NbrCounters)(nil), "stats.VnetIP4NbrCounters") + api.RegisterMessage((*VnetIP6FibCounters)(nil), "stats.VnetIP6FibCounters") + api.RegisterMessage((*VnetIP6MfibCounters)(nil), "stats.VnetIP6MfibCounters") + api.RegisterMessage((*VnetIP6NbrCounters)(nil), "stats.VnetIP6NbrCounters") + api.RegisterMessage((*VnetInterfaceSimpleCounters)(nil), "stats.VnetInterfaceSimpleCounters") + api.RegisterMessage((*VnetInterfaceCombinedCounters)(nil), "stats.VnetInterfaceCombinedCounters") + api.RegisterMessage((*VnetPerInterfaceSimpleCounters)(nil), "stats.VnetPerInterfaceSimpleCounters") + api.RegisterMessage((*VnetPerInterfaceCombinedCounters)(nil), "stats.VnetPerInterfaceCombinedCounters") + api.RegisterMessage((*VnetGetSummaryStats)(nil), "stats.VnetGetSummaryStats") + api.RegisterMessage((*VnetGetSummaryStatsReply)(nil), "stats.VnetGetSummaryStatsReply") + api.RegisterMessage((*StatsGetPollerDelay)(nil), "stats.StatsGetPollerDelay") + api.RegisterMessage((*StatsGetPollerDelayReply)(nil), "stats.StatsGetPollerDelayReply") + api.RegisterMessage((*WantUDPEncapStats)(nil), "stats.WantUDPEncapStats") + api.RegisterMessage((*WantUDPEncapStatsReply)(nil), "stats.WantUDPEncapStatsReply") + api.RegisterMessage((*VnetUDPEncapCounters)(nil), "stats.VnetUDPEncapCounters") + api.RegisterMessage((*WantBierNeighborStats)(nil), "stats.WantBierNeighborStats") + api.RegisterMessage((*WantBierNeighborStatsReply)(nil), "stats.WantBierNeighborStatsReply") + api.RegisterMessage((*VnetBierNeighborCounters)(nil), "stats.VnetBierNeighborCounters") +} diff --git a/plugins/vpp/binapi/stn/pkgreflect.go b/plugins/vpp/binapi/stn/pkgreflect.go index a79b7e941d..ce596e1ca6 100644 --- a/plugins/vpp/binapi/stn/pkgreflect.go +++ b/plugins/vpp/binapi/stn/pkgreflect.go @@ -5,6 +5,7 @@ package stn import "reflect" var Types = map[string]reflect.Type{ + "Services": reflect.TypeOf((*Services)(nil)).Elem(), "StnAddDelRule": reflect.TypeOf((*StnAddDelRule)(nil)).Elem(), "StnAddDelRuleReply": reflect.TypeOf((*StnAddDelRuleReply)(nil)).Elem(), "StnRulesDetails": reflect.TypeOf((*StnRulesDetails)(nil)).Elem(), diff --git a/plugins/vpp/binapi/stn/stn.go b/plugins/vpp/binapi/stn/stn.ba.go similarity index 77% rename from plugins/vpp/binapi/stn/stn.go rename to plugins/vpp/binapi/stn/stn.ba.go index 73e3d9a6c0..7e2ea8cc07 100644 --- a/plugins/vpp/binapi/stn/stn.go +++ b/plugins/vpp/binapi/stn/stn.ba.go @@ -1,12 +1,30 @@ -// Code generated by govpp binapi-generator DO NOT EDIT. -// Package stn represents the VPP binary API of the 'stn' VPP module. -// Generated from '/usr/share/vpp/api/stn.api.json' +// Code generated by GoVPP binapi-generator. DO NOT EDIT. +// source: /usr/share/vpp/api/stn.api.json + +/* +Package stn is a generated VPP binary API of the 'stn' VPP module. + +It is generated from this file: + stn.api.json + +It contains these VPP binary API objects: + 4 messages + 2 services +*/ package stn import "git.fd.io/govpp.git/api" +import "github.com/lunixbochs/struc" +import "bytes" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = struc.Pack +var _ = bytes.NewBuffer + +/* Messages */ // StnAddDelRule represents the VPP binary API message 'stn_add_del_rule'. -// Generated from '/usr/share/vpp/api/stn.api.json', line 4: +// Generated from 'stn.api.json', line 4: // // "stn_add_del_rule", // [ @@ -52,18 +70,18 @@ type StnAddDelRule struct { func (*StnAddDelRule) GetMessageName() string { return "stn_add_del_rule" } -func (*StnAddDelRule) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*StnAddDelRule) GetCrcString() string { return "9f0bbe21" } +func (*StnAddDelRule) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewStnAddDelRule() api.Message { return &StnAddDelRule{} } // StnAddDelRuleReply represents the VPP binary API message 'stn_add_del_rule_reply'. -// Generated from '/usr/share/vpp/api/stn.api.json', line 39: +// Generated from 'stn.api.json', line 39: // // "stn_add_del_rule_reply", // [ @@ -89,18 +107,18 @@ type StnAddDelRuleReply struct { func (*StnAddDelRuleReply) GetMessageName() string { return "stn_add_del_rule_reply" } -func (*StnAddDelRuleReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*StnAddDelRuleReply) GetCrcString() string { return "e8d4e804" } +func (*StnAddDelRuleReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewStnAddDelRuleReply() api.Message { return &StnAddDelRuleReply{} } // StnRulesDump represents the VPP binary API message 'stn_rules_dump'. -// Generated from '/usr/share/vpp/api/stn.api.json', line 57: +// Generated from 'stn.api.json', line 57: // // "stn_rules_dump", // [ @@ -119,24 +137,23 @@ func NewStnAddDelRuleReply() api.Message { // "crc": "0x51077d14" // } // -type StnRulesDump struct { -} +type StnRulesDump struct{} func (*StnRulesDump) GetMessageName() string { return "stn_rules_dump" } -func (*StnRulesDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*StnRulesDump) GetCrcString() string { return "51077d14" } +func (*StnRulesDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewStnRulesDump() api.Message { return &StnRulesDump{} } // StnRulesDetails represents the VPP binary API message 'stn_rules_details'. -// Generated from '/usr/share/vpp/api/stn.api.json', line 75: +// Generated from 'stn.api.json', line 75: // // "stn_rules_details", // [ @@ -173,12 +190,26 @@ type StnRulesDetails struct { func (*StnRulesDetails) GetMessageName() string { return "stn_rules_details" } -func (*StnRulesDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*StnRulesDetails) GetCrcString() string { return "5eafa31e" } +func (*StnRulesDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewStnRulesDetails() api.Message { return &StnRulesDetails{} } + +/* Services */ + +type Services interface { + DumpStnRules(*StnRulesDump) (*StnRulesDetails, error) + StnAddDelRule(*StnAddDelRule) (*StnAddDelRuleReply, error) +} + +func init() { + api.RegisterMessage((*StnAddDelRule)(nil), "stn.StnAddDelRule") + api.RegisterMessage((*StnAddDelRuleReply)(nil), "stn.StnAddDelRuleReply") + api.RegisterMessage((*StnRulesDump)(nil), "stn.StnRulesDump") + api.RegisterMessage((*StnRulesDetails)(nil), "stn.StnRulesDetails") +} diff --git a/plugins/vpp/binapi/tap/pkgreflect.go b/plugins/vpp/binapi/tap/pkgreflect.go index 7792cbcae0..7843f9f934 100644 --- a/plugins/vpp/binapi/tap/pkgreflect.go +++ b/plugins/vpp/binapi/tap/pkgreflect.go @@ -5,6 +5,7 @@ package tap import "reflect" var Types = map[string]reflect.Type{ + "Services": reflect.TypeOf((*Services)(nil)).Elem(), "SwInterfaceTapDetails": reflect.TypeOf((*SwInterfaceTapDetails)(nil)).Elem(), "SwInterfaceTapDump": reflect.TypeOf((*SwInterfaceTapDump)(nil)).Elem(), "TapConnect": reflect.TypeOf((*TapConnect)(nil)).Elem(), diff --git a/plugins/vpp/binapi/tap/tap.go b/plugins/vpp/binapi/tap/tap.ba.go similarity index 84% rename from plugins/vpp/binapi/tap/tap.go rename to plugins/vpp/binapi/tap/tap.ba.go index b747c7c565..17c344eb81 100644 --- a/plugins/vpp/binapi/tap/tap.go +++ b/plugins/vpp/binapi/tap/tap.ba.go @@ -1,12 +1,30 @@ -// Code generated by govpp binapi-generator DO NOT EDIT. -// Package tap represents the VPP binary API of the 'tap' VPP module. -// Generated from '/usr/share/vpp/api/tap.api.json' +// Code generated by GoVPP binapi-generator. DO NOT EDIT. +// source: /usr/share/vpp/api/tap.api.json + +/* +Package tap is a generated VPP binary API of the 'tap' VPP module. + +It is generated from this file: + tap.api.json + +It contains these VPP binary API objects: + 8 messages + 4 services +*/ package tap import "git.fd.io/govpp.git/api" +import "github.com/lunixbochs/struc" +import "bytes" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = struc.Pack +var _ = bytes.NewBuffer + +/* Messages */ // TapConnect represents the VPP binary API message 'tap_connect'. -// Generated from '/usr/share/vpp/api/tap.api.json', line 4: +// Generated from 'tap.api.json', line 4: // // "tap_connect", // [ @@ -96,18 +114,18 @@ type TapConnect struct { func (*TapConnect) GetMessageName() string { return "tap_connect" } -func (*TapConnect) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*TapConnect) GetCrcString() string { return "9b9c396f" } +func (*TapConnect) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewTapConnect() api.Message { return &TapConnect{} } // TapConnectReply represents the VPP binary API message 'tap_connect_reply'. -// Generated from '/usr/share/vpp/api/tap.api.json', line 75: +// Generated from 'tap.api.json', line 75: // // "tap_connect_reply", // [ @@ -138,18 +156,18 @@ type TapConnectReply struct { func (*TapConnectReply) GetMessageName() string { return "tap_connect_reply" } -func (*TapConnectReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*TapConnectReply) GetCrcString() string { return "fda5941f" } +func (*TapConnectReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewTapConnectReply() api.Message { return &TapConnectReply{} } // TapModify represents the VPP binary API message 'tap_modify'. -// Generated from '/usr/share/vpp/api/tap.api.json', line 97: +// Generated from 'tap.api.json', line 97: // // "tap_modify", // [ @@ -206,18 +224,18 @@ type TapModify struct { func (*TapModify) GetMessageName() string { return "tap_modify" } -func (*TapModify) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*TapModify) GetCrcString() string { return "8047ae5c" } +func (*TapModify) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewTapModify() api.Message { return &TapModify{} } // TapModifyReply represents the VPP binary API message 'tap_modify_reply'. -// Generated from '/usr/share/vpp/api/tap.api.json', line 141: +// Generated from 'tap.api.json', line 141: // // "tap_modify_reply", // [ @@ -248,18 +266,18 @@ type TapModifyReply struct { func (*TapModifyReply) GetMessageName() string { return "tap_modify_reply" } -func (*TapModifyReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*TapModifyReply) GetCrcString() string { return "fda5941f" } +func (*TapModifyReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewTapModifyReply() api.Message { return &TapModifyReply{} } // TapDelete represents the VPP binary API message 'tap_delete'. -// Generated from '/usr/share/vpp/api/tap.api.json', line 163: +// Generated from 'tap.api.json', line 163: // // "tap_delete", // [ @@ -289,18 +307,18 @@ type TapDelete struct { func (*TapDelete) GetMessageName() string { return "tap_delete" } -func (*TapDelete) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*TapDelete) GetCrcString() string { return "529cb13f" } +func (*TapDelete) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewTapDelete() api.Message { return &TapDelete{} } // TapDeleteReply represents the VPP binary API message 'tap_delete_reply'. -// Generated from '/usr/share/vpp/api/tap.api.json', line 185: +// Generated from 'tap.api.json', line 185: // // "tap_delete_reply", // [ @@ -326,18 +344,18 @@ type TapDeleteReply struct { func (*TapDeleteReply) GetMessageName() string { return "tap_delete_reply" } -func (*TapDeleteReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*TapDeleteReply) GetCrcString() string { return "e8d4e804" } +func (*TapDeleteReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewTapDeleteReply() api.Message { return &TapDeleteReply{} } // SwInterfaceTapDump represents the VPP binary API message 'sw_interface_tap_dump'. -// Generated from '/usr/share/vpp/api/tap.api.json', line 203: +// Generated from 'tap.api.json', line 203: // // "sw_interface_tap_dump", // [ @@ -356,24 +374,23 @@ func NewTapDeleteReply() api.Message { // "crc": "0x51077d14" // } // -type SwInterfaceTapDump struct { -} +type SwInterfaceTapDump struct{} func (*SwInterfaceTapDump) GetMessageName() string { return "sw_interface_tap_dump" } -func (*SwInterfaceTapDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceTapDump) GetCrcString() string { return "51077d14" } +func (*SwInterfaceTapDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceTapDump() api.Message { return &SwInterfaceTapDump{} } // SwInterfaceTapDetails represents the VPP binary API message 'sw_interface_tap_details'. -// Generated from '/usr/share/vpp/api/tap.api.json', line 221: +// Generated from 'tap.api.json', line 221: // // "sw_interface_tap_details", // [ @@ -405,12 +422,32 @@ type SwInterfaceTapDetails struct { func (*SwInterfaceTapDetails) GetMessageName() string { return "sw_interface_tap_details" } -func (*SwInterfaceTapDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceTapDetails) GetCrcString() string { return "76229a57" } +func (*SwInterfaceTapDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceTapDetails() api.Message { return &SwInterfaceTapDetails{} } + +/* Services */ + +type Services interface { + DumpSwInterfaceTap(*SwInterfaceTapDump) (*SwInterfaceTapDetails, error) + TapConnect(*TapConnect) (*TapConnectReply, error) + TapDelete(*TapDelete) (*TapDeleteReply, error) + TapModify(*TapModify) (*TapModifyReply, error) +} + +func init() { + api.RegisterMessage((*TapConnect)(nil), "tap.TapConnect") + api.RegisterMessage((*TapConnectReply)(nil), "tap.TapConnectReply") + api.RegisterMessage((*TapModify)(nil), "tap.TapModify") + api.RegisterMessage((*TapModifyReply)(nil), "tap.TapModifyReply") + api.RegisterMessage((*TapDelete)(nil), "tap.TapDelete") + api.RegisterMessage((*TapDeleteReply)(nil), "tap.TapDeleteReply") + api.RegisterMessage((*SwInterfaceTapDump)(nil), "tap.SwInterfaceTapDump") + api.RegisterMessage((*SwInterfaceTapDetails)(nil), "tap.SwInterfaceTapDetails") +} diff --git a/plugins/vpp/binapi/tapv2/pkgreflect.go b/plugins/vpp/binapi/tapv2/pkgreflect.go index 271910c5c4..d1bc760e37 100644 --- a/plugins/vpp/binapi/tapv2/pkgreflect.go +++ b/plugins/vpp/binapi/tapv2/pkgreflect.go @@ -5,6 +5,7 @@ package tapv2 import "reflect" var Types = map[string]reflect.Type{ + "Services": reflect.TypeOf((*Services)(nil)).Elem(), "SwInterfaceTapV2Details": reflect.TypeOf((*SwInterfaceTapV2Details)(nil)).Elem(), "SwInterfaceTapV2Dump": reflect.TypeOf((*SwInterfaceTapV2Dump)(nil)).Elem(), "TapCreateV2": reflect.TypeOf((*TapCreateV2)(nil)).Elem(), diff --git a/plugins/vpp/binapi/tapv2/tapv2.go b/plugins/vpp/binapi/tapv2/tapv2.ba.go similarity index 87% rename from plugins/vpp/binapi/tapv2/tapv2.go rename to plugins/vpp/binapi/tapv2/tapv2.ba.go index aef1c712a7..4da3ae2d26 100644 --- a/plugins/vpp/binapi/tapv2/tapv2.go +++ b/plugins/vpp/binapi/tapv2/tapv2.ba.go @@ -1,12 +1,30 @@ -// Code generated by govpp binapi-generator DO NOT EDIT. -// Package tapv2 represents the VPP binary API of the 'tapv2' VPP module. -// Generated from '/usr/share/vpp/api/tapv2.api.json' +// Code generated by GoVPP binapi-generator. DO NOT EDIT. +// source: /usr/share/vpp/api/tapv2.api.json + +/* +Package tapv2 is a generated VPP binary API of the 'tapv2' VPP module. + +It is generated from this file: + tapv2.api.json + +It contains these VPP binary API objects: + 6 messages + 3 services +*/ package tapv2 import "git.fd.io/govpp.git/api" +import "github.com/lunixbochs/struc" +import "bytes" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = struc.Pack +var _ = bytes.NewBuffer + +/* Messages */ // TapCreateV2 represents the VPP binary API message 'tap_create_v2'. -// Generated from '/usr/share/vpp/api/tapv2.api.json', line 4: +// Generated from 'tapv2.api.json', line 4: // // "tap_create_v2", // [ @@ -161,18 +179,18 @@ type TapCreateV2 struct { func (*TapCreateV2) GetMessageName() string { return "tap_create_v2" } -func (*TapCreateV2) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*TapCreateV2) GetCrcString() string { return "34ce8043" } +func (*TapCreateV2) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewTapCreateV2() api.Message { return &TapCreateV2{} } // TapCreateV2Reply represents the VPP binary API message 'tap_create_v2_reply'. -// Generated from '/usr/share/vpp/api/tapv2.api.json', line 128: +// Generated from 'tapv2.api.json', line 128: // // "tap_create_v2_reply", // [ @@ -203,18 +221,18 @@ type TapCreateV2Reply struct { func (*TapCreateV2Reply) GetMessageName() string { return "tap_create_v2_reply" } -func (*TapCreateV2Reply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*TapCreateV2Reply) GetCrcString() string { return "fda5941f" } +func (*TapCreateV2Reply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewTapCreateV2Reply() api.Message { return &TapCreateV2Reply{} } // TapDeleteV2 represents the VPP binary API message 'tap_delete_v2'. -// Generated from '/usr/share/vpp/api/tapv2.api.json', line 150: +// Generated from 'tapv2.api.json', line 150: // // "tap_delete_v2", // [ @@ -244,18 +262,18 @@ type TapDeleteV2 struct { func (*TapDeleteV2) GetMessageName() string { return "tap_delete_v2" } -func (*TapDeleteV2) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*TapDeleteV2) GetCrcString() string { return "529cb13f" } +func (*TapDeleteV2) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewTapDeleteV2() api.Message { return &TapDeleteV2{} } // TapDeleteV2Reply represents the VPP binary API message 'tap_delete_v2_reply'. -// Generated from '/usr/share/vpp/api/tapv2.api.json', line 172: +// Generated from 'tapv2.api.json', line 172: // // "tap_delete_v2_reply", // [ @@ -281,18 +299,18 @@ type TapDeleteV2Reply struct { func (*TapDeleteV2Reply) GetMessageName() string { return "tap_delete_v2_reply" } -func (*TapDeleteV2Reply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*TapDeleteV2Reply) GetCrcString() string { return "e8d4e804" } +func (*TapDeleteV2Reply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewTapDeleteV2Reply() api.Message { return &TapDeleteV2Reply{} } // SwInterfaceTapV2Dump represents the VPP binary API message 'sw_interface_tap_v2_dump'. -// Generated from '/usr/share/vpp/api/tapv2.api.json', line 190: +// Generated from 'tapv2.api.json', line 190: // // "sw_interface_tap_v2_dump", // [ @@ -311,24 +329,23 @@ func NewTapDeleteV2Reply() api.Message { // "crc": "0x51077d14" // } // -type SwInterfaceTapV2Dump struct { -} +type SwInterfaceTapV2Dump struct{} func (*SwInterfaceTapV2Dump) GetMessageName() string { return "sw_interface_tap_v2_dump" } -func (*SwInterfaceTapV2Dump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceTapV2Dump) GetCrcString() string { return "51077d14" } +func (*SwInterfaceTapV2Dump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceTapV2Dump() api.Message { return &SwInterfaceTapV2Dump{} } // SwInterfaceTapV2Details represents the VPP binary API message 'sw_interface_tap_v2_details'. -// Generated from '/usr/share/vpp/api/tapv2.api.json', line 208: +// Generated from 'tapv2.api.json', line 208: // // "sw_interface_tap_v2_details", // [ @@ -421,12 +438,29 @@ type SwInterfaceTapV2Details struct { func (*SwInterfaceTapV2Details) GetMessageName() string { return "sw_interface_tap_v2_details" } -func (*SwInterfaceTapV2Details) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceTapV2Details) GetCrcString() string { return "b4c58229" } +func (*SwInterfaceTapV2Details) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceTapV2Details() api.Message { return &SwInterfaceTapV2Details{} } + +/* Services */ + +type Services interface { + DumpSwInterfaceTapV2(*SwInterfaceTapV2Dump) (*SwInterfaceTapV2Details, error) + TapCreateV2(*TapCreateV2) (*TapCreateV2Reply, error) + TapDeleteV2(*TapDeleteV2) (*TapDeleteV2Reply, error) +} + +func init() { + api.RegisterMessage((*TapCreateV2)(nil), "tapv2.TapCreateV2") + api.RegisterMessage((*TapCreateV2Reply)(nil), "tapv2.TapCreateV2Reply") + api.RegisterMessage((*TapDeleteV2)(nil), "tapv2.TapDeleteV2") + api.RegisterMessage((*TapDeleteV2Reply)(nil), "tapv2.TapDeleteV2Reply") + api.RegisterMessage((*SwInterfaceTapV2Dump)(nil), "tapv2.SwInterfaceTapV2Dump") + api.RegisterMessage((*SwInterfaceTapV2Details)(nil), "tapv2.SwInterfaceTapV2Details") +} diff --git a/plugins/vpp/binapi/vpe/pkgreflect.go b/plugins/vpp/binapi/vpe/pkgreflect.go index ee46893fcf..4058c07b90 100644 --- a/plugins/vpp/binapi/vpe/pkgreflect.go +++ b/plugins/vpp/binapi/vpe/pkgreflect.go @@ -19,6 +19,7 @@ var Types = map[string]reflect.Type{ "GetNodeGraphReply": reflect.TypeOf((*GetNodeGraphReply)(nil)).Elem(), "GetNodeIndex": reflect.TypeOf((*GetNodeIndex)(nil)).Elem(), "GetNodeIndexReply": reflect.TypeOf((*GetNodeIndexReply)(nil)).Elem(), + "Services": reflect.TypeOf((*Services)(nil)).Elem(), "ShowVersion": reflect.TypeOf((*ShowVersion)(nil)).Elem(), "ShowVersionReply": reflect.TypeOf((*ShowVersionReply)(nil)).Elem(), } diff --git a/vendor/git.fd.io/govpp.git/core/bin_api/vpe/vpe.go b/plugins/vpp/binapi/vpe/vpe.ba.go similarity index 84% rename from vendor/git.fd.io/govpp.git/core/bin_api/vpe/vpe.go rename to plugins/vpp/binapi/vpe/vpe.ba.go index 547e200892..0a9d136569 100644 --- a/vendor/git.fd.io/govpp.git/core/bin_api/vpe/vpe.go +++ b/plugins/vpp/binapi/vpe/vpe.ba.go @@ -1,15 +1,30 @@ -// Code generated by govpp binapi-generator DO NOT EDIT. -// Package vpe represents the VPP binary API of the 'vpe' VPP module. -// Generated from 'bin_api/vpe.api.json' +// Code generated by GoVPP binapi-generator. DO NOT EDIT. +// source: /usr/share/vpp/api/vpe.api.json + +/* +Package vpe is a generated VPP binary API of the 'vpe' VPP module. + +It is generated from this file: + vpe.api.json + +It contains these VPP binary API objects: + 16 messages + 8 services +*/ package vpe import "git.fd.io/govpp.git/api" +import "github.com/lunixbochs/struc" +import "bytes" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = struc.Pack +var _ = bytes.NewBuffer -// VlApiVersion contains version of the API. -const VlAPIVersion = 0xe02a02b0 +/* Messages */ // ControlPing represents the VPP binary API message 'control_ping'. -// Generated from 'bin_api/vpe.api.json', line 48: +// Generated from 'vpe.api.json', line 4: // // "control_ping", // [ @@ -28,24 +43,23 @@ const VlAPIVersion = 0xe02a02b0 // "crc": "0x51077d14" // } // -type ControlPing struct { -} +type ControlPing struct{} func (*ControlPing) GetMessageName() string { return "control_ping" } -func (*ControlPing) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ControlPing) GetCrcString() string { return "51077d14" } +func (*ControlPing) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewControlPing() api.Message { return &ControlPing{} } // ControlPingReply represents the VPP binary API message 'control_ping_reply'. -// Generated from 'bin_api/vpe.api.json', line 66: +// Generated from 'vpe.api.json', line 22: // // "control_ping_reply", // [ @@ -75,24 +89,24 @@ func NewControlPing() api.Message { type ControlPingReply struct { Retval int32 ClientIndex uint32 - VpePid uint32 + VpePID uint32 } func (*ControlPingReply) GetMessageName() string { return "control_ping_reply" } -func (*ControlPingReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ControlPingReply) GetCrcString() string { return "f6b0b8ca" } +func (*ControlPingReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewControlPingReply() api.Message { return &ControlPingReply{} } // Cli represents the VPP binary API message 'cli'. -// Generated from 'bin_api/vpe.api.json', line 92: +// Generated from 'vpe.api.json', line 48: // // "cli", // [ @@ -122,18 +136,18 @@ type Cli struct { func (*Cli) GetMessageName() string { return "cli" } -func (*Cli) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*Cli) GetCrcString() string { return "23bfbfff" } +func (*Cli) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewCli() api.Message { return &Cli{} } // CliInband represents the VPP binary API message 'cli_inband'. -// Generated from 'bin_api/vpe.api.json', line 114: +// Generated from 'vpe.api.json', line 70: // // "cli_inband", // [ @@ -170,18 +184,18 @@ type CliInband struct { func (*CliInband) GetMessageName() string { return "cli_inband" } -func (*CliInband) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*CliInband) GetCrcString() string { return "74e00a49" } +func (*CliInband) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewCliInband() api.Message { return &CliInband{} } // CliReply represents the VPP binary API message 'cli_reply'. -// Generated from 'bin_api/vpe.api.json', line 142: +// Generated from 'vpe.api.json', line 98: // // "cli_reply", // [ @@ -212,18 +226,18 @@ type CliReply struct { func (*CliReply) GetMessageName() string { return "cli_reply" } -func (*CliReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*CliReply) GetCrcString() string { return "06d68297" } +func (*CliReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewCliReply() api.Message { return &CliReply{} } // CliInbandReply represents the VPP binary API message 'cli_inband_reply'. -// Generated from 'bin_api/vpe.api.json', line 164: +// Generated from 'vpe.api.json', line 120: // // "cli_inband_reply", // [ @@ -261,18 +275,18 @@ type CliInbandReply struct { func (*CliInbandReply) GetMessageName() string { return "cli_inband_reply" } -func (*CliInbandReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*CliInbandReply) GetCrcString() string { return "1f22bbb8" } +func (*CliInbandReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewCliInbandReply() api.Message { return &CliInbandReply{} } // GetNodeIndex represents the VPP binary API message 'get_node_index'. -// Generated from 'bin_api/vpe.api.json', line 192: +// Generated from 'vpe.api.json', line 148: // // "get_node_index", // [ @@ -303,18 +317,18 @@ type GetNodeIndex struct { func (*GetNodeIndex) GetMessageName() string { return "get_node_index" } -func (*GetNodeIndex) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*GetNodeIndex) GetCrcString() string { return "6c9a495d" } +func (*GetNodeIndex) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewGetNodeIndex() api.Message { return &GetNodeIndex{} } // GetNodeIndexReply represents the VPP binary API message 'get_node_index_reply'. -// Generated from 'bin_api/vpe.api.json', line 215: +// Generated from 'vpe.api.json', line 171: // // "get_node_index_reply", // [ @@ -345,18 +359,18 @@ type GetNodeIndexReply struct { func (*GetNodeIndexReply) GetMessageName() string { return "get_node_index_reply" } -func (*GetNodeIndexReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*GetNodeIndexReply) GetCrcString() string { return "a8600b89" } +func (*GetNodeIndexReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewGetNodeIndexReply() api.Message { return &GetNodeIndexReply{} } // AddNodeNext represents the VPP binary API message 'add_node_next'. -// Generated from 'bin_api/vpe.api.json', line 237: +// Generated from 'vpe.api.json', line 193: // // "add_node_next", // [ @@ -393,18 +407,18 @@ type AddNodeNext struct { func (*AddNodeNext) GetMessageName() string { return "add_node_next" } -func (*AddNodeNext) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*AddNodeNext) GetCrcString() string { return "9ab92f7a" } +func (*AddNodeNext) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewAddNodeNext() api.Message { return &AddNodeNext{} } // AddNodeNextReply represents the VPP binary API message 'add_node_next_reply'. -// Generated from 'bin_api/vpe.api.json', line 265: +// Generated from 'vpe.api.json', line 221: // // "add_node_next_reply", // [ @@ -435,18 +449,18 @@ type AddNodeNextReply struct { func (*AddNodeNextReply) GetMessageName() string { return "add_node_next_reply" } -func (*AddNodeNextReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*AddNodeNextReply) GetCrcString() string { return "2ed75f32" } +func (*AddNodeNextReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewAddNodeNextReply() api.Message { return &AddNodeNextReply{} } // ShowVersion represents the VPP binary API message 'show_version'. -// Generated from 'bin_api/vpe.api.json', line 287: +// Generated from 'vpe.api.json', line 243: // // "show_version", // [ @@ -465,24 +479,23 @@ func NewAddNodeNextReply() api.Message { // "crc": "0x51077d14" // } // -type ShowVersion struct { -} +type ShowVersion struct{} func (*ShowVersion) GetMessageName() string { return "show_version" } -func (*ShowVersion) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*ShowVersion) GetCrcString() string { return "51077d14" } +func (*ShowVersion) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewShowVersion() api.Message { return &ShowVersion{} } // ShowVersionReply represents the VPP binary API message 'show_version_reply'. -// Generated from 'bin_api/vpe.api.json', line 305: +// Generated from 'vpe.api.json', line 261: // // "show_version_reply", // [ @@ -532,18 +545,18 @@ type ShowVersionReply struct { func (*ShowVersionReply) GetMessageName() string { return "show_version_reply" } -func (*ShowVersionReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*ShowVersionReply) GetCrcString() string { return "8b5a13b4" } +func (*ShowVersionReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewShowVersionReply() api.Message { return &ShowVersionReply{} } // GetNodeGraph represents the VPP binary API message 'get_node_graph'. -// Generated from 'bin_api/vpe.api.json', line 343: +// Generated from 'vpe.api.json', line 299: // // "get_node_graph", // [ @@ -562,24 +575,23 @@ func NewShowVersionReply() api.Message { // "crc": "0x51077d14" // } // -type GetNodeGraph struct { -} +type GetNodeGraph struct{} func (*GetNodeGraph) GetMessageName() string { return "get_node_graph" } -func (*GetNodeGraph) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*GetNodeGraph) GetCrcString() string { return "51077d14" } +func (*GetNodeGraph) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewGetNodeGraph() api.Message { return &GetNodeGraph{} } // GetNodeGraphReply represents the VPP binary API message 'get_node_graph_reply'. -// Generated from 'bin_api/vpe.api.json', line 361: +// Generated from 'vpe.api.json', line 317: // // "get_node_graph_reply", // [ @@ -610,18 +622,18 @@ type GetNodeGraphReply struct { func (*GetNodeGraphReply) GetMessageName() string { return "get_node_graph_reply" } -func (*GetNodeGraphReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*GetNodeGraphReply) GetCrcString() string { return "06d68297" } +func (*GetNodeGraphReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewGetNodeGraphReply() api.Message { return &GetNodeGraphReply{} } // GetNextIndex represents the VPP binary API message 'get_next_index'. -// Generated from 'bin_api/vpe.api.json', line 383: +// Generated from 'vpe.api.json', line 339: // // "get_next_index", // [ @@ -658,18 +670,18 @@ type GetNextIndex struct { func (*GetNextIndex) GetMessageName() string { return "get_next_index" } -func (*GetNextIndex) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*GetNextIndex) GetCrcString() string { return "9ab92f7a" } +func (*GetNextIndex) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewGetNextIndex() api.Message { return &GetNextIndex{} } // GetNextIndexReply represents the VPP binary API message 'get_next_index_reply'. -// Generated from 'bin_api/vpe.api.json', line 411: +// Generated from 'vpe.api.json', line 367: // // "get_next_index_reply", // [ @@ -700,12 +712,44 @@ type GetNextIndexReply struct { func (*GetNextIndexReply) GetMessageName() string { return "get_next_index_reply" } -func (*GetNextIndexReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*GetNextIndexReply) GetCrcString() string { return "2ed75f32" } +func (*GetNextIndexReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewGetNextIndexReply() api.Message { return &GetNextIndexReply{} } + +/* Services */ + +type Services interface { + AddNodeNext(*AddNodeNext) (*AddNodeNextReply, error) + Cli(*Cli) (*CliReply, error) + CliInband(*CliInband) (*CliInbandReply, error) + ControlPing(*ControlPing) (*ControlPingReply, error) + GetNextIndex(*GetNextIndex) (*GetNextIndexReply, error) + GetNodeGraph(*GetNodeGraph) (*GetNodeGraphReply, error) + GetNodeIndex(*GetNodeIndex) (*GetNodeIndexReply, error) + ShowVersion(*ShowVersion) (*ShowVersionReply, error) +} + +func init() { + api.RegisterMessage((*ControlPing)(nil), "vpe.ControlPing") + api.RegisterMessage((*ControlPingReply)(nil), "vpe.ControlPingReply") + api.RegisterMessage((*Cli)(nil), "vpe.Cli") + api.RegisterMessage((*CliInband)(nil), "vpe.CliInband") + api.RegisterMessage((*CliReply)(nil), "vpe.CliReply") + api.RegisterMessage((*CliInbandReply)(nil), "vpe.CliInbandReply") + api.RegisterMessage((*GetNodeIndex)(nil), "vpe.GetNodeIndex") + api.RegisterMessage((*GetNodeIndexReply)(nil), "vpe.GetNodeIndexReply") + api.RegisterMessage((*AddNodeNext)(nil), "vpe.AddNodeNext") + api.RegisterMessage((*AddNodeNextReply)(nil), "vpe.AddNodeNextReply") + api.RegisterMessage((*ShowVersion)(nil), "vpe.ShowVersion") + api.RegisterMessage((*ShowVersionReply)(nil), "vpe.ShowVersionReply") + api.RegisterMessage((*GetNodeGraph)(nil), "vpe.GetNodeGraph") + api.RegisterMessage((*GetNodeGraphReply)(nil), "vpe.GetNodeGraphReply") + api.RegisterMessage((*GetNextIndex)(nil), "vpe.GetNextIndex") + api.RegisterMessage((*GetNextIndexReply)(nil), "vpe.GetNextIndexReply") +} diff --git a/plugins/vpp/binapi/vpe/vpe.go b/plugins/vpp/binapi/vpe/vpe.go deleted file mode 100644 index c5c624a413..0000000000 --- a/plugins/vpp/binapi/vpe/vpe.go +++ /dev/null @@ -1,708 +0,0 @@ -// Code generated by govpp binapi-generator DO NOT EDIT. -// Package vpe represents the VPP binary API of the 'vpe' VPP module. -// Generated from '/usr/share/vpp/api/vpe.api.json' -package vpe - -import "git.fd.io/govpp.git/api" - -// ControlPing represents the VPP binary API message 'control_ping'. -// Generated from '/usr/share/vpp/api/vpe.api.json', line 4: -// -// "control_ping", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "client_index" -// ], -// [ -// "u32", -// "context" -// ], -// { -// "crc": "0x51077d14" -// } -// -type ControlPing struct { -} - -func (*ControlPing) GetMessageName() string { - return "control_ping" -} -func (*ControlPing) GetMessageType() api.MessageType { - return api.RequestMessage -} -func (*ControlPing) GetCrcString() string { - return "51077d14" -} -func NewControlPing() api.Message { - return &ControlPing{} -} - -// ControlPingReply represents the VPP binary API message 'control_ping_reply'. -// Generated from '/usr/share/vpp/api/vpe.api.json', line 22: -// -// "control_ping_reply", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "i32", -// "retval" -// ], -// [ -// "u32", -// "client_index" -// ], -// [ -// "u32", -// "vpe_pid" -// ], -// { -// "crc": "0xf6b0b8ca" -// } -// -type ControlPingReply struct { - Retval int32 - ClientIndex uint32 - VpePid uint32 -} - -func (*ControlPingReply) GetMessageName() string { - return "control_ping_reply" -} -func (*ControlPingReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} -func (*ControlPingReply) GetCrcString() string { - return "f6b0b8ca" -} -func NewControlPingReply() api.Message { - return &ControlPingReply{} -} - -// Cli represents the VPP binary API message 'cli'. -// Generated from '/usr/share/vpp/api/vpe.api.json', line 48: -// -// "cli", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "client_index" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "u64", -// "cmd_in_shmem" -// ], -// { -// "crc": "0x23bfbfff" -// } -// -type Cli struct { - CmdInShmem uint64 -} - -func (*Cli) GetMessageName() string { - return "cli" -} -func (*Cli) GetMessageType() api.MessageType { - return api.RequestMessage -} -func (*Cli) GetCrcString() string { - return "23bfbfff" -} -func NewCli() api.Message { - return &Cli{} -} - -// CliInband represents the VPP binary API message 'cli_inband'. -// Generated from '/usr/share/vpp/api/vpe.api.json', line 70: -// -// "cli_inband", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "client_index" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "u32", -// "length" -// ], -// [ -// "u8", -// "cmd", -// 0, -// "length" -// ], -// { -// "crc": "0x74e00a49" -// } -// -type CliInband struct { - Length uint32 `struc:"sizeof=Cmd"` - Cmd []byte -} - -func (*CliInband) GetMessageName() string { - return "cli_inband" -} -func (*CliInband) GetMessageType() api.MessageType { - return api.RequestMessage -} -func (*CliInband) GetCrcString() string { - return "74e00a49" -} -func NewCliInband() api.Message { - return &CliInband{} -} - -// CliReply represents the VPP binary API message 'cli_reply'. -// Generated from '/usr/share/vpp/api/vpe.api.json', line 98: -// -// "cli_reply", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "i32", -// "retval" -// ], -// [ -// "u64", -// "reply_in_shmem" -// ], -// { -// "crc": "0x06d68297" -// } -// -type CliReply struct { - Retval int32 - ReplyInShmem uint64 -} - -func (*CliReply) GetMessageName() string { - return "cli_reply" -} -func (*CliReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} -func (*CliReply) GetCrcString() string { - return "06d68297" -} -func NewCliReply() api.Message { - return &CliReply{} -} - -// CliInbandReply represents the VPP binary API message 'cli_inband_reply'. -// Generated from '/usr/share/vpp/api/vpe.api.json', line 120: -// -// "cli_inband_reply", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "i32", -// "retval" -// ], -// [ -// "u32", -// "length" -// ], -// [ -// "u8", -// "reply", -// 0, -// "length" -// ], -// { -// "crc": "0x1f22bbb8" -// } -// -type CliInbandReply struct { - Retval int32 - Length uint32 `struc:"sizeof=Reply"` - Reply []byte -} - -func (*CliInbandReply) GetMessageName() string { - return "cli_inband_reply" -} -func (*CliInbandReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} -func (*CliInbandReply) GetCrcString() string { - return "1f22bbb8" -} -func NewCliInbandReply() api.Message { - return &CliInbandReply{} -} - -// GetNodeIndex represents the VPP binary API message 'get_node_index'. -// Generated from '/usr/share/vpp/api/vpe.api.json', line 148: -// -// "get_node_index", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "client_index" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "u8", -// "node_name", -// 64 -// ], -// { -// "crc": "0x6c9a495d" -// } -// -type GetNodeIndex struct { - NodeName []byte `struc:"[64]byte"` -} - -func (*GetNodeIndex) GetMessageName() string { - return "get_node_index" -} -func (*GetNodeIndex) GetMessageType() api.MessageType { - return api.RequestMessage -} -func (*GetNodeIndex) GetCrcString() string { - return "6c9a495d" -} -func NewGetNodeIndex() api.Message { - return &GetNodeIndex{} -} - -// GetNodeIndexReply represents the VPP binary API message 'get_node_index_reply'. -// Generated from '/usr/share/vpp/api/vpe.api.json', line 171: -// -// "get_node_index_reply", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "i32", -// "retval" -// ], -// [ -// "u32", -// "node_index" -// ], -// { -// "crc": "0xa8600b89" -// } -// -type GetNodeIndexReply struct { - Retval int32 - NodeIndex uint32 -} - -func (*GetNodeIndexReply) GetMessageName() string { - return "get_node_index_reply" -} -func (*GetNodeIndexReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} -func (*GetNodeIndexReply) GetCrcString() string { - return "a8600b89" -} -func NewGetNodeIndexReply() api.Message { - return &GetNodeIndexReply{} -} - -// AddNodeNext represents the VPP binary API message 'add_node_next'. -// Generated from '/usr/share/vpp/api/vpe.api.json', line 193: -// -// "add_node_next", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "client_index" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "u8", -// "node_name", -// 64 -// ], -// [ -// "u8", -// "next_name", -// 64 -// ], -// { -// "crc": "0x9ab92f7a" -// } -// -type AddNodeNext struct { - NodeName []byte `struc:"[64]byte"` - NextName []byte `struc:"[64]byte"` -} - -func (*AddNodeNext) GetMessageName() string { - return "add_node_next" -} -func (*AddNodeNext) GetMessageType() api.MessageType { - return api.RequestMessage -} -func (*AddNodeNext) GetCrcString() string { - return "9ab92f7a" -} -func NewAddNodeNext() api.Message { - return &AddNodeNext{} -} - -// AddNodeNextReply represents the VPP binary API message 'add_node_next_reply'. -// Generated from '/usr/share/vpp/api/vpe.api.json', line 221: -// -// "add_node_next_reply", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "i32", -// "retval" -// ], -// [ -// "u32", -// "next_index" -// ], -// { -// "crc": "0x2ed75f32" -// } -// -type AddNodeNextReply struct { - Retval int32 - NextIndex uint32 -} - -func (*AddNodeNextReply) GetMessageName() string { - return "add_node_next_reply" -} -func (*AddNodeNextReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} -func (*AddNodeNextReply) GetCrcString() string { - return "2ed75f32" -} -func NewAddNodeNextReply() api.Message { - return &AddNodeNextReply{} -} - -// ShowVersion represents the VPP binary API message 'show_version'. -// Generated from '/usr/share/vpp/api/vpe.api.json', line 243: -// -// "show_version", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "client_index" -// ], -// [ -// "u32", -// "context" -// ], -// { -// "crc": "0x51077d14" -// } -// -type ShowVersion struct { -} - -func (*ShowVersion) GetMessageName() string { - return "show_version" -} -func (*ShowVersion) GetMessageType() api.MessageType { - return api.RequestMessage -} -func (*ShowVersion) GetCrcString() string { - return "51077d14" -} -func NewShowVersion() api.Message { - return &ShowVersion{} -} - -// ShowVersionReply represents the VPP binary API message 'show_version_reply'. -// Generated from '/usr/share/vpp/api/vpe.api.json', line 261: -// -// "show_version_reply", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "i32", -// "retval" -// ], -// [ -// "u8", -// "program", -// 32 -// ], -// [ -// "u8", -// "version", -// 32 -// ], -// [ -// "u8", -// "build_date", -// 32 -// ], -// [ -// "u8", -// "build_directory", -// 256 -// ], -// { -// "crc": "0x8b5a13b4" -// } -// -type ShowVersionReply struct { - Retval int32 - Program []byte `struc:"[32]byte"` - Version []byte `struc:"[32]byte"` - BuildDate []byte `struc:"[32]byte"` - BuildDirectory []byte `struc:"[256]byte"` -} - -func (*ShowVersionReply) GetMessageName() string { - return "show_version_reply" -} -func (*ShowVersionReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} -func (*ShowVersionReply) GetCrcString() string { - return "8b5a13b4" -} -func NewShowVersionReply() api.Message { - return &ShowVersionReply{} -} - -// GetNodeGraph represents the VPP binary API message 'get_node_graph'. -// Generated from '/usr/share/vpp/api/vpe.api.json', line 299: -// -// "get_node_graph", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "client_index" -// ], -// [ -// "u32", -// "context" -// ], -// { -// "crc": "0x51077d14" -// } -// -type GetNodeGraph struct { -} - -func (*GetNodeGraph) GetMessageName() string { - return "get_node_graph" -} -func (*GetNodeGraph) GetMessageType() api.MessageType { - return api.RequestMessage -} -func (*GetNodeGraph) GetCrcString() string { - return "51077d14" -} -func NewGetNodeGraph() api.Message { - return &GetNodeGraph{} -} - -// GetNodeGraphReply represents the VPP binary API message 'get_node_graph_reply'. -// Generated from '/usr/share/vpp/api/vpe.api.json', line 317: -// -// "get_node_graph_reply", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "i32", -// "retval" -// ], -// [ -// "u64", -// "reply_in_shmem" -// ], -// { -// "crc": "0x06d68297" -// } -// -type GetNodeGraphReply struct { - Retval int32 - ReplyInShmem uint64 -} - -func (*GetNodeGraphReply) GetMessageName() string { - return "get_node_graph_reply" -} -func (*GetNodeGraphReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} -func (*GetNodeGraphReply) GetCrcString() string { - return "06d68297" -} -func NewGetNodeGraphReply() api.Message { - return &GetNodeGraphReply{} -} - -// GetNextIndex represents the VPP binary API message 'get_next_index'. -// Generated from '/usr/share/vpp/api/vpe.api.json', line 339: -// -// "get_next_index", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "client_index" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "u8", -// "node_name", -// 64 -// ], -// [ -// "u8", -// "next_name", -// 64 -// ], -// { -// "crc": "0x9ab92f7a" -// } -// -type GetNextIndex struct { - NodeName []byte `struc:"[64]byte"` - NextName []byte `struc:"[64]byte"` -} - -func (*GetNextIndex) GetMessageName() string { - return "get_next_index" -} -func (*GetNextIndex) GetMessageType() api.MessageType { - return api.RequestMessage -} -func (*GetNextIndex) GetCrcString() string { - return "9ab92f7a" -} -func NewGetNextIndex() api.Message { - return &GetNextIndex{} -} - -// GetNextIndexReply represents the VPP binary API message 'get_next_index_reply'. -// Generated from '/usr/share/vpp/api/vpe.api.json', line 367: -// -// "get_next_index_reply", -// [ -// "u16", -// "_vl_msg_id" -// ], -// [ -// "u32", -// "context" -// ], -// [ -// "i32", -// "retval" -// ], -// [ -// "u32", -// "next_index" -// ], -// { -// "crc": "0x2ed75f32" -// } -// -type GetNextIndexReply struct { - Retval int32 - NextIndex uint32 -} - -func (*GetNextIndexReply) GetMessageName() string { - return "get_next_index_reply" -} -func (*GetNextIndexReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} -func (*GetNextIndexReply) GetCrcString() string { - return "2ed75f32" -} -func NewGetNextIndexReply() api.Message { - return &GetNextIndexReply{} -} diff --git a/plugins/vpp/binapi/vxlan/pkgreflect.go b/plugins/vpp/binapi/vxlan/pkgreflect.go index d31e8a93ea..e0dd85918e 100644 --- a/plugins/vpp/binapi/vxlan/pkgreflect.go +++ b/plugins/vpp/binapi/vxlan/pkgreflect.go @@ -5,6 +5,7 @@ package vxlan import "reflect" var Types = map[string]reflect.Type{ + "Services": reflect.TypeOf((*Services)(nil)).Elem(), "SwInterfaceSetVxlanBypass": reflect.TypeOf((*SwInterfaceSetVxlanBypass)(nil)).Elem(), "SwInterfaceSetVxlanBypassReply": reflect.TypeOf((*SwInterfaceSetVxlanBypassReply)(nil)).Elem(), "VxlanAddDelTunnel": reflect.TypeOf((*VxlanAddDelTunnel)(nil)).Elem(), diff --git a/plugins/vpp/binapi/vxlan/vxlan.go b/plugins/vpp/binapi/vxlan/vxlan.ba.go similarity index 83% rename from plugins/vpp/binapi/vxlan/vxlan.go rename to plugins/vpp/binapi/vxlan/vxlan.ba.go index 8c967ed09f..e17e26c2c9 100644 --- a/plugins/vpp/binapi/vxlan/vxlan.go +++ b/plugins/vpp/binapi/vxlan/vxlan.ba.go @@ -1,12 +1,30 @@ -// Code generated by govpp binapi-generator DO NOT EDIT. -// Package vxlan represents the VPP binary API of the 'vxlan' VPP module. -// Generated from '/usr/share/vpp/api/vxlan.api.json' +// Code generated by GoVPP binapi-generator. DO NOT EDIT. +// source: /usr/share/vpp/api/vxlan.api.json + +/* +Package vxlan is a generated VPP binary API of the 'vxlan' VPP module. + +It is generated from this file: + vxlan.api.json + +It contains these VPP binary API objects: + 8 messages + 4 services +*/ package vxlan import "git.fd.io/govpp.git/api" +import "github.com/lunixbochs/struc" +import "bytes" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = struc.Pack +var _ = bytes.NewBuffer + +/* Messages */ // VxlanAddDelTunnel represents the VPP binary API message 'vxlan_add_del_tunnel'. -// Generated from '/usr/share/vpp/api/vxlan.api.json', line 4: +// Generated from 'vxlan.api.json', line 4: // // "vxlan_add_del_tunnel", // [ @@ -65,7 +83,7 @@ import "git.fd.io/govpp.git/api" // type VxlanAddDelTunnel struct { IsAdd uint8 - IsIpv6 uint8 + IsIPv6 uint8 Instance uint32 SrcAddress []byte `struc:"[16]byte"` DstAddress []byte `struc:"[16]byte"` @@ -78,18 +96,18 @@ type VxlanAddDelTunnel struct { func (*VxlanAddDelTunnel) GetMessageName() string { return "vxlan_add_del_tunnel" } -func (*VxlanAddDelTunnel) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*VxlanAddDelTunnel) GetCrcString() string { return "00f4bdd0" } +func (*VxlanAddDelTunnel) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewVxlanAddDelTunnel() api.Message { return &VxlanAddDelTunnel{} } // VxlanAddDelTunnelReply represents the VPP binary API message 'vxlan_add_del_tunnel_reply'. -// Generated from '/usr/share/vpp/api/vxlan.api.json', line 60: +// Generated from 'vxlan.api.json', line 60: // // "vxlan_add_del_tunnel_reply", // [ @@ -120,18 +138,18 @@ type VxlanAddDelTunnelReply struct { func (*VxlanAddDelTunnelReply) GetMessageName() string { return "vxlan_add_del_tunnel_reply" } -func (*VxlanAddDelTunnelReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*VxlanAddDelTunnelReply) GetCrcString() string { return "fda5941f" } +func (*VxlanAddDelTunnelReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewVxlanAddDelTunnelReply() api.Message { return &VxlanAddDelTunnelReply{} } // VxlanTunnelDump represents the VPP binary API message 'vxlan_tunnel_dump'. -// Generated from '/usr/share/vpp/api/vxlan.api.json', line 82: +// Generated from 'vxlan.api.json', line 82: // // "vxlan_tunnel_dump", // [ @@ -161,18 +179,18 @@ type VxlanTunnelDump struct { func (*VxlanTunnelDump) GetMessageName() string { return "vxlan_tunnel_dump" } -func (*VxlanTunnelDump) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*VxlanTunnelDump) GetCrcString() string { return "529cb13f" } +func (*VxlanTunnelDump) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewVxlanTunnelDump() api.Message { return &VxlanTunnelDump{} } // VxlanTunnelDetails represents the VPP binary API message 'vxlan_tunnel_details'. -// Generated from '/usr/share/vpp/api/vxlan.api.json', line 104: +// Generated from 'vxlan.api.json', line 104: // // "vxlan_tunnel_details", // [ @@ -234,24 +252,24 @@ type VxlanTunnelDetails struct { EncapVrfID uint32 DecapNextIndex uint32 Vni uint32 - IsIpv6 uint8 + IsIPv6 uint8 } func (*VxlanTunnelDetails) GetMessageName() string { return "vxlan_tunnel_details" } -func (*VxlanTunnelDetails) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*VxlanTunnelDetails) GetCrcString() string { return "ce38e127" } +func (*VxlanTunnelDetails) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewVxlanTunnelDetails() api.Message { return &VxlanTunnelDetails{} } // SwInterfaceSetVxlanBypass represents the VPP binary API message 'sw_interface_set_vxlan_bypass'. -// Generated from '/usr/share/vpp/api/vxlan.api.json', line 156: +// Generated from 'vxlan.api.json', line 156: // // "sw_interface_set_vxlan_bypass", // [ @@ -284,25 +302,25 @@ func NewVxlanTunnelDetails() api.Message { // type SwInterfaceSetVxlanBypass struct { SwIfIndex uint32 - IsIpv6 uint8 + IsIPv6 uint8 Enable uint8 } func (*SwInterfaceSetVxlanBypass) GetMessageName() string { return "sw_interface_set_vxlan_bypass" } -func (*SwInterfaceSetVxlanBypass) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*SwInterfaceSetVxlanBypass) GetCrcString() string { return "e74ca095" } +func (*SwInterfaceSetVxlanBypass) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewSwInterfaceSetVxlanBypass() api.Message { return &SwInterfaceSetVxlanBypass{} } // SwInterfaceSetVxlanBypassReply represents the VPP binary API message 'sw_interface_set_vxlan_bypass_reply'. -// Generated from '/usr/share/vpp/api/vxlan.api.json', line 186: +// Generated from 'vxlan.api.json', line 186: // // "sw_interface_set_vxlan_bypass_reply", // [ @@ -328,18 +346,18 @@ type SwInterfaceSetVxlanBypassReply struct { func (*SwInterfaceSetVxlanBypassReply) GetMessageName() string { return "sw_interface_set_vxlan_bypass_reply" } -func (*SwInterfaceSetVxlanBypassReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*SwInterfaceSetVxlanBypassReply) GetCrcString() string { return "e8d4e804" } +func (*SwInterfaceSetVxlanBypassReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewSwInterfaceSetVxlanBypassReply() api.Message { return &SwInterfaceSetVxlanBypassReply{} } // VxlanOffloadRx represents the VPP binary API message 'vxlan_offload_rx'. -// Generated from '/usr/share/vpp/api/vxlan.api.json', line 204: +// Generated from 'vxlan.api.json', line 204: // // "vxlan_offload_rx", // [ @@ -379,18 +397,18 @@ type VxlanOffloadRx struct { func (*VxlanOffloadRx) GetMessageName() string { return "vxlan_offload_rx" } -func (*VxlanOffloadRx) GetMessageType() api.MessageType { - return api.RequestMessage -} func (*VxlanOffloadRx) GetCrcString() string { return "f0b08786" } +func (*VxlanOffloadRx) GetMessageType() api.MessageType { + return api.RequestMessage +} func NewVxlanOffloadRx() api.Message { return &VxlanOffloadRx{} } // VxlanOffloadRxReply represents the VPP binary API message 'vxlan_offload_rx_reply'. -// Generated from '/usr/share/vpp/api/vxlan.api.json', line 234: +// Generated from 'vxlan.api.json', line 234: // // "vxlan_offload_rx_reply", // [ @@ -416,12 +434,32 @@ type VxlanOffloadRxReply struct { func (*VxlanOffloadRxReply) GetMessageName() string { return "vxlan_offload_rx_reply" } -func (*VxlanOffloadRxReply) GetMessageType() api.MessageType { - return api.ReplyMessage -} func (*VxlanOffloadRxReply) GetCrcString() string { return "e8d4e804" } +func (*VxlanOffloadRxReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} func NewVxlanOffloadRxReply() api.Message { return &VxlanOffloadRxReply{} } + +/* Services */ + +type Services interface { + DumpVxlanTunnel(*VxlanTunnelDump) (*VxlanTunnelDetails, error) + SwInterfaceSetVxlanBypass(*SwInterfaceSetVxlanBypass) (*SwInterfaceSetVxlanBypassReply, error) + VxlanAddDelTunnel(*VxlanAddDelTunnel) (*VxlanAddDelTunnelReply, error) + VxlanOffloadRx(*VxlanOffloadRx) (*VxlanOffloadRxReply, error) +} + +func init() { + api.RegisterMessage((*VxlanAddDelTunnel)(nil), "vxlan.VxlanAddDelTunnel") + api.RegisterMessage((*VxlanAddDelTunnelReply)(nil), "vxlan.VxlanAddDelTunnelReply") + api.RegisterMessage((*VxlanTunnelDump)(nil), "vxlan.VxlanTunnelDump") + api.RegisterMessage((*VxlanTunnelDetails)(nil), "vxlan.VxlanTunnelDetails") + api.RegisterMessage((*SwInterfaceSetVxlanBypass)(nil), "vxlan.SwInterfaceSetVxlanBypass") + api.RegisterMessage((*SwInterfaceSetVxlanBypassReply)(nil), "vxlan.SwInterfaceSetVxlanBypassReply") + api.RegisterMessage((*VxlanOffloadRx)(nil), "vxlan.VxlanOffloadRx") + api.RegisterMessage((*VxlanOffloadRxReply)(nil), "vxlan.VxlanOffloadRxReply") +} diff --git a/plugins/vpp/data_change.go b/plugins/vpp/data_change.go index 8cbbea1cf7..1b1b925b2b 100644 --- a/plugins/vpp/data_change.go +++ b/plugins/vpp/data_change.go @@ -35,11 +35,11 @@ func (plugin *Plugin) changePropagateRequest(dataChng datasync.ChangeEvent, call key := dataChng.GetKey() // Skip potential changes on error keys - if strings.HasPrefix(key, interfaces.InterfaceErrorPrefix()) || strings.HasPrefix(key, l2.BridgeDomainErrorPrefix()) { + if strings.HasPrefix(key, interfaces.ErrorPrefix) || strings.HasPrefix(key, l2.BdErrPrefix) { return false, nil } plugin.Log.Debug("Start processing change for key: ", key) - if strings.HasPrefix(key, acl.KeyPrefix()) { + if strings.HasPrefix(key, acl.Prefix) { var value, prevValue acl.AccessLists_Acl if err := dataChng.GetValue(&value); err != nil { return false, err @@ -51,7 +51,7 @@ func (plugin *Plugin) changePropagateRequest(dataChng datasync.ChangeEvent, call } else { return false, err } - } else if strings.HasPrefix(key, interfaces.InterfaceKeyPrefix()) { + } else if strings.HasPrefix(key, interfaces.Prefix) { var value, prevValue interfaces.Interfaces_Interface if err := dataChng.GetValue(&value); err != nil { return false, err @@ -63,7 +63,7 @@ func (plugin *Plugin) changePropagateRequest(dataChng datasync.ChangeEvent, call } else { return false, err } - } else if strings.HasPrefix(key, bfd.SessionKeyPrefix()) { + } else if strings.HasPrefix(key, bfd.SessionPrefix) { var value, prevValue bfd.SingleHopBFD_Session if err := dataChng.GetValue(&value); err != nil { return false, err @@ -75,7 +75,7 @@ func (plugin *Plugin) changePropagateRequest(dataChng datasync.ChangeEvent, call } else { return false, err } - } else if strings.HasPrefix(key, bfd.AuthKeysKeyPrefix()) { + } else if strings.HasPrefix(key, bfd.AuthKeysPrefix) { var value, prevValue bfd.SingleHopBFD_Key if err := dataChng.GetValue(&value); err != nil { return false, err @@ -87,7 +87,7 @@ func (plugin *Plugin) changePropagateRequest(dataChng datasync.ChangeEvent, call } else { return false, err } - } else if strings.HasPrefix(key, bfd.EchoFunctionKeyPrefix()) { + } else if strings.HasPrefix(key, bfd.EchoFunctionPrefix) { var value, prevValue bfd.SingleHopBFD_EchoFunction if err := dataChng.GetValue(&value); err != nil { return false, err @@ -99,7 +99,7 @@ func (plugin *Plugin) changePropagateRequest(dataChng datasync.ChangeEvent, call } else { return false, err } - } else if strings.HasPrefix(key, l2.BridgeDomainKeyPrefix()) { + } else if strings.HasPrefix(key, l2.BdPrefix) { fib, _, _ := l2.ParseFibKey(key) if fib { // L2 FIB entry @@ -128,7 +128,7 @@ func (plugin *Plugin) changePropagateRequest(dataChng datasync.ChangeEvent, call return false, err } } - } else if strings.HasPrefix(key, l2.XConnectKeyPrefix()) { + } else if strings.HasPrefix(key, l2.XConnectPrefix) { var value, prevValue l2.XConnectPairs_XConnectPair if err := dataChng.GetValue(&value); err != nil { return false, err @@ -140,7 +140,7 @@ func (plugin *Plugin) changePropagateRequest(dataChng datasync.ChangeEvent, call } else { return false, err } - } else if strings.HasPrefix(key, l3.VrfKeyPrefix()) { + } else if strings.HasPrefix(key, l3.VrfPrefix) { isRoute, vrfFromKey, _, _, _ := l3.ParseRouteKey(key) if isRoute { // Route @@ -156,11 +156,9 @@ func (plugin *Plugin) changePropagateRequest(dataChng datasync.ChangeEvent, call return false, err } } else { - // Vrf - // TODO vrf not implemented yet - plugin.Log.Warn("VRFs are not supported yet") + plugin.Log.Warnf("Key '%s' not supported", key) } - } else if strings.HasPrefix(key, l3.ArpKeyPrefix()) { + } else if strings.HasPrefix(key, l3.ArpPrefix) { _, _, err := l3.ParseArpKey(key) if err != nil { return false, err @@ -176,7 +174,7 @@ func (plugin *Plugin) changePropagateRequest(dataChng datasync.ChangeEvent, call } else { return false, err } - } else if strings.HasPrefix(key, l3.ProxyArpInterfacePrefix()) { + } else if strings.HasPrefix(key, l3.ProxyARPInterfacePrefix) { var value, prevValue l3.ProxyArpInterfaces_InterfaceList if err := dataChng.GetValue(&value); err != nil { return false, err @@ -188,7 +186,7 @@ func (plugin *Plugin) changePropagateRequest(dataChng datasync.ChangeEvent, call } else { return false, err } - } else if strings.HasPrefix(key, l3.ProxyArpRangePrefix()) { + } else if strings.HasPrefix(key, l3.ProxyARPRangePrefix) { var value, prevValue l3.ProxyArpRanges_RangeList if err := dataChng.GetValue(&value); err != nil { return false, err @@ -200,31 +198,41 @@ func (plugin *Plugin) changePropagateRequest(dataChng datasync.ChangeEvent, call } else { return false, err } - } else if strings.HasPrefix(key, l4.AppNamespacesKeyPrefix()) { - var value, prevValue l4.AppNamespaces_AppNamespace + } else if strings.HasPrefix(key, l3.IPScanNeighPrefix) { + var value l3.IPScanNeighbor if err := dataChng.GetValue(&value); err != nil { return false, err } - if diff, err := dataChng.GetPrevValue(&prevValue); err == nil { - if err := plugin.dataChangeAppNamespace(diff, &value, &prevValue, dataChng.GetChangeType()); err != nil { - return false, err - } - } else { + if err := plugin.dataChangeIPScanNeigh(&value, dataChng.GetChangeType()); err != nil { return false, err } - } else if strings.HasPrefix(key, l4.FeatureKeyPrefix()) { - var value, prevValue l4.L4Features - if err := dataChng.GetValue(&value); err != nil { - return false, err - } - if _, err := dataChng.GetPrevValue(&prevValue); err == nil { - if err := plugin.dataChangeL4Features(&value, &prevValue, dataChng.GetChangeType()); err != nil { + } else if strings.HasPrefix(key, l4.Prefix) { + if strings.HasPrefix(key, l4.NamespacesPrefix) { + var value, prevValue l4.AppNamespaces_AppNamespace + if err := dataChng.GetValue(&value); err != nil { + return false, err + } + if diff, err := dataChng.GetPrevValue(&prevValue); err == nil { + if err := plugin.dataChangeAppNamespace(diff, &value, &prevValue, dataChng.GetChangeType()); err != nil { + return false, err + } + } else { + return false, err + } + } else if strings.HasPrefix(key, l4.FeaturesPrefix) { + var value, prevValue l4.L4Features + if err := dataChng.GetValue(&value); err != nil { + return false, err + } + if _, err := dataChng.GetPrevValue(&prevValue); err == nil { + if err := plugin.dataChangeL4Features(&value, &prevValue, dataChng.GetChangeType()); err != nil { + return false, err + } + } else { return false, err } - } else { - return false, err } - } else if strings.HasPrefix(key, stn.KeyPrefix()) { + } else if strings.HasPrefix(key, stn.Prefix) { var value, prevValue stn.STN_Rule if err := dataChng.GetValue(&value); err != nil { return false, err @@ -236,7 +244,7 @@ func (plugin *Plugin) changePropagateRequest(dataChng datasync.ChangeEvent, call } else { return false, err } - } else if strings.HasPrefix(key, nat.GlobalConfigPrefix()) { + } else if strings.HasPrefix(key, nat.GlobalPrefix) { // Global NAT config var value, prevValue nat.Nat44Global if err := dataChng.GetValue(&value); err != nil { @@ -249,7 +257,7 @@ func (plugin *Plugin) changePropagateRequest(dataChng datasync.ChangeEvent, call } else { return false, err } - } else if strings.HasPrefix(key, nat.SNatPrefix()) { + } else if strings.HasPrefix(key, nat.SNatPrefix) { // SNAT config var value, prevValue nat.Nat44SNat_SNatConfig if err := dataChng.GetValue(&value); err != nil { @@ -262,7 +270,7 @@ func (plugin *Plugin) changePropagateRequest(dataChng datasync.ChangeEvent, call } else { return false, err } - } else if strings.HasPrefix(key, nat.DNatPrefix()) { + } else if strings.HasPrefix(key, nat.DNatPrefix) { // DNAT config var value, prevValue nat.Nat44DNat_DNatConfig if err := dataChng.GetValue(&value); err != nil { @@ -371,7 +379,7 @@ func (plugin *Plugin) extractFrom(dataChng datasync.ChangeEvent, value proto.Mes // dataChangeACL propagates data change to the particular aclConfigurator. func (plugin *Plugin) dataChangeACL(diff bool, value *acl.AccessLists_Acl, prevValue *acl.AccessLists_Acl, - changeType datasync.PutDel) error { + changeType datasync.Op) error { plugin.Log.Debug("dataChangeAcl ", diff, " ", changeType, " ", value, " ", prevValue) if datasync.Delete == changeType { @@ -384,7 +392,7 @@ func (plugin *Plugin) dataChangeACL(diff bool, value *acl.AccessLists_Acl, prevV // DataChangeIface propagates data change to the ifConfigurator. func (plugin *Plugin) dataChangeIface(diff bool, value *interfaces.Interfaces_Interface, prevValue *interfaces.Interfaces_Interface, - changeType datasync.PutDel) error { + changeType datasync.Op) error { plugin.Log.Debug("dataChangeIface ", diff, " ", changeType, " ", value, " ", prevValue) if datasync.Delete == changeType { @@ -397,7 +405,7 @@ func (plugin *Plugin) dataChangeIface(diff bool, value *interfaces.Interfaces_In // DataChangeBfdSession propagates data change to the bfdConfigurator. func (plugin *Plugin) dataChangeBfdSession(diff bool, value *bfd.SingleHopBFD_Session, prevValue *bfd.SingleHopBFD_Session, - changeType datasync.PutDel) error { + changeType datasync.Op) error { plugin.Log.Debug("dataChangeBfdSession ", diff, " ", changeType, " ", value, " ", prevValue) if datasync.Delete == changeType { @@ -410,7 +418,7 @@ func (plugin *Plugin) dataChangeBfdSession(diff bool, value *bfd.SingleHopBFD_Se // DataChangeBfdKey propagates data change to the bfdConfigurator. func (plugin *Plugin) dataChangeBfdKey(diff bool, value *bfd.SingleHopBFD_Key, prevValue *bfd.SingleHopBFD_Key, - changeType datasync.PutDel) error { + changeType datasync.Op) error { plugin.Log.Debug("dataChangeBfdKey ", diff, " ", changeType, " ", value, " ", prevValue) if datasync.Delete == changeType { @@ -423,7 +431,7 @@ func (plugin *Plugin) dataChangeBfdKey(diff bool, value *bfd.SingleHopBFD_Key, p // DataChangeBfdEchoFunction propagates data change to the bfdConfigurator. func (plugin *Plugin) dataChangeBfdEchoFunction(diff bool, value *bfd.SingleHopBFD_EchoFunction, prevValue *bfd.SingleHopBFD_EchoFunction, - changeType datasync.PutDel) error { + changeType datasync.Op) error { plugin.Log.Debug("dataChangeBfdEchoFunction ", diff, " ", changeType, " ", value, " ", prevValue) if datasync.Delete == changeType { @@ -436,7 +444,7 @@ func (plugin *Plugin) dataChangeBfdEchoFunction(diff bool, value *bfd.SingleHopB // dataChangeBD propagates data change to the bdConfigurator. func (plugin *Plugin) dataChangeBD(diff bool, value *l2.BridgeDomains_BridgeDomain, prevValue *l2.BridgeDomains_BridgeDomain, - changeType datasync.PutDel) error { + changeType datasync.Op) error { plugin.Log.Debug("dataChangeBD ", diff, " ", changeType, " ", value, " ", prevValue) if datasync.Delete == changeType { @@ -449,7 +457,7 @@ func (plugin *Plugin) dataChangeBD(diff bool, value *l2.BridgeDomains_BridgeDoma // dataChangeFIB propagates data change to the fibConfigurator. func (plugin *Plugin) dataChangeFIB(diff bool, value *l2.FibTable_FibEntry, prevValue *l2.FibTable_FibEntry, - changeType datasync.PutDel, callback func(error)) error { + changeType datasync.Op, callback func(error)) error { plugin.Log.Debug("dataChangeFIB diff=", diff, " ", changeType, " ", value, " ", prevValue) if datasync.Delete == changeType { @@ -462,7 +470,7 @@ func (plugin *Plugin) dataChangeFIB(diff bool, value *l2.FibTable_FibEntry, prev // DataChangeIface propagates data change to the xcConfugurator. func (plugin *Plugin) dataChangeXCon(diff bool, value *l2.XConnectPairs_XConnectPair, prevValue *l2.XConnectPairs_XConnectPair, - changeType datasync.PutDel) error { + changeType datasync.Op) error { plugin.Log.Debug("dataChangeXCon ", diff, " ", changeType, " ", value, " ", prevValue) if datasync.Delete == changeType { @@ -476,7 +484,7 @@ func (plugin *Plugin) dataChangeXCon(diff bool, value *l2.XConnectPairs_XConnect // DataChangeStaticRoute propagates data change to the routeConfigurator. func (plugin *Plugin) dataChangeStaticRoute(diff bool, value *l3.StaticRoutes_Route, prevValue *l3.StaticRoutes_Route, - vrfFromKey string, changeType datasync.PutDel) error { + vrfFromKey string, changeType datasync.Op) error { plugin.Log.Debug("dataChangeStaticRoute ", diff, " ", changeType, " ", value, " ", prevValue) if datasync.Delete == changeType { @@ -489,7 +497,7 @@ func (plugin *Plugin) dataChangeStaticRoute(diff bool, value *l3.StaticRoutes_Ro // dataChangeARP propagates data change to the arpConfigurator func (plugin *Plugin) dataChangeARP(diff bool, value *l3.ArpTable_ArpEntry, prevValue *l3.ArpTable_ArpEntry, - changeType datasync.PutDel) error { + changeType datasync.Op) error { plugin.Log.Debug("dataChangeARP diff=", diff, " ", changeType, " ", value, " ", prevValue) if datasync.Delete == changeType { @@ -502,7 +510,7 @@ func (plugin *Plugin) dataChangeARP(diff bool, value *l3.ArpTable_ArpEntry, prev // dataChangeProxyARPInterface propagates data change to the arpConfigurator func (plugin *Plugin) dataChangeProxyARPInterface(diff bool, value, prevValue *l3.ProxyArpInterfaces_InterfaceList, - changeType datasync.PutDel) error { + changeType datasync.Op) error { plugin.Log.Debug("dataChangeProxyARPInterface diff=", diff, " ", changeType, " ", value, " ", prevValue) if datasync.Delete == changeType { @@ -515,7 +523,7 @@ func (plugin *Plugin) dataChangeProxyARPInterface(diff bool, value, prevValue *l // dataChangeProxyARPRange propagates data change to the arpConfigurator func (plugin *Plugin) dataChangeProxyARPRange(diff bool, value, prevValue *l3.ProxyArpRanges_RangeList, - changeType datasync.PutDel) error { + changeType datasync.Op) error { plugin.Log.Debug("dataChangeProxyARPRange diff=", diff, " ", changeType, " ", value, " ", prevValue) if datasync.Delete == changeType { @@ -526,9 +534,19 @@ func (plugin *Plugin) dataChangeProxyARPRange(diff bool, value, prevValue *l3.Pr return plugin.proxyArpConfigurator.AddRange(value) } +// dataChangeIPScanNeigh propagates data change to the ipNeighConfigurator +func (plugin *Plugin) dataChangeIPScanNeigh(value *l3.IPScanNeighbor, + changeType datasync.Op) error { + + if datasync.Delete == changeType { + return plugin.ipNeighConfigurator.Unset() + } + return plugin.ipNeighConfigurator.Set(value) +} + // DataChangeStaticRoute propagates data change to the l4Configurator func (plugin *Plugin) dataChangeAppNamespace(diff bool, value *l4.AppNamespaces_AppNamespace, prevValue *l4.AppNamespaces_AppNamespace, - changeType datasync.PutDel) error { + changeType datasync.Op) error { plugin.Log.Debug("dataChangeL4AppNamespace ", diff, " ", changeType, " ", value, " ", prevValue) if datasync.Delete == changeType { @@ -541,7 +559,7 @@ func (plugin *Plugin) dataChangeAppNamespace(diff bool, value *l4.AppNamespaces_ // DataChangeL4Features propagates data change to the l4Configurator func (plugin *Plugin) dataChangeL4Features(value *l4.L4Features, prevValue *l4.L4Features, - changeType datasync.PutDel) error { + changeType datasync.Op) error { plugin.Log.Debug("dataChangeL4Feature ", changeType, " ", value, " ", prevValue) // diff and previous value is not important, features flag can be either set or not. @@ -553,7 +571,7 @@ func (plugin *Plugin) dataChangeL4Features(value *l4.L4Features, prevValue *l4.L } // DataChangeStnRule propagates data change to the stn configurator -func (plugin *Plugin) dataChangeStnRule(diff bool, value *stn.STN_Rule, prevValue *stn.STN_Rule, changeType datasync.PutDel) error { +func (plugin *Plugin) dataChangeStnRule(diff bool, value *stn.STN_Rule, prevValue *stn.STN_Rule, changeType datasync.Op) error { plugin.Log.Debug("stnRuleChange diff->", diff, " changeType->", changeType, " value->", value, " prevValue->", prevValue) if datasync.Delete == changeType { @@ -565,7 +583,7 @@ func (plugin *Plugin) dataChangeStnRule(diff bool, value *stn.STN_Rule, prevValu } // dataChangeNatGlobal propagates data change to the nat configurator -func (plugin *Plugin) dataChangeNatGlobal(diff bool, value, prevValue *nat.Nat44Global, changeType datasync.PutDel) error { +func (plugin *Plugin) dataChangeNatGlobal(diff bool, value, prevValue *nat.Nat44Global, changeType datasync.Op) error { plugin.Log.Debug("natGlobalChange diff->", diff, " changeType->", changeType, " value->", value, " prevValue->", prevValue) if datasync.Delete == changeType { @@ -577,7 +595,7 @@ func (plugin *Plugin) dataChangeNatGlobal(diff bool, value, prevValue *nat.Nat44 } // dataChangeSNat propagates data change to the nat configurator -func (plugin *Plugin) dataChangeSNat(diff bool, value, prevValue *nat.Nat44SNat_SNatConfig, changeType datasync.PutDel) error { +func (plugin *Plugin) dataChangeSNat(diff bool, value, prevValue *nat.Nat44SNat_SNatConfig, changeType datasync.Op) error { plugin.Log.Debug("sNatChange diff->", diff, " changeType->", changeType, " value->", value, " prevValue->", prevValue) if datasync.Delete == changeType { @@ -589,7 +607,7 @@ func (plugin *Plugin) dataChangeSNat(diff bool, value, prevValue *nat.Nat44SNat_ } // dataChangeDNat propagates data change to the nat configurator -func (plugin *Plugin) dataChangeDNat(diff bool, value, prevValue *nat.Nat44DNat_DNatConfig, changeType datasync.PutDel) error { +func (plugin *Plugin) dataChangeDNat(diff bool, value, prevValue *nat.Nat44DNat_DNatConfig, changeType datasync.Op) error { plugin.Log.Debug("dNatChange diff->", diff, " changeType->", changeType, " value->", value, " prevValue->", prevValue) if datasync.Delete == changeType { @@ -601,7 +619,7 @@ func (plugin *Plugin) dataChangeDNat(diff bool, value, prevValue *nat.Nat44DNat_ } // dataChangeIPSecSPD propagates data change to the IPSec configurator -func (plugin *Plugin) dataChangeIPSecSPD(diff bool, value, prevValue *ipsec.SecurityPolicyDatabases_SPD, changeType datasync.PutDel) error { +func (plugin *Plugin) dataChangeIPSecSPD(diff bool, value, prevValue *ipsec.SecurityPolicyDatabases_SPD, changeType datasync.Op) error { plugin.Log.Debug("dataChangeIPSecSPD diff->", diff, " changeType->", changeType, " value->", value, " prevValue->", prevValue) if datasync.Delete == changeType { @@ -613,7 +631,7 @@ func (plugin *Plugin) dataChangeIPSecSPD(diff bool, value, prevValue *ipsec.Secu } // dataChangeIPSecSA propagates data change to the IPSec configurator -func (plugin *Plugin) dataChangeIPSecSA(diff bool, value, prevValue *ipsec.SecurityAssociations_SA, changeType datasync.PutDel) error { +func (plugin *Plugin) dataChangeIPSecSA(diff bool, value, prevValue *ipsec.SecurityAssociations_SA, changeType datasync.Op) error { plugin.Log.Debug("dataChangeIPSecSA diff->", diff, " changeType->", changeType, " value->", value, " prevValue->", prevValue) if datasync.Delete == changeType { @@ -625,7 +643,7 @@ func (plugin *Plugin) dataChangeIPSecSA(diff bool, value, prevValue *ipsec.Secur } // dataChangeIPSecTunnel propagates data change to the IPSec configurator -func (plugin *Plugin) dataChangeIPSecTunnel(diff bool, value, prevValue *ipsec.TunnelInterfaces_Tunnel, changeType datasync.PutDel) error { +func (plugin *Plugin) dataChangeIPSecTunnel(diff bool, value, prevValue *ipsec.TunnelInterfaces_Tunnel, changeType datasync.Op) error { plugin.Log.Debug("dataChangeIPSecTunnel diff->", diff, " changeType->", changeType, " value->", value, " prevValue->", prevValue) if datasync.Delete == changeType { @@ -637,7 +655,7 @@ func (plugin *Plugin) dataChangeIPSecTunnel(diff bool, value, prevValue *ipsec.T } // DataChangeLocalSID handles change events from ETCD related to local SIDs -func (plugin *Plugin) dataChangeLocalSID(diff bool, value *srv6.LocalSID, prevValue *srv6.LocalSID, changeType datasync.PutDel) error { +func (plugin *Plugin) dataChangeLocalSID(diff bool, value *srv6.LocalSID, prevValue *srv6.LocalSID, changeType datasync.Op) error { plugin.Log.Debug("dataChangeLocalSIDs ", diff, " ", changeType, " ", value, " ", prevValue) if datasync.Delete == changeType { return plugin.srv6Configurator.DeleteLocalSID(prevValue) @@ -648,7 +666,7 @@ func (plugin *Plugin) dataChangeLocalSID(diff bool, value *srv6.LocalSID, prevVa } // dataChangePolicy handles change events from ETCD related to policies -func (plugin *Plugin) dataChangePolicy(diff bool, value *srv6.Policy, prevValue *srv6.Policy, changeType datasync.PutDel) error { +func (plugin *Plugin) dataChangePolicy(diff bool, value *srv6.Policy, prevValue *srv6.Policy, changeType datasync.Op) error { plugin.Log.Debug("dataChangePolicy ", diff, " ", changeType, " ", value, " ", prevValue) if datasync.Delete == changeType { return plugin.srv6Configurator.RemovePolicy(prevValue) @@ -659,7 +677,7 @@ func (plugin *Plugin) dataChangePolicy(diff bool, value *srv6.Policy, prevValue } // dataChangePolicySegment handles change events from ETCD related to policies segments -func (plugin *Plugin) dataChangePolicySegment(segmentName string, diff bool, value *srv6.PolicySegment, prevValue *srv6.PolicySegment, changeType datasync.PutDel) error { +func (plugin *Plugin) dataChangePolicySegment(segmentName string, diff bool, value *srv6.PolicySegment, prevValue *srv6.PolicySegment, changeType datasync.Op) error { plugin.Log.Debug("dataChangePolicySegment ", segmentName, " ", diff, " ", changeType, " ", value, " ", prevValue) if datasync.Delete == changeType { return plugin.srv6Configurator.RemovePolicySegment(segmentName, prevValue) @@ -670,7 +688,7 @@ func (plugin *Plugin) dataChangePolicySegment(segmentName string, diff bool, val } // dataChangeSteering handles change events from ETCD related to steering -func (plugin *Plugin) dataChangeSteering(steeringName string, diff bool, value *srv6.Steering, prevValue *srv6.Steering, changeType datasync.PutDel) error { +func (plugin *Plugin) dataChangeSteering(steeringName string, diff bool, value *srv6.Steering, prevValue *srv6.Steering, changeType datasync.Op) error { plugin.Log.Debug("dataChangeSteering ", steeringName, " ", diff, " ", changeType, " ", value, " ", prevValue) if datasync.Delete == changeType { return plugin.srv6Configurator.RemoveSteering(steeringName, prevValue) diff --git a/plugins/vpp/data_resync.go b/plugins/vpp/data_resync.go index e056517254..452c3c4d8f 100644 --- a/plugins/vpp/data_resync.go +++ b/plugins/vpp/data_resync.go @@ -15,13 +15,11 @@ package vpp import ( + "fmt" "strconv" "strings" - "time" - "fmt" - "github.com/ligato/cn-infra/datasync" "github.com/ligato/cn-infra/logging" "github.com/ligato/vpp-agent/plugins/vpp/model/acl" @@ -63,6 +61,8 @@ type DataResyncReq struct { ProxyArpInterfaces []*l3.ProxyArpInterfaces_InterfaceList // ProxyArpRanges is a list af all proxy ARP ranges that are expected to be in VPP after RESYNC. ProxyArpRanges []*l3.ProxyArpRanges_RangeList + // IPScanNeigh is a IP scan neighbor config that is expected to be set in VPP after RESYNC. + IPScanNeigh *l3.IPScanNeighbor // L4Features is a bool flag that is expected to be set in VPP after RESYNC. L4Features *l4.L4Features // AppNamespaces is a list af all App Namespaces that are expected to be in VPP after RESYNC. @@ -106,6 +106,7 @@ func NewDataResyncReq() *DataResyncReq { ArpEntries: []*l3.ArpTable_ArpEntry{}, ProxyArpInterfaces: []*l3.ProxyArpInterfaces_InterfaceList{}, ProxyArpRanges: []*l3.ProxyArpRanges_RangeList{}, + IPScanNeigh: &l3.IPScanNeighbor{}, L4Features: &l4.L4Features{}, AppNamespaces: []*l4.AppNamespaces_AppNamespace{}, StnRules: []*stn.STN_Rule{}, @@ -159,92 +160,97 @@ func (plugin *Plugin) resyncConfig(req *DataResyncReq) error { // store all resync errors var resyncErrs []error - if !plugin.droppedFromResync(interfaces.InterfaceKeyPrefix()) { + if !plugin.droppedFromResync(interfaces.Prefix) { if errs := plugin.ifConfigurator.Resync(req.Interfaces); errs != nil { resyncErrs = append(resyncErrs, errs...) } } - if !plugin.droppedFromResync(acl.KeyPrefix()) { + if !plugin.droppedFromResync(acl.Prefix) { if err := plugin.aclConfigurator.Resync(req.ACLs); err != nil { resyncErrs = append(resyncErrs, err) } } - if !plugin.droppedFromResync(bfd.AuthKeysKeyPrefix()) { + if !plugin.droppedFromResync(bfd.AuthKeysPrefix) { if err := plugin.bfdConfigurator.ResyncAuthKey(req.SingleHopBFDKey); err != nil { resyncErrs = append(resyncErrs, err) } } - if !plugin.droppedFromResync(bfd.SessionKeyPrefix()) { + if !plugin.droppedFromResync(bfd.SessionPrefix) { if err := plugin.bfdConfigurator.ResyncSession(req.SingleHopBFDSession); err != nil { resyncErrs = append(resyncErrs, err) } } - if !plugin.droppedFromResync(bfd.EchoFunctionKeyPrefix()) { + if !plugin.droppedFromResync(bfd.EchoFunctionPrefix) { if err := plugin.bfdConfigurator.ResyncEchoFunction(req.SingleHopBFDEcho); err != nil { resyncErrs = append(resyncErrs, err) } } - if !plugin.droppedFromResync(l2.BridgeDomainKeyPrefix()) { + if !plugin.droppedFromResync(l2.BdPrefix) { if err := plugin.bdConfigurator.Resync(req.BridgeDomains); err != nil { resyncErrs = append(resyncErrs, err) } } - if !plugin.droppedFromResync(l2.FibKeyPrefix()) { + if !plugin.droppedFromResync(l2.FibPrefix) { if err := plugin.fibConfigurator.Resync(req.FibTableEntries); err != nil { resyncErrs = append(resyncErrs, err) } } - if !plugin.droppedFromResync(l2.XConnectKeyPrefix()) { + if !plugin.droppedFromResync(l2.XConnectPrefix) { if err := plugin.xcConfigurator.Resync(req.XConnects); err != nil { resyncErrs = append(resyncErrs, err) } } - if !plugin.droppedFromResync(l3.RouteKeyPrefix()) { + if !plugin.droppedFromResync(l3.RoutesPrefix) { if err := plugin.routeConfigurator.Resync(req.StaticRoutes); err != nil { resyncErrs = append(resyncErrs, err) } } - if !plugin.droppedFromResync(l3.ArpKeyPrefix()) { + if !plugin.droppedFromResync(l3.ArpPrefix) { if err := plugin.arpConfigurator.Resync(req.ArpEntries); err != nil { resyncErrs = append(resyncErrs, err) } } - if !plugin.droppedFromResync(l3.ProxyArpInterfacePrefix()) { + if !plugin.droppedFromResync(l3.ProxyARPInterfacePrefix) { if err := plugin.proxyArpConfigurator.ResyncInterfaces(req.ProxyArpInterfaces); err != nil { resyncErrs = append(resyncErrs, err) } } - if !plugin.droppedFromResync(l3.ProxyArpRangePrefix()) { + if !plugin.droppedFromResync(l3.ProxyARPRangePrefix) { if err := plugin.proxyArpConfigurator.ResyncRanges(req.ProxyArpRanges); err != nil { resyncErrs = append(resyncErrs, err) } } - if !plugin.droppedFromResync(l4.FeatureKeyPrefix()) { + if !plugin.droppedFromResync(l3.IPScanNeighPrefix) { + if err := plugin.ipNeighConfigurator.Resync(req.IPScanNeigh); err != nil { + resyncErrs = append(resyncErrs, err) + } + } + if !plugin.droppedFromResync(l4.FeaturesPrefix) { if err := plugin.appNsConfigurator.ResyncFeatures(req.L4Features); err != nil { resyncErrs = append(resyncErrs, err) } } - if !plugin.droppedFromResync(l4.AppNamespacesKeyPrefix()) { + if !plugin.droppedFromResync(l4.NamespacesPrefix) { if err := plugin.appNsConfigurator.ResyncAppNs(req.AppNamespaces); err != nil { resyncErrs = append(resyncErrs, err) } } - if !plugin.droppedFromResync(stn.KeyPrefix()) { + if !plugin.droppedFromResync(stn.Prefix) { if err := plugin.stnConfigurator.Resync(req.StnRules); err != nil { resyncErrs = append(resyncErrs, err) } } - if !plugin.droppedFromResync(nat.GlobalConfigPrefix()) { + if !plugin.droppedFromResync(nat.GlobalPrefix) { if err := plugin.natConfigurator.ResyncNatGlobal(req.Nat44Global); err != nil { resyncErrs = append(resyncErrs, err) } } - if !plugin.droppedFromResync(nat.SNatPrefix()) { + if !plugin.droppedFromResync(nat.SNatPrefix) { if err := plugin.natConfigurator.ResyncSNat(req.Nat44SNat); err != nil { resyncErrs = append(resyncErrs, err) } } - if !plugin.droppedFromResync(nat.DNatPrefix()) { + if !plugin.droppedFromResync(nat.DNatPrefix) { if err := plugin.natConfigurator.ResyncDNat(req.Nat44DNat); err != nil { resyncErrs = append(resyncErrs, err) } @@ -272,63 +278,66 @@ func (plugin *Plugin) resyncConfig(req *DataResyncReq) error { func (plugin *Plugin) resyncParseEvent(resyncEv datasync.ResyncEvent) *DataResyncReq { req := NewDataResyncReq() for key := range resyncEv.GetValues() { - plugin.Log.Debug("Received RESYNC key ", key) + plugin.Log.Debugf("Received RESYNC key %q", key) } for key, resyncData := range resyncEv.GetValues() { if plugin.droppedFromResync(key) { continue } - if strings.HasPrefix(key, acl.KeyPrefix()) { + if strings.HasPrefix(key, acl.Prefix) { numAcls := appendACLInterface(resyncData, req) plugin.Log.Debug("Received RESYNC ACL values ", numAcls) - } else if strings.HasPrefix(key, interfaces.InterfaceKeyPrefix()) { + } else if strings.HasPrefix(key, interfaces.Prefix) { numInterfaces := appendResyncInterface(resyncData, req) plugin.Log.Debug("Received RESYNC interface values ", numInterfaces) - } else if strings.HasPrefix(key, bfd.SessionKeyPrefix()) { + } else if strings.HasPrefix(key, bfd.SessionPrefix) { numBfdSession := resyncAppendBfdSession(resyncData, req) plugin.Log.Debug("Received RESYNC BFD Session values ", numBfdSession) - } else if strings.HasPrefix(key, bfd.AuthKeysKeyPrefix()) { + } else if strings.HasPrefix(key, bfd.AuthKeysPrefix) { numBfdAuthKeys := resyncAppendBfdAuthKeys(resyncData, req) plugin.Log.Debug("Received RESYNC BFD Auth Key values ", numBfdAuthKeys) - } else if strings.HasPrefix(key, bfd.EchoFunctionKeyPrefix()) { + } else if strings.HasPrefix(key, bfd.EchoFunctionPrefix) { numBfdEchos := resyncAppendBfdEcho(resyncData, req) plugin.Log.Debug("Received RESYNC BFD Echo values ", numBfdEchos) - } else if strings.HasPrefix(key, l2.BridgeDomainKeyPrefix()) { + } else if strings.HasPrefix(key, l2.BdPrefix) { numBDs, numL2FIBs := resyncAppendBDs(resyncData, req) plugin.Log.Debug("Received RESYNC BD values ", numBDs) plugin.Log.Debug("Received RESYNC L2 FIB values ", numL2FIBs) - } else if strings.HasPrefix(key, l2.XConnectKeyPrefix()) { + } else if strings.HasPrefix(key, l2.XConnectPrefix) { numXCons := resyncAppendXCons(resyncData, req) plugin.Log.Debug("Received RESYNC XConnects values ", numXCons) - } else if strings.HasPrefix(key, l3.VrfKeyPrefix()) { + } else if strings.HasPrefix(key, l3.VrfPrefix) { numVRFs, numL3FIBs := resyncAppendVRFs(resyncData, req, plugin.Log) plugin.Log.Debug("Received RESYNC VRF values ", numVRFs) plugin.Log.Debug("Received RESYNC L3 FIB values ", numL3FIBs) - } else if strings.HasPrefix(key, l3.ArpKeyPrefix()) { + } else if strings.HasPrefix(key, l3.ArpPrefix) { numARPs := resyncAppendARPs(resyncData, req, plugin.Log) plugin.Log.Debug("Received RESYNC ARP values ", numARPs) - } else if strings.HasPrefix(key, l3.ProxyArpInterfacePrefix()) { + } else if strings.HasPrefix(key, l3.ProxyARPInterfacePrefix) { numARPs := resyncAppendProxyArpInterfaces(resyncData, req, plugin.Log) plugin.Log.Debug("Received RESYNC proxy ARP interface values ", numARPs) - } else if strings.HasPrefix(key, l3.ProxyArpRangePrefix()) { + } else if strings.HasPrefix(key, l3.IPScanNeighPrefix) { + resyncAppendIPScanNeighs(resyncData, req) + plugin.Log.Debug("Received RESYNC IPScanNeigh") + } else if strings.HasPrefix(key, l3.ProxyARPRangePrefix) { numARPs := resyncAppendProxyArpRanges(resyncData, req, plugin.Log) plugin.Log.Debug("Received RESYNC proxy ARP range values ", numARPs) - } else if strings.HasPrefix(key, l4.FeatureKeyPrefix()) { + } else if strings.HasPrefix(key, l4.FeaturesPrefix) { resyncFeatures(resyncData, req) plugin.Log.Debug("Received RESYNC AppNs feature flag") - } else if strings.HasPrefix(key, l4.AppNamespacesKeyPrefix()) { + } else if strings.HasPrefix(key, l4.NamespacesPrefix) { numAppNs := resyncAppendAppNs(resyncData, req) plugin.Log.Debug("Received RESYNC AppNamespace values ", numAppNs) - } else if strings.HasPrefix(key, stn.KeyPrefix()) { + } else if strings.HasPrefix(key, stn.Prefix) { numStns := appendResyncStnRules(resyncData, req) plugin.Log.Debug("Received RESYNC STN rules values ", numStns) - } else if strings.HasPrefix(key, nat.GlobalConfigPrefix()) { + } else if strings.HasPrefix(key, nat.GlobalPrefix) { resyncNatGlobal(resyncData, req) plugin.Log.Debug("Received RESYNC NAT global config") - } else if strings.HasPrefix(key, nat.SNatPrefix()) { + } else if strings.HasPrefix(key, nat.SNatPrefix) { numSNats := appendResyncSNat(resyncData, req) plugin.Log.Debug("Received RESYNC SNAT configs ", numSNats) - } else if strings.HasPrefix(key, nat.DNatPrefix()) { + } else if strings.HasPrefix(key, nat.DNatPrefix) { numDNats := appendResyncDNat(resyncData, req) plugin.Log.Debug("Received RESYNC DNAT configs ", numDNats) } else if strings.HasPrefix(key, ipsec.KeyPrefix) { @@ -338,7 +347,7 @@ func (plugin *Plugin) resyncParseEvent(resyncEv datasync.ResyncEvent) *DataResyn numSRs := appendResyncSR(resyncData, req) plugin.Log.Debug("Received RESYNC SR configs ", numSRs) } else { - plugin.Log.Warn("ignoring ", resyncEv, " by VPP standard plugins") + plugin.Log.Warnf("ignoring prefix %q by VPP standard plugins", key) } } return req @@ -384,6 +393,19 @@ func resyncAppendProxyArpInterfaces(resyncData datasync.KeyValIterator, req *Dat return num } +func resyncAppendIPScanNeighs(resyncData datasync.KeyValIterator, req *DataResyncReq) { + for { + arpData, stop := resyncData.GetNext() + if stop { + break + } + entry := &l3.IPScanNeighbor{} + if err := arpData.GetValue(entry); err == nil { + req.IPScanNeigh = entry + } + } +} + func resyncAppendProxyArpRanges(resyncData datasync.KeyValIterator, req *DataResyncReq, log logging.Logger) int { num := 0 for { @@ -745,34 +767,40 @@ func appendResyncSR(resyncData datasync.KeyValIterator, req *DataResyncReq) (num // All registration for above channel select (it ensures proper order during initialization) are put here. func (plugin *Plugin) subscribeWatcher() (err error) { plugin.Log.Debug("subscribeWatcher begin") - plugin.swIfIndexes.WatchNameToIdx(plugin.PluginName, plugin.ifIdxWatchCh) + plugin.swIfIndexes.WatchNameToIdx(plugin.String(), plugin.ifIdxWatchCh) plugin.Log.Debug("swIfIndexes watch registration finished") - plugin.bdIndexes.WatchNameToIdx(plugin.PluginName, plugin.bdIdxWatchCh) + plugin.bdIndexes.WatchNameToIdx(plugin.String(), plugin.bdIdxWatchCh) plugin.Log.Debug("bdIndexes watch registration finished") - if plugin.linuxIfIndexes != nil { - plugin.linuxIfIndexes.WatchNameToIdx(plugin.PluginName, plugin.linuxIfIdxWatchCh) + if plugin.Linux != nil { + // Get pointer to the map with Linux interface indexes. + linuxIfIndexes := plugin.Linux.GetLinuxIfIndexes() + if linuxIfIndexes == nil { + return fmt.Errorf("linux plugin enabled but interface indexes are not available") + } + linuxIfIndexes.WatchNameToIdx(plugin.String(), plugin.linuxIfIdxWatchCh) plugin.Log.Debug("linuxIfIndexes watch registration finished") } - plugin.watchConfigReg, err = plugin.Watch. + plugin.watchConfigReg, err = plugin.Watcher. Watch("Config VPP default plug:IF/L2/L3", plugin.changeChan, plugin.resyncConfigChan, - acl.KeyPrefix(), - interfaces.InterfaceKeyPrefix(), - bfd.SessionKeyPrefix(), - bfd.AuthKeysKeyPrefix(), - bfd.EchoFunctionKeyPrefix(), - l2.BridgeDomainKeyPrefix(), - l2.XConnectKeyPrefix(), - l3.VrfKeyPrefix(), - l3.ArpKeyPrefix(), - l3.ProxyArpInterfacePrefix(), - l3.ProxyArpRangePrefix(), - l4.FeatureKeyPrefix(), - l4.AppNamespacesKeyPrefix(), - stn.KeyPrefix(), - nat.GlobalConfigPrefix(), - nat.SNatPrefix(), - nat.DNatPrefix(), + acl.Prefix, + interfaces.Prefix, + bfd.SessionPrefix, + bfd.AuthKeysPrefix, + bfd.EchoFunctionPrefix, + l2.BdPrefix, + l2.XConnectPrefix, + l3.VrfPrefix, + l3.ArpPrefix, + l3.ProxyARPInterfacePrefix, + l3.ProxyARPRangePrefix, + l3.IPScanNeighPrefix, + l4.FeaturesPrefix, + l4.NamespacesPrefix, + stn.Prefix, + nat.GlobalPrefix, + nat.SNatPrefix, + nat.DNatPrefix, ipsec.KeyPrefix, srv6.BasePrefix(), ) @@ -780,9 +808,9 @@ func (plugin *Plugin) subscribeWatcher() (err error) { return err } - plugin.watchStatusReg, err = plugin.Watch. + plugin.watchStatusReg, err = plugin.Watcher. Watch("Status VPP default plug:IF/L2/L3", nil, plugin.resyncStatusChan, - interfaces.InterfaceStateKeyPrefix(), l2.BridgeDomainStateKeyPrefix()) + interfaces.StatePrefix, l2.BdStatePrefix) if err != nil { return err } diff --git a/plugins/vpp/doc.go b/plugins/vpp/doc.go index 8b312a12fd..1a99f1c931 100644 --- a/plugins/vpp/doc.go +++ b/plugins/vpp/doc.go @@ -1,3 +1,3 @@ -// Package vppplugin is the parent package for all "default" VPP-related +// Package vpp is the parent package for all "default" VPP-related // plugins. package vpp diff --git a/plugins/vpp/error_status.go b/plugins/vpp/error_status.go index 98d59c7f4b..be265b12ba 100644 --- a/plugins/vpp/error_status.go +++ b/plugins/vpp/error_status.go @@ -61,9 +61,9 @@ func (plugin *Plugin) changePropagateError() { } // Process provides error data and adds a new entry. -func (plugin *Plugin) processError(errInfo error, key string, changeType datasync.PutDel, change datasync.ChangeEvent) { +func (plugin *Plugin) processError(errInfo error, key string, changeType datasync.Op, change datasync.ChangeEvent) { // Interfaces - if strings.HasPrefix(key, interfaces.InterfaceKeyPrefix()) { + if strings.HasPrefix(key, interfaces.Prefix) { var err error var iface, prevIface interfaces.Interfaces_Interface if err := change.GetValue(&iface); err != nil { @@ -92,7 +92,7 @@ func (plugin *Plugin) processError(errInfo error, key string, changeType datasyn plugin.Log.Errorf("Failed to propagate interface error, cause: %v", err) } // Bridge domains - } else if strings.HasPrefix(key, l2.BridgeDomainKeyPrefix()) { + } else if strings.HasPrefix(key, l2.BdPrefix) { var err error var bd, prevBd l2.BridgeDomains_BridgeDomain if err := change.GetValue(&bd); err != nil { @@ -125,7 +125,7 @@ func (plugin *Plugin) processError(errInfo error, key string, changeType datasyn // Create a list of errors for the provided interface and register it. If the interface // already has some errors logged, find it and add a new error log to the list. -func (plugin *Plugin) composeInterfaceErrors(ifName string, change datasync.PutDel, errs ...error) *interfaces.InterfaceErrors_Interface { +func (plugin *Plugin) composeInterfaceErrors(ifName string, change datasync.Op, errs ...error) *interfaces.InterfaceErrors_Interface { // Read registered data. _, data, exists := plugin.errorIndexes.LookupIdx(ifName) @@ -163,7 +163,7 @@ func (plugin *Plugin) composeInterfaceErrors(ifName string, change datasync.PutD // Create a list of errors for the provided bridge domain and register it. If the bridge domain // already has any error logged, find it and add a new error log to the list. -func (plugin *Plugin) composeBridgeDomainErrors(bdName string, change datasync.PutDel, errs ...error) *l2.BridgeDomainErrors_BridgeDomain { +func (plugin *Plugin) composeBridgeDomainErrors(bdName string, change datasync.Op, errs ...error) *l2.BridgeDomainErrors_BridgeDomain { // Read registered data _, data, exists := plugin.errorIndexes.LookupIdx(bdName) @@ -250,7 +250,7 @@ func (plugin *Plugin) removeErrorLog(key string) { return } - if prefix == interfaces.InterfacePrefix { + if prefix == interfaces.Prefix { key := interfaces.InterfaceErrorKey(name) plugin.Publish.Put(key, nil) plugin.Log.Infof("Error status log for interface %v cleared", name) @@ -269,8 +269,8 @@ func (plugin *Plugin) removeOldestErrorLogEntry(key string) { var name string var metaData interface{} var exists bool - if strings.HasPrefix(key, interfaces.IfErrorPrefix) { - name = strings.Replace(key, interfaces.IfErrorPrefix, "", 1) + if strings.HasPrefix(key, interfaces.ErrorPrefix) { + name = strings.Replace(key, interfaces.ErrorPrefix, "", 1) _, metaData, exists = plugin.errorIndexes.LookupIdx(name) } else if strings.HasPrefix(key, l2.BdErrPrefix) { name = strings.Replace(key, l2.BdErrPrefix, "", 1) diff --git a/plugins/vpp/ifplugin/afpacket_config.go b/plugins/vpp/ifplugin/afpacket_config.go index c93a3d9308..e01a59bf28 100644 --- a/plugins/vpp/ifplugin/afpacket_config.go +++ b/plugins/vpp/ifplugin/afpacket_config.go @@ -17,9 +17,7 @@ package ifplugin import ( "errors" - govppapi "git.fd.io/govpp.git/api" "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" intf "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" @@ -37,8 +35,7 @@ type AFPacketConfigurator struct { afPacketByName map[string]*AfPacketConfig // af packet name -> Af Packet interface configuration linuxHostInterfaces map[string]struct{} // a set of available host (Linux) interfaces - vppCh govppapi.Channel // govpp channel used by InterfaceConfigurator - stopwatch *measure.Stopwatch // from InterfaceConfigurator + ifHandler vppcalls.IfVppAPI // handler used by InterfaceConfigurator } // AfPacketConfig wraps the proto formatted configuration of an Afpacket interface together with a flag @@ -73,13 +70,13 @@ func (plugin *AFPacketConfigurator) GetHostInterfacesEntry(hostIf string) bool { } // Init members of AFPacketConfigurator. -func (plugin *AFPacketConfigurator) Init(logger logging.Logger, vppCh govppapi.Channel, linux interface{}, - indexes ifaceidx.SwIfIndexRW, stopwatch *measure.Stopwatch) (err error) { +func (plugin *AFPacketConfigurator) Init(logger logging.Logger, ifHandler vppcalls.IfVppAPI, linux interface{}, + indexes ifaceidx.SwIfIndexRW) (err error) { plugin.log = logger plugin.log.Infof("Initializing AF-Packet configurator") - // VPP channel - plugin.vppCh = vppCh + // VPP API handler + plugin.ifHandler = ifHandler // Linux plugin.linux = linux @@ -90,9 +87,6 @@ func (plugin *AFPacketConfigurator) Init(logger logging.Logger, vppCh govppapi.C plugin.afPacketByName = make(map[string]*AfPacketConfig) plugin.linuxHostInterfaces = make(map[string]struct{}) - // Stopwatch - plugin.stopwatch = stopwatch - return nil } @@ -115,7 +109,7 @@ func (plugin *AFPacketConfigurator) ConfigureAfPacketInterface(afpacket *intf.In return 0, true, nil } } - swIdx, err := vppcalls.AddAfPacketInterface(afpacket.Name, afpacket.PhysAddress, afpacket.Afpacket, plugin.vppCh, plugin.stopwatch) + swIdx, err := plugin.ifHandler.AddAfPacketInterface(afpacket.Name, afpacket.PhysAddress, afpacket.Afpacket) if err != nil { plugin.addToCache(afpacket, true) return 0, true, err @@ -156,7 +150,7 @@ func (plugin *AFPacketConfigurator) DeleteAfPacketInterface(afpacket *intf.Inter config, found := plugin.afPacketByName[afpacket.Name] if !found || !config.pending { - err = vppcalls.DeleteAfPacketInterface(afpacket.Name, ifIdx, afpacket.GetAfpacket(), plugin.vppCh, plugin.stopwatch) + err = plugin.ifHandler.DeleteAfPacketInterface(afpacket.Name, ifIdx, afpacket.GetAfpacket()) // unregister interface to let other plugins know that it is removed from the vpp plugin.ifIndexes.UnregisterName(afpacket.Name) } diff --git a/plugins/vpp/ifplugin/afpacket_config_test.go b/plugins/vpp/ifplugin/afpacket_config_test.go index e34660f716..407777941a 100644 --- a/plugins/vpp/ifplugin/afpacket_config_test.go +++ b/plugins/vpp/ifplugin/afpacket_config_test.go @@ -17,8 +17,6 @@ package ifplugin_test import ( "testing" - "git.fd.io/govpp.git/adapter/mock" - "git.fd.io/govpp.git/core" "github.com/ligato/cn-infra/logging" "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/cn-infra/utils/safeclose" @@ -27,36 +25,22 @@ import ( if_api "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" + "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" ) -/* AF_PACKET configurator init */ - -// Test init function -func TestAfPacketConfiguratorInit(t *testing.T) { - RegisterTestingT(t) - connection, err := core.Connect(&mock.VppAdapter{}) - Expect(err).To(BeNil()) - plugin := &ifplugin.AFPacketConfigurator{} - vppCh, err := connection.NewAPIChannel() - Expect(err).To(BeNil()) - err = plugin.Init(logrus.DefaultLogger(), vppCh, struct{}{}, nil, nil) - Expect(err).To(BeNil()) - connection.Disconnect() -} - /* AF_PACKET test cases */ // Configure af packet interface with unavailable host func TestAfPacketConfigureHostNotAvail(t *testing.T) { - var err error - // Setup ctx, plugin, _ := afPacketTestSetup(t) defer afPacketTestTeardown(ctx) + // Data data := getTestAfPacketData("if1", []string{"10.0.0.1/24"}, "host1") + // Test configure af packet with host unavailable swIfIdx, pending, err := plugin.ConfigureAfPacketInterface(data) Expect(err).To(BeNil()) @@ -74,10 +58,9 @@ func TestAfPacketConfigureHostNotAvail(t *testing.T) { // Configure af packet interface func TestAfPacketConfigureHostAvail(t *testing.T) { - var err error - // Setup ctx, plugin, _ := afPacketTestSetup(t) defer afPacketTestTeardown(ctx) + // Reply set ctx.MockVpp.MockReply(&ap_api.AfPacketCreateReply{ SwIfIndex: 2, @@ -85,6 +68,7 @@ func TestAfPacketConfigureHostAvail(t *testing.T) { ctx.MockVpp.MockReply(&if_api.SwInterfaceTagAddDelReply{}) // Data data := getTestAfPacketData("if1", []string{"10.0.0.1/24"}, "host1") + // Test af packet plugin.ResolveCreatedLinuxInterface("host1", "host1", 1) swIfIdx, pending, err := plugin.ConfigureAfPacketInterface(data) @@ -103,10 +87,9 @@ func TestAfPacketConfigureHostAvail(t *testing.T) { // Configure af packet with error reply from VPP API func TestAfPacketConfigureHostAvailError(t *testing.T) { - var err error - // Setup ctx, plugin, _ := afPacketTestSetup(t) defer afPacketTestTeardown(ctx) + // Reply set ctx.MockVpp.MockReply(&ap_api.AfPacketCreateReply{ Retval: 1, @@ -114,6 +97,7 @@ func TestAfPacketConfigureHostAvailError(t *testing.T) { }) // Data data := getTestAfPacketData("if1", []string{"10.0.0.1/24"}, "host1") + // Test configure af packet with return value != 0 plugin.ResolveCreatedLinuxInterface("host1", "host1", 1) swIfIdx, pending, err := plugin.ConfigureAfPacketInterface(data) @@ -130,13 +114,13 @@ func TestAfPacketConfigureHostAvailError(t *testing.T) { // Configure af packet as incorrect interface type func TestAfPacketConfigureIncorrectTypeError(t *testing.T) { - var err error - // Setup ctx, plugin, _ := afPacketTestSetup(t) defer afPacketTestTeardown(ctx) + // Data data := getTestAfPacketData("host1", []string{"10.0.0.1/24"}, "host1") data.Type = interfaces.InterfaceType_SOFTWARE_LOOPBACK + // Test configure af packet with incorrect type swIfIdx, pending, err := plugin.ConfigureAfPacketInterface(data) Expect(err).ToNot(BeNil()) @@ -150,10 +134,9 @@ func TestAfPacketConfigureIncorrectTypeError(t *testing.T) { // Call af packet modification which causes recreation of the interface func TestAfPacketModifyRecreateChangedHost(t *testing.T) { - var err error - // Setup ctx, plugin, _ := afPacketTestSetup(t) defer afPacketTestTeardown(ctx) + // Reply set ctx.MockVpp.MockReply(&ap_api.AfPacketCreateReply{ SwIfIndex: 1, @@ -162,6 +145,7 @@ func TestAfPacketModifyRecreateChangedHost(t *testing.T) { // Data oldData := getTestAfPacketData("if1", []string{"10.0.0.1/24"}, "host1") newData := getTestAfPacketData("if1", []string{"10.0.0.2/24"}, "host2") + // Test configure initial af packet data plugin.ResolveCreatedLinuxInterface("host1", "host1", 1) swIfIdx, pending, err := plugin.ConfigureAfPacketInterface(oldData) @@ -176,9 +160,8 @@ func TestAfPacketModifyRecreateChangedHost(t *testing.T) { // Test modify pending af packet interface func TestAfPacketModifyRecreatePending(t *testing.T) { - var err error - // Setup ctx, plugin, _ := afPacketTestSetup(t) + defer afPacketTestTeardown(ctx) // Reply set ctx.MockVpp.MockReply(&ap_api.AfPacketCreateReply{ @@ -188,6 +171,7 @@ func TestAfPacketModifyRecreatePending(t *testing.T) { // Data oldData := getTestAfPacketData("if1", []string{"10.0.0.1/24"}, "host1") newData := getTestAfPacketData("if1", []string{"10.0.0.1/24"}, "host1") + // Test configure initial af packet data _, pending, err := plugin.ConfigureAfPacketInterface(oldData) Expect(err).To(BeNil()) @@ -200,13 +184,13 @@ func TestAfPacketModifyRecreatePending(t *testing.T) { // Modify recreate of af packet interface which was not found func TestAfPacketModifyRecreateNotFound(t *testing.T) { - var err error - // Setup ctx, plugin, _ := afPacketTestSetup(t) defer afPacketTestTeardown(ctx) + // Data oldData := getTestAfPacketData("if1", []string{"10.0.0.1/24"}, "host1") newData := getTestAfPacketData("if1", []string{"10.0.0.1/24"}, "host2") + // Test af packet modify recreate, err := plugin.ModifyAfPacketInterface(newData, oldData) Expect(err).To(BeNil()) @@ -215,10 +199,9 @@ func TestAfPacketModifyRecreateNotFound(t *testing.T) { // Modify af packet interface without recreation func TestAfPacketModifyNoRecreate(t *testing.T) { - var err error - // Setup ctx, plugin, _ := afPacketTestSetup(t) defer afPacketTestTeardown(ctx) + // Reply set ctx.MockVpp.MockReply(&ap_api.AfPacketCreateReply{ SwIfIndex: 1, @@ -227,6 +210,7 @@ func TestAfPacketModifyNoRecreate(t *testing.T) { // Data oldData := getTestAfPacketData("if1", []string{"10.0.0.1/24"}, "host1") newData := getTestAfPacketData("if1", []string{"10.0.0.1/24"}, "host1") + // Test configure initial data plugin.ResolveCreatedLinuxInterface("host1", "host1", 1) swIfIdx, pending, err := plugin.ConfigureAfPacketInterface(oldData) @@ -249,10 +233,9 @@ func TestAfPacketModifyNoRecreate(t *testing.T) { // Modify af packet with incorrect interface type func TestAfPacketModifyIncorrectType(t *testing.T) { - var err error - // Setup ctx, plugin, _ := afPacketTestSetup(t) defer afPacketTestTeardown(ctx) + // Reply set ctx.MockVpp.MockReply(&ap_api.AfPacketCreateReply{ SwIfIndex: 1, @@ -262,6 +245,7 @@ func TestAfPacketModifyIncorrectType(t *testing.T) { oldData := getTestAfPacketData("if1", []string{"10.0.0.1/24"}, "host1") newData := getTestAfPacketData("if1", []string{"10.0.0.1/24"}, "host2") newData.Type = interfaces.InterfaceType_SOFTWARE_LOOPBACK + // Test configure initial data plugin.ResolveCreatedLinuxInterface("host1", "host1", 1) swIfIdx, pending, err := plugin.ConfigureAfPacketInterface(oldData) @@ -275,10 +259,9 @@ func TestAfPacketModifyIncorrectType(t *testing.T) { // Af packet delete func TestAfPacketDelete(t *testing.T) { - var err error - // Setup ctx, plugin, _ := afPacketTestSetup(t) defer afPacketTestTeardown(ctx) + // Reply set ctx.MockVpp.MockReply(&ap_api.AfPacketCreateReply{ // Create SwIfIndex: 1, @@ -288,6 +271,7 @@ func TestAfPacketDelete(t *testing.T) { ctx.MockVpp.MockReply(&if_api.SwInterfaceTagAddDelReply{}) // Data data := getTestAfPacketData("if1", []string{"10.0.0.1/24"}, "host1") + // Test configure initial af packet data plugin.ResolveCreatedLinuxInterface("host1", "host1", 1) swIfIdx, pending, err := plugin.ConfigureAfPacketInterface(data) @@ -313,10 +297,9 @@ func TestAfPacketDelete(t *testing.T) { // Delete af packet with incorrect interface type data func TestAfPacketDeleteIncorrectType(t *testing.T) { - var err error - // Setup ctx, plugin, _ := afPacketTestSetup(t) defer afPacketTestTeardown(ctx) + // Reply set ctx.MockVpp.MockReply(&ap_api.AfPacketCreateReply{ SwIfIndex: 1, @@ -326,6 +309,7 @@ func TestAfPacketDeleteIncorrectType(t *testing.T) { data := getTestAfPacketData("if1", []string{"10.0.0.1/24"}, "host1") modifiedData := getTestAfPacketData("if1", []string{"10.0.0.1/24"}, "host1") modifiedData.Type = interfaces.InterfaceType_SOFTWARE_LOOPBACK + // Test configure initial af packet plugin.ResolveCreatedLinuxInterface("host1", "host1", 1) swIfIdx, pending, err := plugin.ConfigureAfPacketInterface(data) @@ -339,9 +323,9 @@ func TestAfPacketDeleteIncorrectType(t *testing.T) { // Register new linux interface and test af packet behaviour func TestAfPacketNewLinuxInterfaceHostFound(t *testing.T) { - // Setup ctx, plugin, _ := afPacketTestSetup(t) defer afPacketTestTeardown(ctx) + // Reply set ctx.MockVpp.MockReply(&ap_api.AfPacketCreateReply{ SwIfIndex: 1, @@ -349,6 +333,7 @@ func TestAfPacketNewLinuxInterfaceHostFound(t *testing.T) { ctx.MockVpp.MockReply(&if_api.SwInterfaceTagAddDelReply{}) // Data data := getTestAfPacketData("if1", []string{"10.0.0.1/24"}, "host1") + // Test registered linux interface _, pending, err := plugin.ConfigureAfPacketInterface(data) Expect(err).To(BeNil()) @@ -361,9 +346,9 @@ func TestAfPacketNewLinuxInterfaceHostFound(t *testing.T) { // Register new linux interface while af packet is not pending. Note: this is a case which should NOT happen func TestAfPacketNewLinuxInterfaceHostNotPending(t *testing.T) { - // Setup ctx, plugin, _ := afPacketTestSetup(t) defer afPacketTestTeardown(ctx) + // Reply set ctx.MockVpp.MockReply(&ap_api.AfPacketCreateReply{ SwIfIndex: 1, @@ -373,6 +358,7 @@ func TestAfPacketNewLinuxInterfaceHostNotPending(t *testing.T) { ctx.MockVpp.MockReply(&if_api.SwInterfaceTagAddDelReply{}) // Data data := getTestAfPacketData("if1", []string{"10.0.0.1/24"}, "host1") + // Test registered linux interface plugin.ResolveCreatedLinuxInterface("host1", "host1", 1) _, pending, err := plugin.ConfigureAfPacketInterface(data) @@ -386,10 +372,11 @@ func TestAfPacketNewLinuxInterfaceHostNotPending(t *testing.T) { // Test new linux interface which is not a host func TestAfPacketNewLinuxInterfaceHostNotFound(t *testing.T) { - // Setup ctx, plugin, _ := afPacketTestSetup(t) defer afPacketTestTeardown(ctx) + Expect(plugin.GetHostInterfacesEntry("host1")).To(BeFalse()) + // Test registered linux interface config := plugin.ResolveCreatedLinuxInterface("host1", "host1", 1) Expect(config).To(BeNil()) @@ -400,6 +387,7 @@ func TestAfPacketNewLinuxInterfaceHostNotFound(t *testing.T) { func TestAfPacketNewLinuxInterfaceNoLinux(t *testing.T) { ctx := vppcallmock.SetupTestCtx(t) defer ctx.TeardownTestCtx() + // Logger log := logrus.DefaultLogger() log.SetLevel(logging.DebugLevel) @@ -407,7 +395,8 @@ func TestAfPacketNewLinuxInterfaceNoLinux(t *testing.T) { swIfIndices := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(log, "afpacket", nil)) // Configurator plugin := &ifplugin.AFPacketConfigurator{} - err := plugin.Init(log, ctx.MockChannel, nil, swIfIndices, nil) + ifHandler := vppcalls.NewIfVppHandler(ctx.MockChannel, log, nil) + err := plugin.Init(log, ifHandler, nil, swIfIndices) Expect(err).To(BeNil()) // Test registered linux interface config := plugin.ResolveCreatedLinuxInterface("host1", "host1", 1) @@ -416,9 +405,9 @@ func TestAfPacketNewLinuxInterfaceNoLinux(t *testing.T) { // Un-register linux interface func TestAfPacketDeletedLinuxInterface(t *testing.T) { - // Setup ctx, plugin, _ := afPacketTestSetup(t) defer afPacketTestTeardown(ctx) + // Reply set ctx.MockVpp.MockReply(&ap_api.AfPacketCreateReply{}) ctx.MockVpp.MockReply(&if_api.SwInterfaceTagAddDelReply{}) @@ -441,9 +430,9 @@ func TestAfPacketDeletedLinuxInterface(t *testing.T) { // Un-register linux interface while host is not found func TestAfPacketDeletedLinuxInterfaceHostNotFound(t *testing.T) { - // Setup ctx, plugin, _ := afPacketTestSetup(t) defer afPacketTestTeardown(ctx) + // Prepare plugin.ResolveCreatedLinuxInterface("host1", "host1", 1) // Test un-registered linux interface @@ -455,6 +444,7 @@ func TestAfPacketDeletedLinuxInterfaceHostNotFound(t *testing.T) { func TestAfPacketDeleteLinuxInterfaceNoLinux(t *testing.T) { ctx := vppcallmock.SetupTestCtx(t) defer ctx.TeardownTestCtx() + // Logger log := logrus.DefaultLogger() log.SetLevel(logging.DebugLevel) @@ -462,7 +452,8 @@ func TestAfPacketDeleteLinuxInterfaceNoLinux(t *testing.T) { swIfIndices := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(log, "afpacket", nil)) // Configurator plugin := &ifplugin.AFPacketConfigurator{} - err := plugin.Init(log, ctx.MockChannel, nil, swIfIndices, nil) + ifHandler := vppcalls.NewIfVppHandler(ctx.MockChannel, log, nil) + err := plugin.Init(log, ifHandler, nil, swIfIndices) Expect(err).To(BeNil()) // Prepare plugin.ResolveCreatedLinuxInterface("host1", "host1", 1) @@ -475,9 +466,9 @@ func TestAfPacketDeleteLinuxInterfaceNoLinux(t *testing.T) { // Check if 'IsPending' returns correct output func TestAfPacketIsPending(t *testing.T) { - // Setup ctx, plugin, _ := afPacketTestSetup(t) defer afPacketTestTeardown(ctx) + // Reply set ctx.MockVpp.MockReply(&ap_api.AfPacketCreateReply{}) ctx.MockVpp.MockReply(&if_api.SwInterfaceTagAddDelReply{}) @@ -504,6 +495,8 @@ func TestAfPacketIsPending(t *testing.T) { /* AF_PACKET Test Setup */ func afPacketTestSetup(t *testing.T) (*vppcallmock.TestCtx, *ifplugin.AFPacketConfigurator, ifaceidx.SwIfIndexRW) { + RegisterTestingT(t) + ctx := vppcallmock.SetupTestCtx(t) // Logger log := logrus.DefaultLogger() @@ -513,7 +506,8 @@ func afPacketTestSetup(t *testing.T) (*vppcallmock.TestCtx, *ifplugin.AFPacketCo swIfIndices := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(log, "afpacket", nil)) // Configurator plugin := &ifplugin.AFPacketConfigurator{} - err := plugin.Init(log, ctx.MockChannel, struct{}{}, swIfIndices, nil) + ifHandler := vppcalls.NewIfVppHandler(ctx.MockChannel, log, nil) + err := plugin.Init(log, ifHandler, struct{}{}, swIfIndices) Expect(err).To(BeNil()) return ctx, plugin, swIfIndices @@ -523,6 +517,7 @@ func afPacketTestTeardown(ctx *vppcallmock.TestCtx) { ctx.TeardownTestCtx() err := safeclose.Close(ctx) Expect(err).To(BeNil()) + logging.DefaultRegistry.ClearRegistry() } /* AF_PACKET Test Data */ diff --git a/plugins/vpp/ifplugin/bfd_config.go b/plugins/vpp/ifplugin/bfd_config.go index 0f31fd9fe0..9900c9a0d4 100644 --- a/plugins/vpp/ifplugin/bfd_config.go +++ b/plugins/vpp/ifplugin/bfd_config.go @@ -51,6 +51,9 @@ type BFDConfigurator struct { echoFunctionIndex idxvpp.NameToIdxRW vppChan govppapi.Channel + + // VPP API handler + bfdHandler vppcalls.BfdVppAPI } // Init members and channels @@ -60,6 +63,11 @@ func (plugin *BFDConfigurator) Init(logger logging.PluginLogger, goVppMux govppm plugin.log = logger.NewLogger("-bfd-conf") plugin.log.Infof("Initializing BFD configurator") + // Configurator-wide stopwatch instance + if enableStopwatch { + plugin.stopwatch = measure.NewStopwatch("BFD-configurator", plugin.log) + } + // Mappings plugin.ifIndexes = swIfIndexes plugin.sessionsIndexes = nametoidx.NewNameToIdx(plugin.log, "bfd_session_indexes", nil) @@ -72,15 +80,8 @@ func (plugin *BFDConfigurator) Init(logger logging.PluginLogger, goVppMux govppm return err } - // Stopwatch - if enableStopwatch { - plugin.stopwatch = measure.NewStopwatch("BFDConfigurator", plugin.log) - } - - if err = vppcalls.CheckMsgCompatibilityForBfd(plugin.vppChan); err != nil { - plugin.log.Error(err) - return err - } + // VPP API handler + plugin.bfdHandler = vppcalls.NewBfdVppHandler(plugin.vppChan, plugin.ifIndexes, plugin.log, plugin.stopwatch) return nil } @@ -146,7 +147,7 @@ func (plugin *BFDConfigurator) ConfigureBfdSession(bfdInput *bfd.SingleHopBFD_Se } // Call vpp api - err := vppcalls.AddBfdUDPSession(bfdInput, ifIdx, plugin.keysIndexes, plugin.log, plugin.vppChan, plugin.stopwatch) + err := plugin.bfdHandler.AddBfdUDPSession(bfdInput, ifIdx, plugin.keysIndexes) if err != nil { return fmt.Errorf("error while configuring BFD for interface %v", bfdInput.Interface) } @@ -197,7 +198,7 @@ func (plugin *BFDConfigurator) ModifyBfdSession(oldBfdInput *bfd.SingleHopBFD_Se _, _, found = plugin.sessionsIndexes.LookupIdx(oldBfdInput.Interface) if !found { plugin.log.Printf("Previous BFD session does not exist, creating a new one for interface %v", newBfdInput.Interface) - err := vppcalls.AddBfdUDPSession(newBfdInput, ifIdx, plugin.keysIndexes, plugin.log, plugin.vppChan, plugin.stopwatch) + err := plugin.bfdHandler.AddBfdUDPSession(newBfdInput, ifIdx, plugin.keysIndexes) if err != nil { return err } @@ -210,7 +211,7 @@ func (plugin *BFDConfigurator) ModifyBfdSession(oldBfdInput *bfd.SingleHopBFD_Se return fmt.Errorf("unable to modify BFD session, adresses does not match. Odl session source: %v, dest: %v, new session source: %v, dest: %v", oldBfdInput.SourceAddress, oldBfdInput.DestinationAddress, newBfdInput.SourceAddress, newBfdInput.DestinationAddress) } - err := vppcalls.ModifyBfdUDPSession(newBfdInput, plugin.ifIndexes, plugin.vppChan, plugin.stopwatch) + err := plugin.bfdHandler.ModifyBfdUDPSession(newBfdInput, plugin.ifIndexes) if err != nil { return err } @@ -230,7 +231,7 @@ func (plugin *BFDConfigurator) DeleteBfdSession(bfdInput *bfd.SingleHopBFD_Sessi return fmt.Errorf("cannot remove BFD session, interface %s not found", bfdInput.Interface) } - err := vppcalls.DeleteBfdUDPSession(ifIndex, bfdInput.SourceAddress, bfdInput.DestinationAddress, plugin.vppChan, plugin.stopwatch) + err := plugin.bfdHandler.DeleteBfdUDPSession(ifIndex, bfdInput.SourceAddress, bfdInput.DestinationAddress) if err != nil { return fmt.Errorf("error while deleting BFD for interface %v", bfdInput.Interface) } @@ -241,50 +242,11 @@ func (plugin *BFDConfigurator) DeleteBfdSession(bfdInput *bfd.SingleHopBFD_Sessi return nil } -// DumpBfdSessions returns a list of all configured BFD sessions -func (plugin *BFDConfigurator) DumpBfdSessions() ([]*bfd.SingleHopBFD_Session, error) { - var bfdSessionList []*bfd.SingleHopBFD_Session - - bfdList, err := vppcalls.DumpBfdUDPSessions(plugin.vppChan, plugin.stopwatch) - if err != nil { - return bfdSessionList, err - } - - var wasError error - for _, bfdItem := range bfdList { - // find interface - ifName, _, found := plugin.ifIndexes.LookupName(bfdItem.SwIfIndex) - if !found { - plugin.log.Warnf("required interface %v not found for BFD", bfdItem.SwIfIndex) - } - - // Prepare IPv4 IP addresses - var dstAddr net.IP = bfdItem.PeerAddr[:4] - var srcAddr net.IP = bfdItem.LocalAddr[:4] - - bfdSessionList = append(bfdSessionList, &bfd.SingleHopBFD_Session{ - Interface: ifName, - DestinationAddress: dstAddr.To4().String(), - SourceAddress: srcAddr.To4().String(), - Enabled: true, - DesiredMinTxInterval: bfdItem.DesiredMinTx, - RequiredMinRxInterval: bfdItem.RequiredMinRx, - DetectMultiplier: uint32(bfdItem.DetectMult), - Authentication: &bfd.SingleHopBFD_Session_Authentication{ - KeyId: uint32(bfdItem.BfdKeyID), - AdvertisedKeyId: uint32(bfdItem.BfdKeyID), - }, - }) - } - - return bfdSessionList, wasError -} - // ConfigureBfdAuthKey crates new authentication key which can be used for BFD session func (plugin *BFDConfigurator) ConfigureBfdAuthKey(bfdAuthKey *bfd.SingleHopBFD_Key) error { plugin.log.Infof("Configuring BFD authentication key with ID %v", bfdAuthKey.Id) - err := vppcalls.SetBfdUDPAuthenticationKey(bfdAuthKey, plugin.log, plugin.vppChan, plugin.stopwatch) + err := plugin.bfdHandler.SetBfdUDPAuthenticationKey(bfdAuthKey) if err != nil { return fmt.Errorf("error while setting up BFD auth key with ID %v", bfdAuthKey.Id) } @@ -304,41 +266,49 @@ func (plugin *BFDConfigurator) ModifyBfdAuthKey(oldInput *bfd.SingleHopBFD_Key, plugin.log.Infof("Modifying BFD auth key for ID %d", oldInput.Id) // Check that this auth key is not used in any session - sessionList, err := vppcalls.DumpBfdUDPSessionsWithID(newInput.Id, plugin.vppChan, plugin.stopwatch) + sessionList, err := plugin.bfdHandler.DumpBfdUDPSessionsWithID(newInput.Id) if err != nil { return fmt.Errorf("error while verifying authentication key usage. Id: %d: %v", oldInput.Id, err) } - if len(sessionList) != 0 { + if sessionList != nil && len(sessionList.Session) != 0 { // Authentication Key is used and cannot be removed directly - for _, bfds := range sessionList { - sourceAddr := net.HardwareAddr(bfds.LocalAddr).String() - destAddr := net.HardwareAddr(bfds.PeerAddr).String() - err := vppcalls.DeleteBfdUDPSession(bfds.SwIfIndex, sourceAddr, destAddr, plugin.vppChan, plugin.stopwatch) + for _, bfds := range sessionList.Session { + sourceAddr := net.HardwareAddr(bfds.SourceAddress).String() + destAddr := net.HardwareAddr(bfds.DestinationAddress).String() + ifIdx, _, found := plugin.ifIndexes.LookupIdx(bfds.Interface) + if !found { + plugin.log.Warnf("Modify BFD auth key: interface index for %s not found", bfds.Interface) + } + err := plugin.bfdHandler.DeleteBfdUDPSession(ifIdx, sourceAddr, destAddr) if err != nil { return err } } - plugin.log.Debugf("%v session(s) temporary removed", len(sessionList)) + plugin.log.Debugf("%v session(s) temporary removed", len(sessionList.Session)) } - err = vppcalls.DeleteBfdUDPAuthenticationKey(oldInput, plugin.vppChan, plugin.stopwatch) + err = plugin.bfdHandler.DeleteBfdUDPAuthenticationKey(oldInput) if err != nil { return fmt.Errorf("error while removing BFD auth key with ID %d: %v", oldInput.Id, err) } - err = vppcalls.SetBfdUDPAuthenticationKey(newInput, plugin.log, plugin.vppChan, plugin.stopwatch) + err = plugin.bfdHandler.SetBfdUDPAuthenticationKey(newInput) if err != nil { return fmt.Errorf("error while setting up BFD auth key with ID %d: %v", oldInput.Id, err) } // Recreate BFD sessions if necessary - if len(sessionList) != 0 { - for _, bfdSession := range sessionList { - err := vppcalls.AddBfdUDPSessionFromDetails(bfdSession, plugin.keysIndexes, plugin.log, plugin.vppChan, plugin.stopwatch) + if sessionList != nil && len(sessionList.Session) != 0 { + for _, bfdSession := range sessionList.Session { + ifIdx, _, found := plugin.ifIndexes.LookupIdx(bfdSession.Interface) + if !found { + plugin.log.Warnf("Modify BFD auth key: interface index for %s not found", bfdSession.Interface) + } + err := plugin.bfdHandler.AddBfdUDPSession(bfdSession, ifIdx, plugin.keysIndexes) if err != nil { return err } } - plugin.log.Debugf("%v session(s) recreated", len(sessionList)) + plugin.log.Debugf("%v session(s) recreated", len(sessionList.Session)) } return nil @@ -349,71 +319,49 @@ func (plugin *BFDConfigurator) DeleteBfdAuthKey(bfdInput *bfd.SingleHopBFD_Key) plugin.log.Info("Deleting BFD auth key") // Check that this auth key is not used in any session - sessionList, err := vppcalls.DumpBfdUDPSessionsWithID(bfdInput.Id, plugin.vppChan, plugin.stopwatch) + sessionList, err := plugin.bfdHandler.DumpBfdUDPSessionsWithID(bfdInput.Id) if err != nil { return fmt.Errorf("error while verifying authentication key usage. Id: %v", bfdInput.Id) } - if len(sessionList) != 0 { + if sessionList != nil && len(sessionList.Session) != 0 { // Authentication Key is used and cannot be removed directly - for _, bfds := range sessionList { - sourceAddr := net.IP(bfds.LocalAddr[0:4]).String() - destAddr := net.IP(bfds.PeerAddr[0:4]).String() - err := vppcalls.DeleteBfdUDPSession(bfds.SwIfIndex, sourceAddr, destAddr, plugin.vppChan, nil) + for _, bfds := range sessionList.Session { + ifIdx, _, found := plugin.ifIndexes.LookupIdx(bfds.Interface) + if !found { + plugin.log.Warnf("Delete BFD auth key: interface index for %s not found", bfds.Interface) + } + err := plugin.bfdHandler.DeleteBfdUDPSession(ifIdx, bfds.SourceAddress, bfds.DestinationAddress) if err != nil { return err } } - plugin.log.Debugf("%v session(s) temporary removed", len(sessionList)) + plugin.log.Debugf("%v session(s) temporary removed", len(sessionList.Session)) } - err = vppcalls.DeleteBfdUDPAuthenticationKey(bfdInput, plugin.vppChan, nil) + err = plugin.bfdHandler.DeleteBfdUDPAuthenticationKey(bfdInput) if err != nil { return fmt.Errorf("error while removing BFD auth key with ID %v", bfdInput.Id) } - authKeyIDAsString := strconv.FormatUint(uint64(bfdInput.Id), 10) + authKeyIDAsString := AuthKeyIdentifier(bfdInput.Id) plugin.keysIndexes.UnregisterName(authKeyIDAsString) plugin.log.Debugf("BFD authentication key with id %v unregistered", bfdInput.Id) // Recreate BFD sessions if necessary - if len(sessionList) != 0 { - for _, bfdSession := range sessionList { - err := vppcalls.AddBfdUDPSessionFromDetails(bfdSession, plugin.keysIndexes, plugin.log, plugin.vppChan, nil) + if sessionList != nil && len(sessionList.Session) != 0 { + for _, bfdSession := range sessionList.Session { + ifIdx, _, found := plugin.ifIndexes.LookupIdx(bfdSession.Interface) + if !found { + plugin.log.Warnf("Delete BFD auth key: interface index for %s not found", bfdSession.Interface) + } + err := plugin.bfdHandler.AddBfdUDPSession(bfdSession, ifIdx, plugin.keysIndexes) if err != nil { return err } } - plugin.log.Debugf("%v session(s) recreated", len(sessionList)) + plugin.log.Debugf("%v session(s) recreated", len(sessionList.Session)) } return nil } -// DumpBFDAuthKeys returns a list of all configured authentication keys -func (plugin *BFDConfigurator) DumpBFDAuthKeys() ([]*bfd.SingleHopBFD_Key, error) { - var bfdAuthKeyList []*bfd.SingleHopBFD_Key - - keys, err := vppcalls.DumpBfdKeys(plugin.vppChan, plugin.stopwatch) - if err != nil { - return bfdAuthKeyList, err - } - - for _, key := range keys { - // resolve authentication type - var authType bfd.SingleHopBFD_Key_AuthenticationType - if key.AuthType == 4 { - authType = bfd.SingleHopBFD_Key_KEYED_SHA1 - } else { - authType = bfd.SingleHopBFD_Key_METICULOUS_KEYED_SHA1 - } - - bfdAuthKeyList = append(bfdAuthKeyList, &bfd.SingleHopBFD_Key{ - Id: key.ConfKeyID, - AuthKeyIndex: key.ConfKeyID, - AuthenticationType: authType, - }) - } - - return bfdAuthKeyList, nil -} - // ConfigureBfdEchoFunction is used to setup BFD Echo function on existing interface func (plugin *BFDConfigurator) ConfigureBfdEchoFunction(bfdInput *bfd.SingleHopBFD_EchoFunction) error { plugin.log.Infof("Configuring BFD echo function for source interface %v", bfdInput.EchoSourceInterface) @@ -424,7 +372,7 @@ func (plugin *BFDConfigurator) ConfigureBfdEchoFunction(bfdInput *bfd.SingleHopB return fmt.Errorf("interface %v does not exist", bfdInput.EchoSourceInterface) } - err := vppcalls.AddBfdEchoFunction(bfdInput, plugin.ifIndexes, plugin.vppChan, plugin.stopwatch) + err := plugin.bfdHandler.AddBfdEchoFunction(bfdInput, plugin.ifIndexes) if err != nil { return fmt.Errorf("error while setting up BFD echo source with interface %v", bfdInput.EchoSourceInterface) } @@ -449,7 +397,7 @@ func (plugin *BFDConfigurator) ModifyBfdEchoFunction(oldInput *bfd.SingleHopBFD_ func (plugin *BFDConfigurator) DeleteBfdEchoFunction(bfdInput *bfd.SingleHopBFD_EchoFunction) error { plugin.log.Info("Deleting BFD echo function") - err := vppcalls.DeleteBfdEchoFunction(plugin.vppChan, plugin.stopwatch) + err := plugin.bfdHandler.DeleteBfdEchoFunction() if err != nil { return fmt.Errorf("error while removing BFD echo source with interface %v", bfdInput.EchoSourceInterface) } @@ -462,7 +410,7 @@ func (plugin *BFDConfigurator) DeleteBfdEchoFunction(bfdInput *bfd.SingleHopBFD_ return nil } -// Generates common identifier for authentication key +// AuthKeyIdentifier generates common identifier for authentication key func AuthKeyIdentifier(id uint32) string { - return strconv.FormatUint(uint64(id), 10) + return strconv.Itoa(int(id)) } diff --git a/plugins/vpp/ifplugin/bfd_config_test.go b/plugins/vpp/ifplugin/bfd_config_test.go index d036c90fd9..396f429eb2 100644 --- a/plugins/vpp/ifplugin/bfd_config_test.go +++ b/plugins/vpp/ifplugin/bfd_config_test.go @@ -34,23 +34,6 @@ import ( . "github.com/onsi/gomega" ) -/* BFD configurator init and close */ - -// Test init function -func TestBfdConfiguratorInit(t *testing.T) { - RegisterTestingT(t) - connection, _ := core.Connect(&mock.VppAdapter{}) - defer connection.Disconnect() - - plugin := &ifplugin.BFDConfigurator{} - err := plugin.Init(logging.ForPlugin("test-log", logrus.NewLogRegistry()), connection, - nil, true) - Expect(err).To(BeNil()) - - err = plugin.Close() - Expect(err).To(BeNil()) -} - /* BFD Sessions */ // Configure BFD session without interface @@ -309,33 +292,6 @@ func TestBfdConfiguratorDeleteSessionError(t *testing.T) { Expect(err).ToNot(BeNil()) } -// BFD session dump -func TestBfdConfiguratorDumpBfdSessions(t *testing.T) { - var err error - // Setup - ctx, connection, plugin, ifIndexes := bfdTestSetup(t) - defer bfdTestTeardown(connection, plugin) - // Reply set - ctx.MockVpp.MockReply( - &bfd_api.BfdUDPSessionDetails{ - SwIfIndex: 1, - LocalAddr: net.ParseIP("10.0.0.1").To4(), - PeerAddr: net.ParseIP("10.0.0.2").To4(), - }, - &bfd_api.BfdUDPSessionDetails{ - SwIfIndex: 2, - LocalAddr: net.ParseIP("10.0.0.3").To4(), - PeerAddr: net.ParseIP("10.0.0.4").To4(), - }) - ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - // Register (only first interface) - ifIndexes.RegisterName("if1", 1, nil) - // Test bfd session dump - sessions, err := plugin.DumpBfdSessions() - Expect(err).To(BeNil()) - Expect(sessions).To(HaveLen(2)) -} - // Configure BFD authentication key func TestBfdConfiguratorSetAuthKey(t *testing.T) { var err error @@ -451,31 +407,6 @@ func TestBfdConfiguratorDeleteUsedAuthKey(t *testing.T) { Expect(err).To(BeNil()) } -// Dump BFD authentication key -func TestBfdConfiguratorDumpAuthKey(t *testing.T) { - var err error - // Setup - ctx, connection, plugin, _ := bfdTestSetup(t) - defer bfdTestTeardown(connection, plugin) - // Reply set - ctx.MockVpp.MockReply( - &bfd_api.BfdAuthKeysDetails{ - ConfKeyID: 1, - AuthType: 4, // Means KEYED SHA1 - }, - &bfd_api.BfdAuthKeysDetails{ - ConfKeyID: 2, - AuthType: 1, // Any other number is METICULOUS KEYED SHA1 - }) - ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - // Test authentication key dump - keys, err := plugin.DumpBFDAuthKeys() - Expect(err).To(BeNil()) - Expect(keys).To(HaveLen(2)) - Expect(keys[0].AuthenticationType).To(BeEquivalentTo(bfd.SingleHopBFD_Key_KEYED_SHA1)) - Expect(keys[1].AuthenticationType).To(BeEquivalentTo(bfd.SingleHopBFD_Key_METICULOUS_KEYED_SHA1)) -} - // Configure BFD echo function create/modify/delete func TestBfdConfiguratorEchoFunction(t *testing.T) { var err error @@ -569,13 +500,13 @@ func bfdTestSetup(t *testing.T) (*vppcallmock.TestCtx, *core.Connection, *ifplug connection, err := core.Connect(ctx.MockVpp) Expect(err).ShouldNot(HaveOccurred()) // Logger - log := logging.ForPlugin("test-log", logrus.NewLogRegistry()) + log := logging.ForPlugin("test-log") log.SetLevel(logging.DebugLevel) // Interface indices swIfIndices := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(log, "stn", nil)) // Configurator plugin := &ifplugin.BFDConfigurator{} - err = plugin.Init(log, connection, swIfIndices, false) + err = plugin.Init(log, connection, swIfIndices, true) Expect(err).To(BeNil()) return ctx, connection, plugin, swIfIndices @@ -585,6 +516,7 @@ func bfdTestTeardown(connection *core.Connection, plugin *ifplugin.BFDConfigurat connection.Disconnect() err := plugin.Close() Expect(err).To(BeNil()) + logging.DefaultRegistry.ClearRegistry() } func bfdVppMockHandler(vppMock *mock.VppAdapter) mock.ReplyHandler { diff --git a/plugins/vpp/ifplugin/data_resync.go b/plugins/vpp/ifplugin/data_resync.go index 10f63bdb2b..ae24ec8a79 100644 --- a/plugins/vpp/ifplugin/data_resync.go +++ b/plugins/vpp/ifplugin/data_resync.go @@ -20,9 +20,6 @@ import ( "net" "strings" - _ "github.com/ligato/vpp-agent/plugins/vpp/binapi/nat" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppdump" "github.com/ligato/vpp-agent/plugins/vpp/model/bfd" intf "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" "github.com/ligato/vpp-agent/plugins/vpp/model/nat" @@ -56,8 +53,13 @@ func (plugin *InterfaceConfigurator) Resync(nbIfs []*intf.Interfaces_Interface) } plugin.afPacketConfigurator.clearMapping() + var err error + if plugin.memifScCache, err = plugin.ifHandler.DumpMemifSocketDetails(); err != nil { + return []error{err} + } + // Dump current state of the VPP interfaces - vppIfs, err := vppdump.DumpInterfaces(plugin.log, plugin.vppCh, plugin.stopwatch) + vppIfs, err := plugin.ifHandler.DumpInterfaces() if err != nil { return []error{err} } @@ -69,46 +71,46 @@ func (plugin *InterfaceConfigurator) Resync(nbIfs []*intf.Interfaces_Interface) for vppIfIdx, vppIf := range vppIfs { if vppIfIdx == 0 { // Register local0 interface with zero index - if err := plugin.registerInterface(vppIf.VPPInternalName, vppIfIdx, &vppIf.Interfaces_Interface); err != nil { + if err := plugin.registerInterface(vppIf.Meta.InternalName, vppIfIdx, vppIf.Interface); err != nil { errs = append(errs, err) } continue } - if vppIf.Name == "" { + if vppIf.Interface.Name == "" { // If interface has no name, it is stored as unnamed and resolved later plugin.log.Debugf("RESYNC interfaces: interface %v has no name (tag)", vppIfIdx) - unnamedVppIfs[vppIfIdx] = &vppIf.Interfaces_Interface + unnamedVppIfs[vppIfIdx] = vppIf.Interface continue } var correlated bool for _, nbIf := range nbIfs { - if vppIf.Name == nbIf.Name { + if vppIf.Interface.Name == nbIf.Name { correlated = true // Register interface to mapping and VPP tag/index - if err := plugin.registerInterface(vppIf.Name, vppIfIdx, nbIf); err != nil { + if err := plugin.registerInterface(vppIf.Interface.Name, vppIfIdx, nbIf); err != nil { errs = append(errs, err) } // Calculate whether modification is needed - if plugin.isIfModified(nbIf, &vppIf.Interfaces_Interface) { - plugin.log.Debugf("RESYNC interfaces: modifying interface %v", vppIf.Name) - if err = plugin.ModifyVPPInterface(nbIf, &vppIf.Interfaces_Interface); err != nil { + if plugin.isIfModified(nbIf, vppIf.Interface) { + plugin.log.Debugf("RESYNC interfaces: modifying interface %v", vppIf.Interface.Name) + if err = plugin.ModifyVPPInterface(nbIf, vppIf.Interface); err != nil { plugin.log.Errorf("Error while modifying interface: %v", err) errs = append(errs, err) } } else { - plugin.log.Debugf("RESYNC interfaces: %v registered without additional changes", vppIf.Name) + plugin.log.Debugf("RESYNC interfaces: %v registered without additional changes", vppIf.Interface.Name) } break } } if !correlated { // Register interface before removal (to keep state consistent) - if err := plugin.registerInterface(vppIf.Name, vppIfIdx, &vppIf.Interfaces_Interface); err != nil { + if err := plugin.registerInterface(vppIf.Interface.Name, vppIfIdx, vppIf.Interface); err != nil { errs = append(errs, err) } // VPP interface is obsolete and will be removed (un-configured if physical device) - plugin.log.Debugf("RESYNC interfaces: removing obsolete interface %v", vppIf.Name) - if err = plugin.deleteVPPInterface(&vppIf.Interfaces_Interface, vppIfIdx); err != nil { + plugin.log.Debugf("RESYNC interfaces: removing obsolete interface %v", vppIf.Interface.Name) + if err = plugin.deleteVPPInterface(vppIf.Interface, vppIfIdx); err != nil { plugin.log.Errorf("Error while removing interface: %v", err) errs = append(errs, err) } @@ -190,7 +192,7 @@ func (plugin *InterfaceConfigurator) VerifyVPPConfigPresence(nbIfaces []*intf.In var stop bool // Step 0: Dump actual state of the VPP - vppIfaces, err := vppdump.DumpInterfaces(plugin.log, plugin.vppCh, plugin.stopwatch) + vppIfaces, err := plugin.ifHandler.DumpInterfaces() if err != nil { return stop } @@ -234,7 +236,7 @@ func (plugin *BFDConfigurator) ResyncSession(nbSessions []*bfd.SingleHopBFD_Sess plugin.clearMapping() // Dump all BFD vppSessions - vppSessions, err := plugin.DumpBfdSessions() + vppBfdSessions, err := plugin.bfdHandler.DumpBfdSessions() if err != nil { return err } @@ -244,7 +246,7 @@ func (plugin *BFDConfigurator) ResyncSession(nbSessions []*bfd.SingleHopBFD_Sess for _, nbSession := range nbSessions { // look for configured session var found bool - for _, vppSession := range vppSessions { + for _, vppSession := range vppBfdSessions.Session { // compare fixed fields if nbSession.Interface == vppSession.Interface && nbSession.SourceAddress == vppSession.SourceAddress && nbSession.DestinationAddress == vppSession.DestinationAddress { @@ -267,7 +269,7 @@ func (plugin *BFDConfigurator) ResyncSession(nbSessions []*bfd.SingleHopBFD_Sess } // Remove old sessions - for _, vppSession := range vppSessions { + for _, vppSession := range vppBfdSessions.Session { // remove every not-yet-registered session _, _, found := plugin.sessionsIndexes.LookupIdx(vppSession.Interface) if !found { @@ -294,7 +296,7 @@ func (plugin *BFDConfigurator) ResyncAuthKey(nbKeys []*bfd.SingleHopBFD_Key) err }() // lookup BFD auth keys - vppKeys, err := plugin.DumpBFDAuthKeys() + vppBfdKeys, err := plugin.bfdHandler.DumpBfdAuthKeys() if err != nil { return err } @@ -304,7 +306,7 @@ func (plugin *BFDConfigurator) ResyncAuthKey(nbKeys []*bfd.SingleHopBFD_Key) err for _, nbKey := range nbKeys { // look for configured keys var found bool - for _, vppKey := range vppKeys { + for _, vppKey := range vppBfdKeys.AuthKeys { // compare key ID if nbKey.Id == vppKey.Id { plugin.log.Debugf("found configured BFD auth key with ID %v", nbKey.Id) @@ -326,7 +328,7 @@ func (plugin *BFDConfigurator) ResyncAuthKey(nbKeys []*bfd.SingleHopBFD_Key) err } // Remove old keys - for _, vppKey := range vppKeys { + for _, vppKey := range vppBfdKeys.AuthKeys { // remove every not-yet-registered keys _, _, found := plugin.keysIndexes.LookupIdx(AuthKeyIdentifier(vppKey.Id)) if !found { @@ -378,42 +380,35 @@ func (plugin *StnConfigurator) Resync(nbStnRules []*stn.STN_Rule) error { plugin.clearMapping() // Dump existing STN Rules - vppStnRules, err := plugin.Dump() + vppStnDetails, err := plugin.Dump() if err != nil { return err } // Correlate configuration, and remove obsolete rules STN rules var wasErr error - for _, vppStnRule := range vppStnRules { + for _, vppStnRule := range vppStnDetails.Rules { // Parse parameters var vppStnIP net.IP var vppStnIPStr string - if vppStnRule.IsIP4 == 1 { - vppStnIP = vppStnRule.IPAddress[:4] - } else { - vppStnIP = vppStnRule.IPAddress - } - vppStnIPStr = vppStnIP.String() - - vppStnIfName, _, found := plugin.ifIndexes.LookupName(vppStnRule.SwIfIndex) + vppStnIfIdx, _, found := plugin.ifIndexes.LookupIdx(vppStnRule.Interface) if !found { // The rule is attached to non existing interface but it can be removed. If there is a similar // rule in NB config, it will be configured (or cached) - if err := vppcalls.DelStnRule(vppStnRule.SwIfIndex, &vppStnIP, plugin.vppChan, nil); err != nil { + if err := plugin.stnHandler.DelStnRule(vppStnIfIdx, &vppStnIP); err != nil { plugin.log.Error(err) wasErr = err } plugin.log.Debugf("RESYNC STN: rule IP: %v ifIdx: %v removed due to missing interface, will be reconfigured if needed", - vppStnIPStr, vppStnRule.SwIfIndex) + vppStnIPStr, vppStnIfIdx) continue } // Look for equal rule in NB configuration var match bool for _, nbStnRule := range nbStnRules { - if nbStnRule.IpAddress == vppStnIPStr && nbStnRule.Interface == vppStnIfName { + if nbStnRule.IpAddress == vppStnIPStr && nbStnRule.Interface == vppStnRule.Interface { // Register existing rule plugin.indexSTNRule(nbStnRule, false) match = true @@ -423,11 +418,11 @@ func (plugin *StnConfigurator) Resync(nbStnRules []*stn.STN_Rule) error { // If STN rule does not exist, it is obsolete if !match { - if err := vppcalls.DelStnRule(vppStnRule.SwIfIndex, &vppStnIP, plugin.vppChan, nil); err != nil { + if err := plugin.stnHandler.DelStnRule(vppStnIfIdx, &vppStnIP); err != nil { plugin.log.Error(err) wasErr = err } - plugin.log.Debugf("RESYNC STN: rule IP: %v ifName: %v removed as obsolete", vppStnIPStr, vppStnIfName) + plugin.log.Debugf("RESYNC STN: rule IP: %v ifName: %v removed as obsolete", vppStnIPStr, vppStnRule.Interface) } } @@ -454,7 +449,7 @@ func (plugin *NatConfigurator) ResyncNatGlobal(nbGlobal *nat.Nat44Global) error // Re-initialize cache plugin.clearMapping() - vppNatGlobal, err := vppdump.Nat44GlobalConfigDump(plugin.ifIndexes, plugin.log, plugin.vppChan, plugin.stopwatch) + vppNatGlobal, err := plugin.natHandler.Nat44GlobalConfigDump() if err != nil { return fmt.Errorf("failed to dump NAT44 global config: %v", err) } @@ -473,7 +468,7 @@ func (plugin *NatConfigurator) ResyncSNat(sNatConf []*nat.Nat44SNat_SNatConfig) func (plugin *NatConfigurator) ResyncDNat(nbDNatConfig []*nat.Nat44DNat_DNatConfig) error { plugin.log.Debug("RESYNC DNAT config.") - vppDNatCfg, err := vppdump.NAT44DNatDump(plugin.ifIndexes, plugin.log, plugin.vppChan, plugin.stopwatch) + vppDNatCfg, err := plugin.natHandler.Nat44DNatDump() if err != nil { return fmt.Errorf("failed to dump DNAT config: %v", err) } @@ -513,18 +508,18 @@ func (plugin *NatConfigurator) ResyncDNat(nbDNatConfig []*nat.Nat44DNat_DNatConf } } // Configure all missing DNAT identity mappings - for _, nbIdMapping := range nbDNat.IdMappings { - mappingIdentifier := GetIdMappingIdentifier(nbIdMapping) - _, _, found := plugin.dNatIdMappingIndexes.LookupIdx(mappingIdentifier) + for _, nbIDMapping := range nbDNat.IdMappings { + mappingIdentifier := GetIDMappingIdentifier(nbIDMapping) + _, _, found := plugin.dNatIDMappingIndexes.LookupIdx(mappingIdentifier) if !found { // Configure missing mapping - if err := plugin.handleIdentityMapping(nbIdMapping, "", true); err != nil { + if err := plugin.handleIdentityMapping(nbIDMapping, "", true); err != nil { plugin.log.Errorf("NAT44 resync: failed to configure identity mapping: %v", err) continue } // Register new DNAT mapping - plugin.dNatIdMappingIndexes.RegisterName(mappingIdentifier, plugin.natIndexSeq, nil) + plugin.dNatIDMappingIndexes.RegisterName(mappingIdentifier, plugin.natIndexSeq, nil) plugin.natIndexSeq++ plugin.log.Debugf("NAT44 resync: new identity mapping %v configured", mappingIdentifier) } @@ -546,9 +541,9 @@ func (plugin *NatConfigurator) ResyncDNat(nbDNatConfig []*nat.Nat44DNat_DNatConf } } } - for _, vppIdMapping := range vppDNat.IdMappings { + for _, vppIDMapping := range vppDNat.IdMappings { // Identity mapping - if err := plugin.handleIdentityMapping(vppIdMapping, "", false); err != nil { + if err := plugin.handleIdentityMapping(vppIDMapping, "", false); err != nil { plugin.log.Errorf("NAT44 resync: failed to remove identity mapping: %v", err) continue } @@ -578,7 +573,7 @@ func (plugin *NatConfigurator) ResyncDNat(nbDNatConfig []*nat.Nat44DNat_DNatConf // Looks for the same mapping in the VPP, register existing ones func (plugin *NatConfigurator) resolveMappings(nbDNatConfig *nat.Nat44DNat_DNatConfig, - vppMappings *[]*nat.Nat44DNat_DNatConfig_StaticMapping, vppIdMappings *[]*nat.Nat44DNat_DNatConfig_IdentityMapping) { + vppMappings *[]*nat.Nat44DNat_DNatConfig_StaticMapping, vppIDMappings *[]*nat.Nat44DNat_DNatConfig_IdentityMapping) { // Iterate over static mappings in NB DNAT config for _, nbMapping := range nbDNatConfig.StMappings { if len(nbMapping.LocalIps) > 1 { @@ -586,7 +581,7 @@ func (plugin *NatConfigurator) resolveMappings(nbDNatConfig *nat.Nat44DNat_DNatC MappingCompare: for vppIndex, vppLbMapping := range *vppMappings { // Compare VRF/SNAT fields - if nbMapping.VrfId != vppLbMapping.VrfId || nbMapping.TwiceNat != vppLbMapping.TwiceNat { + if nbMapping.TwiceNat != vppLbMapping.TwiceNat { continue } // Compare external IP/Port @@ -604,8 +599,7 @@ func (plugin *NatConfigurator) resolveMappings(nbDNatConfig *nat.Nat44DNat_DNatC for _, nbLocal := range nbMapping.LocalIps { var found bool for _, vppLocal := range vppLbMapping.LocalIps { - if nbLocal.LocalIp == vppLocal.LocalIp || nbLocal.LocalPort == vppLocal.LocalPort || - nbLocal.Probability == vppLocal.Probability { + if *nbLocal == *vppLocal { found = true } } @@ -627,7 +621,7 @@ func (plugin *NatConfigurator) resolveMappings(nbDNatConfig *nat.Nat44DNat_DNatC // No load balancer for vppIndex, vppMapping := range *vppMappings { // Compare VRF/SNAT fields - if nbMapping.VrfId != vppMapping.VrfId || nbMapping.TwiceNat != vppMapping.TwiceNat { + if nbMapping.TwiceNat != vppMapping.TwiceNat { continue } // Compare external IP/Port and interface @@ -649,8 +643,7 @@ func (plugin *NatConfigurator) resolveMappings(nbDNatConfig *nat.Nat44DNat_DNatC } nbLocal := nbMapping.LocalIps[0] vppLocal := vppMapping.LocalIps[0] - if nbLocal.LocalIp != vppLocal.LocalIp || nbLocal.LocalPort != vppLocal.LocalPort || - nbLocal.Probability != vppLocal.Probability { + if *nbLocal != *vppLocal { continue } @@ -667,29 +660,29 @@ func (plugin *NatConfigurator) resolveMappings(nbDNatConfig *nat.Nat44DNat_DNatC } } // Iterate over identity mappings in NB DNAT config - for _, nbIdMapping := range nbDNatConfig.IdMappings { - for vppIdIndex, vppIdMapping := range *vppIdMappings { + for _, nbIDMapping := range nbDNatConfig.IdMappings { + for vppIDIndex, vppIDMapping := range *vppIDMappings { // Compare VRF and address interface - if nbIdMapping.VrfId != vppIdMapping.VrfId || nbIdMapping.AddressedInterface != vppIdMapping.AddressedInterface { + if nbIDMapping.VrfId != vppIDMapping.VrfId || nbIDMapping.AddressedInterface != vppIDMapping.AddressedInterface { continue } // Compare IP and port values - if nbIdMapping.IpAddress != vppIdMapping.IpAddress || nbIdMapping.Port != vppIdMapping.Port { + if nbIDMapping.IpAddress != vppIDMapping.IpAddress || nbIDMapping.Port != vppIDMapping.Port { continue } // Compare protocol - if nbIdMapping.Protocol != vppIdMapping.Protocol { + if nbIDMapping.Protocol != vppIDMapping.Protocol { continue } // At this point, the NB mapping matched the VPP one, so register it - mappingIdentifier := GetIdMappingIdentifier(nbIdMapping) - plugin.dNatIdMappingIndexes.RegisterName(mappingIdentifier, plugin.natIndexSeq, nil) + mappingIdentifier := GetIDMappingIdentifier(nbIDMapping) + plugin.dNatIDMappingIndexes.RegisterName(mappingIdentifier, plugin.natIndexSeq, nil) plugin.natIndexSeq++ // Remove registered entry from vpp mapping (configurator knows which mappings were registered) - dIdMappings := *vppIdMappings - *vppIdMappings = append(dIdMappings[:vppIdIndex], dIdMappings[vppIdIndex+1:]...) + dIDMappings := *vppIDMappings + *vppIDMappings = append(dIDMappings[:vppIDIndex], dIDMappings[vppIDIndex+1:]...) plugin.log.Debugf("NAT44 resync: identity mapping %v already configured", mappingIdentifier) } } @@ -1003,7 +996,7 @@ func (plugin *InterfaceConfigurator) isIfModified(nbIf, vppIf *intf.Interfaces_I // Register interface to mapping and add tag/index to the VPP func (plugin *InterfaceConfigurator) registerInterface(ifName string, ifIdx uint32, ifData *intf.Interfaces_Interface) error { plugin.swIfIndexes.RegisterName(ifName, ifIdx, ifData) - if err := vppcalls.SetInterfaceTag(ifName, ifIdx, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.SetInterfaceTag(ifName, ifIdx); err != nil { return fmt.Errorf("error while adding interface tag %s, index %d: %v", ifName, ifIdx, err) } // Add AF-packet type interface to local cache diff --git a/plugins/vpp/ifplugin/data_resync_test.go b/plugins/vpp/ifplugin/data_resync_test.go index 96f111a9f1..bc40e00ed7 100644 --- a/plugins/vpp/ifplugin/data_resync_test.go +++ b/plugins/vpp/ifplugin/data_resync_test.go @@ -23,16 +23,12 @@ import ( "github.com/ligato/cn-infra/logging" "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/idxvpp/nametoidx" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/af_packet" bfdApi "github.com/ligato/vpp-agent/plugins/vpp/binapi/bfd" "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" "github.com/ligato/vpp-agent/plugins/vpp/binapi/memif" natApi "github.com/ligato/vpp-agent/plugins/vpp/binapi/nat" stnApi "github.com/ligato/vpp-agent/plugins/vpp/binapi/stn" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/tap" "github.com/ligato/vpp-agent/plugins/vpp/binapi/tapv2" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/vpe" "github.com/ligato/vpp-agent/plugins/vpp/binapi/vxlan" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" @@ -44,98 +40,15 @@ import ( . "github.com/onsi/gomega" ) -type vppReplyMock struct { - Name string - Ping bool - Message govppapi.Message - Messages []govppapi.Message -} - -func vppMockHandler(vppMock *mock.VppAdapter, dataList []*vppReplyMock) mock.ReplyHandler { - var sendControlPing bool - - vppMock.RegisterBinAPITypes(af_packet.Types) - vppMock.RegisterBinAPITypes(bfdApi.Types) - vppMock.RegisterBinAPITypes(natApi.Types) - vppMock.RegisterBinAPITypes(stnApi.Types) - vppMock.RegisterBinAPITypes(interfaces.Types) - vppMock.RegisterBinAPITypes(ip.Types) - vppMock.RegisterBinAPITypes(memif.Types) - vppMock.RegisterBinAPITypes(tap.Types) - vppMock.RegisterBinAPITypes(tapv2.Types) - vppMock.RegisterBinAPITypes(vpe.Types) - vppMock.RegisterBinAPITypes(vxlan.Types) - - return func(request mock.MessageDTO) (reply []byte, msgID uint16, prepared bool) { - // Following types are not automatically stored in mock adapter's map and will be sent with empty MsgName - // TODO: initialize mock adapter's map with these - switch request.MsgID { - case 100: - request.MsgName = "control_ping" - case 101: - request.MsgName = "control_ping_reply" - case 200: - request.MsgName = "sw_interface_dump" - case 201: - request.MsgName = "sw_interface_details" - } - - if request.MsgName == "" { - logrus.DefaultLogger().Fatalf("mockHandler received request (ID: %v) with empty MsgName, check if compatbility check is done before using this request", request.MsgID) - } - - if sendControlPing { - sendControlPing = false - data := &vpe.ControlPingReply{} - reply, err := vppMock.ReplyBytes(request, data) - Expect(err).To(BeNil()) - msgID, err := vppMock.GetMsgID(data.GetMessageName(), data.GetCrcString()) - Expect(err).To(BeNil()) - return reply, msgID, true - } - - for _, dataMock := range dataList { - if request.MsgName == dataMock.Name { - // Send control ping next iteration if set - sendControlPing = dataMock.Ping - if len(dataMock.Messages) > 0 { - logrus.DefaultLogger().Infof(" MOCK HANDLER: mocking %d messages", len(dataMock.Messages)) - for _, msg := range dataMock.Messages { - vppMock.MockReply(msg) - } - return nil, 0, false - } - msgID, err := vppMock.GetMsgID(dataMock.Message.GetMessageName(), dataMock.Message.GetCrcString()) - Expect(err).To(BeNil()) - reply, err := vppMock.ReplyBytes(request, dataMock.Message) - Expect(err).To(BeNil()) - return reply, msgID, true - } - } - - replyMsg, msgID, ok := vppMock.ReplyFor(request.MsgName) - if ok { - reply, err := vppMock.ReplyBytes(request, replyMsg) - Expect(err).To(BeNil()) - return reply, msgID, true - } else { - logrus.DefaultLogger().Warnf("no reply for %v found", request.MsgName) - } - - return reply, 0, false - } -} +// TODO: use configurator initializers from other files which do the same thing -func interfaceConfiguratorTestInitialization(t *testing.T, mocks []*vppReplyMock) (*ifplugin.InterfaceConfigurator, *govpp.Connection) { - // Setup +func interfaceConfiguratorTestInitialization(t *testing.T) (*vppcallmock.TestCtx, *ifplugin.InterfaceConfigurator, *govpp.Connection) { RegisterTestingT(t) ctx := &vppcallmock.TestCtx{ MockVpp: &mock.VppAdapter{}, } - ctx.MockVpp.MockReplyHandler(vppMockHandler(ctx.MockVpp, mocks)) - conn, err := govpp.Connect(ctx.MockVpp) Expect(err).To(BeNil()) @@ -143,118 +56,114 @@ func interfaceConfiguratorTestInitialization(t *testing.T, mocks []*vppReplyMock plugin := &ifplugin.InterfaceConfigurator{} ifVppNotifCh := make(chan govppapi.Message, 100) - plugLog := logging.ForPlugin("tests", logrus.NewLogRegistry()) + plugLog := logging.ForPlugin("tests") - err = plugin.Init(plugLog, conn, nil, ifVppNotifCh, 0, false) + err = plugin.Init(plugLog, conn, nil, ifVppNotifCh, 0, true) Expect(err).To(BeNil()) - return plugin, conn + return ctx, plugin, conn } -func bfdConfiguratorTestInitialization(t *testing.T, mocks []*vppReplyMock) (*ifplugin.BFDConfigurator, *govpp.Connection, ifaceidx.SwIfIndexRW) { - // Setup +func interfaceConfiguratorTestTeardown(plugin *ifplugin.InterfaceConfigurator, conn *govpp.Connection) { + conn.Disconnect() + Expect(plugin.Close()).To(BeNil()) + logging.DefaultRegistry.ClearRegistry() +} + +func bfdConfiguratorTestInitialization(t *testing.T) (*vppcallmock.TestCtx, *ifplugin.BFDConfigurator, *govpp.Connection, ifaceidx.SwIfIndexRW) { RegisterTestingT(t) ctx := &vppcallmock.TestCtx{ MockVpp: &mock.VppAdapter{}, } - ctx.MockVpp.MockReplyHandler(vppMockHandler(ctx.MockVpp, mocks)) - - connection, _ := govpp.Connect(ctx.MockVpp) - plugin := &ifplugin.BFDConfigurator{} + c, err := govpp.Connect(ctx.MockVpp) + Expect(err).To(BeNil()) // initialize index nameToIdx := nametoidx.NewNameToIdx(logrus.DefaultLogger(), "sw_if_index_test", ifaceidx.IndexMetadata) index := ifaceidx.NewSwIfIndex(nameToIdx) names := nameToIdx.ListNames() - - // check if names were empty Expect(names).To(BeEmpty()) // Test init - err := plugin.Init( - logging.ForPlugin("test-log", - logrus.NewLogRegistry()), - connection, - index, - false) - + plugin := &ifplugin.BFDConfigurator{} + err = plugin.Init(logging.ForPlugin("test-log"), c, index, true) Expect(err).To(BeNil()) - return plugin, connection, index + return ctx, plugin, c, index } -func stnConfiguratorTestInitialization(t *testing.T, mocks []*vppReplyMock) (*ifplugin.StnConfigurator, *govpp.Connection) { - // Setup +func bfdConfiguratorTestTeardown(plugin *ifplugin.BFDConfigurator, conn *govpp.Connection) { + conn.Disconnect() + Expect(plugin.Close()).To(BeNil()) + logging.DefaultRegistry.ClearRegistry() +} + +func stnConfiguratorTestInitialization(t *testing.T) (*vppcallmock.TestCtx, *ifplugin.StnConfigurator, *govpp.Connection) { RegisterTestingT(t) ctx := &vppcallmock.TestCtx{ MockVpp: &mock.VppAdapter{}, } - - ctx.MockVpp.MockReplyHandler(vppMockHandler(ctx.MockVpp, mocks)) - - connection, _ := govpp.Connect(ctx.MockVpp) - plugin := &ifplugin.StnConfigurator{} + c, err := govpp.Connect(ctx.MockVpp) + Expect(err).To(BeNil()) // initialize index nameToIdx := nametoidx.NewNameToIdx(logrus.DefaultLogger(), "sw_if_index_test", ifaceidx.IndexMetadata) index := ifaceidx.NewSwIfIndex(nameToIdx) names := nameToIdx.ListNames() - - // check if names were empty Expect(names).To(BeEmpty()) // Test init - err := plugin.Init( - logging.ForPlugin("test-log", - logrus.NewLogRegistry()), - connection, - index, - false) - + plugin := &ifplugin.StnConfigurator{} + err = plugin.Init(logging.ForPlugin("test-log"), c, index, true) Expect(err).To(BeNil()) - return plugin, connection + + return ctx, plugin, c +} + +func stnConfiguratorTestTeardown(plugin *ifplugin.StnConfigurator, conn *govpp.Connection) { + conn.Disconnect() + Expect(plugin.Close()).To(BeNil()) + logging.DefaultRegistry.ClearRegistry() } -func natConfiguratorTestInitialization(t *testing.T, mocks []*vppReplyMock) (*ifplugin.NatConfigurator, ifaceidx.SwIfIndexRW, *govpp.Connection) { - // Setup +func natConfiguratorTestInitialization(t *testing.T) (*vppcallmock.TestCtx, *ifplugin.NatConfigurator, *govpp.Connection, ifaceidx.SwIfIndexRW) { RegisterTestingT(t) ctx := &vppcallmock.TestCtx{ MockVpp: &mock.VppAdapter{}, } - - ctx.MockVpp.MockReplyHandler(vppMockHandler(ctx.MockVpp, mocks)) - - connection, _ := govpp.Connect(ctx.MockVpp) - plugin := &ifplugin.NatConfigurator{} + c, err := govpp.Connect(ctx.MockVpp) + Expect(err).To(BeNil()) // initialize index nameToIdx := nametoidx.NewNameToIdx(logrus.DefaultLogger(), "sw_if_index_test", ifaceidx.IndexMetadata) index := ifaceidx.NewSwIfIndex(nameToIdx) names := nameToIdx.ListNames() - - // check if names were empty Expect(names).To(BeEmpty()) // Test init - err := plugin.Init( - logging.ForPlugin("test-log", - logrus.NewLogRegistry()), - connection, - index, - false) - + plugin := &ifplugin.NatConfigurator{} + err = plugin.Init(logging.ForPlugin("test-log"), c, index, true) Expect(err).To(BeNil()) - return plugin, index, connection + + return ctx, plugin, c, index +} + +func natConfiguratorTestTeardown(plugin *ifplugin.NatConfigurator, conn *govpp.Connection) { + conn.Disconnect() + Expect(plugin.Close()).To(BeNil()) + logging.DefaultRegistry.ClearRegistry() } // Tests InterfaceConfigurator resync func TestDataResyncResync(t *testing.T) { - // Setup - plugin, conn := interfaceConfiguratorTestInitialization(t, []*vppReplyMock{ + ctx, plugin, conn := interfaceConfiguratorTestInitialization(t) + defer interfaceConfiguratorTestTeardown(plugin, conn) + + ctx.MockReplies([]*vppcallmock.HandleReplies{ { Name: (&interfaces.SwInterfaceDump{}).GetMessageName(), Ping: true, @@ -276,11 +185,6 @@ func TestDataResyncResync(t *testing.T) { }, }) - defer plugin.Close() - defer conn.Disconnect() - - Expect(plugin.IsSocketFilenameCached("testsocket")).To(BeTrue()) - // Test intfaces := []*intf.Interfaces_Interface{ { @@ -298,6 +202,7 @@ func TestDataResyncResync(t *testing.T) { errs := plugin.Resync(intfaces) Expect(errs).To(BeEmpty()) + Expect(plugin.IsSocketFilenameCached("testsocket")).To(BeTrue()) _, meta, found := plugin.GetSwIfIndexes().LookupIdx("test") Expect(found).To(BeTrue()) @@ -307,8 +212,10 @@ func TestDataResyncResync(t *testing.T) { // Tests InterfaceConfigurator resync with SwIfIndex 0 func TestDataResyncResyncIdx0(t *testing.T) { - // Setup - plugin, conn := interfaceConfiguratorTestInitialization(t, []*vppReplyMock{ + ctx, plugin, conn := interfaceConfiguratorTestInitialization(t) + defer interfaceConfiguratorTestTeardown(plugin, conn) + + ctx.MockReplies([]*vppcallmock.HandleReplies{ { Name: (&interfaces.SwInterfaceDump{}).GetMessageName(), Ping: true, @@ -330,9 +237,6 @@ func TestDataResyncResyncIdx0(t *testing.T) { }, }) - defer plugin.Close() - defer conn.Disconnect() - // Test intfaces := []*intf.Interfaces_Interface{ { @@ -359,8 +263,10 @@ func TestDataResyncResyncIdx0(t *testing.T) { // Tests InterfaceConfigurator resync with same interface name/tag func TestDataResyncResyncSameName(t *testing.T) { - // Setup - plugin, conn := interfaceConfiguratorTestInitialization(t, []*vppReplyMock{ + ctx, plugin, conn := interfaceConfiguratorTestInitialization(t) + defer interfaceConfiguratorTestTeardown(plugin, conn) + + ctx.MockReplies([]*vppcallmock.HandleReplies{ { Name: (&interfaces.SwInterfaceDump{}).GetMessageName(), Ping: true, @@ -382,9 +288,6 @@ func TestDataResyncResyncSameName(t *testing.T) { }, }) - defer plugin.Close() - defer conn.Disconnect() - // Test intfaces := []*intf.Interfaces_Interface{ { @@ -409,8 +312,10 @@ func TestDataResyncResyncSameName(t *testing.T) { // Tests InterfaceConfigurator resync with unnamed interface func TestDataResyncResyncUnnamed(t *testing.T) { - // Setup - plugin, conn := interfaceConfiguratorTestInitialization(t, []*vppReplyMock{ + ctx, plugin, conn := interfaceConfiguratorTestInitialization(t) + defer interfaceConfiguratorTestTeardown(plugin, conn) + + ctx.MockReplies([]*vppcallmock.HandleReplies{ { Name: (&interfaces.SwInterfaceDump{}).GetMessageName(), Ping: true, @@ -431,9 +336,6 @@ func TestDataResyncResyncUnnamed(t *testing.T) { }, }) - defer plugin.Close() - defer conn.Disconnect() - // Test intfaces := []*intf.Interfaces_Interface{ { @@ -460,8 +362,10 @@ func TestDataResyncResyncUnnamed(t *testing.T) { // Tests InterfaceConfigurator resync with unnumbered VXLAN interface func TestDataResyncResyncUnnumbered(t *testing.T) { - // Setup - plugin, conn := interfaceConfiguratorTestInitialization(t, []*vppReplyMock{ + ctx, plugin, conn := interfaceConfiguratorTestInitialization(t) + defer interfaceConfiguratorTestTeardown(plugin, conn) + + ctx.MockReplies([]*vppcallmock.HandleReplies{ { Name: (&interfaces.SwInterfaceDump{}).GetMessageName(), Ping: true, @@ -493,9 +397,6 @@ func TestDataResyncResyncUnnumbered(t *testing.T) { }, }) - defer plugin.Close() - defer conn.Disconnect() - // Test intfaces := []*intf.Interfaces_Interface{ { @@ -526,8 +427,10 @@ func TestDataResyncResyncUnnumbered(t *testing.T) { // Tests InterfaceConfigurator resync with unnumbered tap interface func TestDataResyncResyncUnnumberedTap(t *testing.T) { - // Setup - plugin, conn := interfaceConfiguratorTestInitialization(t, []*vppReplyMock{ + ctx, plugin, conn := interfaceConfiguratorTestInitialization(t) + defer interfaceConfiguratorTestTeardown(plugin, conn) + + ctx.MockReplies([]*vppcallmock.HandleReplies{ { Name: (&interfaces.SwInterfaceDump{}).GetMessageName(), Ping: true, @@ -558,9 +461,6 @@ func TestDataResyncResyncUnnumberedTap(t *testing.T) { }, }) - defer plugin.Close() - defer conn.Disconnect() - // Test intfaces := []*intf.Interfaces_Interface{ { @@ -591,8 +491,10 @@ func TestDataResyncResyncUnnumberedTap(t *testing.T) { // Tests InterfaceConfigurator resync with unnumbered AF_PACKET interface func TestDataResyncResyncUnnumberedAfPacket(t *testing.T) { - // Setup - plugin, conn := interfaceConfiguratorTestInitialization(t, []*vppReplyMock{ + ctx, plugin, conn := interfaceConfiguratorTestInitialization(t) + defer interfaceConfiguratorTestTeardown(plugin, conn) + + ctx.MockReplies([]*vppcallmock.HandleReplies{ { Name: (&interfaces.SwInterfaceDump{}).GetMessageName(), Ping: true, @@ -614,9 +516,6 @@ func TestDataResyncResyncUnnumberedAfPacket(t *testing.T) { }, }) - defer plugin.Close() - defer conn.Disconnect() - // Test intfaces := []*intf.Interfaces_Interface{ { @@ -645,8 +544,10 @@ func TestDataResyncResyncUnnumberedAfPacket(t *testing.T) { // Tests InterfaceConfigurator resync with unnumbered MEMIF interface func TestDataResyncResyncUnnumberedMemif(t *testing.T) { - // Setup - plugin, conn := interfaceConfiguratorTestInitialization(t, []*vppReplyMock{ + ctx, plugin, conn := interfaceConfiguratorTestInitialization(t) + defer interfaceConfiguratorTestTeardown(plugin, conn) + + ctx.MockReplies([]*vppcallmock.HandleReplies{ { Name: (&interfaces.SwInterfaceDump{}).GetMessageName(), Ping: true, @@ -679,9 +580,6 @@ func TestDataResyncResyncUnnumberedMemif(t *testing.T) { }, }) - defer plugin.Close() - defer conn.Disconnect() - // Test intfaces := []*intf.Interfaces_Interface{ { @@ -713,8 +611,10 @@ func TestDataResyncResyncUnnumberedMemif(t *testing.T) { // Tests if InterfaceConfigurator VPP config is present func TestDataResyncVerifyVPPConfigPresence(t *testing.T) { - // Setup - plugin, conn := interfaceConfiguratorTestInitialization(t, []*vppReplyMock{ + ctx, plugin, conn := interfaceConfiguratorTestInitialization(t) + defer interfaceConfiguratorTestTeardown(plugin, conn) + + ctx.MockReplies([]*vppcallmock.HandleReplies{ { Name: (&interfaces.SwInterfaceDump{}).GetMessageName(), Ping: true, @@ -735,9 +635,6 @@ func TestDataResyncVerifyVPPConfigPresence(t *testing.T) { }, }) - defer plugin.Close() - defer conn.Disconnect() - // Test intfaces := []*intf.Interfaces_Interface{ { @@ -757,8 +654,10 @@ func TestDataResyncVerifyVPPConfigPresence(t *testing.T) { // Tests if InterfaceConfigurator VPP config is not present func TestDataResyncVerifyVPPConfigPresenceNegative(t *testing.T) { - // Setup - plugin, conn := interfaceConfiguratorTestInitialization(t, []*vppReplyMock{ + ctx, plugin, conn := interfaceConfiguratorTestInitialization(t) + defer interfaceConfiguratorTestTeardown(plugin, conn) + + ctx.MockReplies([]*vppcallmock.HandleReplies{ { Name: (&interfaces.SwInterfaceDump{}).GetMessageName(), Ping: true, @@ -785,9 +684,6 @@ func TestDataResyncVerifyVPPConfigPresenceNegative(t *testing.T) { }, }) - defer plugin.Close() - defer conn.Disconnect() - // Test ok := plugin.VerifyVPPConfigPresence([]*intf.Interfaces_Interface{}) Expect(ok).To(BeFalse()) @@ -799,8 +695,10 @@ func TestDataResyncVerifyVPPConfigPresenceNegative(t *testing.T) { // Tests BFDConfigurator session resync func TestDataResyncResyncSession(t *testing.T) { - // Setup - plugin, conn, index := bfdConfiguratorTestInitialization(t, []*vppReplyMock{ + ctx, plugin, conn, index := bfdConfiguratorTestInitialization(t) + defer bfdConfiguratorTestTeardown(plugin, conn) + + ctx.MockReplies([]*vppcallmock.HandleReplies{ { Name: (&bfdApi.BfdUDPAdd{}).GetMessageName(), Message: &bfdApi.BfdUDPAddReply{}, @@ -820,9 +718,6 @@ func TestDataResyncResyncSession(t *testing.T) { }, }) - defer plugin.Close() - defer conn.Disconnect() - index.RegisterName("if0", 0, &intf.Interfaces_Interface{ Name: "if0", IpAddresses: []string{"192.168.1.10", "192.168.2.10"}, @@ -846,8 +741,10 @@ func TestDataResyncResyncSession(t *testing.T) { // Tests BFDConfigurator session resync func TestDataResyncResyncSessionSameData(t *testing.T) { - // Setup - plugin, conn, index := bfdConfiguratorTestInitialization(t, []*vppReplyMock{ + ctx, plugin, conn, index := bfdConfiguratorTestInitialization(t) + defer bfdConfiguratorTestTeardown(plugin, conn) + + ctx.MockReplies([]*vppcallmock.HandleReplies{ { Name: (&bfdApi.BfdUDPAdd{}).GetMessageName(), Message: &bfdApi.BfdUDPAddReply{}, @@ -872,9 +769,6 @@ func TestDataResyncResyncSessionSameData(t *testing.T) { }, }) - defer plugin.Close() - defer conn.Disconnect() - index.RegisterName("if0", 1, &intf.Interfaces_Interface{ Name: "if0", IpAddresses: []string{"192.168.1.10", "192.168.2.10"}, @@ -898,8 +792,10 @@ func TestDataResyncResyncSessionSameData(t *testing.T) { // Tests BFDConfigurator authorization key resync func TestDataResyncResyncAuthKey(t *testing.T) { - // Setup - plugin, conn, _ := bfdConfiguratorTestInitialization(t, []*vppReplyMock{ + ctx, plugin, conn, _ := bfdConfiguratorTestInitialization(t) + defer bfdConfiguratorTestTeardown(plugin, conn) + + ctx.MockReplies([]*vppcallmock.HandleReplies{ { Name: (&bfdApi.BfdAuthKeysDump{}).GetMessageName(), Ping: true, @@ -920,9 +816,6 @@ func TestDataResyncResyncAuthKey(t *testing.T) { }, }) - defer plugin.Close() - defer conn.Disconnect() - // Test authKey := []*bfd.SingleHopBFD_Key{ { @@ -939,8 +832,10 @@ func TestDataResyncResyncAuthKey(t *testing.T) { // Tests BFDConfigurator authorization key resync func TestDataResyncResyncAuthKeyNoMatch(t *testing.T) { - // Setup - plugin, conn, _ := bfdConfiguratorTestInitialization(t, []*vppReplyMock{ + ctx, plugin, conn, _ := bfdConfiguratorTestInitialization(t) + defer bfdConfiguratorTestTeardown(plugin, conn) + + ctx.MockReplies([]*vppcallmock.HandleReplies{ { Name: (&bfdApi.BfdAuthKeysDump{}).GetMessageName(), Ping: true, @@ -963,9 +858,6 @@ func TestDataResyncResyncAuthKeyNoMatch(t *testing.T) { }, }) - defer plugin.Close() - defer conn.Disconnect() - // Test authKey := []*bfd.SingleHopBFD_Key{ { @@ -983,17 +875,16 @@ func TestDataResyncResyncAuthKeyNoMatch(t *testing.T) { // Tests BFDConfigurator echo resync func TestDataResyncResyncEchoFunction(t *testing.T) { - // Setup - plugin, conn, index := bfdConfiguratorTestInitialization(t, []*vppReplyMock{ + ctx, plugin, conn, index := bfdConfiguratorTestInitialization(t) + defer bfdConfiguratorTestTeardown(plugin, conn) + + ctx.MockReplies([]*vppcallmock.HandleReplies{ { Name: (&bfdApi.BfdUDPSetEchoSource{}).GetMessageName(), Message: &bfdApi.BfdUDPSetEchoSourceReply{}, }, }) - defer plugin.Close() - defer conn.Disconnect() - index.RegisterName("if0", 0, &intf.Interfaces_Interface{ Name: "if0", IpAddresses: []string{"192.168.1.10/24"}, @@ -1016,28 +907,22 @@ func TestDataResyncResyncEchoFunction(t *testing.T) { // Tests StnConfigurator resync func TestDataResyncResyncStn(t *testing.T) { - // Setup - plugin, conn := stnConfiguratorTestInitialization(t, []*vppReplyMock{ - { - Name: (&stnApi.StnRulesDump{}).GetMessageName(), - Ping: true, - Message: &stnApi.StnRulesDetails{}, - }, + ctx, plugin, conn := stnConfiguratorTestInitialization(t) + defer stnConfiguratorTestTeardown(plugin, conn) + + ctx.MockReplies([]*vppcallmock.HandleReplies{ { Name: (&stnApi.StnAddDelRule{}).GetMessageName(), Message: &stnApi.StnAddDelRuleReply{}, }, }) - defer plugin.Close() - defer conn.Disconnect() - // Test nbStnRules := []*stn.STN_Rule{ { RuleName: "test", Interface: "if0", - IpAddress: "192.168.0.1/24", + IpAddress: "192.168.0.1", }, } @@ -1049,8 +934,10 @@ func TestDataResyncResyncStn(t *testing.T) { // Tests NATConfigurator NAT global resync func TestDataResyncResyncNatGlobal(t *testing.T) { - // Setup - plugin, _, conn := natConfiguratorTestInitialization(t, []*vppReplyMock{ + ctx, plugin, conn, _ := natConfiguratorTestInitialization(t) + defer natConfiguratorTestTeardown(plugin, conn) + + ctx.MockReplies([]*vppcallmock.HandleReplies{ { Name: (&natApi.Nat44ForwardingIsEnabled{}).GetMessageName(), Message: &natApi.Nat44ForwardingIsEnabledReply{}, @@ -1081,9 +968,6 @@ func TestDataResyncResyncNatGlobal(t *testing.T) { }, }) - defer plugin.Close() - defer conn.Disconnect() - // Test nbGlobal := &nat.Nat44Global{ NatInterfaces: []*nat.Nat44Global_NatInterface{ @@ -1101,10 +985,10 @@ func TestDataResyncResyncNatGlobal(t *testing.T) { // Tests NATConfigurator SNAT resync func TestDataResyncResyncSNat(t *testing.T) { - // Setup - plugin, _, conn := natConfiguratorTestInitialization(t, []*vppReplyMock{}) - defer plugin.Close() - defer conn.Disconnect() + ctx, plugin, conn, _ := natConfiguratorTestInitialization(t) + defer natConfiguratorTestTeardown(plugin, conn) + + ctx.MockReplies(nil) // Test sNatConf := []*nat.Nat44SNat_SNatConfig{ @@ -1120,8 +1004,10 @@ func TestDataResyncResyncSNat(t *testing.T) { // Tests NATConfigurator DNAT resync func TestDataResyncResyncDNat(t *testing.T) { - // Setup - plugin, index, conn := natConfiguratorTestInitialization(t, []*vppReplyMock{ + ctx, plugin, conn, index := natConfiguratorTestInitialization(t) + defer natConfiguratorTestTeardown(plugin, conn) + + ctx.MockReplies([]*vppcallmock.HandleReplies{ { Name: (&natApi.Nat44AddDelStaticMapping{}).GetMessageName(), Message: &natApi.Nat44AddDelStaticMappingReply{}, @@ -1162,9 +1048,6 @@ func TestDataResyncResyncDNat(t *testing.T) { }, }) - defer plugin.Close() - defer conn.Disconnect() - // Register index index.RegisterName("if0", 0, &intf.Interfaces_Interface{ Name: "if0", @@ -1256,19 +1139,21 @@ func TestDataResyncResyncDNat(t *testing.T) { }, }) - idIdent := ifplugin.GetIdMappingIdentifier(&nat.Nat44DNat_DNatConfig_IdentityMapping{ + idIdent := ifplugin.GetIDMappingIdentifier(&nat.Nat44DNat_DNatConfig_IdentityMapping{ Protocol: nat.Protocol_TCP, IpAddress: "192.168.0.1", }) - Expect(plugin.IsDNatLabelIdMappingRegistered(idIdent)).To(BeTrue()) + Expect(plugin.IsDNatLabelIDMappingRegistered(idIdent)).To(BeTrue()) Expect(plugin.IsDNatLabelStMappingRegistered(stIdent)).To(BeTrue()) } // Tests NATConfigurator DNAT resync func TestDataResyncResyncDNatMultipleIPs(t *testing.T) { - // Setup - plugin, index, conn := natConfiguratorTestInitialization(t, []*vppReplyMock{ + ctx, plugin, conn, index := natConfiguratorTestInitialization(t) + defer natConfiguratorTestTeardown(plugin, conn) + + ctx.MockReplies([]*vppcallmock.HandleReplies{ { Name: (&natApi.Nat44AddDelStaticMapping{}).GetMessageName(), Message: &natApi.Nat44AddDelStaticMappingReply{}, @@ -1307,9 +1192,6 @@ func TestDataResyncResyncDNatMultipleIPs(t *testing.T) { }, }) - defer plugin.Close() - defer conn.Disconnect() - // Register index index.RegisterName("if0", 0, &intf.Interfaces_Interface{ Name: "if0", @@ -1444,11 +1326,290 @@ func TestDataResyncResyncDNatMultipleIPs(t *testing.T) { }, }) - idIdent := ifplugin.GetIdMappingIdentifier(&nat.Nat44DNat_DNatConfig_IdentityMapping{ + idIdent := ifplugin.GetIDMappingIdentifier(&nat.Nat44DNat_DNatConfig_IdentityMapping{ Protocol: nat.Protocol_TCP, IpAddress: "192.168.0.1", }) - Expect(plugin.IsDNatLabelIdMappingRegistered(idIdent)).To(BeTrue()) + Expect(plugin.IsDNatLabelIDMappingRegistered(idIdent)).To(BeTrue()) Expect(plugin.IsDNatLabelStMappingRegistered(stIdent)).To(BeTrue()) } + +// Test unexported method resolving NB static mapping equal to the VPP static mapping. Mapping +// is expected to be registered +func TestResolveStaticMapping(t *testing.T) { + _, plugin, conn, _ := natConfiguratorTestInitialization(t) + defer natConfiguratorTestTeardown(plugin, conn) + + var idMappings []*nat.Nat44DNat_DNatConfig_IdentityMapping + + nbData := getNat44StaticMappingData() + vppData := getNat44StaticMappingData().StMappings + + // Test where NB == VPP + ifplugin.ResolveMappings(plugin, nbData, &vppData, &idMappings) + Expect(plugin.IsDNatLabelStMappingRegistered(ifplugin.GetStMappingIdentifier(nbData.StMappings[0]))).To(BeTrue()) +} + +// Test unexported method resolving NB static mapping with different local IP address as the VPP static mapping. Mapping +// is not expected to be registered +func TestResolveStaticMappingNoMatch1(t *testing.T) { + _, plugin, conn, _ := natConfiguratorTestInitialization(t) + defer natConfiguratorTestTeardown(plugin, conn) + + var idMappings []*nat.Nat44DNat_DNatConfig_IdentityMapping + + nbData := getNat44StaticMappingData() + vppData := getNat44StaticMappingData().StMappings + vppData[0].LocalIps[0].LocalIp = "" // Change localIP + + // Tests where NB != VPP + ifplugin.ResolveMappings(plugin, nbData, &vppData, &idMappings) + Expect(plugin.IsDNatLabelStMappingRegistered(ifplugin.GetStMappingIdentifier(nbData.StMappings[0]))).To(BeFalse()) +} + +// Test unexported method resolving NB static mapping with different external IP address as the VPP static mapping. +// Mapping is not expected to be registered +func TestResolveStaticMappingNoMatch2(t *testing.T) { + _, plugin, conn, _ := natConfiguratorTestInitialization(t) + defer natConfiguratorTestTeardown(plugin, conn) + + var idMappings []*nat.Nat44DNat_DNatConfig_IdentityMapping + + nbData := getNat44StaticMappingData() + vppData := getNat44StaticMappingData().StMappings + vppData[0].ExternalIp = "" // Change external IP + + // Tests where NB != VPP + ifplugin.ResolveMappings(plugin, nbData, &vppData, &idMappings) + Expect(plugin.IsDNatLabelStMappingRegistered(ifplugin.GetStMappingIdentifier(nbData.StMappings[0]))).To(BeFalse()) +} + +// Test unexported method resolving NB static mapping with different VRF as the VPP static mapping. Mapping +// is not expected to be registered +func TestResolveStaticMappingNoMatch3(t *testing.T) { + _, plugin, conn, _ := natConfiguratorTestInitialization(t) + defer natConfiguratorTestTeardown(plugin, conn) + + var idMappings []*nat.Nat44DNat_DNatConfig_IdentityMapping + + nbData := getNat44StaticMappingData() + vppData := getNat44StaticMappingData().StMappings + vppData[0].LocalIps[0].VrfId = 1 // Change VRF + + // Tests where NB != VPP + ifplugin.ResolveMappings(plugin, nbData, &vppData, &idMappings) + Expect(plugin.IsDNatLabelStMappingRegistered(ifplugin.GetStMappingIdentifier(nbData.StMappings[0]))).To(BeFalse()) +} + +// Test unexported method resolving NB static mapping with different count of local IP addresses as the VPP static +// mapping. Mapping is not expected to be registered +func TestResolveStaticMappingNoMatch4(t *testing.T) { + _, plugin, conn, _ := natConfiguratorTestInitialization(t) + defer natConfiguratorTestTeardown(plugin, conn) + + var idMappings []*nat.Nat44DNat_DNatConfig_IdentityMapping + + nbData := getNat44StaticMappingData() + vppData := getNat44StaticMappingData().StMappings + vppData[0].LocalIps = append(vppData[0].LocalIps, getLocalIP("10.0.0.2", 30, 15, 0)) // Change number of Local IPs + + // Tests where NB != VPP + ifplugin.ResolveMappings(plugin, nbData, &vppData, &idMappings) + Expect(plugin.IsDNatLabelStMappingRegistered(ifplugin.GetStMappingIdentifier(nbData.StMappings[0]))).To(BeFalse()) +} + +// Test unexported method resolving NB load-balanced static mapping equal to the VPP load-balanced static mapping. +// Mapping is expected to be registered +func TestResolveStaticMappingLb(t *testing.T) { + _, plugin, conn, _ := natConfiguratorTestInitialization(t) + defer natConfiguratorTestTeardown(plugin, conn) + + var idMappings []*nat.Nat44DNat_DNatConfig_IdentityMapping + + nbData := getNat44StaticMappingLbData() + vppData := getNat44StaticMappingLbData().StMappings + + // Test where NB == VPP + ifplugin.ResolveMappings(plugin, nbData, &vppData, &idMappings) + Expect(plugin.IsDNatLabelStMappingRegistered(ifplugin.GetStMappingIdentifier(nbData.StMappings[0]))).To(BeTrue()) +} + +// Test unexported method resolving NB load-balanced static mapping with different local IP in one of the entries. +// Mapping is expected to not be registered +func TestResolveStaticMappingLbNoMatch1(t *testing.T) { + _, plugin, conn, _ := natConfiguratorTestInitialization(t) + defer natConfiguratorTestTeardown(plugin, conn) + + var idMappings []*nat.Nat44DNat_DNatConfig_IdentityMapping + + nbData := getNat44StaticMappingLbData() + vppData := getNat44StaticMappingLbData().StMappings + vppData[0].LocalIps[1].LocalIp = "" // Change localIP in second entry + + // Tests where NB != VPP + ifplugin.ResolveMappings(plugin, nbData, &vppData, &idMappings) + Expect(plugin.IsDNatLabelStMappingRegistered(ifplugin.GetStMappingIdentifier(nbData.StMappings[0]))).To(BeFalse()) +} + +// Test unexported method resolving NB load-balanced static mapping with different external IP. +// Mapping is expected to not be registered +func TestResolveStaticMappingLbNoMatch2(t *testing.T) { + _, plugin, conn, _ := natConfiguratorTestInitialization(t) + defer natConfiguratorTestTeardown(plugin, conn) + + var idMappings []*nat.Nat44DNat_DNatConfig_IdentityMapping + + nbData := getNat44StaticMappingLbData() + vppData := getNat44StaticMappingLbData().StMappings + vppData[0].ExternalIp = "" // Change external IP + + // Tests where NB != VPP + ifplugin.ResolveMappings(plugin, nbData, &vppData, &idMappings) + Expect(plugin.IsDNatLabelStMappingRegistered(ifplugin.GetStMappingIdentifier(nbData.StMappings[0]))).To(BeFalse()) +} + +// Test unexported method resolving NB load-balanced static mapping with different VRF. +// Mapping is expected to not be registered +func TestResolveStaticMappingLbNoMatch3(t *testing.T) { + _, plugin, conn, _ := natConfiguratorTestInitialization(t) + defer natConfiguratorTestTeardown(plugin, conn) + + var idMappings []*nat.Nat44DNat_DNatConfig_IdentityMapping + + nbData := getNat44StaticMappingLbData() + vppData := getNat44StaticMappingLbData().StMappings + vppData[0].LocalIps[1].VrfId = 1 // Change VRF + + // Tests where NB != VPP + ifplugin.ResolveMappings(plugin, nbData, &vppData, &idMappings) + Expect(plugin.IsDNatLabelStMappingRegistered(ifplugin.GetStMappingIdentifier(nbData.StMappings[0]))).To(BeFalse()) +} + +// Test unexported method resolving NB load-balanced static mapping with different count of local IP entries. +// Mapping is expected to not be registered +func TestResolveStaticMappingLbNoMatch4(t *testing.T) { + _, plugin, conn, _ := natConfiguratorTestInitialization(t) + defer natConfiguratorTestTeardown(plugin, conn) + + var idMappings []*nat.Nat44DNat_DNatConfig_IdentityMapping + + nbData := getNat44StaticMappingLbData() + vppData := getNat44StaticMappingLbData().StMappings + vppData[0].LocalIps = append(vppData[0].LocalIps, getLocalIP("10.0.0.3", 35, 20, 0)) // Change number of Local IPs + + // Tests where NB != VPP + ifplugin.ResolveMappings(plugin, nbData, &vppData, &idMappings) + Expect(plugin.IsDNatLabelStMappingRegistered(ifplugin.GetStMappingIdentifier(nbData.StMappings[0]))).To(BeFalse()) +} + +// Test unexported method resolving NB identity mapping equal to the VPP identity mapping. +// Mapping is expected to be registered. +func TestResolveIdentityMapping(t *testing.T) { + _, plugin, conn, _ := natConfiguratorTestInitialization(t) + defer natConfiguratorTestTeardown(plugin, conn) + + var stMappings []*nat.Nat44DNat_DNatConfig_StaticMapping + + nbData := getNat44IdentityMappingData() + vppData := getNat44IdentityMappingData().IdMappings + + // Test where NB == VPP + ifplugin.ResolveMappings(plugin, nbData, &stMappings, &vppData) + Expect(plugin.IsDNatLabelIDMappingRegistered(ifplugin.GetIDMappingIdentifier(nbData.IdMappings[0]))).To(BeTrue()) +} + +// Test unexported method resolving NB identity mapping with different IP address. +// Mapping is expected to not be registered. +func TestResolveIdentityMappingNoMatch1(t *testing.T) { + _, plugin, conn, _ := natConfiguratorTestInitialization(t) + defer natConfiguratorTestTeardown(plugin, conn) + + var stMappings []*nat.Nat44DNat_DNatConfig_StaticMapping + + nbData := getNat44IdentityMappingData() + vppData := getNat44IdentityMappingData().IdMappings + vppData[0].IpAddress = "" // Ip address change + + // Test where NB == VPP + ifplugin.ResolveMappings(plugin, nbData, &stMappings, &vppData) + Expect(plugin.IsDNatLabelIDMappingRegistered(ifplugin.GetIDMappingIdentifier(nbData.IdMappings[0]))).To(BeFalse()) +} + +// Test unexported method resolving NB identity mapping with different VRF. +// Mapping is expected to not be registered. +func TestResolveIdentityMappingNoMatch2(t *testing.T) { + _, plugin, conn, _ := natConfiguratorTestInitialization(t) + defer natConfiguratorTestTeardown(plugin, conn) + + var stMappings []*nat.Nat44DNat_DNatConfig_StaticMapping + + nbData := getNat44IdentityMappingData() + vppData := getNat44IdentityMappingData().IdMappings + vppData[0].VrfId = 1 // VRF change + + // Test where NB == VPP + ifplugin.ResolveMappings(plugin, nbData, &stMappings, &vppData) + Expect(plugin.IsDNatLabelIDMappingRegistered(ifplugin.GetIDMappingIdentifier(nbData.IdMappings[0]))).To(BeFalse()) +} + +func getNat44StaticMappingData() *nat.Nat44DNat_DNatConfig { + var stMappings []*nat.Nat44DNat_DNatConfig_StaticMapping + var localIPs []*nat.Nat44DNat_DNatConfig_StaticMapping_LocalIP + + nbData := &nat.Nat44DNat_DNatConfig{ + Label: "test-dnat", + StMappings: append(stMappings, getStaticMapping("10.0.0.1", 25, 6)), + } + nbData.StMappings[0].LocalIps = append(localIPs, getLocalIP("192.168.0.1", 9000, 35, 0)) + return nbData +} + +func getNat44StaticMappingLbData() *nat.Nat44DNat_DNatConfig { + var stMappings []*nat.Nat44DNat_DNatConfig_StaticMapping + var localIPs []*nat.Nat44DNat_DNatConfig_StaticMapping_LocalIP + + nbData := &nat.Nat44DNat_DNatConfig{ + Label: "test-dnat", + StMappings: append(stMappings, getStaticMapping("10.0.0.1", 25, 6)), + } + nbData.StMappings[0].LocalIps = append(localIPs, getLocalIP("192.168.0.1", 9000, 35, 0), + getLocalIP("192.168.0.2", 9001, 40, 0)) + return nbData +} + +func getNat44IdentityMappingData() *nat.Nat44DNat_DNatConfig { + var idMappings []*nat.Nat44DNat_DNatConfig_IdentityMapping + + nbData := &nat.Nat44DNat_DNatConfig{ + Label: "test-dnat", + IdMappings: append(idMappings, getIdentityMapping("10.0.0.1", 25, 0, 6)), + } + return nbData +} + +func getStaticMapping(ip string, port uint32, proto nat.Protocol) *nat.Nat44DNat_DNatConfig_StaticMapping { + return &nat.Nat44DNat_DNatConfig_StaticMapping{ + ExternalIp: ip, + ExternalPort: port, + Protocol: proto, + } +} + +func getIdentityMapping(ip string, port, vrf uint32, proto nat.Protocol) *nat.Nat44DNat_DNatConfig_IdentityMapping { + return &nat.Nat44DNat_DNatConfig_IdentityMapping{ + VrfId: vrf, + IpAddress: ip, + Port: port, + Protocol: proto, + } +} + +func getLocalIP(ip string, port, probability uint32, vrf uint32) *nat.Nat44DNat_DNatConfig_StaticMapping_LocalIP { + return &nat.Nat44DNat_DNatConfig_StaticMapping_LocalIP{ + VrfId: vrf, + LocalIp: ip, + LocalPort: port, + Probability: probability, + } +} diff --git a/plugins/vpp/ifplugin/export_test.go b/plugins/vpp/ifplugin/export_test.go new file mode 100644 index 0000000000..854cecbbef --- /dev/null +++ b/plugins/vpp/ifplugin/export_test.go @@ -0,0 +1,23 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ifplugin + +import "github.com/ligato/vpp-agent/plugins/vpp/model/nat" + +// Export for testing +func ResolveMappings(natCfg *NatConfigurator, nbDNatConfig *nat.Nat44DNat_DNatConfig, + vppMappings *[]*nat.Nat44DNat_DNatConfig_StaticMapping, vppIDMappings *[]*nat.Nat44DNat_DNatConfig_IdentityMapping) { + natCfg.resolveMappings(nbDNatConfig, vppMappings, vppIDMappings) +} diff --git a/plugins/vpp/ifplugin/ifaceidx/cache_iface.go b/plugins/vpp/ifplugin/ifaceidx/cache_iface.go index 27fa0e0c76..5cf0e867c4 100644 --- a/plugins/vpp/ifplugin/ifaceidx/cache_iface.go +++ b/plugins/vpp/ifplugin/ifaceidx/cache_iface.go @@ -31,7 +31,7 @@ func Cache(watcher datasync.KeyValProtoWatcher) SwIfIndex { swIdx := NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), resyncName, IndexMetadata)) helper := cacheutil.CacheHelper{ - Prefix: interfaces.InterfaceKeyPrefix(), + Prefix: interfaces.Prefix, IDX: swIdx.GetMapping(), DataPrototype: &interfaces.Interfaces_Interface{Name: "aaa"}, ParseName: interfaces.ParseNameFromKey} diff --git a/plugins/vpp/ifplugin/ifaceidx/dhcp_index.go b/plugins/vpp/ifplugin/ifaceidx/dhcp_index.go index d7adad5836..c588883526 100644 --- a/plugins/vpp/ifplugin/ifaceidx/dhcp_index.go +++ b/plugins/vpp/ifplugin/ifaceidx/dhcp_index.go @@ -15,7 +15,6 @@ package ifaceidx import ( - "github.com/ligato/cn-infra/core" log "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/idxvpp" "github.com/ligato/vpp-agent/idxvpp/nametoidx" @@ -44,7 +43,7 @@ type DhcpIndex interface { LookupName(idx uint32) (name string, metadata *DHCPSettings, exists bool) // WatchNameToIdx allows to subscribe for watching changes in DhcpIndex mapping. - WatchNameToIdx(subscriber core.PluginName, pluginChannel chan DhcpIdxDto) + WatchNameToIdx(subscriber string, pluginChannel chan DhcpIdxDto) } // DhcpIndexRW is mapping between software interface names, indices @@ -132,7 +131,7 @@ func (dhcp *dhcpIndex) LookupName(idx uint32) (name string, metadata *DHCPSettin } // WatchNameToIdx allows to subscribe for watching changes in dhcpIndex mapping. -func (dhcp *dhcpIndex) WatchNameToIdx(subscriber core.PluginName, pluginChannel chan DhcpIdxDto) { +func (dhcp *dhcpIndex) WatchNameToIdx(subscriber string, pluginChannel chan DhcpIdxDto) { ch := make(chan idxvpp.NameToIdxDto) dhcp.mapping.Watch(subscriber, nametoidx.ToChan(ch)) go func() { diff --git a/plugins/vpp/ifplugin/ifaceidx/sw_if_index.go b/plugins/vpp/ifplugin/ifaceidx/sw_if_index.go index f5b523c8c0..f1d87c93de 100644 --- a/plugins/vpp/ifplugin/ifaceidx/sw_if_index.go +++ b/plugins/vpp/ifplugin/ifaceidx/sw_if_index.go @@ -15,7 +15,6 @@ package ifaceidx import ( - "github.com/ligato/cn-infra/core" "github.com/ligato/vpp-agent/idxvpp" "github.com/ligato/vpp-agent/idxvpp/nametoidx" intf "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" @@ -37,7 +36,7 @@ type SwIfIndex interface { LookupNameByIP(ip string) []string // WatchNameToIdx allows to subscribe for watching changes in swIfIndex mapping. - WatchNameToIdx(subscriber core.PluginName, pluginChannel chan SwIfIdxDto) + WatchNameToIdx(subscriber string, pluginChannel chan SwIfIdxDto) } // SwIfIndexRW is mapping between software interface indices @@ -153,7 +152,7 @@ func (swi *swIfIndex) castMetadata(meta interface{}) *intf.Interfaces_Interface } // WatchNameToIdx allows to subscribe for watching changes in swIfIndex mapping. -func (swi *swIfIndex) WatchNameToIdx(subscriber core.PluginName, pluginChannel chan SwIfIdxDto) { +func (swi *swIfIndex) WatchNameToIdx(subscriber string, pluginChannel chan SwIfIdxDto) { ch := make(chan idxvpp.NameToIdxDto) swi.mapping.Watch(subscriber, nametoidx.ToChan(ch)) go func() { diff --git a/plugins/vpp/ifplugin/interface_config.go b/plugins/vpp/ifplugin/interface_config.go index d6d5d4669e..0858eb96c2 100644 --- a/plugins/vpp/ifplugin/interface_config.go +++ b/plugins/vpp/ifplugin/interface_config.go @@ -28,7 +28,6 @@ import ( govppapi "git.fd.io/govpp.git/api" "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/cn-infra/utils/addrs" "github.com/ligato/cn-infra/utils/safeclose" @@ -36,10 +35,8 @@ import ( "github.com/ligato/vpp-agent/plugins/govppmux" "github.com/ligato/vpp-agent/plugins/vpp/binapi/dhcp" "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/memif" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppdump" intf "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" ) @@ -68,6 +65,9 @@ type InterfaceConfigurator struct { vppCh govppapi.Channel + // VPP API handler + ifHandler vppcalls.IfVppAPI + // Notification channels NotifChan chan govppapi.Message // to publish SwInterfaceDetails to interface_state.go DhcpChan chan govppapi.Message // channel to receive DHCP notifications @@ -80,44 +80,43 @@ func (plugin *InterfaceConfigurator) Init(logger logging.PluginLogger, goVppMux plugin.log = logger.NewLogger("-if-conf") plugin.log.Debug("Initializing Interface configurator") + // Configurator-wide stopwatch instance + if enableStopwatch { + plugin.stopwatch = measure.NewStopwatch("Interface-configurator", plugin.log) + } + // State notification channel plugin.NotifChan = notifChan // Config file data plugin.defaultMtu = defaultMtu - // VPP channel & compatibility + // VPP channel if plugin.vppCh, err = goVppMux.NewAPIChannel(); err != nil { return err } - if err := vppcalls.CheckMsgCompatibilityForInterface(plugin.log, plugin.vppCh); err != nil { - return err - } + + // VPP API handler + plugin.ifHandler = vppcalls.NewIfVppHandler(plugin.vppCh, plugin.log, plugin.stopwatch) // Mappings plugin.swIfIndexes = ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(plugin.log, "sw_if_indexes", ifaceidx.IndexMetadata)) plugin.dhcpIndexes = ifaceidx.NewDHCPIndex(nametoidx.NewNameToIdx(plugin.log, "dhcp_indices", ifaceidx.IndexDHCPMetadata)) plugin.uIfaceCache = make(map[string]string) plugin.vxlanMulticastCache = make(map[string]*intf.Interfaces_Interface) - if plugin.memifScCache, err = vppdump.DumpMemifSocketDetails(plugin.log, plugin.vppCh, - measure.GetTimeLog(memif.MemifSocketFilenameDump{}, plugin.stopwatch)); err != nil { - return err - } + plugin.memifScCache = make(map[string]uint32) // Init AF-packet configurator plugin.linux = linux plugin.afPacketConfigurator = &AFPacketConfigurator{} - plugin.afPacketConfigurator.Init(plugin.log, plugin.vppCh, plugin.linux, plugin.swIfIndexes, plugin.stopwatch) + plugin.afPacketConfigurator.Init(plugin.log, plugin.ifHandler, plugin.linux, plugin.swIfIndexes) // DHCP channel plugin.DhcpChan = make(chan govppapi.Message, 1) - if _, err := plugin.vppCh.SubscribeNotification(plugin.DhcpChan, dhcp.NewDhcpComplEvent); err != nil { + if _, err := plugin.vppCh.SubscribeNotification(plugin.DhcpChan, dhcp.NewDHCPComplEvent); err != nil { return err } - if enableStopwatch { - plugin.stopwatch = measure.NewStopwatch("InterfaceConfigurator", plugin.log) - } go plugin.watchDHCPNotifications() return nil @@ -134,11 +133,7 @@ func (plugin *InterfaceConfigurator) clearMapping() error { plugin.dhcpIndexes.Clear() plugin.uIfaceCache = make(map[string]string) plugin.vxlanMulticastCache = make(map[string]*intf.Interfaces_Interface) - var err error - if plugin.memifScCache, err = vppdump.DumpMemifSocketDetails(plugin.log, plugin.vppCh, - measure.GetTimeLog(memif.MemifSocketFilenameDump{}, plugin.stopwatch)); err != nil { - return err - } + plugin.memifScCache = make(map[string]uint32) return nil } @@ -218,23 +213,23 @@ func (plugin *InterfaceConfigurator) ConfigureVPPInterface(iface *intf.Interface switch iface.Type { case intf.InterfaceType_TAP_INTERFACE: - ifIdx, err = vppcalls.AddTapInterface(iface.Name, iface.Tap, plugin.vppCh, plugin.stopwatch) + ifIdx, err = plugin.ifHandler.AddTapInterface(iface.Name, iface.Tap) case intf.InterfaceType_MEMORY_INTERFACE: var id uint32 // Memif socket id id, err = plugin.resolveMemifSocketFilename(iface.Memif) if err != nil { return err } - ifIdx, err = vppcalls.AddMemifInterface(iface.Name, iface.Memif, id, plugin.vppCh, plugin.stopwatch) + ifIdx, err = plugin.ifHandler.AddMemifInterface(iface.Name, iface.Memif, id) case intf.InterfaceType_VXLAN_TUNNEL: // VxLAN multicast interface. Interrupt the processing if there is an error or interface was cached multicastIfIdx, cached, err := plugin.getVxLanMulticast(iface) if err != nil || cached { return err } - ifIdx, err = vppcalls.AddVxlanTunnel(iface.Name, iface.Vxlan, iface.Vrf, multicastIfIdx, plugin.vppCh, plugin.stopwatch) + ifIdx, err = plugin.ifHandler.AddVxLanTunnel(iface.Name, iface.Vrf, multicastIfIdx, iface.Vxlan) case intf.InterfaceType_SOFTWARE_LOOPBACK: - ifIdx, err = vppcalls.AddLoopbackInterface(iface.Name, plugin.vppCh, plugin.stopwatch) + ifIdx, err = plugin.ifHandler.AddLoopbackInterface(iface.Name) case intf.InterfaceType_ETHERNET_CSMACD: var exists bool if ifIdx, _, exists = plugin.swIfIndexes.LookupIdx(iface.Name); !exists { @@ -258,16 +253,16 @@ func (plugin *InterfaceConfigurator) ConfigureVPPInterface(iface *intf.Interface var errs []error - // rx mode + // Rx-mode if err := plugin.configRxModeForInterface(iface, ifIdx); err != nil { errs = append(errs, err) } - // TODO: simplify implementation for rx placement when the binary api call will be available (remove dump) + // Rx-placement TODO: simplify implementation for rx placement when the binary api call will be available (remove dump) if iface.RxPlacementSettings != nil { // Required in order to get vpp internal name. Must be called from here, calling in vppcalls causes // import cycle - ifMap, err := vppdump.DumpInterfaces(logrus.DefaultLogger(), plugin.vppCh, plugin.stopwatch) + ifMap, err := plugin.ifHandler.DumpInterfaces() if err != nil { return err } @@ -275,46 +270,57 @@ func (plugin *InterfaceConfigurator) ConfigureVPPInterface(iface *intf.Interface if !ok || ifData == nil { return fmt.Errorf("set rx-placement failed, no data available for interface index %d", ifIdx) } - if err := vppcalls.SetRxPlacement(ifData.VPPInternalName, iface.RxPlacementSettings, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.SetRxPlacement(ifData.Meta.InternalName, iface.RxPlacementSettings); err != nil { errs = append(errs, err) } } - // configure optional mac address (for af packet it is configured in different way) + // MAC address (optional, for af-packet is configured in different way) if iface.PhysAddress != "" && iface.Type != intf.InterfaceType_AF_PACKET_INTERFACE { - if err := vppcalls.SetInterfaceMac(ifIdx, iface.PhysAddress, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.SetInterfaceMac(ifIdx, iface.PhysAddress); err != nil { errs = append(errs, err) } } - // configure optional vrf - if iface.Type != intf.InterfaceType_VXLAN_TUNNEL { - if err := vppcalls.SetInterfaceVRF(ifIdx, iface.Vrf, plugin.log, plugin.vppCh); err != nil { - errs = append(errs, err) - } - } - - // configure DHCP client + // DHCP client if iface.SetDhcpClient { - if err := vppcalls.SetInterfaceAsDHCPClient(ifIdx, iface.Name, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.SetInterfaceAsDHCPClient(ifIdx, iface.Name); err != nil { errs = append(errs, err) } else { plugin.log.Debugf("Interface %v set as DHCP client", iface.Name) } } - // configure IP addresses/un-numbered + // Get IP addresses IPAddrs, err := addrs.StrAddrsToStruct(iface.IpAddresses) if err != nil { return err } + + // VRF (optional, unavailable for VxLAN interfaces), has to be done before IP addresses are configured + if iface.Type != intf.InterfaceType_VXLAN_TUNNEL { + // Configured separately for IPv4/IPv6 + isIPv4, isIPv6 := plugin.getIPAddressVersions(IPAddrs) + if isIPv4 { + if err := plugin.ifHandler.SetInterfaceVrf(ifIdx, iface.Vrf); err != nil { + errs = append(errs, err) + } + } + if isIPv6 { + if err := plugin.ifHandler.SetInterfaceVrfIPv6(ifIdx, iface.Vrf); err != nil { + errs = append(errs, err) + } + } + } + + // Configure IP addresses or unnumbered config if err := plugin.configureIPAddresses(iface.Name, ifIdx, IPAddrs, iface.Unnumbered); err != nil { errs = append(errs, err) } // configure container IP address if iface.ContainerIpAddress != "" { - if err := vppcalls.AddContainerIP(ifIdx, iface.ContainerIpAddress, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.AddContainerIP(ifIdx, iface.ContainerIpAddress); err != nil { errs = append(errs, err) } else { plugin.log.WithFields(logging.Fields{"IPaddr": iface.ContainerIpAddress, "ifIdx": ifIdx}). @@ -330,7 +336,7 @@ func (plugin *InterfaceConfigurator) ConfigureVPPInterface(iface *intf.Interface } if mtuToConfigure != 0 { iface.Mtu = mtuToConfigure - if err := vppcalls.SetInterfaceMtu(ifIdx, mtuToConfigure, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.SetInterfaceMtu(ifIdx, mtuToConfigure); err != nil { errs = append(errs, err) } } @@ -347,7 +353,7 @@ func (plugin *InterfaceConfigurator) ConfigureVPPInterface(iface *intf.Interface // set interface up if enabled // NOTE: needs to be called after RegisterName, otherwise interface up/down notification won't map to a valid interface if iface.Enabled { - if err := vppcalls.InterfaceAdminUp(ifIdx, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.InterfaceAdminUp(ifIdx); err != nil { l.Warnf("setting interface up failed: %v", err) errs = append(errs, err) return fmt.Errorf("found %d errors: %v", len(errs), errs) @@ -406,7 +412,7 @@ func (plugin *InterfaceConfigurator) configRxModeForInterface(iface *intf.Interf Call specific vpp API method for setting rx-mode */ func (plugin *InterfaceConfigurator) configRxMode(iface *intf.Interfaces_Interface, ifIdx uint32, rxModeSettings *intf.Interfaces_Interface_RxModeSettings) error { - err := vppcalls.SetRxMode(ifIdx, rxModeSettings, plugin.vppCh, plugin.stopwatch) + err := plugin.ifHandler.SetRxMode(ifIdx, rxModeSettings) plugin.log.WithFields(logging.Fields{"ifName": iface.Name, "rxMode": rxModeSettings.RxMode}). Debug("RX-mode configuration for ", iface.Type, ".") return err @@ -426,11 +432,11 @@ func (plugin *InterfaceConfigurator) configureIPAddresses(ifName string, ifIdx u return nil } // Set interface as un-numbered - if err := vppcalls.SetUnnumberedIP(ifIdx, ifIdxIP, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.SetUnnumberedIP(ifIdx, ifIdxIP); err != nil { return err - } else { - plugin.log.WithFields(logging.Fields{"un-numberedIface": ifIdx, "ifIdxIP": ifIdxIP}).Debug("Interface set as un-numbered") } + plugin.log.WithFields(logging.Fields{"un-numberedIface": ifIdx, "ifIdxIP": ifIdxIP}).Debug("Interface set as un-numbered") + // just log if len(addresses) != 0 { plugin.log.Warnf("Interface %v set as un-numbered contains IP address(es)", ifName, addresses) @@ -440,7 +446,7 @@ func (plugin *InterfaceConfigurator) configureIPAddresses(ifName string, ifIdx u // configure optional ip address var wasErr error for _, address := range addresses { - if err := vppcalls.AddInterfaceIP(ifIdx, address, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.AddInterfaceIP(ifIdx, address); err != nil { plugin.log.Errorf("adding interface IP address failed: %v", err) wasErr = err } @@ -456,7 +462,7 @@ func (plugin *InterfaceConfigurator) configureIPAddresses(ifName string, ifIdx u func (plugin *InterfaceConfigurator) removeIPAddresses(ifIdx uint32, addresses []*net.IPNet, unnumbered *intf.Interfaces_Interface_Unnumbered) error { if unnumbered != nil && unnumbered.IsUnnumbered { // Set interface as un-numbered - if err := vppcalls.UnsetUnnumberedIP(ifIdx, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.UnsetUnnumberedIP(ifIdx); err != nil { return err } } @@ -464,7 +470,7 @@ func (plugin *InterfaceConfigurator) removeIPAddresses(ifIdx uint32, addresses [ // delete IP Addresses var wasErr error for _, addr := range addresses { - err := vppcalls.DelInterfaceIP(ifIdx, addr, plugin.vppCh, plugin.stopwatch) + err := plugin.ifHandler.DelInterfaceIP(ifIdx, addr) if err != nil { plugin.log.Errorf("deleting IP address failed: %v", err) wasErr = err @@ -490,7 +496,7 @@ func (plugin *InterfaceConfigurator) resolveDependentUnnumberedInterfaces(ifName delete(plugin.uIfaceCache, uIface) continue } - if err := vppcalls.SetUnnumberedIP(uIdx, ifIdxIP, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.SetUnnumberedIP(uIdx, ifIdxIP); err != nil { plugin.log.Errorf("setting unnumbered IP failed: %v", err) wasErr = err } else { @@ -593,7 +599,7 @@ func (plugin *InterfaceConfigurator) modifyVPPInterface(newConfig *intf.Interfac if newConfig.RxPlacementSettings != nil { // Required in order to get vpp internal name. Must be called from here, calling in vppcalls causes // import cycle - ifMap, err := vppdump.DumpInterfaces(logrus.DefaultLogger(), plugin.vppCh, plugin.stopwatch) + ifMap, err := plugin.ifHandler.DumpInterfaces() if err != nil { return err } @@ -601,7 +607,7 @@ func (plugin *InterfaceConfigurator) modifyVPPInterface(newConfig *intf.Interfac if !ok || ifData == nil { return fmt.Errorf("set rx-placement for new config failed, no data available for interface index %d", ifIdx) } - if err := vppcalls.SetRxPlacement(ifData.VPPInternalName, newConfig.RxPlacementSettings, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.SetRxPlacement(ifData.Meta.InternalName, newConfig.RxPlacementSettings); err != nil { wasError = err } } @@ -609,9 +615,9 @@ func (plugin *InterfaceConfigurator) modifyVPPInterface(newConfig *intf.Interfac // admin status if newConfig.Enabled != oldConfig.Enabled { if newConfig.Enabled { - err = vppcalls.InterfaceAdminUp(ifIdx, plugin.vppCh, nil) + err = plugin.ifHandler.InterfaceAdminUp(ifIdx) } else { - err = vppcalls.InterfaceAdminDown(ifIdx, plugin.vppCh, nil) + err = plugin.ifHandler.InterfaceAdminDown(ifIdx) } if nil != err { wasError = err @@ -620,7 +626,7 @@ func (plugin *InterfaceConfigurator) modifyVPPInterface(newConfig *intf.Interfac // configure new mac address if set (and only if it was changed) if newConfig.PhysAddress != "" && newConfig.PhysAddress != oldConfig.PhysAddress { - if err := vppcalls.SetInterfaceMac(ifIdx, newConfig.PhysAddress, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.SetInterfaceMac(ifIdx, newConfig.PhysAddress); err != nil { plugin.log.Errorf("setting interface MAC address failed: %v", err) wasError = err } @@ -629,14 +635,14 @@ func (plugin *InterfaceConfigurator) modifyVPPInterface(newConfig *intf.Interfac // reconfigure DHCP if oldConfig.SetDhcpClient != newConfig.SetDhcpClient { if newConfig.SetDhcpClient { - if err := vppcalls.SetInterfaceAsDHCPClient(ifIdx, newConfig.Name, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.SetInterfaceAsDHCPClient(ifIdx, newConfig.Name); err != nil { plugin.log.Error(err) wasError = err } else { plugin.log.Debugf("Interface %v set as DHCP client", newConfig.Name) } } else { - if err := vppcalls.UnsetInterfaceAsDHCPClient(ifIdx, newConfig.Name, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.UnsetInterfaceAsDHCPClient(ifIdx, newConfig.Name); err != nil { plugin.log.Error(err) wasError = err } else { @@ -658,9 +664,8 @@ func (plugin *InterfaceConfigurator) modifyVPPInterface(newConfig *intf.Interfac return err } - // configure VRF if it was changed - if oldConfig.Vrf != newConfig.Vrf && - ifaceType != intf.InterfaceType_VXLAN_TUNNEL { + // Reconfigure VRF + if ifaceType != intf.InterfaceType_VXLAN_TUNNEL { plugin.log.Debugf("VRF changed: %v -> %v", oldConfig.Vrf, newConfig.Vrf) // interface must not have IP when setting VRF @@ -669,26 +674,23 @@ func (plugin *InterfaceConfigurator) modifyVPPInterface(newConfig *intf.Interfac wasError = err } - if err := vppcalls.SetInterfaceVRF(ifIdx, newConfig.Vrf, plugin.log, plugin.vppCh); err != nil { - plugin.log.Error(err) - wasError = err - } - - if err = plugin.configureIPAddresses(newConfig.Name, ifIdx, newAddrs, newConfig.Unnumbered); err != nil { - plugin.log.Error(err) - wasError = err + // Get VRF IP version using new list of addresses. During modify, interface VRF IP version + // should be updated as well. + isIPv4, isIPv6 := plugin.getIPAddressVersions(newAddrs) + if isIPv4 { + if err := plugin.ifHandler.SetInterfaceVrf(ifIdx, newConfig.Vrf); err != nil { + plugin.log.Error(err) + wasError = err + } } - - } else { - // if VRF is not changed, try to add/del only differences - del, add := addrs.DiffAddr(newAddrs, oldAddrs) - - if err := plugin.removeIPAddresses(ifIdx, del, oldConfig.Unnumbered); err != nil { - plugin.log.Error(err) - wasError = err + if isIPv6 { + if err := plugin.ifHandler.SetInterfaceVrfIPv6(ifIdx, newConfig.Vrf); err != nil { + plugin.log.Error(err) + wasError = err + } } - if err := plugin.configureIPAddresses(newConfig.Name, ifIdx, add, newConfig.Unnumbered); err != nil { + if err = plugin.configureIPAddresses(newConfig.Name, ifIdx, newAddrs, newConfig.Unnumbered); err != nil { plugin.log.Error(err) wasError = err } @@ -698,7 +700,7 @@ func (plugin *InterfaceConfigurator) modifyVPPInterface(newConfig *intf.Interfac if newConfig.ContainerIpAddress != oldConfig.ContainerIpAddress { plugin.log.WithFields(logging.Fields{"ifIdx": ifIdx, "ip_new": newConfig.ContainerIpAddress, "ip_old": oldConfig.ContainerIpAddress}). Debug("Container IP address modification.") - if err := vppcalls.AddContainerIP(ifIdx, newConfig.ContainerIpAddress, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.AddContainerIP(ifIdx, newConfig.ContainerIpAddress); err != nil { plugin.log.WithFields(logging.Fields{"newIP": newConfig.ContainerIpAddress, "oldIP": oldConfig.ContainerIpAddress, "ifIdx": ifIdx}). Errorf("adding container IP failed: %v", err) wasError = err @@ -707,11 +709,11 @@ func (plugin *InterfaceConfigurator) modifyVPPInterface(newConfig *intf.Interfac // Set MTU if changed in interface config if newConfig.Mtu != 0 && newConfig.Mtu != oldConfig.Mtu { - if err := vppcalls.SetInterfaceMtu(ifIdx, newConfig.Mtu, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.SetInterfaceMtu(ifIdx, newConfig.Mtu); err != nil { wasError = err } } else if newConfig.Mtu == 0 && plugin.defaultMtu != 0 { - if err := vppcalls.SetInterfaceMtu(ifIdx, plugin.defaultMtu, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.SetInterfaceMtu(ifIdx, plugin.defaultMtu); err != nil { wasError = err } } @@ -759,7 +761,7 @@ func (plugin *InterfaceConfigurator) modifyRxModeForInterfaces(oldIntf *intf.Int Direct call of vpp api to change rx-mode of specified interface */ func (plugin *InterfaceConfigurator) modifyRxMode(ifName string, ifIdx uint32, rxMode *intf.Interfaces_Interface_RxModeSettings) error { - err := vppcalls.SetRxMode(ifIdx, rxMode, plugin.vppCh, plugin.stopwatch) + err := plugin.ifHandler.SetRxMode(ifIdx, rxMode) plugin.log.Debugf("RX-mode for %s set to %v", ifName, rxMode.RxMode) return err } @@ -840,7 +842,7 @@ func (plugin *InterfaceConfigurator) deleteVPPInterface(oldConfig *intf.Interfac if oldConfig.Type != intf.InterfaceType_AF_PACKET_INTERFACE { plugin.log.Infof("Setting interface %v down", oldConfig.Name) // Let's try to do following even if previously error occurred - if err := vppcalls.InterfaceAdminDown(ifIdx, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.InterfaceAdminDown(ifIdx); err != nil { plugin.log.Errorf("Setting interface down failed: %v", err) wasError = err } @@ -848,7 +850,7 @@ func (plugin *InterfaceConfigurator) deleteVPPInterface(oldConfig *intf.Interfac // Remove DHCP if it was set if oldConfig.SetDhcpClient { - if err := vppcalls.UnsetInterfaceAsDHCPClient(ifIdx, oldConfig.Name, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.UnsetInterfaceAsDHCPClient(ifIdx, oldConfig.Name); err != nil { plugin.log.Error(err) wasError = err } @@ -859,7 +861,7 @@ func (plugin *InterfaceConfigurator) deleteVPPInterface(oldConfig *intf.Interfac // let's try to do following even if previously error occurred if oldConfig.ContainerIpAddress != "" { - if err := vppcalls.DelContainerIP(ifIdx, oldConfig.ContainerIpAddress, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.DelContainerIP(ifIdx, oldConfig.ContainerIpAddress); err != nil { plugin.log.Error(err) wasError = err } else { @@ -881,7 +883,7 @@ func (plugin *InterfaceConfigurator) deleteVPPInterface(oldConfig *intf.Interfac return err } for _, oldAddr := range oldAddrs { - if err := vppcalls.DelInterfaceIP(ifIdx, oldAddr, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.DelInterfaceIP(ifIdx, oldAddr); err != nil { plugin.log.Errorf("deleting interface IP address failed: %v", err) wasError = err } @@ -892,13 +894,13 @@ func (plugin *InterfaceConfigurator) deleteVPPInterface(oldConfig *intf.Interfac // let's try to do following even if previously error occurred switch oldConfig.Type { case intf.InterfaceType_TAP_INTERFACE: - err = vppcalls.DeleteTapInterface(oldConfig.Name, ifIdx, oldConfig.Tap.Version, plugin.vppCh, plugin.stopwatch) + err = plugin.ifHandler.DeleteTapInterface(oldConfig.Name, ifIdx, oldConfig.Tap.Version) case intf.InterfaceType_MEMORY_INTERFACE: - err = vppcalls.DeleteMemifInterface(oldConfig.Name, ifIdx, plugin.vppCh, plugin.stopwatch) + err = plugin.ifHandler.DeleteMemifInterface(oldConfig.Name, ifIdx) case intf.InterfaceType_VXLAN_TUNNEL: - err = vppcalls.DeleteVxlanTunnel(oldConfig.Name, ifIdx, oldConfig.GetVxlan(), plugin.vppCh, plugin.stopwatch) + err = plugin.ifHandler.DeleteVxLanTunnel(oldConfig.Name, ifIdx, oldConfig.Vrf, oldConfig.GetVxlan()) case intf.InterfaceType_SOFTWARE_LOOPBACK: - err = vppcalls.DeleteLoopbackInterface(oldConfig.Name, ifIdx, plugin.vppCh, plugin.stopwatch) + err = plugin.ifHandler.DeleteLoopbackInterface(oldConfig.Name, ifIdx) case intf.InterfaceType_ETHERNET_CSMACD: plugin.log.Debugf("Interface removal skipped: cannot remove (blacklist) physical interface") // Not an error return nil @@ -935,6 +937,19 @@ func (plugin *InterfaceConfigurator) ResolveDeletedLinuxInterface(interfaceName, plugin.afPacketConfigurator.ResolveDeletedLinuxInterface(interfaceName, hostIfName, ifIdx) } +// Returns two flags, whether provided list of addresses contains IPv4 and/or IPv6 type addresses +func (plugin *InterfaceConfigurator) getIPAddressVersions(ipAddrs []*net.IPNet) (isIPv4, isIPv6 bool) { + for _, ip := range ipAddrs { + if ip.IP.To4() != nil { + isIPv4 = true + } else { + isIPv6 = true + } + } + + return +} + // returns memif socket filename ID. Registers it if does not exists yet func (plugin *InterfaceConfigurator) resolveMemifSocketFilename(memifIf *intf.Interfaces_Interface_Memif) (uint32, error) { if memifIf.SocketFilename == "" { @@ -944,7 +959,7 @@ func (plugin *InterfaceConfigurator) resolveMemifSocketFilename(memifIf *intf.In if !ok { // Register new socket. ID is generated (default filename ID is 0, first is ID 1, second ID 2, etc) registeredID = uint32(len(plugin.memifScCache)) - err := vppcalls.RegisterMemifSocketFilename([]byte(memifIf.SocketFilename), registeredID, plugin.vppCh, plugin.stopwatch) + err := plugin.ifHandler.RegisterMemifSocketFilename([]byte(memifIf.SocketFilename), registeredID) if err != nil { return 0, fmt.Errorf("error registering socket file name %s (ID %d): %v", memifIf.SocketFilename, registeredID, err) } @@ -1053,14 +1068,14 @@ func (plugin *InterfaceConfigurator) watchDHCPNotifications() { select { case notification := <-plugin.DhcpChan: switch dhcpNotif := notification.(type) { - case *dhcp.DhcpComplEvent: + case *dhcp.DHCPComplEvent: var ipAddr, rIPAddr net.IP = dhcpNotif.Lease.HostAddress, dhcpNotif.Lease.RouterAddress var hwAddr net.HardwareAddr = dhcpNotif.Lease.HostMac var ipStr, rIPStr string name := string(bytes.SplitN(dhcpNotif.Lease.Hostname, []byte{0x00}, 2)[0]) - if dhcpNotif.Lease.IsIpv6 == 1 { + if dhcpNotif.Lease.IsIPv6 == 1 { ipStr = ipAddr.To16().String() rIPStr = rIPAddr.To16().String() } else { @@ -1084,7 +1099,7 @@ func (plugin *InterfaceConfigurator) watchDHCPNotifications() { return true } return false - }(dhcpNotif.Lease.IsIpv6), + }(dhcpNotif.Lease.IsIPv6), IPAddress: ipStr, Mask: uint32(dhcpNotif.Lease.MaskWidth), PhysAddress: hwAddr.String(), diff --git a/plugins/vpp/ifplugin/interface_config_test.go b/plugins/vpp/ifplugin/interface_config_test.go index b7d44f8bfe..d0d5e05da8 100644 --- a/plugins/vpp/ifplugin/interface_config_test.go +++ b/plugins/vpp/ifplugin/interface_config_test.go @@ -23,7 +23,6 @@ import ( govppapi "git.fd.io/govpp.git/api" govpp "git.fd.io/govpp.git/core" "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/plugins/vpp/binapi/af_packet" dhcp_api "github.com/ligato/vpp-agent/plugins/vpp/binapi/dhcp" "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" @@ -39,36 +38,6 @@ import ( . "github.com/onsi/gomega" ) -/* Interface configurator init and close */ - -// Test init function -func TestInterfaceConfiguratorInit(t *testing.T) { - var err error - // Setup - RegisterTestingT(t) - ctx := &vppcallmock.TestCtx{ - MockVpp: &mock.VppAdapter{}, - } - connection, _ := govpp.Connect(ctx.MockVpp) - defer connection.Disconnect() - plugin := &ifplugin.InterfaceConfigurator{} - ifVppNotifChan := make(chan govppapi.Message, 100) - // Reply set - ctx.MockVpp.MockReply(&memif.MemifSocketFilenameDetails{ - SocketID: 1, - SocketFilename: []byte("test-socket-filename"), - }) - ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - // Test init - err = plugin.Init(logging.ForPlugin("test-log", logrus.NewLogRegistry()), connection, - nil, ifVppNotifChan, 0, false) - Expect(err).To(BeNil()) - Expect(plugin.IsSocketFilenameCached("test-socket-filename")).To(BeTrue()) - // Test close - err = plugin.Close() - Expect(err).To(BeNil()) -} - // Test dhcp func TestInterfaceConfiguratorDHCPNotifications(t *testing.T) { var err error @@ -79,8 +48,8 @@ func TestInterfaceConfiguratorDHCPNotifications(t *testing.T) { plugin.GetSwIfIndexes().RegisterName("if1", 1, nil) plugin.GetSwIfIndexes().RegisterName("if2", 2, nil) // Test DHCP notifications - dhcpIpv4 := &dhcp_api.DhcpComplEvent{ - Lease: dhcp_api.DhcpLease{ + dhcpIpv4 := &dhcp_api.DHCPComplEvent{ + Lease: dhcp_api.DHCPLease{ HostAddress: net.ParseIP("10.0.0.1"), RouterAddress: net.ParseIP("10.0.0.2"), HostMac: func(mac string) []byte { @@ -88,11 +57,11 @@ func TestInterfaceConfiguratorDHCPNotifications(t *testing.T) { return parsed }("7C:4E:E7:8A:63:68"), Hostname: []byte("if1"), - IsIpv6: 0, + IsIPv6: 0, }, } - dhcpIpv6 := &dhcp_api.DhcpComplEvent{ - Lease: dhcp_api.DhcpLease{ + dhcpIpv6 := &dhcp_api.DHCPComplEvent{ + Lease: dhcp_api.DHCPLease{ HostAddress: net.ParseIP("fd21:7408:186f::/48"), RouterAddress: net.ParseIP("2001:db8:a0b:12f0::1/48"), HostMac: func(mac string) []byte { @@ -101,7 +70,7 @@ func TestInterfaceConfiguratorDHCPNotifications(t *testing.T) { return parsed }("7C:4E:E7:8A:63:68"), Hostname: []byte("if2"), - IsIpv6: 1, + IsIPv6: 1, }, } plugin.DhcpChan <- dhcpIpv4 @@ -210,8 +179,7 @@ func TestInterfacesConfigureTapV2(t *testing.T) { ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetRxModeReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetMacAddressReply{}) - ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetTableReply{}) - ctx.MockVpp.MockReply(&dhcp_api.DhcpClientConfigReply{}) + ctx.MockVpp.MockReply(&dhcp_api.DHCPClientConfigReply{}) ctx.MockVpp.MockReply(&ip.IPContainerProxyAddDelReply{}) ctx.MockVpp.MockReply(&interfaces.HwInterfaceSetMtuReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetFlagsReply{}) @@ -244,7 +212,6 @@ func TestInterfacesConfigureMemif(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetMacAddressReply{}) - ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetTableReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetUnnumberedReply{}) ctx.MockVpp.MockReply(&ip.IPContainerProxyAddDelReply{}) ctx.MockVpp.MockReply(&interfaces.HwInterfaceSetMtuReply{}) @@ -281,7 +248,6 @@ func TestInterfacesConfigureMemifAsSlave(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetMacAddressReply{}) - ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetTableReply{}) ctx.MockVpp.MockReply(&ip.IPContainerProxyAddDelReply{}) ctx.MockVpp.MockReply(&interfaces.HwInterfaceSetMtuReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetFlagsReply{}) @@ -292,7 +258,6 @@ func TestInterfacesConfigureMemifAsSlave(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetMacAddressReply{}) - ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetTableReply{}) ctx.MockVpp.MockReply(&ip.IPContainerProxyAddDelReply{}) ctx.MockVpp.MockReply(&interfaces.HwInterfaceSetMtuReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetFlagsReply{}) @@ -520,7 +485,6 @@ func TestInterfacesConfigureVxLANWithMulticastIPError(t *testing.T) { SwIfIndex: 1, }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetTableReply{}) ctx.MockVpp.MockReply(&ip.IPContainerProxyAddDelReply{}) ctx.MockVpp.MockReply(&interfaces.HwInterfaceSetMtuReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetFlagsReply{}) @@ -736,6 +700,7 @@ func TestInterfacesModifyTapV1WithoutTapData(t *testing.T) { ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetRxModeReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetMacAddressReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceAddDelAddressReply{}) + ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetTableReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceAddDelAddressReply{}) ctx.MockVpp.MockReply(&interfaces.HwInterfaceSetMtuReply{}) ctx.MockVpp.MockReply() // Do not propagate interface details @@ -813,7 +778,7 @@ func TestInterfacesModifyMemifWithoutMemifData(t *testing.T) { defer ifTestTeardown(connection, plugin) // Reply set ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetFlagsReply{}) - ctx.MockVpp.MockReply(&dhcp_api.DhcpClientConfigReply{}) + ctx.MockVpp.MockReply(&dhcp_api.DHCPClientConfigReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceAddDelAddressReply{}) ctx.MockVpp.MockReply(&ip.IPContainerProxyAddDelReply{}) ctx.MockVpp.MockReply() // Do not propagate interface details @@ -906,12 +871,12 @@ func TestInterfacesModifyVxLanSimple(t *testing.T) { SwIfIndex: 1, }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - ctx.MockVpp.MockReply(&dhcp_api.DhcpClientConfigReply{}) + ctx.MockVpp.MockReply(&dhcp_api.DHCPClientConfigReply{}) ctx.MockVpp.MockReply(&ip.IPContainerProxyAddDelReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetFlagsReply{}) ctx.MockVpp.MockReply() // Do not propagate interface details ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - ctx.MockVpp.MockReply(&dhcp_api.DhcpClientConfigReply{}) // Modify - delete old data + ctx.MockVpp.MockReply(&dhcp_api.DHCPClientConfigReply{}) // Modify - delete old data ctx.MockVpp.MockReply(&interfaces.HwInterfaceSetMtuReply{}) ctx.MockVpp.MockReply() // Do not propagate interface details ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) @@ -1033,6 +998,9 @@ func TestInterfacesModifyLoopback(t *testing.T) { ctx.MockVpp.MockReply() // Do not propagate interface details ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceAddDelAddressReply{}) // Modify + ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetTableReply{}) + ctx.MockVpp.MockReply(&interfaces.SwInterfaceAddDelAddressReply{}) + ctx.MockVpp.MockReply(&interfaces.SwInterfaceAddDelAddressReply{}) ctx.MockVpp.MockReply(&interfaces.HwInterfaceSetMtuReply{}) ctx.MockVpp.MockReply() ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) @@ -1076,6 +1044,7 @@ func TestInterfacesModifyEthernet(t *testing.T) { ctx.MockVpp.MockReply() // Do not propagate interface details ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceAddDelAddressReply{}) // Modify + ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetTableReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceAddDelAddressReply{}) // Data oldData := getTestInterface("if1", if_api.InterfaceType_ETHERNET_CSMACD, []string{"10.0.0.1/24"}, false, "46:06:18:DB:05:3A", 1500) @@ -1118,6 +1087,7 @@ func TestInterfacesModifyAfPacket(t *testing.T) { ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetRxModeReply{}) // Modify ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetFlagsReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceAddDelAddressReply{}) + ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetTableReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceAddDelAddressReply{}) ctx.MockVpp.MockReply(&interfaces.HwInterfaceSetMtuReply{}) // Data @@ -1221,7 +1191,7 @@ func TestInterfacesDeleteTapInterface(t *testing.T) { defer ifTestTeardown(connection, plugin) // Reply set ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetFlagsReply{}) - ctx.MockVpp.MockReply(&dhcp_api.DhcpClientConfigReply{}) + ctx.MockVpp.MockReply(&dhcp_api.DHCPClientConfigReply{}) ctx.MockVpp.MockReply(&ip.IPContainerProxyAddDelReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceAddDelAddressReply{}) ctx.MockVpp.MockReply(&tap.TapDeleteReply{}) @@ -1390,8 +1360,8 @@ func TestModifyRxMode(t *testing.T) { // Reply set ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetRxModeReply{}) - ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetFlagsReply{}) - ctx.MockVpp.MockReply(&dhcp_api.DhcpClientConfigReply{}) + ctx.MockVpp.MockReply(&interfaces.SwInterfaceAddDelAddressReply{}) + ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetTableReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceAddDelAddressReply{}) ctx.MockVpp.MockReply(&ip.IPContainerProxyAddDelReply{}) ctx.MockVpp.MockReply() // Do not propagate interface details @@ -1421,19 +1391,21 @@ func TestModifyRxMode(t *testing.T) { func ifTestSetup(t *testing.T) (*vppcallmock.TestCtx, *govpp.Connection, *ifplugin.InterfaceConfigurator) { RegisterTestingT(t) + ctx := &vppcallmock.TestCtx{ MockVpp: &mock.VppAdapter{}, } connection, err := govpp.Connect(ctx.MockVpp) Expect(err).ShouldNot(HaveOccurred()) - ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) + // Logger - log := logging.ForPlugin("test-log", logrus.NewLogRegistry()) + log := logging.ForPlugin("test-log") log.SetLevel(logging.DebugLevel) + // Configurator plugin := &ifplugin.InterfaceConfigurator{} notifChan := make(chan govppapi.Message, 5) - err = plugin.Init(log, connection, 1, notifChan, 1500, false) + err = plugin.Init(log, connection, 1, notifChan, 1500, true) Expect(err).To(BeNil()) return ctx, connection, plugin @@ -1443,6 +1415,7 @@ func ifTestTeardown(connection *govpp.Connection, plugin *ifplugin.InterfaceConf connection.Disconnect() err := plugin.Close() Expect(err).To(BeNil()) + logging.DefaultRegistry.ClearRegistry() } /* Interface Test Data */ diff --git a/plugins/vpp/ifplugin/interface_state.go b/plugins/vpp/ifplugin/interface_state.go index 0ddebd8576..6333ab87bc 100644 --- a/plugins/vpp/ifplugin/interface_state.go +++ b/plugins/vpp/ifplugin/interface_state.go @@ -15,6 +15,7 @@ package ifplugin import ( + "bytes" "context" "fmt" "net" @@ -22,10 +23,7 @@ import ( "sync" "time" - "bytes" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/core" "github.com/ligato/cn-infra/logging" "github.com/ligato/cn-infra/utils/safeclose" "github.com/ligato/vpp-agent/plugins/govppmux" @@ -86,7 +84,7 @@ type InterfaceStateUpdater struct { } // Init members (channels, maps...) and start go routines -func (plugin *InterfaceStateUpdater) Init(logger logging.PluginLogger, goVppMux govppmux.API, ctx context.Context, +func (plugin *InterfaceStateUpdater) Init(ctx context.Context, logger logging.PluginLogger, goVppMux govppmux.API, swIfIndexes ifaceidx.SwIfIndex, notifChan chan govppapi.Message, publishIfState func(notification *intf.InterfaceNotification)) (err error) { // Logger @@ -106,7 +104,7 @@ func (plugin *InterfaceStateUpdater) Init(logger logging.PluginLogger, goVppMux } plugin.swIdxChan = make(chan ifaceidx.SwIfIdxDto, 100) - swIfIndexes.WatchNameToIdx(core.PluginName("ifplugin_ifstate"), plugin.swIdxChan) + swIfIndexes.WatchNameToIdx("ifplugin_ifstate", plugin.swIdxChan) plugin.notifChan = notifChan // Create child context @@ -151,7 +149,7 @@ func (plugin *InterfaceStateUpdater) subscribeVPPNotifications() error { wantInterfaceEventsReply := &interfaces.WantInterfaceEventsReply{} // enable interface state notifications from VPP err = plugin.vppCh.SendRequest(&interfaces.WantInterfaceEvents{ - Pid: uint32(os.Getpid()), + PID: uint32(os.Getpid()), EnableDisable: 1, }).ReceiveReply(wantInterfaceEventsReply) plugin.log.Debug("wantInterfaceEventsReply: ", wantInterfaceEventsReply, " ", err) @@ -165,7 +163,7 @@ func (plugin *InterfaceStateUpdater) subscribeVPPNotifications() error { wantStatsReply := &stats.WantStatsReply{} // enable interface counters notifications from VPP err = plugin.vppCh.SendRequest(&stats.WantStats{ - Pid: uint32(os.Getpid()), + PID: uint32(os.Getpid()), EnableDisable: 1, }).ReceiveReply(wantStatsReply) plugin.log.Debug("wantStatsReply: ", wantStatsReply, " ", err) @@ -194,7 +192,7 @@ func (plugin *InterfaceStateUpdater) Close() error { plugin.vppCh.UnsubscribeNotification(plugin.vppCombinedCountersSubs) } - return safeclose.Close(plugin.vppCh, plugin.swIdxChan) + return safeclose.Close(plugin.vppCh) } // watchVPPNotifications watches for delivery of notifications from VPP. diff --git a/plugins/vpp/ifplugin/interface_state_test.go b/plugins/vpp/ifplugin/interface_state_test.go index 9b1cefec7b..81bfa14ff8 100644 --- a/plugins/vpp/ifplugin/interface_state_test.go +++ b/plugins/vpp/ifplugin/interface_state_test.go @@ -35,7 +35,8 @@ import ( ) func testPluginDataInitialization(t *testing.T) (*govpp.Connection, ifaceidx.SwIfIndexRW, *ifplugin.InterfaceStateUpdater, - chan govppapi.Message, chan *intf.InterfaceNotification, error) { + chan govppapi.Message, chan *intf.InterfaceNotification, +) { RegisterTestingT(t) // Initialize notification channel @@ -45,8 +46,6 @@ func testPluginDataInitialization(t *testing.T) (*govpp.Connection, ifaceidx.SwI nameToIdx := nametoidx.NewNameToIdx(logrus.DefaultLogger(), "interface_state_test", ifaceidx.IndexMetadata) index := ifaceidx.NewSwIfIndex(nameToIdx) names := nameToIdx.ListNames() - - // Check if names were empty Expect(names).To(BeEmpty()) // Create publish state function @@ -62,38 +61,31 @@ func testPluginDataInitialization(t *testing.T) (*govpp.Connection, ifaceidx.SwI // Create connection mockCtx := &vppcallmock.TestCtx{MockVpp: &mock.VppAdapter{}} connection, err := govpp.Connect(mockCtx.MockVpp) - - if err != nil { - return nil, nil, nil, nil, nil, err - } + Expect(err).To(BeNil()) // Create plugin logger - pluginLogger := logging.ForPlugin("testname", logrus.NewLogRegistry()) + pluginLogger := logging.ForPlugin("testname") // Test initialization ifPlugin := &ifplugin.InterfaceStateUpdater{} - err = ifPlugin.Init(pluginLogger, connection, ctx, index, notifChan, publishIfState) - - if err != nil { - return nil, nil, nil, nil, nil, err - } - - // Test after init + err = ifPlugin.Init(ctx, pluginLogger, connection, index, notifChan, publishIfState) + Expect(err).To(BeNil()) err = ifPlugin.AfterInit() + Expect(err).To(BeNil()) - if err != nil { - return nil, nil, nil, nil, nil, err - } + return connection, index, ifPlugin, notifChan, publishChan +} - return connection, index, ifPlugin, notifChan, publishChan, nil +func testPluginDataTeardown(plugin *ifplugin.InterfaceStateUpdater, connection *govpp.Connection) { + connection.Disconnect() + Expect(plugin.Close()).To(BeNil()) + logging.DefaultRegistry.ClearRegistry() } // Test UPDOWN notification func TestInterfaceStateUpdaterUpDownNotif(t *testing.T) { - conn, index, ifPlugin, notifChan, publishChan, err := testPluginDataInitialization(t) - Expect(err).To(BeNil()) - defer ifPlugin.Close() - defer conn.Disconnect() + conn, index, ifPlugin, notifChan, publishChan := testPluginDataInitialization(t) + defer testPluginDataTeardown(ifPlugin, conn) // Register name index.RegisterName("test", 0, &intf.Interfaces_Interface{ @@ -105,7 +97,7 @@ func TestInterfaceStateUpdaterUpDownNotif(t *testing.T) { // Test notifications notifChan <- &interfaces.SwInterfaceEvent{ - Pid: 0, + PID: 0, SwIfIndex: 0, AdminUpDown: 1, LinkUpDown: 1, @@ -121,10 +113,8 @@ func TestInterfaceStateUpdaterUpDownNotif(t *testing.T) { // Test simple counter notification func TestInterfaceStateUpdaterVnetSimpleCounterNotif(t *testing.T) { - conn, index, ifPlugin, notifChan, publishChan, err := testPluginDataInitialization(t) - Expect(err).To(BeNil()) - defer ifPlugin.Close() - defer conn.Disconnect() + conn, index, ifPlugin, notifChan, publishChan := testPluginDataInitialization(t) + defer testPluginDataTeardown(ifPlugin, conn) // Register name index.RegisterName("test", 0, &intf.Interfaces_Interface{ @@ -187,7 +177,7 @@ func TestInterfaceStateUpdaterVnetSimpleCounterNotif(t *testing.T) { // Send interface event notification to propagate update from counter to publish channel notifChan <- &interfaces.SwInterfaceEvent{ - Pid: 0, + PID: 0, SwIfIndex: 0, AdminUpDown: 1, LinkUpDown: 1, @@ -195,10 +185,19 @@ func TestInterfaceStateUpdaterVnetSimpleCounterNotif(t *testing.T) { } var notif *intf.InterfaceNotification - Eventually(publishChan).Should(Receive(¬if)) Expect(notif.Type).To(Equal(intf.InterfaceNotification_UPDOWN)) Expect(notif.State.AdminStatus).Should(BeEquivalentTo(intf.InterfacesState_Interface_UP)) + Expect(notif.State.Statistics).To(BeEquivalentTo(&intf.InterfacesState_Interface_Statistics{ + DropPackets: 32768, + PuntPackets: 32769, + Ipv4Packets: 32770, + Ipv6Packets: 32771, + InNobufPackets: 32772, + InMissPackets: 32773, + InErrorPackets: 32774, + OutErrorPackets: 32775, + })) Expect(notif.State.Statistics.DropPackets).Should(BeEquivalentTo(32768)) Expect(notif.State.Statistics.PuntPackets).Should(BeEquivalentTo(32769)) Expect(notif.State.Statistics.Ipv4Packets).Should(BeEquivalentTo(32770)) @@ -211,10 +210,8 @@ func TestInterfaceStateUpdaterVnetSimpleCounterNotif(t *testing.T) { // Test VnetIntCombined notification func TestInterfaceStateUpdaterVnetIntCombinedNotif(t *testing.T) { - conn, index, ifPlugin, notifChan, publishChan, err := testPluginDataInitialization(t) - Expect(err).To(BeNil()) - defer ifPlugin.Close() - defer conn.Disconnect() + conn, index, ifPlugin, notifChan, publishChan := testPluginDataInitialization(t) + defer testPluginDataTeardown(ifPlugin, conn) // Register name index.RegisterName("test0", 0, &intf.Interfaces_Interface{ @@ -263,10 +260,8 @@ func TestInterfaceStateUpdaterVnetIntCombinedNotif(t *testing.T) { // Test SwInterfaceDetails notification func TestInterfaceStateUpdaterSwInterfaceDetailsNotif(t *testing.T) { - conn, index, ifPlugin, notifChan, publishChan, err := testPluginDataInitialization(t) - Expect(err).To(BeNil()) - defer ifPlugin.Close() - defer conn.Disconnect() + conn, index, ifPlugin, notifChan, publishChan := testPluginDataInitialization(t) + defer testPluginDataTeardown(ifPlugin, conn) // Register name index.RegisterName("test", 0, &intf.Interfaces_Interface{ @@ -305,10 +300,8 @@ func TestInterfaceStateUpdaterSwInterfaceDetailsNotif(t *testing.T) { // Test deleted notification func TestInterfaceStateUpdaterIfStateDeleted(t *testing.T) { - conn, index, ifPlugin, notifChan, publishChan, err := testPluginDataInitialization(t) - Expect(err).To(BeNil()) - defer ifPlugin.Close() - defer conn.Disconnect() + conn, index, ifPlugin, notifChan, publishChan := testPluginDataInitialization(t) + defer testPluginDataTeardown(ifPlugin, conn) // Register name index.RegisterName("test", 0, &intf.Interfaces_Interface{ @@ -320,7 +313,7 @@ func TestInterfaceStateUpdaterIfStateDeleted(t *testing.T) { // Test notifications notifChan <- &interfaces.SwInterfaceEvent{ - Pid: 0, + PID: 0, SwIfIndex: 0, AdminUpDown: 1, LinkUpDown: 1, diff --git a/plugins/vpp/ifplugin/nat_config.go b/plugins/vpp/ifplugin/nat_config.go index 8d1705e010..45fb1cc67b 100644 --- a/plugins/vpp/ifplugin/nat_config.go +++ b/plugins/vpp/ifplugin/nat_config.go @@ -32,7 +32,6 @@ import ( "github.com/ligato/vpp-agent/plugins/govppmux" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppdump" "github.com/ligato/vpp-agent/plugins/vpp/model/nat" ) @@ -44,6 +43,13 @@ const ( dummyTag = "dummy-tag" // used for deletion where tag is not needed ) +// Default NAT virtual reassembly values +const ( + maxReassembly = 1024 + maxFragments = 5 + timeout = 2 +) + // NatConfigurator runs in the background in its own goroutine where it watches for any changes // in the configuration of NAT address pools and static entries with or without a load ballance, // as modelled by the proto file "../common/model/nat/nat.proto" @@ -66,7 +72,7 @@ type NatConfigurator struct { sNatMappingIndexes idxvpp.NameToIdxRW // SNAT indices for static mapping dNatIndexes idxvpp.NameToIdxRW // DNAT indices dNatStMappingIndexes idxvpp.NameToIdxRW // DNAT indices for static mapping - dNatIdMappingIndexes idxvpp.NameToIdxRW // DNAT indices for identity mapping + dNatIDMappingIndexes idxvpp.NameToIdxRW // DNAT indices for identity mapping natIndexSeq uint32 // Nat name-to-idx mapping sequence natMappingTagSeq uint32 // Static/identity mapping tag sequence @@ -79,6 +85,9 @@ type NatConfigurator struct { vppChan govppapi.Channel vppDumpChan govppapi.Channel + // VPP API handler + natHandler vppcalls.NatVppAPI + stopwatch *measure.Stopwatch } @@ -89,13 +98,18 @@ func (plugin *NatConfigurator) Init(logger logging.PluginLogger, goVppMux govppm plugin.log = logger.NewLogger("-nat-conf") plugin.log.Debug("Initializing NAT configurator") + // Configurator-wide stopwatch instance + if enableStopwatch { + plugin.stopwatch = measure.NewStopwatch("NAT-configurator", plugin.log) + } + // Mappings plugin.ifIndexes = ifIndexes plugin.sNatIndexes = nametoidx.NewNameToIdx(plugin.log, "snat-indices", nil) plugin.sNatMappingIndexes = nametoidx.NewNameToIdx(plugin.log, "snat-mapping-indices", nil) plugin.dNatIndexes = nametoidx.NewNameToIdx(plugin.log, "dnat-indices", nil) plugin.dNatStMappingIndexes = nametoidx.NewNameToIdx(plugin.log, "dnat-st-mapping-indices", nil) - plugin.dNatIdMappingIndexes = nametoidx.NewNameToIdx(plugin.log, "dnat-id-mapping-indices", nil) + plugin.dNatIDMappingIndexes = nametoidx.NewNameToIdx(plugin.log, "dnat-id-mapping-indices", nil) plugin.notEnabledIfs = make(map[string]*nat.Nat44Global_NatInterface) plugin.notDisabledIfs = make(map[string]*nat.Nat44Global_NatInterface) plugin.natIndexSeq, plugin.natMappingTagSeq = 1, 1 @@ -108,15 +122,9 @@ func (plugin *NatConfigurator) Init(logger logging.PluginLogger, goVppMux govppm return err } - // Stopwatch - if enableStopwatch { - plugin.stopwatch = measure.NewStopwatch("InterfaceConfigurator", plugin.log) - } - - // Check VPP message compatibility - if err := vppcalls.CheckMsgCompatibilityForNat(plugin.vppChan); err != nil { - return err - } + // VPP API handler + plugin.natHandler = vppcalls.NewNatVppHandler(plugin.vppChan, plugin.vppDumpChan, plugin.ifIndexes, + plugin.log, plugin.stopwatch) return nil } @@ -132,7 +140,7 @@ func (plugin *NatConfigurator) clearMapping() { plugin.sNatMappingIndexes.Clear() plugin.dNatIndexes.Clear() plugin.dNatStMappingIndexes.Clear() - plugin.dNatIdMappingIndexes.Clear() + plugin.dNatIDMappingIndexes.Clear() plugin.notEnabledIfs = make(map[string]*nat.Nat44Global_NatInterface) plugin.notDisabledIfs = make(map[string]*nat.Nat44Global_NatInterface) } @@ -154,21 +162,21 @@ func (plugin *NatConfigurator) IsInNotDisabledIfCache(ifName string) bool { return ok } -// IsInNotDisabledIfCache checks if interface is present in 'notDisabledIfs' cache +// IsDNatLabelRegistered checks if interface is present in 'notDisabledIfs' cache func (plugin *NatConfigurator) IsDNatLabelRegistered(label string) bool { _, _, found := plugin.dNatIndexes.LookupIdx(label) return found } -// IsInNotDisabledIfCache checks if DNAT static mapping with provided id is registered +// IsDNatLabelStMappingRegistered checks if DNAT static mapping with provided id is registered func (plugin *NatConfigurator) IsDNatLabelStMappingRegistered(id string) bool { _, _, found := plugin.dNatStMappingIndexes.LookupIdx(id) return found } -// IsDNatLabelIdMappingRegistered checks if DNAT identity mapping with provided id is registered -func (plugin *NatConfigurator) IsDNatLabelIdMappingRegistered(id string) bool { - _, _, found := plugin.dNatIdMappingIndexes.LookupIdx(id) +// IsDNatLabelIDMappingRegistered checks if DNAT identity mapping with provided id is registered +func (plugin *NatConfigurator) IsDNatLabelIDMappingRegistered(id string) bool { + _, _, found := plugin.dNatIDMappingIndexes.LookupIdx(id) return found } @@ -180,7 +188,7 @@ func (plugin *NatConfigurator) SetNatGlobalConfig(config *nat.Nat44Global) error plugin.globalNAT = config // Forwarding - if err := vppcalls.SetNat44Forwarding(config.Forwarding, plugin.vppChan, plugin.stopwatch); err != nil { + if err := plugin.natHandler.SetNat44Forwarding(config.Forwarding); err != nil { return err } if config.Forwarding { @@ -189,7 +197,7 @@ func (plugin *NatConfigurator) SetNatGlobalConfig(config *nat.Nat44Global) error plugin.log.Debugf("NAT forwarding disabled") } - // / Inside/outside interfaces + // Inside/outside interfaces if len(config.NatInterfaces) > 0 { if err := plugin.enableNatInterfaces(config.NatInterfaces); err != nil { return err @@ -202,6 +210,21 @@ func (plugin *NatConfigurator) SetNatGlobalConfig(config *nat.Nat44Global) error return err } + // Virtual reassembly IPv4 + if config.VirtualReassemblyIpv4 != nil { + if err := plugin.natHandler.SetVirtualReassemblyIPv4(config.VirtualReassemblyIpv4); err != nil { + return err + } + plugin.log.Debug("Nat virtual reassembly set for IPv4") + } + // Virtual reassembly IPv6 + if config.VirtualReassemblyIpv6 != nil { + if err := plugin.natHandler.SetVirtualReassemblyIPv6(config.VirtualReassemblyIpv6); err != nil { + return err + } + plugin.log.Debug("Nat virtual reassembly set for IPv6") + } + plugin.log.Debug("Setting up NAT global config done") return nil @@ -216,7 +239,7 @@ func (plugin *NatConfigurator) ModifyNatGlobalConfig(oldConfig, newConfig *nat.N // Forwarding if oldConfig.Forwarding != newConfig.Forwarding { - if err := vppcalls.SetNat44Forwarding(newConfig.Forwarding, plugin.vppChan, plugin.stopwatch); err != nil { + if err := plugin.natHandler.SetNat44Forwarding(newConfig.Forwarding); err != nil { return err } } @@ -245,7 +268,20 @@ func (plugin *NatConfigurator) ModifyNatGlobalConfig(oldConfig, newConfig *nat.N return err } - plugin.log.Debug("Modifying NAT global config done") + // Virtual reassembly IPv4 + if toConfigure := isVirtualReassModified(oldConfig.VirtualReassemblyIpv4, newConfig.VirtualReassemblyIpv4); toConfigure != nil { + if err := plugin.natHandler.SetVirtualReassemblyIPv4(toConfigure); err != nil { + return err + } + plugin.log.Debug("Nat virtual reassembly modified for IPv4") + } + // Virtual reassembly IPv6 + if toConfigure := isVirtualReassModified(oldConfig.VirtualReassemblyIpv6, newConfig.VirtualReassemblyIpv6); toConfigure != nil { + if err := plugin.natHandler.SetVirtualReassemblyIPv6(toConfigure); err != nil { + return err + } + plugin.log.Debug("Nat virtual reassembly modified for IPv6") + } return nil } @@ -271,6 +307,14 @@ func (plugin *NatConfigurator) DeleteNatGlobalConfig(config *nat.Nat44Global) (e } } + // Reset virtual reassembly to default + if err := plugin.natHandler.SetVirtualReassemblyIPv4(getDefaultVr()); err != nil { + return err + } + if err := plugin.natHandler.SetVirtualReassemblyIPv6(getDefaultVr()); err != nil { + return err + } + plugin.log.Debug("Deleting NAT global config done") return nil @@ -440,12 +484,12 @@ func (plugin *NatConfigurator) ResolveDeletedInterface(ifName string, ifIdx uint // DumpNatGlobal returns the current NAT44 global config func (plugin *NatConfigurator) DumpNatGlobal() (*nat.Nat44Global, error) { - return vppdump.Nat44GlobalConfigDump(plugin.ifIndexes, plugin.log, plugin.vppDumpChan, plugin.stopwatch) + return plugin.natHandler.Nat44GlobalConfigDump() } // DumpNatDNat returns the current NAT44 DNAT config func (plugin *NatConfigurator) DumpNatDNat() (*nat.Nat44DNat, error) { - return vppdump.NAT44DNatDump(plugin.ifIndexes, plugin.log, plugin.vppDumpChan, plugin.stopwatch) + return plugin.natHandler.Nat44DNatDump() } // enables set of interfaces as inside/outside in NAT @@ -458,7 +502,7 @@ func (plugin *NatConfigurator) enableNatInterfaces(natInterfaces []*nat.Nat44Glo } else { if natInterface.OutputFeature { // enable nat interface and output feature - if err = vppcalls.EnableNat44InterfaceOutput(ifIdx, natInterface.IsInside, plugin.vppChan, plugin.stopwatch); err != nil { + if err = plugin.natHandler.EnableNat44InterfaceOutput(ifIdx, natInterface.IsInside); err != nil { return } if natInterface.IsInside { @@ -468,7 +512,7 @@ func (plugin *NatConfigurator) enableNatInterfaces(natInterfaces []*nat.Nat44Glo } } else { // enable interface only - if err = vppcalls.EnableNat44Interface(ifIdx, natInterface.IsInside, plugin.vppChan, plugin.stopwatch); err != nil { + if err = plugin.natHandler.EnableNat44Interface(ifIdx, natInterface.IsInside); err != nil { return } if natInterface.IsInside { @@ -500,7 +544,7 @@ func (plugin *NatConfigurator) disableNatInterfaces(natInterfaces []*nat.Nat44Gl } else { if natInterface.OutputFeature { // disable nat interface and output feature - if err = vppcalls.DisableNat44InterfaceOutput(ifIdx, natInterface.IsInside, plugin.vppChan, plugin.stopwatch); err != nil { + if err = plugin.natHandler.DisableNat44InterfaceOutput(ifIdx, natInterface.IsInside); err != nil { return } if natInterface.IsInside { @@ -510,7 +554,7 @@ func (plugin *NatConfigurator) disableNatInterfaces(natInterfaces []*nat.Nat44Gl } } else { // disable interface - if err = vppcalls.DisableNat44Interface(ifIdx, natInterface.IsInside, plugin.vppChan, plugin.stopwatch); err != nil { + if err = plugin.natHandler.DisableNat44Interface(ifIdx, natInterface.IsInside); err != nil { return } if natInterface.IsInside { @@ -561,7 +605,7 @@ func (plugin *NatConfigurator) addAddressPool(addressPools []*nat.Nat44Global_Ad } else if lastIP == nil { lastIP = firstIP } - if err = vppcalls.AddNat44AddressPool(firstIP, lastIP, addressPool.VrfId, addressPool.TwiceNat, plugin.vppChan, plugin.stopwatch); err != nil { + if err = plugin.natHandler.AddNat44AddressPool(firstIP, lastIP, addressPool.VrfId, addressPool.TwiceNat); err != nil { plugin.log.Error(err) wasErr = err } @@ -607,7 +651,7 @@ func (plugin *NatConfigurator) delAddressPool(addressPools []*nat.Nat44Global_Ad } // remove address pool - if err = vppcalls.DelNat44AddressPool(firstIP, lastIP, addressPool.VrfId, addressPool.TwiceNat, plugin.vppChan, plugin.stopwatch); err != nil { + if err = plugin.natHandler.DelNat44AddressPool(firstIP, lastIP, addressPool.VrfId, addressPool.TwiceNat); err != nil { plugin.log.Error(err) wasErr = err } @@ -711,7 +755,6 @@ func (plugin *NatConfigurator) handleStaticMappingLb(staticMappingLb *nat.Nat44D ExternalPort: uint16(staticMappingLb.ExternalPort), Protocol: getProtocol(staticMappingLb.Protocol, plugin.log), LocalIPs: getLocalIPs(staticMappingLb.LocalIps, plugin.log), - Vrf: staticMappingLb.VrfId, TwiceNat: staticMappingLb.TwiceNat == nat.TwiceNatMode_ENABLED, SelfTwiceNat: staticMappingLb.TwiceNat == nat.TwiceNatMode_SELF, } @@ -721,9 +764,9 @@ func (plugin *NatConfigurator) handleStaticMappingLb(staticMappingLb *nat.Nat44D } if add { - return vppcalls.AddNat44StaticMappingLb(ctx, plugin.vppChan, plugin.stopwatch) + return plugin.natHandler.AddNat44StaticMappingLb(ctx) } - return vppcalls.DelNat44StaticMappingLb(ctx, plugin.vppChan, plugin.stopwatch) + return plugin.natHandler.DelNat44StaticMappingLb(ctx) } // handler for single static mapping entry @@ -739,6 +782,7 @@ func (plugin *NatConfigurator) handleStaticMapping(staticMapping *nat.Nat44DNat_ // Parse local IP address and port lcIPAddr := net.ParseIP(staticMapping.LocalIps[0].LocalIp).To4() lcPort := staticMapping.LocalIps[0].LocalPort + lcVrf := staticMapping.LocalIps[0].VrfId if lcIPAddr == nil { return fmt.Errorf("cannot configure DNAT mapping: unable to parse local IP %v", lcIPAddr) } @@ -775,15 +819,15 @@ func (plugin *NatConfigurator) handleStaticMapping(staticMapping *nat.Nat44DNat_ ExternalPort: uint16(staticMapping.ExternalPort), ExternalIfIdx: ifIdx, Protocol: getProtocol(staticMapping.Protocol, plugin.log), - Vrf: staticMapping.VrfId, + Vrf: lcVrf, TwiceNat: staticMapping.TwiceNat == nat.TwiceNatMode_ENABLED, SelfTwiceNat: staticMapping.TwiceNat == nat.TwiceNatMode_SELF, } if add { - return vppcalls.AddNat44StaticMapping(ctx, plugin.vppChan, plugin.stopwatch) + return plugin.natHandler.AddNat44StaticMapping(ctx) } - return vppcalls.DelNat44StaticMapping(ctx, plugin.vppChan, plugin.stopwatch) + return plugin.natHandler.DelNat44StaticMapping(ctx) } // configures a list of identity mappings with label @@ -804,8 +848,8 @@ func (plugin *NatConfigurator) configureIdentityMappings(label string, mappings } // Register DNAT identity mapping - mappingIdentifier := GetIdMappingIdentifier(idMapping) - plugin.dNatIdMappingIndexes.RegisterName(mappingIdentifier, plugin.natIndexSeq, nil) + mappingIdentifier := GetIDMappingIdentifier(idMapping) + plugin.dNatIDMappingIndexes.RegisterName(mappingIdentifier, plugin.natIndexSeq, nil) plugin.natIndexSeq++ plugin.log.Debugf("DNAT identity mapping configured (ID: %s, Tag: %s)", mappingIdentifier, tag) @@ -830,8 +874,8 @@ func (plugin *NatConfigurator) unconfigureIdentityMappings(mappings []*nat.Nat44 } // Unregister DNAT identity mapping - mappingIdentifier := GetIdMappingIdentifier(idMapping) - plugin.dNatIdMappingIndexes.UnregisterName(mappingIdentifier) + mappingIdentifier := GetIDMappingIdentifier(idMapping) + plugin.dNatIDMappingIndexes.UnregisterName(mappingIdentifier) plugin.natIndexSeq++ plugin.log.Debugf("DNAT identity (lb)mapping un-configured (ID: %v)", mappingIdentifier) @@ -874,9 +918,9 @@ func (plugin *NatConfigurator) handleIdentityMapping(idMapping *nat.Nat44DNat_DN // Configure/remove identity mapping if isAdd { - return vppcalls.AddNat44IdentityMapping(ctx, plugin.vppChan, plugin.stopwatch) + return plugin.natHandler.AddNat44IdentityMapping(ctx) } - return vppcalls.DelNat44IdentityMapping(ctx, plugin.vppChan, plugin.stopwatch) + return plugin.natHandler.DelNat44IdentityMapping(ctx) } // looks for new and obsolete IN interfaces @@ -976,7 +1020,7 @@ func (plugin *NatConfigurator) diffStatic(oldMappings, newMappings []*nat.Nat44D var found bool for _, oldMap := range oldMappings { // VRF, protocol and twice map - if newMap.VrfId != oldMap.VrfId || newMap.Protocol != oldMap.Protocol || newMap.TwiceNat != oldMap.TwiceNat { + if newMap.Protocol != oldMap.Protocol || newMap.TwiceNat != oldMap.TwiceNat { continue } // External interface, IP and port @@ -999,7 +1043,7 @@ func (plugin *NatConfigurator) diffStatic(oldMappings, newMappings []*nat.Nat44D var found bool for _, newMap := range newMappings { // VRF, protocol and twice map - if newMap.VrfId != oldMap.VrfId || newMap.Protocol != oldMap.Protocol || newMap.TwiceNat != oldMap.TwiceNat { + if newMap.Protocol != oldMap.Protocol || newMap.TwiceNat != oldMap.TwiceNat { continue } // External interface, IP and port @@ -1065,6 +1109,20 @@ func (plugin *NatConfigurator) diffIdentity(oldMappings, newMappings []*nat.Nat4 return } +// diffVirtualReassembly compares virtual reassembly from old config, returns virtual reassembly to be configured, or nil +// if no changes are needed +func isVirtualReassModified(oldReass, newReass *nat.Nat44Global_VirtualReassembly) *nat.Nat44Global_VirtualReassembly { + // If new value is set while the old value does not exist, or it is different, return new value to configure + if newReass != nil && (oldReass == nil || *oldReass != *newReass) { + return newReass + } + // If old value was set but new is not, return default + if oldReass != nil && newReass == nil { + return getDefaultVr() + } + return nil +} + // comapares two lists of Local IP addresses, returns true if lists are equal, false otherwise func (plugin *NatConfigurator) compareLocalIPs(oldIPs, newIPs []*nat.Nat44DNat_DNatConfig_StaticMapping_LocalIP) bool { if len(oldIPs) != len(newIPs) { @@ -1073,7 +1131,7 @@ func (plugin *NatConfigurator) compareLocalIPs(oldIPs, newIPs []*nat.Nat44DNat_D for _, newIP := range newIPs { var found bool for _, oldIP := range oldIPs { - if newIP.LocalIp == oldIP.LocalIp && newIP.LocalPort == oldIP.LocalPort && newIP.Probability == oldIP.Probability { + if newIP.VrfId == oldIP.VrfId && newIP.LocalIp == oldIP.LocalIp && newIP.LocalPort == oldIP.LocalPort && newIP.Probability == oldIP.Probability { found = true } } @@ -1100,6 +1158,7 @@ func getLocalIPs(ipPorts []*nat.Nat44DNat_DNatConfig_StaticMapping_LocalIP, log } locals = append(locals, &vppcalls.LocalLbAddress{ + Vrf: ipPort.VrfId, LocalIP: localIP, LocalPort: uint16(ipPort.LocalPort), Probability: uint8(ipPort.Probability), @@ -1130,11 +1189,11 @@ func GetStMappingIdentifier(mapping *nat.Nat44DNat_DNatConfig_StaticMapping) str extIP = strings.Replace(extIP, "/", "", -1) locIP := strings.Replace(mapping.LocalIps[0].LocalIp, ".", "", -1) locIP = strings.Replace(locIP, "/", "", -1) - return extIP + locIP + strconv.Itoa(int(mapping.VrfId)) + return extIP + locIP + strconv.Itoa(int(mapping.LocalIps[0].VrfId)) } -// GetIdMappingIdentifier returns unique ID of the mapping -func GetIdMappingIdentifier(mapping *nat.Nat44DNat_DNatConfig_IdentityMapping) string { +// GetIDMappingIdentifier returns unique ID of the mapping +func GetIDMappingIdentifier(mapping *nat.Nat44DNat_DNatConfig_IdentityMapping) string { extIP := strings.Replace(mapping.IpAddress, ".", "", -1) extIP = strings.Replace(extIP, "/", "", -1) if mapping.AddressedInterface == "" { @@ -1153,3 +1212,13 @@ func (plugin *NatConfigurator) getMappingTag(label, mType string) string { return buffer.String() } + +// getDefaultVr returns default nat virtual reassembly configuration. +func getDefaultVr() *nat.Nat44Global_VirtualReassembly { + return &nat.Nat44Global_VirtualReassembly{ + MaxReass: maxReassembly, + MaxFrag: maxFragments, + Timeout: timeout, + DropFrag: false, + } +} diff --git a/plugins/vpp/ifplugin/nat_config_test.go b/plugins/vpp/ifplugin/nat_config_test.go index 9324c55291..75743d98cf 100644 --- a/plugins/vpp/ifplugin/nat_config_test.go +++ b/plugins/vpp/ifplugin/nat_config_test.go @@ -20,7 +20,6 @@ import ( "git.fd.io/govpp.git/adapter/mock" "git.fd.io/govpp.git/core" "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/idxvpp/nametoidx" nat_api "github.com/ligato/vpp-agent/plugins/vpp/binapi/nat" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin" @@ -30,61 +29,43 @@ import ( . "github.com/onsi/gomega" ) -/* NAT configurator init and close */ - -// Test init function -func TestNatConfiguratorInit(t *testing.T) { - RegisterTestingT(t) - connection, _ := core.Connect(&mock.VppAdapter{}) - defer connection.Disconnect() - - plugin := &ifplugin.NatConfigurator{} - err := plugin.Init(logging.ForPlugin("test-log", logrus.NewLogRegistry()), connection, - nil, true) - Expect(err).To(BeNil()) - - err = plugin.Close() - Expect(err).To(BeNil()) -} - /* Global NAT Test Cases */ // Enable NAT forwarding func TestNatConfiguratorEnableForwarding(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44ForwardingEnableDisableReply{}) // Data data := getTestNatForwardingConfig(true) + // Test - err = plugin.SetNatGlobalConfig(data) + err := plugin.SetNatGlobalConfig(data) Expect(err).To(BeNil()) } // Disable NAT forwarding func TestNatConfiguratorDisableForwarding(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44ForwardingEnableDisableReply{}) // Data data := getTestNatForwardingConfig(false) + // Test - err = plugin.SetNatGlobalConfig(data) + err := plugin.SetNatGlobalConfig(data) Expect(err).To(BeNil()) } // Modify NAT forwarding func TestNatConfiguratorModifyForwarding(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44ForwardingEnableDisableReply{}) // Create ctx.MockVpp.MockReply(&nat_api.Nat44ForwardingEnableDisableReply{}) // Modify @@ -92,7 +73,7 @@ func TestNatConfiguratorModifyForwarding(t *testing.T) { oldData := getTestNatForwardingConfig(true) newData := getTestNatForwardingConfig(false) // Test create - err = plugin.SetNatGlobalConfig(oldData) + err := plugin.SetNatGlobalConfig(oldData) Expect(err).To(BeNil()) Expect(plugin.GetGlobalNat().Forwarding).To(BeTrue()) // Test modify @@ -103,27 +84,26 @@ func TestNatConfiguratorModifyForwarding(t *testing.T) { // NAT set forwarding return error func TestNatConfiguratorCreateForwardingError(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44ForwardingEnableDisableReply{ Retval: 1, }) // Data data := getTestNatForwardingConfig(false) + // Test - err = plugin.SetNatGlobalConfig(data) + err := plugin.SetNatGlobalConfig(data) Expect(err).ToNot(BeNil()) } // Modify NAT forwarding error func TestNatConfiguratorModifyForwardingError(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44ForwardingEnableDisableReply{}) // Create ctx.MockVpp.MockReply(&nat_api.Nat44ForwardingEnableDisableReply{ // Modify @@ -132,8 +112,9 @@ func TestNatConfiguratorModifyForwardingError(t *testing.T) { // Data oldData := getTestNatForwardingConfig(true) newData := getTestNatForwardingConfig(false) + // Test create - err = plugin.SetNatGlobalConfig(oldData) + err := plugin.SetNatGlobalConfig(oldData) Expect(err).To(BeNil()) Expect(plugin.GetGlobalNat().Forwarding).To(BeTrue()) // Test modify @@ -143,10 +124,9 @@ func TestNatConfiguratorModifyForwardingError(t *testing.T) { // Enable two interfaces for NAT, then remove one func TestNatConfiguratorEnableDisableInterfaces(t *testing.T) { - var err error - // Setup ctx, connection, plugin, ifIndexes := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44ForwardingEnableDisableReply{}) // First case ctx.MockVpp.MockReply(&nat_api.Nat44InterfaceAddDelFeatureReply{}) @@ -163,8 +143,9 @@ func TestNatConfiguratorEnableDisableInterfaces(t *testing.T) { getTestNatInterfaceConfig("if2", true, false))} secondData := &nat.Nat44Global{NatInterfaces: append(ifs2, getTestNatInterfaceConfig("if1", true, false))} + // Test set interfaces - err = plugin.SetNatGlobalConfig(firstData) + err := plugin.SetNatGlobalConfig(firstData) Expect(err).To(BeNil()) Expect(plugin.IsInNotEnabledIfCache("if1")).To(BeFalse()) Expect(plugin.IsInNotEnabledIfCache("if2")).To(BeFalse()) @@ -183,10 +164,9 @@ func TestNatConfiguratorEnableDisableInterfaces(t *testing.T) { // Attempt to enable interface resulting in return value error func TestNatConfiguratorEnableDisableInterfacesError(t *testing.T) { - var err error - // Setup ctx, connection, plugin, ifIndexes := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44ForwardingEnableDisableReply{}) // First case ctx.MockVpp.MockReply(&nat_api.Nat44InterfaceAddDelFeatureReply{ @@ -198,16 +178,16 @@ func TestNatConfiguratorEnableDisableInterfacesError(t *testing.T) { var ifs1 []*nat.Nat44Global_NatInterface firstData := &nat.Nat44Global{NatInterfaces: append(ifs1, getTestNatInterfaceConfig("if1", true, false))} + // Test set interfaces - err = plugin.SetNatGlobalConfig(firstData) + err := plugin.SetNatGlobalConfig(firstData) Expect(err).ToNot(BeNil()) } // Enable two output interfaces for NAT, then remove one func TestNatConfiguratorEnableDisableOutputInterfaces(t *testing.T) { - var err error - // Setup ctx, connection, plugin, ifIndexes := natTestSetup(t) + defer natTestTeardown(connection, plugin) // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44ForwardingEnableDisableReply{}) // First case @@ -225,8 +205,9 @@ func TestNatConfiguratorEnableDisableOutputInterfaces(t *testing.T) { getTestNatInterfaceConfig("if2", true, true))} secondData := &nat.Nat44Global{NatInterfaces: append(ifs2, getTestNatInterfaceConfig("if1", true, true))} + // Test set output interfaces - err = plugin.SetNatGlobalConfig(firstData) + err := plugin.SetNatGlobalConfig(firstData) Expect(err).To(BeNil()) Expect(plugin.IsInNotEnabledIfCache("if1")).To(BeFalse()) Expect(plugin.IsInNotEnabledIfCache("if2")).To(BeFalse()) @@ -245,10 +226,9 @@ func TestNatConfiguratorEnableDisableOutputInterfaces(t *testing.T) { // Create and modify NAT interfaces and output interfaces func TestNatConfiguratorModifyInterfaces(t *testing.T) { - var err error - // Setup ctx, connection, plugin, ifIndexes := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44ForwardingEnableDisableReply{}) // Create ctx.MockVpp.MockReply(&nat_api.Nat44InterfaceAddDelFeatureReply{}) @@ -272,8 +252,9 @@ func TestNatConfiguratorModifyInterfaces(t *testing.T) { getTestNatInterfaceConfig("if1", false, true), getTestNatInterfaceConfig("if2", true, false), getTestNatInterfaceConfig("if3", true, true))} + // Test create - err = plugin.SetNatGlobalConfig(oldData) + err := plugin.SetNatGlobalConfig(oldData) Expect(err).To(BeNil()) Expect(plugin.IsInNotEnabledIfCache("if1")).To(BeFalse()) Expect(plugin.IsInNotEnabledIfCache("if2")).To(BeFalse()) @@ -287,10 +268,9 @@ func TestNatConfiguratorModifyInterfaces(t *testing.T) { // Test interface cache registering and un-registering interfaces after configuration func TestNatConfiguratorInterfaceCache(t *testing.T) { - var err error - // Setup ctx, connection, plugin, ifIndexes := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44ForwardingEnableDisableReply{}) ctx.MockVpp.MockReply(&nat_api.Nat44InterfaceAddDelFeatureReply{}) @@ -301,8 +281,9 @@ func TestNatConfiguratorInterfaceCache(t *testing.T) { data := &nat.Nat44Global{NatInterfaces: append(ifs, getTestNatInterfaceConfig("if1", true, false), getTestNatInterfaceConfig("if2", true, true))} + // Test create - err = plugin.SetNatGlobalConfig(data) + err := plugin.SetNatGlobalConfig(data) Expect(err).To(BeNil()) Expect(plugin.IsInNotEnabledIfCache("if1")).To(BeTrue()) Expect(plugin.IsInNotEnabledIfCache("if2")).To(BeTrue()) @@ -341,10 +322,9 @@ func TestNatConfiguratorInterfaceCache(t *testing.T) { // Set NAT address pools func TestNatConfiguratorCreateAddressPool(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44ForwardingEnableDisableReply{}) ctx.MockVpp.MockReply(&nat_api.Nat44AddDelAddressRangeReply{}) @@ -356,18 +336,18 @@ func TestNatConfiguratorCreateAddressPool(t *testing.T) { getTestNatAddressPoolConfig("10.0.0.1", "10.0.0.2", 0, true), getTestNatAddressPoolConfig("10.0.0.3", "", 1, false), getTestNatAddressPoolConfig("", "10.0.0.4", 1, false))} + // Test set address pool - err = plugin.SetNatGlobalConfig(data) + err := plugin.SetNatGlobalConfig(data) Expect(err).To(BeNil()) Expect(plugin.GetGlobalNat().AddressPools).To(HaveLen(3)) } // Set NAT address pool with return value error func TestNatConfiguratorCreateAddressPoolRetvalError(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44ForwardingEnableDisableReply{}) ctx.MockVpp.MockReply(&nat_api.Nat44AddDelAddressRangeReply{ @@ -377,17 +357,17 @@ func TestNatConfiguratorCreateAddressPoolRetvalError(t *testing.T) { var aps []*nat.Nat44Global_AddressPool data := &nat.Nat44Global{AddressPools: append(aps, getTestNatAddressPoolConfig("10.0.0.1", "10.0.0.2", 0, true))} + // Test set address pool - err = plugin.SetNatGlobalConfig(data) + err := plugin.SetNatGlobalConfig(data) Expect(err).ToNot(BeNil()) } // Set and modify NAT address pools func TestNatConfiguratorModifyAddressPool(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44ForwardingEnableDisableReply{}) // Configure ctx.MockVpp.MockReply(&nat_api.Nat44AddDelAddressRangeReply{}) @@ -402,8 +382,9 @@ func TestNatConfiguratorModifyAddressPool(t *testing.T) { newData := &nat.Nat44Global{AddressPools: append(aps2, getTestNatAddressPoolConfig("10.0.0.1", "", 0, true), getTestNatAddressPoolConfig("", "10.0.0.3", 1, false))} + // Test set address pool - err = plugin.SetNatGlobalConfig(oldData) + err := plugin.SetNatGlobalConfig(oldData) Expect(err).To(BeNil()) Expect(plugin.GetGlobalNat().AddressPools).To(HaveLen(2)) // Test modify address pool @@ -414,10 +395,9 @@ func TestNatConfiguratorModifyAddressPool(t *testing.T) { // Test various errors which may occur during address pool configuration func TestNatConfiguratorAddressPoolErrors(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44ForwardingEnableDisableReply{}) ctx.MockVpp.MockReply(&nat_api.Nat44ForwardingEnableDisableReply{}) @@ -427,8 +407,9 @@ func TestNatConfiguratorAddressPoolErrors(t *testing.T) { data1 := &nat.Nat44Global{AddressPools: append(aps1, getTestNatAddressPoolConfig("", "", 0, true))} data2 := &nat.Nat44Global{AddressPools: append(aps2, getTestNatAddressPoolConfig("invalid-ip", "", 0, true))} data3 := &nat.Nat44Global{AddressPools: append(aps3, getTestNatAddressPoolConfig("", "invalid-ip", 0, true))} + // Test no IP address provided - err = plugin.SetNatGlobalConfig(data1) + err := plugin.SetNatGlobalConfig(data1) Expect(err).ToNot(BeNil()) // Test invalid first IP err = plugin.SetNatGlobalConfig(data2) @@ -440,10 +421,9 @@ func TestNatConfiguratorAddressPoolErrors(t *testing.T) { // Set NAT address pool with invalid ip addresses func TestNatConfiguratorModifyAddressPoolErrors(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44ForwardingEnableDisableReply{}) ctx.MockVpp.MockReply(&nat_api.Nat44AddDelAddressRangeReply{}) @@ -456,7 +436,9 @@ func TestNatConfiguratorModifyAddressPoolErrors(t *testing.T) { getTestNatAddressPoolConfig("invalid-ip", "", 0, true), // invalid first IP getTestNatAddressPoolConfig("10.0.0.1", "invalid-ip", 0, true))} // invalid last // Test set address pool - err = plugin.SetNatGlobalConfig(oldData) + + // Test + err := plugin.SetNatGlobalConfig(oldData) Expect(err).To(BeNil()) err = plugin.ModifyNatGlobalConfig(oldData, newData) Expect(err).ToNot(BeNil()) @@ -464,10 +446,9 @@ func TestNatConfiguratorModifyAddressPoolErrors(t *testing.T) { // Set NAT address pool with invalid ip addresses and then modify it with correct one func TestNatConfiguratorModifyAddressPoolModifyErrors(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44ForwardingEnableDisableReply{}) ctx.MockVpp.MockReply(&nat_api.Nat44AddDelAddressRangeReply{}) @@ -479,7 +460,9 @@ func TestNatConfiguratorModifyAddressPoolModifyErrors(t *testing.T) { newData := &nat.Nat44Global{AddressPools: append(aps, getTestNatAddressPoolConfig("10.0.0.1", "", 0, true))} // valid // Test set address pool - err = plugin.SetNatGlobalConfig(oldData) + + // Test + err := plugin.SetNatGlobalConfig(oldData) Expect(err).ToNot(BeNil()) err = plugin.ModifyNatGlobalConfig(oldData, newData) Expect(err).To(BeNil()) @@ -487,10 +470,9 @@ func TestNatConfiguratorModifyAddressPoolModifyErrors(t *testing.T) { // Remove global NAT configuration func TestNatConfiguratorDeleteGlobalConfig(t *testing.T) { - var err error - // Setup ctx, connection, plugin, ifIndexes := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44ForwardingEnableDisableReply{}) // Configure ctx.MockVpp.MockReply(&nat_api.Nat44InterfaceAddDelFeatureReply{}) @@ -498,6 +480,8 @@ func TestNatConfiguratorDeleteGlobalConfig(t *testing.T) { ctx.MockVpp.MockReply(&nat_api.Nat44AddDelAddressRangeReply{}) ctx.MockVpp.MockReply(&nat_api.Nat44InterfaceAddDelFeatureReply{}) // Delete ctx.MockVpp.MockReply(&nat_api.Nat44AddDelAddressRangeReply{}) + ctx.MockVpp.MockReply(&nat_api.NatSetReassReply{}) + ctx.MockVpp.MockReply(&nat_api.NatSetReassReply{}) ctx.MockVpp.MockReply(&nat_api.Nat44InterfaceAddDelOutputFeatureReply{}) // Re-register ctx.MockVpp.MockReply(&nat_api.Nat44InterfaceAddDelFeatureReply{}) // Registration @@ -511,8 +495,9 @@ func TestNatConfiguratorDeleteGlobalConfig(t *testing.T) { getTestNatInterfaceConfig("if2", false, true), getTestNatInterfaceConfig("if3", false, false)), AddressPools: append(aps, getTestNatAddressPoolConfig("10.0.0.1", "10.0.0.2", 0, true))} + // Test set config - err = plugin.SetNatGlobalConfig(data) + err := plugin.SetNatGlobalConfig(data) Expect(err).To(BeNil()) Expect(plugin.IsInNotEnabledIfCache("if1")).To(BeFalse()) Expect(plugin.IsInNotEnabledIfCache("if2")).To(BeFalse()) @@ -552,10 +537,9 @@ func TestNatConfiguratorDeleteGlobalConfig(t *testing.T) { // Remove global NAT configuration with errors func TestNatConfiguratorDeleteGlobalConfigErrors(t *testing.T) { - var err error - // Setup ctx, connection, plugin, ifIndexes := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44InterfaceAddDelFeatureReply{ Retval: 1, @@ -570,22 +554,25 @@ func TestNatConfiguratorDeleteGlobalConfigErrors(t *testing.T) { var aps []*nat.Nat44Global_AddressPool data := &nat.Nat44Global{NatInterfaces: append(ifs, getTestNatInterfaceConfig("if1", true, false)), - AddressPools: append(aps, getTestNatAddressPoolConfig("10.0.0.1", "10.0.0.2", 0, true))} + AddressPools: append(aps, getTestNatAddressPoolConfig("10.0.0.1", "10.0.0.2", 0, true)), + } + // Test delete config - err = plugin.DeleteNatGlobalConfig(data) + err := plugin.DeleteNatGlobalConfig(data) Expect(err).ToNot(BeNil()) } // Remove empty global NAT configuration func TestNatConfiguratorDeleteGlobalConfigEmpty(t *testing.T) { - var err error - // Setup - _, connection, plugin, _ := natTestSetup(t) + ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + ctx.MockVpp.MockReply(&nat_api.NatSetReassReply{}) + ctx.MockVpp.MockReply(&nat_api.NatSetReassReply{}) // Data data := &nat.Nat44Global{} + // Test delete empty config - err = plugin.DeleteNatGlobalConfig(data) + err := plugin.DeleteNatGlobalConfig(data) Expect(err).To(BeNil()) Expect(plugin.GetGlobalNat()).To(BeNil()) } @@ -594,25 +581,24 @@ func TestNatConfiguratorDeleteGlobalConfigEmpty(t *testing.T) { // Test SNAT Create func TestNatConfiguratorSNatCreate(t *testing.T) { - var err error - // Setup _, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Data data := &nat.Nat44SNat_SNatConfig{ Label: "test-snat", } + // Test configure SNAT without local IPs - err = plugin.ConfigureSNat(data) + err := plugin.ConfigureSNat(data) Expect(err).To(BeNil()) } // Test SNAT Modify func TestNatConfiguratorSNatModify(t *testing.T) { - var err error - // Setup _, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Data oldData := &nat.Nat44SNat_SNatConfig{ Label: "test-snat", @@ -620,23 +606,24 @@ func TestNatConfiguratorSNatModify(t *testing.T) { newData := &nat.Nat44SNat_SNatConfig{ Label: "test-snat", } + // Test configure SNAT without local IPs - err = plugin.ModifySNat(oldData, newData) + err := plugin.ModifySNat(oldData, newData) Expect(err).To(BeNil()) } // Test SNAT Delete func TestNatConfiguratorSNatDelete(t *testing.T) { - var err error - // Setup _, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Data data := &nat.Nat44SNat_SNatConfig{ Label: "test-snat", } + // Test configure SNAT without local IPs - err = plugin.DeleteSNat(data) + err := plugin.DeleteSNat(data) Expect(err).To(BeNil()) } @@ -644,28 +631,27 @@ func TestNatConfiguratorSNatDelete(t *testing.T) { // Configure DNAT static mapping without local IP func TestNatConfiguratorDNatStaticMappingNoLocalIPError(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44AddDelStaticMappingReply{}) // Data var stMaps []*nat.Nat44DNat_DNatConfig_StaticMapping data := &nat.Nat44DNat_DNatConfig{Label: "dNatLabel", StMappings: append(stMaps, getTestNatStaticMappingConfig(0, "", "10.0.0.1", 8000, nat.Protocol_TCP))} + // Test configure DNAT without local IPs - err = plugin.ConfigureDNat(data) + err := plugin.ConfigureDNat(data) Expect(err).ToNot(BeNil()) Expect(plugin.IsDNatLabelRegistered(data.Label)).To(BeTrue()) } // Configure DNAT static mapping using external IP func TestNatConfiguratorDNatStaticMapping(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44AddDelStaticMappingReply{}) // Data @@ -673,8 +659,9 @@ func TestNatConfiguratorDNatStaticMapping(t *testing.T) { data := &nat.Nat44DNat_DNatConfig{Label: "dNatLabel", StMappings: append(stMaps, getTestNatStaticMappingConfig(0, "", "10.0.0.1", 8000, nat.Protocol_TCP, getTestNatStaticLocalIP("10.0.0.2", 9000, 32)))} + // Test configure DNAT - err = plugin.ConfigureDNat(data) + err := plugin.ConfigureDNat(data) Expect(err).To(BeNil()) Expect(plugin.IsDNatLabelRegistered(data.Label)).To(BeTrue()) id := ifplugin.GetStMappingIdentifier(data.StMappings[0]) @@ -683,10 +670,9 @@ func TestNatConfiguratorDNatStaticMapping(t *testing.T) { // Configure DNAT static mapping using external interface func TestNatConfiguratorDNatStaticMappingExternalInterface(t *testing.T) { - var err error - // Setup ctx, connection, plugin, ifconfig := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44AddDelStaticMappingReply{}) // Registrations @@ -696,8 +682,9 @@ func TestNatConfiguratorDNatStaticMappingExternalInterface(t *testing.T) { data := &nat.Nat44DNat_DNatConfig{Label: "dNatLabel", StMappings: append(stMaps, getTestNatStaticMappingConfig(0, "if1", "10.0.0.1", 8000, nat.Protocol_UDP, getTestNatStaticLocalIP("10.0.0.2", 9000, 32)))} + // Configure DNAT with external interface - err = plugin.ConfigureDNat(data) + err := plugin.ConfigureDNat(data) Expect(err).To(BeNil()) Expect(plugin.IsDNatLabelRegistered(data.Label)).To(BeTrue()) id := ifplugin.GetStMappingIdentifier(data.StMappings[0]) @@ -706,10 +693,9 @@ func TestNatConfiguratorDNatStaticMappingExternalInterface(t *testing.T) { // Configure DNAT static mapping as address-only func TestNatConfiguratorDNatStaticMappingAddressOnly(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44AddDelStaticMappingReply{}) // Data @@ -717,8 +703,9 @@ func TestNatConfiguratorDNatStaticMappingAddressOnly(t *testing.T) { data := &nat.Nat44DNat_DNatConfig{Label: "dNatLabel", StMappings: append(stMaps, getTestNatStaticMappingConfig(0, "", "10.0.0.1", 0, nat.Protocol_ICMP, getTestNatStaticLocalIP("10.0.0.2", 0, 32)))} + // Test configure DNAT address only - err = plugin.ConfigureDNat(data) + err := plugin.ConfigureDNat(data) Expect(err).To(BeNil()) Expect(plugin.IsDNatLabelRegistered(data.Label)).To(BeTrue()) id := ifplugin.GetStMappingIdentifier(data.StMappings[0]) @@ -727,17 +714,17 @@ func TestNatConfiguratorDNatStaticMappingAddressOnly(t *testing.T) { // Configure DNAT with invalid local IP func TestNatConfiguratorDNatStaticMappingInvalidLocalAddressError(t *testing.T) { - var err error - // Setup _, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Data var stMaps []*nat.Nat44DNat_DNatConfig_StaticMapping data := &nat.Nat44DNat_DNatConfig{Label: "dNatLabel", StMappings: append(stMaps, getTestNatStaticMappingConfig(0, "", "10.0.0.1", 0, 0, getTestNatStaticLocalIP("no-ip", 0, 32)))} + // Test configure DNAT with invalid local IP - err = plugin.ConfigureDNat(data) + err := plugin.ConfigureDNat(data) Expect(err).ToNot(BeNil()) Expect(plugin.IsDNatLabelRegistered(data.Label)).To(BeTrue()) id := ifplugin.GetStMappingIdentifier(data.StMappings[0]) @@ -746,17 +733,17 @@ func TestNatConfiguratorDNatStaticMappingInvalidLocalAddressError(t *testing.T) // Configure DNAT with invalid external IP func TestNatConfiguratorDNatStaticMappingInvalidExternalAddressError(t *testing.T) { - var err error - // Setup _, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Data var stMaps []*nat.Nat44DNat_DNatConfig_StaticMapping data := &nat.Nat44DNat_DNatConfig{Label: "dNatLabel", StMappings: append(stMaps, getTestNatStaticMappingConfig(0, "", "no-ip", 0, 0, getTestNatStaticLocalIP("10.0.0.1", 0, 32)))} + // Test configure DNAT with invalid external IP - err = plugin.ConfigureDNat(data) + err := plugin.ConfigureDNat(data) Expect(err).ToNot(BeNil()) Expect(plugin.IsDNatLabelRegistered(data.Label)).To(BeTrue()) id := ifplugin.GetStMappingIdentifier(data.StMappings[0]) @@ -765,17 +752,17 @@ func TestNatConfiguratorDNatStaticMappingInvalidExternalAddressError(t *testing. // Configure DNAT with non-existing external interface func TestNatConfiguratorDNatStaticMappingMissingInterfaceError(t *testing.T) { - var err error - // Setup _, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Data var stMaps []*nat.Nat44DNat_DNatConfig_StaticMapping data := &nat.Nat44DNat_DNatConfig{Label: "dNatLabel", StMappings: append(stMaps, getTestNatStaticMappingConfig(0, "if1", "10.0.0.1", 0, 0, getTestNatStaticLocalIP("10.0.0.2", 0, 32)))} + // Test configure DNAT with missing external interface - err = plugin.ConfigureDNat(data) + err := plugin.ConfigureDNat(data) Expect(err).ToNot(BeNil()) Expect(plugin.IsDNatLabelRegistered(data.Label)).To(BeTrue()) id := ifplugin.GetStMappingIdentifier(data.StMappings[0]) @@ -784,10 +771,9 @@ func TestNatConfiguratorDNatStaticMappingMissingInterfaceError(t *testing.T) { // Configure DNAT with unknown protocol and check whether it will be set to default func TestNatConfiguratorDNatStaticMappingUnknownProtocol(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44AddDelStaticMappingReply{}) // Data @@ -795,8 +781,9 @@ func TestNatConfiguratorDNatStaticMappingUnknownProtocol(t *testing.T) { data := &nat.Nat44DNat_DNatConfig{Label: "dNatLabel", StMappings: append(stMaps, getTestNatStaticMappingConfig(0, "", "10.0.0.1", 0, 10, getTestNatStaticLocalIP("10.0.0.2", 0, 32)))} + // Test configure DNAT with unnown protocol - err = plugin.ConfigureDNat(data) + err := plugin.ConfigureDNat(data) Expect(err).To(BeNil()) Expect(plugin.IsDNatLabelRegistered(data.Label)).To(BeTrue()) id := ifplugin.GetStMappingIdentifier(data.StMappings[0]) @@ -805,10 +792,9 @@ func TestNatConfiguratorDNatStaticMappingUnknownProtocol(t *testing.T) { // Configure DNAT static mapping with load balancer func TestNatConfiguratorDNatStaticMappingLb(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44AddDelLbStaticMappingReply{}) // Data @@ -817,8 +803,9 @@ func TestNatConfiguratorDNatStaticMappingLb(t *testing.T) { getTestNatStaticMappingConfig(0, "", "10.0.0.1", 8000, nat.Protocol_TCP, getTestNatStaticLocalIP("10.0.0.2", 9000, 35), getTestNatStaticLocalIP("10.0.0.3", 9001, 65)))} + // Test configure DNAT static mapping with load balancer - err = plugin.ConfigureDNat(data) + err := plugin.ConfigureDNat(data) Expect(err).To(BeNil()) Expect(plugin.IsDNatLabelRegistered(data.Label)).To(BeTrue()) id := ifplugin.GetStMappingIdentifier(data.StMappings[0]) @@ -827,18 +814,18 @@ func TestNatConfiguratorDNatStaticMappingLb(t *testing.T) { // Configure DNAT static mapping with load balancer with invalid local IP func TestNatConfiguratorDNatStaticMappingLbInvalidLocalError(t *testing.T) { - var err error - // Setup _, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Data var stMaps []*nat.Nat44DNat_DNatConfig_StaticMapping data := &nat.Nat44DNat_DNatConfig{Label: "dNatLabel", StMappings: append(stMaps, getTestNatStaticMappingConfig(0, "", "10.0.0.1", 0, nat.Protocol_TCP, getTestNatStaticLocalIP("10.0.0.2", 0, 35), getTestNatStaticLocalIP("no-ip", 8000, 65)))} + // Test configure DNAT static mapping with load balancer with invalid local IP - err = plugin.ConfigureDNat(data) + err := plugin.ConfigureDNat(data) Expect(err).ToNot(BeNil()) Expect(plugin.IsDNatLabelRegistered(data.Label)).To(BeTrue()) id := ifplugin.GetStMappingIdentifier(data.StMappings[0]) @@ -847,18 +834,18 @@ func TestNatConfiguratorDNatStaticMappingLbInvalidLocalError(t *testing.T) { // Configure DNAT static mapping with load balancer with missing external port func TestNatConfiguratorDNatStaticMappingLbMissingExternalPortError(t *testing.T) { - var err error - // Setup _, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Data var stMaps []*nat.Nat44DNat_DNatConfig_StaticMapping data := &nat.Nat44DNat_DNatConfig{Label: "dNatLabel", StMappings: append(stMaps, getTestNatStaticMappingConfig(0, "", "10.0.0.1", 0, nat.Protocol_TCP, getTestNatStaticLocalIP("10.0.0.2", 8000, 35), getTestNatStaticLocalIP("10.0.0.3", 9000, 65)))} + // Test configure static mapping with load balancer with missing external port - err = plugin.ConfigureDNat(data) + err := plugin.ConfigureDNat(data) Expect(err).ToNot(BeNil()) Expect(plugin.IsDNatLabelRegistered(data.Label)).To(BeTrue()) id := ifplugin.GetStMappingIdentifier(data.StMappings[0]) @@ -867,18 +854,18 @@ func TestNatConfiguratorDNatStaticMappingLbMissingExternalPortError(t *testing.T // Configure DNAT static mapping with load balancer with invalid external IP func TestNatConfiguratorDNatStaticMappingLbInvalidExternalIPError(t *testing.T) { - var err error - // Setup _, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Data var stMaps []*nat.Nat44DNat_DNatConfig_StaticMapping data := &nat.Nat44DNat_DNatConfig{Label: "dNatLabel", StMappings: append(stMaps, getTestNatStaticMappingConfig(0, "", "no-ip", 8000, nat.Protocol_TCP, getTestNatStaticLocalIP("10.0.0.1", 9000, 35), getTestNatStaticLocalIP("10.0.0.2", 9001, 65)))} + // Test DNAT static mapping invalid external IP - err = plugin.ConfigureDNat(data) + err := plugin.ConfigureDNat(data) Expect(err).ToNot(BeNil()) Expect(plugin.IsDNatLabelRegistered(data.Label)).To(BeTrue()) id := ifplugin.GetStMappingIdentifier(data.StMappings[0]) @@ -887,29 +874,29 @@ func TestNatConfiguratorDNatStaticMappingLbInvalidExternalIPError(t *testing.T) // Configure NAT identity mapping func TestNatConfiguratorDNatIdentityMapping(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44AddDelIdentityMappingReply{}) // Data var idMaps []*nat.Nat44DNat_DNatConfig_IdentityMapping data := &nat.Nat44DNat_DNatConfig{Label: "dNatLabel", IdMappings: append(idMaps, getTestNatIdentityMappingConfig(0, "", "10.0.0.1", 8000, nat.Protocol_TCP))} - err = plugin.ConfigureDNat(data) + + // Test + err := plugin.ConfigureDNat(data) Expect(err).To(BeNil()) Expect(plugin.IsDNatLabelRegistered(data.Label)).To(BeTrue()) - id := ifplugin.GetIdMappingIdentifier(data.IdMappings[0]) - Expect(plugin.IsDNatLabelIdMappingRegistered(id)).To(BeTrue()) + id := ifplugin.GetIDMappingIdentifier(data.IdMappings[0]) + Expect(plugin.IsDNatLabelIDMappingRegistered(id)).To(BeTrue()) } // Configure NAT identity mapping with address interface func TestNatConfiguratorDNatIdentityMappingInterface(t *testing.T) { - var err error - // Setup ctx, connection, plugin, ifIndexes := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44AddDelIdentityMappingReply{}) // Register @@ -918,74 +905,74 @@ func TestNatConfiguratorDNatIdentityMappingInterface(t *testing.T) { var idMaps []*nat.Nat44DNat_DNatConfig_IdentityMapping data := &nat.Nat44DNat_DNatConfig{Label: "dNatLabel", IdMappings: append(idMaps, getTestNatIdentityMappingConfig(0, "if1", "", 0, nat.Protocol_TCP))} + // Test identity mapping with address interface - err = plugin.ConfigureDNat(data) + err := plugin.ConfigureDNat(data) Expect(err).To(BeNil()) Expect(plugin.IsDNatLabelRegistered(data.Label)).To(BeTrue()) - id := ifplugin.GetIdMappingIdentifier(data.IdMappings[0]) - Expect(plugin.IsDNatLabelIdMappingRegistered(id)).To(BeTrue()) + id := ifplugin.GetIDMappingIdentifier(data.IdMappings[0]) + Expect(plugin.IsDNatLabelIDMappingRegistered(id)).To(BeTrue()) } // Configure NAT identity mapping with address interface while interface is not registered func TestNatConfiguratorDNatIdentityMappingMissingInterfaceError(t *testing.T) { - var err error - // Setup _, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Data var idMaps []*nat.Nat44DNat_DNatConfig_IdentityMapping data := &nat.Nat44DNat_DNatConfig{Label: "dNatLabel", IdMappings: append(idMaps, getTestNatIdentityMappingConfig(0, "if1", "", 0, nat.Protocol_TCP))} + // Test identity mapping with address interface while interface is not registered - err = plugin.ConfigureDNat(data) + err := plugin.ConfigureDNat(data) Expect(err).ToNot(BeNil()) Expect(plugin.IsDNatLabelRegistered(data.Label)).To(BeTrue()) - id := ifplugin.GetIdMappingIdentifier(data.IdMappings[0]) - Expect(plugin.IsDNatLabelIdMappingRegistered(id)).To(BeFalse()) + id := ifplugin.GetIDMappingIdentifier(data.IdMappings[0]) + Expect(plugin.IsDNatLabelIDMappingRegistered(id)).To(BeFalse()) } // Create NAT identity mapping with invalid IP address func TestNatConfiguratorDNatIdentityMappingInvalidIPError(t *testing.T) { - var err error - // Setup _, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Data var idMaps []*nat.Nat44DNat_DNatConfig_IdentityMapping data := &nat.Nat44DNat_DNatConfig{Label: "dNatLabel", IdMappings: append(idMaps, getTestNatIdentityMappingConfig(0, "", "no-ip", 9000, nat.Protocol_TCP))} + // Test identity mapping with invalid IP - err = plugin.ConfigureDNat(data) + err := plugin.ConfigureDNat(data) Expect(err).ToNot(BeNil()) Expect(plugin.IsDNatLabelRegistered(data.Label)).To(BeTrue()) - id := ifplugin.GetIdMappingIdentifier(data.IdMappings[0]) - Expect(plugin.IsDNatLabelIdMappingRegistered(id)).To(BeFalse()) + id := ifplugin.GetIDMappingIdentifier(data.IdMappings[0]) + Expect(plugin.IsDNatLabelIDMappingRegistered(id)).To(BeFalse()) } // Create identity mapping without IP address and interface set func TestNatConfiguratorDNatIdentityMappingNoInterfaceAndIPError(t *testing.T) { - var err error - // Setup _, connection, plugin, _ := natTestSetup(t) + defer natTestTeardown(connection, plugin) // Data var idMaps []*nat.Nat44DNat_DNatConfig_IdentityMapping data := &nat.Nat44DNat_DNatConfig{Label: "dNatLabel", IdMappings: append(idMaps, getTestNatIdentityMappingConfig(0, "", "", 8000, nat.Protocol_TCP))} + // Test identity mapping without interface and IP - err = plugin.ConfigureDNat(data) + err := plugin.ConfigureDNat(data) Expect(err).ToNot(BeNil()) Expect(plugin.IsDNatLabelRegistered(data.Label)).To(BeTrue()) - id := ifplugin.GetIdMappingIdentifier(data.IdMappings[0]) - Expect(plugin.IsDNatLabelIdMappingRegistered(id)).To(BeFalse()) + id := ifplugin.GetIDMappingIdentifier(data.IdMappings[0]) + Expect(plugin.IsDNatLabelIDMappingRegistered(id)).To(BeFalse()) } // Configure and modify static and identity mappings func TestNatConfiguratorDNatModify(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44AddDelStaticMappingReply{}) // Configure ctx.MockVpp.MockReply(&nat_api.Nat44AddDelLbStaticMappingReply{}) @@ -1012,16 +999,17 @@ func TestNatConfiguratorDNatModify(t *testing.T) { getTestNatStaticLocalIP("10.0.0.4", 9000, 0))), IdMappings: append(idMaps, getTestNatIdentityMappingConfig(0, "", "10.0.0.3", 9000, 0))} + // Test configure static and identity mappings - err = plugin.ConfigureDNat(oldData) + err := plugin.ConfigureDNat(oldData) Expect(err).To(BeNil()) Expect(plugin.IsDNatLabelRegistered(oldData.Label)).To(BeTrue()) id := ifplugin.GetStMappingIdentifier(oldData.StMappings[0]) Expect(plugin.IsDNatLabelStMappingRegistered(id)).To(BeTrue()) id = ifplugin.GetStMappingIdentifier(oldData.StMappings[1]) Expect(plugin.IsDNatLabelStMappingRegistered(id)).To(BeTrue()) - id = ifplugin.GetIdMappingIdentifier(oldData.IdMappings[0]) - Expect(plugin.IsDNatLabelIdMappingRegistered(id)).To(BeTrue()) + id = ifplugin.GetIDMappingIdentifier(oldData.IdMappings[0]) + Expect(plugin.IsDNatLabelIDMappingRegistered(id)).To(BeTrue()) // Test modify static and identity mapping err = plugin.ModifyDNat(oldData, newData) Expect(err).To(BeNil()) @@ -1029,16 +1017,15 @@ func TestNatConfiguratorDNatModify(t *testing.T) { Expect(plugin.IsDNatLabelStMappingRegistered(id)).To(BeTrue()) id = ifplugin.GetStMappingIdentifier(newData.StMappings[1]) Expect(plugin.IsDNatLabelStMappingRegistered(id)).To(BeTrue()) - id = ifplugin.GetIdMappingIdentifier(newData.IdMappings[0]) - Expect(plugin.IsDNatLabelIdMappingRegistered(id)).To(BeTrue()) + id = ifplugin.GetIDMappingIdentifier(newData.IdMappings[0]) + Expect(plugin.IsDNatLabelIDMappingRegistered(id)).To(BeTrue()) } // Configure and modify static and identity mappings with errors func TestNatConfiguratorDNatModifyErrors(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44AddDelStaticMappingReply{}) // Configure ctx.MockVpp.MockReply(&nat_api.Nat44AddDelIdentityMappingReply{}) @@ -1067,8 +1054,9 @@ func TestNatConfiguratorDNatModifyErrors(t *testing.T) { getTestNatStaticLocalIP("10.0.0.3", 0, 65))), IdMappings: append(idMaps, getTestNatIdentityMappingConfig(0, "", "10.0.0.3", 9000, 0))} + // Test configure static and identity mappings - err = plugin.ConfigureDNat(oldData) + err := plugin.ConfigureDNat(oldData) Expect(err).To(BeNil()) // Test modify static and identity mapping err = plugin.ModifyDNat(oldData, newData) @@ -1077,10 +1065,9 @@ func TestNatConfiguratorDNatModifyErrors(t *testing.T) { // Configure and delete static mapping func TestNatConfiguratorDeleteDNatStaticMapping(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44AddDelStaticMappingReply{}) // Configure ctx.MockVpp.MockReply(&nat_api.Nat44AddDelStaticMappingReply{}) // Delete @@ -1089,8 +1076,9 @@ func TestNatConfiguratorDeleteDNatStaticMapping(t *testing.T) { data := &nat.Nat44DNat_DNatConfig{Label: "dNatLabel", StMappings: append(stMaps, getTestNatStaticMappingConfig(0, "", "10.0.0.1", 8000, nat.Protocol_TCP, getTestNatStaticLocalIP("10.0.0.1", 9000, 35)))} + // Test configure DNAT static mapping - err = plugin.ConfigureDNat(data) + err := plugin.ConfigureDNat(data) Expect(err).To(BeNil()) Expect(plugin.IsDNatLabelRegistered(data.Label)).To(BeTrue()) id := ifplugin.GetStMappingIdentifier(data.StMappings[0]) @@ -1105,26 +1093,25 @@ func TestNatConfiguratorDeleteDNatStaticMapping(t *testing.T) { // Delete static mapping with invalid IP func TestNatConfiguratorDeleteDNatStaticMappingInvalidIPError(t *testing.T) { - var err error - // Setup _, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Data var stMaps []*nat.Nat44DNat_DNatConfig_StaticMapping data := &nat.Nat44DNat_DNatConfig{Label: "dNatLabel", StMappings: append(stMaps, getTestNatStaticMappingConfig(0, "", "no-ip", 8000, nat.Protocol_TCP, getTestNatStaticLocalIP("10.0.0.1", 9000, 35)))} + // Test delete static mapping with invalid interface - err = plugin.DeleteDNat(data) + err := plugin.DeleteDNat(data) Expect(err).ToNot(BeNil()) } // Configure and delete static mapping with load balancer func TestNatConfiguratorDeleteDNatStaticMappingLb(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44AddDelLbStaticMappingReply{}) // Configure ctx.MockVpp.MockReply(&nat_api.Nat44AddDelLbStaticMappingReply{}) // Delete @@ -1134,8 +1121,9 @@ func TestNatConfiguratorDeleteDNatStaticMappingLb(t *testing.T) { getTestNatStaticMappingConfig(0, "", "10.0.0.1", 8000, nat.Protocol_TCP, getTestNatStaticLocalIP("10.0.0.2", 9000, 35), getTestNatStaticLocalIP("10.0.0.3", 9001, 65)))} + // Test configure static mapping with load balancer - err = plugin.ConfigureDNat(data) + err := plugin.ConfigureDNat(data) Expect(err).To(BeNil()) Expect(plugin.IsDNatLabelRegistered(data.Label)).To(BeTrue()) id := ifplugin.GetStMappingIdentifier(data.StMappings[0]) @@ -1150,27 +1138,26 @@ func TestNatConfiguratorDeleteDNatStaticMappingLb(t *testing.T) { // Delete static mapping with load ballancer with invalid IP address func TestNatConfiguratorDeleteDNatStaticMappingLbInvalidIPError(t *testing.T) { - var err error - // Setup _, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Data var stMaps []*nat.Nat44DNat_DNatConfig_StaticMapping data := &nat.Nat44DNat_DNatConfig{Label: "test-dnat", StMappings: append(stMaps, getTestNatStaticMappingConfig(0, "", "invalid-ip", 8000, nat.Protocol_TCP, getTestNatStaticLocalIP("10.0.0.2", 9000, 35), getTestNatStaticLocalIP("10.0.0.3", 9001, 65)))} + // Test delete static mapping with load balancer with invalid IP - err = plugin.DeleteDNat(data) + err := plugin.DeleteDNat(data) Expect(err).ToNot(BeNil()) } // Configure and delete NAT identity mapping func TestNatConfiguratorDNatDeleteIdentityMapping(t *testing.T) { - var err error - // Setup ctx, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Reply set ctx.MockVpp.MockReply(&nat_api.Nat44AddDelIdentityMappingReply{}) // Configure ctx.MockVpp.MockReply(&nat_api.Nat44AddDelIdentityMappingReply{}) // Delete @@ -1178,32 +1165,33 @@ func TestNatConfiguratorDNatDeleteIdentityMapping(t *testing.T) { var idMaps []*nat.Nat44DNat_DNatConfig_IdentityMapping data := &nat.Nat44DNat_DNatConfig{Label: "dNatLabel", IdMappings: append(idMaps, getTestNatIdentityMappingConfig(0, "", "10.0.0.1", 9000, nat.Protocol_TCP))} + // Test configure identity mapping - err = plugin.ConfigureDNat(data) + err := plugin.ConfigureDNat(data) Expect(err).To(BeNil()) Expect(plugin.IsDNatLabelRegistered(data.Label)).To(BeTrue()) - id := ifplugin.GetIdMappingIdentifier(data.IdMappings[0]) - Expect(plugin.IsDNatLabelIdMappingRegistered(id)).To(BeTrue()) + id := ifplugin.GetIDMappingIdentifier(data.IdMappings[0]) + Expect(plugin.IsDNatLabelIDMappingRegistered(id)).To(BeTrue()) // Test delete identity mapping err = plugin.DeleteDNat(data) Expect(err).To(BeNil()) Expect(plugin.IsDNatLabelRegistered(data.Label)).To(BeFalse()) - id = ifplugin.GetIdMappingIdentifier(data.IdMappings[0]) - Expect(plugin.IsDNatLabelIdMappingRegistered(id)).To(BeFalse()) + id = ifplugin.GetIDMappingIdentifier(data.IdMappings[0]) + Expect(plugin.IsDNatLabelIDMappingRegistered(id)).To(BeFalse()) } // Delete NAT identity mapping without ip address set func TestNatConfiguratorDNatDeleteIdentityMappingNoInterfaceAndIP(t *testing.T) { - var err error - // Setup _, connection, plugin, _ := natTestSetup(t) defer natTestTeardown(connection, plugin) + // Data var idMaps []*nat.Nat44DNat_DNatConfig_IdentityMapping data := &nat.Nat44DNat_DNatConfig{Label: "test-dnat", IdMappings: append(idMaps, getTestNatIdentityMappingConfig(0, "", "", 8000, nat.Protocol_TCP))} + // Test delete identity mapping without interface IP - err = plugin.DeleteDNat(data) + err := plugin.DeleteDNat(data) Expect(err).ToNot(BeNil()) } @@ -1211,19 +1199,23 @@ func TestNatConfiguratorDNatDeleteIdentityMappingNoInterfaceAndIP(t *testing.T) func natTestSetup(t *testing.T) (*vppcallmock.TestCtx, *core.Connection, *ifplugin.NatConfigurator, ifaceidx.SwIfIndexRW) { RegisterTestingT(t) + ctx := &vppcallmock.TestCtx{ MockVpp: &mock.VppAdapter{}, } connection, err := core.Connect(ctx.MockVpp) Expect(err).ShouldNot(HaveOccurred()) + // Logger - log := logging.ForPlugin("test-log", logrus.NewLogRegistry()) + log := logging.ForPlugin("test-log") log.SetLevel(logging.DebugLevel) + // Interface indices swIfIndices := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(log, "nat", nil)) + // Configurator plugin := &ifplugin.NatConfigurator{} - err = plugin.Init(log, connection, swIfIndices, false) + err = plugin.Init(log, connection, swIfIndices, true) Expect(err).To(BeNil()) return ctx, connection, plugin, swIfIndices @@ -1233,6 +1225,7 @@ func natTestTeardown(connection *core.Connection, plugin *ifplugin.NatConfigurat connection.Disconnect() err := plugin.Close() Expect(err).To(BeNil()) + logging.DefaultRegistry.ClearRegistry() } /* NAT Test Data */ @@ -1260,7 +1253,6 @@ func getTestNatAddressPoolConfig(first, last string, vrf uint32, twn bool) *nat. func getTestNatStaticMappingConfig(vrf uint32, ifName, externalIP string, externalPort uint32, proto nat.Protocol, locals ...*nat.Nat44DNat_DNatConfig_StaticMapping_LocalIP) *nat.Nat44DNat_DNatConfig_StaticMapping { return &nat.Nat44DNat_DNatConfig_StaticMapping{ - VrfId: vrf, ExternalInterface: ifName, ExternalIp: externalIP, ExternalPort: externalPort, diff --git a/plugins/vpp/ifplugin/stn_config.go b/plugins/vpp/ifplugin/stn_config.go index 803f877b9d..13b2f0d2ff 100644 --- a/plugins/vpp/ifplugin/stn_config.go +++ b/plugins/vpp/ifplugin/stn_config.go @@ -28,10 +28,8 @@ import ( "github.com/ligato/vpp-agent/idxvpp" "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/govppmux" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/stn" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppdump" modelStn "github.com/ligato/vpp-agent/plugins/vpp/model/stn" ) @@ -48,6 +46,8 @@ type StnConfigurator struct { unstoredIndexSeq uint32 // VPP vppChan govppapi.Channel + // VPP API handler + stnHandler vppcalls.StnVppAPI // Stopwatch stopwatch *measure.Stopwatch } @@ -71,6 +71,11 @@ func (plugin *StnConfigurator) Init(logger logging.PluginLogger, goVppMux govppm plugin.log = logger.NewLogger("-stn-conf") plugin.log.Debug("Initializing STN configurator") + // Configurator-wide stopwatch instance + if enableStopwatch { + plugin.stopwatch = measure.NewStopwatch("STN-configurator", plugin.log) + } + // Init VPP API channel plugin.vppChan, err = goVppMux.NewAPIChannel() if err != nil { @@ -83,15 +88,8 @@ func (plugin *StnConfigurator) Init(logger logging.PluginLogger, goVppMux govppm plugin.unstoredIndexes = nametoidx.NewNameToIdx(plugin.log, "stn-unstored-indexes", nil) plugin.allIndexesSeq, plugin.unstoredIndexSeq = 1, 1 - // Stopwatch - if enableStopwatch { - plugin.stopwatch = measure.NewStopwatch("stnConfigurator", plugin.log) - } - - // Check VPP message compatibility - if err := vppcalls.CheckMsgCompatibilityForStn(plugin.vppChan); err != nil { - return err - } + // VPP API handler + plugin.stnHandler = vppcalls.NewStnVppHandler(plugin.vppChan, plugin.ifIndexes, plugin.log, plugin.stopwatch) return nil } @@ -137,7 +135,7 @@ func (plugin *StnConfigurator) Add(rule *modelStn.STN_Rule) error { } else { plugin.log.Debugf("adding STN rule: %+v", rule) // Create and register new stn - if err := vppcalls.AddStnRule(stnRule.IfaceIdx, &stnRule.IPAddress, plugin.vppChan, plugin.stopwatch); err != nil { + if err := plugin.stnHandler.AddStnRule(stnRule.IfaceIdx, &stnRule.IPAddress); err != nil { return err } plugin.indexSTNRule(rule, false) @@ -165,7 +163,7 @@ func (plugin *StnConfigurator) Delete(rule *modelStn.STN_Rule) error { plugin.log.Debugf("STN rule: %+v was stored in VPP, trying to delete it. %+v", stnRule) // Remove rule - if err := vppcalls.DelStnRule(stnRule.IfaceIdx, &stnRule.IPAddress, plugin.vppChan, plugin.stopwatch); err != nil { + if err := plugin.stnHandler.DelStnRule(stnRule.IfaceIdx, &stnRule.IPAddress); err != nil { return err } @@ -200,13 +198,13 @@ func (plugin *StnConfigurator) Modify(ruleOld *modelStn.STN_Rule, ruleNew *model } // Dump STN rules configured on the VPP -func (plugin *StnConfigurator) Dump() ([]*stn.StnRulesDetails, error) { - rules, err := vppdump.DumpStnRules(plugin.vppChan, plugin.stopwatch) +func (plugin *StnConfigurator) Dump() (*vppcalls.StnDetails, error) { + stnDetails, err := plugin.stnHandler.DumpStnRules() if err != nil { return nil, err } - plugin.log.Debugf("found %d configured STN rules", len(rules)) - return rules, nil + plugin.log.Debugf("found %d configured STN rules", len(stnDetails.Rules)) + return stnDetails, nil } // Close GOVPP channel. diff --git a/plugins/vpp/ifplugin/stn_config_test.go b/plugins/vpp/ifplugin/stn_config_test.go index 265dfa9dcc..495fd06aa7 100644 --- a/plugins/vpp/ifplugin/stn_config_test.go +++ b/plugins/vpp/ifplugin/stn_config_test.go @@ -21,7 +21,6 @@ import ( "git.fd.io/govpp.git/adapter/mock" "git.fd.io/govpp.git/core" "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/idxvpp/nametoidx" stn_api "github.com/ligato/vpp-agent/plugins/vpp/binapi/stn" "github.com/ligato/vpp-agent/plugins/vpp/binapi/vpe" @@ -32,39 +31,22 @@ import ( . "github.com/onsi/gomega" ) -/* STN configurator init and close */ - -// Test init function -func TestStnConfiguratorInit(t *testing.T) { - RegisterTestingT(t) - connection, _ := core.Connect(&mock.VppAdapter{}) - defer connection.Disconnect() - - plugin := &ifplugin.StnConfigurator{} - err := plugin.Init(logging.ForPlugin("test-log", logrus.NewLogRegistry()), connection, - nil, true) - Expect(err).To(BeNil()) - - err = plugin.Close() - Expect(err).To(BeNil()) -} - /* STN Test Cases */ // Add STN rule func TestStnConfiguratorAddRule(t *testing.T) { - var err error - // Setup ctx, conn, plugin, swIfIndices := stnTestSetup(t) defer stnTestTeardown(conn, plugin) + // Reply set ctx.MockVpp.MockReply(&stn_api.StnAddDelRuleReply{}) // Data data := getTestStnRule("rule1", "if1", "10.0.0.1") // Register swIfIndices.RegisterName("if1", 1, nil) + // Test add stn rule - err = plugin.Add(data) + err := plugin.Add(data) Expect(err).To(BeNil()) Expect(plugin.IndexExistsFor(ifplugin.StnIdentifier("if1"))).To(BeTrue()) Expect(plugin.UnstoredIndexExistsFor(ifplugin.StnIdentifier("if1"))).To(BeFalse()) @@ -72,18 +54,18 @@ func TestStnConfiguratorAddRule(t *testing.T) { // Add STN rule with full IP (address/mask) func TestStnConfiguratorAddRuleFullIP(t *testing.T) { - var err error - // Setup ctx, conn, plugin, swIfIndices := stnTestSetup(t) defer stnTestTeardown(conn, plugin) + // Reply set ctx.MockVpp.MockReply(&stn_api.StnAddDelRuleReply{}) // Data data := getTestStnRule("rule1", "if1", "10.0.0.1/24") // Register swIfIndices.RegisterName("if1", 1, nil) + // Test add stn rule with full IP - err = plugin.Add(data) + err := plugin.Add(data) Expect(err).To(BeNil()) Expect(plugin.IndexExistsFor(ifplugin.StnIdentifier("if1"))).To(BeTrue()) Expect(plugin.UnstoredIndexExistsFor(ifplugin.StnIdentifier("if1"))).To(BeFalse()) @@ -91,16 +73,16 @@ func TestStnConfiguratorAddRuleFullIP(t *testing.T) { // Add STN rule while interface is missing func TestStnConfiguratorAddRuleMissingInterface(t *testing.T) { - var err error - // Setup ctx, conn, plugin, _ := stnTestSetup(t) defer stnTestTeardown(conn, plugin) + // Reply set ctx.MockVpp.MockReply(&stn_api.StnAddDelRuleReply{}) // Data data := getTestStnRule("rule1", "if1", "10.0.0.1") + // Test add rule while interface is not registered - err = plugin.Add(data) + err := plugin.Add(data) Expect(err).To(BeNil()) Expect(plugin.IndexExistsFor(ifplugin.StnIdentifier("if1"))).To(BeTrue()) Expect(plugin.UnstoredIndexExistsFor(ifplugin.StnIdentifier("if1"))).To(BeTrue()) @@ -108,10 +90,9 @@ func TestStnConfiguratorAddRuleMissingInterface(t *testing.T) { // Add STN rule while non-zero return value is get func TestStnConfiguratorAddRuleRetvalError(t *testing.T) { - var err error - // Setup ctx, conn, plugin, swIfIndices := stnTestSetup(t) defer stnTestTeardown(conn, plugin) + // Reply set ctx.MockVpp.MockReply(&stn_api.StnAddDelRuleReply{ Retval: 1, @@ -120,8 +101,9 @@ func TestStnConfiguratorAddRuleRetvalError(t *testing.T) { data := getTestStnRule("rule1", "if1", "10.0.0.1") // Register swIfIndices.RegisterName("if1", 1, nil) + // Test add rule returns -1 - err = plugin.Add(data) + err := plugin.Add(data) Expect(err).ToNot(BeNil()) Expect(plugin.IndexExistsFor(ifplugin.StnIdentifier("if1"))).To(BeFalse()) Expect(plugin.UnstoredIndexExistsFor(ifplugin.StnIdentifier("if1"))).To(BeFalse()) @@ -129,29 +111,28 @@ func TestStnConfiguratorAddRuleRetvalError(t *testing.T) { // Add nil STN rule func TestStnConfiguratorAddRuleNoInput(t *testing.T) { - var err error - // Setup _, conn, plugin, _ := stnTestSetup(t) defer stnTestTeardown(conn, plugin) + // Test add empty rule - err = plugin.Add(nil) + err := plugin.Add(nil) Expect(err).ToNot(BeNil()) } // Add STN rule without interface func TestStnConfiguratorAddRuleNoInterface(t *testing.T) { - var err error - // Setup ctx, conn, plugin, swIfIndices := stnTestSetup(t) defer stnTestTeardown(conn, plugin) + // Reply set ctx.MockVpp.MockReply(&stn_api.StnAddDelRuleReply{}) // Data data := getTestStnRule("rule1", "", "10.0.0.1") // Register swIfIndices.RegisterName("if1", 1, nil) + // Test add rule with invalid interface data - err = plugin.Add(data) + err := plugin.Add(data) Expect(err).ToNot(BeNil()) Expect(plugin.IndexExistsFor(ifplugin.StnIdentifier("if1"))).To(BeFalse()) Expect(plugin.UnstoredIndexExistsFor(ifplugin.StnIdentifier("if1"))).To(BeFalse()) @@ -159,18 +140,18 @@ func TestStnConfiguratorAddRuleNoInterface(t *testing.T) { // Add STN rule without IP func TestStnConfiguratorAddRuleNoIP(t *testing.T) { - var err error - // Setup ctx, conn, plugin, swIfIndices := stnTestSetup(t) defer stnTestTeardown(conn, plugin) + // Reply set ctx.MockVpp.MockReply(&stn_api.StnAddDelRuleReply{}) // Data data := getTestStnRule("rule1", "if1", "") // Register swIfIndices.RegisterName("if1", 1, nil) + // Test add rule with missing IP data - err = plugin.Add(data) + err := plugin.Add(data) Expect(err).ToNot(BeNil()) Expect(plugin.IndexExistsFor(ifplugin.StnIdentifier("if1"))).To(BeFalse()) Expect(plugin.UnstoredIndexExistsFor(ifplugin.StnIdentifier("if1"))).To(BeFalse()) @@ -178,10 +159,9 @@ func TestStnConfiguratorAddRuleNoIP(t *testing.T) { // Add STN rule with invalid IP func TestStnConfiguratorAddRuleInvalidIP(t *testing.T) { - var err error - // Setup ctx, conn, plugin, swIfIndices := stnTestSetup(t) defer stnTestTeardown(conn, plugin) + // Reply set ctx.MockVpp.MockReply(&stn_api.StnAddDelRuleReply{}) ctx.MockVpp.MockReply(&stn_api.StnAddDelRuleReply{}) @@ -189,8 +169,9 @@ func TestStnConfiguratorAddRuleInvalidIP(t *testing.T) { data := getTestStnRule("rule1", "if1", "no-ip") // Register swIfIndices.RegisterName("if1", 1, nil) + // Test add rule with invalid IP data - err = plugin.Add(data) + err := plugin.Add(data) Expect(err).ToNot(BeNil()) Expect(plugin.IndexExistsFor(ifplugin.StnIdentifier("if1"))).To(BeFalse()) Expect(plugin.UnstoredIndexExistsFor(ifplugin.StnIdentifier("if1"))).To(BeFalse()) @@ -198,10 +179,9 @@ func TestStnConfiguratorAddRuleInvalidIP(t *testing.T) { // Delete STN rule func TestStnConfiguratorDeleteRule(t *testing.T) { - var err error - // Setup ctx, conn, plugin, swIfIndices := stnTestSetup(t) defer stnTestTeardown(conn, plugin) + // Reply set ctx.MockVpp.MockReply(&stn_api.StnAddDelRuleReply{}) ctx.MockVpp.MockReply(&stn_api.StnAddDelRuleReply{}) @@ -209,8 +189,9 @@ func TestStnConfiguratorDeleteRule(t *testing.T) { data := getTestStnRule("rule1", "if1", "10.0.0.1") // Register swIfIndices.RegisterName("if1", 1, nil) + // Test delete stn rule - err = plugin.Add(data) + err := plugin.Add(data) Expect(err).To(BeNil()) err = plugin.Delete(data) Expect(err).To(BeNil()) @@ -220,14 +201,14 @@ func TestStnConfiguratorDeleteRule(t *testing.T) { // Delete STN rule with missing interface func TestStnConfiguratorDeleteRuleMissingInterface(t *testing.T) { - var err error - // Setup _, conn, plugin, _ := stnTestSetup(t) defer stnTestTeardown(conn, plugin) + // Data data := getTestStnRule("rule1", "if1", "10.0.0.1") + // Test delete rule while interface is not registered - err = plugin.Add(data) + err := plugin.Add(data) Expect(err).To(BeNil()) err = plugin.Delete(data) Expect(err).To(BeNil()) @@ -237,10 +218,9 @@ func TestStnConfiguratorDeleteRuleMissingInterface(t *testing.T) { // Delete STN rule non-zero return value func TestStnConfiguratorDeleteRuleRetvalError(t *testing.T) { - var err error - // Setup ctx, conn, plugin, swIfIndices := stnTestSetup(t) defer stnTestTeardown(conn, plugin) + // Reply set ctx.MockVpp.MockReply(&stn_api.StnAddDelRuleReply{}) ctx.MockVpp.MockReply(&stn_api.StnAddDelRuleReply{ @@ -250,8 +230,9 @@ func TestStnConfiguratorDeleteRuleRetvalError(t *testing.T) { data := getTestStnRule("rule1", "if1", "10.0.0.1") // Register swIfIndices.RegisterName("if1", 1, nil) + // Test delete rule with return value -1 - err = plugin.Add(data) + err := plugin.Add(data) Expect(err).To(BeNil()) err = plugin.Delete(data) Expect(err).ToNot(BeNil()) @@ -261,18 +242,18 @@ func TestStnConfiguratorDeleteRuleRetvalError(t *testing.T) { // Delete STN rule failed check func TestStnConfiguratorDeleteRuleCheckError(t *testing.T) { - var err error - // Setup ctx, conn, plugin, swIfIndices := stnTestSetup(t) defer stnTestTeardown(conn, plugin) + // Reply set ctx.MockVpp.MockReply(&stn_api.StnAddDelRuleReply{}) // Data data := getTestStnRule("rule1", "if1", "no-ip") // Register swIfIndices.RegisterName("if1", 1, nil) - err = plugin.Add(data) + err := plugin.Add(data) Expect(err).ToNot(BeNil()) + // Test delete rule with error check err = plugin.Delete(data) Expect(err).ToNot(BeNil()) @@ -282,23 +263,22 @@ func TestStnConfiguratorDeleteRuleCheckError(t *testing.T) { // Delete STN rule without interface func TestStnConfiguratorDeleteRuleNoInterface(t *testing.T) { - var err error - // Setup _, conn, plugin, _ := stnTestSetup(t) defer stnTestTeardown(conn, plugin) + // Data data := getTestStnRule("rule1", "", "10.0.0.1") + // Test delete rule - err = plugin.Delete(data) + err := plugin.Delete(data) Expect(err).ToNot(BeNil()) } // Modify STN rule func TestStnConfiguratorModifyRule(t *testing.T) { - var err error - // Setup ctx, conn, plugin, swIfIndices := stnTestSetup(t) defer stnTestTeardown(conn, plugin) + // Reply set ctx.MockVpp.MockReply(&stn_api.StnAddDelRuleReply{}) ctx.MockVpp.MockReply(&stn_api.StnAddDelRuleReply{}) @@ -308,8 +288,9 @@ func TestStnConfiguratorModifyRule(t *testing.T) { newData := getTestStnRule("rule1", "if1", "10.0.0.2") // Register swIfIndices.RegisterName("if1", 1, nil) + // Test modify rule - err = plugin.Add(oldData) + err := plugin.Add(oldData) Expect(err).To(BeNil()) err = plugin.Modify(oldData, newData) Expect(err).To(BeNil()) @@ -318,17 +299,17 @@ func TestStnConfiguratorModifyRule(t *testing.T) { // Modify STN rule nil check func TestStnConfiguratorModifyRuleNilCheck(t *testing.T) { - var err error - // Setup _, conn, plugin, swIfIndices := stnTestSetup(t) defer stnTestTeardown(conn, plugin) + // Data oldData := getTestStnRule("rule1", "if1", "10.0.0.1") newData := getTestStnRule("rule1", "if1", "10.0.0.2") // Register swIfIndices.RegisterName("if1", 1, nil) + // Test nil old rule - err = plugin.Modify(nil, newData) + err := plugin.Modify(nil, newData) Expect(err).ToNot(BeNil()) // Test nil new rule err = plugin.Modify(oldData, nil) @@ -337,46 +318,47 @@ func TestStnConfiguratorModifyRuleNilCheck(t *testing.T) { // Dump STN rule func TestStnConfiguratorDumpRule(t *testing.T) { - var err error - // Setup ctx, conn, plugin, swIfIndices := stnTestSetup(t) defer stnTestTeardown(conn, plugin) + // Reply set ctx.MockVpp.MockReply(&stn_api.StnRulesDetails{ IsIP4: 1, - IPAddress: net.ParseIP("10.0.0.1"), + IPAddress: net.ParseIP("10.0.0.1").To4(), SwIfIndex: 1, }) ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) // Register swIfIndices.RegisterName("if1", 1, nil) + // Test rule dump data, err := plugin.Dump() Expect(err).To(BeNil()) - Expect(data).ToNot(BeNil()) - Expect(data).To(HaveLen(1)) - Expect(data[0].SwIfIndex).To(BeEquivalentTo(1)) - Expect(data[0].IPAddress).To(BeEquivalentTo(net.ParseIP("10.0.0.1"))) - Expect(data[0].IsIP4).To(BeEquivalentTo(1)) + Expect(data.Rules).ToNot(BeNil()) + Expect(data.Rules).To(HaveLen(1)) + Expect(data.Rules[0].Interface).To(BeEquivalentTo("if1")) + Expect(data.Rules[0].IpAddress).To(BeEquivalentTo("10.0.0.1")) + Expect(data.Meta).ToNot(BeNil()) + Expect(data.Meta.IfNameToIdx[1]).To(BeEquivalentTo("if1")) } // Resolve new interface for STN func TestStnConfiguratorResolveCreatedInterface(t *testing.T) { - var err error - // Setup ctx, conn, plugin, swIfIndices := stnTestSetup(t) defer stnTestTeardown(conn, plugin) + // Reply set ctx.MockVpp.MockReply(&stn_api.StnAddDelRuleReply{}) // Data - data := getTestStnRule("rule1", "if1", "10.0.0.1") + rule := getTestStnRule("rule1", "if1", "10.0.0.1") // Test add rule while interface is not registered - err = plugin.Add(data) + err := plugin.Add(rule) Expect(err).To(BeNil()) Expect(plugin.IndexExistsFor(ifplugin.StnIdentifier("if1"))).To(BeTrue()) Expect(plugin.UnstoredIndexExistsFor(ifplugin.StnIdentifier("if1"))).To(BeTrue()) // Register swIfIndices.RegisterName("if1", 1, nil) + // Test resolving of new interface plugin.ResolveCreatedInterface("if1") Expect(plugin.IndexExistsFor(ifplugin.StnIdentifier("if1"))).To(BeTrue()) @@ -385,10 +367,9 @@ func TestStnConfiguratorResolveCreatedInterface(t *testing.T) { // Resolve removed interface for STN func TestStnConfiguratorResolveDeletedInterface(t *testing.T) { - var err error - // Setup ctx, conn, plugin, swIfIndices := stnTestSetup(t) defer stnTestTeardown(conn, plugin) + // Reply set ctx.MockVpp.MockReply(&stn_api.StnAddDelRuleReply{}) ctx.MockVpp.MockReply(&stn_api.StnAddDelRuleReply{}) @@ -396,8 +377,9 @@ func TestStnConfiguratorResolveDeletedInterface(t *testing.T) { data := getTestStnRule("rule1", "if1", "10.0.0.1") // Register swIfIndices.RegisterName("if1", 1, nil) - err = plugin.Add(data) + err := plugin.Add(data) Expect(err).To(BeNil()) + // Test resolving of deleted interface swIfIndices.UnregisterName("if1") plugin.ResolveDeletedInterface("if1") @@ -415,13 +397,13 @@ func stnTestSetup(t *testing.T) (*vppcallmock.TestCtx, *core.Connection, *ifplug connection, err := core.Connect(ctx.MockVpp) Expect(err).ShouldNot(HaveOccurred()) // Logger - log := logging.ForPlugin("test-log", logrus.NewLogRegistry()) + log := logging.ForPlugin("test-log") log.SetLevel(logging.DebugLevel) // Interface indices swIfIndices := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(log, "stn", nil)) // Configurator plugin := &ifplugin.StnConfigurator{} - err = plugin.Init(log, connection, swIfIndices, false) + err = plugin.Init(log, connection, swIfIndices, true) Expect(err).To(BeNil()) return ctx, connection, plugin, swIfIndices @@ -431,6 +413,7 @@ func stnTestTeardown(connection *core.Connection, plugin *ifplugin.StnConfigurat connection.Disconnect() err := plugin.Close() Expect(err).To(BeNil()) + logging.DefaultRegistry.ClearRegistry() } /* STN Test Data */ diff --git a/plugins/vpp/ifplugin/vppcalls/admin_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/admin_vppcalls.go index 869db0162d..439f513256 100644 --- a/plugins/vpp/ifplugin/vppcalls/admin_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/admin_vppcalls.go @@ -18,49 +18,52 @@ import ( "fmt" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" ) -func interfaceSetFlags(ifIdx uint32, adminUp bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +// InterfaceAdminDown implements interface handler. +func (h *IfVppHandler) InterfaceAdminDown(ifIdx uint32) error { + return h.interfaceSetFlags(ifIdx, false) +} + +// InterfaceAdminUp implements interface handler. +func (h *IfVppHandler) InterfaceAdminUp(ifIdx uint32) error { + return h.interfaceSetFlags(ifIdx, true) +} + +// SetInterfaceTag implements interface handler. +func (h *IfVppHandler) SetInterfaceTag(tag string, ifIdx uint32) error { + return h.handleInterfaceTag(tag, ifIdx, true) +} + +// RemoveInterfaceTag implements interface handler. +func (h *IfVppHandler) RemoveInterfaceTag(tag string, ifIdx uint32) error { + return h.handleInterfaceTag(tag, ifIdx, false) +} + +func (h *IfVppHandler) interfaceSetFlags(ifIdx uint32, adminUp bool) error { defer func(t time.Time) { - stopwatch.TimeLog(interfaces.SwInterfaceSetFlagsReply{}).LogTimeEntry(time.Since(t)) + h.stopwatch.TimeLog(interfaces.SwInterfaceSetFlagsReply{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &interfaces.SwInterfaceSetFlags{ - SwIfIndex: ifIdx, - } - if adminUp { - req.AdminUpDown = 1 - } else { - req.AdminUpDown = 0 + SwIfIndex: ifIdx, + AdminUpDown: boolToUint(adminUp), } - reply := &interfaces.SwInterfaceSetFlagsReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return nil } -// InterfaceAdminDown calls binary API SwInterfaceSetFlagsReply with AdminUpDown=0. -func InterfaceAdminDown(ifIdx uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return interfaceSetFlags(ifIdx, false, vppChan, stopwatch) -} - -// InterfaceAdminUp calls binary API SwInterfaceSetFlagsReply with AdminUpDown=1. -func InterfaceAdminUp(ifIdx uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return interfaceSetFlags(ifIdx, true, vppChan, stopwatch) -} - -func handleInterfaceTag(tag string, ifIdx uint32, isAdd bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +func (h *IfVppHandler) handleInterfaceTag(tag string, ifIdx uint32, isAdd bool) error { defer func(t time.Time) { - stopwatch.TimeLog(interfaces.SwInterfaceTagAddDel{}).LogTimeEntry(time.Since(t)) + h.stopwatch.TimeLog(interfaces.SwInterfaceTagAddDel{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &interfaces.SwInterfaceTagAddDel{ @@ -72,30 +75,19 @@ func handleInterfaceTag(tag string, ifIdx uint32, isAdd bool, vppChan govppapi.C if isAdd { req.SwIfIndex = ifIdx } - reply := &interfaces.SwInterfaceTagAddDelReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s %v (index %v) add/del returned %v", reply.GetMessageName(), tag, ifIdx, reply.Retval) } return nil } -// SetInterfaceTag registers new interface index/tag pair -func SetInterfaceTag(tag string, ifIdx uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return handleInterfaceTag(tag, ifIdx, true, vppChan, stopwatch) -} - -// RemoveInterfaceTag un-registers new interface index/tag pair -func RemoveInterfaceTag(tag string, ifIdx uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return handleInterfaceTag(tag, ifIdx, false, vppChan, stopwatch) -} - -func boolToUint(value bool) uint8 { - if value { +func boolToUint(input bool) uint8 { + if input { return 1 } return 0 diff --git a/plugins/vpp/ifplugin/vppcalls/admin_vppcalls_test.go b/plugins/vpp/ifplugin/vppcalls/admin_vppcalls_test.go index 4916d5b3e6..c7821cd715 100644 --- a/plugins/vpp/ifplugin/vppcalls/admin_vppcalls_test.go +++ b/plugins/vpp/ifplugin/vppcalls/admin_vppcalls_test.go @@ -17,6 +17,7 @@ package vppcalls_test import ( "testing" + "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" "github.com/ligato/vpp-agent/tests/vppcallmock" @@ -24,11 +25,11 @@ import ( ) func TestInterfaceAdminDown(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetFlagsReply{}) - err := vppcalls.InterfaceAdminDown(1, ctx.MockChannel, nil) + err := ifHandler.InterfaceAdminDown(1) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*interfaces.SwInterfaceSetFlags) @@ -39,33 +40,33 @@ func TestInterfaceAdminDown(t *testing.T) { } func TestInterfaceAdminDownError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.HwInterfaceSetMtuReply{}) - err := vppcalls.InterfaceAdminDown(1, ctx.MockChannel, nil) + err := ifHandler.InterfaceAdminDown(1) Expect(err).ToNot(BeNil()) } func TestInterfaceAdminDownRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetFlagsReply{ Retval: 1, }) - err := vppcalls.InterfaceAdminDown(1, ctx.MockChannel, nil) + err := ifHandler.InterfaceAdminDown(1) Expect(err).ToNot(BeNil()) } func TestInterfaceAdminUp(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetFlagsReply{}) - err := vppcalls.InterfaceAdminUp(1, ctx.MockChannel, nil) + err := ifHandler.InterfaceAdminUp(1) Expect(err).ShouldNot(HaveOccurred()) vppMsg, ok := ctx.MockChannel.Msg.(*interfaces.SwInterfaceSetFlags) @@ -76,33 +77,33 @@ func TestInterfaceAdminUp(t *testing.T) { } func TestInterfaceAdminUpError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.HwInterfaceSetMtuReply{}) - err := vppcalls.InterfaceAdminDown(1, ctx.MockChannel, nil) + err := ifHandler.InterfaceAdminDown(1) Expect(err).ToNot(BeNil()) } func TestInterfaceAdminUpRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetFlagsReply{ Retval: 1, }) - err := vppcalls.InterfaceAdminDown(1, ctx.MockChannel, nil) + err := ifHandler.InterfaceAdminDown(1) Expect(err).ToNot(BeNil()) } func TestInterfaceSetTag(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - err := vppcalls.SetInterfaceTag("tag", 1, ctx.MockChannel, nil) + err := ifHandler.SetInterfaceTag("tag", 1) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*interfaces.SwInterfaceTagAddDel) @@ -113,33 +114,33 @@ func TestInterfaceSetTag(t *testing.T) { } func TestInterfaceSetTagError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.HwInterfaceSetMtuReply{}) - err := vppcalls.SetInterfaceTag("tag", 1, ctx.MockChannel, nil) + err := ifHandler.SetInterfaceTag("tag", 1) Expect(err).ToNot(BeNil()) } func TestInterfaceSetTagRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{ Retval: 1, }) - err := vppcalls.SetInterfaceTag("tag", 1, ctx.MockChannel, nil) + err := ifHandler.SetInterfaceTag("tag", 1) Expect(err).ToNot(BeNil()) } func TestInterfaceRemoveTag(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - err := vppcalls.RemoveInterfaceTag("tag", 1, ctx.MockChannel, nil) + err := ifHandler.RemoveInterfaceTag("tag", 1) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*interfaces.SwInterfaceTagAddDel) @@ -150,23 +151,30 @@ func TestInterfaceRemoveTag(t *testing.T) { } func TestInterfaceRemoveTagError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.HwInterfaceSetMtuReply{}) - err := vppcalls.RemoveInterfaceTag("tag", 1, ctx.MockChannel, nil) + err := ifHandler.RemoveInterfaceTag("tag", 1) Expect(err).ToNot(BeNil()) } func TestInterfaceRemoveTagRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{ Retval: 1, }) - err := vppcalls.RemoveInterfaceTag("tag", 1, ctx.MockChannel, nil) + err := ifHandler.RemoveInterfaceTag("tag", 1) Expect(err).ToNot(BeNil()) } + +func ifTestSetup(t *testing.T) (*vppcallmock.TestCtx, vppcalls.IfVppAPI) { + ctx := vppcallmock.SetupTestCtx(t) + log := logrus.NewLogger("test-log") + ifHandler := vppcalls.NewIfVppHandler(ctx.MockChannel, log, nil) + return ctx, ifHandler +} diff --git a/plugins/vpp/ifplugin/vppcalls/afpacket_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/afpacket_vppcalls.go index cee07acf24..711b1c25f4 100644 --- a/plugins/vpp/ifplugin/vppcalls/afpacket_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/afpacket_vppcalls.go @@ -16,65 +16,58 @@ package vppcalls import ( "fmt" + "net" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/vpp-agent/plugins/vpp/binapi/af_packet" intf "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" - "net" ) -// AddAfPacketInterface calls AfPacketCreate VPP binary API. -func AddAfPacketInterface(ifName string, hwAddr string, afPacketIntf *intf.Interfaces_Interface_Afpacket, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (swIndex uint32, err error) { +// AddAfPacketInterface implements AfPacket handler. +func (h *IfVppHandler) AddAfPacketInterface(ifName string, hwAddr string, afPacketIntf *intf.Interfaces_Interface_Afpacket) (swIndex uint32, err error) { defer func(t time.Time) { - stopwatch.TimeLog(af_packet.AfPacketCreate{}).LogTimeEntry(time.Since(t)) + h.stopwatch.TimeLog(af_packet.AfPacketCreate{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &af_packet.AfPacketCreate{ HostIfName: []byte(afPacketIntf.HostIfName), } - if hwAddr == "" { req.UseRandomHwAddr = 1 } else { mac, err := net.ParseMAC(hwAddr) - if err != nil { return 0, err } - req.HwAddr = mac } - reply := &af_packet.AfPacketCreateReply{} - if err = vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err = h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return 0, err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return 0, fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } - return reply.SwIfIndex, SetInterfaceTag(ifName, reply.SwIfIndex, vppChan, stopwatch) + return reply.SwIfIndex, h.SetInterfaceTag(ifName, reply.SwIfIndex) } -// DeleteAfPacketInterface calls AfPacketDelete VPP binary API. -func DeleteAfPacketInterface(ifName string, idx uint32, afPacketIntf *intf.Interfaces_Interface_Afpacket, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +// DeleteAfPacketInterface implements AfPacket handler. +func (h *IfVppHandler) DeleteAfPacketInterface(ifName string, idx uint32, afPacketIntf *intf.Interfaces_Interface_Afpacket) error { defer func(t time.Time) { - stopwatch.TimeLog(af_packet.AfPacketDelete{}).LogTimeEntry(time.Since(t)) + h.stopwatch.TimeLog(af_packet.AfPacketDelete{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &af_packet.AfPacketDelete{ HostIfName: []byte(afPacketIntf.HostIfName), } - reply := &af_packet.AfPacketDeleteReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } - return RemoveInterfaceTag(ifName, idx, vppChan, stopwatch) + return h.RemoveInterfaceTag(ifName, idx) } diff --git a/plugins/vpp/ifplugin/vppcalls/afpacket_vppcalls_test.go b/plugins/vpp/ifplugin/vppcalls/afpacket_vppcalls_test.go index 4820751042..87d57218f2 100644 --- a/plugins/vpp/ifplugin/vppcalls/afpacket_vppcalls_test.go +++ b/plugins/vpp/ifplugin/vppcalls/afpacket_vppcalls_test.go @@ -20,22 +20,20 @@ import ( "github.com/ligato/vpp-agent/plugins/vpp/binapi/af_packet" "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" if_api "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" - "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" ) func TestAddAfPacketInterface(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&af_packet.AfPacketCreateReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - ifIndex, err := vppcalls.AddAfPacketInterface("if1", "", &if_api.Interfaces_Interface_Afpacket{ + ifIndex, err := ifHandler.AddAfPacketInterface("if1", "", &if_api.Interfaces_Interface_Afpacket{ HostIfName: "host1", - }, ctx.MockChannel, nil) + }) Expect(err).To(BeNil()) Expect(ifIndex).ToNot(BeNil()) @@ -54,20 +52,20 @@ func TestAddAfPacketInterface(t *testing.T) { } func TestAddAfPacketInterfaceError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&af_packet.AfPacketDeleteReply{}) - _, err := vppcalls.AddAfPacketInterface("if1", "", &if_api.Interfaces_Interface_Afpacket{ + _, err := ifHandler.AddAfPacketInterface("if1", "", &if_api.Interfaces_Interface_Afpacket{ HostIfName: "host1", - }, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } func TestAddAfPacketInterfaceRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&af_packet.AfPacketCreateReply{ @@ -75,23 +73,23 @@ func TestAddAfPacketInterfaceRetval(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - _, err := vppcalls.AddAfPacketInterface("if1", "", &if_api.Interfaces_Interface_Afpacket{ + _, err := ifHandler.AddAfPacketInterface("if1", "", &if_api.Interfaces_Interface_Afpacket{ HostIfName: "host1", - }, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } func TestDeleteAfPacketInterface(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&af_packet.AfPacketDeleteReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - err := vppcalls.DeleteAfPacketInterface("if1", 0, &if_api.Interfaces_Interface_Afpacket{ + err := ifHandler.DeleteAfPacketInterface("if1", 0, &if_api.Interfaces_Interface_Afpacket{ HostIfName: "host1", - }, ctx.MockChannel, nil) + }) Expect(err).To(BeNil()) Expect(len(ctx.MockChannel.Msgs)).To(BeEquivalentTo(2)) @@ -107,20 +105,20 @@ func TestDeleteAfPacketInterface(t *testing.T) { } func TestDeleteAfPacketInterfaceError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&af_packet.AfPacketCreateReply{}) - err := vppcalls.DeleteAfPacketInterface("if1", 0, &if_api.Interfaces_Interface_Afpacket{ + err := ifHandler.DeleteAfPacketInterface("if1", 0, &if_api.Interfaces_Interface_Afpacket{ HostIfName: "host1", - }, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } func TestDeleteAfPacketInterfaceRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&af_packet.AfPacketDeleteReply{ @@ -128,23 +126,23 @@ func TestDeleteAfPacketInterfaceRetval(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - err := vppcalls.DeleteAfPacketInterface("if1", 0, &if_api.Interfaces_Interface_Afpacket{ + err := ifHandler.DeleteAfPacketInterface("if1", 0, &if_api.Interfaces_Interface_Afpacket{ HostIfName: "host1", - }, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } func TestAddAfPacketInterfaceMac(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&af_packet.AfPacketCreateReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - ifIndex, err := vppcalls.AddAfPacketInterface("if1", "a2:01:01:01:01:01", &if_api.Interfaces_Interface_Afpacket{ + ifIndex, err := ifHandler.AddAfPacketInterface("if1", "a2:01:01:01:01:01", &if_api.Interfaces_Interface_Afpacket{ HostIfName: "host1", - }, ctx.MockChannel, nil) + }) Expect(err).To(BeNil()) Expect(ifIndex).ToNot(BeNil()) diff --git a/plugins/vpp/ifplugin/vppcalls/api_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/api_vppcalls.go new file mode 100644 index 0000000000..8da71cd786 --- /dev/null +++ b/plugins/vpp/ifplugin/vppcalls/api_vppcalls.go @@ -0,0 +1,303 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vppcalls + +import ( + "net" + + "git.fd.io/govpp.git/api" + "github.com/ligato/cn-infra/logging" + "github.com/ligato/cn-infra/logging/measure" + "github.com/ligato/vpp-agent/idxvpp" + bfd_api "github.com/ligato/vpp-agent/plugins/vpp/binapi/bfd" + "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" + "github.com/ligato/vpp-agent/plugins/vpp/model/bfd" + "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" + "github.com/ligato/vpp-agent/plugins/vpp/model/nat" +) + +// IfVppAPI provides methods for creating and managing interface plugin +type IfVppAPI interface { + IfVppWrite + IfVppRead +} + +// IfVppWrite provides write methods for interface plugin +type IfVppWrite interface { + // AddAfPacketInterface calls AfPacketCreate VPP binary API. + AddAfPacketInterface(ifName string, hwAddr string, afPacketIntf *interfaces.Interfaces_Interface_Afpacket) (swIndex uint32, err error) + // DeleteAfPacketInterface calls AfPacketDelete VPP binary API. + DeleteAfPacketInterface(ifName string, idx uint32, afPacketIntf *interfaces.Interfaces_Interface_Afpacket) error + // AddLoopbackInterface calls CreateLoopback bin API. + AddLoopbackInterface(ifName string) (swIndex uint32, err error) + // DeleteLoopbackInterface calls DeleteLoopback bin API. + DeleteLoopbackInterface(ifName string, idx uint32) error + // AddMemifInterface calls MemifCreate bin API. + AddMemifInterface(ifName string, memIface *interfaces.Interfaces_Interface_Memif, socketID uint32) (swIdx uint32, err error) + // DeleteMemifInterface calls MemifDelete bin API. + DeleteMemifInterface(ifName string, idx uint32) error + // AddTapInterface calls TapConnect bin API. + AddTapInterface(ifName string, tapIf *interfaces.Interfaces_Interface_Tap) (swIfIdx uint32, err error) + // DeleteTapInterface calls TapDelete bin API. + DeleteTapInterface(ifName string, idx uint32, version uint32) error + // AddVxLanTunnel calls AddDelVxLanTunnelReq with flag add=1. + AddVxLanTunnel(ifName string, vrf, multicastIf uint32, vxLan *interfaces.Interfaces_Interface_Vxlan) (swIndex uint32, err error) + // DeleteVxLanTunnel calls AddDelVxLanTunnelReq with flag add=0. + DeleteVxLanTunnel(ifName string, idx, vrf uint32, vxLan *interfaces.Interfaces_Interface_Vxlan) error + // InterfaceAdminDown calls binary API SwInterfaceSetFlagsReply with AdminUpDown=0. + InterfaceAdminDown(ifIdx uint32) error + // InterfaceAdminUp calls binary API SwInterfaceSetFlagsReply with AdminUpDown=1. + InterfaceAdminUp(ifIdx uint32) error + // SetInterfaceTag registers new interface index/tag pair + SetInterfaceTag(tag string, ifIdx uint32) error + // RemoveInterfaceTag un-registers new interface index/tag pair + RemoveInterfaceTag(tag string, ifIdx uint32) error + // SetInterfaceAsDHCPClient sets provided interface as a DHCP client + SetInterfaceAsDHCPClient(ifIdx uint32, hostName string) error + // UnsetInterfaceAsDHCPClient un-sets interface as DHCP client + UnsetInterfaceAsDHCPClient(ifIdx uint32, hostName string) error + // AddContainerIP calls IPContainerProxyAddDel VPP API with IsAdd=1 + AddContainerIP(ifIdx uint32, addr string) error + // DelContainerIP calls IPContainerProxyAddDel VPP API with IsAdd=0 + DelContainerIP(ifIdx uint32, addr string) error + // AddInterfaceIP calls SwInterfaceAddDelAddress bin API with IsAdd=1. + AddInterfaceIP(ifIdx uint32, addr *net.IPNet) error + // DelInterfaceIP calls SwInterfaceAddDelAddress bin API with IsAdd=00. + DelInterfaceIP(ifIdx uint32, addr *net.IPNet) error + // SetUnnumberedIP sets interface as un-numbered, linking IP address of the another interface (ifIdxWithIP) + SetUnnumberedIP(uIfIdx uint32, ifIdxWithIP uint32) error + // UnsetUnnumberedIP unset provided interface as un-numbered. IP address of the linked interface is removed + UnsetUnnumberedIP(uIfIdx uint32) error + // SetInterfaceMac calls SwInterfaceSetMacAddress bin API. + SetInterfaceMac(ifIdx uint32, macAddress string) error + // RegisterMemifSocketFilename registers new socket file name with provided ID. + RegisterMemifSocketFilename(filename []byte, id uint32) error + // SetInterfaceMtu calls HwInterfaceSetMtu bin API with desired MTU value. + SetInterfaceMtu(ifIdx uint32, mtu uint32) error + // SetRxMode calls SwInterfaceSetRxMode bin + SetRxMode(ifIdx uint32, rxModeSettings *interfaces.Interfaces_Interface_RxModeSettings) error + // SetRxPlacement configures rx-placement for interface + SetRxPlacement(vppInternalName string, rxPlacement *interfaces.Interfaces_Interface_RxPlacementSettings) error + // CreateVrf checks if VRF exists and creates it if not + CreateVrf(vrfID uint32) error + // CreateVrfIPv6 checks if IPv6 VRF exists and creates it if not + CreateVrfIPv6(vrfID uint32) error + // SetInterfaceVrf retrieves VRF table from interface + SetInterfaceVrf(ifaceIndex, vrfID uint32) error + // SetInterfaceVrfIPv6 retrieves IPV6 VRF table from interface + SetInterfaceVrfIPv6(ifaceIndex, vrfID uint32) error +} + +// IfVppRead provides read methods for interface plugin +type IfVppRead interface { + // DumpInterfaces dumps VPP interface data into the northbound API data structure + // map indexed by software interface index. + // + // LIMITATIONS: + // - there is no af_packet dump binary API. We relay on naming conventions of the internal VPP interface names + // - ip.IPAddressDetails has wrong internal structure, as a workaround we need to handle them as notifications + DumpInterfaces() (map[uint32]*InterfaceDetails, error) + // DumpInterfacesByType returns all VPP interfaces of the specified type + DumpInterfacesByType(reqType interfaces.InterfaceType) (map[uint32]*InterfaceDetails, error) + // GetInterfaceVrf reads VRF table to interface + GetInterfaceVrf(ifIdx uint32) (vrfID uint32, err error) + // GetInterfaceVrfIPv6 reads IPv6 VRF table to interface + GetInterfaceVrfIPv6(ifIdx uint32) (vrfID uint32, err error) + // DumpMemifSocketDetails dumps memif socket details from the VPP + DumpMemifSocketDetails() (map[string]uint32, error) +} + +// BfdVppAPI provides methods for managing BFD +type BfdVppAPI interface { + BfdVppWrite + BfdVppRead +} + +// BfdVppWrite provides write methods for BFD +type BfdVppWrite interface { + // AddBfdUDPSession adds new BFD session with authentication if available. + AddBfdUDPSession(bfdSess *bfd.SingleHopBFD_Session, ifIdx uint32, bfdKeyIndexes idxvpp.NameToIdx) error + // AddBfdUDPSessionFromDetails adds new BFD session with authentication if available. + AddBfdUDPSessionFromDetails(bfdSess *bfd_api.BfdUDPSessionDetails, bfdKeyIndexes idxvpp.NameToIdx) error + // ModifyBfdUDPSession modifies existing BFD session excluding authentication which cannot be changed this way. + ModifyBfdUDPSession(bfdSess *bfd.SingleHopBFD_Session, swIfIndexes ifaceidx.SwIfIndex) error + // DeleteBfdUDPSession removes an existing BFD session. + DeleteBfdUDPSession(ifIndex uint32, sourceAddress string, destAddress string) error + // SetBfdUDPAuthenticationKey creates new authentication key. + SetBfdUDPAuthenticationKey(bfdKey *bfd.SingleHopBFD_Key) error + // DeleteBfdUDPAuthenticationKey removes the authentication key. + DeleteBfdUDPAuthenticationKey(bfdKey *bfd.SingleHopBFD_Key) error + // AddBfdEchoFunction sets up an echo function for the interface. + AddBfdEchoFunction(bfdInput *bfd.SingleHopBFD_EchoFunction, swIfIndexes ifaceidx.SwIfIndex) error + // DeleteBfdEchoFunction removes an echo function. + DeleteBfdEchoFunction() error +} + +// BfdVppRead provides read methods for BFD +type BfdVppRead interface { + // DumpBfdSingleHop returns complete BFD configuration + DumpBfdSingleHop() (*BfdDetails, error) + // DumpBfdUDPSessions returns a list of BFD session's metadata + DumpBfdSessions() (*BfdSessionDetails, error) + // DumpBfdUDPSessionsWithID returns a list of BFD session's metadata filtered according to provided authentication key + DumpBfdUDPSessionsWithID(authKeyIndex uint32) (*BfdSessionDetails, error) + // DumpBfdKeys looks up all BFD auth keys and saves their name-to-index mapping + DumpBfdAuthKeys() (*BfdAuthKeyDetails, error) +} + +// NatVppAPI provides methods for managing NAT +type NatVppAPI interface { + NatVppWrite + NatVppRead +} + +// NatVppWrite provides write methods for NAT +type NatVppWrite interface { + // SetNat44Forwarding configures global forwarding setup for NAT44 + SetNat44Forwarding(enableFwd bool) error + // EnableNat44Interface enables NAT feature for provided interface + EnableNat44Interface(ifIdx uint32, isInside bool) error + // DisableNat44Interface enables NAT feature for provided interface + DisableNat44Interface(ifIdx uint32, isInside bool) error + // EnableNat44InterfaceOutput enables NAT output feature for provided interface + EnableNat44InterfaceOutput(ifIdx uint32, isInside bool) error + // DisableNat44InterfaceOutput disables NAT output feature for provided interface + DisableNat44InterfaceOutput(ifIdx uint32, isInside bool) error + // AddNat44AddressPool sets new NAT address pool + AddNat44AddressPool(first, last []byte, vrf uint32, twiceNat bool) error + // DelNat44AddressPool removes existing NAT address pool + DelNat44AddressPool(first, last []byte, vrf uint32, twiceNat bool) error + // SetVirtualReassemblyIPv4 configures NAT virtual reassembly for IPv4 packets + SetVirtualReassemblyIPv4(vrCfg *nat.Nat44Global_VirtualReassembly) error + // SetVirtualReassemblyIPv4 configures NAT virtual reassembly for IPv6 packets + SetVirtualReassemblyIPv6(vrCfg *nat.Nat44Global_VirtualReassembly) error + // AddNat44IdentityMapping adds new NAT44 identity mapping + AddNat44IdentityMapping(ctx *IdentityMappingContext) error + // DelNat44IdentityMapping removes NAT44 identity mapping + DelNat44IdentityMapping(ctx *IdentityMappingContext) error + // AddNat44StaticMapping creates new static mapping entry (considering address only or both, address and port + // depending on the context) + AddNat44StaticMapping(ctx *StaticMappingContext) error + // DelNat44StaticMapping removes existing static mapping entry + DelNat44StaticMapping(ctx *StaticMappingContext) error + // AddNat44StaticMappingLb creates new static mapping entry with load balancer + AddNat44StaticMappingLb(ctx *StaticMappingLbContext) error + // DelNat44StaticMappingLb removes existing static mapping entry with load balancer + DelNat44StaticMappingLb(ctx *StaticMappingLbContext) error +} + +// NatVppRead provides read methods for NAT +type NatVppRead interface { + // Nat44Dump retuns global NAT configuration together with the DNAT configs + Nat44Dump() (*Nat44Details, error) + // Nat44GlobalConfigDump returns global config in NB format + Nat44GlobalConfigDump() (*nat.Nat44Global, error) + // NAT44NatDump dumps all types of mappings, sorts it according to tag (DNAT label) and creates a set of DNAT configurations + Nat44DNatDump() (*nat.Nat44DNat, error) + // Nat44InterfaceDump returns a list of interfaces enabled for NAT44 + Nat44InterfaceDump() (interfaces []*nat.Nat44Global_NatInterface, err error) +} + +// StnVppAPI provides methods for managing STN +type StnVppAPI interface { + StnVppWrite + StnVppRead +} + +// StnVppWrite provides write methods for STN +type StnVppWrite interface { + // AddStnRule calls StnAddDelRule bin API with IsAdd=1 + AddStnRule(ifIdx uint32, addr *net.IP) error + // DelStnRule calls StnAddDelRule bin API with IsAdd=0 + DelStnRule(ifIdx uint32, addr *net.IP) error +} + +// StnVppRead provides read methods for STN +type StnVppRead interface { + // DumpStnRules returns a list of all STN rules configured on the VPP + DumpStnRules() (rules *StnDetails, err error) +} + +// IfVppHandler is accessor for interface-related vppcalls methods +type IfVppHandler struct { + stopwatch *measure.Stopwatch + callsChannel api.Channel + log logging.Logger +} + +// BfdVppHandler is accessor for BFD-related vppcalls methods +type BfdVppHandler struct { + stopwatch *measure.Stopwatch + callsChannel api.Channel + ifIndexes ifaceidx.SwIfIndex + log logging.Logger +} + +// NatVppHandler is accessor for NAT-related vppcalls methods +type NatVppHandler struct { + stopwatch *measure.Stopwatch + callsChannel api.Channel + dumpChannel api.Channel + ifIndexes ifaceidx.SwIfIndex + log logging.Logger +} + +// StnVppHandler is accessor for STN-related vppcalls methods +type StnVppHandler struct { + stopwatch *measure.Stopwatch + ifIndexes ifaceidx.SwIfIndex + callsChannel api.Channel + log logging.Logger +} + +// NewIfVppHandler creates new instance of interface vppcalls handler +func NewIfVppHandler(callsChan api.Channel, log logging.Logger, stopwatch *measure.Stopwatch) *IfVppHandler { + return &IfVppHandler{ + callsChannel: callsChan, + stopwatch: stopwatch, + log: log, + } +} + +// NewBfdVppHandler creates new instance of BFD vppcalls handler +func NewBfdVppHandler(callsChan api.Channel, ifIndexes ifaceidx.SwIfIndex, log logging.Logger, stopwatch *measure.Stopwatch) *BfdVppHandler { + return &BfdVppHandler{ + callsChannel: callsChan, + stopwatch: stopwatch, + ifIndexes: ifIndexes, + log: log, + } +} + +// NewNatVppHandler creates new instance of NAT vppcalls handler +func NewNatVppHandler(callsChan, dumpChan api.Channel, ifIndexes ifaceidx.SwIfIndex, log logging.Logger, stopwatch *measure.Stopwatch) *NatVppHandler { + return &NatVppHandler{ + callsChannel: callsChan, + dumpChannel: dumpChan, + stopwatch: stopwatch, + ifIndexes: ifIndexes, + log: log, + } +} + +// NewStnVppHandler creates new instance of STN vppcalls handler +func NewStnVppHandler(callsChan api.Channel, ifIndexes ifaceidx.SwIfIndex, log logging.Logger, stopwatch *measure.Stopwatch) *StnVppHandler { + return &StnVppHandler{ + callsChannel: callsChan, + ifIndexes: ifIndexes, + stopwatch: stopwatch, + log: log, + } +} diff --git a/plugins/vpp/ifplugin/vppcalls/bfd_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/bfd_vppcalls.go index b8f704e230..f8ecf5d868 100644 --- a/plugins/vpp/ifplugin/vppcalls/bfd_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/bfd_vppcalls.go @@ -17,11 +17,9 @@ package vppcalls import ( "fmt" "net" + "strconv" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/cn-infra/utils/addrs" "github.com/ligato/vpp-agent/idxvpp" bfd_api "github.com/ligato/vpp-agent/plugins/vpp/binapi/bfd" @@ -29,11 +27,10 @@ import ( "github.com/ligato/vpp-agent/plugins/vpp/model/bfd" ) -// AddBfdUDPSession adds new BFD session with authentication if available. -func AddBfdUDPSession(bfdSess *bfd.SingleHopBFD_Session, ifIdx uint32, bfdKeyIndexes idxvpp.NameToIdx, - log logging.Logger, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +// AddBfdUDPSession implements BFD handler. +func (handler *BfdVppHandler) AddBfdUDPSession(bfdSess *bfd.SingleHopBFD_Session, ifIdx uint32, bfdKeyIndexes idxvpp.NameToIdx) error { defer func(t time.Time) { - stopwatch.TimeLog(bfd_api.BfdUDPAdd{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(bfd_api.BfdUDPAdd{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &bfd_api.BfdUDPAdd{ @@ -52,11 +49,11 @@ func AddBfdUDPSession(bfdSess *bfd.SingleHopBFD_Session, ifIdx uint32, bfdKeyInd return err } if isLocalIpv6 && isPeerIpv6 { - req.IsIpv6 = 1 + req.IsIPv6 = 1 req.LocalAddr = net.ParseIP(bfdSess.SourceAddress).To16() req.PeerAddr = net.ParseIP(bfdSess.DestinationAddress).To16() } else if !isLocalIpv6 && !isPeerIpv6 { - req.IsIpv6 = 0 + req.IsIPv6 = 0 req.LocalAddr = net.ParseIP(bfdSess.SourceAddress).To4() req.PeerAddr = net.ParseIP(bfdSess.DestinationAddress).To4() } else { @@ -66,37 +63,35 @@ func AddBfdUDPSession(bfdSess *bfd.SingleHopBFD_Session, ifIdx uint32, bfdKeyInd // Authentication if bfdSess.Authentication != nil { - keyID := string(bfdSess.Authentication.KeyId) - log.Infof("Setting up authentication with index %v", keyID) + keyID := strconv.Itoa(int(bfdSess.Authentication.KeyId)) + handler.log.Infof("Setting up authentication with index %v", keyID) _, _, found := bfdKeyIndexes.LookupIdx(keyID) if found { req.IsAuthenticated = 1 req.BfdKeyID = uint8(bfdSess.Authentication.KeyId) req.ConfKeyID = bfdSess.Authentication.AdvertisedKeyId } else { - log.Infof("Authentication key %v not found", bfdSess.Authentication.KeyId) + handler.log.Infof("Authentication key %v not found", bfdSess.Authentication.KeyId) req.IsAuthenticated = 0 } } else { req.IsAuthenticated = 0 } - reply := &bfd_api.BfdUDPAddReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return nil } -// AddBfdUDPSessionFromDetails adds new BFD session with authentication if available. -func AddBfdUDPSessionFromDetails(bfdSess *bfd_api.BfdUDPSessionDetails, bfdKeyIndexes idxvpp.NameToIdx, log logging.Logger, - vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +// AddBfdUDPSessionFromDetails implements BFD handler. +func (handler *BfdVppHandler) AddBfdUDPSessionFromDetails(bfdSess *bfd_api.BfdUDPSessionDetails, bfdKeyIndexes idxvpp.NameToIdx) error { defer func(t time.Time) { - stopwatch.TimeLog(bfd_api.BfdUDPAdd{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(bfd_api.BfdUDPAdd{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &bfd_api.BfdUDPAdd{ @@ -106,41 +101,40 @@ func AddBfdUDPSessionFromDetails(bfdSess *bfd_api.BfdUDPSessionDetails, bfdKeyIn LocalAddr: bfdSess.LocalAddr, PeerAddr: bfdSess.PeerAddr, DetectMult: bfdSess.DetectMult, - IsIpv6: bfdSess.IsIpv6, + IsIPv6: bfdSess.IsIPv6, } // Authentication if bfdSess.IsAuthenticated != 0 { keyID := string(bfdSess.BfdKeyID) - log.Infof("Setting up authentication with index %v", keyID) + handler.log.Infof("Setting up authentication with index %v", keyID) _, _, found := bfdKeyIndexes.LookupIdx(keyID) if found { req.IsAuthenticated = 1 req.BfdKeyID = bfdSess.BfdKeyID req.ConfKeyID = bfdSess.ConfKeyID } else { - log.Infof("Authentication key %v not found", bfdSess.BfdKeyID) + handler.log.Infof("Authentication key %v not found", bfdSess.BfdKeyID) req.IsAuthenticated = 0 } } else { req.IsAuthenticated = 0 } - reply := &bfd_api.BfdUDPAddReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return nil } -// ModifyBfdUDPSession modifies existing BFD session excluding authentication which cannot be changed this way. -func ModifyBfdUDPSession(bfdSess *bfd.SingleHopBFD_Session, swIfIndexes ifaceidx.SwIfIndex, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (err error) { +// ModifyBfdUDPSession implements BFD handler. +func (handler *BfdVppHandler) ModifyBfdUDPSession(bfdSess *bfd.SingleHopBFD_Session, swIfIndexes ifaceidx.SwIfIndex) error { defer func(t time.Time) { - stopwatch.TimeLog(bfd_api.BfdUDPMod{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(bfd_api.BfdUDPMod{}).LogTimeEntry(time.Since(t)) }(time.Now()) // Find the interface @@ -165,100 +159,55 @@ func ModifyBfdUDPSession(bfdSess *bfd.SingleHopBFD_Session, swIfIndexes ifaceidx return err } if isLocalIpv6 && isPeerIpv6 { - req.IsIpv6 = 1 + req.IsIPv6 = 1 req.LocalAddr = net.ParseIP(bfdSess.SourceAddress).To16() req.PeerAddr = net.ParseIP(bfdSess.DestinationAddress).To16() } else if !isLocalIpv6 && !isPeerIpv6 { - req.IsIpv6 = 0 + req.IsIPv6 = 0 req.LocalAddr = net.ParseIP(bfdSess.SourceAddress).To4() req.PeerAddr = net.ParseIP(bfdSess.DestinationAddress).To4() } else { return fmt.Errorf("different IP versions or missing IP address. Local: %v, Peer: %v", bfdSess.SourceAddress, bfdSess.DestinationAddress) } - reply := &bfd_api.BfdUDPModReply{} - if err = vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err = handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return nil } -// DeleteBfdUDPSession removes an existing BFD session. -func DeleteBfdUDPSession(ifIndex uint32, sourceAddress string, destAddress string, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +// DeleteBfdUDPSession implements BFD handler. +func (handler *BfdVppHandler) DeleteBfdUDPSession(ifIndex uint32, sourceAddress string, destAddress string) error { defer func(t time.Time) { - stopwatch.TimeLog(bfd_api.BfdUDPDel{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(bfd_api.BfdUDPDel{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &bfd_api.BfdUDPDel{ SwIfIndex: ifIndex, LocalAddr: net.ParseIP(sourceAddress).To4(), PeerAddr: net.ParseIP(destAddress).To4(), - IsIpv6: 0, + IsIPv6: 0, } - reply := &bfd_api.BfdUDPDelReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return nil } -// DumpBfdUDPSessions returns a list of BFD session's metadata -func DumpBfdUDPSessions(vppChan govppapi.Channel, stopwatch *measure.Stopwatch) ([]*bfd_api.BfdUDPSessionDetails, error) { - return dumpBfdUDPSessionsWithID(false, 0, vppChan, stopwatch) -} - -// DumpBfdUDPSessionsWithID returns a list of BFD session's metadata filtered according to provided authentication key -func DumpBfdUDPSessionsWithID(authKeyIndex uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) ([]*bfd_api.BfdUDPSessionDetails, error) { - return dumpBfdUDPSessionsWithID(true, authKeyIndex, vppChan, stopwatch) -} - -func dumpBfdUDPSessionsWithID(filterID bool, authKeyIndex uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (sessions []*bfd_api.BfdUDPSessionDetails, err error) { - defer func(t time.Time) { - stopwatch.TimeLog(bfd_api.BfdUDPSessionDump{}).LogTimeEntry(time.Since(t)) - }(time.Now()) - - req := &bfd_api.BfdUDPSessionDump{} - reqCtx := vppChan.SendMultiRequest(req) - for { - msg := &bfd_api.BfdUDPSessionDetails{} - stop, err := reqCtx.ReceiveReply(msg) - if stop { - break - } - if err != nil { - return sessions, err - } - - if filterID { - // Not interested in sessions without auth key - if msg.IsAuthenticated == 0 { - continue - } - if msg.BfdKeyID == uint8(authKeyIndex) { - sessions = append(sessions, msg) - } - } else { - sessions = append(sessions, msg) - } - } - - return sessions, nil -} - -// SetBfdUDPAuthenticationKey creates new authentication key. -func SetBfdUDPAuthenticationKey(bfdKey *bfd.SingleHopBFD_Key, log logging.Logger, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (err error) { +// SetBfdUDPAuthenticationKey implements BFD handler. +func (handler *BfdVppHandler) SetBfdUDPAuthenticationKey(bfdKey *bfd.SingleHopBFD_Key) error { defer func(t time.Time) { - stopwatch.TimeLog(bfd_api.BfdAuthSetKey{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(bfd_api.BfdAuthSetKey{}).LogTimeEntry(time.Since(t)) }(time.Now()) // Convert authentication according to RFC5880. @@ -268,7 +217,7 @@ func SetBfdUDPAuthenticationKey(bfdKey *bfd.SingleHopBFD_Key, log logging.Logger } else if bfdKey.AuthenticationType == 1 { authentication = 5 // Meticulous keyed SHA1 } else { - log.Warnf("Provided authentication type not supported, setting up SHA1") + handler.log.Warnf("Provided authentication type not supported, setting up SHA1") authentication = 4 } @@ -278,67 +227,41 @@ func SetBfdUDPAuthenticationKey(bfdKey *bfd.SingleHopBFD_Key, log logging.Logger Key: []byte(bfdKey.Secret), KeyLen: uint8(len(bfdKey.Secret)), } - reply := &bfd_api.BfdAuthSetKeyReply{} - if err = vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return nil } -// DeleteBfdUDPAuthenticationKey removes the authentication key. -func DeleteBfdUDPAuthenticationKey(bfdKey *bfd.SingleHopBFD_Key, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (err error) { +// DeleteBfdUDPAuthenticationKey implements BFD handler. +func (handler *BfdVppHandler) DeleteBfdUDPAuthenticationKey(bfdKey *bfd.SingleHopBFD_Key) error { defer func(t time.Time) { - stopwatch.TimeLog(bfd_api.BfdAuthDelKey{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(bfd_api.BfdAuthDelKey{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &bfd_api.BfdAuthDelKey{ ConfKeyID: bfdKey.Id, } - reply := &bfd_api.BfdAuthDelKeyReply{} - if err = vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return nil } -// DumpBfdKeys looks up all BFD auth keys and saves their name-to-index mapping -func DumpBfdKeys(vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (keys []*bfd_api.BfdAuthKeysDetails, err error) { +// AddBfdEchoFunction implements BFD handler. +func (handler *BfdVppHandler) AddBfdEchoFunction(bfdInput *bfd.SingleHopBFD_EchoFunction, swIfIndexes ifaceidx.SwIfIndex) error { defer func(t time.Time) { - stopwatch.TimeLog(bfd_api.BfdAuthKeysDump{}).LogTimeEntry(time.Since(t)) - }(time.Now()) - - req := &bfd_api.BfdAuthKeysDump{} - reqCtx := vppChan.SendMultiRequest(req) - for { - msg := &bfd_api.BfdAuthKeysDetails{} - stop, err := reqCtx.ReceiveReply(msg) - if stop { - break - } - if err != nil { - return nil, err - } - - keys = append(keys, msg) - } - - return keys, nil -} - -// AddBfdEchoFunction sets up an echo function for the interface. -func AddBfdEchoFunction(bfdInput *bfd.SingleHopBFD_EchoFunction, swIfIndexes ifaceidx.SwIfIndex, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (err error) { - defer func(t time.Time) { - stopwatch.TimeLog(bfd_api.BfdUDPSetEchoSource{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(bfd_api.BfdUDPSetEchoSource{}).LogTimeEntry(time.Since(t)) }(time.Now()) // Verify the interface presence. @@ -350,32 +273,30 @@ func AddBfdEchoFunction(bfdInput *bfd.SingleHopBFD_EchoFunction, swIfIndexes ifa req := &bfd_api.BfdUDPSetEchoSource{ SwIfIndex: ifIdx, } - reply := &bfd_api.BfdUDPSetEchoSourceReply{} - if err = vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return nil } -// DeleteBfdEchoFunction removes an echo function. -func DeleteBfdEchoFunction(vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (err error) { +// DeleteBfdEchoFunction implements BFD handler. +func (handler *BfdVppHandler) DeleteBfdEchoFunction() error { defer func(t time.Time) { - stopwatch.TimeLog(bfd_api.BfdUDPDelEchoSource{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(bfd_api.BfdUDPDelEchoSource{}).LogTimeEntry(time.Since(t)) }(time.Now()) // Prepare the message. req := &bfd_api.BfdUDPDelEchoSource{} - reply := &bfd_api.BfdUDPDelEchoSourceReply{} - if err = vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } diff --git a/plugins/vpp/ifplugin/vppcalls/bfd_vppcalls_test.go b/plugins/vpp/ifplugin/vppcalls/bfd_vppcalls_test.go index 380a784983..858f9a06e3 100644 --- a/plugins/vpp/ifplugin/vppcalls/bfd_vppcalls_test.go +++ b/plugins/vpp/ifplugin/vppcalls/bfd_vppcalls_test.go @@ -21,7 +21,7 @@ import ( "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/idxvpp/nametoidx" bfd_api "github.com/ligato/vpp-agent/plugins/vpp/binapi/bfd" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/vpe" + "github.com/ligato/vpp-agent/plugins/vpp/ifplugin" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" "github.com/ligato/vpp-agent/plugins/vpp/model/bfd" @@ -30,15 +30,15 @@ import ( ) func TestAddBfdUDPSession(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() bfdKeyIndexes := nametoidx.NewNameToIdx(logrus.DefaultLogger(), "bfd", nil) - bfdKeyIndexes.RegisterName(string(1), 1, nil) + bfdKeyIndexes.RegisterName(ifplugin.AuthKeyIdentifier(1), 1, nil) ctx.MockVpp.MockReply(&bfd_api.BfdUDPAddReply{}) - err := vppcalls.AddBfdUDPSession(&bfd.SingleHopBFD_Session{ + err := bfdHandler.AddBfdUDPSession(&bfd.SingleHopBFD_Session{ SourceAddress: "10.0.0.1", DestinationAddress: "20.0.0.1", DesiredMinTxInterval: 10, @@ -48,7 +48,7 @@ func TestAddBfdUDPSession(t *testing.T) { KeyId: 1, AdvertisedKeyId: 1, }, - }, 1, bfdKeyIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + }, 1, bfdKeyIndexes) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*bfd_api.BfdUDPAdd) @@ -57,20 +57,20 @@ func TestAddBfdUDPSession(t *testing.T) { Expect(vppMsg.DesiredMinTx).To(BeEquivalentTo(10)) Expect(vppMsg.RequiredMinRx).To(BeEquivalentTo(15)) Expect(vppMsg.DetectMult).To(BeEquivalentTo(2)) - Expect(vppMsg.IsIpv6).To(BeEquivalentTo(0)) + Expect(vppMsg.IsIPv6).To(BeEquivalentTo(0)) Expect(vppMsg.IsAuthenticated).To(BeEquivalentTo(1)) } func TestAddBfdUDPSessionIPv6(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() bfdKeyIndexes := nametoidx.NewNameToIdx(logrus.DefaultLogger(), "bfd", nil) - bfdKeyIndexes.RegisterName(string(1), 1, nil) + bfdKeyIndexes.RegisterName(ifplugin.AuthKeyIdentifier(1), 1, nil) ctx.MockVpp.MockReply(&bfd_api.BfdUDPAddReply{}) - err := vppcalls.AddBfdUDPSession(&bfd.SingleHopBFD_Session{ + err := bfdHandler.AddBfdUDPSession(&bfd.SingleHopBFD_Session{ SourceAddress: "2001:db8::1", DestinationAddress: "2001:db8:0:1:1:1:1:1", DesiredMinTxInterval: 10, @@ -80,7 +80,7 @@ func TestAddBfdUDPSessionIPv6(t *testing.T) { KeyId: 1, AdvertisedKeyId: 1, }, - }, 1, bfdKeyIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + }, 1, bfdKeyIndexes) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*bfd_api.BfdUDPAdd) @@ -89,19 +89,19 @@ func TestAddBfdUDPSessionIPv6(t *testing.T) { Expect(vppMsg.DesiredMinTx).To(BeEquivalentTo(10)) Expect(vppMsg.RequiredMinRx).To(BeEquivalentTo(15)) Expect(vppMsg.DetectMult).To(BeEquivalentTo(2)) - Expect(vppMsg.IsIpv6).To(BeEquivalentTo(1)) + Expect(vppMsg.IsIPv6).To(BeEquivalentTo(1)) Expect(vppMsg.IsAuthenticated).To(BeEquivalentTo(1)) } func TestAddBfdUDPSessionAuthKeyNotFound(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() bfdKeyIndexes := nametoidx.NewNameToIdx(logrus.DefaultLogger(), "bfd", nil) ctx.MockVpp.MockReply(&bfd_api.BfdUDPAddReply{}) - err := vppcalls.AddBfdUDPSession(&bfd.SingleHopBFD_Session{ + err := bfdHandler.AddBfdUDPSession(&bfd.SingleHopBFD_Session{ SourceAddress: "10.0.0.1", DestinationAddress: "20.0.0.1", DesiredMinTxInterval: 10, @@ -111,7 +111,7 @@ func TestAddBfdUDPSessionAuthKeyNotFound(t *testing.T) { KeyId: 1, AdvertisedKeyId: 1, }, - }, 1, bfdKeyIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + }, 1, bfdKeyIndexes) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*bfd_api.BfdUDPAdd) @@ -120,22 +120,22 @@ func TestAddBfdUDPSessionAuthKeyNotFound(t *testing.T) { Expect(vppMsg.DesiredMinTx).To(BeEquivalentTo(10)) Expect(vppMsg.RequiredMinRx).To(BeEquivalentTo(15)) Expect(vppMsg.DetectMult).To(BeEquivalentTo(2)) - Expect(vppMsg.IsIpv6).To(BeEquivalentTo(0)) + Expect(vppMsg.IsIPv6).To(BeEquivalentTo(0)) Expect(vppMsg.IsAuthenticated).To(BeEquivalentTo(0)) } func TestAddBfdUDPSessionNoAuthKey(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&bfd_api.BfdUDPAddReply{}) - err := vppcalls.AddBfdUDPSession(&bfd.SingleHopBFD_Session{ + err := bfdHandler.AddBfdUDPSession(&bfd.SingleHopBFD_Session{ SourceAddress: "10.0.0.1", DestinationAddress: "20.0.0.1", DesiredMinTxInterval: 10, RequiredMinRxInterval: 15, DetectMultiplier: 2, - }, 1, nil, logrus.DefaultLogger(), ctx.MockChannel, nil) + }, 1, nil) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*bfd_api.BfdUDPAdd) @@ -144,20 +144,20 @@ func TestAddBfdUDPSessionNoAuthKey(t *testing.T) { Expect(vppMsg.DesiredMinTx).To(BeEquivalentTo(10)) Expect(vppMsg.RequiredMinRx).To(BeEquivalentTo(15)) Expect(vppMsg.DetectMult).To(BeEquivalentTo(2)) - Expect(vppMsg.IsIpv6).To(BeEquivalentTo(0)) + Expect(vppMsg.IsIPv6).To(BeEquivalentTo(0)) Expect(vppMsg.IsAuthenticated).To(BeEquivalentTo(0)) } func TestAddBfdUDPSessionIncorrectSrcIPError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() bfdKeyIndexes := nametoidx.NewNameToIdx(logrus.DefaultLogger(), "bfd", nil) - bfdKeyIndexes.RegisterName(string(1), 1, nil) + bfdKeyIndexes.RegisterName(ifplugin.AuthKeyIdentifier(1), 1, nil) ctx.MockVpp.MockReply(&bfd_api.BfdUDPAddReply{}) - err := vppcalls.AddBfdUDPSession(&bfd.SingleHopBFD_Session{ + err := bfdHandler.AddBfdUDPSession(&bfd.SingleHopBFD_Session{ SourceAddress: "incorrect-ip", DestinationAddress: "20.0.0.1", DesiredMinTxInterval: 10, @@ -167,13 +167,13 @@ func TestAddBfdUDPSessionIncorrectSrcIPError(t *testing.T) { KeyId: 1, AdvertisedKeyId: 1, }, - }, 1, bfdKeyIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + }, 1, bfdKeyIndexes) Expect(err).ToNot(BeNil()) } func TestAddBfdUDPSessionIncorrectDstIPError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() bfdKeyIndexes := nametoidx.NewNameToIdx(logrus.DefaultLogger(), "bfd", nil) @@ -181,7 +181,7 @@ func TestAddBfdUDPSessionIncorrectDstIPError(t *testing.T) { ctx.MockVpp.MockReply(&bfd_api.BfdUDPAddReply{}) - err := vppcalls.AddBfdUDPSession(&bfd.SingleHopBFD_Session{ + err := bfdHandler.AddBfdUDPSession(&bfd.SingleHopBFD_Session{ SourceAddress: "10.0.0.1", DestinationAddress: "incorrect-ip", DesiredMinTxInterval: 10, @@ -191,13 +191,13 @@ func TestAddBfdUDPSessionIncorrectDstIPError(t *testing.T) { KeyId: 1, AdvertisedKeyId: 1, }, - }, 1, bfdKeyIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + }, 1, bfdKeyIndexes) Expect(err).ToNot(BeNil()) } func TestAddBfdUDPSessionIPVerError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() bfdKeyIndexes := nametoidx.NewNameToIdx(logrus.DefaultLogger(), "bfd", nil) @@ -205,7 +205,7 @@ func TestAddBfdUDPSessionIPVerError(t *testing.T) { ctx.MockVpp.MockReply(&bfd_api.BfdUDPAddReply{}) - err := vppcalls.AddBfdUDPSession(&bfd.SingleHopBFD_Session{ + err := bfdHandler.AddBfdUDPSession(&bfd.SingleHopBFD_Session{ SourceAddress: "10.0.0.1", DestinationAddress: "2001:db8:0:1:1:1:1:1", DesiredMinTxInterval: 10, @@ -215,47 +215,47 @@ func TestAddBfdUDPSessionIPVerError(t *testing.T) { KeyId: 1, AdvertisedKeyId: 1, }, - }, 1, bfdKeyIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + }, 1, bfdKeyIndexes) Expect(err).ToNot(BeNil()) } func TestAddBfdUDPSessionError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&bfd_api.BfdAuthSetKeyReply{}) - err := vppcalls.AddBfdUDPSession(&bfd.SingleHopBFD_Session{ + err := bfdHandler.AddBfdUDPSession(&bfd.SingleHopBFD_Session{ SourceAddress: "10.0.0.1", DestinationAddress: "20.0.0.1", DesiredMinTxInterval: 10, RequiredMinRxInterval: 15, DetectMultiplier: 2, - }, 1, nil, logrus.DefaultLogger(), ctx.MockChannel, nil) + }, 1, nil) Expect(err).ToNot(BeNil()) } func TestAddBfdUDPSessionRetvalError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&bfd_api.BfdUDPAddReply{ Retval: 1, }) - err := vppcalls.AddBfdUDPSession(&bfd.SingleHopBFD_Session{ + err := bfdHandler.AddBfdUDPSession(&bfd.SingleHopBFD_Session{ SourceAddress: "10.0.0.1", DestinationAddress: "20.0.0.1", DesiredMinTxInterval: 10, RequiredMinRxInterval: 15, DetectMultiplier: 2, - }, 1, nil, logrus.DefaultLogger(), ctx.MockChannel, nil) + }, 1, nil) Expect(err).ToNot(BeNil()) } func TestAddBfdUDPSessionFromDetails(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() bfdKeyIndexes := nametoidx.NewNameToIdx(logrus.DefaultLogger(), "bfd", nil) @@ -263,17 +263,17 @@ func TestAddBfdUDPSessionFromDetails(t *testing.T) { ctx.MockVpp.MockReply(&bfd_api.BfdUDPAddReply{}) - err := vppcalls.AddBfdUDPSessionFromDetails(&bfd_api.BfdUDPSessionDetails{ + err := bfdHandler.AddBfdUDPSessionFromDetails(&bfd_api.BfdUDPSessionDetails{ SwIfIndex: 1, LocalAddr: net.ParseIP("10.0.0.1"), PeerAddr: net.ParseIP("20.0.0.1"), - IsIpv6: 0, + IsIPv6: 0, IsAuthenticated: 1, BfdKeyID: 1, RequiredMinRx: 15, DesiredMinTx: 10, DetectMult: 2, - }, bfdKeyIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + }, bfdKeyIndexes) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*bfd_api.BfdUDPAdd) @@ -282,29 +282,29 @@ func TestAddBfdUDPSessionFromDetails(t *testing.T) { Expect(vppMsg.DesiredMinTx).To(BeEquivalentTo(10)) Expect(vppMsg.RequiredMinRx).To(BeEquivalentTo(15)) Expect(vppMsg.DetectMult).To(BeEquivalentTo(2)) - Expect(vppMsg.IsIpv6).To(BeEquivalentTo(0)) + Expect(vppMsg.IsIPv6).To(BeEquivalentTo(0)) Expect(vppMsg.IsAuthenticated).To(BeEquivalentTo(1)) } func TestAddBfdUDPSessionFromDetailsAuthKeyNotFound(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() bfdKeyIndexes := nametoidx.NewNameToIdx(logrus.DefaultLogger(), "bfd", nil) ctx.MockVpp.MockReply(&bfd_api.BfdUDPAddReply{}) - err := vppcalls.AddBfdUDPSessionFromDetails(&bfd_api.BfdUDPSessionDetails{ + err := bfdHandler.AddBfdUDPSessionFromDetails(&bfd_api.BfdUDPSessionDetails{ SwIfIndex: 1, LocalAddr: net.ParseIP("10.0.0.1"), PeerAddr: net.ParseIP("20.0.0.1"), - IsIpv6: 0, + IsIPv6: 0, IsAuthenticated: 1, BfdKeyID: 1, RequiredMinRx: 15, DesiredMinTx: 10, DetectMult: 2, - }, bfdKeyIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + }, bfdKeyIndexes) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*bfd_api.BfdUDPAdd) @@ -313,24 +313,24 @@ func TestAddBfdUDPSessionFromDetailsAuthKeyNotFound(t *testing.T) { } func TestAddBfdUDPSessionFromDetailsNoAuth(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() bfdKeyIndexes := nametoidx.NewNameToIdx(logrus.DefaultLogger(), "bfd", nil) ctx.MockVpp.MockReply(&bfd_api.BfdUDPAddReply{}) - err := vppcalls.AddBfdUDPSessionFromDetails(&bfd_api.BfdUDPSessionDetails{ + err := bfdHandler.AddBfdUDPSessionFromDetails(&bfd_api.BfdUDPSessionDetails{ SwIfIndex: 1, LocalAddr: net.ParseIP("10.0.0.1"), PeerAddr: net.ParseIP("20.0.0.1"), - IsIpv6: 0, + IsIPv6: 0, IsAuthenticated: 0, BfdKeyID: 1, RequiredMinRx: 15, DesiredMinTx: 10, DetectMult: 2, - }, bfdKeyIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + }, bfdKeyIndexes) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*bfd_api.BfdUDPAdd) @@ -339,25 +339,25 @@ func TestAddBfdUDPSessionFromDetailsNoAuth(t *testing.T) { } func TestAddBfdUDPSessionFromDetailsError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() bfdKeyIndexes := nametoidx.NewNameToIdx(logrus.DefaultLogger(), "bfd", nil) ctx.MockVpp.MockReply(&bfd_api.BfdAuthSetKeyReply{}) - err := vppcalls.AddBfdUDPSessionFromDetails(&bfd_api.BfdUDPSessionDetails{ + err := bfdHandler.AddBfdUDPSessionFromDetails(&bfd_api.BfdUDPSessionDetails{ SwIfIndex: 1, LocalAddr: net.ParseIP("10.0.0.1"), PeerAddr: net.ParseIP("20.0.0.1"), - IsIpv6: 0, - }, bfdKeyIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + IsIPv6: 0, + }, bfdKeyIndexes) Expect(err).ToNot(BeNil()) } func TestAddBfdUDPSessionFromDetailsRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() bfdKeyIndexes := nametoidx.NewNameToIdx(logrus.DefaultLogger(), "bfd", nil) @@ -366,18 +366,18 @@ func TestAddBfdUDPSessionFromDetailsRetval(t *testing.T) { Retval: 1, }) - err := vppcalls.AddBfdUDPSessionFromDetails(&bfd_api.BfdUDPSessionDetails{ + err := bfdHandler.AddBfdUDPSessionFromDetails(&bfd_api.BfdUDPSessionDetails{ SwIfIndex: 1, LocalAddr: net.ParseIP("10.0.0.1"), PeerAddr: net.ParseIP("20.0.0.1"), - IsIpv6: 0, - }, bfdKeyIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + IsIPv6: 0, + }, bfdKeyIndexes) Expect(err).ToNot(BeNil()) } func TestModifyBfdUDPSession(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "if", nil)) @@ -385,14 +385,14 @@ func TestModifyBfdUDPSession(t *testing.T) { ctx.MockVpp.MockReply(&bfd_api.BfdUDPModReply{}) - err := vppcalls.ModifyBfdUDPSession(&bfd.SingleHopBFD_Session{ + err := bfdHandler.ModifyBfdUDPSession(&bfd.SingleHopBFD_Session{ Interface: "if1", SourceAddress: "10.0.0.1", DestinationAddress: "20.0.0.1", DesiredMinTxInterval: 10, RequiredMinRxInterval: 15, DetectMultiplier: 2, - }, ifIndexes, ctx.MockChannel, nil) + }, ifIndexes) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*bfd_api.BfdUDPMod) @@ -401,11 +401,11 @@ func TestModifyBfdUDPSession(t *testing.T) { Expect(vppMsg.DesiredMinTx).To(BeEquivalentTo(10)) Expect(vppMsg.RequiredMinRx).To(BeEquivalentTo(15)) Expect(vppMsg.DetectMult).To(BeEquivalentTo(2)) - Expect(vppMsg.IsIpv6).To(BeEquivalentTo(0)) + Expect(vppMsg.IsIPv6).To(BeEquivalentTo(0)) } func TestModifyBfdUDPSessionIPv6(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "if", nil)) @@ -413,20 +413,20 @@ func TestModifyBfdUDPSessionIPv6(t *testing.T) { ctx.MockVpp.MockReply(&bfd_api.BfdUDPModReply{}) - err := vppcalls.ModifyBfdUDPSession(&bfd.SingleHopBFD_Session{ + err := bfdHandler.ModifyBfdUDPSession(&bfd.SingleHopBFD_Session{ Interface: "if1", SourceAddress: "2001:db8::1", DestinationAddress: "2001:db8:0:1:1:1:1:1", - }, ifIndexes, ctx.MockChannel, nil) + }, ifIndexes) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*bfd_api.BfdUDPMod) Expect(ok).To(BeTrue()) - Expect(vppMsg.IsIpv6).To(BeEquivalentTo(1)) + Expect(vppMsg.IsIPv6).To(BeEquivalentTo(1)) } func TestModifyBfdUDPSessionDifferentIPVer(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "if", nil)) @@ -434,34 +434,34 @@ func TestModifyBfdUDPSessionDifferentIPVer(t *testing.T) { ctx.MockVpp.MockReply(&bfd_api.BfdUDPModReply{}) - err := vppcalls.ModifyBfdUDPSession(&bfd.SingleHopBFD_Session{ + err := bfdHandler.ModifyBfdUDPSession(&bfd.SingleHopBFD_Session{ Interface: "if1", SourceAddress: "10.0.0.1", DestinationAddress: "2001:db8:0:1:1:1:1:1", - }, ifIndexes, ctx.MockChannel, nil) + }, ifIndexes) Expect(err).ToNot(BeNil()) } func TestModifyBfdUDPSessionNoInterface(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "if", nil)) ctx.MockVpp.MockReply(&bfd_api.BfdUDPModReply{}) - err := vppcalls.ModifyBfdUDPSession(&bfd.SingleHopBFD_Session{ + err := bfdHandler.ModifyBfdUDPSession(&bfd.SingleHopBFD_Session{ Interface: "if1", SourceAddress: "10.0.0.1", DestinationAddress: "20.0.0.1", - }, ifIndexes, ctx.MockChannel, nil) + }, ifIndexes) Expect(err).ToNot(BeNil()) } func TestModifyBfdUDPSessionInvalidSrcIP(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "if", nil)) @@ -469,17 +469,17 @@ func TestModifyBfdUDPSessionInvalidSrcIP(t *testing.T) { ctx.MockVpp.MockReply(&bfd_api.BfdUDPModReply{}) - err := vppcalls.ModifyBfdUDPSession(&bfd.SingleHopBFD_Session{ + err := bfdHandler.ModifyBfdUDPSession(&bfd.SingleHopBFD_Session{ Interface: "if1", SourceAddress: "invalid-ip", DestinationAddress: "20.0.0.1", - }, ifIndexes, ctx.MockChannel, nil) + }, ifIndexes) Expect(err).ToNot(BeNil()) } func TestModifyBfdUDPSessionInvalidDstIP(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "if", nil)) @@ -487,17 +487,17 @@ func TestModifyBfdUDPSessionInvalidDstIP(t *testing.T) { ctx.MockVpp.MockReply(&bfd_api.BfdUDPModReply{}) - err := vppcalls.ModifyBfdUDPSession(&bfd.SingleHopBFD_Session{ + err := bfdHandler.ModifyBfdUDPSession(&bfd.SingleHopBFD_Session{ Interface: "if1", SourceAddress: "10.0.0.1", DestinationAddress: "invalid-ip", - }, ifIndexes, ctx.MockChannel, nil) + }, ifIndexes) Expect(err).ToNot(BeNil()) } func TestModifyBfdUDPSessionError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "if", nil)) @@ -505,17 +505,17 @@ func TestModifyBfdUDPSessionError(t *testing.T) { ctx.MockVpp.MockReply(&bfd_api.BfdUDPAddReply{}) - err := vppcalls.ModifyBfdUDPSession(&bfd.SingleHopBFD_Session{ + err := bfdHandler.ModifyBfdUDPSession(&bfd.SingleHopBFD_Session{ Interface: "if1", SourceAddress: "10.0.0.1", DestinationAddress: "20.0.0.1", - }, ifIndexes, ctx.MockChannel, nil) + }, ifIndexes) Expect(err).ToNot(BeNil()) } func TestModifyBfdUDPSessionRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "if", nil)) @@ -525,22 +525,22 @@ func TestModifyBfdUDPSessionRetval(t *testing.T) { Retval: 1, }) - err := vppcalls.ModifyBfdUDPSession(&bfd.SingleHopBFD_Session{ + err := bfdHandler.ModifyBfdUDPSession(&bfd.SingleHopBFD_Session{ Interface: "if1", SourceAddress: "10.0.0.1", DestinationAddress: "20.0.0.1", - }, ifIndexes, ctx.MockChannel, nil) + }, ifIndexes) Expect(err).ToNot(BeNil()) } func TestDeleteBfdUDPSession(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&bfd_api.BfdUDPDelReply{}) - err := vppcalls.DeleteBfdUDPSession(1, "10.0.0.1", "20.0.0.1", ctx.MockChannel, nil) + err := bfdHandler.DeleteBfdUDPSession(1, "10.0.0.1", "20.0.0.1") Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*bfd_api.BfdUDPDel) @@ -548,99 +548,46 @@ func TestDeleteBfdUDPSession(t *testing.T) { Expect(vppMsg.SwIfIndex).To(BeEquivalentTo(1)) Expect(vppMsg.LocalAddr).To(BeEquivalentTo(net.ParseIP("10.0.0.1").To4())) Expect(vppMsg.PeerAddr).To(BeEquivalentTo(net.ParseIP("20.0.0.1").To4())) - Expect(vppMsg.IsIpv6).To(BeEquivalentTo(0)) + Expect(vppMsg.IsIPv6).To(BeEquivalentTo(0)) } func TestDeleteBfdUDPSessionError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&bfd_api.BfdUDPModReply{}) - err := vppcalls.DeleteBfdUDPSession(1, "10.0.0.1", "20.0.0.1", ctx.MockChannel, nil) + err := bfdHandler.DeleteBfdUDPSession(1, "10.0.0.1", "20.0.0.1") Expect(err).ToNot(BeNil()) } func TestDeleteBfdUDPSessionRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&bfd_api.BfdUDPDelReply{ Retval: 1, }) - err := vppcalls.DeleteBfdUDPSession(1, "10.0.0.1", "20.0.0.1", ctx.MockChannel, nil) + err := bfdHandler.DeleteBfdUDPSession(1, "10.0.0.1", "20.0.0.1") Expect(err).ToNot(BeNil()) } -func TestDumpBfdUDPSessions(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) - defer ctx.TeardownTestCtx() - - ctx.MockVpp.MockReply(&bfd_api.BfdUDPSessionDetails{ - SwIfIndex: 1, - LocalAddr: net.ParseIP("10.0.0.1"), - PeerAddr: net.ParseIP("20.0.0.1"), - }) - ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - - sessions, err := vppcalls.DumpBfdUDPSessions(ctx.MockChannel, nil) - - Expect(err).To(BeNil()) - Expect(sessions).To(HaveLen(1)) -} - -func TestDumpBfdUDPSessionsWithID(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) - defer ctx.TeardownTestCtx() - - // Authenticated wiht ID 1 - ctx.MockVpp.MockReply( - &bfd_api.BfdUDPSessionDetails{ - SwIfIndex: 1, - LocalAddr: net.ParseIP("10.0.0.1"), - PeerAddr: net.ParseIP("20.0.0.1"), - IsAuthenticated: 1, - BfdKeyID: 1, - }, - // Authenticated with ID 2 (filtered) - &bfd_api.BfdUDPSessionDetails{ - SwIfIndex: 2, - LocalAddr: net.ParseIP("10.0.0.2"), - PeerAddr: net.ParseIP("20.0.0.2"), - IsAuthenticated: 1, - BfdKeyID: 2, - }, - // Not authenticated - &bfd_api.BfdUDPSessionDetails{ - SwIfIndex: 3, - LocalAddr: net.ParseIP("10.0.0.3"), - PeerAddr: net.ParseIP("20.0.0.3"), - IsAuthenticated: 0, - }) - ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - - sessions, err := vppcalls.DumpBfdUDPSessionsWithID(1, ctx.MockChannel, nil) - - Expect(err).To(BeNil()) - Expect(sessions).To(HaveLen(1)) -} - func TestSetBfdUDPAuthenticationKeySha1(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&bfd_api.BfdAuthSetKeyReply{}) - err := vppcalls.SetBfdUDPAuthenticationKey(&bfd.SingleHopBFD_Key{ + err := bfdHandler.SetBfdUDPAuthenticationKey(&bfd.SingleHopBFD_Key{ Name: "bfd-key", AuthKeyIndex: 1, Id: 1, AuthenticationType: bfd.SingleHopBFD_Key_KEYED_SHA1, Secret: "secret", - }, logrus.DefaultLogger(), ctx.MockChannel, nil) + }) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*bfd_api.BfdAuthSetKey) @@ -652,18 +599,18 @@ func TestSetBfdUDPAuthenticationKeySha1(t *testing.T) { } func TestSetBfdUDPAuthenticationKeyMeticulous(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&bfd_api.BfdAuthSetKeyReply{}) - err := vppcalls.SetBfdUDPAuthenticationKey(&bfd.SingleHopBFD_Key{ + err := bfdHandler.SetBfdUDPAuthenticationKey(&bfd.SingleHopBFD_Key{ Name: "bfd-key", AuthKeyIndex: 1, Id: 1, AuthenticationType: bfd.SingleHopBFD_Key_METICULOUS_KEYED_SHA1, Secret: "secret", - }, logrus.DefaultLogger(), ctx.MockChannel, nil) + }) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*bfd_api.BfdAuthSetKey) @@ -675,18 +622,18 @@ func TestSetBfdUDPAuthenticationKeyMeticulous(t *testing.T) { } func TestSetBfdUDPAuthenticationKeyUnknown(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&bfd_api.BfdAuthSetKeyReply{}) - err := vppcalls.SetBfdUDPAuthenticationKey(&bfd.SingleHopBFD_Key{ + err := bfdHandler.SetBfdUDPAuthenticationKey(&bfd.SingleHopBFD_Key{ Name: "bfd-key", AuthKeyIndex: 1, Id: 1, AuthenticationType: 2, // Unknown type Secret: "secret", - }, logrus.DefaultLogger(), ctx.MockChannel, nil) + }) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*bfd_api.BfdAuthSetKey) @@ -698,54 +645,54 @@ func TestSetBfdUDPAuthenticationKeyUnknown(t *testing.T) { } func TestSetBfdUDPAuthenticationError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&bfd_api.BfdAuthDelKeyReply{}) - err := vppcalls.SetBfdUDPAuthenticationKey(&bfd.SingleHopBFD_Key{ + err := bfdHandler.SetBfdUDPAuthenticationKey(&bfd.SingleHopBFD_Key{ Name: "bfd-key", AuthKeyIndex: 1, Id: 1, AuthenticationType: bfd.SingleHopBFD_Key_KEYED_SHA1, Secret: "secret", - }, logrus.DefaultLogger(), ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } func TestSetBfdUDPAuthenticationRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&bfd_api.BfdAuthSetKeyReply{ Retval: 1, }) - err := vppcalls.SetBfdUDPAuthenticationKey(&bfd.SingleHopBFD_Key{ + err := bfdHandler.SetBfdUDPAuthenticationKey(&bfd.SingleHopBFD_Key{ Name: "bfd-key", AuthKeyIndex: 1, Id: 1, AuthenticationType: bfd.SingleHopBFD_Key_KEYED_SHA1, Secret: "secret", - }, logrus.DefaultLogger(), ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } func TestDeleteBfdUDPAuthenticationKey(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&bfd_api.BfdAuthDelKeyReply{}) - err := vppcalls.DeleteBfdUDPAuthenticationKey(&bfd.SingleHopBFD_Key{ + err := bfdHandler.DeleteBfdUDPAuthenticationKey(&bfd.SingleHopBFD_Key{ Name: "bfd-key", AuthKeyIndex: 1, Id: 1, AuthenticationType: bfd.SingleHopBFD_Key_KEYED_SHA1, Secret: "secret", - }, ctx.MockChannel, nil) + }) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*bfd_api.BfdAuthDelKey) @@ -754,65 +701,43 @@ func TestDeleteBfdUDPAuthenticationKey(t *testing.T) { } func TestDeleteBfdUDPAuthenticationKeyError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&bfd_api.BfdAuthSetKeyReply{}) - err := vppcalls.DeleteBfdUDPAuthenticationKey(&bfd.SingleHopBFD_Key{ + err := bfdHandler.DeleteBfdUDPAuthenticationKey(&bfd.SingleHopBFD_Key{ Name: "bfd-key", AuthKeyIndex: 1, Id: 1, AuthenticationType: bfd.SingleHopBFD_Key_KEYED_SHA1, Secret: "secret", - }, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } func TestDeleteBfdUDPAuthenticationKeyRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&bfd_api.BfdAuthDelKeyReply{ Retval: 1, }) - err := vppcalls.DeleteBfdUDPAuthenticationKey(&bfd.SingleHopBFD_Key{ + err := bfdHandler.DeleteBfdUDPAuthenticationKey(&bfd.SingleHopBFD_Key{ Name: "bfd-key", AuthKeyIndex: 1, Id: 1, AuthenticationType: bfd.SingleHopBFD_Key_KEYED_SHA1, Secret: "secret", - }, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } -func TestDumpBfdKeys(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) - defer ctx.TeardownTestCtx() - - ctx.MockVpp.MockReply(&bfd_api.BfdAuthKeysDetails{ - ConfKeyID: 1, - UseCount: 0, - AuthType: 4, - }, - &bfd_api.BfdAuthKeysDetails{ - ConfKeyID: 2, - UseCount: 1, - AuthType: 5, - }) - ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - - keys, err := vppcalls.DumpBfdKeys(ctx.MockChannel, nil) - - Expect(err).To(BeNil()) - Expect(keys).To(HaveLen(2)) -} - func TestAddBfdEchoFunction(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "if", nil)) @@ -820,10 +745,10 @@ func TestAddBfdEchoFunction(t *testing.T) { ctx.MockVpp.MockReply(&bfd_api.BfdUDPSetEchoSourceReply{}) - err := vppcalls.AddBfdEchoFunction(&bfd.SingleHopBFD_EchoFunction{ + err := bfdHandler.AddBfdEchoFunction(&bfd.SingleHopBFD_EchoFunction{ Name: "echo", EchoSourceInterface: "if1", - }, ifIndexes, ctx.MockChannel, nil) + }, ifIndexes) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*bfd_api.BfdUDPSetEchoSource) Expect(ok).To(BeTrue()) @@ -831,22 +756,22 @@ func TestAddBfdEchoFunction(t *testing.T) { } func TestAddBfdEchoFunctionInterfaceNotFound(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "if", nil)) ctx.MockVpp.MockReply(&bfd_api.BfdUDPSetEchoSourceReply{}) - err := vppcalls.AddBfdEchoFunction(&bfd.SingleHopBFD_EchoFunction{ + err := bfdHandler.AddBfdEchoFunction(&bfd.SingleHopBFD_EchoFunction{ Name: "echo", EchoSourceInterface: "if1", - }, ifIndexes, ctx.MockChannel, nil) + }, ifIndexes) Expect(err).ToNot(BeNil()) } func TestAddBfdEchoFunctionError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "if", nil)) @@ -854,15 +779,15 @@ func TestAddBfdEchoFunctionError(t *testing.T) { ctx.MockVpp.MockReply(&bfd_api.BfdUDPDelEchoSourceReply{}) - err := vppcalls.AddBfdEchoFunction(&bfd.SingleHopBFD_EchoFunction{ + err := bfdHandler.AddBfdEchoFunction(&bfd.SingleHopBFD_EchoFunction{ Name: "echo", EchoSourceInterface: "if1", - }, ifIndexes, ctx.MockChannel, nil) + }, ifIndexes) Expect(err).ToNot(BeNil()) } func TestAddBfdEchoFunctionRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "if", nil)) @@ -872,43 +797,51 @@ func TestAddBfdEchoFunctionRetval(t *testing.T) { Retval: 1, }) - err := vppcalls.AddBfdEchoFunction(&bfd.SingleHopBFD_EchoFunction{ + err := bfdHandler.AddBfdEchoFunction(&bfd.SingleHopBFD_EchoFunction{ Name: "echo", EchoSourceInterface: "if1", - }, ifIndexes, ctx.MockChannel, nil) + }, ifIndexes) Expect(err).ToNot(BeNil()) } func TestDeleteBfdEchoFunction(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&bfd_api.BfdUDPDelEchoSourceReply{}) - err := vppcalls.DeleteBfdEchoFunction(ctx.MockChannel, nil) + err := bfdHandler.DeleteBfdEchoFunction() Expect(err).To(BeNil()) _, ok := ctx.MockChannel.Msg.(*bfd_api.BfdUDPDelEchoSource) Expect(ok).To(BeTrue()) } func TestDeleteBfdEchoFunctionError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&bfd_api.BfdUDPSetEchoSourceReply{}) - err := vppcalls.DeleteBfdEchoFunction(ctx.MockChannel, nil) + err := bfdHandler.DeleteBfdEchoFunction() Expect(err).ToNot(BeNil()) } func TestDeleteBfdEchoFunctionRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bfdHandler, _ := bfdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&bfd_api.BfdUDPDelEchoSourceReply{ Retval: 1, }) - err := vppcalls.DeleteBfdEchoFunction(ctx.MockChannel, nil) + err := bfdHandler.DeleteBfdEchoFunction() Expect(err).ToNot(BeNil()) } + +func bfdTestSetup(t *testing.T) (*vppcallmock.TestCtx, vppcalls.BfdVppAPI, ifaceidx.SwIfIndexRW) { + ctx := vppcallmock.SetupTestCtx(t) + log := logrus.NewLogger("test-log") + ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(log, "bfd-if-idx", nil)) + bfdHandler := vppcalls.NewBfdVppHandler(ctx.MockChannel, ifIndexes, log, nil) + return ctx, bfdHandler, ifIndexes +} diff --git a/plugins/vpp/ifplugin/vppcalls/compat_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/compat_vppcalls.go deleted file mode 100644 index 6019375dd1..0000000000 --- a/plugins/vpp/ifplugin/vppcalls/compat_vppcalls.go +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (c) 2017 Cisco and/or its affiliates. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at: -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package vppcalls - -import ( - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/af_packet" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/bfd" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/memif" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/nat" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/stn" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/tap" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/tapv2" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/vxlan" -) - -// CheckMsgCompatibilityForInterface checks if interface CRSs are compatible with VPP in runtime. -func CheckMsgCompatibilityForInterface(log logging.Logger, vppChan govppapi.Channel) error { - msgs := []govppapi.Message{ - &memif.MemifCreate{}, - &memif.MemifCreateReply{}, - &memif.MemifDelete{}, - &memif.MemifDeleteReply{}, - &memif.MemifDump{}, - &memif.MemifDetails{}, - &memif.MemifSocketFilenameDump{}, - &memif.MemifSocketFilenameDetails{}, - - &interfaces.CreateLoopback{}, - &interfaces.CreateLoopbackReply{}, - - &vxlan.VxlanAddDelTunnel{}, - &vxlan.VxlanAddDelTunnelReply{}, - &vxlan.VxlanTunnelDump{}, - &vxlan.VxlanTunnelDetails{}, - - &af_packet.AfPacketCreate{}, - &af_packet.AfPacketCreateReply{}, - &af_packet.AfPacketDelete{}, - &af_packet.AfPacketDeleteReply{}, - - &tap.TapConnect{}, - &tap.TapConnectReply{}, - &tap.TapDelete{}, - &tap.TapDeleteReply{}, - &tap.SwInterfaceTapDump{}, - &tap.SwInterfaceTapDetails{}, - - &tapv2.TapCreateV2{}, - &tapv2.TapCreateV2Reply{}, - &tapv2.TapDeleteV2{}, - &tapv2.TapDeleteV2Reply{}, - - &interfaces.SwInterfaceDump{}, - &interfaces.SwInterfaceDetails{}, - &interfaces.SwInterfaceEvent{}, - &interfaces.SwInterfaceSetFlags{}, - &interfaces.SwInterfaceSetFlagsReply{}, - &interfaces.SwInterfaceAddDelAddress{}, - &interfaces.SwInterfaceAddDelAddressReply{}, - &interfaces.SwInterfaceSetMacAddress{}, - &interfaces.SwInterfaceSetMacAddressReply{}, - &interfaces.SwInterfaceSetTable{}, - &interfaces.SwInterfaceSetTableReply{}, - &interfaces.SwInterfaceGetTable{}, - &interfaces.SwInterfaceGetTableReply{}, - &interfaces.SwInterfaceSetUnnumbered{}, - &interfaces.SwInterfaceSetUnnumberedReply{}, - &interfaces.SwInterfaceTagAddDel{}, - &interfaces.SwInterfaceTagAddDelReply{}, - &interfaces.SwInterfaceSetMtu{}, - &interfaces.SwInterfaceSetMtuReply{}, - &interfaces.HwInterfaceSetMtu{}, - &interfaces.HwInterfaceSetMtuReply{}, - - &ip.IPAddressDump{}, - &ip.IPAddressDetails{}, - &ip.IPFibDump{}, - &ip.IPFibDetails{}, - &ip.IPTableAddDel{}, - &ip.IPTableAddDelReply{}, - &ip.IPContainerProxyAddDel{}, - &ip.IPContainerProxyAddDelReply{}, - } - err := vppChan.CheckMessageCompatibility(msgs...) - if err != nil { - log.Error(err) - } - return err -} - -// CheckMsgCompatibilityForBfd checks if bfd CRSs are compatible with VPP in runtime. -func CheckMsgCompatibilityForBfd(vppChan govppapi.Channel) error { - msgs := []govppapi.Message{ - &bfd.BfdUDPAdd{}, - &bfd.BfdUDPAddReply{}, - &bfd.BfdUDPMod{}, - &bfd.BfdUDPModReply{}, - &bfd.BfdUDPDel{}, - &bfd.BfdUDPDelReply{}, - &bfd.BfdAuthSetKey{}, - &bfd.BfdAuthSetKeyReply{}, - &bfd.BfdAuthDelKey{}, - &bfd.BfdAuthDelKeyReply{}, - } - return vppChan.CheckMessageCompatibility(msgs...) -} - -// CheckMsgCompatibilityForNat verifies compatibility of used binary API calls -func CheckMsgCompatibilityForNat(vppChan govppapi.Channel) error { - msgs := []govppapi.Message{ - &nat.Nat44AddDelAddressRange{}, - &nat.Nat44AddDelAddressRangeReply{}, - &nat.Nat44ForwardingEnableDisable{}, - &nat.Nat44ForwardingEnableDisableReply{}, - &nat.Nat44InterfaceAddDelFeature{}, - &nat.Nat44InterfaceAddDelFeatureReply{}, - &nat.Nat44AddDelStaticMapping{}, - &nat.Nat44AddDelStaticMappingReply{}, - &nat.Nat44AddDelLbStaticMapping{}, - &nat.Nat44AddDelLbStaticMappingReply{}, - } - return vppChan.CheckMessageCompatibility(msgs...) -} - -// CheckMsgCompatibilityForStn verifies compatibility of used binary API calls -func CheckMsgCompatibilityForStn(vppChan govppapi.Channel) error { - msgs := []govppapi.Message{ - &stn.StnAddDelRule{}, - &stn.StnAddDelRuleReply{}, - } - return vppChan.CheckMessageCompatibility(msgs...) -} diff --git a/plugins/vpp/ifplugin/vppcalls/dhcp_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/dhcp_vppcalls.go index 2b796fdb22..0a9664b588 100644 --- a/plugins/vpp/ifplugin/vppcalls/dhcp_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/dhcp_vppcalls.go @@ -18,44 +18,39 @@ import ( "fmt" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/vpp-agent/plugins/vpp/binapi/dhcp" ) -func handleInterfaceDHCP(ifIdx uint32, hostName string, isAdd bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +func (h *IfVppHandler) handleInterfaceDHCP(ifIdx uint32, hostName string, isAdd bool) error { defer func(t time.Time) { - stopwatch.TimeLog(dhcp.DhcpClientConfig{}).LogTimeEntry(time.Since(t)) + h.stopwatch.TimeLog(dhcp.DHCPClientConfig{}).LogTimeEntry(time.Since(t)) }(time.Now()) - req := &dhcp.DhcpClientConfig{ - Client: dhcp.DhcpClient{ + req := &dhcp.DHCPClientConfig{ + IsAdd: boolToUint(isAdd), + Client: dhcp.DHCPClient{ SwIfIndex: ifIdx, Hostname: []byte(hostName), - WantDhcpEvent: 1, + WantDHCPEvent: 1, }, } - if isAdd { - req.IsAdd = 1 - } + reply := &dhcp.DHCPClientConfigReply{} - reply := &dhcp.DhcpClientConfigReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return nil } -// SetInterfaceAsDHCPClient sets provided interface as a DHCP client -func SetInterfaceAsDHCPClient(ifIdx uint32, hostName string, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (err error) { - return handleInterfaceDHCP(ifIdx, hostName, true, vppChan, stopwatch) +// SetInterfaceAsDHCPClient implements interface handler. +func (h *IfVppHandler) SetInterfaceAsDHCPClient(ifIdx uint32, hostName string) error { + return h.handleInterfaceDHCP(ifIdx, hostName, true) } -// UnsetInterfaceAsDHCPClient un-sets interface as DHCP client -func UnsetInterfaceAsDHCPClient(ifIdx uint32, hostName string, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (err error) { - return handleInterfaceDHCP(ifIdx, hostName, false, vppChan, stopwatch) +// UnsetInterfaceAsDHCPClient implements interface handler. +func (h *IfVppHandler) UnsetInterfaceAsDHCPClient(ifIdx uint32, hostName string) error { + return h.handleInterfaceDHCP(ifIdx, hostName, false) } diff --git a/plugins/vpp/ifplugin/vppcalls/dhcp_vppcalls_test.go b/plugins/vpp/ifplugin/vppcalls/dhcp_vppcalls_test.go index bca0cf24de..c8391e9c0b 100644 --- a/plugins/vpp/ifplugin/vppcalls/dhcp_vppcalls_test.go +++ b/plugins/vpp/ifplugin/vppcalls/dhcp_vppcalls_test.go @@ -18,89 +18,87 @@ import ( "testing" "github.com/ligato/vpp-agent/plugins/vpp/binapi/dhcp" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" - "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" ) func TestSetInterfaceAsDHCPClient(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() - ctx.MockVpp.MockReply(&dhcp.DhcpClientConfigReply{}) + ctx.MockVpp.MockReply(&dhcp.DHCPClientConfigReply{}) - err := vppcalls.SetInterfaceAsDHCPClient(1, "hostName", ctx.MockChannel, nil) + err := ifHandler.SetInterfaceAsDHCPClient(1, "hostName") Expect(err).To(BeNil()) - vppMsg, ok := ctx.MockChannel.Msg.(*dhcp.DhcpClientConfig) + vppMsg, ok := ctx.MockChannel.Msg.(*dhcp.DHCPClientConfig) Expect(ok).To(BeTrue()) Expect(vppMsg.Client.SwIfIndex).To(BeEquivalentTo(1)) Expect(vppMsg.Client.Hostname).To(BeEquivalentTo([]byte("hostName"))) - Expect(vppMsg.Client.WantDhcpEvent).To(BeEquivalentTo(1)) + Expect(vppMsg.Client.WantDHCPEvent).To(BeEquivalentTo(1)) Expect(vppMsg.IsAdd).To(BeEquivalentTo(1)) } func TestSetInterfaceAsDHCPClientError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() - ctx.MockVpp.MockReply(&dhcp.DhcpComplEvent{}) + ctx.MockVpp.MockReply(&dhcp.DHCPComplEvent{}) - err := vppcalls.SetInterfaceAsDHCPClient(1, "hostName", ctx.MockChannel, nil) + err := ifHandler.SetInterfaceAsDHCPClient(1, "hostName") Expect(err).ToNot(BeNil()) } func TestSetInterfaceAsDHCPClientRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() - ctx.MockVpp.MockReply(&dhcp.DhcpClientConfigReply{ + ctx.MockVpp.MockReply(&dhcp.DHCPClientConfigReply{ Retval: 1, }) - err := vppcalls.SetInterfaceAsDHCPClient(1, "hostName", ctx.MockChannel, nil) + err := ifHandler.SetInterfaceAsDHCPClient(1, "hostName") Expect(err).ToNot(BeNil()) } func TestUnsetInterfaceAsDHCPClient(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() - ctx.MockVpp.MockReply(&dhcp.DhcpClientConfigReply{}) + ctx.MockVpp.MockReply(&dhcp.DHCPClientConfigReply{}) - err := vppcalls.UnsetInterfaceAsDHCPClient(1, "hostName", ctx.MockChannel, nil) + err := ifHandler.UnsetInterfaceAsDHCPClient(1, "hostName") Expect(err).To(BeNil()) - vppMsg, ok := ctx.MockChannel.Msg.(*dhcp.DhcpClientConfig) + vppMsg, ok := ctx.MockChannel.Msg.(*dhcp.DHCPClientConfig) Expect(ok).To(BeTrue()) Expect(vppMsg.Client.SwIfIndex).To(BeEquivalentTo(1)) Expect(vppMsg.Client.Hostname).To(BeEquivalentTo([]byte("hostName"))) - Expect(vppMsg.Client.WantDhcpEvent).To(BeEquivalentTo(1)) + Expect(vppMsg.Client.WantDHCPEvent).To(BeEquivalentTo(1)) Expect(vppMsg.IsAdd).To(BeEquivalentTo(0)) } func TestUnsetInterfaceAsDHCPClientError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() - ctx.MockVpp.MockReply(&dhcp.DhcpComplEvent{}) + ctx.MockVpp.MockReply(&dhcp.DHCPComplEvent{}) - err := vppcalls.UnsetInterfaceAsDHCPClient(1, "hostName", ctx.MockChannel, nil) + err := ifHandler.UnsetInterfaceAsDHCPClient(1, "hostName") Expect(err).ToNot(BeNil()) } func TestUnsetInterfaceAsDHCPClientRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() - ctx.MockVpp.MockReply(&dhcp.DhcpClientConfigReply{ + ctx.MockVpp.MockReply(&dhcp.DHCPClientConfigReply{ Retval: 1, }) - err := vppcalls.UnsetInterfaceAsDHCPClient(1, "hostName", ctx.MockChannel, nil) + err := ifHandler.UnsetInterfaceAsDHCPClient(1, "hostName") Expect(err).ToNot(BeNil()) } diff --git a/plugins/vpp/ifplugin/vppcalls/doc.go b/plugins/vpp/ifplugin/vppcalls/doc.go index b6a8c38966..c2b6f93842 100644 --- a/plugins/vpp/ifplugin/vppcalls/doc.go +++ b/plugins/vpp/ifplugin/vppcalls/doc.go @@ -1,3 +1,3 @@ // Package vppcalls contains wrappers over VPP binary APIs for all supported -// interface types. +// interface types and for dumping all interfaces configured in VPP. package vppcalls diff --git a/plugins/vpp/ifplugin/vppcalls/dump_bfd_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/dump_bfd_vppcalls.go new file mode 100644 index 0000000000..bb300ddbc1 --- /dev/null +++ b/plugins/vpp/ifplugin/vppcalls/dump_bfd_vppcalls.go @@ -0,0 +1,197 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vppcalls + +import ( + "net" + "time" + + bfdapi "github.com/ligato/vpp-agent/plugins/vpp/binapi/bfd" + "github.com/ligato/vpp-agent/plugins/vpp/model/bfd" +) + +// BfdDetails is the wrapper structure for the BFD northbound API structure. +type BfdDetails struct { + Bfd *bfd.SingleHopBFD `json:"bfd"` + Meta *BfdMeta `json:"bfd_meta"` +} + +// BfdMeta is combination of proto-modelled BFD data and VPP provided metadata +type BfdMeta struct { + *BfdSessionMeta `json:"bfd_session_meta"` + *BfdAuthKeyMeta `json:"bfd_authkey_meta"` +} + +// DumpBfdSingleHop implements BFD handler. +func (handler *BfdVppHandler) DumpBfdSingleHop() (*BfdDetails, error) { + sessionDetails, err := handler.DumpBfdSessions() + if err != nil { + return nil, err + } + keyDetails, err := handler.DumpBfdAuthKeys() + if err != nil { + return nil, err + } + + return &BfdDetails{ + Bfd: &bfd.SingleHopBFD{ + Sessions: sessionDetails.Session, + Keys: keyDetails.AuthKeys, + }, + Meta: &BfdMeta{ + BfdSessionMeta: sessionDetails.Meta, + BfdAuthKeyMeta: keyDetails.Meta, + }, + }, nil +} + +// BfdSessionDetails is the wrapper structure for the BFD session northbound API structure. +type BfdSessionDetails struct { + Session []*bfd.SingleHopBFD_Session + Meta *BfdSessionMeta +} + +// BfdSessionMeta is combination of proto-modelled BFD session data and session interface to index map +type BfdSessionMeta struct { + SessionIfToIdx map[uint32]string +} + +// DumpBfdSessions implements BFD handler. +func (handler *BfdVppHandler) DumpBfdSessions() (*BfdSessionDetails, error) { + defer func(t time.Time) { + handler.stopwatch.TimeLog(bfdapi.BfdUDPSessionDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + var sessions []*bfd.SingleHopBFD_Session + meta := &BfdSessionMeta{ + SessionIfToIdx: make(map[uint32]string), + } + + req := &bfdapi.BfdUDPSessionDump{} + sessionsRequest := handler.callsChannel.SendMultiRequest(req) + + for { + sessionDetails := &bfdapi.BfdUDPSessionDetails{} + stop, err := sessionsRequest.ReceiveReply(sessionDetails) + if stop { + break + } + if err != nil { + return nil, err + } + + ifName, _, exists := handler.ifIndexes.LookupName(sessionDetails.SwIfIndex) + if !exists { + handler.log.Warnf("BFD session dump: interface name not found for index %d", sessionDetails.SwIfIndex) + } + var srcAddr, dstAddr net.IP = sessionDetails.LocalAddr, sessionDetails.PeerAddr + + // Put session info + sessions = append(sessions, &bfd.SingleHopBFD_Session{ + Interface: ifName, + DestinationAddress: dstAddr.String(), + SourceAddress: srcAddr.String(), + DesiredMinTxInterval: sessionDetails.DesiredMinTx, + RequiredMinRxInterval: sessionDetails.RequiredMinRx, + DetectMultiplier: uint32(sessionDetails.DetectMult), + Authentication: &bfd.SingleHopBFD_Session_Authentication{ + KeyId: uint32(sessionDetails.BfdKeyID), + AdvertisedKeyId: uint32(sessionDetails.ConfKeyID), + }, + }) + // Put bfd interface info + meta.SessionIfToIdx[sessionDetails.SwIfIndex] = ifName + } + + return &BfdSessionDetails{ + Session: sessions, + Meta: meta, + }, nil +} + +// DumpBfdUDPSessionsWithID implements BFD handler. +func (handler *BfdVppHandler) DumpBfdUDPSessionsWithID(authKeyIndex uint32) (*BfdSessionDetails, error) { + details, err := handler.DumpBfdSessions() + if err != nil || len(details.Session) == 0 { + return nil, err + } + + var indexedSessions []*bfd.SingleHopBFD_Session + for _, session := range details.Session { + if session.Authentication != nil && session.Authentication.KeyId == authKeyIndex { + indexedSessions = append(indexedSessions, session) + } + } + + return &BfdSessionDetails{ + Session: indexedSessions, + }, nil +} + +// BfdAuthKeyDetails is the wrapper structure for the BFD authentication key northbound API structure. +type BfdAuthKeyDetails struct { + AuthKeys []*bfd.SingleHopBFD_Key + Meta *BfdAuthKeyMeta +} + +// BfdAuthKeyMeta is combination of proto-modelled BFD session data and key-to-usage map +type BfdAuthKeyMeta struct { + KeyIDToUseCount map[uint32]uint32 +} + +// DumpBfdAuthKeys implements BFD handler. +func (handler *BfdVppHandler) DumpBfdAuthKeys() (*BfdAuthKeyDetails, error) { + defer func(t time.Time) { + handler.stopwatch.TimeLog(bfdapi.BfdAuthKeysDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + var authKeys []*bfd.SingleHopBFD_Key + meta := &BfdAuthKeyMeta{ + KeyIDToUseCount: make(map[uint32]uint32), + } + + req := &bfdapi.BfdAuthKeysDump{} + keysRequest := handler.callsChannel.SendMultiRequest(req) + + for { + keyDetails := &bfdapi.BfdAuthKeysDetails{} + stop, err := keysRequest.ReceiveReply(keyDetails) + if stop { + break + } + if err != nil { + return nil, err + } + + // Put auth key info + authKeys = append(authKeys, &bfd.SingleHopBFD_Key{ + AuthKeyIndex: keyDetails.ConfKeyID, + Id: keyDetails.ConfKeyID, + AuthenticationType: func(authType uint8) bfd.SingleHopBFD_Key_AuthenticationType { + if authType == 4 { + return bfd.SingleHopBFD_Key_KEYED_SHA1 + } + return bfd.SingleHopBFD_Key_METICULOUS_KEYED_SHA1 + }(keyDetails.AuthType), + }) + // Put bfd key use count info + meta.KeyIDToUseCount[keyDetails.ConfKeyID] = keyDetails.UseCount + } + + return &BfdAuthKeyDetails{ + AuthKeys: authKeys, + Meta: meta, + }, nil +} diff --git a/plugins/vpp/ifplugin/vppcalls/dump_bfd_vppcalls_test.go b/plugins/vpp/ifplugin/vppcalls/dump_bfd_vppcalls_test.go new file mode 100644 index 0000000000..153c9894f1 --- /dev/null +++ b/plugins/vpp/ifplugin/vppcalls/dump_bfd_vppcalls_test.go @@ -0,0 +1,103 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vppcalls_test + +import ( + "net" + "testing" + + bfd_api "github.com/ligato/vpp-agent/plugins/vpp/binapi/bfd" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/vpe" + . "github.com/onsi/gomega" +) + +// TestDumpBfdUDPSessions tests BFD udp session dump +func TestDumpBfdUDPSessions(t *testing.T) { + ctx, bfdHandler, _ := bfdTestSetup(t) + defer ctx.TeardownTestCtx() + + ctx.MockVpp.MockReply(&bfd_api.BfdUDPSessionDetails{ + SwIfIndex: 1, + LocalAddr: net.ParseIP("10.0.0.1"), + PeerAddr: net.ParseIP("20.0.0.1"), + }) + ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) + + bfdConfig, err := bfdHandler.DumpBfdSessions() + + Expect(err).To(BeNil()) + Expect(bfdConfig.Session).To(HaveLen(1)) +} + +// TestDumpBfdUDPSessions tests BFD udp session dump where the result is filtered +// according to session authentication key ID +func TestDumpBfdUDPSessionsWithID(t *testing.T) { + ctx, bfdHandler, _ := bfdTestSetup(t) + defer ctx.TeardownTestCtx() + + // Authenticated wiht ID 1 + ctx.MockVpp.MockReply( + &bfd_api.BfdUDPSessionDetails{ + SwIfIndex: 1, + LocalAddr: net.ParseIP("10.0.0.1"), + PeerAddr: net.ParseIP("20.0.0.1"), + IsAuthenticated: 1, + BfdKeyID: 1, + }, + // Authenticated with ID 2 (filtered) + &bfd_api.BfdUDPSessionDetails{ + SwIfIndex: 2, + LocalAddr: net.ParseIP("10.0.0.2"), + PeerAddr: net.ParseIP("20.0.0.2"), + IsAuthenticated: 1, + BfdKeyID: 2, + }, + // Not authenticated + &bfd_api.BfdUDPSessionDetails{ + SwIfIndex: 3, + LocalAddr: net.ParseIP("10.0.0.3"), + PeerAddr: net.ParseIP("20.0.0.3"), + IsAuthenticated: 0, + }) + ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) + + bfdConfig, err := bfdHandler.DumpBfdUDPSessionsWithID(1) + + Expect(err).To(BeNil()) + Expect(bfdConfig.Session).To(HaveLen(1)) +} + +// TestDumpBfdKeys tests BFD key dump +func TestDumpBfdKeys(t *testing.T) { + ctx, bfdHandler, _ := bfdTestSetup(t) + defer ctx.TeardownTestCtx() + + ctx.MockVpp.MockReply(&bfd_api.BfdAuthKeysDetails{ + ConfKeyID: 1, + UseCount: 0, + AuthType: 4, + }, + &bfd_api.BfdAuthKeysDetails{ + ConfKeyID: 2, + UseCount: 1, + AuthType: 5, + }) + ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) + + bfdConfig, err := bfdHandler.DumpBfdAuthKeys() + + Expect(err).To(BeNil()) + Expect(bfdConfig.AuthKeys).To(HaveLen(2)) +} diff --git a/plugins/vpp/ifplugin/vppcalls/dump_interface_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/dump_interface_vppcalls.go new file mode 100644 index 0000000000..33373f27d8 --- /dev/null +++ b/plugins/vpp/ifplugin/vppcalls/dump_interface_vppcalls.go @@ -0,0 +1,541 @@ +// Copyright (c) 2017 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vppcalls + +import ( + "bytes" + "fmt" + "net" + "strings" + "time" + + "github.com/ligato/cn-infra/logging/measure" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/dhcp" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/memif" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/tap" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/tapv2" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/vxlan" + ifnb "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" +) + +// Default VPP MTU value +const defaultVPPMtu = 9216 + +// InterfaceDetails is the wrapper structure for the interface northbound API structure. +type InterfaceDetails struct { + Interface *ifnb.Interfaces_Interface `json:"interface"` + Meta *InterfaceMeta `json:"interface_meta"` +} + +// InterfaceMeta is combination of proto-modelled Interface data and VPP provided metadata +type InterfaceMeta struct { + SwIfIndex uint32 `json:"sw_if_index"` + Tag string `json:"tag"` + InternalName string `json:"internal_name"` + Dhcp *Dhcp `json:"dhcp"` +} + +// Dhcp is helper struct for DHCP metadata, split to client and lease (similar to VPP binary API) +type Dhcp struct { + Client *Client `json:"dhcp_client"` + Lease *Lease `json:"dhcp_lease"` +} + +// Client is helper struct grouping DHCP client data +type Client struct { + SwIfIndex uint32 + Hostname string + ID string + WantDhcpEvent bool + SetBroadcastFlag bool + Pid uint32 +} + +// Lease is helper struct grouping DHCP lease data +type Lease struct { + SwIfIndex uint32 + State uint8 + Hostname string + IsIPv6 bool + MaskWidth uint8 + HostAddress string + RouterAddress string + HostMac string +} + +// DumpInterfacesByType implements interface handler. +func (h *IfVppHandler) DumpInterfacesByType(reqType ifnb.InterfaceType) (map[uint32]*InterfaceDetails, error) { + // Dump all + ifs, err := h.DumpInterfaces() + if err != nil { + return nil, err + } + // Filter by type + for ifIdx, ifData := range ifs { + if ifData.Interface.Type != reqType { + delete(ifs, ifIdx) + } + } + + return ifs, nil +} + +// DumpInterfaces implements interface handler. +func (h *IfVppHandler) DumpInterfaces() (map[uint32]*InterfaceDetails, error) { + start := time.Now() + // map for the resulting interfaces + ifs := make(map[uint32]*InterfaceDetails) + + // First, dump all interfaces to create initial data. + reqCtx := h.callsChannel.SendMultiRequest(&interfaces.SwInterfaceDump{}) + + for { + ifDetails := &interfaces.SwInterfaceDetails{} + stop, err := reqCtx.ReceiveReply(ifDetails) + if stop { + break // Break from the loop. + } + if err != nil { + return nil, fmt.Errorf("failed to dump interface: %v", err) + } + + details := &InterfaceDetails{ + Interface: &ifnb.Interfaces_Interface{ + Name: string(bytes.SplitN(ifDetails.Tag, []byte{0x00}, 2)[0]), + Type: guessInterfaceType(string(ifDetails.InterfaceName)), // the type may be amended later by further dumps + Enabled: ifDetails.AdminUpDown > 0, + PhysAddress: net.HardwareAddr(ifDetails.L2Address[:ifDetails.L2AddressLength]).String(), + Mtu: func(vppMtu uint16) uint32 { + // If default VPP MTU value is set, return 0 (it means MTU was not set in the NB config) + if vppMtu == defaultVPPMtu { + return 0 + } + return uint32(vppMtu) + }(ifDetails.LinkMtu), + }, + Meta: &InterfaceMeta{ + SwIfIndex: ifDetails.SwIfIndex, + Tag: string(bytes.SplitN(ifDetails.Tag, []byte{0x00}, 2)[0]), + InternalName: string(bytes.SplitN(ifDetails.InterfaceName, []byte{0x00}, 2)[0]), + }, + } + // Fill name for physical interfaces (they are mostly without tag) + if details.Interface.Type == ifnb.InterfaceType_ETHERNET_CSMACD { + details.Interface.Name = details.Meta.InternalName + } + ifs[ifDetails.SwIfIndex] = details + + if details.Interface.Type == ifnb.InterfaceType_AF_PACKET_INTERFACE { + fillAFPacketDetails(ifs, ifDetails.SwIfIndex, details.Meta.InternalName) + } + } + + // Get DHCP clients + dhcpClients, err := h.dumpDhcpClients() + if err != nil { + return nil, fmt.Errorf("failed to dump interface DHCP clients: %v", err) + } + // Get vrf for every interface and fill DHCP if set + for _, ifData := range ifs { + // VRF + vrf, err := h.GetInterfaceVrf(ifData.Meta.SwIfIndex) + if err != nil { + h.log.Warnf("Interface dump: failed to get VRF from interface %d: %v", ifData.Meta.SwIfIndex, err) + continue + } + ifData.Interface.Vrf = vrf + // DHCP + dhcpData, ok := dhcpClients[ifData.Meta.SwIfIndex] + if ok { + ifData.Interface.SetDhcpClient = true + ifData.Meta.Dhcp = dhcpData + } + } + + h.log.Debugf("dumped %d interfaces", len(ifs)) + + // SwInterfaceDump time + timeLog := measure.GetTimeLog(interfaces.SwInterfaceDump{}, h.stopwatch) + if timeLog != nil { + timeLog.LogTimeEntry(time.Since(start)) + } + + timeLog = measure.GetTimeLog(ip.IPAddressDump{}, h.stopwatch) + err = h.dumpIPAddressDetails(ifs, 0, timeLog) + if err != nil { + return nil, err + } + err = h.dumpIPAddressDetails(ifs, 1, timeLog) + if err != nil { + return nil, err + } + + err = h.dumpMemifDetails(ifs) + if err != nil { + return nil, err + } + + err = h.dumpTapDetails(ifs) + if err != nil { + return nil, err + } + + err = h.dumpVxlanDetails(ifs) + if err != nil { + return nil, err + } + + return ifs, nil +} + +// DumpMemifSocketDetails implements interface handler. +func (h *IfVppHandler) DumpMemifSocketDetails() (map[string]uint32, error) { + // MemifSocketFilenameDump time measurement + defer func(t time.Time) { + h.stopwatch.TimeLog(memif.MemifSocketFilenameDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + memifSocketMap := make(map[string]uint32) + + reqCtx := h.callsChannel.SendMultiRequest(&memif.MemifSocketFilenameDump{}) + for { + socketDetails := &memif.MemifSocketFilenameDetails{} + stop, err := reqCtx.ReceiveReply(socketDetails) + if stop { + break // Break from the loop. + } + if err != nil { + return memifSocketMap, fmt.Errorf("failed to dump memif socket filename details: %v", err) + } + + filename := string(bytes.SplitN(socketDetails.SocketFilename, []byte{0x00}, 2)[0]) + memifSocketMap[filename] = socketDetails.SocketID + } + + h.log.Debugf("Memif socket dump completed, found %d entries", len(memifSocketMap)) + + return memifSocketMap, nil +} + +// dumpIPAddressDetails dumps IP address details of interfaces from VPP and fills them into the provided interface map. +func (h *IfVppHandler) dumpIPAddressDetails(ifs map[uint32]*InterfaceDetails, isIPv6 uint8, timeLog measure.StopWatchEntry) error { + // Dump IP addresses of each interface. + for idx := range ifs { + // IPAddressDetails time measurement + start := time.Now() + + reqCtx := h.callsChannel.SendMultiRequest(&ip.IPAddressDump{ + SwIfIndex: idx, + IsIPv6: isIPv6, + }) + for { + ipDetails := &ip.IPAddressDetails{} + stop, err := reqCtx.ReceiveReply(ipDetails) + if stop { + break // Break from the loop. + } + if err != nil { + return fmt.Errorf("failed to dump interface %d IP address details: %v", idx, err) + } + h.processIPDetails(ifs, ipDetails) + } + + // IPAddressDump time + if timeLog != nil { + timeLog.LogTimeEntry(time.Since(start)) + } + } + + return nil +} + +// processIPDetails processes ip.IPAddressDetails binary API message and fills the details into the provided interface map. +func (h *IfVppHandler) processIPDetails(ifs map[uint32]*InterfaceDetails, ipDetails *ip.IPAddressDetails) { + ifDetails, ifIdxExists := ifs[ipDetails.SwIfIndex] + if !ifIdxExists { + return + } + var ipAddr string + if ipDetails.IsIPv6 == 1 { + ipAddr = fmt.Sprintf("%s/%d", net.IP(ipDetails.IP).To16().String(), uint32(ipDetails.PrefixLength)) + } else { + ipAddr = fmt.Sprintf("%s/%d", net.IP(ipDetails.IP[:4]).To4().String(), uint32(ipDetails.PrefixLength)) + } + ifDetails.Interface.IpAddresses = append(ifDetails.Interface.IpAddresses, ipAddr) +} + +// fillAFPacketDetails fills af_packet interface details into the provided interface map. +func fillAFPacketDetails(ifs map[uint32]*InterfaceDetails, swIfIndex uint32, ifName string) { + ifs[swIfIndex].Interface.Afpacket = &ifnb.Interfaces_Interface_Afpacket{ + HostIfName: strings.TrimPrefix(ifName, "host-"), + } + ifs[swIfIndex].Interface.Type = ifnb.InterfaceType_AF_PACKET_INTERFACE +} + +// dumpMemifDetails dumps memif interface details from VPP and fills them into the provided interface map. +func (h *IfVppHandler) dumpMemifDetails(ifs map[uint32]*InterfaceDetails) error { + // MemifDetails time measurement + defer func(t time.Time) { + h.stopwatch.TimeLog(memif.MemifDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + // Dump all memif sockets + memifSocketMap, err := h.DumpMemifSocketDetails() + if err != nil { + return err + } + + reqCtx := h.callsChannel.SendMultiRequest(&memif.MemifDump{}) + for { + memifDetails := &memif.MemifDetails{} + stop, err := reqCtx.ReceiveReply(memifDetails) + if stop { + break // Break from the loop. + } + if err != nil { + return fmt.Errorf("failed to dump memif interface: %v", err) + } + _, ifIdxExists := ifs[memifDetails.SwIfIndex] + if !ifIdxExists { + continue + } + ifs[memifDetails.SwIfIndex].Interface.Memif = &ifnb.Interfaces_Interface_Memif{ + Master: memifDetails.Role == 0, + Mode: memifModetoNB(memifDetails.Mode), + Id: memifDetails.ID, + // TODO: Secret - not available in the binary API + SocketFilename: func(socketMap map[string]uint32) (filename string) { + for filename, id := range socketMap { + if memifDetails.SocketID == id { + return filename + } + } + // Socket for configured memif should exist + h.log.Warnf("Socket ID not found for memif %v", memifDetails.SwIfIndex) + return + }(memifSocketMap), + RingSize: memifDetails.RingSize, + BufferSize: uint32(memifDetails.BufferSize), + // TODO: RxQueues, TxQueues - not available in the binary API + } + ifs[memifDetails.SwIfIndex].Interface.Type = ifnb.InterfaceType_MEMORY_INTERFACE + } + + return nil +} + +// dumpTapDetails dumps tap interface details from VPP and fills them into the provided interface map. +func (h *IfVppHandler) dumpTapDetails(ifs map[uint32]*InterfaceDetails) error { + // SwInterfaceTapDump time measurement + defer func(t time.Time) { + h.stopwatch.TimeLog(tap.SwInterfaceTapDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + // Original TAP. + reqCtx := h.callsChannel.SendMultiRequest(&tap.SwInterfaceTapDump{}) + for { + tapDetails := &tap.SwInterfaceTapDetails{} + stop, err := reqCtx.ReceiveReply(tapDetails) + if stop { + break // Break from the loop. + } + if err != nil { + return fmt.Errorf("failed to dump TAP interface details: %v", err) + } + _, ifIdxExists := ifs[tapDetails.SwIfIndex] + if !ifIdxExists { + continue + } + ifs[tapDetails.SwIfIndex].Interface.Tap = &ifnb.Interfaces_Interface_Tap{ + Version: 1, + HostIfName: string(bytes.SplitN(tapDetails.DevName, []byte{0x00}, 2)[0]), + } + ifs[tapDetails.SwIfIndex].Interface.Type = ifnb.InterfaceType_TAP_INTERFACE + } + + // TAP v.2 + reqCtx = h.callsChannel.SendMultiRequest(&tapv2.SwInterfaceTapV2Dump{}) + for { + tapDetails := &tapv2.SwInterfaceTapV2Details{} + stop, err := reqCtx.ReceiveReply(tapDetails) + if stop { + break // Break from the loop. + } + if err != nil { + return fmt.Errorf("failed to dump TAPv2 interface details: %v", err) + } + _, ifIdxExists := ifs[tapDetails.SwIfIndex] + if !ifIdxExists { + continue + } + ifs[tapDetails.SwIfIndex].Interface.Tap = &ifnb.Interfaces_Interface_Tap{ + Version: 2, + HostIfName: string(bytes.SplitN(tapDetails.HostIfName, []byte{0x00}, 2)[0]), + // Other parameters are not not yet part of the dump. + + } + ifs[tapDetails.SwIfIndex].Interface.Type = ifnb.InterfaceType_TAP_INTERFACE + } + + return nil +} + +// dumpVxlanDetails dumps VXLAN interface details from VPP and fills them into the provided interface map. +func (h *IfVppHandler) dumpVxlanDetails(ifs map[uint32]*InterfaceDetails) error { + // VxlanTunnelDump time measurement + defer func(t time.Time) { + h.stopwatch.TimeLog(vxlan.VxlanTunnelDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + reqCtx := h.callsChannel.SendMultiRequest(&vxlan.VxlanTunnelDump{SwIfIndex: ^uint32(0)}) + for { + vxlanDetails := &vxlan.VxlanTunnelDetails{} + stop, err := reqCtx.ReceiveReply(vxlanDetails) + if stop { + break // Break from the loop. + } + if err != nil { + return fmt.Errorf("failed to dump VxLAN tunnel interface details: %v", err) + } + _, ifIdxExists := ifs[vxlanDetails.SwIfIndex] + if !ifIdxExists { + continue + } + // Multicast interface + var multicastIfName string + _, exists := ifs[vxlanDetails.McastSwIfIndex] + if exists { + multicastIfName = ifs[vxlanDetails.McastSwIfIndex].Interface.Name + } + + if vxlanDetails.IsIPv6 == 1 { + ifs[vxlanDetails.SwIfIndex].Interface.Vxlan = &ifnb.Interfaces_Interface_Vxlan{ + Multicast: multicastIfName, + SrcAddress: net.IP(vxlanDetails.SrcAddress).To16().String(), + DstAddress: net.IP(vxlanDetails.DstAddress).To16().String(), + Vni: vxlanDetails.Vni, + } + } else { + ifs[vxlanDetails.SwIfIndex].Interface.Vxlan = &ifnb.Interfaces_Interface_Vxlan{ + Multicast: multicastIfName, + SrcAddress: net.IP(vxlanDetails.SrcAddress[:4]).To4().String(), + DstAddress: net.IP(vxlanDetails.DstAddress[:4]).To4().String(), + Vni: vxlanDetails.Vni, + } + } + ifs[vxlanDetails.SwIfIndex].Interface.Type = ifnb.InterfaceType_VXLAN_TUNNEL + } + + return nil +} + +// dumpDhcpClients returns a slice of DhcpMeta with all interfaces and other DHCP-related information available +func (h *IfVppHandler) dumpDhcpClients() (map[uint32]*Dhcp, error) { + defer func(t time.Time) { + h.stopwatch.TimeLog(dhcp.DHCPClientDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + dhcpData := make(map[uint32]*Dhcp) + reqCtx := h.callsChannel.SendMultiRequest(&dhcp.DHCPClientDump{}) + + for { + dhcpDetails := &dhcp.DHCPClientDetails{} + last, err := reqCtx.ReceiveReply(dhcpDetails) + if last { + break + } + if err != nil { + return nil, err + } + client := dhcpDetails.Client + lease := dhcpDetails.Lease + + var hostMac net.HardwareAddr = lease.HostMac + var hostAddr, routerAddr string + if uintToBool(lease.IsIPv6) { + hostAddr = fmt.Sprintf("%s/%d", net.IP(lease.HostAddress).To16().String(), uint32(lease.MaskWidth)) + routerAddr = fmt.Sprintf("%s/%d", net.IP(lease.RouterAddress).To16().String(), uint32(lease.MaskWidth)) + } else { + hostAddr = fmt.Sprintf("%s/%d", net.IP(lease.HostAddress[:4]).To4().String(), uint32(lease.MaskWidth)) + routerAddr = fmt.Sprintf("%s/%d", net.IP(lease.RouterAddress[:4]).To4().String(), uint32(lease.MaskWidth)) + } + + // DHCP client data + dhcpClient := &Client{ + SwIfIndex: client.SwIfIndex, + Hostname: string(bytes.SplitN(client.Hostname, []byte{0x00}, 2)[0]), + ID: string(bytes.SplitN(client.ID, []byte{0x00}, 2)[0]), + WantDhcpEvent: uintToBool(client.WantDHCPEvent), + SetBroadcastFlag: uintToBool(client.SetBroadcastFlag), + Pid: client.PID, + } + + // DHCP lease data + dhcpLease := &Lease{ + SwIfIndex: lease.SwIfIndex, + State: lease.State, + Hostname: string(bytes.SplitN(lease.Hostname, []byte{0x00}, 2)[0]), + IsIPv6: uintToBool(lease.IsIPv6), + MaskWidth: lease.MaskWidth, + HostAddress: hostAddr, + RouterAddress: routerAddr, + HostMac: hostMac.String(), + } + + // DHCP metadata + dhcpData[client.SwIfIndex] = &Dhcp{ + Client: dhcpClient, + Lease: dhcpLease, + } + } + + return dhcpData, nil +} + +// guessInterfaceType attempts to guess the correct interface type from its internal name (as given by VPP). +// This is required mainly for those interface types, that do not provide dump binary API, +// such as loopback of af_packet. +func guessInterfaceType(ifName string) ifnb.InterfaceType { + switch { + case strings.HasPrefix(ifName, "loop"): + return ifnb.InterfaceType_SOFTWARE_LOOPBACK + case strings.HasPrefix(ifName, "local"): + return ifnb.InterfaceType_SOFTWARE_LOOPBACK + case strings.HasPrefix(ifName, "memif"): + return ifnb.InterfaceType_MEMORY_INTERFACE + case strings.HasPrefix(ifName, "tap"): + return ifnb.InterfaceType_TAP_INTERFACE + case strings.HasPrefix(ifName, "host"): + return ifnb.InterfaceType_AF_PACKET_INTERFACE + case strings.HasPrefix(ifName, "vxlan"): + return ifnb.InterfaceType_VXLAN_TUNNEL + } + return ifnb.InterfaceType_ETHERNET_CSMACD +} + +// memifModetoNB converts binary API type of memif mode to the northbound API type memif mode. +func memifModetoNB(mode uint8) ifnb.Interfaces_Interface_Memif_MemifMode { + switch mode { + case 0: + return ifnb.Interfaces_Interface_Memif_ETHERNET + case 1: + return ifnb.Interfaces_Interface_Memif_IP + case 2: + return ifnb.Interfaces_Interface_Memif_PUNT_INJECT + } + return ifnb.Interfaces_Interface_Memif_ETHERNET +} diff --git a/plugins/vpp/ifplugin/vppcalls/dump_interface_vppcalls_test.go b/plugins/vpp/ifplugin/vppcalls/dump_interface_vppcalls_test.go new file mode 100644 index 0000000000..9e7aa10429 --- /dev/null +++ b/plugins/vpp/ifplugin/vppcalls/dump_interface_vppcalls_test.go @@ -0,0 +1,376 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vppcalls_test + +import ( + "net" + "testing" + + "github.com/ligato/vpp-agent/plugins/vpp/binapi/dhcp" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/memif" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/tap" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/tapv2" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/vpe" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/vxlan" + interfaces2 "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" + "github.com/ligato/vpp-agent/tests/vppcallmock" + . "github.com/onsi/gomega" +) + +// Test dump of interfaces with vxlan type +func TestDumpInterfacesVxLan(t *testing.T) { + ctx, ifHandler := ifTestSetup(t) + defer ctx.TeardownTestCtx() + + ipv61Parse := net.ParseIP("dead:beef:feed:face:cafe:babe:baad:c0de").To16() + ipv62Parse := net.ParseIP("d3ad:beef:feed:face:cafe:babe:baad:c0de").To16() + + ctx.MockReplies([]*vppcallmock.HandleReplies{ + { + Name: (&interfaces.SwInterfaceDump{}).GetMessageName(), + Ping: true, + Message: &interfaces.SwInterfaceDetails{ + InterfaceName: []byte("vxlan1"), + }, + }, + { + Name: (&interfaces.SwInterfaceGetTable{}).GetMessageName(), + Ping: false, + Message: &interfaces.SwInterfaceGetTableReply{}, + }, + { + Name: (&ip.IPAddressDump{}).GetMessageName(), + Ping: true, + Message: &ip.IPAddressDetails{}, + }, + { + Name: (&memif.MemifSocketFilenameDump{}).GetMessageName(), + Ping: true, + Message: &memif.MemifSocketFilenameDetails{}, + }, + { + Name: (&memif.MemifDump{}).GetMessageName(), + Ping: true, + Message: &memif.MemifDetails{}, + }, + { + Name: (&tap.SwInterfaceTapDump{}).GetMessageName(), + Ping: true, + Message: &tap.SwInterfaceTapDetails{}, + }, + { + Name: (&tapv2.SwInterfaceTapV2Dump{}).GetMessageName(), + Ping: true, + Message: &tapv2.SwInterfaceTapV2Details{}, + }, + { + Name: (&vxlan.VxlanTunnelDump{}).GetMessageName(), + Ping: true, + Message: &vxlan.VxlanTunnelDetails{ + IsIPv6: 1, + SwIfIndex: 0, + SrcAddress: ipv61Parse, + DstAddress: ipv62Parse, + }, + }, + }) + + intfs, err := ifHandler.DumpInterfaces() + Expect(err).To(BeNil()) + Expect(intfs).To(HaveLen(1)) + intface := intfs[0].Interface + + // Check vxlan + Expect(intface.Vxlan.SrcAddress).To(Equal("dead:beef:feed:face:cafe:babe:baad:c0de")) + Expect(intface.Vxlan.DstAddress).To(Equal("d3ad:beef:feed:face:cafe:babe:baad:c0de")) +} + +// Test dump of interfaces with host type +func TestDumpInterfacesHost(t *testing.T) { + ctx, ifHandler := ifTestSetup(t) + defer ctx.TeardownTestCtx() + + ctx.MockReplies([]*vppcallmock.HandleReplies{ + { + Name: (&interfaces.SwInterfaceDump{}).GetMessageName(), + Ping: true, + Message: &interfaces.SwInterfaceDetails{ + InterfaceName: []byte("host-localhost"), + }, + }, + { + Name: (&interfaces.SwInterfaceGetTable{}).GetMessageName(), + Ping: false, + Message: &interfaces.SwInterfaceGetTableReply{}, + }, + { + Name: (&ip.IPAddressDump{}).GetMessageName(), + Ping: true, + Message: &ip.IPAddressDetails{}, + }, + { + Name: (&memif.MemifSocketFilenameDump{}).GetMessageName(), + Ping: true, + Message: &memif.MemifSocketFilenameDetails{}, + }, + { + Name: (&memif.MemifDump{}).GetMessageName(), + Ping: true, + Message: &memif.MemifDetails{}, + }, + { + Name: (&tap.SwInterfaceTapDump{}).GetMessageName(), + Ping: true, + Message: &tap.SwInterfaceTapDetails{}, + }, + { + Name: (&tapv2.SwInterfaceTapV2Dump{}).GetMessageName(), + Ping: true, + Message: &tapv2.SwInterfaceTapV2Details{}, + }, + { + Name: (&vxlan.VxlanTunnelDump{}).GetMessageName(), + Ping: true, + Message: &vxlan.VxlanTunnelDetails{}, + }, + }) + + intfs, err := ifHandler.DumpInterfaces() + Expect(err).To(BeNil()) + Expect(intfs).To(HaveLen(1)) + intface := intfs[0].Interface + + // Check interface data + Expect(intface.Afpacket.HostIfName).To(Equal("localhost")) +} + +// Test dump of interfaces with memif type +func TestDumpInterfacesMemif(t *testing.T) { + ctx, ifHandler := ifTestSetup(t) + defer ctx.TeardownTestCtx() + + ctx.MockReplies([]*vppcallmock.HandleReplies{ + { + Name: (&interfaces.SwInterfaceDump{}).GetMessageName(), + Ping: true, + Message: &interfaces.SwInterfaceDetails{ + InterfaceName: []byte("memif1"), + }, + }, + { + Name: (&interfaces.SwInterfaceGetTable{}).GetMessageName(), + Ping: false, + Message: &interfaces.SwInterfaceGetTableReply{}, + }, + { + Name: (&ip.IPAddressDump{}).GetMessageName(), + Ping: true, + Message: &ip.IPAddressDetails{}, + }, + { + Name: (&memif.MemifSocketFilenameDump{}).GetMessageName(), + Ping: true, + Message: &memif.MemifSocketFilenameDetails{ + SocketID: 1, + SocketFilename: []byte("test"), + }, + }, + { + Name: (&memif.MemifDump{}).GetMessageName(), + Ping: true, + Message: &memif.MemifDetails{ + ID: 2, + SwIfIndex: 0, + Role: 1, // Slave + Mode: 1, // IP + SocketID: 1, + RingSize: 0, + BufferSize: 0, + }, + }, + { + Name: (&tap.SwInterfaceTapDump{}).GetMessageName(), + Ping: true, + Message: &tap.SwInterfaceTapDetails{}, + }, + { + Name: (&tapv2.SwInterfaceTapV2Dump{}).GetMessageName(), + Ping: true, + Message: &tapv2.SwInterfaceTapV2Details{}, + }, + { + Name: (&vxlan.VxlanTunnelDump{}).GetMessageName(), + Ping: true, + Message: &vxlan.VxlanTunnelDetails{}, + }, + }) + + intfs, err := ifHandler.DumpInterfaces() + Expect(err).To(BeNil()) + Expect(intfs).To(HaveLen(1)) + intface := intfs[0].Interface + + // Check memif + Expect(intface.Memif.SocketFilename).To(Equal("test")) + Expect(intface.Memif.Id).To(Equal(uint32(2))) + Expect(intface.Memif.Mode).To(Equal(interfaces2.Interfaces_Interface_Memif_IP)) + Expect(intface.Memif.Master).To(BeFalse()) +} + +// Test dump of interfaces using custom mock reply handler to avoid issues with ControlPingMessageReply +// not being properly recognized +func TestDumpInterfacesFull(t *testing.T) { + ctx, ifHandler := ifTestSetup(t) + defer ctx.TeardownTestCtx() + + hwAddr1Parse, err := net.ParseMAC("01:23:45:67:89:ab") + Expect(err).To(BeNil()) + + ctx.MockReplies([]*vppcallmock.HandleReplies{ + { + Name: (&interfaces.SwInterfaceDump{}).GetMessageName(), + Ping: true, + Message: &interfaces.SwInterfaceDetails{ + SwIfIndex: 0, + InterfaceName: []byte("memif1"), + Tag: []byte("interface2"), + AdminUpDown: 1, + LinkMtu: 9216, // Default MTU + L2Address: hwAddr1Parse, + L2AddressLength: uint32(len(hwAddr1Parse)), + }, + }, + { + Name: (&interfaces.SwInterfaceGetTable{}).GetMessageName(), + Ping: false, + Message: &interfaces.SwInterfaceGetTableReply{ + Retval: 0, + VrfID: 42, + }, + }, + { + Name: (&ip.IPAddressDump{}).GetMessageName(), + Ping: true, + Message: &ip.IPAddressDetails{}, + }, + { + Name: (&dhcp.DHCPClientDump{}).GetMessageName(), + Ping: true, + Message: &dhcp.DHCPClientDetails{ + Client: dhcp.DHCPClient{ + SwIfIndex: 0, + }, + }, + }, + { + Name: (&memif.MemifSocketFilenameDump{}).GetMessageName(), + Ping: true, + Message: &memif.MemifSocketFilenameDetails{ + SocketID: 1, + SocketFilename: []byte("test"), + }, + }, + { + Name: (&memif.MemifDump{}).GetMessageName(), + Ping: true, + Message: &memif.MemifDetails{ + ID: 2, + SwIfIndex: 0, + Role: 0, // Master + Mode: 0, // Ethernet + SocketID: 1, + RingSize: 0, + BufferSize: 0, + }, + }, + { + Name: (&tap.SwInterfaceTapDump{}).GetMessageName(), + Ping: true, + Message: &tap.SwInterfaceTapDetails{ + SwIfIndex: 0, + DevName: []byte("taptap"), + }, + }, + { + Name: (&tapv2.SwInterfaceTapV2Dump{}).GetMessageName(), + Ping: true, + Message: &tapv2.SwInterfaceTapV2Details{ + SwIfIndex: 0, + HostIfName: []byte("taptap2"), // This will overwrite the v1 tap name + }, + }, + { + Name: (&vxlan.VxlanTunnelDump{}).GetMessageName(), + Ping: true, + Message: &vxlan.VxlanTunnelDetails{ + SwIfIndex: 0, + SrcAddress: []byte{192, 168, 0, 1}, + DstAddress: []byte{192, 168, 0, 2}, + }, + }, + }) + + intfs, err := ifHandler.DumpInterfaces() + Expect(err).To(BeNil()) + Expect(intfs).To(HaveLen(1)) + + intface := intfs[0].Interface + + // This is last checked type, so it will be equal to that + Expect(intface.Type).To(Equal(interfaces2.InterfaceType_VXLAN_TUNNEL)) + Expect(intface.PhysAddress).To(Equal("01:23:45:67:89:ab")) + Expect(intface.Name).To(Equal("interface2")) + Expect(intface.Mtu).To(Equal(uint32(0))) // default mtu + Expect(intface.Enabled).To(BeTrue()) + Expect(intface.Vrf).To(Equal(uint32(42))) + Expect(intface.SetDhcpClient).To(BeTrue()) + + // Check memif + Expect(intface.Memif.SocketFilename).To(Equal("test")) + Expect(intface.Memif.Id).To(Equal(uint32(2))) + Expect(intface.Memif.Mode).To(Equal(interfaces2.Interfaces_Interface_Memif_ETHERNET)) + Expect(intface.Memif.Master).To(BeTrue()) + + // Check tap + Expect(intface.Tap.HostIfName).To(Equal("taptap2")) + Expect(intface.Tap.Version).To(Equal(uint32(2))) + + // Check vxlan + Expect(intface.Vxlan.SrcAddress).To(Equal("192.168.0.1")) + Expect(intface.Vxlan.DstAddress).To(Equal("192.168.0.2")) +} + +// Test dump of memif socket details using standard reply mocking +func TestDumpMemifSocketDetails(t *testing.T) { + ctx, ifHandler := ifTestSetup(t) + defer ctx.TeardownTestCtx() + + ctx.MockVpp.MockReply(&memif.MemifSocketFilenameDetails{ + SocketID: 1, + SocketFilename: []byte("test"), + }) + + ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) + + result, err := ifHandler.DumpMemifSocketDetails() + Expect(err).To(BeNil()) + Expect(result).To(Not(BeEmpty())) + + socketID, ok := result["test"] + Expect(ok).To(BeTrue()) + Expect(socketID).To(Equal(uint32(1))) +} diff --git a/plugins/vpp/ifplugin/vppdump/dump_nat_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/dump_nat_vppcalls.go similarity index 53% rename from plugins/vpp/ifplugin/vppdump/dump_nat_vppcalls.go rename to plugins/vpp/ifplugin/vppcalls/dump_nat_vppcalls.go index 5e70cd627c..a238924538 100644 --- a/plugins/vpp/ifplugin/vppdump/dump_nat_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/dump_nat_vppcalls.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package vppdump +package vppcalls import ( "bytes" @@ -21,34 +21,54 @@ import ( "strings" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/measure" bin_api "github.com/ligato/vpp-agent/plugins/vpp/binapi/nat" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" "github.com/ligato/vpp-agent/plugins/vpp/model/nat" ) -// Nat44GlobalConfigDump returns global config in NB format -func Nat44GlobalConfigDump(swIfIndices ifaceidx.SwIfIndex, log logging.Logger, vppChan govppapi.Channel, - stopwatch *measure.Stopwatch) (*nat.Nat44Global, error) { - log.Debug("dumping Nat44Global") +// Nat44Details contains all configuration available for network address translation. +// Note: SNAT is currently skipped, since there is no model defined for it +type Nat44Details struct { + Global *nat.Nat44Global + DNat *nat.Nat44DNat +} +// Nat44Dump implements NAT handler. +func (handler *NatVppHandler) Nat44Dump() (*Nat44Details, error) { + global, err := handler.Nat44GlobalConfigDump() + if err != nil { + return nil, err + } + dNat, err := handler.Nat44DNatDump() + if err != nil { + return nil, err + } + return &Nat44Details{ + Global: global, + DNat: dNat, + }, nil +} + +// Nat44GlobalConfigDump implements NAT handler. +func (handler *NatVppHandler) Nat44GlobalConfigDump() (*nat.Nat44Global, error) { + handler.log.Debug("dumping Nat44Global") // Dump all necessary data to reconstruct global NAT configuration - isEnabled, err := nat44IsForwardingEnabled(log, vppChan, stopwatch) + isEnabled, err := handler.isNat44ForwardingEnabled() if err != nil { return nil, err } - natInterfaces, err := nat44InterfaceDump(swIfIndices, log, vppChan, stopwatch) + natInterfaces, err := handler.Nat44InterfaceDump() if err != nil { return nil, err } - natOutputFeature, err := nat44InterfaceOutputFeatureDump(swIfIndices, log, vppChan, stopwatch) + natOutputFeature, err := handler.nat44InterfaceOutputFeatureDump() if err != nil { return nil, err } - natAddressPools, err := nat44AddressDump(log, vppChan, stopwatch) + natAddressPools, err := handler.nat44AddressDump() + if err != nil { + return nil, err + } + vrIPv4, vrIPv6, err := handler.virtualReassemblyDump() if err != nil { return nil, err } @@ -70,68 +90,65 @@ func Nat44GlobalConfigDump(swIfIndices ifaceidx.SwIfIndex, log logging.Logger, v }) } - log.Debug("dumped Nat44Global") + handler.log.Debug("dumped Nat44Global") // Set fields return &nat.Nat44Global{ - Forwarding: isEnabled, - NatInterfaces: nat44GlobalInterfaces, - AddressPools: natAddressPools, + Forwarding: isEnabled, + NatInterfaces: nat44GlobalInterfaces, + AddressPools: natAddressPools, + VirtualReassemblyIpv4: vrIPv4, + VirtualReassemblyIpv6: vrIPv6, }, nil } -// NAT44NatDump dumps all types of mappings, sorts it according to tag (DNAT label) and creates a set of DNAT configurations -func NAT44DNatDump(swIfIndices ifaceidx.SwIfIndex, log logging.Logger, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (*nat.Nat44DNat, error) { +// Nat44DNatDump implements NAT handler. +func (handler *NatVppHandler) Nat44DNatDump() (*nat.Nat44DNat, error) { // List od DNAT configs var dNatCfgs []*nat.Nat44DNat_DNatConfig - var wasErr error - log.Debug("dumping DNat") + handler.log.Debug("dumping DNat") // Static mappings - natStMappings, err := nat44StaticMappingDump(swIfIndices, log, vppChan, stopwatch) + natStMappings, err := handler.nat44StaticMappingDump() if err != nil { - log.Errorf("Failed to dump NAT44 static mappings: %v", err) - wasErr = err + return nil, fmt.Errorf("failed to dump NAT44 static mappings: %v", err) } for tag, data := range natStMappings { - processDNatData(tag, data, &dNatCfgs, log) + handler.processDNatData(tag, data, &dNatCfgs) } // Static mappings with load balancer - natStLbMappings, err := nat44StaticMappingLbDump(log, vppChan, stopwatch) + natStLbMappings, err := handler.nat44StaticMappingLbDump() if err != nil { - log.Errorf("Failed to dump NAT44 static mappings with load balancer: %v", err) - wasErr = err + return nil, fmt.Errorf("failed to dump NAT44 static mappings with load balancer: %v", err) } for tag, data := range natStLbMappings { - processDNatData(tag, data, &dNatCfgs, log) + handler.processDNatData(tag, data, &dNatCfgs) } // Identity mappings - natIdMappings, err := nat44IdentityMappingDump(swIfIndices, log, vppChan, stopwatch) + natIDMappings, err := handler.nat44IdentityMappingDump() if err != nil { - log.Errorf("Failed to dump NAT44 identity mappings: %v", err) - wasErr = err + return nil, fmt.Errorf("failed to dump NAT44 identity mappings: %v", err) } - for tag, data := range natIdMappings { - processDNatData(tag, data, &dNatCfgs, log) + for tag, data := range natIDMappings { + handler.processDNatData(tag, data, &dNatCfgs) } - log.Debugf("dumped %d NAT44DNat configs", len(dNatCfgs)) + handler.log.Debugf("dumped %d NAT44DNat configs", len(dNatCfgs)) return &nat.Nat44DNat{ DnatConfigs: dNatCfgs, - }, wasErr + }, nil } // nat44AddressDump returns a list of NAT44 address pools configured in the VPP -func nat44AddressDump(log logging.Logger, vppChan govppapi.Channel, - stopwatch *measure.Stopwatch) (addresses []*nat.Nat44Global_AddressPool, err error) { +func (handler *NatVppHandler) nat44AddressDump() (addresses []*nat.Nat44Global_AddressPool, err error) { defer func(t time.Time) { - stopwatch.TimeLog(bin_api.Nat44AddressDump{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(bin_api.Nat44AddressDump{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &bin_api.Nat44AddressDump{} - reqContext := vppChan.SendMultiRequest(req) + reqContext := handler.dumpChannel.SendMultiRequest(req) for { msg := &bin_api.Nat44AddressDetails{} @@ -152,21 +169,52 @@ func nat44AddressDump(log logging.Logger, vppChan govppapi.Channel, }) } - log.Debugf("NAT44 address pool dump complete, found %d entries", len(addresses)) + handler.log.Debugf("NAT44 address pool dump complete, found %d entries", len(addresses)) + + return +} + +// virtualReassemblyDump returns current NAT44 virtual-reassembly configuration. The output config may be nil. +func (handler *NatVppHandler) virtualReassemblyDump() (vrIPv4 *nat.Nat44Global_VirtualReassembly, vrIPv6 *nat.Nat44Global_VirtualReassembly, err error) { + defer func(t time.Time) { + handler.stopwatch.TimeLog(bin_api.NatGetReass{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + req := &bin_api.NatGetReass{} + reply := &bin_api.NatGetReassReply{} + + if err := handler.dumpChannel.SendRequest(req).ReceiveReply(reply); err != nil { + return nil, nil, fmt.Errorf("failed to get NAT44 virtual reassembly configuration: %v", err) + } + if reply.Retval != 0 { + return nil, nil, fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) + } + + vrIPv4 = &nat.Nat44Global_VirtualReassembly{ + Timeout: reply.IP4Timeout, + MaxReass: uint32(reply.IP4MaxReass), + MaxFrag: uint32(reply.IP4MaxFrag), + DropFrag: uintToBool(reply.IP4DropFrag), + } + vrIPv6 = &nat.Nat44Global_VirtualReassembly{ + Timeout: reply.IP6Timeout, + MaxReass: uint32(reply.IP6MaxReass), + MaxFrag: uint32(reply.IP6MaxFrag), + DropFrag: uintToBool(reply.IP6DropFrag), + } return } // nat44StaticMappingDump returns a map of static mapping tag/data pairs -func nat44StaticMappingDump(swIfIndices ifaceidx.SwIfIndex, log logging.Logger, vppChan govppapi.Channel, - stopwatch *measure.Stopwatch) (entries map[string]*nat.Nat44DNat_DNatConfig_StaticMapping, err error) { +func (handler *NatVppHandler) nat44StaticMappingDump() (entries map[string]*nat.Nat44DNat_DNatConfig_StaticMapping, err error) { defer func(t time.Time) { - stopwatch.TimeLog(bin_api.Nat44StaticMappingDump{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(bin_api.Nat44StaticMappingDump{}).LogTimeEntry(time.Since(t)) }(time.Now()) entries = make(map[string]*nat.Nat44DNat_DNatConfig_StaticMapping) req := &bin_api.Nat44StaticMappingDump{} - reqContext := vppChan.SendMultiRequest(req) + reqContext := handler.dumpChannel.SendMultiRequest(req) for { msg := &bin_api.Nat44StaticMappingDetails{} @@ -186,40 +234,39 @@ func nat44StaticMappingDump(swIfIndices ifaceidx.SwIfIndex, log logging.Logger, // Fill data (value) entries[tag] = &nat.Nat44DNat_DNatConfig_StaticMapping{ - VrfId: msg.VrfID, ExternalInterface: func(ifIdx uint32) string { - ifName, _, found := swIfIndices.LookupName(ifIdx) - if !found && ifIdx != 0xffffffff { - log.Warnf("Interface with index %v not found in the mapping", ifIdx) + ifName, _, found := handler.ifIndexes.LookupName(ifIdx) + if !found && ifIdx != ^uint32(0) { + handler.log.Warnf("Interface with index %v not found in the mapping", ifIdx) } return ifName }(msg.ExternalSwIfIndex), ExternalIp: exIPAddress.To4().String(), ExternalPort: uint32(msg.ExternalPort), LocalIps: append(locals, &nat.Nat44DNat_DNatConfig_StaticMapping_LocalIP{ // single-value + VrfId: msg.VrfID, LocalIp: lcIPAddress.To4().String(), LocalPort: uint32(msg.LocalPort), }), - Protocol: getNatProtocol(msg.Protocol, log), - TwiceNat: getTwiceNatMode(msg.TwiceNat, msg.SelfTwiceNat, log), + Protocol: handler.getProtocol(msg.Protocol), + TwiceNat: handler.getTwiceNatMode(msg.TwiceNat, msg.SelfTwiceNat), } } - log.Debugf("NAT44 static mapping dump complete, found %d entries", len(entries)) + handler.log.Debugf("NAT44 static mapping dump complete, found %d entries", len(entries)) return entries, nil } // nat44StaticMappingLbDump returns a map of static mapping tag/data pairs with load balancer -func nat44StaticMappingLbDump(log logging.Logger, vppChan govppapi.Channel, - stopwatch *measure.Stopwatch) (entries map[string]*nat.Nat44DNat_DNatConfig_StaticMapping, err error) { +func (handler *NatVppHandler) nat44StaticMappingLbDump() (entries map[string]*nat.Nat44DNat_DNatConfig_StaticMapping, err error) { defer func(t time.Time) { - stopwatch.TimeLog(bin_api.Nat44LbStaticMappingDump{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(bin_api.Nat44LbStaticMappingDump{}).LogTimeEntry(time.Since(t)) }(time.Now()) entries = make(map[string]*nat.Nat44DNat_DNatConfig_StaticMapping) req := &bin_api.Nat44LbStaticMappingDump{} - reqContext := vppChan.SendMultiRequest(req) + reqContext := handler.dumpChannel.SendMultiRequest(req) for { msg := &bin_api.Nat44LbStaticMappingDetails{} @@ -239,6 +286,7 @@ func nat44StaticMappingLbDump(log logging.Logger, vppChan govppapi.Channel, for _, localIPVal := range msg.Locals { localIP := net.IP(localIPVal.Addr) locals = append(locals, &nat.Nat44DNat_DNatConfig_StaticMapping_LocalIP{ + VrfId: localIPVal.VrfID, LocalIp: localIP.To4().String(), LocalPort: uint32(localIPVal.Port), Probability: uint32(localIPVal.Probability), @@ -247,30 +295,28 @@ func nat44StaticMappingLbDump(log logging.Logger, vppChan govppapi.Channel, exIPAddress := net.IP(msg.ExternalAddr) entries[tag] = &nat.Nat44DNat_DNatConfig_StaticMapping{ - VrfId: msg.VrfID, ExternalIp: exIPAddress.To4().String(), ExternalPort: uint32(msg.ExternalPort), LocalIps: locals, - Protocol: getNatProtocol(msg.Protocol, log), - TwiceNat: getTwiceNatMode(msg.TwiceNat, msg.SelfTwiceNat, log), + Protocol: handler.getProtocol(msg.Protocol), + TwiceNat: handler.getTwiceNatMode(msg.TwiceNat, msg.SelfTwiceNat), } } - log.Debugf("NAT44 lb-static mapping dump complete, found %d entries", len(entries)) + handler.log.Debugf("NAT44 lb-static mapping dump complete, found %d entries", len(entries)) return entries, nil } // nat44IdentityMappingDump returns a map of identity mapping tag/data pairs -func nat44IdentityMappingDump(swIfIndices ifaceidx.SwIfIndex, log logging.Logger, vppChan govppapi.Channel, - stopwatch *measure.Stopwatch) (entries map[string]*nat.Nat44DNat_DNatConfig_IdentityMapping, err error) { +func (handler *NatVppHandler) nat44IdentityMappingDump() (entries map[string]*nat.Nat44DNat_DNatConfig_IdentityMapping, err error) { defer func(t time.Time) { - stopwatch.TimeLog(bin_api.Nat44IdentityMappingDump{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(bin_api.Nat44IdentityMappingDump{}).LogTimeEntry(time.Since(t)) }(time.Now()) entries = make(map[string]*nat.Nat44DNat_DNatConfig_IdentityMapping) req := &bin_api.Nat44IdentityMappingDump{} - reqContext := vppChan.SendMultiRequest(req) + reqContext := handler.dumpChannel.SendMultiRequest(req) for { msg := &bin_api.Nat44IdentityMappingDetails{} @@ -291,32 +337,31 @@ func nat44IdentityMappingDump(swIfIndices ifaceidx.SwIfIndex, log logging.Logger entries[tag] = &nat.Nat44DNat_DNatConfig_IdentityMapping{ VrfId: msg.VrfID, AddressedInterface: func(ifIdx uint32) string { - ifName, _, found := swIfIndices.LookupName(ifIdx) + ifName, _, found := handler.ifIndexes.LookupName(ifIdx) if !found && ifIdx != 0xffffffff { - log.Warnf("Interface with index %v not found in the mapping", ifIdx) + handler.log.Warnf("Interface with index %v not found in the mapping", ifIdx) } return ifName }(msg.SwIfIndex), IpAddress: ipAddress.To4().String(), Port: uint32(msg.Port), - Protocol: getNatProtocol(msg.Protocol, log), + Protocol: handler.getProtocol(msg.Protocol), } } - log.Debugf("NAT44 identity mapping dump complete, found %d entries", len(entries)) + handler.log.Debugf("NAT44 identity mapping dump complete, found %d entries", len(entries)) return entries, nil } -// nat44InterfaceDump returns a list of interfaces enabled for NAT44 -func nat44InterfaceDump(swIfIndices ifaceidx.SwIfIndex, log logging.Logger, vppChan govppapi.Channel, - stopwatch *measure.Stopwatch) (interfaces []*nat.Nat44Global_NatInterface, err error) { +// Nat44InterfaceDump implements NAT handler. +func (handler *NatVppHandler) Nat44InterfaceDump() (interfaces []*nat.Nat44Global_NatInterface, err error) { defer func(t time.Time) { - stopwatch.TimeLog(bin_api.Nat44InterfaceDump{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(bin_api.Nat44InterfaceDump{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &bin_api.Nat44InterfaceDump{} - reqContext := vppChan.SendMultiRequest(req) + reqContext := handler.dumpChannel.SendMultiRequest(req) for { msg := &bin_api.Nat44InterfaceDetails{} @@ -329,9 +374,9 @@ func nat44InterfaceDump(swIfIndices ifaceidx.SwIfIndex, log logging.Logger, vppC } // Find interface name - ifName, _, found := swIfIndices.LookupName(msg.SwIfIndex) + ifName, _, found := handler.ifIndexes.LookupName(msg.SwIfIndex) if !found { - log.Warnf("Interface with index %d not found in the mapping", msg.SwIfIndex) + handler.log.Warnf("Interface with index %d not found in the mapping", msg.SwIfIndex) continue } @@ -349,20 +394,19 @@ func nat44InterfaceDump(swIfIndices ifaceidx.SwIfIndex, log logging.Logger, vppC } } - log.Debugf("NAT44 interface dump complete, found %d entries", len(interfaces)) + handler.log.Debugf("NAT44 interface dump complete, found %d entries", len(interfaces)) return } // nat44InterfaceOutputFeatureDump returns a list of interfaces with output feature set -func nat44InterfaceOutputFeatureDump(swIfIndices ifaceidx.SwIfIndex, log logging.Logger, - vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (ifaces []*nat.Nat44Global_NatInterface, err error) { +func (handler *NatVppHandler) nat44InterfaceOutputFeatureDump() (ifaces []*nat.Nat44Global_NatInterface, err error) { defer func(t time.Time) { - stopwatch.TimeLog(bin_api.Nat44InterfaceOutputFeatureDump{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(bin_api.Nat44InterfaceOutputFeatureDump{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &bin_api.Nat44InterfaceOutputFeatureDump{} - reqContext := vppChan.SendMultiRequest(req) + reqContext := handler.dumpChannel.SendMultiRequest(req) for { msg := &bin_api.Nat44InterfaceOutputFeatureDetails{} @@ -375,9 +419,9 @@ func nat44InterfaceOutputFeatureDump(swIfIndices ifaceidx.SwIfIndex, log logging } // Find interface name - ifName, _, found := swIfIndices.LookupName(msg.SwIfIndex) + ifName, _, found := handler.ifIndexes.LookupName(msg.SwIfIndex) if !found { - log.Warnf("Interface with index %d not found in the mapping", msg.SwIfIndex) + handler.log.Warnf("Interface with index %d not found in the mapping", msg.SwIfIndex) continue } @@ -388,37 +432,37 @@ func nat44InterfaceOutputFeatureDump(swIfIndices ifaceidx.SwIfIndex, log logging }) } - log.Debugf("NAT44 interface with output feature dump complete, found %d entries", len(ifaces)) + handler.log.Debugf("NAT44 interface with output feature dump complete, found %d entries", len(ifaces)) return ifaces, nil } // Nat44IsForwardingEnabled returns a list of interfaces enabled for NAT44 -func nat44IsForwardingEnabled(log logging.Logger, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (isEnabled bool, err error) { +func (handler *NatVppHandler) isNat44ForwardingEnabled() (isEnabled bool, err error) { defer func(t time.Time) { - stopwatch.TimeLog(bin_api.Nat44ForwardingIsEnabled{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(bin_api.Nat44ForwardingIsEnabled{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &bin_api.Nat44ForwardingIsEnabled{} reply := &bin_api.Nat44ForwardingIsEnabledReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + if err := handler.dumpChannel.SendRequest(req).ReceiveReply(reply); err != nil { return false, fmt.Errorf("failed to dump forwarding: %v", err) } isEnabled = uintToBool(reply.Enabled) - log.Debugf("NAT44 forwarding dump complete, is enabled: %v", isEnabled) + handler.log.Debugf("NAT44 forwarding dump complete, is enabled: %v", isEnabled) return isEnabled, nil } // Common function can process all static and identity mappings -func processDNatData(tag string, data interface{}, dNatCfgs *[]*nat.Nat44DNat_DNatConfig, log logging.Logger) { +func (handler *NatVppHandler) processDNatData(tag string, data interface{}, dNatCfgs *[]*nat.Nat44DNat_DNatConfig) { if tag == "" { - log.Errorf("Cannot process DNAT config without tag") + handler.log.Errorf("Cannot process DNAT config without tag") return } - label := getDnatLabel(tag, log) + label := handler.getDnatLabel(tag) // Look for DNAT config using tag var dNat *nat.Nat44DNat_DNatConfig @@ -436,39 +480,39 @@ func processDNatData(tag string, data interface{}, dNatCfgs *[]*nat.Nat44DNat_DN IdMappings: make([]*nat.Nat44DNat_DNatConfig_IdentityMapping, 0), } *dNatCfgs = append(*dNatCfgs, dNat) - log.Debugf("Created new DNAT configuration %s", label) + handler.log.Debugf("Created new DNAT configuration %s", label) } // Add data to config switch mapping := data.(type) { case *nat.Nat44DNat_DNatConfig_StaticMapping: - log.Debugf("Static mapping added to DNAT %s", label) + handler.log.Debugf("Static mapping added to DNAT %s", label) dNat.StMappings = append(dNat.StMappings, mapping) case *nat.Nat44DNat_DNatConfig_IdentityMapping: - log.Debugf("Identity mapping added to DNAT %s", label) + handler.log.Debugf("Identity mapping added to DNAT %s", label) dNat.IdMappings = append(dNat.IdMappings, mapping) } } // returns NAT numeric representation of provided protocol value -func getNatProtocol(protocol uint8, log logging.Logger) (proto nat.Protocol) { +func (handler *NatVppHandler) getProtocol(protocol uint8) (proto nat.Protocol) { switch protocol { - case vppcalls.TCP: + case TCP: return nat.Protocol_TCP - case vppcalls.UDP: + case UDP: return nat.Protocol_UDP - case vppcalls.ICMP: + case ICMP: return nat.Protocol_ICMP default: - log.Warnf("Unknown protocol %v", protocol) + handler.log.Warnf("Unknown protocol %v", protocol) return 0 } } -func getTwiceNatMode(twiceNat, selfTwiceNat uint8, log logging.Logger) nat.TwiceNatMode { +func (handler *NatVppHandler) getTwiceNatMode(twiceNat, selfTwiceNat uint8) nat.TwiceNatMode { if twiceNat > 0 { if selfTwiceNat > 0 { - log.Warnf("Both TwiceNAT and self-TwiceNAT are enabled") + handler.log.Warnf("Both TwiceNAT and self-TwiceNAT are enabled") return 0 } return nat.TwiceNatMode_ENABLED @@ -487,15 +531,15 @@ func uintToBool(value uint8) bool { } // Obtain DNAT label from provided tag -func getDnatLabel(tag string, log logging.Logger) (label string) { +func (handler *NatVppHandler) getDnatLabel(tag string) (label string) { parts := strings.Split(tag, "|") // Tag should be in format label|mappingType|index if len(parts) == 0 { - log.Errorf("Unable to obtain DNAT label, incorrect mapping tag format: '%s'", tag) + handler.log.Errorf("Unable to obtain DNAT label, incorrect mapping tag format: '%s'", tag) return } if len(parts) != 3 { - log.Warnf("Mapping tag has unexpected format: %s. Resolved DNAT label may not be correct", tag) + handler.log.Warnf("Mapping tag has unexpected format: %s. Resolved DNAT label may not be correct", tag) } return parts[0] } diff --git a/plugins/vpp/ifplugin/vppdump/dump_nat_vppcalls_test.go b/plugins/vpp/ifplugin/vppcalls/dump_nat_vppcalls_test.go similarity index 77% rename from plugins/vpp/ifplugin/vppdump/dump_nat_vppcalls_test.go rename to plugins/vpp/ifplugin/vppcalls/dump_nat_vppcalls_test.go index 11ad653890..f891c38f0f 100644 --- a/plugins/vpp/ifplugin/vppdump/dump_nat_vppcalls_test.go +++ b/plugins/vpp/ifplugin/vppcalls/dump_nat_vppcalls_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package vppdump +package vppcalls_test import ( "testing" @@ -24,11 +24,12 @@ import ( "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" "github.com/ligato/vpp-agent/tests/vppcallmock" + "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" . "github.com/onsi/gomega" ) func TestNat44InterfaceDump(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, swIfIndexes := natTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&bin_api.Nat44InterfaceDetails{ @@ -37,17 +38,16 @@ func TestNat44InterfaceDump(t *testing.T) { }) ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - swIfIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "test-sw_if_indexes", ifaceidx.IndexMetadata)) swIfIndexes.RegisterName("if0", 1, nil) - ifaces, err := nat44InterfaceDump(swIfIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + ifaces, err := natHandler.Nat44InterfaceDump() Expect(err).To(Succeed()) Expect(ifaces).To(HaveLen(1)) Expect(ifaces[0].IsInside).To(BeFalse()) } func TestNat44InterfaceDump2(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, swIfIndexes := natTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&bin_api.Nat44InterfaceDetails{ @@ -56,17 +56,16 @@ func TestNat44InterfaceDump2(t *testing.T) { }) ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - swIfIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "test-sw_if_indexes", ifaceidx.IndexMetadata)) swIfIndexes.RegisterName("if0", 1, nil) - ifaces, err := nat44InterfaceDump(swIfIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + ifaces, err := natHandler.Nat44InterfaceDump() Expect(err).To(Succeed()) Expect(ifaces).To(HaveLen(1)) Expect(ifaces[0].IsInside).To(BeTrue()) } func TestNat44InterfaceDump3(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, swIfIndexes := natTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&bin_api.Nat44InterfaceDetails{ @@ -75,12 +74,19 @@ func TestNat44InterfaceDump3(t *testing.T) { }) ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - swIfIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "test-sw_if_indexes", ifaceidx.IndexMetadata)) swIfIndexes.RegisterName("if0", 1, nil) - ifaces, err := nat44InterfaceDump(swIfIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + ifaces, err := natHandler.Nat44InterfaceDump() Expect(err).To(Succeed()) Expect(ifaces).To(HaveLen(2)) Expect(ifaces[0].IsInside).To(BeFalse()) Expect(ifaces[1].IsInside).To(BeTrue()) } + +func natTestSetup(t *testing.T) (*vppcallmock.TestCtx, vppcalls.NatVppAPI, ifaceidx.SwIfIndexRW) { + ctx := vppcallmock.SetupTestCtx(t) + log := logrus.NewLogger("test-log") + swIfIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "test-sw_if_indexes", ifaceidx.IndexMetadata)) + natHandler := vppcalls.NewNatVppHandler(ctx.MockChannel, ctx.MockChannel, swIfIndexes, log, nil) + return ctx, natHandler, swIfIndexes +} diff --git a/plugins/vpp/ifplugin/vppcalls/dump_stn_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/dump_stn_vppcalls.go new file mode 100644 index 0000000000..e3cbb77496 --- /dev/null +++ b/plugins/vpp/ifplugin/vppcalls/dump_stn_vppcalls.go @@ -0,0 +1,84 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vppcalls + +import ( + "time" + + "net" + + "fmt" + + stnapi "github.com/ligato/vpp-agent/plugins/vpp/binapi/stn" + "github.com/ligato/vpp-agent/plugins/vpp/model/stn" +) + +// StnDetails contains proto-modelled STN data and vpp specific metadata +type StnDetails struct { + Rules []*stn.STN_Rule + Meta *StnMeta +} + +// StnMeta contains map of interface name/index +type StnMeta struct { + IfNameToIdx map[uint32]string +} + +// DumpStnRules implements STN handler. +func (handler *StnVppHandler) DumpStnRules() (rules *StnDetails, err error) { + defer func(t time.Time) { + handler.stopwatch.TimeLog(stnapi.StnRulesDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + var ruleList []*stn.STN_Rule + meta := &StnMeta{ + IfNameToIdx: make(map[uint32]string), + } + + req := &stnapi.StnRulesDump{} + reqCtx := handler.callsChannel.SendMultiRequest(req) + for { + msg := &stnapi.StnRulesDetails{} + stop, err := reqCtx.ReceiveReply(msg) + if stop { + break + } + if err != nil { + return nil, err + } + ifName, _, found := handler.ifIndexes.LookupName(msg.SwIfIndex) + if !found { + handler.log.Warnf("STN dump: name not found for interface %d", msg.SwIfIndex) + } + + var stnStrIP string + if uintToBool(msg.IsIP4) { + stnStrIP = fmt.Sprintf("%s", net.IP(msg.IPAddress[:4]).To4().String()) + } else { + stnStrIP = fmt.Sprintf("%s", net.IP(msg.IPAddress).To16().String()) + } + + ruleList = append(ruleList, &stn.STN_Rule{ + IpAddress: stnStrIP, + Interface: ifName, + }) + meta.IfNameToIdx[msg.SwIfIndex] = ifName + } + + return &StnDetails{ + Rules: ruleList, + Meta: meta, + }, nil +} diff --git a/plugins/vpp/ifplugin/vppcalls/ip_container_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/ip_container_vppcalls.go index a94b1c5df1..4ef1941cbb 100644 --- a/plugins/vpp/ifplugin/vppcalls/ip_container_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/ip_container_vppcalls.go @@ -18,8 +18,6 @@ import ( "fmt" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/cn-infra/utils/addrs" "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" ) @@ -29,9 +27,9 @@ const ( removeContainerIP uint8 = 0 ) -func sendAndLogMessageForVpp(ifIdx uint32, addr string, isAdd uint8, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +func (h *IfVppHandler) sendAndLogMessageForVpp(ifIdx uint32, addr string, isAdd uint8) error { defer func(t time.Time) { - stopwatch.TimeLog(ip.IPContainerProxyAddDel{}).LogTimeEntry(time.Since(t)) + h.stopwatch.TimeLog(ip.IPContainerProxyAddDel{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &ip.IPContainerProxyAddDel{ @@ -53,24 +51,23 @@ func sendAndLogMessageForVpp(ifIdx uint32, addr string, isAdd uint8, vppChan gov req.IP = []byte(IPaddr.IP.To4()) req.IsIP4 = 1 } - reply := &ip.IPContainerProxyAddDelReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return nil } -// AddContainerIP calls IPContainerProxyAddDel VPP API with IsAdd=1 -func AddContainerIP(ifIdx uint32, addr string, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return sendAndLogMessageForVpp(ifIdx, addr, addContainerIP, vppChan, stopwatch) +// AddContainerIP implements interface handler. +func (h *IfVppHandler) AddContainerIP(ifIdx uint32, addr string) error { + return h.sendAndLogMessageForVpp(ifIdx, addr, addContainerIP) } -// DelContainerIP calls IPContainerProxyAddDel VPP API with IsAdd=0 -func DelContainerIP(ifIdx uint32, addr string, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return sendAndLogMessageForVpp(ifIdx, addr, removeContainerIP, vppChan, stopwatch) +// DelContainerIP implements interface handler. +func (h *IfVppHandler) DelContainerIP(ifIdx uint32, addr string) error { + return h.sendAndLogMessageForVpp(ifIdx, addr, removeContainerIP) } diff --git a/plugins/vpp/ifplugin/vppcalls/ip_container_vppcalls_test.go b/plugins/vpp/ifplugin/vppcalls/ip_container_vppcalls_test.go index 4ebacc4ecc..4f70ac6e2a 100644 --- a/plugins/vpp/ifplugin/vppcalls/ip_container_vppcalls_test.go +++ b/plugins/vpp/ifplugin/vppcalls/ip_container_vppcalls_test.go @@ -19,18 +19,16 @@ import ( "testing" "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" - "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" ) func TestAddContainerIP(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&ip.IPContainerProxyAddDelReply{}) - err := vppcalls.AddContainerIP(1, "10.0.0.1/24", ctx.MockChannel, nil) + err := ifHandler.AddContainerIP(1, "10.0.0.1/24") Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*ip.IPContainerProxyAddDel) @@ -43,12 +41,12 @@ func TestAddContainerIP(t *testing.T) { } func TestAddContainerIPv6(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&ip.IPContainerProxyAddDelReply{}) - err := vppcalls.AddContainerIP(1, "2001:db8:0:1:1:1:1:1/128", ctx.MockChannel, nil) + err := ifHandler.AddContainerIP(1, "2001:db8:0:1:1:1:1:1/128") Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*ip.IPContainerProxyAddDel) @@ -61,47 +59,47 @@ func TestAddContainerIPv6(t *testing.T) { } func TestAddContainerIPInvalidIP(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&ip.IPAddressDetails{}) - err := vppcalls.AddContainerIP(1, "invalid-ip", ctx.MockChannel, nil) + err := ifHandler.AddContainerIP(1, "invalid-ip") Expect(err).ToNot(BeNil()) } func TestAddContainerIPError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&ip.IPAddressDetails{}) - err := vppcalls.AddContainerIP(1, "10.0.0.1/24", ctx.MockChannel, nil) + err := ifHandler.AddContainerIP(1, "10.0.0.1/24") Expect(err).ToNot(BeNil()) } func TestAddContainerIPRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&ip.IPContainerProxyAddDelReply{ Retval: 1, }) - err := vppcalls.AddContainerIP(1, "10.0.0.1/24", ctx.MockChannel, nil) + err := ifHandler.AddContainerIP(1, "10.0.0.1/24") Expect(err).ToNot(BeNil()) } func TestDelContainerIP(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&ip.IPContainerProxyAddDelReply{}) - err := vppcalls.DelContainerIP(1, "10.0.0.1/24", ctx.MockChannel, nil) + err := ifHandler.DelContainerIP(1, "10.0.0.1/24") Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*ip.IPContainerProxyAddDel) @@ -114,12 +112,12 @@ func TestDelContainerIP(t *testing.T) { } func TestDelContainerIPv6(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&ip.IPContainerProxyAddDelReply{}) - err := vppcalls.DelContainerIP(1, "2001:db8:0:1:1:1:1:1/128", ctx.MockChannel, nil) + err := ifHandler.DelContainerIP(1, "2001:db8:0:1:1:1:1:1/128") Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*ip.IPContainerProxyAddDel) @@ -132,25 +130,25 @@ func TestDelContainerIPv6(t *testing.T) { } func TestDelContainerIPError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&ip.IPAddressDetails{}) - err := vppcalls.DelContainerIP(1, "10.0.0.1/24", ctx.MockChannel, nil) + err := ifHandler.DelContainerIP(1, "10.0.0.1/24") Expect(err).ToNot(BeNil()) } func TestDelContainerIPRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&ip.IPContainerProxyAddDelReply{ Retval: 1, }) - err := vppcalls.DelContainerIP(1, "10.0.0.1/24", ctx.MockChannel, nil) + err := ifHandler.DelContainerIP(1, "10.0.0.1/24") Expect(err).ToNot(BeNil()) } diff --git a/plugins/vpp/ifplugin/vppcalls/ip_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/ip_vppcalls.go index 84c2e6e999..988ec6286a 100644 --- a/plugins/vpp/ifplugin/vppcalls/ip_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/ip_vppcalls.go @@ -19,8 +19,6 @@ import ( "net" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/cn-infra/utils/addrs" "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" ) @@ -30,9 +28,9 @@ const ( delInterfaceIP uint8 = 0 ) -func addDelInterfaceIP(ifIdx uint32, addr *net.IPNet, isAdd uint8, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +func (h *IfVppHandler) addDelInterfaceIP(ifIdx uint32, addr *net.IPNet, isAdd uint8) error { defer func(t time.Time) { - stopwatch.TimeLog(interfaces.SwInterfaceAddDelAddress{}).LogTimeEntry(time.Since(t)) + h.stopwatch.TimeLog(interfaces.SwInterfaceAddDelAddress{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &interfaces.SwInterfaceAddDelAddress{ @@ -49,31 +47,30 @@ func addDelInterfaceIP(ifIdx uint32, addr *net.IPNet, isAdd uint8, vppChan govpp } if isIPv6 { req.Address = []byte(addr.IP.To16()) - req.IsIpv6 = 1 + req.IsIPv6 = 1 } else { req.Address = []byte(addr.IP.To4()) - req.IsIpv6 = 0 + req.IsIPv6 = 0 } - reply := &interfaces.SwInterfaceAddDelAddressReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return nil } -// AddInterfaceIP calls SwInterfaceAddDelAddress bin API with IsAdd=1. -func AddInterfaceIP(ifIdx uint32, addr *net.IPNet, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return addDelInterfaceIP(ifIdx, addr, addInterfaceIP, vppChan, stopwatch) +// AddInterfaceIP implements interface handler. +func (h *IfVppHandler) AddInterfaceIP(ifIdx uint32, addr *net.IPNet) error { + return h.addDelInterfaceIP(ifIdx, addr, addInterfaceIP) } -// DelInterfaceIP calls SwInterfaceAddDelAddress bin API with IsAdd=00. -func DelInterfaceIP(ifIdx uint32, addr *net.IPNet, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return addDelInterfaceIP(ifIdx, addr, delInterfaceIP, vppChan, stopwatch) +// DelInterfaceIP implements interface handler. +func (h *IfVppHandler) DelInterfaceIP(ifIdx uint32, addr *net.IPNet) error { + return h.addDelInterfaceIP(ifIdx, addr, delInterfaceIP) } const ( @@ -81,9 +78,9 @@ const ( unsetUnnumberedIP uint8 = 0 ) -func setUnsetUnnumberedIP(uIfIdx uint32, ifIdxWithIP uint32, isAdd uint8, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +func (h *IfVppHandler) setUnsetUnnumberedIP(uIfIdx uint32, ifIdxWithIP uint32, isAdd uint8) error { defer func(t time.Time) { - stopwatch.TimeLog(interfaces.SwInterfaceSetUnnumbered{}).LogTimeEntry(time.Since(t)) + h.stopwatch.TimeLog(interfaces.SwInterfaceSetUnnumbered{}).LogTimeEntry(time.Since(t)) }(time.Now()) // Prepare the message. @@ -92,24 +89,23 @@ func setUnsetUnnumberedIP(uIfIdx uint32, ifIdxWithIP uint32, isAdd uint8, vppCha UnnumberedSwIfIndex: uIfIdx, IsAdd: isAdd, } - reply := &interfaces.SwInterfaceSetUnnumberedReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return nil } -// SetUnnumberedIP sets interface as un-numbered, linking IP address of the another interface (ifIdxWithIP) -func SetUnnumberedIP(uIfIdx uint32, ifIdxWithIP uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return setUnsetUnnumberedIP(uIfIdx, ifIdxWithIP, setUnnumberedIP, vppChan, stopwatch) +// SetUnnumberedIP implements interface handler. +func (h *IfVppHandler) SetUnnumberedIP(uIfIdx uint32, ifIdxWithIP uint32) error { + return h.setUnsetUnnumberedIP(uIfIdx, ifIdxWithIP, setUnnumberedIP) } -// UnsetUnnumberedIP unset provided interface as un-numbered. IP address of the linked interface is removed -func UnsetUnnumberedIP(uIfIdx uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return setUnsetUnnumberedIP(uIfIdx, 0, unsetUnnumberedIP, vppChan, stopwatch) +// UnsetUnnumberedIP implements interface handler. +func (h *IfVppHandler) UnsetUnnumberedIP(uIfIdx uint32) error { + return h.setUnsetUnnumberedIP(uIfIdx, 0, unsetUnnumberedIP) } diff --git a/plugins/vpp/ifplugin/vppcalls/ip_vppcalls_test.go b/plugins/vpp/ifplugin/vppcalls/ip_vppcalls_test.go index 7c4b9cb8d1..bf29931035 100644 --- a/plugins/vpp/ifplugin/vppcalls/ip_vppcalls_test.go +++ b/plugins/vpp/ifplugin/vppcalls/ip_vppcalls_test.go @@ -19,26 +19,24 @@ import ( "testing" "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" - "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" ) func TestAddInterfaceIP(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceAddDelAddressReply{}) _, ipNet, err := net.ParseCIDR("10.0.0.1/24") Expect(err).To(BeNil()) - err = vppcalls.AddInterfaceIP(1, ipNet, ctx.MockChannel, nil) + err = ifHandler.AddInterfaceIP(1, ipNet) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*interfaces.SwInterfaceAddDelAddress) Expect(ok).To(BeTrue()) Expect(vppMsg.SwIfIndex).To(BeEquivalentTo(1)) - Expect(vppMsg.IsIpv6).To(BeEquivalentTo(0)) + Expect(vppMsg.IsIPv6).To(BeEquivalentTo(0)) Expect(vppMsg.Address).To(BeEquivalentTo(net.ParseIP("10.0.0.0").To4())) Expect(vppMsg.AddressLength).To(BeEquivalentTo(24)) Expect(vppMsg.DelAll).To(BeEquivalentTo(0)) @@ -46,20 +44,20 @@ func TestAddInterfaceIP(t *testing.T) { } func TestAddInterfaceIPv6(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceAddDelAddressReply{}) _, ipNet, err := net.ParseCIDR("2001:db8:0:1:1:1:1:1/128") Expect(err).To(BeNil()) - err = vppcalls.AddInterfaceIP(1, ipNet, ctx.MockChannel, nil) + err = ifHandler.AddInterfaceIP(1, ipNet) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*interfaces.SwInterfaceAddDelAddress) Expect(ok).To(BeTrue()) Expect(vppMsg.SwIfIndex).To(BeEquivalentTo(1)) - Expect(vppMsg.IsIpv6).To(BeEquivalentTo(1)) + Expect(vppMsg.IsIPv6).To(BeEquivalentTo(1)) Expect(vppMsg.Address).To(BeEquivalentTo(net.ParseIP("2001:db8:0:1:1:1:1:1").To16())) Expect(vppMsg.AddressLength).To(BeEquivalentTo(128)) Expect(vppMsg.DelAll).To(BeEquivalentTo(0)) @@ -67,32 +65,32 @@ func TestAddInterfaceIPv6(t *testing.T) { } func TestAddInterfaceInvalidIP(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceAddDelAddressReply{}) - err := vppcalls.AddInterfaceIP(1, &net.IPNet{ + err := ifHandler.AddInterfaceIP(1, &net.IPNet{ IP: []byte("invalid-ip"), - }, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } func TestAddInterfaceIPError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() _, ipNet, err := net.ParseCIDR("10.0.0.1/24") ctx.MockVpp.MockReply(&interfaces.SwInterfaceAddDelAddress{}) - err = vppcalls.AddInterfaceIP(1, ipNet, ctx.MockChannel, nil) + err = ifHandler.AddInterfaceIP(1, ipNet) Expect(err).ToNot(BeNil()) } func TestAddInterfaceIPRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() _, ipNet, err := net.ParseCIDR("10.0.0.1/24") @@ -100,26 +98,26 @@ func TestAddInterfaceIPRetval(t *testing.T) { Retval: 1, }) - err = vppcalls.AddInterfaceIP(1, ipNet, ctx.MockChannel, nil) + err = ifHandler.AddInterfaceIP(1, ipNet) Expect(err).ToNot(BeNil()) } func TestDelInterfaceIP(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceAddDelAddressReply{}) _, ipNet, err := net.ParseCIDR("10.0.0.1/24") Expect(err).To(BeNil()) - err = vppcalls.DelInterfaceIP(1, ipNet, ctx.MockChannel, nil) + err = ifHandler.DelInterfaceIP(1, ipNet) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*interfaces.SwInterfaceAddDelAddress) Expect(ok).To(BeTrue()) Expect(vppMsg.SwIfIndex).To(BeEquivalentTo(1)) - Expect(vppMsg.IsIpv6).To(BeEquivalentTo(0)) + Expect(vppMsg.IsIPv6).To(BeEquivalentTo(0)) Expect(vppMsg.Address).To(BeEquivalentTo(net.ParseIP("10.0.0.0").To4())) Expect(vppMsg.AddressLength).To(BeEquivalentTo(24)) Expect(vppMsg.DelAll).To(BeEquivalentTo(0)) @@ -127,20 +125,20 @@ func TestDelInterfaceIP(t *testing.T) { } func TestDelInterfaceIPv6(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceAddDelAddressReply{}) _, ipNet, err := net.ParseCIDR("2001:db8:0:1:1:1:1:1/128") Expect(err).To(BeNil()) - err = vppcalls.DelInterfaceIP(1, ipNet, ctx.MockChannel, nil) + err = ifHandler.DelInterfaceIP(1, ipNet) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*interfaces.SwInterfaceAddDelAddress) Expect(ok).To(BeTrue()) Expect(vppMsg.SwIfIndex).To(BeEquivalentTo(1)) - Expect(vppMsg.IsIpv6).To(BeEquivalentTo(1)) + Expect(vppMsg.IsIPv6).To(BeEquivalentTo(1)) Expect(vppMsg.Address).To(BeEquivalentTo(net.ParseIP("2001:db8:0:1:1:1:1:1").To16())) Expect(vppMsg.AddressLength).To(BeEquivalentTo(128)) Expect(vppMsg.DelAll).To(BeEquivalentTo(0)) @@ -148,32 +146,32 @@ func TestDelInterfaceIPv6(t *testing.T) { } func TestDelInterfaceInvalidIP(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceAddDelAddressReply{}) - err := vppcalls.DelInterfaceIP(1, &net.IPNet{ + err := ifHandler.DelInterfaceIP(1, &net.IPNet{ IP: []byte("invalid-ip"), - }, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } func TestDelInterfaceIPError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() _, ipNet, err := net.ParseCIDR("10.0.0.1/24") ctx.MockVpp.MockReply(&interfaces.SwInterfaceAddDelAddress{}) - err = vppcalls.DelInterfaceIP(1, ipNet, ctx.MockChannel, nil) + err = ifHandler.DelInterfaceIP(1, ipNet) Expect(err).ToNot(BeNil()) } func TestDelInterfaceIPRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() _, ipNet, err := net.ParseCIDR("10.0.0.1/24") @@ -181,18 +179,18 @@ func TestDelInterfaceIPRetval(t *testing.T) { Retval: 1, }) - err = vppcalls.DelInterfaceIP(1, ipNet, ctx.MockChannel, nil) + err = ifHandler.DelInterfaceIP(1, ipNet) Expect(err).ToNot(BeNil()) } func TestSetUnnumberedIP(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetUnnumberedReply{}) - err := vppcalls.SetUnnumberedIP(1, 2, ctx.MockChannel, nil) + err := ifHandler.SetUnnumberedIP(1, 2) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*interfaces.SwInterfaceSetUnnumbered) @@ -203,36 +201,36 @@ func TestSetUnnumberedIP(t *testing.T) { } func TestSetUnnumberedIPError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetUnnumbered{}) - err := vppcalls.SetUnnumberedIP(1, 2, ctx.MockChannel, nil) + err := ifHandler.SetUnnumberedIP(1, 2) Expect(err).ToNot(BeNil()) } func TestSetUnnumberedIPRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetUnnumberedReply{ Retval: 1, }) - err := vppcalls.SetUnnumberedIP(1, 2, ctx.MockChannel, nil) + err := ifHandler.SetUnnumberedIP(1, 2) Expect(err).ToNot(BeNil()) } func TestUnsetUnnumberedIP(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetUnnumberedReply{}) - err := vppcalls.UnsetUnnumberedIP(1, ctx.MockChannel, nil) + err := ifHandler.UnsetUnnumberedIP(1) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*interfaces.SwInterfaceSetUnnumbered) @@ -243,25 +241,25 @@ func TestUnsetUnnumberedIP(t *testing.T) { } func TestUnsetUnnumberedIPError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetUnnumbered{}) - err := vppcalls.UnsetUnnumberedIP(1, ctx.MockChannel, nil) + err := ifHandler.UnsetUnnumberedIP(1) Expect(err).ToNot(BeNil()) } func TestUnsetUnnumberedIPRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetUnnumberedReply{ Retval: 1, }) - err := vppcalls.UnsetUnnumberedIP(1, ctx.MockChannel, nil) + err := ifHandler.UnsetUnnumberedIP(1) Expect(err).ToNot(BeNil()) } diff --git a/plugins/vpp/ifplugin/vppcalls/loopback_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/loopback_vppcalls.go index bee6f63e4f..a7893f7fa7 100644 --- a/plugins/vpp/ifplugin/vppcalls/loopback_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/loopback_vppcalls.go @@ -18,48 +18,44 @@ import ( "fmt" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" ) -// AddLoopbackInterface calls CreateLoopback bin API. -func AddLoopbackInterface(ifName string, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (swIndex uint32, err error) { +// AddLoopbackInterface implements interface handler. +func (h *IfVppHandler) AddLoopbackInterface(ifName string) (swIndex uint32, err error) { defer func(t time.Time) { - stopwatch.TimeLog(interfaces.CreateLoopback{}).LogTimeEntry(time.Since(t)) + h.stopwatch.TimeLog(interfaces.CreateLoopback{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &interfaces.CreateLoopback{} - reply := &interfaces.CreateLoopbackReply{} - if err = vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err = h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return 0, err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return 0, fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } - return reply.SwIfIndex, SetInterfaceTag(ifName, reply.SwIfIndex, vppChan, stopwatch) + return reply.SwIfIndex, h.SetInterfaceTag(ifName, reply.SwIfIndex) } -// DeleteLoopbackInterface calls DeleteLoopback bin API. -func DeleteLoopbackInterface(ifName string, idx uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +// DeleteLoopbackInterface implements interface handler. +func (h *IfVppHandler) DeleteLoopbackInterface(ifName string, idx uint32) error { defer func(t time.Time) { - stopwatch.TimeLog(interfaces.DeleteLoopback{}).LogTimeEntry(time.Since(t)) + h.stopwatch.TimeLog(interfaces.DeleteLoopback{}).LogTimeEntry(time.Since(t)) }(time.Now()) // Prepare the message. req := &interfaces.DeleteLoopback{ SwIfIndex: idx, } - reply := &interfaces.DeleteLoopbackReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } - return RemoveInterfaceTag(ifName, idx, vppChan, stopwatch) + return h.RemoveInterfaceTag(ifName, idx) } diff --git a/plugins/vpp/ifplugin/vppcalls/loopback_vppcalls_test.go b/plugins/vpp/ifplugin/vppcalls/loopback_vppcalls_test.go index 79f72120c0..60161cddc0 100644 --- a/plugins/vpp/ifplugin/vppcalls/loopback_vppcalls_test.go +++ b/plugins/vpp/ifplugin/vppcalls/loopback_vppcalls_test.go @@ -18,13 +18,11 @@ import ( "testing" "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" - "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" ) func TestAddLoopbackInterface(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.CreateLoopbackReply{ @@ -32,70 +30,70 @@ func TestAddLoopbackInterface(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - swIfIdx, err := vppcalls.AddLoopbackInterface("loopback", ctx.MockChannel, nil) + swIfIdx, err := ifHandler.AddLoopbackInterface("loopback") Expect(err).To(BeNil()) Expect(swIfIdx).To(BeEquivalentTo(1)) } func TestAddLoopbackInterfaceError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.CreateLoopback{}) - swIfIdx, err := vppcalls.AddLoopbackInterface("loopback", ctx.MockChannel, nil) + swIfIdx, err := ifHandler.AddLoopbackInterface("loopback") Expect(err).ToNot(BeNil()) Expect(swIfIdx).To(BeEquivalentTo(0)) } func TestAddLoopbackInterfaceRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.CreateLoopbackReply{ Retval: 1, }) - swIfIdx, err := vppcalls.AddLoopbackInterface("loopback", ctx.MockChannel, nil) + swIfIdx, err := ifHandler.AddLoopbackInterface("loopback") Expect(err).ToNot(BeNil()) Expect(swIfIdx).To(BeEquivalentTo(0)) } func TestDeleteLoopbackInterface(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.DeleteLoopbackReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - err := vppcalls.DeleteLoopbackInterface("loopback", 1, ctx.MockChannel, nil) + err := ifHandler.DeleteLoopbackInterface("loopback", 1) Expect(err).To(BeNil()) } func TestDeleteLoopbackInterfaceError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.DeleteLoopback{}) - err := vppcalls.DeleteLoopbackInterface("loopback", 1, ctx.MockChannel, nil) + err := ifHandler.DeleteLoopbackInterface("loopback", 1) Expect(err).ToNot(BeNil()) } func TestDeleteLoopbackInterfaceRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.DeleteLoopbackReply{ Retval: 1, }) - err := vppcalls.DeleteLoopbackInterface("loopback", 1, ctx.MockChannel, nil) + err := ifHandler.DeleteLoopbackInterface("loopback", 1) Expect(err).ToNot(BeNil()) } diff --git a/plugins/vpp/ifplugin/vppcalls/mac_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/mac_vppcalls.go index 229a62ecda..196ba47ce3 100644 --- a/plugins/vpp/ifplugin/vppcalls/mac_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/mac_vppcalls.go @@ -19,15 +19,13 @@ import ( "net" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" ) -// SetInterfaceMac calls SwInterfaceSetMacAddress bin API. -func SetInterfaceMac(ifIdx uint32, macAddress string, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +// SetInterfaceMac implements interface handler. +func (h *IfVppHandler) SetInterfaceMac(ifIdx uint32, macAddress string) error { defer func(t time.Time) { - stopwatch.TimeLog(interfaces.SwInterfaceSetMacAddress{}).LogTimeEntry(time.Since(t)) + h.stopwatch.TimeLog(interfaces.SwInterfaceSetMacAddress{}).LogTimeEntry(time.Since(t)) }(time.Now()) mac, err := net.ParseMAC(macAddress) @@ -39,12 +37,11 @@ func SetInterfaceMac(ifIdx uint32, macAddress string, vppChan govppapi.Channel, SwIfIndex: ifIdx, MacAddress: mac, } - reply := &interfaces.SwInterfaceSetMacAddressReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } diff --git a/plugins/vpp/ifplugin/vppcalls/mac_vppcalls_test.go b/plugins/vpp/ifplugin/vppcalls/mac_vppcalls_test.go index 21d6c92449..0e9f3a4128 100644 --- a/plugins/vpp/ifplugin/vppcalls/mac_vppcalls_test.go +++ b/plugins/vpp/ifplugin/vppcalls/mac_vppcalls_test.go @@ -12,25 +12,24 @@ // See the License for the specific language governing permissions and // limitations under the License. -package vppcalls +package vppcalls_test import ( "net" "testing" "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" - "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" ) func TestSetInterfaceMac(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetMacAddressReply{}) mac, _ := net.ParseMAC("65:77:BF:72:C9:8D") - err := SetInterfaceMac(1, "65:77:BF:72:C9:8D", ctx.MockChannel, nil) + err := ifHandler.SetInterfaceMac(1, "65:77:BF:72:C9:8D") Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*interfaces.SwInterfaceSetMacAddress) @@ -40,36 +39,36 @@ func TestSetInterfaceMac(t *testing.T) { } func TestSetInterfaceInvalidMac(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetMacAddress{}) - err := SetInterfaceMac(1, "invalid-mac", ctx.MockChannel, nil) + err := ifHandler.SetInterfaceMac(1, "invalid-mac") Expect(err).ToNot(BeNil()) } func TestSetInterfaceMacError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetMacAddress{}) - err := SetInterfaceMac(1, "65:77:BF:72:C9:8D", ctx.MockChannel, nil) + err := ifHandler.SetInterfaceMac(1, "65:77:BF:72:C9:8D") Expect(err).ToNot(BeNil()) } func TestSetInterfaceMacRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetMacAddressReply{ Retval: 1, }) - err := SetInterfaceMac(1, "65:77:BF:72:C9:8D", ctx.MockChannel, nil) + err := ifHandler.SetInterfaceMac(1, "65:77:BF:72:C9:8D") Expect(err).ToNot(BeNil()) } diff --git a/plugins/vpp/ifplugin/vppcalls/memif_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/memif_vppcalls.go index 3c3b98c812..181b8859d4 100644 --- a/plugins/vpp/ifplugin/vppcalls/memif_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/memif_vppcalls.go @@ -18,16 +18,14 @@ import ( "fmt" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/vpp-agent/plugins/vpp/binapi/memif" intf "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" ) -// AddMemifInterface calls MemifCreate bin API. -func AddMemifInterface(ifName string, memIface *intf.Interfaces_Interface_Memif, socketID uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (swIdx uint32, err error) { +// AddMemifInterface implements interface handler. +func (h *IfVppHandler) AddMemifInterface(ifName string, memIface *intf.Interfaces_Interface_Memif, socketID uint32) (swIdx uint32, err error) { defer func(t time.Time) { - stopwatch.TimeLog(memif.MemifCreate{}).LogTimeEntry(time.Since(t)) + h.stopwatch.TimeLog(memif.MemifCreate{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &memif.MemifCreate{ @@ -52,43 +50,41 @@ func AddMemifInterface(ifName string, memIface *intf.Interfaces_Interface_Memif, if req.TxQueues == 0 { req.TxQueues = 1 } - reply := &memif.MemifCreateReply{} - if err = vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err = h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return 0, err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return 0, fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } - return reply.SwIfIndex, SetInterfaceTag(ifName, reply.SwIfIndex, vppChan, stopwatch) + return reply.SwIfIndex, h.SetInterfaceTag(ifName, reply.SwIfIndex) } -// DeleteMemifInterface calls MemifDelete bin API. -func DeleteMemifInterface(ifName string, idx uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +// DeleteMemifInterface implements interface handler. +func (h *IfVppHandler) DeleteMemifInterface(ifName string, idx uint32) error { defer func(t time.Time) { - stopwatch.TimeLog(memif.MemifDelete{}).LogTimeEntry(time.Since(t)) + h.stopwatch.TimeLog(memif.MemifDelete{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &memif.MemifDelete{ SwIfIndex: idx, } - reply := &memif.MemifDeleteReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } - return RemoveInterfaceTag(ifName, idx, vppChan, stopwatch) + return h.RemoveInterfaceTag(ifName, idx) } -// RegisterMemifSocketFilename registers new socket file name with provided ID. -func RegisterMemifSocketFilename(filename []byte, id uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +// RegisterMemifSocketFilename implements interface handler. +func (h *IfVppHandler) RegisterMemifSocketFilename(filename []byte, id uint32) error { defer func(t time.Time) { - stopwatch.TimeLog(memif.MemifSocketFilenameAddDel{}).LogTimeEntry(time.Since(t)) + h.stopwatch.TimeLog(memif.MemifSocketFilenameAddDel{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &memif.MemifSocketFilenameAddDel{ @@ -96,12 +92,11 @@ func RegisterMemifSocketFilename(filename []byte, id uint32, vppChan govppapi.Ch SocketID: id, IsAdd: 1, // sockets can be added only } - reply := &memif.MemifSocketFilenameAddDelReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } diff --git a/plugins/vpp/ifplugin/vppcalls/memif_vppcalls_test.go b/plugins/vpp/ifplugin/vppcalls/memif_vppcalls_test.go index 6e4248d77d..963aba1a94 100644 --- a/plugins/vpp/ifplugin/vppcalls/memif_vppcalls_test.go +++ b/plugins/vpp/ifplugin/vppcalls/memif_vppcalls_test.go @@ -19,14 +19,12 @@ import ( "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" "github.com/ligato/vpp-agent/plugins/vpp/binapi/memif" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" ifModel "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" - "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" ) func TestAddMasterMemifInterface(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&memif.MemifCreateReply{ @@ -34,12 +32,12 @@ func TestAddMasterMemifInterface(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - swIfIdx, err := vppcalls.AddMemifInterface("memif", &ifModel.Interfaces_Interface_Memif{ + swIfIdx, err := ifHandler.AddMemifInterface("memif", &ifModel.Interfaces_Interface_Memif{ Id: 1, Mode: ifModel.Interfaces_Interface_Memif_IP, Secret: "secret", Master: true, - }, 5, ctx.MockChannel, nil) + }, 5) Expect(err).To(BeNil()) Expect(swIfIdx).To(BeEquivalentTo(1)) @@ -60,7 +58,7 @@ func TestAddMasterMemifInterface(t *testing.T) { } func TestAddMasterMemifInterfaceAsSlave(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&memif.MemifCreateReply{ @@ -68,12 +66,12 @@ func TestAddMasterMemifInterfaceAsSlave(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - swIfIdx, err := vppcalls.AddMemifInterface("memif", &ifModel.Interfaces_Interface_Memif{ + swIfIdx, err := ifHandler.AddMemifInterface("memif", &ifModel.Interfaces_Interface_Memif{ Id: 1, Mode: ifModel.Interfaces_Interface_Memif_IP, Secret: "secret", Master: false, - }, 5, ctx.MockChannel, nil) + }, 5) Expect(err).To(BeNil()) Expect(swIfIdx).To(BeEquivalentTo(1)) @@ -89,24 +87,24 @@ func TestAddMasterMemifInterfaceAsSlave(t *testing.T) { } func TestAddMasterMemifInterfaceError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&memif.MemifCreate{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - _, err := vppcalls.AddMemifInterface("memif", &ifModel.Interfaces_Interface_Memif{ + _, err := ifHandler.AddMemifInterface("memif", &ifModel.Interfaces_Interface_Memif{ Id: 1, Mode: ifModel.Interfaces_Interface_Memif_IP, Secret: "secret", Master: false, - }, 5, ctx.MockChannel, nil) + }, 5) Expect(err).ToNot(BeNil()) } func TestAddMasterMemifInterfaceRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&memif.MemifCreateReply{ @@ -114,42 +112,42 @@ func TestAddMasterMemifInterfaceRetval(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - _, err := vppcalls.AddMemifInterface("memif", &ifModel.Interfaces_Interface_Memif{ + _, err := ifHandler.AddMemifInterface("memif", &ifModel.Interfaces_Interface_Memif{ Id: 1, Mode: ifModel.Interfaces_Interface_Memif_IP, Secret: "secret", Master: false, - }, 5, ctx.MockChannel, nil) + }, 5) Expect(err).ToNot(BeNil()) } func TestDeleteMemifInterface(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&memif.MemifDeleteReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - err := vppcalls.DeleteMemifInterface("memif", 1, ctx.MockChannel, nil) + err := ifHandler.DeleteMemifInterface("memif", 1) Expect(err).To(BeNil()) } func TestDeleteMemifInterfaceError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&memif.MemifDelete{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - err := vppcalls.DeleteMemifInterface("memif", 1, ctx.MockChannel, nil) + err := ifHandler.DeleteMemifInterface("memif", 1) Expect(err).ToNot(BeNil()) } func TestDeleteMemifInterfaceRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&memif.MemifDeleteReply{ @@ -157,18 +155,18 @@ func TestDeleteMemifInterfaceRetval(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - err := vppcalls.DeleteMemifInterface("memif", 1, ctx.MockChannel, nil) + err := ifHandler.DeleteMemifInterface("memif", 1) Expect(err).ToNot(BeNil()) } func TestRegisterMemifSocketFilename(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&memif.MemifSocketFilenameAddDelReply{}) - err := vppcalls.RegisterMemifSocketFilename([]byte("filename"), 1, ctx.MockChannel, nil) + err := ifHandler.RegisterMemifSocketFilename([]byte("filename"), 1) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*memif.MemifSocketFilenameAddDel) @@ -179,25 +177,25 @@ func TestRegisterMemifSocketFilename(t *testing.T) { } func TestRegisterMemifSocketFilenameError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&memif.MemifSocketFilenameAddDel{}) - err := vppcalls.RegisterMemifSocketFilename([]byte("filename"), 1, ctx.MockChannel, nil) + err := ifHandler.RegisterMemifSocketFilename([]byte("filename"), 1) Expect(err).ToNot(BeNil()) } func TestRegisterMemifSocketFilenameRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&memif.MemifSocketFilenameAddDelReply{ Retval: 1, }) - err := vppcalls.RegisterMemifSocketFilename([]byte("filename"), 1, ctx.MockChannel, nil) + err := ifHandler.RegisterMemifSocketFilename([]byte("filename"), 1) Expect(err).ToNot(BeNil()) } diff --git a/plugins/vpp/ifplugin/vppcalls/mtu_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/mtu_vppcalls.go index 68f72541a7..22f470de16 100644 --- a/plugins/vpp/ifplugin/vppcalls/mtu_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/mtu_vppcalls.go @@ -18,27 +18,24 @@ import ( "fmt" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" ) -// SetInterfaceMtu calls HwInterfaceSetMtu bin API with desired MTU value. -func SetInterfaceMtu(ifIdx uint32, mtu uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +// SetInterfaceMtu implements interface handler. +func (h *IfVppHandler) SetInterfaceMtu(ifIdx uint32, mtu uint32) error { defer func(t time.Time) { - stopwatch.TimeLog(interfaces.HwInterfaceSetMtu{}).LogTimeEntry(time.Since(t)) + h.stopwatch.TimeLog(interfaces.HwInterfaceSetMtu{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &interfaces.HwInterfaceSetMtu{ SwIfIndex: ifIdx, Mtu: uint16(mtu), } - reply := &interfaces.HwInterfaceSetMtuReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } diff --git a/plugins/vpp/ifplugin/vppcalls/mtu_vppcalls_test.go b/plugins/vpp/ifplugin/vppcalls/mtu_vppcalls_test.go index fc665d541d..8dfee7513f 100644 --- a/plugins/vpp/ifplugin/vppcalls/mtu_vppcalls_test.go +++ b/plugins/vpp/ifplugin/vppcalls/mtu_vppcalls_test.go @@ -18,18 +18,16 @@ import ( "testing" "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" - "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" ) func TestSetInterfaceMtu(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.HwInterfaceSetMtuReply{}) - err := vppcalls.SetInterfaceMtu(1, 1500, ctx.MockChannel, nil) + err := ifHandler.SetInterfaceMtu(1, 1500) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*interfaces.HwInterfaceSetMtu) @@ -39,25 +37,25 @@ func TestSetInterfaceMtu(t *testing.T) { } func TestSetInterfaceMtuError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.HwInterfaceSetMtu{}) - err := vppcalls.SetInterfaceMtu(1, 1500, ctx.MockChannel, nil) + err := ifHandler.SetInterfaceMtu(1, 1500) Expect(err).ToNot(BeNil()) } func TestSetInterfaceMtuRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.HwInterfaceSetMtuReply{ Retval: 1, }) - err := vppcalls.SetInterfaceMtu(1, 1500, ctx.MockChannel, nil) + err := ifHandler.SetInterfaceMtu(1, 1500) Expect(err).ToNot(BeNil()) } diff --git a/plugins/vpp/ifplugin/vppcalls/nat_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/nat_vppcalls.go index 597fde73bf..d4d8c7ed24 100644 --- a/plugins/vpp/ifplugin/vppcalls/nat_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/nat_vppcalls.go @@ -18,9 +18,8 @@ import ( "fmt" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/vpp-agent/plugins/vpp/binapi/nat" + nat2 "github.com/ligato/vpp-agent/plugins/vpp/model/nat" ) // Num protocol representation @@ -55,7 +54,6 @@ type StaticMappingLbContext struct { ExternalIP []byte ExternalPort uint16 Protocol uint8 - Vrf uint32 TwiceNat bool SelfTwiceNat bool } @@ -72,27 +70,27 @@ type IdentityMappingContext struct { // LocalLbAddress represents one local IP and address entry type LocalLbAddress struct { + Vrf uint32 Tag string LocalIP []byte LocalPort uint16 Probability uint8 } -// SetNat44Forwarding configures global forwarding setup for NAT44 -func SetNat44Forwarding(enableFwd bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +// SetNat44Forwarding implements NAT handler. +func (handler *NatVppHandler) SetNat44Forwarding(enableFwd bool) error { defer func(t time.Time) { - stopwatch.TimeLog(nat.Nat44ForwardingEnableDisable{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(nat.Nat44ForwardingEnableDisable{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &nat.Nat44ForwardingEnableDisable{ Enable: boolToUint(enableFwd), } - reply := &nat.Nat44ForwardingEnableDisableReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } @@ -100,9 +98,9 @@ func SetNat44Forwarding(enableFwd bool, vppChan govppapi.Channel, stopwatch *mea } // Calls VPP binary API to set/unset interface as NAT -func handleNat44Interface(ifIdx uint32, isInside, isAdd bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +func (handler *NatVppHandler) handleNat44Interface(ifIdx uint32, isInside, isAdd bool) error { defer func(t time.Time) { - stopwatch.TimeLog(nat.Nat44InterfaceAddDelFeature{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(nat.Nat44InterfaceAddDelFeature{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &nat.Nat44InterfaceAddDelFeature{ @@ -110,12 +108,11 @@ func handleNat44Interface(ifIdx uint32, isInside, isAdd bool, vppChan govppapi.C IsInside: boolToUint(isInside), IsAdd: boolToUint(isAdd), } - reply := &nat.Nat44InterfaceAddDelFeatureReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } @@ -123,9 +120,9 @@ func handleNat44Interface(ifIdx uint32, isInside, isAdd bool, vppChan govppapi.C } // Calls VPP binary API to set/unset interface as NAT with output feature -func handleNat44InterfaceOutputFeature(ifIdx uint32, isInside, isAdd bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +func (handler *NatVppHandler) handleNat44InterfaceOutputFeature(ifIdx uint32, isInside, isAdd bool) error { defer func(t time.Time) { - stopwatch.TimeLog(nat.Nat44InterfaceAddDelOutputFeature{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(nat.Nat44InterfaceAddDelOutputFeature{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &nat.Nat44InterfaceAddDelOutputFeature{ @@ -133,12 +130,11 @@ func handleNat44InterfaceOutputFeature(ifIdx uint32, isInside, isAdd bool, vppCh IsInside: boolToUint(isInside), IsAdd: boolToUint(isAdd), } - reply := &nat.Nat44InterfaceAddDelOutputFeatureReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } @@ -146,9 +142,9 @@ func handleNat44InterfaceOutputFeature(ifIdx uint32, isInside, isAdd bool, vppCh } // Calls VPP binary API to add/remove address pool -func handleNat44AddressPool(first, last []byte, vrf uint32, twiceNat, isAdd bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +func (handler *NatVppHandler) handleNat44AddressPool(first, last []byte, vrf uint32, twiceNat, isAdd bool) error { defer func(t time.Time) { - stopwatch.TimeLog(nat.Nat44AddDelAddressRange{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(nat.Nat44AddDelAddressRange{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &nat.Nat44AddDelAddressRange{ @@ -158,12 +154,35 @@ func handleNat44AddressPool(first, last []byte, vrf uint32, twiceNat, isAdd bool TwiceNat: boolToUint(twiceNat), IsAdd: boolToUint(isAdd), } - reply := &nat.Nat44AddDelAddressRangeReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err + } else if reply.Retval != 0 { + return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } - if reply.Retval != 0 { + + return nil +} + +// Calls VPP binary API to setup NAT virtual reassembly +func (handler *NatVppHandler) handleNat44VirtualReassembly(timeout, maxReass, maxFrag uint32, dropFrag, isIpv6 bool) error { + defer func(t time.Time) { + handler.stopwatch.TimeLog(nat.NatSetReass{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + req := &nat.NatSetReass{ + Timeout: timeout, + MaxReass: uint16(maxReass), + MaxFrag: uint8(maxFrag), + DropFrag: boolToUint(dropFrag), + IsIP6: boolToUint(isIpv6), + } + reply := &nat.NatSetReassReply{} + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { + return err + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } @@ -171,9 +190,9 @@ func handleNat44AddressPool(first, last []byte, vrf uint32, twiceNat, isAdd bool } // Calls VPP binary API to add/remove static mapping -func handleNat44StaticMapping(ctx *StaticMappingContext, isAdd, addrOnly bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +func (handler *NatVppHandler) handleNat44StaticMapping(ctx *StaticMappingContext, isAdd, addrOnly bool) error { defer func(t time.Time) { - stopwatch.TimeLog(nat.Nat44AddDelStaticMapping{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(nat.Nat44AddDelStaticMapping{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &nat.Nat44AddDelStaticMapping{ @@ -196,12 +215,11 @@ func handleNat44StaticMapping(ctx *StaticMappingContext, isAdd, addrOnly bool, v req.LocalPort = ctx.LocalPort req.ExternalPort = ctx.ExternalPort } - reply := &nat.Nat44AddDelStaticMappingReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } @@ -209,9 +227,9 @@ func handleNat44StaticMapping(ctx *StaticMappingContext, isAdd, addrOnly bool, v } // Calls VPP binary API to add/remove static mapping with load balancer -func handleNat44StaticMappingLb(ctx *StaticMappingLbContext, isAdd bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +func (handler *NatVppHandler) handleNat44StaticMappingLb(ctx *StaticMappingLbContext, isAdd bool) error { defer func(t time.Time) { - stopwatch.TimeLog(nat.Nat44AddDelLbStaticMapping{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(nat.Nat44AddDelLbStaticMapping{}).LogTimeEntry(time.Since(t)) }(time.Now()) // Transform local IP/Ports @@ -221,6 +239,7 @@ func handleNat44StaticMappingLb(ctx *StaticMappingLbContext, isAdd bool, vppChan Addr: ctxLocal.LocalIP, Port: ctxLocal.LocalPort, Probability: ctxLocal.Probability, + VrfID: ctxLocal.Vrf, } localAddrPorts = append(localAddrPorts, localAddrPort) } @@ -232,18 +251,16 @@ func handleNat44StaticMappingLb(ctx *StaticMappingLbContext, isAdd bool, vppChan ExternalAddr: ctx.ExternalIP, ExternalPort: ctx.ExternalPort, Protocol: ctx.Protocol, - VrfID: ctx.Vrf, TwiceNat: boolToUint(ctx.TwiceNat), SelfTwiceNat: boolToUint(ctx.SelfTwiceNat), Out2inOnly: 1, IsAdd: boolToUint(isAdd), } - reply := &nat.Nat44AddDelLbStaticMappingReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } @@ -251,9 +268,9 @@ func handleNat44StaticMappingLb(ctx *StaticMappingLbContext, isAdd bool, vppChan } // Calls VPP binary API to add/remove identity mapping -func handleNat44IdentityMapping(ctx *IdentityMappingContext, isAdd bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +func (handler *NatVppHandler) handleNat44IdentityMapping(ctx *IdentityMappingContext, isAdd bool) error { defer func(t time.Time) { - stopwatch.TimeLog(nat.Nat44AddDelIdentityMapping{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(nat.Nat44AddDelIdentityMapping{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &nat.Nat44AddDelIdentityMapping{ @@ -274,84 +291,92 @@ func handleNat44IdentityMapping(ctx *IdentityMappingContext, isAdd bool, vppChan } return ifIdx }(ctx.IfIdx), - VrfID: ctx.IfIdx, + VrfID: ctx.Vrf, IsAdd: boolToUint(isAdd), } - reply := &nat.Nat44AddDelIdentityMappingReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return nil } -// EnableNat44Interface enables NAT feature for provided interface -func EnableNat44Interface(ifIdx uint32, isInside bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return handleNat44Interface(ifIdx, isInside, true, vppChan, stopwatch) +// EnableNat44Interface implements NAT handler. +func (handler *NatVppHandler) EnableNat44Interface(ifIdx uint32, isInside bool) error { + return handler.handleNat44Interface(ifIdx, isInside, true) +} + +// DisableNat44Interface implements NAT handler. +func (handler *NatVppHandler) DisableNat44Interface(ifIdx uint32, isInside bool) error { + return handler.handleNat44Interface(ifIdx, isInside, false) +} + +// EnableNat44InterfaceOutput implements NAT handler. +func (handler *NatVppHandler) EnableNat44InterfaceOutput(ifIdx uint32, isInside bool) error { + return handler.handleNat44InterfaceOutputFeature(ifIdx, isInside, true) } -// DisableNat44Interface enables NAT feature for provided interface -func DisableNat44Interface(ifIdx uint32, isInside bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return handleNat44Interface(ifIdx, isInside, false, vppChan, stopwatch) +// DisableNat44InterfaceOutput implements NAT handler. +func (handler *NatVppHandler) DisableNat44InterfaceOutput(ifIdx uint32, isInside bool) error { + return handler.handleNat44InterfaceOutputFeature(ifIdx, isInside, false) } -// EnableNat44InterfaceOutput enables NAT output feature for provided interface -func EnableNat44InterfaceOutput(ifIdx uint32, isInside bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return handleNat44InterfaceOutputFeature(ifIdx, isInside, true, vppChan, stopwatch) +// AddNat44AddressPool implements NAT handler. +func (handler *NatVppHandler) AddNat44AddressPool(first, last []byte, vrf uint32, twiceNat bool) error { + return handler.handleNat44AddressPool(first, last, vrf, twiceNat, true) } -// DisableNat44InterfaceOutput disables NAT output feature for provided interface -func DisableNat44InterfaceOutput(ifIdx uint32, isInside bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return handleNat44InterfaceOutputFeature(ifIdx, isInside, false, vppChan, stopwatch) +// DelNat44AddressPool implements NAT handler. +func (handler *NatVppHandler) DelNat44AddressPool(first, last []byte, vrf uint32, twiceNat bool) error { + return handler.handleNat44AddressPool(first, last, vrf, twiceNat, false) } -// AddNat44AddressPool sets new NAT address pool -func AddNat44AddressPool(first, last []byte, vrf uint32, twiceNat bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return handleNat44AddressPool(first, last, vrf, twiceNat, true, vppChan, stopwatch) +// SetVirtualReassemblyIPv4 implements NAT handler. +func (handler *NatVppHandler) SetVirtualReassemblyIPv4(vrCfg *nat2.Nat44Global_VirtualReassembly) error { + return handler.handleNat44VirtualReassembly(vrCfg.Timeout, vrCfg.MaxReass, vrCfg.MaxFrag, vrCfg.DropFrag, false) } -// DelNat44AddressPool removes existing NAT address pool -func DelNat44AddressPool(first, last []byte, vrf uint32, twiceNat bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return handleNat44AddressPool(first, last, vrf, twiceNat, false, vppChan, stopwatch) +// SetVirtualReassemblyIPv6 implements NAT handler. +func (handler *NatVppHandler) SetVirtualReassemblyIPv6(vrCfg *nat2.Nat44Global_VirtualReassembly) error { + return handler.handleNat44VirtualReassembly(vrCfg.Timeout, vrCfg.MaxReass, vrCfg.MaxFrag, vrCfg.DropFrag, true) } -// AddNat44IdentityMapping sets new NAT address pool -func AddNat44IdentityMapping(ctx *IdentityMappingContext, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return handleNat44IdentityMapping(ctx, true, vppChan, stopwatch) +// AddNat44IdentityMapping implements NAT handler. +func (handler *NatVppHandler) AddNat44IdentityMapping(ctx *IdentityMappingContext) error { + return handler.handleNat44IdentityMapping(ctx, true) } -// DelNat44IdentityMapping sets new NAT address pool -func DelNat44IdentityMapping(ctx *IdentityMappingContext, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return handleNat44IdentityMapping(ctx, false, vppChan, stopwatch) +// DelNat44IdentityMapping implements NAT handler. +func (handler *NatVppHandler) DelNat44IdentityMapping(ctx *IdentityMappingContext) error { + return handler.handleNat44IdentityMapping(ctx, false) } -// AddNat44StaticMapping creates new static mapping entry -// (considering address only or both, address and port depending on the context) -func AddNat44StaticMapping(ctx *StaticMappingContext, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +// AddNat44StaticMapping implements NAT handler. +func (handler *NatVppHandler) AddNat44StaticMapping(ctx *StaticMappingContext) error { if ctx.AddressOnly { - return handleNat44StaticMapping(ctx, true, true, vppChan, stopwatch) + return handler.handleNat44StaticMapping(ctx, true, true) } - return handleNat44StaticMapping(ctx, true, false, vppChan, stopwatch) + return handler.handleNat44StaticMapping(ctx, true, false) } -// DelNat44StaticMapping removes existing static mapping entry -func DelNat44StaticMapping(ctx *StaticMappingContext, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +// DelNat44StaticMapping implements NAT handler. +func (handler *NatVppHandler) DelNat44StaticMapping(ctx *StaticMappingContext) error { if ctx.AddressOnly { - return handleNat44StaticMapping(ctx, false, true, vppChan, stopwatch) + return handler.handleNat44StaticMapping(ctx, false, true) } - return handleNat44StaticMapping(ctx, false, false, vppChan, stopwatch) + return handler.handleNat44StaticMapping(ctx, false, false) } -// AddNat44StaticMappingLb creates new static mapping entry with load balancer -func AddNat44StaticMappingLb(ctx *StaticMappingLbContext, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return handleNat44StaticMappingLb(ctx, true, vppChan, stopwatch) +// AddNat44StaticMappingLb implements NAT handler. +func (handler *NatVppHandler) AddNat44StaticMappingLb(ctx *StaticMappingLbContext) error { + return handler.handleNat44StaticMappingLb(ctx, true) } -// DelNat44StaticMappingLb removes existing static mapping entry with load balancer -func DelNat44StaticMappingLb(ctx *StaticMappingLbContext, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return handleNat44StaticMappingLb(ctx, false, vppChan, stopwatch) +// DelNat44StaticMappingLb implements NAT handler. +func (handler *NatVppHandler) DelNat44StaticMappingLb(ctx *StaticMappingLbContext) error { + return handler.handleNat44StaticMappingLb(ctx, false) } diff --git a/plugins/vpp/ifplugin/vppcalls/nat_vppcalls_test.go b/plugins/vpp/ifplugin/vppcalls/nat_vppcalls_test.go index 934a0ca4c2..57f6d97244 100644 --- a/plugins/vpp/ifplugin/vppcalls/nat_vppcalls_test.go +++ b/plugins/vpp/ifplugin/vppcalls/nat_vppcalls_test.go @@ -21,16 +21,16 @@ import ( "github.com/ligato/vpp-agent/plugins/vpp/binapi/nat" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" - "github.com/ligato/vpp-agent/tests/vppcallmock" + natapi "github.com/ligato/vpp-agent/plugins/vpp/model/nat" . "github.com/onsi/gomega" ) func TestSetNat44Forwarding(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&nat.Nat44ForwardingEnableDisableReply{}) - err := vppcalls.SetNat44Forwarding(true, ctx.MockChannel, nil) + err := natHandler.SetNat44Forwarding(true) Expect(err).ShouldNot(HaveOccurred()) @@ -41,11 +41,11 @@ func TestSetNat44Forwarding(t *testing.T) { } func TestUnsetNat44Forwarding(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&nat.Nat44ForwardingEnableDisableReply{}) - err := vppcalls.SetNat44Forwarding(false, ctx.MockChannel, nil) + err := natHandler.SetNat44Forwarding(false) Expect(err).ShouldNot(HaveOccurred()) @@ -56,34 +56,34 @@ func TestUnsetNat44Forwarding(t *testing.T) { } func TestSetNat44ForwardingError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() // Incorrect reply object ctx.MockVpp.MockReply(&nat.Nat44AddDelStaticMappingReply{}) - err := vppcalls.SetNat44Forwarding(true, ctx.MockChannel, nil) + err := natHandler.SetNat44Forwarding(true) Expect(err).Should(HaveOccurred()) } func TestSetNat44ForwardingRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&nat.Nat44ForwardingEnableDisableReply{ Retval: 1, }) - err := vppcalls.SetNat44Forwarding(true, ctx.MockChannel, nil) + err := natHandler.SetNat44Forwarding(true) Expect(err).Should(HaveOccurred()) } func TestEnableNat44InterfaceAsInside(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&nat.Nat44InterfaceAddDelFeatureReply{}) - err := vppcalls.EnableNat44Interface(1, true, ctx.MockChannel, nil) + err := natHandler.EnableNat44Interface(1, true) Expect(err).ShouldNot(HaveOccurred()) @@ -96,11 +96,11 @@ func TestEnableNat44InterfaceAsInside(t *testing.T) { } func TestEnableNat44InterfaceAsOutside(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&nat.Nat44InterfaceAddDelFeatureReply{}) - err := vppcalls.EnableNat44Interface(2, false, ctx.MockChannel, nil) + err := natHandler.EnableNat44Interface(2, false) Expect(err).ShouldNot(HaveOccurred()) @@ -113,34 +113,34 @@ func TestEnableNat44InterfaceAsOutside(t *testing.T) { } func TestEnableNat44InterfaceError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() // Incorrect reply object ctx.MockVpp.MockReply(&nat.Nat44AddDelAddressRangeReply{}) - err := vppcalls.EnableNat44Interface(2, false, ctx.MockChannel, nil) + err := natHandler.EnableNat44Interface(2, false) Expect(err).Should(HaveOccurred()) } func TestEnableNat44InterfaceRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&nat.Nat44InterfaceAddDelFeatureReply{ Retval: 1, }) - err := vppcalls.EnableNat44Interface(2, false, ctx.MockChannel, nil) + err := natHandler.EnableNat44Interface(2, false) Expect(err).Should(HaveOccurred()) } func TestDisableNat44InterfaceAsInside(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&nat.Nat44InterfaceAddDelFeatureReply{}) - err := vppcalls.DisableNat44Interface(1, true, ctx.MockChannel, nil) + err := natHandler.DisableNat44Interface(1, true) Expect(err).ShouldNot(HaveOccurred()) @@ -153,11 +153,11 @@ func TestDisableNat44InterfaceAsInside(t *testing.T) { } func TestDisableNat44InterfaceAsOutside(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&nat.Nat44InterfaceAddDelFeatureReply{}) - err := vppcalls.DisableNat44Interface(2, false, ctx.MockChannel, nil) + err := natHandler.DisableNat44Interface(2, false) Expect(err).ShouldNot(HaveOccurred()) @@ -170,11 +170,11 @@ func TestDisableNat44InterfaceAsOutside(t *testing.T) { } func TestEnableNat44InterfaceOutputAsInside(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&nat.Nat44InterfaceAddDelOutputFeatureReply{}) - err := vppcalls.EnableNat44InterfaceOutput(1, true, ctx.MockChannel, nil) + err := natHandler.EnableNat44InterfaceOutput(1, true) Expect(err).ShouldNot(HaveOccurred()) @@ -187,11 +187,11 @@ func TestEnableNat44InterfaceOutputAsInside(t *testing.T) { } func TestEnableNat44InterfaceOutputAsOutside(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&nat.Nat44InterfaceAddDelOutputFeatureReply{}) - err := vppcalls.EnableNat44InterfaceOutput(2, false, ctx.MockChannel, nil) + err := natHandler.EnableNat44InterfaceOutput(2, false) Expect(err).ShouldNot(HaveOccurred()) @@ -204,34 +204,34 @@ func TestEnableNat44InterfaceOutputAsOutside(t *testing.T) { } func TestEnableNat44InterfaceOutputError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() // Incorrect reply object ctx.MockVpp.MockReply(&nat.Nat44AddDelStaticMappingReply{}) - err := vppcalls.EnableNat44InterfaceOutput(2, false, ctx.MockChannel, nil) + err := natHandler.EnableNat44InterfaceOutput(2, false) Expect(err).Should(HaveOccurred()) } func TestEnableNat44InterfaceOutputRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&nat.Nat44InterfaceAddDelOutputFeatureReply{ Retval: 1, }) - err := vppcalls.EnableNat44InterfaceOutput(2, false, ctx.MockChannel, nil) + err := natHandler.EnableNat44InterfaceOutput(2, false) Expect(err).Should(HaveOccurred()) } func TestDisableNat44InterfaceOutputAsInside(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&nat.Nat44InterfaceAddDelOutputFeatureReply{}) - err := vppcalls.DisableNat44InterfaceOutput(1, true, ctx.MockChannel, nil) + err := natHandler.DisableNat44InterfaceOutput(1, true) Expect(err).ShouldNot(HaveOccurred()) @@ -244,11 +244,11 @@ func TestDisableNat44InterfaceOutputAsInside(t *testing.T) { } func TestDisableNat44InterfaceOutputAsOutside(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&nat.Nat44InterfaceAddDelOutputFeatureReply{}) - err := vppcalls.DisableNat44InterfaceOutput(2, false, ctx.MockChannel, nil) + err := natHandler.DisableNat44InterfaceOutput(2, false) Expect(err).ShouldNot(HaveOccurred()) @@ -261,14 +261,14 @@ func TestDisableNat44InterfaceOutputAsOutside(t *testing.T) { } func TestAddNat44AddressPool(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() firstIP := net.ParseIP("10.0.0.1").To4() lastIP := net.ParseIP("10.0.0.2").To4() ctx.MockVpp.MockReply(&nat.Nat44AddDelAddressRangeReply{}) - err := vppcalls.AddNat44AddressPool(firstIP, lastIP, 0, false, ctx.MockChannel, nil) + err := natHandler.AddNat44AddressPool(firstIP, lastIP, 0, false) Expect(err).ShouldNot(HaveOccurred()) @@ -282,7 +282,7 @@ func TestAddNat44AddressPool(t *testing.T) { } func TestAddNat44AddressPoolError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() firstIP := net.ParseIP("10.0.0.1").To4() @@ -290,13 +290,13 @@ func TestAddNat44AddressPoolError(t *testing.T) { // Incorrect reply object ctx.MockVpp.MockReply(&nat.Nat44AddDelIdentityMappingReply{}) - err := vppcalls.AddNat44AddressPool(firstIP, lastIP, 0, false, ctx.MockChannel, nil) + err := natHandler.AddNat44AddressPool(firstIP, lastIP, 0, false) Expect(err).Should(HaveOccurred()) } func TestAddNat44AddressPoolRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() firstIP := net.ParseIP("10.0.0.1").To4() @@ -305,20 +305,20 @@ func TestAddNat44AddressPoolRetval(t *testing.T) { ctx.MockVpp.MockReply(&nat.Nat44AddDelAddressRangeReply{ Retval: 1, }) - err := vppcalls.AddNat44AddressPool(firstIP, lastIP, 0, false, ctx.MockChannel, nil) + err := natHandler.AddNat44AddressPool(firstIP, lastIP, 0, false) Expect(err).Should(HaveOccurred()) } func TestDelNat44AddressPool(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() firstIP := net.ParseIP("10.0.0.1").To4() lastIP := net.ParseIP("10.0.0.2").To4() ctx.MockVpp.MockReply(&nat.Nat44AddDelAddressRangeReply{}) - err := vppcalls.DelNat44AddressPool(firstIP, lastIP, 0, false, ctx.MockChannel, nil) + err := natHandler.DelNat44AddressPool(firstIP, lastIP, 0, false) Expect(err).ShouldNot(HaveOccurred()) @@ -331,8 +331,52 @@ func TestDelNat44AddressPool(t *testing.T) { Expect(msg.TwiceNat).To(BeEquivalentTo(0)) } +func TestSetNat44VirtualReassemblyIPv4(t *testing.T) { + ctx, natHandler, _ := natTestSetup(t) + defer ctx.TeardownTestCtx() + + ctx.MockVpp.MockReply(&nat.NatSetReassReply{}) + err := natHandler.SetVirtualReassemblyIPv4(&natapi.Nat44Global_VirtualReassembly{ + Timeout: 10, + MaxFrag: 20, + MaxReass: 30, + DropFrag: true, + }) + + Expect(err).ShouldNot(HaveOccurred()) + + msg, ok := ctx.MockChannel.Msg.(*nat.NatSetReass) + Expect(ok).To(BeTrue()) + Expect(msg.Timeout).To(BeEquivalentTo(10)) + Expect(msg.MaxFrag).To(BeEquivalentTo(20)) + Expect(msg.MaxReass).To(BeEquivalentTo(30)) + Expect(msg.DropFrag).To(BeEquivalentTo(1)) +} + +func TestSetNat44VirtualReassemblyIPv6(t *testing.T) { + ctx, natHandler, _ := natTestSetup(t) + defer ctx.TeardownTestCtx() + + ctx.MockVpp.MockReply(&nat.NatSetReassReply{}) + err := natHandler.SetVirtualReassemblyIPv6(&natapi.Nat44Global_VirtualReassembly{ + Timeout: 5, + MaxFrag: 10, + MaxReass: 15, + DropFrag: true, + }) + + Expect(err).ShouldNot(HaveOccurred()) + + msg, ok := ctx.MockChannel.Msg.(*nat.NatSetReass) + Expect(ok).To(BeTrue()) + Expect(msg.Timeout).To(BeEquivalentTo(5)) + Expect(msg.MaxFrag).To(BeEquivalentTo(10)) + Expect(msg.MaxReass).To(BeEquivalentTo(15)) + Expect(msg.DropFrag).To(BeEquivalentTo(1)) +} + func TestAddNat44StaticMapping(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() localIP := net.ParseIP("10.0.0.1").To4() @@ -353,7 +397,7 @@ func TestAddNat44StaticMapping(t *testing.T) { } ctx.MockVpp.MockReply(&nat.Nat44AddDelStaticMappingReply{}) - err := vppcalls.AddNat44StaticMapping(stmCtx, ctx.MockChannel, nil) + err := natHandler.AddNat44StaticMapping(stmCtx) Expect(err).ShouldNot(HaveOccurred()) @@ -374,7 +418,7 @@ func TestAddNat44StaticMapping(t *testing.T) { } func TestAddNat44StaticMappingAddrOnly(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() localIP := net.ParseIP("10.0.0.1").To4() @@ -389,7 +433,7 @@ func TestAddNat44StaticMappingAddrOnly(t *testing.T) { } ctx.MockVpp.MockReply(&nat.Nat44AddDelStaticMappingReply{}) - err := vppcalls.AddNat44StaticMapping(stmCtx, ctx.MockChannel, nil) + err := natHandler.AddNat44StaticMapping(stmCtx) Expect(err).ShouldNot(HaveOccurred()) @@ -403,30 +447,30 @@ func TestAddNat44StaticMappingAddrOnly(t *testing.T) { } func TestAddNat44StaticMappingError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() // Incorrect reply object ctx.MockVpp.MockReply(&nat.Nat44AddDelLbStaticMappingReply{}) - err := vppcalls.AddNat44StaticMapping(&vppcalls.StaticMappingContext{}, ctx.MockChannel, nil) + err := natHandler.AddNat44StaticMapping(&vppcalls.StaticMappingContext{}) Expect(err).Should(HaveOccurred()) } func TestAddNat44StaticMappingRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&nat.Nat44AddDelStaticMappingReply{ Retval: 1, }) - err := vppcalls.AddNat44StaticMapping(&vppcalls.StaticMappingContext{}, ctx.MockChannel, nil) + err := natHandler.AddNat44StaticMapping(&vppcalls.StaticMappingContext{}) Expect(err).Should(HaveOccurred()) } func TestDelNat44StaticMapping(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() localIP := net.ParseIP("10.0.0.1").To4() @@ -441,7 +485,7 @@ func TestDelNat44StaticMapping(t *testing.T) { } ctx.MockVpp.MockReply(&nat.Nat44AddDelStaticMappingReply{}) - err := vppcalls.DelNat44StaticMapping(stmCtx, ctx.MockChannel, nil) + err := natHandler.DelNat44StaticMapping(stmCtx) Expect(err).ShouldNot(HaveOccurred()) @@ -455,7 +499,7 @@ func TestDelNat44StaticMapping(t *testing.T) { } func TestDelNat44StaticMappingAddrOnly(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() localIP := net.ParseIP("10.0.0.1").To4() @@ -470,7 +514,7 @@ func TestDelNat44StaticMappingAddrOnly(t *testing.T) { } ctx.MockVpp.MockReply(&nat.Nat44AddDelStaticMappingReply{}) - err := vppcalls.DelNat44StaticMapping(stmCtx, ctx.MockChannel, nil) + err := natHandler.DelNat44StaticMapping(stmCtx) Expect(err).ShouldNot(HaveOccurred()) @@ -484,7 +528,7 @@ func TestDelNat44StaticMappingAddrOnly(t *testing.T) { } func TestAddNat44StaticMappingLb(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() externalIP := net.ParseIP("10.0.0.1").To4() @@ -498,19 +542,17 @@ func TestAddNat44StaticMappingLb(t *testing.T) { ExternalIP: externalIP, ExternalPort: 8080, Protocol: 16, - Vrf: 1, TwiceNat: true, } ctx.MockVpp.MockReply(&nat.Nat44AddDelLbStaticMappingReply{}) - err := vppcalls.AddNat44StaticMappingLb(stmCtx, ctx.MockChannel, nil) + err := natHandler.AddNat44StaticMappingLb(stmCtx) Expect(err).ShouldNot(HaveOccurred()) msg, ok := ctx.MockChannel.Msg.(*nat.Nat44AddDelLbStaticMapping) Expect(ok).To(BeTrue()) Expect(msg.Tag).To(BeEquivalentTo("tag1")) - Expect(msg.VrfID).To(BeEquivalentTo(1)) Expect(msg.TwiceNat).To(BeEquivalentTo(1)) Expect(msg.IsAdd).To(BeEquivalentTo(1)) Expect(msg.ExternalAddr).To(BeEquivalentTo(externalIP)) @@ -533,30 +575,30 @@ func TestAddNat44StaticMappingLb(t *testing.T) { } func TestAddNat44StaticMappingLbError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() // Incorrect reply object ctx.MockVpp.MockReply(&nat.Nat44AddDelIdentityMappingReply{}) - err := vppcalls.AddNat44StaticMappingLb(&vppcalls.StaticMappingLbContext{}, ctx.MockChannel, nil) + err := natHandler.AddNat44StaticMappingLb(&vppcalls.StaticMappingLbContext{}) Expect(err).Should(HaveOccurred()) } func TestAddNat44StaticMappingLbRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&nat.Nat44AddDelLbStaticMappingReply{ Retval: 1, }) - err := vppcalls.AddNat44StaticMappingLb(&vppcalls.StaticMappingLbContext{}, ctx.MockChannel, nil) + err := natHandler.AddNat44StaticMappingLb(&vppcalls.StaticMappingLbContext{}) Expect(err).Should(HaveOccurred()) } func TestDelNat44StaticMappingLb(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() externalIP := net.ParseIP("10.0.0.1").To4() @@ -570,19 +612,17 @@ func TestDelNat44StaticMappingLb(t *testing.T) { ExternalIP: externalIP, ExternalPort: 8080, Protocol: 16, - Vrf: 1, TwiceNat: true, } ctx.MockVpp.MockReply(&nat.Nat44AddDelLbStaticMappingReply{}) - err := vppcalls.DelNat44StaticMappingLb(stmCtx, ctx.MockChannel, nil) + err := natHandler.DelNat44StaticMappingLb(stmCtx) Expect(err).ShouldNot(HaveOccurred()) msg, ok := ctx.MockChannel.Msg.(*nat.Nat44AddDelLbStaticMapping) Expect(ok).To(BeTrue()) Expect(msg.Tag).To(BeEquivalentTo("tag1")) - Expect(msg.VrfID).To(BeEquivalentTo(1)) Expect(msg.TwiceNat).To(BeEquivalentTo(1)) Expect(msg.IsAdd).To(BeEquivalentTo(0)) Expect(msg.ExternalAddr).To(BeEquivalentTo(externalIP)) @@ -605,7 +645,7 @@ func TestDelNat44StaticMappingLb(t *testing.T) { } func TestAddNat44IdentityMapping(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() address := net.ParseIP("10.0.0.1").To4() @@ -621,7 +661,7 @@ func TestAddNat44IdentityMapping(t *testing.T) { } ctx.MockVpp.MockReply(&nat.Nat44AddDelIdentityMappingReply{}) - err := vppcalls.AddNat44IdentityMapping(idmCtx, ctx.MockChannel, nil) + err := natHandler.AddNat44IdentityMapping(idmCtx) Expect(err).ShouldNot(HaveOccurred()) @@ -638,7 +678,7 @@ func TestAddNat44IdentityMapping(t *testing.T) { } func TestAddNat44IdentityMappingAddrOnly(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() // DataContext (IPAddress == nil and Port == 0 means it's address only) @@ -650,7 +690,7 @@ func TestAddNat44IdentityMappingAddrOnly(t *testing.T) { } ctx.MockVpp.MockReply(&nat.Nat44AddDelIdentityMappingReply{}) - err := vppcalls.AddNat44IdentityMapping(idmCtx, ctx.MockChannel, nil) + err := natHandler.AddNat44IdentityMapping(idmCtx) Expect(err).ShouldNot(HaveOccurred()) @@ -662,7 +702,7 @@ func TestAddNat44IdentityMappingAddrOnly(t *testing.T) { } func TestAddNat44IdentityMappingNoInterface(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() address := net.ParseIP("10.0.0.1").To4() @@ -677,7 +717,7 @@ func TestAddNat44IdentityMappingNoInterface(t *testing.T) { } ctx.MockVpp.MockReply(&nat.Nat44AddDelIdentityMappingReply{}) - err := vppcalls.AddNat44IdentityMapping(idmCtx, ctx.MockChannel, nil) + err := natHandler.AddNat44IdentityMapping(idmCtx) Expect(err).ShouldNot(HaveOccurred()) @@ -691,30 +731,30 @@ func TestAddNat44IdentityMappingNoInterface(t *testing.T) { } func TestAddNat44IdentityMappingError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() // Incorrect reply object ctx.MockVpp.MockReply(&nat.Nat44AddDelStaticMappingReply{}) - err := vppcalls.AddNat44IdentityMapping(&vppcalls.IdentityMappingContext{}, ctx.MockChannel, nil) + err := natHandler.AddNat44IdentityMapping(&vppcalls.IdentityMappingContext{}) Expect(err).Should(HaveOccurred()) } func TestAddNat44IdentityMappingRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&nat.Nat44AddDelIdentityMappingReply{ Retval: 1, }) - err := vppcalls.AddNat44IdentityMapping(&vppcalls.IdentityMappingContext{}, ctx.MockChannel, nil) + err := natHandler.AddNat44IdentityMapping(&vppcalls.IdentityMappingContext{}) Expect(err).Should(HaveOccurred()) } func TestDelNat44IdentityMapping(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, natHandler, _ := natTestSetup(t) defer ctx.TeardownTestCtx() address := net.ParseIP("10.0.0.1").To4() @@ -729,7 +769,7 @@ func TestDelNat44IdentityMapping(t *testing.T) { } ctx.MockVpp.MockReply(&nat.Nat44AddDelIdentityMappingReply{}) - err := vppcalls.DelNat44IdentityMapping(idmCtx, ctx.MockChannel, nil) + err := natHandler.DelNat44IdentityMapping(idmCtx) Expect(err).ShouldNot(HaveOccurred()) diff --git a/plugins/vpp/ifplugin/vppcalls/rx_mode_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/rx_mode_vppcalls.go index 3bc8fd8218..20e12fb1b6 100644 --- a/plugins/vpp/ifplugin/vppcalls/rx_mode_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/rx_mode_vppcalls.go @@ -18,16 +18,14 @@ import ( "fmt" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" intf "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" ) -// SetRxMode calls SwInterfaceSetRxMode bin -func SetRxMode(ifIdx uint32, rxModeSettings *intf.Interfaces_Interface_RxModeSettings, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +// SetRxMode implements interface handler. +func (h *IfVppHandler) SetRxMode(ifIdx uint32, rxModeSettings *intf.Interfaces_Interface_RxModeSettings) error { defer func(t time.Time) { - stopwatch.TimeLog(interfaces.SwInterfaceSetRxMode{}).LogTimeEntry(time.Since(t)) + h.stopwatch.TimeLog(interfaces.SwInterfaceSetRxMode{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &interfaces.SwInterfaceSetRxMode{ @@ -36,12 +34,11 @@ func SetRxMode(ifIdx uint32, rxModeSettings *intf.Interfaces_Interface_RxModeSet QueueID: rxModeSettings.QueueId, QueueIDValid: uint8(rxModeSettings.QueueIdValid), } - reply := &interfaces.SwInterfaceSetRxModeReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } diff --git a/plugins/vpp/ifplugin/vppcalls/rx_mode_vppcalls_test.go b/plugins/vpp/ifplugin/vppcalls/rx_mode_vppcalls_test.go index c479f65067..d616fc04c2 100644 --- a/plugins/vpp/ifplugin/vppcalls/rx_mode_vppcalls_test.go +++ b/plugins/vpp/ifplugin/vppcalls/rx_mode_vppcalls_test.go @@ -18,23 +18,21 @@ import ( "testing" "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" ifModel "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" - "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" ) func TestSetRxMode(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetRxModeReply{}) - err := vppcalls.SetRxMode(1, &ifModel.Interfaces_Interface_RxModeSettings{ + err := ifHandler.SetRxMode(1, &ifModel.Interfaces_Interface_RxModeSettings{ RxMode: ifModel.RxModeType_DEFAULT, QueueId: 1, QueueIdValid: 2, - }, ctx.MockChannel, nil) + }) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*interfaces.SwInterfaceSetRxMode) @@ -46,33 +44,33 @@ func TestSetRxMode(t *testing.T) { } func TestSetRxModeError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetRxMode{}) - err := vppcalls.SetRxMode(1, &ifModel.Interfaces_Interface_RxModeSettings{ + err := ifHandler.SetRxMode(1, &ifModel.Interfaces_Interface_RxModeSettings{ RxMode: ifModel.RxModeType_DEFAULT, QueueId: 1, QueueIdValid: 2, - }, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } func TestSetRxModeRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetRxModeReply{ Retval: 1, }) - err := vppcalls.SetRxMode(1, &ifModel.Interfaces_Interface_RxModeSettings{ + err := ifHandler.SetRxMode(1, &ifModel.Interfaces_Interface_RxModeSettings{ RxMode: ifModel.RxModeType_DEFAULT, QueueId: 1, QueueIdValid: 2, - }, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } diff --git a/plugins/vpp/ifplugin/vppcalls/rx_placement_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/rx_placement_vppcalls.go index d7397a06d7..d6fa42a49b 100644 --- a/plugins/vpp/ifplugin/vppcalls/rx_placement_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/rx_placement_vppcalls.go @@ -16,23 +16,18 @@ package vppcalls import ( "fmt" - "time" - "strconv" + "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/logrus" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" "github.com/ligato/vpp-agent/plugins/vpp/binapi/vpe" intf "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" ) -// SetRxPlacement -func SetRxPlacement(vppInternalName string, rxPlacement *intf.Interfaces_Interface_RxPlacementSettings, - vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +// SetRxPlacement implements interface handler. +func (h *IfVppHandler) SetRxPlacement(vppInternalName string, rxPlacement *intf.Interfaces_Interface_RxPlacementSettings) error { defer func(t time.Time) { - stopwatch.TimeLog(interfaces.SwInterfaceSetRxMode{}).LogTimeEntry(time.Since(t)) + h.stopwatch.TimeLog(interfaces.SwInterfaceSetRxMode{}).LogTimeEntry(time.Since(t)) }(time.Now()) queue := strconv.Itoa(int(rxPlacement.Queue)) @@ -40,19 +35,18 @@ func SetRxPlacement(vppInternalName string, rxPlacement *intf.Interfaces_Interfa command := "set interface rx-placement " + vppInternalName + " queue " + queue + " worker " + worker - logrus.DefaultLogger().Warnf("Setting rx-placement commnad %s", command) + h.log.Warnf("Setting rx-placement commnad %s", command) - // todo: binary api call for rx-placement is not available + // TODO: binary api call for rx-placement is not available req := &vpe.CliInband{ Length: uint32(len(command)), Cmd: []byte(command), } - reply := &vpe.CliInbandReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } if reply.Length > 0 { diff --git a/plugins/vpp/ifplugin/vppcalls/rx_placement_vppcalls_test.go b/plugins/vpp/ifplugin/vppcalls/rx_placement_vppcalls_test.go index e05d0dda5c..9b53cc5ce2 100644 --- a/plugins/vpp/ifplugin/vppcalls/rx_placement_vppcalls_test.go +++ b/plugins/vpp/ifplugin/vppcalls/rx_placement_vppcalls_test.go @@ -18,22 +18,20 @@ import ( "testing" "github.com/ligato/vpp-agent/plugins/vpp/binapi/vpe" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" - "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" ) func TestSetRxPlacement(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&vpe.CliInbandReply{}) - err := vppcalls.SetRxPlacement("if-internal", &interfaces.Interfaces_Interface_RxPlacementSettings{ + err := ifHandler.SetRxPlacement("if-internal", &interfaces.Interfaces_Interface_RxPlacementSettings{ Queue: 1, Worker: 2, - }, ctx.MockChannel, nil) + }) expMsg := "set interface rx-placement if-internal queue 1 worker 2" expMsgLen := len(expMsg) @@ -46,47 +44,47 @@ func TestSetRxPlacement(t *testing.T) { } func TestSetRxPlacementRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&vpe.CliInbandReply{ Retval: 1, }) - err := vppcalls.SetRxPlacement("if-internal", &interfaces.Interfaces_Interface_RxPlacementSettings{ + err := ifHandler.SetRxPlacement("if-internal", &interfaces.Interfaces_Interface_RxPlacementSettings{ Queue: 1, Worker: 2, - }, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } func TestSetRxPlacementReply(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&vpe.CliInbandReply{ Reply: []byte("dummy-reply"), }) - err := vppcalls.SetRxPlacement("if-internal", &interfaces.Interfaces_Interface_RxPlacementSettings{ + err := ifHandler.SetRxPlacement("if-internal", &interfaces.Interfaces_Interface_RxPlacementSettings{ Queue: 1, Worker: 2, - }, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } func TestSetRxPlacementError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&vpe.CliInband{}) - err := vppcalls.SetRxPlacement("if-internal", &interfaces.Interfaces_Interface_RxPlacementSettings{ + err := ifHandler.SetRxPlacement("if-internal", &interfaces.Interfaces_Interface_RxPlacementSettings{ Queue: 1, Worker: 2, - }, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } diff --git a/plugins/vpp/ifplugin/vppcalls/stn_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/stn_vppcalls.go index d25026d598..20769557ec 100644 --- a/plugins/vpp/ifplugin/vppcalls/stn_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/stn_vppcalls.go @@ -19,8 +19,6 @@ import ( "net" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/cn-infra/utils/addrs" "github.com/ligato/vpp-agent/plugins/vpp/binapi/stn" ) @@ -31,9 +29,9 @@ type StnRule struct { IfaceIdx uint32 } -func addDelStnRule(ifIdx uint32, addr *net.IP, isAdd bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +func (handler *StnVppHandler) addDelStnRule(ifIdx uint32, addr *net.IP, isAdd bool) error { defer func(t time.Time) { - stopwatch.TimeLog(stn.StnAddDelRule{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(stn.StnAddDelRule{}).LogTimeEntry(time.Since(t)) }(time.Now()) // prepare the message @@ -53,12 +51,11 @@ func addDelStnRule(ifIdx uint32, addr *net.IP, isAdd bool, vppChan govppapi.Chan req.IPAddress = []byte(addr.To4()) req.IsIP4 = 1 } - reply := &stn.StnAddDelRuleReply{} - if err = vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err = handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } @@ -66,13 +63,13 @@ func addDelStnRule(ifIdx uint32, addr *net.IP, isAdd bool, vppChan govppapi.Chan } -// AddStnRule calls StnAddDelRule bin API with IsAdd=1 -func AddStnRule(ifIdx uint32, addr *net.IP, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return addDelStnRule(ifIdx, addr, true, vppChan, stopwatch) +// AddStnRule implements STN handler. +func (handler *StnVppHandler) AddStnRule(ifIdx uint32, addr *net.IP) error { + return handler.addDelStnRule(ifIdx, addr, true) } -// DelStnRule calls StnAddDelRule bin API with IsAdd=0 -func DelStnRule(ifIdx uint32, addr *net.IP, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return addDelStnRule(ifIdx, addr, false, vppChan, stopwatch) +// DelStnRule implements STN handler. +func (handler *StnVppHandler) DelStnRule(ifIdx uint32, addr *net.IP) error { + return handler.addDelStnRule(ifIdx, addr, false) } diff --git a/plugins/vpp/ifplugin/vppcalls/stn_vppcalls_test.go b/plugins/vpp/ifplugin/vppcalls/stn_vppcalls_test.go index 1f2c5b957b..e493ff7247 100644 --- a/plugins/vpp/ifplugin/vppcalls/stn_vppcalls_test.go +++ b/plugins/vpp/ifplugin/vppcalls/stn_vppcalls_test.go @@ -18,20 +18,23 @@ import ( "net" "testing" + "github.com/ligato/cn-infra/logging/logrus" + "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/vpp/binapi/stn" + "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" ) func TestAddStnRule(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, stnHandler := stnTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&stn.StnAddDelRuleReply{}) _, ip, _ := net.ParseCIDR("10.0.0.1/24") - err := vppcalls.AddStnRule(1, &ip.IP, ctx.MockChannel, nil) + err := stnHandler.AddStnRule(1, &ip.IP) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*stn.StnAddDelRule) @@ -43,13 +46,13 @@ func TestAddStnRule(t *testing.T) { } func TestAddStnRuleIPv6(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, stnHandler := stnTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&stn.StnAddDelRuleReply{}) _, ip, _ := net.ParseCIDR("2001:db8:0:1:1:1:1:1/128") - err := vppcalls.AddStnRule(1, &ip.IP, ctx.MockChannel, nil) + err := stnHandler.AddStnRule(1, &ip.IP) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*stn.StnAddDelRule) @@ -61,31 +64,31 @@ func TestAddStnRuleIPv6(t *testing.T) { } func TestAddStnRuleInvalidIP(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, stnHandler := stnTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&stn.StnAddDelRuleReply{}) var ip net.IP = []byte("invalid-ip") - err := vppcalls.AddStnRule(1, &ip, ctx.MockChannel, nil) + err := stnHandler.AddStnRule(1, &ip) Expect(err).ToNot(BeNil()) } func TestAddStnRuleError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, stnHandler := stnTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&stn.StnAddDelRule{}) _, ip, _ := net.ParseCIDR("10.0.0.1/24") - err := vppcalls.AddStnRule(1, &ip.IP, ctx.MockChannel, nil) + err := stnHandler.AddStnRule(1, &ip.IP) Expect(err).ToNot(BeNil()) } func TestAddStnRuleRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, stnHandler := stnTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&stn.StnAddDelRuleReply{ @@ -93,22 +96,29 @@ func TestAddStnRuleRetval(t *testing.T) { }) _, ip, _ := net.ParseCIDR("10.0.0.1/24") - err := vppcalls.AddStnRule(1, &ip.IP, ctx.MockChannel, nil) + err := stnHandler.AddStnRule(1, &ip.IP) Expect(err).ToNot(BeNil()) } func TestDelStnRule(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, stnHandler := stnTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&stn.StnAddDelRuleReply{}) _, ip, _ := net.ParseCIDR("10.0.0.1/24") - err := vppcalls.DelStnRule(1, &ip.IP, ctx.MockChannel, nil) + err := stnHandler.DelStnRule(1, &ip.IP) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*stn.StnAddDelRule) Expect(ok).To(BeTrue()) Expect(vppMsg.IsAdd).To(BeEquivalentTo(0)) } + +func stnTestSetup(t *testing.T) (*vppcallmock.TestCtx, vppcalls.StnVppAPI) { + ctx := vppcallmock.SetupTestCtx(t) + ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "stn-if-idx", nil)) + stnHandler := vppcalls.NewStnVppHandler(ctx.MockChannel, ifIndexes, logrus.DefaultLogger(), nil) + return ctx, stnHandler +} diff --git a/plugins/vpp/ifplugin/vppcalls/tap_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/tap_vppcalls.go index d5a2fc6309..256be811bf 100644 --- a/plugins/vpp/ifplugin/vppcalls/tap_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/tap_vppcalls.go @@ -19,17 +19,15 @@ import ( "fmt" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/vpp-agent/plugins/vpp/binapi/tap" "github.com/ligato/vpp-agent/plugins/vpp/binapi/tapv2" "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" ) -// AddTapInterface calls TapConnect bin API. -func AddTapInterface(ifName string, tapIf *interfaces.Interfaces_Interface_Tap, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (swIfIdx uint32, err error) { +// AddTapInterface implements interface handler. +func (h *IfVppHandler) AddTapInterface(ifName string, tapIf *interfaces.Interfaces_Interface_Tap) (swIfIdx uint32, err error) { defer func(t time.Time) { - stopwatch.TimeLog(tap.TapConnect{}).LogTimeEntry(time.Since(t)) + h.stopwatch.TimeLog(tap.TapConnect{}).LogTimeEntry(time.Since(t)) }(time.Now()) if tapIf == nil || tapIf.HostIfName == "" { @@ -56,7 +54,7 @@ func AddTapInterface(ifName string, tapIf *interfaces.Interfaces_Interface_Tap, } reply := &tapv2.TapCreateV2Reply{} - err = vppChan.SendRequest(req).ReceiveReply(reply) + err = h.callsChannel.SendRequest(req).ReceiveReply(reply) retval = reply.Retval swIfIdx = reply.SwIfIndex msgName = reply.GetMessageName() @@ -68,7 +66,7 @@ func AddTapInterface(ifName string, tapIf *interfaces.Interfaces_Interface_Tap, } reply := &tap.TapConnectReply{} - err = vppChan.SendRequest(req).ReceiveReply(reply) + err = h.callsChannel.SendRequest(req).ReceiveReply(reply) retval = reply.Retval swIfIdx = reply.SwIfIndex msgName = reply.GetMessageName() @@ -80,13 +78,13 @@ func AddTapInterface(ifName string, tapIf *interfaces.Interfaces_Interface_Tap, return 0, fmt.Errorf("%s returned %d", msgName, retval) } - return swIfIdx, SetInterfaceTag(ifName, swIfIdx, vppChan, stopwatch) + return swIfIdx, h.SetInterfaceTag(ifName, swIfIdx) } -// DeleteTapInterface calls TapDelete bin API. -func DeleteTapInterface(ifName string, idx uint32, version uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +// DeleteTapInterface implements interface handler. +func (h *IfVppHandler) DeleteTapInterface(ifName string, idx uint32, version uint32) error { defer func(t time.Time) { - stopwatch.TimeLog(tap.TapDelete{}).LogTimeEntry(time.Since(t)) + h.stopwatch.TimeLog(tap.TapDelete{}).LogTimeEntry(time.Since(t)) }(time.Now()) var ( @@ -100,7 +98,7 @@ func DeleteTapInterface(ifName string, idx uint32, version uint32, vppChan govpp } reply := &tapv2.TapDeleteV2Reply{} - err = vppChan.SendRequest(req).ReceiveReply(reply) + err = h.callsChannel.SendRequest(req).ReceiveReply(reply) retval = reply.Retval msgName = reply.GetMessageName() } else { @@ -109,7 +107,7 @@ func DeleteTapInterface(ifName string, idx uint32, version uint32, vppChan govpp } reply := &tap.TapDeleteReply{} - err = vppChan.SendRequest(req).ReceiveReply(reply) + err = h.callsChannel.SendRequest(req).ReceiveReply(reply) retval = reply.Retval msgName = reply.GetMessageName() } @@ -120,5 +118,5 @@ func DeleteTapInterface(ifName string, idx uint32, version uint32, vppChan govpp return fmt.Errorf("%s returned %d", msgName, retval) } - return RemoveInterfaceTag(ifName, idx, vppChan, stopwatch) + return h.RemoveInterfaceTag(ifName, idx) } diff --git a/plugins/vpp/ifplugin/vppcalls/tap_vppcalls_test.go b/plugins/vpp/ifplugin/vppcalls/tap_vppcalls_test.go index 6c2300e4cb..4bb66f0afd 100644 --- a/plugins/vpp/ifplugin/vppcalls/tap_vppcalls_test.go +++ b/plugins/vpp/ifplugin/vppcalls/tap_vppcalls_test.go @@ -20,14 +20,12 @@ import ( "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" "github.com/ligato/vpp-agent/plugins/vpp/binapi/tap" "github.com/ligato/vpp-agent/plugins/vpp/binapi/tapv2" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" ifModel "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" - "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" ) func TestAddTapInterface(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&tap.TapConnectReply{ @@ -35,13 +33,13 @@ func TestAddTapInterface(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - swIfIdx, err := vppcalls.AddTapInterface("tapIf", &ifModel.Interfaces_Interface_Tap{ + swIfIdx, err := ifHandler.AddTapInterface("tapIf", &ifModel.Interfaces_Interface_Tap{ Version: 1, HostIfName: "hostIf", Namespace: "ns1", RxRingSize: 1, TxRingSize: 1, - }, ctx.MockChannel, nil) + }) Expect(err).To(BeNil()) Expect(swIfIdx).To(BeEquivalentTo(1)) var msgCheck bool @@ -57,7 +55,7 @@ func TestAddTapInterface(t *testing.T) { } func TestAddTapInterfaceV2(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&tapv2.TapCreateV2Reply{ @@ -65,13 +63,13 @@ func TestAddTapInterfaceV2(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - swIfIdx, err := vppcalls.AddTapInterface("tapIf", &ifModel.Interfaces_Interface_Tap{ + swIfIdx, err := ifHandler.AddTapInterface("tapIf", &ifModel.Interfaces_Interface_Tap{ Version: 2, HostIfName: "hostIf", Namespace: "ns1", RxRingSize: 1, TxRingSize: 1, - }, ctx.MockChannel, nil) + }) Expect(err).To(BeNil()) Expect(swIfIdx).To(BeEquivalentTo(1)) var msgCheck bool @@ -88,7 +86,7 @@ func TestAddTapInterfaceV2(t *testing.T) { } func TestAddTapInterfaceNoInput(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&tap.TapConnectReply{ @@ -96,29 +94,29 @@ func TestAddTapInterfaceNoInput(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - _, err := vppcalls.AddTapInterface("tapIf", nil, ctx.MockChannel, nil) + _, err := ifHandler.AddTapInterface("tapIf", nil) Expect(err).ToNot(BeNil()) } func TestAddTapInterfaceError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&tap.TapConnect{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - _, err := vppcalls.AddTapInterface("tapIf", &ifModel.Interfaces_Interface_Tap{ + _, err := ifHandler.AddTapInterface("tapIf", &ifModel.Interfaces_Interface_Tap{ Version: 1, HostIfName: "hostIf", Namespace: "ns1", RxRingSize: 1, TxRingSize: 1, - }, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } func TestAddTapInterfaceRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&tap.TapConnectReply{ @@ -126,24 +124,24 @@ func TestAddTapInterfaceRetval(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - _, err := vppcalls.AddTapInterface("tapIf", &ifModel.Interfaces_Interface_Tap{ + _, err := ifHandler.AddTapInterface("tapIf", &ifModel.Interfaces_Interface_Tap{ Version: 1, HostIfName: "hostIf", Namespace: "ns1", RxRingSize: 1, TxRingSize: 1, - }, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } func TestDeleteTapInterface(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&tap.TapDeleteReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - err := vppcalls.DeleteTapInterface("tapIf", 1, 1, ctx.MockChannel, nil) + err := ifHandler.DeleteTapInterface("tapIf", 1, 1) Expect(err).To(BeNil()) var msgCheck bool for _, msg := range ctx.MockChannel.Msgs { @@ -157,13 +155,13 @@ func TestDeleteTapInterface(t *testing.T) { } func TestDeleteTapInterfaceV2(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&tapv2.TapDeleteV2Reply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - err := vppcalls.DeleteTapInterface("tapIf", 1, 2, ctx.MockChannel, nil) + err := ifHandler.DeleteTapInterface("tapIf", 1, 2) Expect(err).To(BeNil()) var msgCheck bool for _, msg := range ctx.MockChannel.Msgs { @@ -177,18 +175,18 @@ func TestDeleteTapInterfaceV2(t *testing.T) { } func TestDeleteTapInterfaceError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&tap.TapDelete{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - err := vppcalls.DeleteTapInterface("tapIf", 1, 1, ctx.MockChannel, nil) + err := ifHandler.DeleteTapInterface("tapIf", 1, 1) Expect(err).ToNot(BeNil()) } func TestDeleteTapInterfaceRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&tap.TapDeleteReply{ @@ -196,6 +194,6 @@ func TestDeleteTapInterfaceRetval(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - err := vppcalls.DeleteTapInterface("tapIf", 1, 1, ctx.MockChannel, nil) + err := ifHandler.DeleteTapInterface("tapIf", 1, 1) Expect(err).ToNot(BeNil()) } diff --git a/plugins/vpp/ifplugin/vppcalls/vrf_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/vrf_vppcalls.go index cbaf06719e..71a2b5edff 100644 --- a/plugins/vpp/ifplugin/vppcalls/vrf_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/vrf_vppcalls.go @@ -17,99 +17,135 @@ package vppcalls import ( "fmt" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/logrus" + "time" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" ) -// GetInterfaceVRF assigns VRF table to interface -func GetInterfaceVRF(ifIdx uint32, log logging.Logger, vppChan govppapi.Channel) (vrfID uint32, err error) { - log.Debugf("Getting VRF for interface %v", ifIdx) +// CreateVrf implements interface handler. +func (h *IfVppHandler) CreateVrf(vrfID uint32) error { + return h.createVrfIfNeeded(vrfID, false) +} - req := &interfaces.SwInterfaceGetTable{ - SwIfIndex: ifIdx, +// CreateVrfIPv6 implements interface handler. +func (h *IfVppHandler) CreateVrfIPv6(vrfID uint32) error { + return h.createVrfIfNeeded(vrfID, true) +} + +// SetInterfaceVrf implements interface handler. +func (h *IfVppHandler) SetInterfaceVrf(ifIdx, vrfID uint32) error { + return h.setInterfaceVrf(ifIdx, vrfID, false) +} + +// SetInterfaceVrfIPv6 implements interface handler. +func (h *IfVppHandler) SetInterfaceVrfIPv6(ifIdx, vrfID uint32) error { + return h.setInterfaceVrf(ifIdx, vrfID, true) +} + +// GetInterfaceVrf implements interface handler. +func (h *IfVppHandler) GetInterfaceVrf(ifIdx uint32) (vrfID uint32, err error) { + return h.getInterfaceVrf(ifIdx, false) +} + +// GetInterfaceVrfIPv6 implements interface handler. +func (h *IfVppHandler) GetInterfaceVrfIPv6(ifIdx uint32) (vrfID uint32, err error) { + return h.getInterfaceVrf(ifIdx, true) +} + +// New VRF with provided ID for IPv4 or IPv6 will be created if missing. +func (h *IfVppHandler) createVrfIfNeeded(vrfID uint32, isIPv6 bool) error { + // Zero VRF exists by default + if vrfID == 0 { + return nil } - /*if table.IsIPv6 { - req.IsIpv6 = 1 - } else { - req.IsIpv6 = 0 - }*/ - // Send message - reply := &interfaces.SwInterfaceGetTableReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { - return 0, err + // Get all VRFs for IPv4 or IPv6 + var exists bool + if isIPv6 { + ipv6Tables, err := h.dumpVrfTablesIPv6() + if err != nil { + return fmt.Errorf("dumping IPv6 VRF tables failed: %v", err) + } + _, exists = ipv6Tables[vrfID] + } else { + tables, err := h.dumpVrfTables() + if err != nil { + return fmt.Errorf("dumping IPv4 VRF tables failed: %v", err) + } + _, exists = tables[vrfID] } - if reply.Retval != 0 { - return 0, fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) + // Create new VRF if needed + if !exists { + h.log.Debugf("VRF table %d does not exists and will be created", vrfID) + return h.vppAddIPTable(vrfID, isIPv6) } - return reply.VrfID, nil + return nil } -// SetInterfaceVRF retrieves VRF table from interface -func SetInterfaceVRF(ifaceIndex, vrfID uint32, log logging.Logger, vppChan govppapi.Channel) error { - if err := CreateVrfIfNeeded(vrfID, vppChan); err != nil { - log.Warnf("creating VRF failed: %v", err) - return err - } +// Interface is set to VRF table. Table IP version has to be defined. +func (h *IfVppHandler) setInterfaceVrf(ifIdx, vrfID uint32, isIPv6 bool) error { + defer func(t time.Time) { + h.stopwatch.TimeLog(interfaces.SwInterfaceSetTable{}).LogTimeEntry(time.Since(t)) + }(time.Now()) - log.Debugf("Setting interface %v to VRF %v", ifaceIndex, vrfID) + if err := h.createVrfIfNeeded(vrfID, isIPv6); err != nil { + return fmt.Errorf("creating VRF failed: %v", err) + } req := &interfaces.SwInterfaceSetTable{ + SwIfIndex: ifIdx, VrfID: vrfID, - SwIfIndex: ifaceIndex, + IsIPv6: boolToUint(isIPv6), } - /*if table.IsIPv6 { - req.IsIpv6 = 1 - } else { - req.IsIpv6 = 0 - }*/ + reply := &interfaces.SwInterfaceSetTableReply{} - // Send message - reply := new(interfaces.SwInterfaceSetTableReply) - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } + h.log.Debugf("Interface %s set to VRF %d", ifIdx, vrfID) + return nil } -// TODO: manage VRF tables globally in separate configurator +// Returns VRF ID for provided interface. +func (h *IfVppHandler) getInterfaceVrf(ifIdx uint32, isIPv6 bool) (vrfID uint32, err error) { + defer func(t time.Time) { + h.stopwatch.TimeLog(interfaces.SwInterfaceGetTable{}).LogTimeEntry(time.Since(t)) + }(time.Now()) -// CreateVrfIfNeeded checks if VRF exists and creates it if not -func CreateVrfIfNeeded(vrfID uint32, vppChan govppapi.Channel) error { - if vrfID == 0 { - return nil + req := &interfaces.SwInterfaceGetTable{ + SwIfIndex: ifIdx, + IsIPv6: boolToUint(isIPv6), } + reply := &interfaces.SwInterfaceGetTableReply{} - tables, err := dumpVrfTables(vppChan) - if err != nil { - logrus.DefaultLogger().Warnf("dumping VRF tables failed: %v", err) - return err - } - if _, ok := tables[vrfID]; !ok { - logrus.DefaultLogger().Warnf("VRF table %v does not exists, creating it", vrfID) - return vppAddIPTable(vrfID, vppChan) + if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { + return 0, err + } else if reply.Retval != 0 { + return 0, fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } - return nil + return reply.VrfID, nil } -func dumpVrfTables(vppChan govppapi.Channel) (map[uint32][]*ip.IPFibDetails, error) { - fibs := map[uint32][]*ip.IPFibDetails{} +// Returns all IPv4 VRF tables +func (h *IfVppHandler) dumpVrfTables() (map[uint32][]*ip.IPFibDetails, error) { + defer func(t time.Time) { + h.stopwatch.TimeLog(ip.IPFibDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) - reqCtx := vppChan.SendMultiRequest(&ip.IPFibDump{}) + fibs := map[uint32][]*ip.IPFibDetails{} + reqCtx := h.callsChannel.SendMultiRequest(&ip.IPFibDump{}) for { fibDetails := &ip.IPFibDetails{} stop, err := reqCtx.ReceiveReply(fibDetails) if stop { - break // break out of the loop + break } if err != nil { return nil, err @@ -122,18 +158,47 @@ func dumpVrfTables(vppChan govppapi.Channel) (map[uint32][]*ip.IPFibDetails, err return fibs, nil } -func vppAddIPTable(tableID uint32, vppChan govppapi.Channel) error { +// Returns all IPv6 VRF tables +func (h *IfVppHandler) dumpVrfTablesIPv6() (map[uint32][]*ip.IP6FibDetails, error) { + defer func(t time.Time) { + h.stopwatch.TimeLog(ip.IP6FibDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + fibs := map[uint32][]*ip.IP6FibDetails{} + reqCtx := h.callsChannel.SendMultiRequest(&ip.IP6FibDump{}) + for { + fibDetails := &ip.IP6FibDetails{} + stop, err := reqCtx.ReceiveReply(fibDetails) + if stop { + break + } + if err != nil { + return nil, err + } + + tableID := fibDetails.TableID + fibs[tableID] = append(fibs[tableID], fibDetails) + } + + return fibs, nil +} + +// Creates new VRF table with provided ID and for desired IP version +func (h *IfVppHandler) vppAddIPTable(vrfID uint32, isIPv6 bool) error { + defer func(t time.Time) { + h.stopwatch.TimeLog(ip.IPTableAddDel{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + req := &ip.IPTableAddDel{ - TableID: tableID, + TableID: vrfID, + IsIPv6: boolToUint(isIPv6), IsAdd: 1, } - - // Send message reply := &ip.IPTableAddDelReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } diff --git a/plugins/vpp/ifplugin/vppcalls/vrf_vppcalls_test.go b/plugins/vpp/ifplugin/vppcalls/vrf_vppcalls_test.go index 88f6dd22ef..d3ef521010 100644 --- a/plugins/vpp/ifplugin/vppcalls/vrf_vppcalls_test.go +++ b/plugins/vpp/ifplugin/vppcalls/vrf_vppcalls_test.go @@ -17,52 +17,62 @@ package vppcalls_test import ( "testing" - "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" "github.com/ligato/vpp-agent/plugins/vpp/binapi/vpe" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" - "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" ) func TestGetInterfaceVRF(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceGetTableReply{ VrfID: 1, }) - vrfID, err := vppcalls.GetInterfaceVRF(1, logrus.DefaultLogger(), ctx.MockChannel) + vrfID, err := ifHandler.GetInterfaceVrf(1) + Expect(err).To(BeNil()) + Expect(vrfID).To(BeEquivalentTo(1)) +} + +func TestGetInterfaceIPv6VRF(t *testing.T) { + ctx, ifHandler := ifTestSetup(t) + defer ctx.TeardownTestCtx() + + ctx.MockVpp.MockReply(&interfaces.SwInterfaceGetTableReply{ + VrfID: 1, + }) + + vrfID, err := ifHandler.GetInterfaceVrfIPv6(1) Expect(err).To(BeNil()) Expect(vrfID).To(BeEquivalentTo(1)) } func TestGetInterfaceVRFError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceGetTable{}) - _, err := vppcalls.GetInterfaceVRF(1, logrus.DefaultLogger(), ctx.MockChannel) + _, err := ifHandler.GetInterfaceVrf(1) Expect(err).ToNot(BeNil()) } func TestGetInterfaceVRFRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&interfaces.SwInterfaceGetTableReply{ Retval: 1, }) - _, err := vppcalls.GetInterfaceVRF(1, logrus.DefaultLogger(), ctx.MockChannel) + _, err := ifHandler.GetInterfaceVrf(1) Expect(err).ToNot(BeNil()) } func TestSetInterfaceVRF(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&ip.IPFibDetails{}) @@ -70,7 +80,7 @@ func TestSetInterfaceVRF(t *testing.T) { ctx.MockVpp.MockReply(&ip.IPTableAddDelReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetTableReply{}) - err := vppcalls.SetInterfaceVRF(1, 2, logrus.DefaultLogger(), ctx.MockChannel) + err := ifHandler.SetInterfaceVrf(1, 2) Expect(err).To(BeNil()) vppMsg, ok := ctx.MockChannel.Msg.(*interfaces.SwInterfaceSetTable) Expect(ok).To(BeTrue()) @@ -78,8 +88,26 @@ func TestSetInterfaceVRF(t *testing.T) { Expect(vppMsg.VrfID).To(BeEquivalentTo(2)) } +func TestSetInterfaceIPv6VRF(t *testing.T) { + ctx, ifHandler := ifTestSetup(t) + defer ctx.TeardownTestCtx() + + ctx.MockVpp.MockReply(&ip.IP6FibDetails{}) + ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) + ctx.MockVpp.MockReply(&ip.IPTableAddDelReply{}) + ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetTableReply{}) + + err := ifHandler.SetInterfaceVrfIPv6(1, 2) + Expect(err).To(BeNil()) + vppMsg, ok := ctx.MockChannel.Msg.(*interfaces.SwInterfaceSetTable) + Expect(ok).To(BeTrue()) + Expect(vppMsg.SwIfIndex).To(BeEquivalentTo(1)) + Expect(vppMsg.VrfID).To(BeEquivalentTo(2)) + Expect(vppMsg.IsIPv6).To(BeEquivalentTo(1)) +} + func TestSetInterfaceVRFError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&ip.IPFibDetails{}) @@ -87,12 +115,12 @@ func TestSetInterfaceVRFError(t *testing.T) { ctx.MockVpp.MockReply(&ip.IPTableAddDelReply{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceSetTable{}) - err := vppcalls.SetInterfaceVRF(1, 2, logrus.DefaultLogger(), ctx.MockChannel) + err := ifHandler.SetInterfaceVrf(1, 2) Expect(err).To(HaveOccurred()) } func TestSetInterfaceVRFRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&ip.IPFibDetails{}) @@ -102,12 +130,12 @@ func TestSetInterfaceVRFRetval(t *testing.T) { Retval: 1, }) - err := vppcalls.SetInterfaceVRF(1, 2, logrus.DefaultLogger(), ctx.MockChannel) + err := ifHandler.SetInterfaceVrf(1, 2) Expect(err).ToNot(BeNil()) } func TestCreateVrfIfNeeded(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() // IP FIB dump @@ -116,14 +144,39 @@ func TestCreateVrfIfNeeded(t *testing.T) { // Add/del table ctx.MockVpp.MockReply(&ip.IPTableAddDelReply{}) - err := vppcalls.CreateVrfIfNeeded(1, ctx.MockChannel) + err := ifHandler.CreateVrf(1) + Expect(err).To(BeNil()) + var msgCheck bool + for _, msg := range ctx.MockChannel.Msgs { + vppMsg, ok := msg.(*ip.IPTableAddDel) + if ok { + Expect(vppMsg.TableID).To(BeEquivalentTo(1)) + Expect(vppMsg.IsIPv6).To(BeEquivalentTo(0)) + Expect(vppMsg.IsAdd).To(BeEquivalentTo(1)) + msgCheck = true + } + } + Expect(msgCheck).To(BeTrue()) +} + +func TestCreateIPv6VrfIfNeeded(t *testing.T) { + ctx, ifHandler := ifTestSetup(t) + defer ctx.TeardownTestCtx() + + // IP FIB dump + ctx.MockVpp.MockReply(&ip.IP6FibDetails{}) + ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) + // Add/del table + ctx.MockVpp.MockReply(&ip.IPTableAddDelReply{}) + + err := ifHandler.CreateVrfIPv6(1) Expect(err).To(BeNil()) var msgCheck bool for _, msg := range ctx.MockChannel.Msgs { vppMsg, ok := msg.(*ip.IPTableAddDel) if ok { Expect(vppMsg.TableID).To(BeEquivalentTo(1)) - Expect(vppMsg.IsIpv6).To(BeEquivalentTo(0)) + Expect(vppMsg.IsIPv6).To(BeEquivalentTo(1)) Expect(vppMsg.IsAdd).To(BeEquivalentTo(1)) msgCheck = true } @@ -132,7 +185,7 @@ func TestCreateVrfIfNeeded(t *testing.T) { } func TestCreateVrfIfNeededNull(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() // IP FIB dump @@ -141,12 +194,12 @@ func TestCreateVrfIfNeededNull(t *testing.T) { // Add/del table ctx.MockVpp.MockReply(&ip.IPTableAddDelReply{}) - err := vppcalls.CreateVrfIfNeeded(0, ctx.MockChannel) + err := ifHandler.CreateVrf(0) Expect(err).To(BeNil()) } func TestCreateVrfIfNeededError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() // IP FIB dump @@ -155,12 +208,12 @@ func TestCreateVrfIfNeededError(t *testing.T) { // Add/del table ctx.MockVpp.MockReply(&ip.IPTableAddDel{}) - err := vppcalls.CreateVrfIfNeeded(1, ctx.MockChannel) + err := ifHandler.CreateVrf(1) Expect(err).ToNot(BeNil()) } func TestCreateVrfIfNeededRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() // IP FIB dump @@ -171,6 +224,6 @@ func TestCreateVrfIfNeededRetval(t *testing.T) { Retval: 1, }) - err := vppcalls.CreateVrfIfNeeded(1, ctx.MockChannel) + err := ifHandler.CreateVrf(1) Expect(err).ToNot(BeNil()) } diff --git a/plugins/vpp/ifplugin/vppcalls/vxlan_vppcalls.go b/plugins/vpp/ifplugin/vppcalls/vxlan_vppcalls.go index 3a75c3d924..6fe674a826 100644 --- a/plugins/vpp/ifplugin/vppcalls/vxlan_vppcalls.go +++ b/plugins/vpp/ifplugin/vppcalls/vxlan_vppcalls.go @@ -19,38 +19,35 @@ import ( "net" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/vpp-agent/plugins/vpp/binapi/vxlan" intf "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" ) -func addDelVxlanTunnel(iface *intf.Interfaces_Interface_Vxlan, encVrf, multicastIf uint32, isAdd bool, vppChan govppapi.Channel, - stopwatch *measure.Stopwatch) (swIdx uint32, err error) { +func (h *IfVppHandler) addDelVxLanTunnel(vxLan *intf.Interfaces_Interface_Vxlan, vrf, multicastIf uint32, isAdd bool) (swIdx uint32, err error) { defer func(t time.Time) { - stopwatch.TimeLog(vxlan.VxlanAddDelTunnel{}).LogTimeEntry(time.Since(t)) + h.stopwatch.TimeLog(vxlan.VxlanAddDelTunnel{}).LogTimeEntry(time.Since(t)) }(time.Now()) - // this is temporary fix to solve creation of VRF table for VXLAN - if err := CreateVrfIfNeeded(encVrf, vppChan); err != nil { + // this is temporary fix to solve creation of VRF table for VxLAN + if err := h.CreateVrf(vrf); err != nil { return 0, err } req := &vxlan.VxlanAddDelTunnel{ IsAdd: boolToUint(isAdd), - Vni: iface.Vni, + Vni: vxLan.Vni, DecapNextIndex: 0xFFFFFFFF, Instance: ^uint32(0), - EncapVrfID: encVrf, + EncapVrfID: vrf, McastSwIfIndex: multicastIf, } - srcAddr := net.ParseIP(iface.SrcAddress).To4() - dstAddr := net.ParseIP(iface.DstAddress).To4() + srcAddr := net.ParseIP(vxLan.SrcAddress).To4() + dstAddr := net.ParseIP(vxLan.DstAddress).To4() if srcAddr == nil && dstAddr == nil { - srcAddr = net.ParseIP(iface.SrcAddress).To16() - dstAddr = net.ParseIP(iface.DstAddress).To16() - req.IsIpv6 = 1 + srcAddr = net.ParseIP(vxLan.SrcAddress).To16() + dstAddr = net.ParseIP(vxLan.DstAddress).To16() + req.IsIPv6 = 1 if srcAddr == nil || dstAddr == nil { return 0, fmt.Errorf("invalid VXLAN address, src: %s, dst: %s", srcAddr, dstAddr) } @@ -62,29 +59,29 @@ func addDelVxlanTunnel(iface *intf.Interfaces_Interface_Vxlan, encVrf, multicast req.DstAddress = []byte(dstAddr) reply := &vxlan.VxlanAddDelTunnelReply{} - if err = vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + if err = h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return 0, err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return 0, fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return reply.SwIfIndex, nil } -// AddVxlanTunnel calls AddDelVxlanTunnelReq with flag add=1. -func AddVxlanTunnel(ifName string, vxlanIntf *intf.Interfaces_Interface_Vxlan, encapVrf, multicastIf uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (swIndex uint32, err error) { - swIfIdx, err := addDelVxlanTunnel(vxlanIntf, encapVrf, multicastIf, true, vppChan, stopwatch) +// AddVxLanTunnel implements VxLan handler. +func (h *IfVppHandler) AddVxLanTunnel(ifName string, vrf, multicastIf uint32, vxLan *intf.Interfaces_Interface_Vxlan) (swIndex uint32, err error) { + swIfIdx, err := h.addDelVxLanTunnel(vxLan, vrf, multicastIf, true) if err != nil { return 0, err } - return swIfIdx, SetInterfaceTag(ifName, swIfIdx, vppChan, stopwatch) + return swIfIdx, h.SetInterfaceTag(ifName, swIfIdx) } -// DeleteVxlanTunnel calls AddDelVxlanTunnelReq with flag add=0. -func DeleteVxlanTunnel(ifName string, idx uint32, vxlanIntf *intf.Interfaces_Interface_Vxlan, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - if _, err := addDelVxlanTunnel(vxlanIntf, 0, 0, false, vppChan, stopwatch); err != nil { +// DeleteVxLanTunnel implements VxLan handler. +func (h *IfVppHandler) DeleteVxLanTunnel(ifName string, idx, vrf uint32, vxLan *intf.Interfaces_Interface_Vxlan) error { + // Multicast does not need to be set + if _, err := h.addDelVxLanTunnel(vxLan, vrf, 0, false); err != nil { return err } - return RemoveInterfaceTag(ifName, idx, vppChan, stopwatch) + return h.RemoveInterfaceTag(ifName, idx) } diff --git a/plugins/vpp/ifplugin/vppcalls/vxlan_vppcalls_test.go b/plugins/vpp/ifplugin/vppcalls/vxlan_vppcalls_test.go index becccdcea6..e61746b8f0 100644 --- a/plugins/vpp/ifplugin/vppcalls/vxlan_vppcalls_test.go +++ b/plugins/vpp/ifplugin/vppcalls/vxlan_vppcalls_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package vppcalls +package vppcalls_test import ( "net" @@ -23,12 +23,11 @@ import ( "github.com/ligato/vpp-agent/plugins/vpp/binapi/vpe" "github.com/ligato/vpp-agent/plugins/vpp/binapi/vxlan" ifModel "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" - "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" ) func TestAddVxlanTunnel(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&vxlan.VxlanAddDelTunnelReply{ @@ -36,11 +35,11 @@ func TestAddVxlanTunnel(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - swIfIdx, err := AddVxlanTunnel("ifName", &ifModel.Interfaces_Interface_Vxlan{ + swIfIdx, err := ifHandler.AddVxLanTunnel("ifName", 0, 2, &ifModel.Interfaces_Interface_Vxlan{ SrcAddress: "10.0.0.1", DstAddress: "20.0.0.1", Vni: 1, - }, 0, 2, ctx.MockChannel, nil) + }) Expect(err).To(BeNil()) Expect(swIfIdx).To(BeEquivalentTo(1)) var msgCheck bool @@ -53,7 +52,7 @@ func TestAddVxlanTunnel(t *testing.T) { Expect(vppMsg.EncapVrfID).To(BeEquivalentTo(0)) Expect(vppMsg.McastSwIfIndex).To(BeEquivalentTo(2)) Expect(vppMsg.Vni).To(BeEquivalentTo(1)) - Expect(vppMsg.IsIpv6).To(BeEquivalentTo(0)) + Expect(vppMsg.IsIPv6).To(BeEquivalentTo(0)) msgCheck = true } } @@ -61,7 +60,7 @@ func TestAddVxlanTunnel(t *testing.T) { } func TestAddVxlanTunnelWithVrf(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() // VRF resolution @@ -74,11 +73,11 @@ func TestAddVxlanTunnelWithVrf(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - swIfIdx, err := AddVxlanTunnel("ifName", &ifModel.Interfaces_Interface_Vxlan{ + swIfIdx, err := ifHandler.AddVxLanTunnel("ifName", 1, 1, &ifModel.Interfaces_Interface_Vxlan{ SrcAddress: "10.0.0.1", DstAddress: "20.0.0.1", Vni: 1, - }, 1, 1, ctx.MockChannel, nil) + }) Expect(err).To(BeNil()) Expect(swIfIdx).To(BeEquivalentTo(1)) var msgCheck bool @@ -91,7 +90,7 @@ func TestAddVxlanTunnelWithVrf(t *testing.T) { Expect(vppMsg.EncapVrfID).To(BeEquivalentTo(1)) Expect(vppMsg.McastSwIfIndex).To(BeEquivalentTo(1)) Expect(vppMsg.Vni).To(BeEquivalentTo(1)) - Expect(vppMsg.IsIpv6).To(BeEquivalentTo(0)) + Expect(vppMsg.IsIPv6).To(BeEquivalentTo(0)) msgCheck = true } } @@ -99,7 +98,7 @@ func TestAddVxlanTunnelWithVrf(t *testing.T) { } func TestAddVxlanTunnelIPv6(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&vxlan.VxlanAddDelTunnelReply{ @@ -107,11 +106,11 @@ func TestAddVxlanTunnelIPv6(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - swIfIdx, err := AddVxlanTunnel("ifName", &ifModel.Interfaces_Interface_Vxlan{ + swIfIdx, err := ifHandler.AddVxLanTunnel("ifName", 0, 0, &ifModel.Interfaces_Interface_Vxlan{ SrcAddress: "2001:db8:0:1:1:1:1:1", DstAddress: "2002:db8:0:1:1:1:1:1", Vni: 1, - }, 0, 0, ctx.MockChannel, nil) + }) Expect(err).To(BeNil()) Expect(swIfIdx).To(BeEquivalentTo(1)) var msgCheck bool @@ -120,7 +119,7 @@ func TestAddVxlanTunnelIPv6(t *testing.T) { if ok { Expect(vppMsg.SrcAddress).To(BeEquivalentTo(net.ParseIP("2001:db8:0:1:1:1:1:1").To16())) Expect(vppMsg.DstAddress).To(BeEquivalentTo(net.ParseIP("2002:db8:0:1:1:1:1:1").To16())) - Expect(vppMsg.IsIpv6).To(BeEquivalentTo(1)) + Expect(vppMsg.IsIPv6).To(BeEquivalentTo(1)) msgCheck = true } } @@ -128,7 +127,7 @@ func TestAddVxlanTunnelIPv6(t *testing.T) { } func TestAddVxlanTunnelIPMismatch(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&vxlan.VxlanAddDelTunnelReply{ @@ -136,16 +135,16 @@ func TestAddVxlanTunnelIPMismatch(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - _, err := AddVxlanTunnel("ifName", &ifModel.Interfaces_Interface_Vxlan{ + _, err := ifHandler.AddVxLanTunnel("ifName", 0, 0, &ifModel.Interfaces_Interface_Vxlan{ SrcAddress: "10.0.0.1", DstAddress: "2001:db8:0:1:1:1:1:1", Vni: 1, - }, 0, 0, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } func TestAddVxlanTunnelInvalidIP(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&vxlan.VxlanAddDelTunnelReply{ @@ -153,31 +152,31 @@ func TestAddVxlanTunnelInvalidIP(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - _, err := AddVxlanTunnel("ifName", &ifModel.Interfaces_Interface_Vxlan{ + _, err := ifHandler.AddVxLanTunnel("ifName", 0, 0, &ifModel.Interfaces_Interface_Vxlan{ SrcAddress: "invalid-ip", DstAddress: "2001:db8:0:1:1:1:1:1", Vni: 1, - }, 0, 0, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } func TestAddVxlanTunnelError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&vxlan.VxlanAddDelTunnel{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - _, err := AddVxlanTunnel("ifName", &ifModel.Interfaces_Interface_Vxlan{ + _, err := ifHandler.AddVxLanTunnel("ifName", 0, 0, &ifModel.Interfaces_Interface_Vxlan{ SrcAddress: "10.0.0.1", DstAddress: "20.0.0.2", Vni: 1, - }, 0, 0, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } func TestAddVxlanTunnelWithVrfError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() // VRF resolution @@ -190,16 +189,16 @@ func TestAddVxlanTunnelWithVrfError(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - _, err := AddVxlanTunnel("ifName", &ifModel.Interfaces_Interface_Vxlan{ + _, err := ifHandler.AddVxLanTunnel("ifName", 1, 0, &ifModel.Interfaces_Interface_Vxlan{ SrcAddress: "10.0.0.1", DstAddress: "20.0.0.1", Vni: 1, - }, 1, 0, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } func TestAddVxlanTunnelRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&vxlan.VxlanAddDelTunnelReply{ @@ -207,16 +206,16 @@ func TestAddVxlanTunnelRetval(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - _, err := AddVxlanTunnel("ifName", &ifModel.Interfaces_Interface_Vxlan{ + _, err := ifHandler.AddVxLanTunnel("ifName", 0, 0, &ifModel.Interfaces_Interface_Vxlan{ SrcAddress: "10.0.0.1", DstAddress: "20.0.0.2", Vni: 1, - }, 0, 0, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } func TestDeleteVxlanTunnel(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&vxlan.VxlanAddDelTunnelReply{ @@ -224,31 +223,31 @@ func TestDeleteVxlanTunnel(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - err := DeleteVxlanTunnel("ifName", 1, &ifModel.Interfaces_Interface_Vxlan{ + err := ifHandler.DeleteVxLanTunnel("ifName", 1, 0, &ifModel.Interfaces_Interface_Vxlan{ SrcAddress: "10.0.0.1", DstAddress: "20.0.0.1", Vni: 1, - }, ctx.MockChannel, nil) + }) Expect(err).To(BeNil()) } func TestDeleteVxlanTunnelError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&vxlan.VxlanAddDelTunnel{}) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - err := DeleteVxlanTunnel("ifName", 1, &ifModel.Interfaces_Interface_Vxlan{ + err := ifHandler.DeleteVxLanTunnel("ifName", 1, 0, &ifModel.Interfaces_Interface_Vxlan{ SrcAddress: "10.0.0.1", DstAddress: "20.0.0.1", Vni: 1, - }, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } func TestDeleteVxlanTunnelRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler := ifTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&vxlan.VxlanAddDelTunnelReply{ @@ -256,10 +255,10 @@ func TestDeleteVxlanTunnelRetval(t *testing.T) { }) ctx.MockVpp.MockReply(&interfaces.SwInterfaceTagAddDelReply{}) - err := DeleteVxlanTunnel("ifName", 1, &ifModel.Interfaces_Interface_Vxlan{ + err := ifHandler.DeleteVxLanTunnel("ifName", 1, 0, &ifModel.Interfaces_Interface_Vxlan{ SrcAddress: "10.0.0.1", DstAddress: "20.0.0.1", Vni: 1, - }, ctx.MockChannel, nil) + }) Expect(err).ToNot(BeNil()) } diff --git a/plugins/vpp/ifplugin/vppdump/doc.go b/plugins/vpp/ifplugin/vppdump/doc.go deleted file mode 100644 index 7d6d25c5c6..0000000000 --- a/plugins/vpp/ifplugin/vppdump/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package vppdump provides helpers for dumping all interfaces configured in VPP. -package vppdump diff --git a/plugins/vpp/ifplugin/vppdump/dump_stn_vppcalls.go b/plugins/vpp/ifplugin/vppdump/dump_stn_vppcalls.go deleted file mode 100644 index 7a9a2e8ae4..0000000000 --- a/plugins/vpp/ifplugin/vppdump/dump_stn_vppcalls.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2018 Cisco and/or its affiliates. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at: -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package vppdump - -import ( - "time" - - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/stn" -) - -// DumpStnRules returns a list of all STN rules configured on the VPP -func DumpStnRules(vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (rules []*stn.StnRulesDetails, err error) { - defer func(t time.Time) { - stopwatch.TimeLog(stn.StnRulesDump{}).LogTimeEntry(time.Since(t)) - }(time.Now()) - - req := &stn.StnRulesDump{} - reqCtx := vppChan.SendMultiRequest(req) - for { - msg := &stn.StnRulesDetails{} - stop, err := reqCtx.ReceiveReply(msg) - if stop { - break - } - if err != nil { - return nil, err - } - rules = append(rules, msg) - } - - return rules, nil -} diff --git a/plugins/vpp/ifplugin/vppdump/dump_vppcalls.go b/plugins/vpp/ifplugin/vppdump/dump_vppcalls.go deleted file mode 100644 index 541d559706..0000000000 --- a/plugins/vpp/ifplugin/vppdump/dump_vppcalls.go +++ /dev/null @@ -1,448 +0,0 @@ -// Copyright (c) 2017 Cisco and/or its affiliates. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at: -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package vppdump - -import ( - "bytes" - "fmt" - "net" - "strings" - "time" - - "git.fd.io/govpp.git/api" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/measure" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/memif" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/tap" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/tapv2" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/vxlan" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" - ifnb "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" -) - -// Default VPP MTU value -const defaultVPPMtu = 9216 - -// Interface is the wrapper structure for the interface northbound API structure. -type Interface struct { - VPPInternalName string `json:"vpp_internal_name"` - ifnb.Interfaces_Interface -} - -// DumpInterfaces dumps VPP interface data into the northbound API data structure -// map indexed by software interface index. -// -// LIMITATIONS: -// - there is no af_packet dump binary API. We relay on naming conventions of the internal VPP interface names -// - ip.IPAddressDetails has wrong internal structure, as a workaround we need to handle them as notifications -// -func DumpInterfaces(log logging.Logger, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (map[uint32]*Interface, error) { - start := time.Now() - // map for the resulting interfaces - ifs := make(map[uint32]*Interface) - - // First, dump all interfaces to create initial data. - reqCtx := vppChan.SendMultiRequest(&interfaces.SwInterfaceDump{}) - - for { - ifDetails := &interfaces.SwInterfaceDetails{} - stop, err := reqCtx.ReceiveReply(ifDetails) - if stop { - break // Break from the loop. - } - if err != nil { - log.Error(err) - return nil, err - } - - iface := &Interface{ - VPPInternalName: string(bytes.SplitN(ifDetails.InterfaceName, []byte{0x00}, 2)[0]), - Interfaces_Interface: ifnb.Interfaces_Interface{ - Name: string(bytes.SplitN(ifDetails.Tag, []byte{0x00}, 2)[0]), - Type: guessInterfaceType(string(ifDetails.InterfaceName)), // the type may be amended later by further dumps - Enabled: ifDetails.AdminUpDown > 0, - PhysAddress: net.HardwareAddr(ifDetails.L2Address[:ifDetails.L2AddressLength]).String(), - Mtu: func(vppMtu uint16) uint32 { - // If default VPP MTU value is set, return 0 (it means MTU was not set in the NB config) - if vppMtu == defaultVPPMtu { - return 0 - } - return uint32(vppMtu) - }(ifDetails.LinkMtu), - }, - } - // Fill name for physical interfaces (they are mostly without tag) - if iface.Type == ifnb.InterfaceType_ETHERNET_CSMACD { - iface.Name = iface.VPPInternalName - } - ifs[ifDetails.SwIfIndex] = iface - - if iface.Type == ifnb.InterfaceType_AF_PACKET_INTERFACE { - fillAFPacketDetails(ifs, ifDetails.SwIfIndex, iface.VPPInternalName) - } - } - - log.Debugf("dumped %d interfaces", len(ifs)) - - // SwInterfaceDump time - timeLog := measure.GetTimeLog(interfaces.SwInterfaceDump{}, stopwatch) - if timeLog != nil { - timeLog.LogTimeEntry(time.Since(start)) - } - - for idx := range ifs { - vrfID, err := vppcalls.GetInterfaceVRF(idx, log, vppChan) - if err != nil { - return nil, err - } - ifs[idx].Vrf = vrfID - } - - timeLog = measure.GetTimeLog(ip.IPAddressDump{}, stopwatch) - err := dumpIPAddressDetails(log, vppChan, ifs, 0, timeLog) - if err != nil { - return nil, err - } - err = dumpIPAddressDetails(log, vppChan, ifs, 1, timeLog) - if err != nil { - return nil, err - } - - err = dumpMemifDetails(log, vppChan, ifs, measure.GetTimeLog(memif.MemifDump{}, stopwatch)) - if err != nil { - return nil, err - } - - err = dumpTapDetails(log, vppChan, ifs, measure.GetTimeLog(tap.SwInterfaceTapDump{}, stopwatch)) - if err != nil { - return nil, err - } - - err = dumpVxlanDetails(log, vppChan, ifs, measure.GetTimeLog(vxlan.VxlanTunnelDump{}, stopwatch)) - if err != nil { - return nil, err - } - - return ifs, nil -} - -// DumpMemifSocketDetails dumps memif socket details from the VPP -func DumpMemifSocketDetails(log logging.Logger, vppChan govppapi.Channel, timeLog measure.StopWatchEntry) (map[string]uint32, error) { - // MemifSocketFilenameDump time measurement - start := time.Now() - defer func() { - if timeLog != nil { - timeLog.LogTimeEntry(time.Since(start)) - } - }() - - memifSocketMap := make(map[string]uint32) - - reqCtx := vppChan.SendMultiRequest(&memif.MemifSocketFilenameDump{}) - for { - socketDetails := &memif.MemifSocketFilenameDetails{} - stop, err := reqCtx.ReceiveReply(socketDetails) - if stop { - break // Break from the loop. - } - if err != nil { - log.Error(err) - return memifSocketMap, err - } - - filename := string(bytes.SplitN(socketDetails.SocketFilename, []byte{0x00}, 2)[0]) - memifSocketMap[filename] = socketDetails.SocketID - } - - log.Debugf("Memif socket dump completed, found %d entries", len(memifSocketMap)) - - return memifSocketMap, nil -} - -// dumpIPAddressDetails dumps IP address details of interfaces from VPP and fills them into the provided interface map. -func dumpIPAddressDetails(log logging.Logger, vppChan govppapi.Channel, ifs map[uint32]*Interface, isIPv6 uint8, timeLog measure.StopWatchEntry) error { - // TODO: workaround for incorrect ip.IPAddressDetails message - notifChan := make(chan api.Message, 100) - subs, _ := vppChan.SubscribeNotification(notifChan, ip.NewIPAddressDetails) - - // Dump IP addresses of each interface. - for idx := range ifs { - // IPAddressDetails time measurement - start := time.Now() - - reqCtx := vppChan.SendMultiRequest(&ip.IPAddressDump{SwIfIndex: idx, IsIpv6: isIPv6}) - for { - ipDetails := &ip.IPAddressDetails{} - stop, err := reqCtx.ReceiveReply(ipDetails) - if stop { - break // Break from the loop. - } - if err != nil { - log.Error(err) - return err - } - processIPDetails(ifs, ipDetails) - } - - // TODO: workaround for incorrect ip.IPAddressDetails message - for len(notifChan) > 0 { - notifMsg := <-notifChan - processIPDetails(ifs, notifMsg.(*ip.IPAddressDetails)) - } - - // IPAddressDump time - if timeLog != nil { - timeLog.LogTimeEntry(time.Since(start)) - } - } - - // TODO: workaround for incorrect ip.IPAddressDetails message - vppChan.UnsubscribeNotification(subs) - - return nil -} - -// processIPDetails processes ip.IPAddressDetails binary API message and fills the details into the provided interface map. -func processIPDetails(ifs map[uint32]*Interface, ipDetails *ip.IPAddressDetails) { - _, ifIdxExists := ifs[ipDetails.SwIfIndex] - if !ifIdxExists { - return - } - if ifs[ipDetails.SwIfIndex].IpAddresses == nil { - ifs[ipDetails.SwIfIndex].IpAddresses = make([]string, 0) - } - var ipAddr string - if ipDetails.IsIpv6 == 1 { - ipAddr = fmt.Sprintf("%s/%d", net.IP(ipDetails.IP).To16().String(), uint32(ipDetails.PrefixLength)) - } else { - ipAddr = fmt.Sprintf("%s/%d", net.IP(ipDetails.IP[:4]).To4().String(), uint32(ipDetails.PrefixLength)) - } - ifs[ipDetails.SwIfIndex].IpAddresses = append(ifs[ipDetails.SwIfIndex].IpAddresses, ipAddr) -} - -// fillAFPacketDetails fills af_packet interface details into the provided interface map. -func fillAFPacketDetails(ifs map[uint32]*Interface, swIfIndex uint32, ifName string) { - ifs[swIfIndex].Afpacket = &ifnb.Interfaces_Interface_Afpacket{ - HostIfName: strings.TrimPrefix(ifName, "host-"), - } - ifs[swIfIndex].Type = ifnb.InterfaceType_AF_PACKET_INTERFACE -} - -// dumpMemifDetails dumps memif interface details from VPP and fills them into the provided interface map. -func dumpMemifDetails(log logging.Logger, vppChan govppapi.Channel, ifs map[uint32]*Interface, timeLog measure.StopWatchEntry) error { - // MemifDetails time measurement - start := time.Now() - defer func() { - if timeLog != nil { - timeLog.LogTimeEntry(time.Since(start)) - } - }() - - // Dump all memif sockets - memifSocketMap, err := DumpMemifSocketDetails(log, vppChan, timeLog) - if err != nil { - return err - } - - reqCtx := vppChan.SendMultiRequest(&memif.MemifDump{}) - for { - memifDetails := &memif.MemifDetails{} - stop, err := reqCtx.ReceiveReply(memifDetails) - if stop { - break // Break from the loop. - } - if err != nil { - log.Error(err) - return err - } - _, ifIdxExists := ifs[memifDetails.SwIfIndex] - if !ifIdxExists { - continue - } - ifs[memifDetails.SwIfIndex].Memif = &ifnb.Interfaces_Interface_Memif{ - Master: memifDetails.Role == 0, - Mode: memifModetoNB(memifDetails.Mode), - Id: memifDetails.ID, - // TODO: Secret - not available in the binary API - SocketFilename: func(socketMap map[string]uint32) (filename string) { - for filename, id := range socketMap { - if memifDetails.SocketID == id { - return filename - } - } - // Socket for configured memif should exist - log.Warnf("Socket ID not found for memif %v", memifDetails.SwIfIndex) - return - }(memifSocketMap), - RingSize: memifDetails.RingSize, - BufferSize: uint32(memifDetails.BufferSize), - // TODO: RxQueues, TxQueues - not available in the binary API - } - ifs[memifDetails.SwIfIndex].Type = ifnb.InterfaceType_MEMORY_INTERFACE - } - - return nil -} - -// dumpTapDetails dumps tap interface details from VPP and fills them into the provided interface map. -func dumpTapDetails(log logging.Logger, vppChan govppapi.Channel, ifs map[uint32]*Interface, timeLog measure.StopWatchEntry) error { - // SwInterfaceTapDump time measurement - start := time.Now() - defer func() { - if timeLog != nil { - timeLog.LogTimeEntry(time.Since(start)) - } - }() - - // Original TAP. - reqCtx := vppChan.SendMultiRequest(&tap.SwInterfaceTapDump{}) - for { - tapDetails := &tap.SwInterfaceTapDetails{} - stop, err := reqCtx.ReceiveReply(tapDetails) - if stop { - break // Break from the loop. - } - if err != nil { - log.Error(err) - return err - } - _, ifIdxExists := ifs[tapDetails.SwIfIndex] - if !ifIdxExists { - continue - } - ifs[tapDetails.SwIfIndex].Tap = &ifnb.Interfaces_Interface_Tap{ - Version: 1, - HostIfName: string(bytes.SplitN(tapDetails.DevName, []byte{0x00}, 2)[0]), - } - ifs[tapDetails.SwIfIndex].Type = ifnb.InterfaceType_TAP_INTERFACE - } - - // TAP v.2 - reqCtx = vppChan.SendMultiRequest(&tapv2.SwInterfaceTapV2Dump{}) - for { - tapDetails := &tapv2.SwInterfaceTapV2Details{} - stop, err := reqCtx.ReceiveReply(tapDetails) - if stop { - break // Break from the loop. - } - if err != nil { - log.Error(err) - return err - } - _, ifIdxExists := ifs[tapDetails.SwIfIndex] - if !ifIdxExists { - continue - } - ifs[tapDetails.SwIfIndex].Tap = &ifnb.Interfaces_Interface_Tap{ - Version: 2, - HostIfName: string(bytes.SplitN(tapDetails.HostIfName, []byte{0x00}, 2)[0]), - // Other parameters are not not yet part of the dump. - - } - ifs[tapDetails.SwIfIndex].Type = ifnb.InterfaceType_TAP_INTERFACE - } - - return nil -} - -// dumpVxlanDetails dumps VXLAN interface details from VPP and fills them into the provided interface map. -func dumpVxlanDetails(log logging.Logger, vppChan govppapi.Channel, ifs map[uint32]*Interface, timeLog measure.StopWatchEntry) error { - // VxlanTunnelDump time measurement - start := time.Now() - defer func() { - if timeLog != nil { - timeLog.LogTimeEntry(time.Since(start)) - } - }() - - reqCtx := vppChan.SendMultiRequest(&vxlan.VxlanTunnelDump{SwIfIndex: ^uint32(0)}) - for { - vxlanDetails := &vxlan.VxlanTunnelDetails{} - stop, err := reqCtx.ReceiveReply(vxlanDetails) - if stop { - break // Break from the loop. - } - if err != nil { - log.Error(err) - return err - } - _, ifIdxExists := ifs[vxlanDetails.SwIfIndex] - if !ifIdxExists { - continue - } - // Multicast interface - var multicastIfName string - _, exists := ifs[vxlanDetails.McastSwIfIndex] - if exists { - multicastIfName = ifs[vxlanDetails.McastSwIfIndex].Name - } - - if vxlanDetails.IsIpv6 == 1 { - ifs[vxlanDetails.SwIfIndex].Vxlan = &ifnb.Interfaces_Interface_Vxlan{ - Multicast: multicastIfName, - SrcAddress: net.IP(vxlanDetails.SrcAddress).To16().String(), - DstAddress: net.IP(vxlanDetails.DstAddress).To16().String(), - Vni: vxlanDetails.Vni, - } - } else { - ifs[vxlanDetails.SwIfIndex].Vxlan = &ifnb.Interfaces_Interface_Vxlan{ - Multicast: multicastIfName, - SrcAddress: net.IP(vxlanDetails.SrcAddress[:4]).To4().String(), - DstAddress: net.IP(vxlanDetails.DstAddress[:4]).To4().String(), - Vni: vxlanDetails.Vni, - } - } - ifs[vxlanDetails.SwIfIndex].Type = ifnb.InterfaceType_VXLAN_TUNNEL - } - - return nil -} - -// guessInterfaceType attempts to guess the correct interface type from its internal name (as given by VPP). -// This is required mainly for those interface types, that do not provide dump binary API, -// such as loopback of af_packet. -func guessInterfaceType(ifName string) ifnb.InterfaceType { - switch { - case strings.HasPrefix(ifName, "loop"): - return ifnb.InterfaceType_SOFTWARE_LOOPBACK - case strings.HasPrefix(ifName, "local"): - return ifnb.InterfaceType_SOFTWARE_LOOPBACK - case strings.HasPrefix(ifName, "memif"): - return ifnb.InterfaceType_MEMORY_INTERFACE - case strings.HasPrefix(ifName, "tap"): - return ifnb.InterfaceType_TAP_INTERFACE - case strings.HasPrefix(ifName, "host"): - return ifnb.InterfaceType_AF_PACKET_INTERFACE - case strings.HasPrefix(ifName, "vxlan"): - return ifnb.InterfaceType_VXLAN_TUNNEL - } - return ifnb.InterfaceType_ETHERNET_CSMACD -} - -// memifModetoNB converts binary API type of memif mode to the northbound API type memif mode. -func memifModetoNB(mode uint8) ifnb.Interfaces_Interface_Memif_MemifMode { - switch mode { - case 0: - return ifnb.Interfaces_Interface_Memif_ETHERNET - case 1: - return ifnb.Interfaces_Interface_Memif_IP - case 2: - return ifnb.Interfaces_Interface_Memif_PUNT_INJECT - } - return ifnb.Interfaces_Interface_Memif_ETHERNET -} diff --git a/plugins/vpp/ifplugin/vppdump/dump_vppcalls_test.go b/plugins/vpp/ifplugin/vppdump/dump_vppcalls_test.go deleted file mode 100644 index 13075d7d3b..0000000000 --- a/plugins/vpp/ifplugin/vppdump/dump_vppcalls_test.go +++ /dev/null @@ -1,654 +0,0 @@ -// Copyright (c) 2018 Cisco and/or its affiliates. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at: -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package vppdump - -import ( - "testing" - - "net" - - "git.fd.io/govpp.git/adapter/mock" - govppapi "git.fd.io/govpp.git/api" - "git.fd.io/govpp.git/core/bin_api/vpe" - "github.com/ligato/cn-infra/logging/logrus" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/memif" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/tap" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/tapv2" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/vxlan" - interfaces2 "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" - "github.com/ligato/vpp-agent/tests/vppcallmock" - . "github.com/onsi/gomega" -) - -type vppReplyMock struct { - Id uint16 - Ping bool - Message govppapi.Message -} - -func vppMockHandler(vppMock *mock.VppAdapter, dataList []*vppReplyMock) mock.ReplyHandler { - var sendControlPing bool - - return func(request mock.MessageDTO) (reply []byte, msgID uint16, prepared bool) { - if sendControlPing { - sendControlPing = false - data := &vpe.ControlPingReply{} - reply, err := vppMock.ReplyBytes(request, data) - Expect(err).To(BeNil()) - msgID, err := vppMock.GetMsgID(data.GetMessageName(), data.GetCrcString()) - Expect(err).To(BeNil()) - return reply, msgID, true - } - - for _, dataMock := range dataList { - if request.MsgID == dataMock.Id { - // Send control ping next iteration if set - sendControlPing = dataMock.Ping - msgID, err := vppMock.GetMsgID(dataMock.Message.GetMessageName(), dataMock.Message.GetCrcString()) - Expect(err).To(BeNil()) - reply, err := vppMock.ReplyBytes(request, dataMock.Message) - Expect(err).To(BeNil()) - return reply, msgID, true - } - } - - replyMsg, msgID, ok := vppMock.ReplyFor(request.MsgName) - - if ok { - reply, err := vppMock.ReplyBytes(request, replyMsg) - Expect(err).To(BeNil()) - return reply, msgID, true - } - - return reply, 0, false - } -} - -// Test dump of interfaces without any replies, should return error and nil -// interfaces -func TestDumpInterfacesFullySilent(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) - defer ctx.TeardownTestCtx() - - intfs, err := DumpInterfaces(logrus.DefaultLogger(), ctx.MockChannel, nil) - Expect(err).To(Not(BeNil())) - Expect(intfs).To(BeNil()) -} - -// Test dump if interfaces without replying to all requests -func TestDumpInterfacesSilentSwInterfaceGetTableReply(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) - defer ctx.TeardownTestCtx() - - ctx.MockVpp.MockReplyHandler(vppMockHandler(ctx.MockVpp, []*vppReplyMock{ - { - Id: 200, - Ping: true, - Message: &interfaces.SwInterfaceDetails{}, - }, - })) - - intfs, err := DumpInterfaces(logrus.DefaultLogger(), ctx.MockChannel, nil) - Expect(err).To(Not(BeNil())) - Expect(intfs).To(BeNil()) -} - -// Test dump if interfaces without replying to all requests -func TestDumpInterfacesSilentIpAddressDetails(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) - defer ctx.TeardownTestCtx() - - ctx.MockVpp.MockReplyHandler(vppMockHandler(ctx.MockVpp, []*vppReplyMock{ - { - Id: 200, - Ping: true, - Message: &interfaces.SwInterfaceDetails{}, - }, - { - Id: 1001, - Ping: false, - Message: &interfaces.SwInterfaceGetTableReply{}, - }, - })) - - intfs, err := DumpInterfaces(logrus.DefaultLogger(), ctx.MockChannel, nil) - Expect(err).To(Not(BeNil())) - Expect(intfs).To(BeNil()) -} - -// Test dump if interfaces without replying to all requests -func TestDumpInterfacesSilentMemifSocketFilenameDetails(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) - defer ctx.TeardownTestCtx() - - ctx.MockVpp.MockReplyHandler(vppMockHandler(ctx.MockVpp, []*vppReplyMock{ - { - Id: 200, - Ping: true, - Message: &interfaces.SwInterfaceDetails{}, - }, - { - Id: 1001, - Ping: false, - Message: &interfaces.SwInterfaceGetTableReply{}, - }, - { - Id: 1004, - Ping: true, - Message: &ip.IPAddressDetails{}, - }, - })) - - intfs, err := DumpInterfaces(logrus.DefaultLogger(), ctx.MockChannel, nil) - Expect(err).To(Not(BeNil())) - Expect(intfs).To(BeNil()) -} - -// Test dump if interfaces without replying to all requests -func TestDumpInterfacesSilentMemifDetails(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) - defer ctx.TeardownTestCtx() - - ctx.MockVpp.MockReplyHandler(vppMockHandler(ctx.MockVpp, []*vppReplyMock{ - { - Id: 200, - Ping: true, - Message: &interfaces.SwInterfaceDetails{}, - }, - { - Id: 1001, - Ping: false, - Message: &interfaces.SwInterfaceGetTableReply{}, - }, - { - Id: 1004, - Ping: true, - Message: &ip.IPAddressDetails{}, - }, - { - Id: 1005, - Ping: true, - Message: &memif.MemifSocketFilenameDetails{}, - }, - })) - - intfs, err := DumpInterfaces(logrus.DefaultLogger(), ctx.MockChannel, nil) - Expect(err).To(Not(BeNil())) - Expect(intfs).To(BeNil()) -} - -// Test dump if interfaces without replying to all requests -func TestDumpInterfacesSilentSwInterfaceTapDetails(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) - defer ctx.TeardownTestCtx() - - ctx.MockVpp.MockReplyHandler(vppMockHandler(ctx.MockVpp, []*vppReplyMock{ - { - Id: 200, - Ping: true, - Message: &interfaces.SwInterfaceDetails{}, - }, - { - Id: 1001, - Ping: false, - Message: &interfaces.SwInterfaceGetTableReply{}, - }, - { - Id: 1004, - Ping: true, - Message: &ip.IPAddressDetails{}, - }, - { - Id: 1005, - Ping: true, - Message: &memif.MemifSocketFilenameDetails{}, - }, - { - Id: 1007, - Ping: true, - Message: &memif.MemifDetails{}, - }, - })) - - intfs, err := DumpInterfaces(logrus.DefaultLogger(), ctx.MockChannel, nil) - Expect(err).To(Not(BeNil())) - Expect(intfs).To(BeNil()) -} - -// Test dump if interfaces without replying to all requests -func TestDumpInterfacesSilentSwInterfaceTapV2Details(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) - defer ctx.TeardownTestCtx() - - ctx.MockVpp.MockReplyHandler(vppMockHandler(ctx.MockVpp, []*vppReplyMock{ - { - Id: 200, - Ping: true, - Message: &interfaces.SwInterfaceDetails{}, - }, - { - Id: 1001, - Ping: false, - Message: &interfaces.SwInterfaceGetTableReply{}, - }, - { - Id: 1004, - Ping: true, - Message: &ip.IPAddressDetails{}, - }, - { - Id: 1005, - Ping: true, - Message: &memif.MemifSocketFilenameDetails{}, - }, - { - Id: 1007, - Ping: true, - Message: &memif.MemifDetails{}, - }, - { - Id: 1009, - Ping: true, - Message: &tap.SwInterfaceTapDetails{}, - }, - })) - - intfs, err := DumpInterfaces(logrus.DefaultLogger(), ctx.MockChannel, nil) - Expect(err).To(Not(BeNil())) - Expect(intfs).To(BeNil()) -} - -// Test dump if interfaces without replying to all requests -func TestDumpInterfacesSilentVxlanTunnelDetails(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) - defer ctx.TeardownTestCtx() - - ctx.MockVpp.MockReplyHandler(vppMockHandler(ctx.MockVpp, []*vppReplyMock{ - { - Id: 200, - Ping: true, - Message: &interfaces.SwInterfaceDetails{}, - }, - { - Id: 1001, - Ping: false, - Message: &interfaces.SwInterfaceGetTableReply{}, - }, - { - Id: 1004, - Ping: true, - Message: &ip.IPAddressDetails{}, - }, - { - Id: 1005, - Ping: true, - Message: &memif.MemifSocketFilenameDetails{}, - }, - { - Id: 1007, - Ping: true, - Message: &memif.MemifDetails{}, - }, - { - Id: 1009, - Ping: true, - Message: &tap.SwInterfaceTapDetails{}, - }, - { - Id: 1011, - Ping: true, - Message: &tapv2.SwInterfaceTapV2Details{}, - }, - })) - - intfs, err := DumpInterfaces(logrus.DefaultLogger(), ctx.MockChannel, nil) - Expect(err).To(Not(BeNil())) - Expect(intfs).To(BeNil()) -} - -// Test dump of interfaces with vxlan type -func TestDumpInterfacesVxLan(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) - defer ctx.TeardownTestCtx() - - ipv61Parse := net.ParseIP("dead:beef:feed:face:cafe:babe:baad:c0de").To16() - ipv62Parse := net.ParseIP("d3ad:beef:feed:face:cafe:babe:baad:c0de").To16() - - ctx.MockVpp.MockReplyHandler(vppMockHandler(ctx.MockVpp, []*vppReplyMock{ - { - Id: 200, - Ping: true, - Message: &interfaces.SwInterfaceDetails{ - InterfaceName: []byte("vxlan1"), - }, - }, - { - Id: 1001, - Ping: false, - Message: &interfaces.SwInterfaceGetTableReply{}, - }, - { - Id: 1004, - Ping: true, - Message: &ip.IPAddressDetails{}, - }, - { - Id: 1005, - Ping: true, - Message: &memif.MemifSocketFilenameDetails{}, - }, - { - Id: 1007, - Ping: true, - Message: &memif.MemifDetails{}, - }, - { - Id: 1009, - Ping: true, - Message: &tap.SwInterfaceTapDetails{}, - }, - { - Id: 1011, - Ping: true, - Message: &tapv2.SwInterfaceTapV2Details{}, - }, - { - Id: 1013, - Ping: true, - Message: &vxlan.VxlanTunnelDetails{ - IsIpv6: 1, - SwIfIndex: 0, - SrcAddress: ipv61Parse, - DstAddress: ipv62Parse, - }, - }, - })) - - intfs, err := DumpInterfaces(logrus.DefaultLogger(), ctx.MockChannel, nil) - Expect(err).To(BeNil()) - Expect(intfs).To(HaveLen(1)) - intface := intfs[0] - - // Check vxlan - Expect(intface.Vxlan.SrcAddress).To(Equal("dead:beef:feed:face:cafe:babe:baad:c0de")) - Expect(intface.Vxlan.DstAddress).To(Equal("d3ad:beef:feed:face:cafe:babe:baad:c0de")) -} - -// Test dump of interfaces with host type -func TestDumpInterfacesHost(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) - defer ctx.TeardownTestCtx() - - ctx.MockVpp.MockReplyHandler(vppMockHandler(ctx.MockVpp, []*vppReplyMock{ - { - Id: 200, - Ping: true, - Message: &interfaces.SwInterfaceDetails{ - InterfaceName: []byte("host-localhost"), - }, - }, - { - Id: 1001, - Ping: false, - Message: &interfaces.SwInterfaceGetTableReply{}, - }, - { - Id: 1004, - Ping: true, - Message: &ip.IPAddressDetails{}, - }, - { - Id: 1005, - Ping: true, - Message: &memif.MemifSocketFilenameDetails{}, - }, - { - Id: 1007, - Ping: true, - Message: &memif.MemifDetails{}, - }, - { - Id: 1009, - Ping: true, - Message: &tap.SwInterfaceTapDetails{}, - }, - { - Id: 1011, - Ping: true, - Message: &tapv2.SwInterfaceTapV2Details{}, - }, - { - Id: 1013, - Ping: true, - Message: &vxlan.VxlanTunnelDetails{}, - }, - })) - - intfs, err := DumpInterfaces(logrus.DefaultLogger(), ctx.MockChannel, nil) - Expect(err).To(BeNil()) - Expect(intfs).To(HaveLen(1)) - intface := intfs[0] - - // Check interface data - Expect(intface.Afpacket.HostIfName).To(Equal("localhost")) -} - -// Test dump of interfaces with memif type -func TestDumpInterfacesMemif(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) - defer ctx.TeardownTestCtx() - - ctx.MockVpp.MockReplyHandler(vppMockHandler(ctx.MockVpp, []*vppReplyMock{ - { - Id: 200, - Ping: true, - Message: &interfaces.SwInterfaceDetails{ - InterfaceName: []byte("memif1"), - }, - }, - { - Id: 1001, - Ping: false, - Message: &interfaces.SwInterfaceGetTableReply{}, - }, - { - Id: 1004, - Ping: true, - Message: &ip.IPAddressDetails{}, - }, - { - Id: 1005, - Ping: true, - Message: &memif.MemifSocketFilenameDetails{ - SocketID: 1, - SocketFilename: []byte("test"), - }, - }, - { - Id: 1007, - Ping: true, - Message: &memif.MemifDetails{ - ID: 2, - SwIfIndex: 0, - Role: 1, // Slave - Mode: 1, // IP - SocketID: 1, - RingSize: 0, - BufferSize: 0, - }, - }, - { - Id: 1009, - Ping: true, - Message: &tap.SwInterfaceTapDetails{}, - }, - { - Id: 1011, - Ping: true, - Message: &tapv2.SwInterfaceTapV2Details{}, - }, - { - Id: 1013, - Ping: true, - Message: &vxlan.VxlanTunnelDetails{}, - }, - })) - - intfs, err := DumpInterfaces(logrus.DefaultLogger(), ctx.MockChannel, nil) - Expect(err).To(BeNil()) - Expect(intfs).To(HaveLen(1)) - intface := intfs[0] - - // Check memif - Expect(intface.Memif.SocketFilename).To(Equal("test")) - Expect(intface.Memif.Id).To(Equal(uint32(2))) - Expect(intface.Memif.Mode).To(Equal(interfaces2.Interfaces_Interface_Memif_IP)) - Expect(intface.Memif.Master).To(BeFalse()) -} - -// Test dump of interfaces using custom mock reply handler to avoid issues with ControlPingMessageReply -// not being properly recognized -func TestDumpInterfacesFull(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) - defer ctx.TeardownTestCtx() - - hwAddr1Parse, err := net.ParseMAC("01:23:45:67:89:ab") - Expect(err).To(BeNil()) - - ctx.MockVpp.MockReplyHandler(vppMockHandler(ctx.MockVpp, []*vppReplyMock{ - { - Id: 200, - Ping: true, - Message: &interfaces.SwInterfaceDetails{ - InterfaceName: []byte("memif1"), - Tag: []byte("interface2"), - AdminUpDown: 1, - LinkMtu: 9216, // Default MTU - L2Address: hwAddr1Parse, - L2AddressLength: uint32(len(hwAddr1Parse)), - }, - }, - { - Id: 1001, - Ping: false, - Message: &interfaces.SwInterfaceGetTableReply{ - Retval: 0, - VrfID: 42, - }, - }, - { - Id: 1004, - Ping: true, - Message: &ip.IPAddressDetails{}, - }, - { - Id: 1005, - Ping: true, - Message: &memif.MemifSocketFilenameDetails{ - SocketID: 1, - SocketFilename: []byte("test"), - }, - }, - { - Id: 1007, - Ping: true, - Message: &memif.MemifDetails{ - ID: 2, - SwIfIndex: 0, - Role: 0, // Master - Mode: 0, // Ethernet - SocketID: 1, - RingSize: 0, - BufferSize: 0, - }, - }, - { - Id: 1009, - Ping: true, - Message: &tap.SwInterfaceTapDetails{ - SwIfIndex: 0, - DevName: []byte("taptap"), - }, - }, - { - Id: 1011, - Ping: true, - Message: &tapv2.SwInterfaceTapV2Details{ - SwIfIndex: 0, - HostIfName: []byte("taptap2"), // This will overwrite the v1 tap name - }, - }, - { - Id: 1013, - Ping: true, - Message: &vxlan.VxlanTunnelDetails{ - SwIfIndex: 0, - SrcAddress: []byte{192, 168, 0, 1}, - DstAddress: []byte{192, 168, 0, 2}, - }, - }, - })) - - intfs, err := DumpInterfaces(logrus.DefaultLogger(), ctx.MockChannel, nil) - Expect(err).To(BeNil()) - Expect(intfs).To(HaveLen(1)) - - intface := intfs[0] - - // This is last checked type, so it will be equal to that - Expect(intface.Type).To(Equal(interfaces2.InterfaceType_VXLAN_TUNNEL)) - Expect(intface.PhysAddress).To(Equal("01:23:45:67:89:ab")) - Expect(intface.Name).To(Equal("interface2")) - Expect(intface.Mtu).To(Equal(uint32(0))) // default mtu - Expect(intface.Enabled).To(BeTrue()) - Expect(intface.Vrf).To(Equal(uint32(42))) - - // Check memif - Expect(intface.Memif.SocketFilename).To(Equal("test")) - Expect(intface.Memif.Id).To(Equal(uint32(2))) - Expect(intface.Memif.Mode).To(Equal(interfaces2.Interfaces_Interface_Memif_ETHERNET)) - Expect(intface.Memif.Master).To(BeTrue()) - - // Check tap - Expect(intface.Tap.HostIfName).To(Equal("taptap2")) - Expect(intface.Tap.Version).To(Equal(uint32(2))) - - // Check vxlan - Expect(intface.Vxlan.SrcAddress).To(Equal("192.168.0.1")) - Expect(intface.Vxlan.DstAddress).To(Equal("192.168.0.2")) -} - -// Test dump of memif socket details using standard reply mocking -func TestDumpMemifSocketDetails(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) - defer ctx.TeardownTestCtx() - - ctx.MockVpp.MockReply(&memif.MemifSocketFilenameDetails{ - SocketID: 1, - SocketFilename: []byte("test"), - }) - - ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - - result, err := DumpMemifSocketDetails(logrus.DefaultLogger(), ctx.MockChannel, nil) - Expect(err).To(BeNil()) - Expect(result).To(Not(BeEmpty())) - - socketID, ok := result["test"] - Expect(ok).To(BeTrue()) - Expect(socketID).To(Equal(uint32(1))) -} diff --git a/plugins/vpp/ipsecplugin/ipsec_config.go b/plugins/vpp/ipsecplugin/ipsec_config.go index d05d091f49..20f073c546 100644 --- a/plugins/vpp/ipsecplugin/ipsec_config.go +++ b/plugins/vpp/ipsecplugin/ipsec_config.go @@ -30,6 +30,7 @@ import ( iface_vppcalls "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" "github.com/ligato/vpp-agent/plugins/vpp/ipsecplugin/ipsecidx" "github.com/ligato/vpp-agent/plugins/vpp/ipsecplugin/vppcalls" + "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" "github.com/ligato/vpp-agent/plugins/vpp/model/ipsec" ) @@ -61,6 +62,10 @@ type IPSecConfigurator struct { // VPP channel vppCh govppapi.Channel + // VPP API handlers + ifHandler iface_vppcalls.IfVppAPI + ipSecHandler vppcalls.IPSecVppAPI + // Timer used to measure and store time stopwatch *measure.Stopwatch } @@ -72,6 +77,11 @@ func (plugin *IPSecConfigurator) Init(logger logging.PluginLogger, goVppMux govp plugin.log = logger.NewLogger("-ipsec-plugin") plugin.log.Debug("Initializing IPSec configurator") + // Configurator-wide stopwatch instance + if enableStopwatch { + plugin.stopwatch = measure.NewStopwatch("IPSec-configurator", plugin.log) + } + // Mappings plugin.ifIndexes = swIfIndexes plugin.spdIndexes = ipsecidx.NewSPDIndex(nametoidx.NewNameToIdx(plugin.log, "ipsec_spd_indexes", nil)) @@ -86,16 +96,9 @@ func (plugin *IPSecConfigurator) Init(logger logging.PluginLogger, goVppMux govp return err } - // Stopwatch - if enableStopwatch { - plugin.stopwatch = measure.NewStopwatch("IPSecConfigurator", plugin.log) - } - - // Message compatibility - if err = plugin.vppCh.CheckMessageCompatibility(vppcalls.IPSecMessages...); err != nil { - plugin.log.Error(err) - return err - } + // VPP API handlers + plugin.ifHandler = iface_vppcalls.NewIfVppHandler(plugin.vppCh, plugin.log, plugin.stopwatch) + plugin.ipSecHandler = vppcalls.NewIPsecVppHandler(plugin.vppCh, plugin.ifIndexes, plugin.spdIndexes, plugin.log, plugin.stopwatch) return nil } @@ -117,7 +120,7 @@ func (plugin *IPSecConfigurator) GetSaIndexes() idxvpp.NameToIdxRW { return plugin.saIndexes } -// GetSaIndexes returns security policy database indexes +// GetSpdIndexes returns security policy database indexes func (plugin *IPSecConfigurator) GetSpdIndexes() ipsecidx.SPDIndex { return plugin.spdIndexes } @@ -145,7 +148,7 @@ func (plugin *IPSecConfigurator) ConfigureSPD(spd *ipsec.SecurityPolicyDatabases func (plugin *IPSecConfigurator) configureSPD(spdID uint32, spd *ipsec.SecurityPolicyDatabases_SPD) error { plugin.log.Debugf("configuring SPD %v (%d)", spd.Name, spdID) - if err := vppcalls.AddSPD(spdID, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ipSecHandler.AddSPD(spdID); err != nil { return err } @@ -162,7 +165,7 @@ func (plugin *IPSecConfigurator) configureSPD(spdID uint32, spd *ipsec.SecurityP continue } - if err := vppcalls.InterfaceAddSPD(spdID, swIfIdx, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ipSecHandler.InterfaceAddSPD(spdID, swIfIdx); err != nil { plugin.log.Errorf("assigning interface to SPD failed: %v", err) continue } @@ -182,7 +185,7 @@ func (plugin *IPSecConfigurator) configureSPD(spdID uint32, spd *ipsec.SecurityP } } - if err := vppcalls.AddSPDEntry(spdID, saID, entry, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ipSecHandler.AddSPDEntry(spdID, saID, entry); err != nil { plugin.log.Errorf("adding SPD policy entry failed: %v", err) continue } @@ -226,7 +229,7 @@ func (plugin *IPSecConfigurator) DeleteSPD(oldSpd *ipsec.SecurityPolicyDatabases plugin.log.Warnf("SPD %q not found", oldSpd.Name) return nil } - if err := vppcalls.DelSPD(spdID, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ipSecHandler.DelSPD(spdID); err != nil { return err } @@ -251,7 +254,7 @@ func (plugin *IPSecConfigurator) ConfigureSA(sa *ipsec.SecurityAssociations_SA) saID := plugin.saIndexSeq plugin.saIndexSeq++ - if err := vppcalls.AddSAEntry(saID, sa, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ipSecHandler.AddSAEntry(saID, sa); err != nil { return err } @@ -314,7 +317,7 @@ func (plugin *IPSecConfigurator) DeleteSA(oldSa *ipsec.SecurityAssociations_SA) plugin.log.Warnf("caching SPD %v due removed SA %v", entry.SPD.Name, oldSa.Name) } - if err := vppcalls.DelSAEntry(saID, oldSa, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ipSecHandler.DelSAEntry(saID, oldSa); err != nil { return err } @@ -328,15 +331,21 @@ func (plugin *IPSecConfigurator) DeleteSA(oldSa *ipsec.SecurityAssociations_SA) func (plugin *IPSecConfigurator) ConfigureTunnel(tunnel *ipsec.TunnelInterfaces_Tunnel) error { plugin.log.Debugf("Configuring Tunnel %v", tunnel.Name) - ifIdx, err := vppcalls.AddTunnelInterface(tunnel, plugin.vppCh, plugin.stopwatch) + ifIdx, err := plugin.ipSecHandler.AddTunnelInterface(tunnel) if err != nil { return err } - plugin.ifIndexes.RegisterName(tunnel.Name, ifIdx, nil) + // Register with necessary metadta info + plugin.ifIndexes.RegisterName(tunnel.Name, ifIdx, &interfaces.Interfaces_Interface{ + Name: tunnel.Name, + Enabled: tunnel.Enabled, + IpAddresses: tunnel.IpAddresses, + Vrf: tunnel.Vrf, + }) plugin.log.Infof("Registered Tunnel %v (%d)", tunnel.Name, ifIdx) - if err := iface_vppcalls.SetInterfaceVRF(ifIdx, tunnel.Vrf, plugin.log, plugin.vppCh); err != nil { + if err := plugin.ifHandler.SetInterfaceVrf(ifIdx, tunnel.Vrf); err != nil { return err } @@ -345,14 +354,14 @@ func (plugin *IPSecConfigurator) ConfigureTunnel(tunnel *ipsec.TunnelInterfaces_ return err } for _, ip := range ipAddrs { - if err := iface_vppcalls.AddInterfaceIP(ifIdx, ip, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.AddInterfaceIP(ifIdx, ip); err != nil { plugin.log.Errorf("adding interface IP address failed: %v", err) return err } } if tunnel.Enabled { - if err := iface_vppcalls.InterfaceAdminUp(ifIdx, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ifHandler.InterfaceAdminUp(ifIdx); err != nil { plugin.log.Debugf("setting interface up failed: %v", err) return err } @@ -387,7 +396,7 @@ func (plugin *IPSecConfigurator) DeleteTunnel(oldTunnel *ipsec.TunnelInterfaces_ return nil } - if err := vppcalls.DelTunnelInterface(ifIdx, oldTunnel, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ipSecHandler.DelTunnelInterface(ifIdx, oldTunnel); err != nil { return err } @@ -404,13 +413,13 @@ func (plugin *IPSecConfigurator) ResolveCreatedInterface(ifName string, swIfIdx plugin.log.Infof("Assigning SPD %v to interface %q", entry.spdID, ifName) // TODO: loop through stored deletes, this is now needed because old assignment might still exist - if err := vppcalls.InterfaceDelSPD(entry.spdID, swIfIdx, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ipSecHandler.InterfaceDelSPD(entry.spdID, swIfIdx); err != nil { plugin.log.Errorf("unassigning interface from SPD failed: %v", err) } else { plugin.log.Infof("Unassigned SPD %v from interface %q", entry.spdID, ifName) } - if err := vppcalls.InterfaceAddSPD(entry.spdID, swIfIdx, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ipSecHandler.InterfaceAddSPD(entry.spdID, swIfIdx); err != nil { plugin.log.Errorf("assigning interface to SPD failed: %v", err) continue } else { @@ -428,7 +437,7 @@ func (plugin *IPSecConfigurator) ResolveDeletedInterface(ifName string, swIfIdx plugin.log.Infof("Unassigning SPD %v from interface %q", assign.SpdID, ifName) // TODO: just store this for future, because this will fail since swIfIdx no longer exists - if err := vppcalls.InterfaceDelSPD(assign.SpdID, swIfIdx, plugin.vppCh, plugin.stopwatch); err != nil { + if err := plugin.ipSecHandler.InterfaceDelSPD(assign.SpdID, swIfIdx); err != nil { plugin.log.Errorf("unassigning interface from SPD failed: %v", err) } else { plugin.log.Infof("Unassigned SPD %v from interface %q", assign.SpdID, ifName) diff --git a/plugins/vpp/ipsecplugin/ipsecidx/spd_index.go b/plugins/vpp/ipsecplugin/ipsecidx/spd_index.go index f6f6a76a45..5d11b7958c 100644 --- a/plugins/vpp/ipsecplugin/ipsecidx/spd_index.go +++ b/plugins/vpp/ipsecplugin/ipsecidx/spd_index.go @@ -37,7 +37,7 @@ type SPDIndex interface { LookupBySA(saName string) []SPDEntry } -// RouteIndexRW is mapping between SPD data (metadata) and SPD entry names. +// SPDIndexRW is mapping between SPD data (metadata) and SPD entry names. type SPDIndexRW interface { SPDIndex diff --git a/plugins/vpp/ipsecplugin/vppcalls/api_vppcalls.go b/plugins/vpp/ipsecplugin/vppcalls/api_vppcalls.go new file mode 100644 index 0000000000..2e6dcb3729 --- /dev/null +++ b/plugins/vpp/ipsecplugin/vppcalls/api_vppcalls.go @@ -0,0 +1,87 @@ +// Copyright (c) 2017 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vppcalls + +import ( + govppapi "git.fd.io/govpp.git/api" + "github.com/ligato/cn-infra/logging" + "github.com/ligato/cn-infra/logging/measure" + "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" + "github.com/ligato/vpp-agent/plugins/vpp/ipsecplugin/ipsecidx" + "github.com/ligato/vpp-agent/plugins/vpp/model/ipsec" +) + +// IPSecVppAPI provides methods for creating and managing of a IPsec configuration +type IPSecVppAPI interface { + IPSecVppWrite + IPSecVPPRead +} + +// IPSecVppWrite provides write methods for IPsec +type IPSecVppWrite interface { + // AddTunnelInterface adds tunnel interface + AddTunnelInterface(tunnel *ipsec.TunnelInterfaces_Tunnel) (uint32, error) + // DelTunnelInterface removes tunnel interface + DelTunnelInterface(ifIdx uint32, tunnel *ipsec.TunnelInterfaces_Tunnel) error + // AddSPD adds SPD to VPP via binary API + AddSPD(spdID uint32) error + // DelSPD deletes SPD from VPP via binary API + DelSPD(spdID uint32) error + // InterfaceAddSPD adds SPD interface assignment to VPP via binary API + InterfaceAddSPD(spdID, swIfIdx uint32) error + // InterfaceDelSPD deletes SPD interface assignment from VPP via binary API + InterfaceDelSPD(spdID, swIfIdx uint32) error + // AddSPDEntry adds SPD policy entry to VPP via binary API + AddSPDEntry(spdID, saID uint32, spd *ipsec.SecurityPolicyDatabases_SPD_PolicyEntry) error + // DelSPDEntry deletes SPD policy entry from VPP via binary API + DelSPDEntry(spdID, saID uint32, spd *ipsec.SecurityPolicyDatabases_SPD_PolicyEntry) error + // AddSAEntry adds SA to VPP via binary API + AddSAEntry(saID uint32, sa *ipsec.SecurityAssociations_SA) error + // DelSAEntry deletes SA from VPP via binary API + DelSAEntry(saID uint32, sa *ipsec.SecurityAssociations_SA) error +} + +// IPSecVPPRead provides read methods for IPSec +type IPSecVPPRead interface { + // DumpIPSecSPD returns a list of IPSec security policy databases + DumpIPSecSPD() (spdList []*IPSecSpdDetails, err error) + // DumpIPSecSA returns a list of configured security associations + DumpIPSecSA() (saList []*IPSecSaDetails, err error) + // DumpIPSecSAWithIndex returns a security association with provided index + DumpIPSecSAWithIndex(saID uint32) (saList []*IPSecSaDetails, err error) + // DumpIPSecTunnelInterfaces returns a list of configured IPSec tunnel interfaces + DumpIPSecTunnelInterfaces() (tun []*IPSecTunnelInterfaceDetails, err error) +} + +// IPSecVppHandler is accessor for IPsec-related vppcalls methods +type IPSecVppHandler struct { + stopwatch *measure.Stopwatch + callsChannel govppapi.Channel + ifIndexes ifaceidx.SwIfIndex + spdIndexes ipsecidx.SPDIndex // TODO workaround in order to be able to dump at least spds configurator knows about + log logging.Logger +} + +// NewIPsecVppHandler creates new instance of IPsec vppcalls handler +func NewIPsecVppHandler(callsChan govppapi.Channel, ifIndexes ifaceidx.SwIfIndex, spdIndexes ipsecidx.SPDIndex, + log logging.Logger, stopwatch *measure.Stopwatch) *IPSecVppHandler { + return &IPSecVppHandler{ + callsChannel: callsChan, + stopwatch: stopwatch, + ifIndexes: ifIndexes, + spdIndexes: spdIndexes, + log: log, + } +} diff --git a/plugins/vpp/ipsecplugin/vppcalls/dump_vppcalls.go b/plugins/vpp/ipsecplugin/vppcalls/dump_vppcalls.go new file mode 100644 index 0000000000..060bb40d13 --- /dev/null +++ b/plugins/vpp/ipsecplugin/vppcalls/dump_vppcalls.go @@ -0,0 +1,334 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vppcalls + +import ( + "net" + "strconv" + "time" + + ipsecapi "github.com/ligato/vpp-agent/plugins/vpp/binapi/ipsec" + "github.com/ligato/vpp-agent/plugins/vpp/model/ipsec" +) + +// IPSecSaDetails holds security association with VPP metadata +type IPSecSaDetails struct { + Sa *ipsec.SecurityAssociations_SA + Meta *IPSecSaMeta +} + +// IPSecSaMeta contains all VPP-specific metadata +type IPSecSaMeta struct { + SaID uint32 + Interface string + IfIdx uint32 + CryptoKeyLen uint8 + IntegKeyLen uint8 + Salt uint32 + SeqOutbound uint64 + LastSeqInbound uint64 + ReplayWindow uint64 + TotalDataSize uint64 +} + +// DumpIPSecSA implements IPSec handler. +func (handler *IPSecVppHandler) DumpIPSecSA() (saList []*IPSecSaDetails, err error) { + return handler.DumpIPSecSAWithIndex(^uint32(0)) // Get everything +} + +// DumpIPSecSAWithIndex implements IPSec handler. +func (handler *IPSecVppHandler) DumpIPSecSAWithIndex(saID uint32) (saList []*IPSecSaDetails, err error) { + defer func(t time.Time) { + handler.stopwatch.TimeLog(ipsecapi.IpsecSaDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + saDetails, err := handler.dumpSecurityAssociations(saID) + if err != nil { + return nil, err + } + + for _, saData := range saDetails { + // Skip tunnel interfaces + if saData.SwIfIndex != ^uint32(0) { + continue + } + + // Addresses + var tunnelSrcAddrStr, tunnelDstAddrStr string + if uintToBool(saData.IsTunnelIP6) { + var tunnelSrcAddr, tunnelDstAddr net.IP = saData.TunnelSrcAddr, saData.TunnelDstAddr + tunnelSrcAddrStr, tunnelDstAddrStr = tunnelSrcAddr.String(), tunnelDstAddr.String() + } else { + var tunnelSrcAddr, tunnelDstAddr net.IP = saData.TunnelSrcAddr[:4], saData.TunnelDstAddr[:4] + tunnelSrcAddrStr, tunnelDstAddrStr = tunnelSrcAddr.String(), tunnelDstAddr.String() + } + + sa := &ipsec.SecurityAssociations_SA{ + Spi: saData.Spi, + Protocol: ipsec.SecurityAssociations_SA_IPSecProtocol(saData.Protocol), + CryptoAlg: ipsec.CryptoAlgorithm(saData.CryptoAlg), + CryptoKey: string(saData.CryptoKey[:saData.CryptoKeyLen]), + IntegAlg: ipsec.IntegAlgorithm(saData.IntegAlg), + IntegKey: string(saData.IntegKey[:saData.IntegKeyLen]), + UseEsn: uintToBool(saData.UseEsn), + UseAntiReplay: uintToBool(saData.UseAntiReplay), + TunnelSrcAddr: tunnelSrcAddrStr, + TunnelDstAddr: tunnelDstAddrStr, + EnableUdpEncap: uintToBool(saData.UDPEncap), + } + meta := &IPSecSaMeta{ + SaID: saData.SaID, + IfIdx: saData.SwIfIndex, + CryptoKeyLen: saData.CryptoKeyLen, + IntegKeyLen: saData.IntegKeyLen, + Salt: saData.Salt, + SeqOutbound: saData.SeqOutbound, + LastSeqInbound: saData.LastSeqInbound, + ReplayWindow: saData.ReplayWindow, + TotalDataSize: saData.TotalDataSize, + } + saList = append(saList, &IPSecSaDetails{ + Sa: sa, + Meta: meta, + }) + } + + return saList, nil +} + +// IPSecTunnelInterfaceDetails hold a list of tunnel interfaces with name/index map as metadata +type IPSecTunnelInterfaceDetails struct { + Tunnel *ipsec.TunnelInterfaces_Tunnel + Meta *IPSecTunnelMeta +} + +// IPSecTunnelMeta contains map of name/index pairs +type IPSecTunnelMeta struct { + SwIfIndex uint32 +} + +// DumpIPSecTunnelInterfaces implements IPSec handler. +func (handler *IPSecVppHandler) DumpIPSecTunnelInterfaces() (tun []*IPSecTunnelInterfaceDetails, err error) { + defer func(t time.Time) { + handler.stopwatch.TimeLog(ipsecapi.IpsecSaDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + saDetails, err := handler.dumpSecurityAssociations(^uint32(0)) + if err != nil { + return nil, err + } + + for _, saData := range saDetails { + // Skip non-tunnel security associations + if saData.SwIfIndex == ^uint32(0) { + continue + } + + // Interface + ifName, ifData, found := handler.ifIndexes.LookupName(saData.SwIfIndex) + if !found { + handler.log.Warnf("IPSec SA dump: interface name not found for %d", saData.SwIfIndex) + continue + } + if ifData == nil { + handler.log.Warnf("IPSec SA dump: interface %s has no metadata", ifName) + continue + } + + // Addresses + var tunnelSrcAddrStr, tunnelDstAddrStr string + if uintToBool(saData.IsTunnelIP6) { + var tunnelSrcAddr, tunnelDstAddr net.IP = saData.TunnelSrcAddr, saData.TunnelDstAddr + tunnelSrcAddrStr, tunnelDstAddrStr = tunnelSrcAddr.String(), tunnelDstAddr.String() + } else { + var tunnelSrcAddr, tunnelDstAddr net.IP = saData.TunnelSrcAddr[:4], saData.TunnelDstAddr[:4] + tunnelSrcAddrStr, tunnelDstAddrStr = tunnelSrcAddr.String(), tunnelDstAddr.String() + } + + // Prepare tunnel interface data + tunnel := &ipsec.TunnelInterfaces_Tunnel{ + Name: ifName, + Esn: uintToBool(saData.UseEsn), + AntiReplay: uintToBool(saData.UseAntiReplay), + LocalIp: tunnelSrcAddrStr, + RemoteIp: tunnelDstAddrStr, + LocalSpi: saData.Spi, + RemoteSpi: saData.Spi, + CryptoAlg: ipsec.CryptoAlgorithm(saData.CryptoAlg), + IntegAlg: ipsec.IntegAlgorithm(saData.IntegAlg), + Enabled: ifData.Enabled, + IpAddresses: ifData.IpAddresses, + Vrf: ifData.Vrf, + } + tun = append(tun, &IPSecTunnelInterfaceDetails{ + Tunnel: tunnel, + Meta: &IPSecTunnelMeta{ + SwIfIndex: saData.SwIfIndex, + }, + }) + } + + return tun, nil +} + +// IPSecSpdDetails represents IPSec policy databases with particular metadata +type IPSecSpdDetails struct { + Spd *ipsec.SecurityPolicyDatabases_SPD + Meta *IPSecSpdMeta +} + +// IPSecSpdMeta is map where key is a generated security association name, and value is an SpdMeta object +type IPSecSpdMeta struct { + SpdMeta map[string]*SpdMeta // SA-generated name is a key +} + +// SpdMeta hold VPP-specific data related to SPD +type SpdMeta struct { + SaID uint32 + SpdID uint32 + Policy uint8 + Bytes uint64 + Packets uint64 +} + +// DumpIPSecSPD implements IPSec handler. +func (handler *IPSecVppHandler) DumpIPSecSPD() (spdList []*IPSecSpdDetails, err error) { + defer func(t time.Time) { + handler.stopwatch.TimeLog(ipsecapi.IpsecSpdDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + metadata := &IPSecSpdMeta{ + SpdMeta: make(map[string]*SpdMeta), + } + + // TODO IPSec SPD dump request requires SPD ID, otherwise it returns nothing. There is currently no way + // to dump all SPDs available on the VPP, so let's dump at least the ones configurator knows about. + for _, spdName := range handler.spdIndexes.GetMapping().ListNames() { + spdIdx, _, found := handler.spdIndexes.LookupIdx(spdName) + if !found { + // Shouldn't happen, call the police or something + continue + } + spd := &ipsec.SecurityPolicyDatabases_SPD{} + + // Prepare VPP binapi request + req := &ipsecapi.IpsecSpdDump{ + SpdID: spdIdx, + SaID: ^uint32(0), + } + requestCtx := handler.callsChannel.SendMultiRequest(req) + + // Policy association index, used to generate SA name + var paIdx int + + for { + spdDetails := &ipsecapi.IpsecSpdDetails{} + stop, err := requestCtx.ReceiveReply(spdDetails) + if stop { + break + } + if err != nil { + return nil, err + } + + // Security association name, to distinguish metadata + saGenName := "sa-generated-" + strconv.Itoa(paIdx) + paIdx++ + + // Addresses + var remoteStartAddrStr, remoteStopAddrStr, localStartAddrStr, localStopAddrStr string + if uintToBool(spdDetails.IsIPv6) { + var remoteStartAddr, remoteStopAddr net.IP = spdDetails.RemoteStartAddr, spdDetails.RemoteStopAddr + remoteStartAddrStr, remoteStopAddrStr = remoteStartAddr.String(), remoteStopAddr.String() + var localStartAddr, localStopAddr net.IP = spdDetails.LocalStartAddr, spdDetails.LocalStopAddr + localStartAddrStr, localStopAddrStr = localStartAddr.String(), localStopAddr.String() + } else { + var remoteStartAddr, remoteStopAddr net.IP = spdDetails.RemoteStartAddr[:4], spdDetails.RemoteStopAddr[:4] + remoteStartAddrStr, remoteStopAddrStr = remoteStartAddr.String(), remoteStopAddr.String() + var localStartAddr, localStopAddr net.IP = spdDetails.LocalStartAddr[:4], spdDetails.LocalStopAddr[:4] + localStartAddrStr, localStopAddrStr = localStartAddr.String(), localStopAddr.String() + } + + // Prepare policy entry and put to the SPD + policyEntry := &ipsec.SecurityPolicyDatabases_SPD_PolicyEntry{ + Sa: saGenName, + Priority: spdDetails.Priority, + IsOutbound: uintToBool(spdDetails.IsOutbound), + RemoteAddrStart: remoteStartAddrStr, + RemoteAddrStop: remoteStopAddrStr, + LocalAddrStart: localStartAddrStr, + LocalAddrStop: localStopAddrStr, + Protocol: uint32(spdDetails.Protocol), + RemotePortStart: uint32(spdDetails.RemoteStartPort), + RemotePortStop: uint32(spdDetails.RemoteStopPort), + LocalPortStart: uint32(spdDetails.LocalStartPort), + LocalPortStop: uint32(spdDetails.LocalStopPort), + } + spd.PolicyEntries = append(spd.PolicyEntries, policyEntry) + + // Prepare meta and put to the metadata map + meta := &SpdMeta{ + SpdID: spdDetails.SpdID, + SaID: spdDetails.SaID, + Policy: spdDetails.Policy, + Bytes: spdDetails.Bytes, + Packets: spdDetails.Packets, + } + metadata.SpdMeta[saGenName] = meta + } + // Store STD in list + spdList = append(spdList, &IPSecSpdDetails{ + Spd: spd, + Meta: metadata, + }) + } + + return spdList, nil +} + +// Get all security association (used also for tunnel interfaces) in binary api format +func (handler *IPSecVppHandler) dumpSecurityAssociations(saID uint32) (saList []*ipsecapi.IpsecSaDetails, err error) { + defer func(t time.Time) { + handler.stopwatch.TimeLog(ipsecapi.IpsecSaDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + req := &ipsecapi.IpsecSaDump{ + SaID: saID, + } + requestCtx := handler.callsChannel.SendMultiRequest(req) + + for { + saDetails := &ipsecapi.IpsecSaDetails{} + stop, err := requestCtx.ReceiveReply(saDetails) + if stop { + break + } + if err != nil { + return nil, err + } + + saList = append(saList, saDetails) + } + + return saList, nil + +} + +func uintToBool(input uint8) bool { + if input == 1 { + return true + } + return false +} diff --git a/plugins/vpp/ipsecplugin/vppcalls/ipsec_vppcalls.go b/plugins/vpp/ipsecplugin/vppcalls/ipsec_vppcalls.go index e9470a6cc8..049255e0bb 100644 --- a/plugins/vpp/ipsecplugin/vppcalls/ipsec_vppcalls.go +++ b/plugins/vpp/ipsecplugin/vppcalls/ipsec_vppcalls.go @@ -20,38 +20,14 @@ import ( "net" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/cn-infra/utils/addrs" ipsec_api "github.com/ligato/vpp-agent/plugins/vpp/binapi/ipsec" "github.com/ligato/vpp-agent/plugins/vpp/model/ipsec" ) -// IPSecMessages is list of used VPP messages for compatibility check -var IPSecMessages = []govppapi.Message{ - &ipsec_api.IpsecSpdAddDel{}, - &ipsec_api.IpsecSpdAddDelReply{}, - &ipsec_api.IpsecInterfaceAddDelSpd{}, - &ipsec_api.IpsecInterfaceAddDelSpdReply{}, - &ipsec_api.IpsecSpdAddDelEntry{}, - &ipsec_api.IpsecSpdAddDelEntryReply{}, - &ipsec_api.IpsecSadAddDelEntry{}, - &ipsec_api.IpsecSadAddDelEntryReply{}, - &ipsec_api.IpsecSpdDump{}, - &ipsec_api.IpsecSpdDetails{}, - &ipsec_api.IpsecTunnelIfAddDel{}, - &ipsec_api.IpsecTunnelIfAddDelReply{}, - &ipsec_api.IpsecSaDump{}, - &ipsec_api.IpsecSaDetails{}, - &ipsec_api.IpsecTunnelIfSetKey{}, - &ipsec_api.IpsecTunnelIfSetKeyReply{}, - &ipsec_api.IpsecTunnelIfSetSa{}, - &ipsec_api.IpsecTunnelIfSetSaReply{}, -} - -func tunnelIfAddDel(tunnel *ipsec.TunnelInterfaces_Tunnel, isAdd bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (uint32, error) { +func (handler *IPSecVppHandler) tunnelIfAddDel(tunnel *ipsec.TunnelInterfaces_Tunnel, isAdd bool) (uint32, error) { defer func(t time.Time) { - stopwatch.TimeLog(ipsec_api.IpsecTunnelIfAddDel{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(ipsec_api.IpsecTunnelIfAddDel{}).LogTimeEntry(time.Since(t)) }(time.Now()) localCryptoKey, err := hex.DecodeString(tunnel.LocalCryptoKey) @@ -90,64 +66,62 @@ func tunnelIfAddDel(tunnel *ipsec.TunnelInterfaces_Tunnel, isAdd bool, vppChan g RemoteIntegKey: remoteIntegKey, RemoteIntegKeyLen: uint8(len(remoteIntegKey)), } - reply := &ipsec_api.IpsecTunnelIfAddDelReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return 0, err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return 0, fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return reply.SwIfIndex, nil } -// AddSPD adds SPD to VPP via binary API -func AddTunnelInterface(tunnel *ipsec.TunnelInterfaces_Tunnel, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (uint32, error) { - return tunnelIfAddDel(tunnel, true, vppChan, stopwatch) +// AddTunnelInterface implements IPSec handler. +func (handler *IPSecVppHandler) AddTunnelInterface(tunnel *ipsec.TunnelInterfaces_Tunnel) (uint32, error) { + return handler.tunnelIfAddDel(tunnel, true) } -// DelSPD deletes SPD from VPP via binary API -func DelTunnelInterface(ifIdx uint32, tunnel *ipsec.TunnelInterfaces_Tunnel, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +// DelTunnelInterface implements IPSec handler. +func (handler *IPSecVppHandler) DelTunnelInterface(ifIdx uint32, tunnel *ipsec.TunnelInterfaces_Tunnel) error { // Note: ifIdx is not used now, tunnel shiould be matched based on paramters - _, err := tunnelIfAddDel(tunnel, false, vppChan, stopwatch) + _, err := handler.tunnelIfAddDel(tunnel, false) return err } -func spdAddDel(spdID uint32, isAdd bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +func (handler *IPSecVppHandler) spdAddDel(spdID uint32, isAdd bool) error { defer func(t time.Time) { - stopwatch.TimeLog(ipsec_api.IpsecSpdAddDel{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(ipsec_api.IpsecSpdAddDel{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &ipsec_api.IpsecSpdAddDel{ IsAdd: boolToUint(isAdd), SpdID: spdID, } - reply := &ipsec_api.IpsecSpdAddDelReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return nil } -// AddSPD adds SPD to VPP via binary API -func AddSPD(spdID uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return spdAddDel(spdID, true, vppChan, stopwatch) +// AddSPD implements IPSec handler. +func (handler *IPSecVppHandler) AddSPD(spdID uint32) error { + return handler.spdAddDel(spdID, true) } -// DelSPD deletes SPD from VPP via binary API -func DelSPD(spdID uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return spdAddDel(spdID, false, vppChan, stopwatch) +// DelSPD implements IPSec handler. +func (handler *IPSecVppHandler) DelSPD(spdID uint32) error { + return handler.spdAddDel(spdID, false) } -func interfaceAddDelSpd(spdID, swIfIdx uint32, isAdd bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +func (handler *IPSecVppHandler) interfaceAddDelSpd(spdID, swIfIdx uint32, isAdd bool) error { defer func(t time.Time) { - stopwatch.TimeLog(ipsec_api.IpsecInterfaceAddDelSpd{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(ipsec_api.IpsecInterfaceAddDelSpd{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &ipsec_api.IpsecInterfaceAddDelSpd{ @@ -155,31 +129,30 @@ func interfaceAddDelSpd(spdID, swIfIdx uint32, isAdd bool, vppChan govppapi.Chan SwIfIndex: swIfIdx, SpdID: spdID, } - reply := &ipsec_api.IpsecInterfaceAddDelSpdReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return nil } -// InterfaceAddSPD adds SPD interface assignment to VPP via binary API -func InterfaceAddSPD(spdID, swIfIdx uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return interfaceAddDelSpd(spdID, swIfIdx, true, vppChan, stopwatch) +// InterfaceAddSPD implements IPSec handler. +func (handler *IPSecVppHandler) InterfaceAddSPD(spdID, swIfIdx uint32) error { + return handler.interfaceAddDelSpd(spdID, swIfIdx, true) } -// InterfaceDelSPD deletes SPD interface assignment from VPP via binary API -func InterfaceDelSPD(spdID, swIfIdx uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return interfaceAddDelSpd(spdID, swIfIdx, false, vppChan, stopwatch) +// InterfaceDelSPD implements IPSec handler. +func (handler *IPSecVppHandler) InterfaceDelSPD(spdID, swIfIdx uint32) error { + return handler.interfaceAddDelSpd(spdID, swIfIdx, false) } -func spdAddDelEntry(spdID, saID uint32, spd *ipsec.SecurityPolicyDatabases_SPD_PolicyEntry, isAdd bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +func (handler *IPSecVppHandler) spdAddDelEntry(spdID, saID uint32, spd *ipsec.SecurityPolicyDatabases_SPD_PolicyEntry, isAdd bool) error { defer func(t time.Time) { - stopwatch.TimeLog(ipsec_api.IpsecSpdAddDelEntry{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(ipsec_api.IpsecSpdAddDelEntry{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &ipsec_api.IpsecSpdAddDelEntry{ @@ -207,13 +180,13 @@ func spdAddDelEntry(spdID, saID uint32, spd *ipsec.SecurityPolicyDatabases_SPD_P return err } if isIPv6 { - req.IsIpv6 = 1 + req.IsIPv6 = 1 req.RemoteAddressStart = net.ParseIP(spd.RemoteAddrStart).To16() req.RemoteAddressStop = net.ParseIP(spd.RemoteAddrStop).To16() req.LocalAddressStart = net.ParseIP(spd.LocalAddrStart).To16() req.LocalAddressStop = net.ParseIP(spd.LocalAddrStop).To16() } else { - req.IsIpv6 = 0 + req.IsIPv6 = 0 req.RemoteAddressStart = net.ParseIP(spd.RemoteAddrStart).To4() req.RemoteAddressStop = net.ParseIP(spd.RemoteAddrStop).To4() req.LocalAddressStart = net.ParseIP(spd.LocalAddrStart).To4() @@ -225,31 +198,30 @@ func spdAddDelEntry(spdID, saID uint32, spd *ipsec.SecurityPolicyDatabases_SPD_P req.LocalAddressStart = net.ParseIP("0.0.0.0").To4() req.LocalAddressStop = net.ParseIP("255.255.255.255").To4() } - reply := &ipsec_api.IpsecSpdAddDelEntryReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return nil } -// AddSPDEntry adds SPD policy entry to VPP via binary API -func AddSPDEntry(spdID, saID uint32, spd *ipsec.SecurityPolicyDatabases_SPD_PolicyEntry, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return spdAddDelEntry(spdID, saID, spd, true, vppChan, stopwatch) +// AddSPDEntry implements IPSec handler. +func (handler *IPSecVppHandler) AddSPDEntry(spdID, saID uint32, spd *ipsec.SecurityPolicyDatabases_SPD_PolicyEntry) error { + return handler.spdAddDelEntry(spdID, saID, spd, true) } -// DelSPDEntry deletes SPD policy entry from VPP via binary API -func DelSPDEntry(spdID, saID uint32, spd *ipsec.SecurityPolicyDatabases_SPD_PolicyEntry, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return spdAddDelEntry(spdID, saID, spd, false, vppChan, stopwatch) +// DelSPDEntry implements IPSec handler. +func (handler *IPSecVppHandler) DelSPDEntry(spdID, saID uint32, spd *ipsec.SecurityPolicyDatabases_SPD_PolicyEntry) error { + return handler.spdAddDelEntry(spdID, saID, spd, false) } -func sadAddDelEntry(saID uint32, sa *ipsec.SecurityAssociations_SA, isAdd bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +func (handler *IPSecVppHandler) sadAddDelEntry(saID uint32, sa *ipsec.SecurityAssociations_SA, isAdd bool) error { defer func(t time.Time) { - stopwatch.TimeLog(ipsec_api.IpsecSadAddDelEntry{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(ipsec_api.IpsecSadAddDelEntry{}).LogTimeEntry(time.Since(t)) }(time.Now()) cryptoKey, err := hex.DecodeString(sa.CryptoKey) @@ -283,35 +255,34 @@ func sadAddDelEntry(saID uint32, sa *ipsec.SecurityAssociations_SA, isAdd bool, return err } if isIPv6 { - req.IsTunnelIpv6 = 1 + req.IsTunnelIPv6 = 1 req.TunnelSrcAddress = net.ParseIP(sa.TunnelSrcAddr).To16() req.TunnelDstAddress = net.ParseIP(sa.TunnelDstAddr).To16() } else { - req.IsTunnelIpv6 = 0 + req.IsTunnelIPv6 = 0 req.TunnelSrcAddress = net.ParseIP(sa.TunnelSrcAddr).To4() req.TunnelDstAddress = net.ParseIP(sa.TunnelDstAddr).To4() } } - reply := &ipsec_api.IpsecSadAddDelEntryReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return nil } -// AddSAEntry adds SA to VPP via binary API -func AddSAEntry(saID uint32, sa *ipsec.SecurityAssociations_SA, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return sadAddDelEntry(saID, sa, true, vppChan, stopwatch) +// AddSAEntry implements IPSec handler. +func (handler *IPSecVppHandler) AddSAEntry(saID uint32, sa *ipsec.SecurityAssociations_SA) error { + return handler.sadAddDelEntry(saID, sa, true) } -// DelSAEntry deletes SA from VPP via binary API -func DelSAEntry(saID uint32, sa *ipsec.SecurityAssociations_SA, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return sadAddDelEntry(saID, sa, false, vppChan, stopwatch) +// DelSAEntry implements IPSec handler. +func (handler *IPSecVppHandler) DelSAEntry(saID uint32, sa *ipsec.SecurityAssociations_SA) error { + return handler.sadAddDelEntry(saID, sa, false) } func boolToUint(value bool) uint8 { diff --git a/plugins/vpp/l2plugin/bd_config.go b/plugins/vpp/l2plugin/bd_config.go index 07d881a979..462d0576bc 100644 --- a/plugins/vpp/l2plugin/bd_config.go +++ b/plugins/vpp/l2plugin/bd_config.go @@ -28,6 +28,7 @@ import ( "github.com/ligato/vpp-agent/plugins/govppmux" l2ba "github.com/ligato/vpp-agent/plugins/vpp/binapi/l2" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" + ifvppcalls "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" "github.com/ligato/vpp-agent/plugins/vpp/l2plugin/l2idx" "github.com/ligato/vpp-agent/plugins/vpp/l2plugin/vppcalls" "github.com/ligato/vpp-agent/plugins/vpp/model/l2" @@ -49,9 +50,15 @@ type BDConfigurator struct { // VPP channel vppChan govppapi.Channel + // VPP API handlers + bdHandler vppcalls.BridgeDomainVppAPI + // State notification channel notificationChan chan BridgeDomainStateMessage // Injected, do not close here + // VPP API handlers + ifHandler ifvppcalls.IfVppAPI + // Timer used to measure and store time stopwatch *measure.Stopwatch } @@ -63,13 +70,14 @@ type BridgeDomainStateMessage struct { Name string } -// GetSwIfIndexes exposes interface name-to-index mapping +// GetBdIndexes exposes interface name-to-index mapping func (plugin *BDConfigurator) GetBdIndexes() l2idx.BDIndexRW { return plugin.bdIndexes } // Init members (channels...) and start go routines. -func (plugin *BDConfigurator) Init(logger logging.PluginLogger, goVppMux govppmux.API, swIfIndexes ifaceidx.SwIfIndex, notificationChannel chan BridgeDomainStateMessage, enableStopwatch bool) (err error) { +func (plugin *BDConfigurator) Init(logger logging.PluginLogger, goVppMux govppmux.API, swIfIndexes ifaceidx.SwIfIndex, + notificationChannel chan BridgeDomainStateMessage, enableStopwatch bool) (err error) { // Logger plugin.log = logger.NewLogger("-l2-bd-conf") plugin.log.Debug("Initializing L2 Bridge domains configurator") @@ -91,14 +99,12 @@ func (plugin *BDConfigurator) Init(logger logging.PluginLogger, goVppMux govppmu // Stopwatch if enableStopwatch { - plugin.stopwatch = measure.NewStopwatch("ACLConfigurator", plugin.log) + plugin.stopwatch = measure.NewStopwatch("BDConfigurator", plugin.log) } - // Message compatibility - err = plugin.vppChan.CheckMessageCompatibility(vppcalls.BridgeDomainMessages...) - if err != nil { - return err - } + // VPP API handlers + plugin.ifHandler = ifvppcalls.NewIfVppHandler(plugin.vppChan, plugin.log, plugin.stopwatch) + plugin.bdHandler = vppcalls.NewBridgeDomainVppHandler(plugin.vppChan, plugin.ifIndexes, plugin.log, plugin.stopwatch) return nil } @@ -128,14 +134,13 @@ func (plugin *BDConfigurator) ConfigureBridgeDomain(bdConfig *l2.BridgeDomains_B plugin.bdIDSeq++ // Create bridge domain with respective index. - if err := vppcalls.VppAddBridgeDomain(bdIdx, bdConfig, plugin.vppChan, plugin.stopwatch); err != nil { + if err := plugin.bdHandler.VppAddBridgeDomain(bdIdx, bdConfig); err != nil { plugin.log.Errorf("adding bridge domain %v failed: %v", bdConfig.Name, err) return err } // Find all interfaces belonging to this bridge domain and set them up. - configuredIfs, err := vppcalls.SetInterfacesToBridgeDomain(bdConfig.Name, bdIdx, bdConfig.Interfaces, plugin.ifIndexes, plugin.log, - plugin.vppChan, plugin.stopwatch) + configuredIfs, err := plugin.bdHandler.SetInterfacesToBridgeDomain(bdConfig.Name, bdIdx, bdConfig.Interfaces, plugin.ifIndexes) if err != nil { return err } @@ -145,8 +150,7 @@ func (plugin *BDConfigurator) ConfigureBridgeDomain(bdConfig *l2.BridgeDomains_B if arpTerminationTable != nil && len(arpTerminationTable) != 0 { arpTable := bdConfig.ArpTerminationTable for _, arpEntry := range arpTable { - err := vppcalls.VppAddArpTerminationTableEntry(bdIdx, arpEntry.PhysAddress, arpEntry.IpAddress, - plugin.log, plugin.vppChan, plugin.stopwatch) + err := plugin.bdHandler.VppAddArpTerminationTableEntry(bdIdx, arpEntry.PhysAddress, arpEntry.IpAddress) if err != nil { plugin.log.Error(err) } @@ -207,13 +211,11 @@ func (plugin *BDConfigurator) ModifyBridgeDomain(newBdConfig *l2.BridgeDomains_B // Update interfaces. toSet, toUnset := plugin.calculateIfaceDiff(newBdConfig.Interfaces, oldBdConfig.Interfaces) - unConfIfs, err := vppcalls.UnsetInterfacesFromBridgeDomain(newBdConfig.Name, bdIdx, toUnset, plugin.ifIndexes, plugin.log, - plugin.vppChan, plugin.stopwatch) + unConfIfs, err := plugin.bdHandler.UnsetInterfacesFromBridgeDomain(newBdConfig.Name, bdIdx, toUnset, plugin.ifIndexes) if err != nil { return err } - newConfIfs, err := vppcalls.SetInterfacesToBridgeDomain(newBdConfig.Name, bdIdx, toSet, plugin.ifIndexes, plugin.log, - plugin.vppChan, plugin.stopwatch) + newConfIfs, err := plugin.bdHandler.SetInterfacesToBridgeDomain(newBdConfig.Name, bdIdx, toSet, plugin.ifIndexes) if err != nil { return err } @@ -223,12 +225,10 @@ func (plugin *BDConfigurator) ModifyBridgeDomain(newBdConfig *l2.BridgeDomains_B // Update ARP termination table. toAdd, toRemove := plugin.calculateARPDiff(newBdConfig.ArpTerminationTable, oldBdConfig.ArpTerminationTable) for _, entry := range toAdd { - vppcalls.VppAddArpTerminationTableEntry(bdIdx, entry.PhysAddress, entry.IpAddress, - plugin.log, plugin.vppChan, plugin.stopwatch) + plugin.bdHandler.VppAddArpTerminationTableEntry(bdIdx, entry.PhysAddress, entry.IpAddress) } for _, entry := range toRemove { - vppcalls.VppRemoveArpTerminationTableEntry(bdIdx, entry.PhysAddress, entry.IpAddress, - plugin.log, plugin.vppChan, plugin.stopwatch) + plugin.bdHandler.VppRemoveArpTerminationTableEntry(bdIdx, entry.PhysAddress, entry.IpAddress) } // Push change to bridge domain state. @@ -261,12 +261,11 @@ func (plugin *BDConfigurator) DeleteBridgeDomain(bdConfig *l2.BridgeDomains_Brid func (plugin *BDConfigurator) deleteBridgeDomain(bdConfig *l2.BridgeDomains_BridgeDomain, bdIdx uint32) error { // Unmap all interfaces from removed bridge domain. - if _, err := vppcalls.UnsetInterfacesFromBridgeDomain(bdConfig.Name, bdIdx, bdConfig.Interfaces, plugin.ifIndexes, - plugin.log, plugin.vppChan, plugin.stopwatch); err != nil { + if _, err := plugin.bdHandler.UnsetInterfacesFromBridgeDomain(bdConfig.Name, bdIdx, bdConfig.Interfaces, plugin.ifIndexes); err != nil { plugin.log.Error(err) // Try to remove bridge domain anyway } - if err := vppcalls.VppDeleteBridgeDomain(bdIdx, plugin.vppChan, plugin.stopwatch); err != nil { + if err := plugin.bdHandler.VppDeleteBridgeDomain(bdIdx); err != nil { return err } @@ -327,8 +326,7 @@ func (plugin *BDConfigurator) ResolveCreatedInterface(ifName string, ifIdx uint3 return nil } var bdIfs []*l2.BridgeDomains_BridgeDomain_Interfaces // Single-value - configuredIf, err := vppcalls.SetInterfacesToBridgeDomain(bd.Name, bdIdx, append(bdIfs, bdIf), plugin.ifIndexes, plugin.log, - plugin.vppChan, plugin.stopwatch) + configuredIf, err := plugin.bdHandler.SetInterfacesToBridgeDomain(bd.Name, bdIdx, append(bdIfs, bdIf), plugin.ifIndexes) if err != nil { return fmt.Errorf("error while assigning interface %s to bridge domain %s", ifName, bd.Name) } diff --git a/plugins/vpp/l2plugin/bd_config_test.go b/plugins/vpp/l2plugin/bd_config_test.go index 165be64312..c2c4963655 100644 --- a/plugins/vpp/l2plugin/bd_config_test.go +++ b/plugins/vpp/l2plugin/bd_config_test.go @@ -15,6 +15,8 @@ package l2plugin_test import ( + "testing" + "git.fd.io/govpp.git/adapter/mock" "git.fd.io/govpp.git/core" "github.com/ligato/cn-infra/logging" @@ -29,10 +31,9 @@ import ( "github.com/ligato/vpp-agent/plugins/vpp/model/l2" "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" - "testing" ) -func bdConfigTestInitialization(t *testing.T) (*vppcallmock.TestCtx, *core.Connection, ifaceidx.SwIfIndexRW, chan l2plugin.BridgeDomainStateMessage, *l2plugin.BDConfigurator, error) { +func bdConfigTestInitialization(t *testing.T) (*vppcallmock.TestCtx, *core.Connection, ifaceidx.SwIfIndexRW, chan l2plugin.BridgeDomainStateMessage, *l2plugin.BDConfigurator) { RegisterTestingT(t) // Initialize notification channel @@ -49,48 +50,36 @@ func bdConfigTestInitialization(t *testing.T) (*vppcallmock.TestCtx, *core.Conne // Create connection mockCtx := &vppcallmock.TestCtx{MockVpp: &mock.VppAdapter{}} connection, err := core.Connect(mockCtx.MockVpp) - - if err != nil { - return nil, nil, nil, nil, nil, err - } + Expect(err).To(BeNil()) // Create plugin logger - pluginLogger := logging.ForPlugin("testname", logrus.NewLogRegistry()) + pluginLogger := logging.ForPlugin("testname") // Test initialization bdConfiguratorPlugin := &l2plugin.BDConfigurator{} err = bdConfiguratorPlugin.Init(pluginLogger, connection, swIfIndex, notifChan, false) + Expect(err).To(BeNil()) - if err != nil { - return nil, nil, nil, nil, nil, err - } - - return mockCtx, connection, swIfIndex, notifChan, bdConfiguratorPlugin, nil + return mockCtx, connection, swIfIndex, notifChan, bdConfiguratorPlugin } -// Tests initialization and close of bridge domain configurator -func TestBDConfigurator_Init(t *testing.T) { - _, conn, _, _, plugin, err := bdConfigTestInitialization(t) - defer conn.Disconnect() - Expect(err).To(BeNil()) - - err = plugin.Close() - Expect(err).To(BeNil()) +func bdConfigTeardown(conn *core.Connection, plugin *l2plugin.BDConfigurator) { + conn.Disconnect() + Expect(plugin.Close()).To(Succeed()) + logging.DefaultRegistry.ClearRegistry() } // Tests configuration of bridge domain func TestBDConfigurator_ConfigureBridgeDomain(t *testing.T) { - ctx, conn, _, _, plugin, err := bdConfigTestInitialization(t) - defer plugin.Close() - defer conn.Disconnect() - Expect(err).To(BeNil()) + ctx, conn, _, _, plugin := bdConfigTestInitialization(t) + defer bdConfigTeardown(conn, plugin) ctx.MockVpp.MockReply(&l22.BridgeDomainAddDelReply{}) ctx.MockVpp.MockReply(&l22.BdIPMacAddDelReply{}) ctx.MockVpp.MockReply(&l22.BridgeDomainDetails{}) ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - err = plugin.ConfigureBridgeDomain(&l2.BridgeDomains_BridgeDomain{ + err := plugin.ConfigureBridgeDomain(&l2.BridgeDomains_BridgeDomain{ Name: "test", Flood: true, UnknownUnicastFlood: true, @@ -126,17 +115,15 @@ func TestBDConfigurator_ConfigureBridgeDomain(t *testing.T) { // Tests modification of bridge domain (recreating it) func TestBDConfigurator_ModifyBridgeDomainRecreate(t *testing.T) { - ctx, conn, _, _, plugin, err := bdConfigTestInitialization(t) - defer plugin.Close() - defer conn.Disconnect() - Expect(err).To(BeNil()) + ctx, conn, _, _, plugin := bdConfigTestInitialization(t) + defer bdConfigTeardown(conn, plugin) ctx.MockVpp.MockReply(&l22.BridgeDomainAddDelReply{}) ctx.MockVpp.MockReply(&l22.BdIPMacAddDelReply{}) ctx.MockVpp.MockReply(&l22.BridgeDomainDetails{}) ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - err = plugin.ModifyBridgeDomain(&l2.BridgeDomains_BridgeDomain{ + err := plugin.ModifyBridgeDomain(&l2.BridgeDomains_BridgeDomain{ Name: "test", Flood: false, UnknownUnicastFlood: false, @@ -194,17 +181,15 @@ func TestBDConfigurator_ModifyBridgeDomainRecreate(t *testing.T) { // Tests modification of bridge domain (bridge domain not found) func TestBDConfigurator_ModifyBridgeDomainNotFound(t *testing.T) { - ctx, conn, _, _, plugin, err := bdConfigTestInitialization(t) - defer plugin.Close() - defer conn.Disconnect() - Expect(err).To(BeNil()) + ctx, conn, _, _, plugin := bdConfigTestInitialization(t) + defer bdConfigTeardown(conn, plugin) ctx.MockVpp.MockReply(&l22.BridgeDomainAddDelReply{}) ctx.MockVpp.MockReply(&l22.BdIPMacAddDelReply{}) ctx.MockVpp.MockReply(&l22.BridgeDomainDetails{}) ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - err = plugin.ModifyBridgeDomain(&l2.BridgeDomains_BridgeDomain{ + err := plugin.ModifyBridgeDomain(&l2.BridgeDomains_BridgeDomain{ Name: "test", Flood: true, UnknownUnicastFlood: true, @@ -261,10 +246,8 @@ func TestBDConfigurator_ModifyBridgeDomainNotFound(t *testing.T) { // Tests modification of bridge domain (bridge domain already present) func TestBDConfigurator_ModifyBridgeDomainFound(t *testing.T) { - ctx, conn, _, _, plugin, err := bdConfigTestInitialization(t) - defer plugin.Close() - defer conn.Disconnect() - Expect(err).To(BeNil()) + ctx, conn, _, _, plugin := bdConfigTestInitialization(t) + defer bdConfigTeardown(conn, plugin) ctx.MockVpp.MockReply(&l22.BridgeDomainAddDelReply{}) ctx.MockVpp.MockReply(&l22.BdIPMacAddDelReply{}) @@ -294,7 +277,7 @@ func TestBDConfigurator_ModifyBridgeDomainFound(t *testing.T) { }, }, []string{"if0"})) - err = plugin.ModifyBridgeDomain(&l2.BridgeDomains_BridgeDomain{ + err := plugin.ModifyBridgeDomain(&l2.BridgeDomains_BridgeDomain{ Name: "test", Flood: true, UnknownUnicastFlood: true, @@ -351,10 +334,8 @@ func TestBDConfigurator_ModifyBridgeDomainFound(t *testing.T) { // Tests deletion of bridge domain func TestBDConfigurator_DeleteBridgeDomain(t *testing.T) { - ctx, conn, _, _, plugin, err := bdConfigTestInitialization(t) - defer plugin.Close() - defer conn.Disconnect() - Expect(err).To(BeNil()) + ctx, conn, _, _, plugin := bdConfigTestInitialization(t) + defer bdConfigTeardown(conn, plugin) ctx.MockVpp.MockReply(&l22.BridgeDomainAddDelReply{}) @@ -381,7 +362,7 @@ func TestBDConfigurator_DeleteBridgeDomain(t *testing.T) { }, }, []string{"if0"})) - err = plugin.DeleteBridgeDomain(&l2.BridgeDomains_BridgeDomain{ + err := plugin.DeleteBridgeDomain(&l2.BridgeDomains_BridgeDomain{ Name: "test", Flood: true, UnknownUnicastFlood: true, @@ -412,21 +393,17 @@ func TestBDConfigurator_DeleteBridgeDomain(t *testing.T) { // Tests resolving of created interface (not found) func TestBDConfigurator_ResolveCreatedInterfaceNotFound(t *testing.T) { - _, conn, _, _, plugin, err := bdConfigTestInitialization(t) - defer plugin.Close() - defer conn.Disconnect() - Expect(err).To(BeNil()) + _, conn, _, _, plugin := bdConfigTestInitialization(t) + defer bdConfigTeardown(conn, plugin) - err = plugin.ResolveCreatedInterface("test", 0) + err := plugin.ResolveCreatedInterface("test", 0) Expect(err).To(BeNil()) } // Tests resolving of created interface (present) func TestBDConfigurator_ResolveCreatedInterfaceFound(t *testing.T) { - ctx, conn, _, _, plugin, err := bdConfigTestInitialization(t) - defer plugin.Close() - defer conn.Disconnect() - Expect(err).To(BeNil()) + ctx, conn, _, _, plugin := bdConfigTestInitialization(t) + defer bdConfigTeardown(conn, plugin) ctx.MockVpp.MockReply(&l22.BridgeDomainDetails{ BdID: 1, @@ -472,7 +449,7 @@ func TestBDConfigurator_ResolveCreatedInterfaceFound(t *testing.T) { }, }, []string{"test"})) - err = plugin.ResolveCreatedInterface("test", 0) + err := plugin.ResolveCreatedInterface("test", 0) Expect(err).To(BeNil()) _, meta, found := plugin.GetBdIndexes().LookupIdx("test") @@ -483,21 +460,17 @@ func TestBDConfigurator_ResolveCreatedInterfaceFound(t *testing.T) { // Tests resolving of deleted interface (not found) func TestBDConfigurator_ResolveDeletedInterfaceNotFound(t *testing.T) { - _, conn, _, _, plugin, err := bdConfigTestInitialization(t) - defer plugin.Close() - defer conn.Disconnect() - Expect(err).To(BeNil()) + _, conn, _, _, plugin := bdConfigTestInitialization(t) + defer bdConfigTeardown(conn, plugin) - err = plugin.ResolveDeletedInterface("test") + err := plugin.ResolveDeletedInterface("test") Expect(err).To(BeNil()) } // Tests resolving of deleted interface (present) func TestBDConfigurator_ResolveDeletedInterfaceFound(t *testing.T) { - ctx, conn, _, _, plugin, err := bdConfigTestInitialization(t) - defer plugin.Close() - defer conn.Disconnect() - Expect(err).To(BeNil()) + ctx, conn, _, _, plugin := bdConfigTestInitialization(t) + defer bdConfigTeardown(conn, plugin) ctx.MockVpp.MockReply(&l22.BridgeDomainDetails{ BdID: 1, @@ -543,7 +516,7 @@ func TestBDConfigurator_ResolveDeletedInterfaceFound(t *testing.T) { }, }, []string{"test"})) - err = plugin.ResolveDeletedInterface("test") + err := plugin.ResolveDeletedInterface("test") Expect(err).To(BeNil()) _, meta, found := plugin.GetBdIndexes().LookupIdx("test") @@ -553,10 +526,8 @@ func TestBDConfigurator_ResolveDeletedInterfaceFound(t *testing.T) { // Tests configuration and modification of bridge domain with 4 interfaces func TestBDConfigurator_FourInterfacesModify(t *testing.T) { - ctx, conn, index, _, plugin, err := bdConfigTestInitialization(t) - defer plugin.Close() - defer conn.Disconnect() - Expect(err).To(BeNil()) + ctx, conn, index, _, plugin := bdConfigTestInitialization(t) + defer bdConfigTeardown(conn, plugin) // Register interfaces to index index.RegisterName("if0", 0, &interfaces.Interfaces_Interface{ @@ -620,7 +591,7 @@ func TestBDConfigurator_FourInterfacesModify(t *testing.T) { }, } - err = plugin.ConfigureBridgeDomain(bdData) + err := plugin.ConfigureBridgeDomain(bdData) Expect(err).To(BeNil()) // Check for correct metadata after creation @@ -714,10 +685,8 @@ func TestBDConfigurator_FourInterfacesModify(t *testing.T) { // Tests invalid bridge domain with 2 BVI interfaces func TestBDConfigurator_TwoBVI(t *testing.T) { - _, conn, _, _, plugin, err := bdConfigTestInitialization(t) - defer plugin.Close() - defer conn.Disconnect() - Expect(err).To(BeNil()) + _, conn, _, _, plugin := bdConfigTestInitialization(t) + defer bdConfigTeardown(conn, plugin) // Create incorrect domain bdData := &l2.BridgeDomains_BridgeDomain{ @@ -738,7 +707,7 @@ func TestBDConfigurator_TwoBVI(t *testing.T) { }, } - err = plugin.ConfigureBridgeDomain(bdData) + err := plugin.ConfigureBridgeDomain(bdData) Expect(err).To(BeNil()) // Check for missing index after failed creation diff --git a/plugins/vpp/l2plugin/bd_state.go b/plugins/vpp/l2plugin/bd_state.go index d9d03478d1..3b2495a562 100644 --- a/plugins/vpp/l2plugin/bd_state.go +++ b/plugins/vpp/l2plugin/bd_state.go @@ -20,7 +20,6 @@ import ( "time" govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/core" "github.com/ligato/cn-infra/logging" "github.com/ligato/vpp-agent/plugins/govppmux" l2_api "github.com/ligato/vpp-agent/plugins/vpp/binapi/l2" @@ -29,6 +28,11 @@ import ( "github.com/ligato/vpp-agent/plugins/vpp/model/l2" ) +// BridgeDomainStateNotification contains bridge domain state object with all data published to ETCD. +type BridgeDomainStateNotification struct { + State *l2.BridgeDomainState_BridgeDomain +} + // BridgeDomainStateUpdater holds all data required to handle bridge domain state. type BridgeDomainStateUpdater struct { log logging.Logger @@ -55,13 +59,8 @@ type BridgeDomainStateUpdater struct { bdIdxChan chan l2idx.BdChangeDto } -// BridgeDomainStateNotification contains bridge domain state object with all data published to ETCD. -type BridgeDomainStateNotification struct { - State *l2.BridgeDomainState_BridgeDomain -} - // Init bridge domain state updater. -func (plugin *BridgeDomainStateUpdater) Init(logger logging.PluginLogger, goVppMux govppmux.API, ctx context.Context, bdIndexes l2idx.BDIndex, swIfIndexes ifaceidx.SwIfIndex, +func (plugin *BridgeDomainStateUpdater) Init(ctx context.Context, logger logging.PluginLogger, goVppMux govppmux.API, bdIndexes l2idx.BDIndex, swIfIndexes ifaceidx.SwIfIndex, notificationChan chan BridgeDomainStateMessage, publishBdState func(notification *BridgeDomainStateNotification)) (err error) { // Logger plugin.log = logger.NewLogger("-l2-bd-state") @@ -84,7 +83,7 @@ func (plugin *BridgeDomainStateUpdater) Init(logger logging.PluginLogger, goVppM // Name-to-index watcher plugin.bdIdxChan = make(chan l2idx.BdChangeDto, 100) - bdIndexes.WatchNameToIdx(core.PluginName("bdplugin_bdstate"), plugin.bdIdxChan) + bdIndexes.WatchNameToIdx("bdplugin_bdstate", plugin.bdIdxChan) var childCtx context.Context childCtx, plugin.cancel = context.WithCancel(ctx) diff --git a/plugins/vpp/l2plugin/bd_state_test.go b/plugins/vpp/l2plugin/bd_state_test.go index 0c9932789b..3cc87c399d 100644 --- a/plugins/vpp/l2plugin/bd_state_test.go +++ b/plugins/vpp/l2plugin/bd_state_test.go @@ -15,6 +15,8 @@ package l2plugin_test import ( + "testing" + "git.fd.io/govpp.git/adapter/mock" "git.fd.io/govpp.git/core" "github.com/ligato/cn-infra/logging" @@ -29,10 +31,9 @@ import ( "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" "golang.org/x/net/context" - "testing" ) -func bdStateTestInitialization(t *testing.T) (*core.Connection, l2idx.BDIndexRW, ifaceidx.SwIfIndexRW, chan l2plugin.BridgeDomainStateMessage, chan *l2plugin.BridgeDomainStateNotification, error) { +func bdStateTestInitialization(t *testing.T) (*l2plugin.BridgeDomainStateUpdater, *core.Connection, l2idx.BDIndexRW, ifaceidx.SwIfIndexRW, chan l2plugin.BridgeDomainStateMessage, chan *l2plugin.BridgeDomainStateNotification) { RegisterTestingT(t) // Initialize notification channel @@ -67,37 +68,28 @@ func bdStateTestInitialization(t *testing.T) (*core.Connection, l2idx.BDIndexRW, // Create connection mockCtx := &vppcallmock.TestCtx{MockVpp: &mock.VppAdapter{}} connection, err := core.Connect(mockCtx.MockVpp) - - if err != nil { - return nil, nil, nil, nil, nil, err - } + Expect(err).To(BeNil()) // Create plugin logger - pluginLogger := logging.ForPlugin("testname", logrus.NewLogRegistry()) + pluginLogger := logging.ForPlugin("testname") // Test initialization - bdStatePlugin := &l2plugin.BridgeDomainStateUpdater{} - err = bdStatePlugin.Init(pluginLogger, connection, ctx, index, swIfIndex, notifChan, publishIfState) - - if err != nil { - return nil, nil, nil, nil, nil, err - } + plugin := &l2plugin.BridgeDomainStateUpdater{} + err = plugin.Init(ctx, pluginLogger, connection, index, swIfIndex, notifChan, publishIfState) + Expect(err).To(BeNil()) - return connection, index, swIfIndex, notifChan, publishChan, nil + return plugin, connection, index, swIfIndex, notifChan, publishChan } -// Tests initialization of bridge domain state updater -func TestBridgeDomainStateUpdater_Init(t *testing.T) { - conn, _, _, _, _, err := bdStateTestInitialization(t) - defer conn.Disconnect() - Expect(err).To(BeNil()) +func bdStateTestTeardown(plugin *l2plugin.BridgeDomainStateUpdater, conn *core.Connection) { + conn.Disconnect() + logging.DefaultRegistry.ClearRegistry() } // Tests notification processing in bridge domain state updater with zero index func TestBridgeDomainStateUpdater_watchVppNotificationsZero(t *testing.T) { - conn, _, _, notifChan, publishChan, err := bdStateTestInitialization(t) - defer conn.Disconnect() - Expect(err).To(BeNil()) + plugin, conn, _, _, notifChan, publishChan := bdStateTestInitialization(t) + defer bdStateTestTeardown(plugin, conn) // Test notifications notifChan <- l2plugin.BridgeDomainStateMessage{ @@ -114,9 +106,8 @@ func TestBridgeDomainStateUpdater_watchVppNotificationsZero(t *testing.T) { // Tests notification processing in bridge domain state updater with zero index and no name (invalid) func TestBridgeDomainStateUpdater_watchVppNotificationsZeroNoName(t *testing.T) { - conn, _, _, notifChan, publishChan, err := bdStateTestInitialization(t) - defer conn.Disconnect() - Expect(err).To(BeNil()) + plugin, conn, _, _, notifChan, publishChan := bdStateTestInitialization(t) + defer bdStateTestTeardown(plugin, conn) // Test notifications notifChan <- l2plugin.BridgeDomainStateMessage{ @@ -132,9 +123,8 @@ func TestBridgeDomainStateUpdater_watchVppNotificationsZeroNoName(t *testing.T) // Tests notification processing in bridge domain state updater func TestBridgeDomainStateUpdater_watchVppNotifications(t *testing.T) { - conn, bdIndex, swIfIndex, notifChan, publishChan, err := bdStateTestInitialization(t) - defer conn.Disconnect() - Expect(err).To(BeNil()) + plugin, conn, bdIndex, swIfIndex, notifChan, publishChan := bdStateTestInitialization(t) + defer bdStateTestTeardown(plugin, conn) // Register interface name swIfIndex.RegisterName("test", 1, &intf.Interfaces_Interface{ diff --git a/plugins/vpp/l2plugin/data_resync.go b/plugins/vpp/l2plugin/data_resync.go index bfdfce6200..7777763434 100644 --- a/plugins/vpp/l2plugin/data_resync.go +++ b/plugins/vpp/l2plugin/data_resync.go @@ -17,10 +17,7 @@ package l2plugin import ( "strings" - if_dump "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppdump" "github.com/ligato/vpp-agent/plugins/vpp/l2plugin/l2idx" - "github.com/ligato/vpp-agent/plugins/vpp/l2plugin/vppcalls" - "github.com/ligato/vpp-agent/plugins/vpp/l2plugin/vppdump" "github.com/ligato/vpp-agent/plugins/vpp/model/l2" ) @@ -38,7 +35,7 @@ func (plugin *BDConfigurator) Resync(nbBDs []*l2.BridgeDomains_BridgeDomain) err plugin.clearMapping() // Dump current state of the VPP bridge domains - vppBDs, err := vppdump.DumpBridgeDomains(plugin.vppChan, plugin.stopwatch) + vppBDs, err := plugin.bdHandler.DumpBridgeDomains() if err != nil { return err } @@ -47,7 +44,7 @@ func (plugin *BDConfigurator) Resync(nbBDs []*l2.BridgeDomains_BridgeDomain) err var wasErr error for vppBDIdx, vppBD := range vppBDs { // tag is bridge domain name (unique identifier) - tag := vppBD.Name + tag := vppBD.Bd.Name // Find NB bridge domain with the same name var nbBD *l2.BridgeDomains_BridgeDomain for _, nbBDConfig := range nbBDs { @@ -70,12 +67,12 @@ func (plugin *BDConfigurator) Resync(nbBDs []*l2.BridgeDomains_BridgeDomain) err // Bridge domain exists, validate valid, recreate := plugin.vppValidateBridgeDomainBVI(nbBD, &l2.BridgeDomains_BridgeDomain{ Name: tag, - Learn: vppBD.Learn, - Flood: vppBD.Flood, - Forward: vppBD.Forward, - UnknownUnicastFlood: vppBD.UnknownUnicastFlood, - ArpTermination: vppBD.ArpTermination, - MacAge: vppBD.MacAge, + Learn: vppBD.Bd.Learn, + Flood: vppBD.Bd.Flood, + Forward: vppBD.Bd.Forward, + UnknownUnicastFlood: vppBD.Bd.UnknownUnicastFlood, + ArpTermination: vppBD.Bd.ArpTermination, + MacAge: vppBD.Bd.MacAge, }) if !valid { plugin.log.Errorf("RESYNC bridge domain: new config %v is invalid", nbBD.Name) @@ -99,7 +96,7 @@ func (plugin *BDConfigurator) Resync(nbBDs []*l2.BridgeDomains_BridgeDomain) err // todo currently it is not possible to dump interfaces. In order to prevent BD removal, unset all available interfaces // Dump all interfaces - interfaceMap, err := if_dump.DumpInterfaces(plugin.log, plugin.vppChan, nil) + interfaceMap, err := plugin.ifHandler.DumpInterfaces() if err != nil { plugin.log.Error(err) wasErr = err @@ -109,19 +106,17 @@ func (plugin *BDConfigurator) Resync(nbBDs []*l2.BridgeDomains_BridgeDomain) err var interfacesToUnset []*l2.BridgeDomains_BridgeDomain_Interfaces for _, iface := range interfaceMap { interfacesToUnset = append(interfacesToUnset, &l2.BridgeDomains_BridgeDomain_Interfaces{ - Name: iface.Name, + Name: iface.Interface.Name, }) } // Remove interfaces from bridge domain. Attempt to unset interface which does not belong to the bridge domain // does not cause an error - if _, err := vppcalls.UnsetInterfacesFromBridgeDomain(nbBD.Name, vppBDIdx, interfacesToUnset, plugin.ifIndexes, plugin.log, - plugin.vppChan, nil); err != nil { + if _, err := plugin.bdHandler.UnsetInterfacesFromBridgeDomain(nbBD.Name, vppBDIdx, interfacesToUnset, plugin.ifIndexes); err != nil { return err } // Set all new interfaces to the bridge domain // todo there is no need to calculate diff from configured interfaces, because currently all available interfaces are set here - configuredIfs, err := vppcalls.SetInterfacesToBridgeDomain(nbBD.Name, vppBDIdx, nbBD.Interfaces, plugin.ifIndexes, plugin.log, - plugin.vppChan, nil) + configuredIfs, err := plugin.bdHandler.SetInterfacesToBridgeDomain(nbBD.Name, vppBDIdx, nbBD.Interfaces, plugin.ifIndexes) if err != nil { return err } @@ -129,8 +124,7 @@ func (plugin *BDConfigurator) Resync(nbBDs []*l2.BridgeDomains_BridgeDomain) err // todo VPP does not support ARP dump, they can be only added at this time // Resolve new ARP entries for _, arpEntry := range nbBD.ArpTerminationTable { - if err := vppcalls.VppAddArpTerminationTableEntry(vppBDIdx, arpEntry.PhysAddress, arpEntry.IpAddress, - plugin.log, plugin.vppChan, nil); err != nil { + if err := plugin.bdHandler.VppAddArpTerminationTableEntry(vppBDIdx, arpEntry.PhysAddress, arpEntry.IpAddress); err != nil { plugin.log.Error(err) wasErr = err } @@ -173,7 +167,7 @@ func (plugin *FIBConfigurator) Resync(nbFIBs []*l2.FibTable_FibEntry) error { plugin.clearMapping() // Get all FIB entries configured on the VPP - vppFIBs, err := vppdump.DumpFIBTableEntries(plugin.syncChannel, plugin.stopwatch) + vppFIBs, err := plugin.fibHandler.DumpFIBTableEntries() if err != nil { return err } @@ -189,20 +183,20 @@ func (plugin *FIBConfigurator) Resync(nbFIBs []*l2.FibTable_FibEntry) error { } // Bridge domain bdIdx, _, found := plugin.bdIndexes.LookupIdx(nbFIB.BridgeDomain) - if !found || vppFIBdata.BridgeDomainIdx != bdIdx { + if !found || vppFIBdata.Meta.BdID != bdIdx { continue } // BVI - if vppFIBdata.BridgedVirtualInterface != nbFIB.BridgedVirtualInterface { + if vppFIBdata.Fib.BridgedVirtualInterface != nbFIB.BridgedVirtualInterface { continue } // Interface swIdx, _, found := plugin.ifIndexes.LookupIdx(nbFIB.OutgoingInterface) - if !found || vppFIBdata.OutgoingInterfaceSwIfIdx != swIdx { + if !found || vppFIBdata.Meta.IfIdx != swIdx { continue } // Is static - if vppFIBdata.StaticConfig != nbFIB.StaticConfig { + if vppFIBdata.Fib.StaticConfig != nbFIB.StaticConfig { continue } @@ -215,10 +209,10 @@ func (plugin *FIBConfigurator) Resync(nbFIBs []*l2.FibTable_FibEntry) error { if exists { plugin.fibIndexes.RegisterName(vppFIBmac, plugin.fibIndexSeq, meta) plugin.fibIndexSeq++ - } else if vppFIBdata.StaticConfig { + } else if vppFIBdata.Fib.StaticConfig { // Get appropriate interface/bridge domain names - ifIdx, _, ifFound := plugin.ifIndexes.LookupName(vppFIBdata.OutgoingInterfaceSwIfIdx) - bdIdx, _, bdFound := plugin.bdIndexes.LookupName(vppFIBdata.BridgeDomainIdx) + ifIdx, _, ifFound := plugin.ifIndexes.LookupName(vppFIBdata.Meta.IfIdx) + bdIdx, _, bdFound := plugin.bdIndexes.LookupName(vppFIBdata.Meta.BdID) if !ifFound || !bdFound { // FIB entry cannot be removed without these informations and // it should be removed by the VPP @@ -269,7 +263,7 @@ func (plugin *XConnectConfigurator) Resync(nbXConns []*l2.XConnectPairs_XConnect plugin.clearMapping() // Read cross connects from the VPP - vppXConns, err := vppdump.DumpXConnectPairs(plugin.vppChan, plugin.stopwatch) + vppXConns, err := plugin.xcHandler.DumpXConnectPairs() if err != nil { return err } @@ -281,8 +275,8 @@ func (plugin *XConnectConfigurator) Resync(nbXConns []*l2.XConnectPairs_XConnect var rxIfName, txIfName string for _, nbXConn := range nbXConns { // Find receive and transmit interface - rxIfName, _, rxIfFound := plugin.ifIndexes.LookupName(vppXConn.ReceiveInterfaceSwIfIdx) - txIfName, _, txIfFound := plugin.ifIndexes.LookupName(vppXConn.TransmitInterfaceSwIfIdx) + rxIfName, _, rxIfFound := plugin.ifIndexes.LookupName(vppXConn.Meta.ReceiveInterfaceSwIfIdx) + txIfName, _, txIfFound := plugin.ifIndexes.LookupName(vppXConn.Meta.TransmitInterfaceSwIfIdx) if !rxIfFound || !txIfFound { continue } diff --git a/plugins/vpp/l2plugin/fib_config.go b/plugins/vpp/l2plugin/fib_config.go index 680434eb2d..7222c457b7 100644 --- a/plugins/vpp/l2plugin/fib_config.go +++ b/plugins/vpp/l2plugin/fib_config.go @@ -46,7 +46,7 @@ type FIBConfigurator struct { fibIndexSeq uint32 // VPP binary api call helper - vppcalls *vppcalls.L2FibVppCalls + fibHandler vppcalls.FibVppAPI // VPP channels syncChannel govppapi.Channel @@ -57,11 +57,17 @@ type FIBConfigurator struct { } // Init goroutines, mappings, channels.. -func (plugin *FIBConfigurator) Init(logger logging.PluginLogger, goVppMux govppmux.API, swIfIndexes ifaceidx.SwIfIndex, bdIndexes l2idx.BDIndex, enableStopwatch bool) (err error) { +func (plugin *FIBConfigurator) Init(logger logging.PluginLogger, goVppMux govppmux.API, swIfIndexes ifaceidx.SwIfIndex, + bdIndexes l2idx.BDIndex, enableStopwatch bool) (err error) { // Logger plugin.log = logger.NewLogger("-l2-fib-conf") plugin.log.Debug("Initializing L2 Bridge domains") + // Stopwatch + if enableStopwatch { + plugin.stopwatch = measure.NewStopwatch("FIBConfigurator", plugin.log) + } + // Mappings plugin.ifIndexes = swIfIndexes plugin.bdIndexes = bdIndexes @@ -80,21 +86,12 @@ func (plugin *FIBConfigurator) Init(logger logging.PluginLogger, goVppMux govppm return err } - // Stopwatch - if enableStopwatch { - plugin.stopwatch = measure.NewStopwatch("FIBConfigurator", plugin.log) - } - - // Message compatibility - if err := plugin.syncChannel.CheckMessageCompatibility(vppcalls.L2FibMessages...); err != nil { - return err - } - // VPP calls helper object - plugin.vppcalls = vppcalls.NewL2FibVppCalls(plugin.log, plugin.asyncChannel, plugin.stopwatch) + plugin.fibHandler = vppcalls.NewFibVppHandler(plugin.syncChannel, plugin.asyncChannel, plugin.ifIndexes, + plugin.bdIndexes, plugin.log, plugin.stopwatch) // FIB reply watcher - go plugin.vppcalls.WatchFIBReplies() + go plugin.fibHandler.WatchFIBReplies() return nil } @@ -152,7 +149,7 @@ func (plugin *FIBConfigurator) Add(fib *l2.FibTable_FibEntry, callback func(erro } plugin.log.Debugf("Configuring FIB entry %s for bridge domain %s and interface %s", fib.PhysAddress, bdIdx, ifIdx) - return plugin.vppcalls.Add(fib.PhysAddress, bdIdx, ifIdx, fib.BridgedVirtualInterface, fib.StaticConfig, + return plugin.fibHandler.Add(fib.PhysAddress, bdIdx, ifIdx, fib.BridgedVirtualInterface, fib.StaticConfig, func(err error) { // Register plugin.fibIndexes.RegisterName(fib.PhysAddress, plugin.fibIndexSeq, fib) @@ -185,7 +182,7 @@ func (plugin *FIBConfigurator) Modify(oldFib *l2.FibTable_FibEntry, plugin.log.Debugf("FIB %s cannot be removed, bridge domain %s no longer exists", oldFib.PhysAddress, oldFib.BridgeDomain) } else { - if err := plugin.vppcalls.Delete(oldFib.PhysAddress, oldBdIdx, oldIfIdx, func(err error) { + if err := plugin.fibHandler.Delete(oldFib.PhysAddress, oldBdIdx, oldIfIdx, func(err error) { plugin.fibIndexes.UnregisterName(oldFib.PhysAddress) callback(err) }); err != nil { @@ -201,7 +198,7 @@ func (plugin *FIBConfigurator) Modify(oldFib *l2.FibTable_FibEntry, return nil } - return plugin.vppcalls.Add(newFib.PhysAddress, bdIdx, ifIdx, newFib.BridgedVirtualInterface, newFib.StaticConfig, + return plugin.fibHandler.Add(newFib.PhysAddress, bdIdx, ifIdx, newFib.BridgedVirtualInterface, newFib.StaticConfig, func(err error) { plugin.fibIndexes.RegisterName(oldFib.PhysAddress, plugin.fibIndexSeq, newFib) plugin.fibIndexSeq++ @@ -232,7 +229,7 @@ func (plugin *FIBConfigurator) Delete(fib *l2.FibTable_FibEntry, callback func(e plugin.fibIndexes.UnregisterName(fib.PhysAddress) plugin.log.Debugf("FIB %s removed from mappings", fib.PhysAddress) - return plugin.vppcalls.Delete(fib.PhysAddress, bdIdx, ifIdx, func(err error) { + return plugin.fibHandler.Delete(fib.PhysAddress, bdIdx, ifIdx, func(err error) { callback(err) }) } @@ -292,7 +289,7 @@ func (plugin *FIBConfigurator) ResolveUpdatedBridgeDomain(bdName string, bdID ui return nil } -// ResolveDeletedInterface handles removed bridge domain. In that case, FIB entry remains on the VPP but it is not possible +// ResolveDeletedBridgeDomain handles removed bridge domain. In that case, FIB entry remains on the VPP but it is not possible // to delete it. func (plugin *FIBConfigurator) ResolveDeletedBridgeDomain(bdName string, bdID uint32, callback func(error)) error { plugin.log.Infof("FIB configurator: resolving unregistered bridge domain %s", bdName) @@ -310,8 +307,8 @@ func (plugin *FIBConfigurator) ResolveDeletedBridgeDomain(bdName string, bdID ui func (plugin *FIBConfigurator) resolveRegisteredItem(callback func(error)) error { var wasErr error // First, remove FIBs which cannot be removed due to missing interface - for _, cachedFibId := range plugin.delCacheIndexes.GetMapping().ListNames() { - _, fibData, found := plugin.delCacheIndexes.LookupIdx(cachedFibId) + for _, cachedFibID := range plugin.delCacheIndexes.GetMapping().ListNames() { + _, fibData, found := plugin.delCacheIndexes.LookupIdx(cachedFibID) if !found || fibData == nil { // Should not happen continue @@ -321,22 +318,22 @@ func (plugin *FIBConfigurator) resolveRegisteredItem(callback func(error)) error if cached { continue } - if err := plugin.vppcalls.Delete(cachedFibId, bdIdx, ifIdx, func(err error) { - plugin.log.Debugf("Deleting cached obsolete FIB %s", cachedFibId) + if err := plugin.fibHandler.Delete(cachedFibID, bdIdx, ifIdx, func(err error) { + plugin.log.Debugf("Deleting cached obsolete FIB %s", cachedFibID) // Handle registration - plugin.fibIndexes.UnregisterName(cachedFibId) + plugin.fibIndexes.UnregisterName(cachedFibID) callback(err) }); err != nil { plugin.log.Error(err) wasErr = err } - plugin.delCacheIndexes.UnregisterName(cachedFibId) - plugin.log.Debugf("FIB %s removed from 'del' cache", cachedFibId) + plugin.delCacheIndexes.UnregisterName(cachedFibID) + plugin.log.Debugf("FIB %s removed from 'del' cache", cachedFibID) } // Configure un-configurable FIBs - for _, cachedFibId := range plugin.addCacheIndexes.GetMapping().ListNames() { - _, fibData, found := plugin.addCacheIndexes.LookupIdx(cachedFibId) + for _, cachedFibID := range plugin.addCacheIndexes.GetMapping().ListNames() { + _, fibData, found := plugin.addCacheIndexes.LookupIdx(cachedFibID) if !found || fibData == nil { // Should not happen continue @@ -346,18 +343,18 @@ func (plugin *FIBConfigurator) resolveRegisteredItem(callback func(error)) error if cached { continue } - if err := plugin.vppcalls.Add(cachedFibId, bdIdx, ifIdx, fibData.BridgedVirtualInterface, fibData.StaticConfig, func(err error) { - plugin.log.Infof("Configuring cached FIB %s", cachedFibId) + if err := plugin.fibHandler.Add(cachedFibID, bdIdx, ifIdx, fibData.BridgedVirtualInterface, fibData.StaticConfig, func(err error) { + plugin.log.Infof("Configuring cached FIB %s", cachedFibID) // Handle registration - plugin.fibIndexes.RegisterName(cachedFibId, plugin.fibIndexSeq, fibData) + plugin.fibIndexes.RegisterName(cachedFibID, plugin.fibIndexSeq, fibData) plugin.fibIndexSeq++ callback(err) }); err != nil { plugin.log.Error(err) wasErr = err } - plugin.addCacheIndexes.UnregisterName(cachedFibId) - plugin.log.Debugf("FIB %s removed from 'add' cache", cachedFibId) + plugin.addCacheIndexes.UnregisterName(cachedFibID) + plugin.log.Debugf("FIB %s removed from 'add' cache", cachedFibID) } return wasErr diff --git a/plugins/vpp/l2plugin/fib_config_test.go b/plugins/vpp/l2plugin/fib_config_test.go index 22b402a136..d03282330d 100644 --- a/plugins/vpp/l2plugin/fib_config_test.go +++ b/plugins/vpp/l2plugin/fib_config_test.go @@ -22,7 +22,6 @@ import ( "git.fd.io/govpp.git/adapter/mock" "git.fd.io/govpp.git/core" "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/idxvpp/nametoidx" l2Api "github.com/ligato/vpp-agent/plugins/vpp/binapi/l2" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" @@ -46,28 +45,6 @@ func (m *mockCallback) Done(err error) { /* FIB configurator init and close */ -// Test init function -func TestFIBConnectConfiguratorInit(t *testing.T) { - var err error - // Setup - RegisterTestingT(t) - ctx := &vppcallmock.TestCtx{ - MockVpp: &mock.VppAdapter{}, - } - connection, _ := core.Connect(ctx.MockVpp) - defer connection.Disconnect() - plugin := &l2plugin.FIBConfigurator{} - // Test init - log := logging.ForPlugin("test-log", logrus.NewLogRegistry()) - ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "if", ifaceidx.IndexMetadata)) - bdIndexes := l2idx.NewBDIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "if", ifaceidx.IndexMetadata)) - err = plugin.Init(log, connection, ifIndexes, bdIndexes, false) - Expect(err).To(BeNil()) - // Test close - err = plugin.Close() - Expect(err).To(BeNil()) -} - /* FIB configurator test cases */ // Configure FIB entry with all initial data available @@ -1130,31 +1107,29 @@ func fibTestSetup(t *testing.T) (*vppcallmock.TestCtx, *core.Connection, *l2plug connection, err := core.Connect(ctx.MockVpp) Expect(err).ShouldNot(HaveOccurred()) // Logger - log := logging.ForPlugin("test-log", logrus.NewLogRegistry()) + log := logging.ForPlugin("test-log") log.SetLevel(logging.DebugLevel) // Interface indices swIfIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(log, "fib-if", nil)) bdIndexes := l2idx.NewBDIndex(nametoidx.NewNameToIdx(log, "fib-bd", nil)) // Configurator plugin := &l2plugin.FIBConfigurator{} - err = plugin.Init(logging.ForPlugin("test-log", logrus.NewLogRegistry()), connection, swIfIndexes, bdIndexes, false) + err = plugin.Init(logging.ForPlugin("test-log"), connection, swIfIndexes, bdIndexes, false) Expect(err).To(BeNil()) - // Callback return ctx, connection, plugin, swIfIndexes, bdIndexes } func getCallback(buffer int) *mockCallback { - c := make(chan error, buffer) return &mockCallback{ - doneChan: c, + doneChan: make(chan error, buffer), } } func fibTestTeardown(connection *core.Connection, plugin *l2plugin.FIBConfigurator) { connection.Disconnect() - err := plugin.Close() - Expect(err).To(BeNil()) + Expect(plugin.Close()).To(BeNil()) + logging.DefaultRegistry.ClearRegistry() } /* FIB Test Data */ diff --git a/plugins/vpp/l2plugin/l2idx/bd_index.go b/plugins/vpp/l2plugin/l2idx/bd_index.go index caae04d35c..7631437da2 100644 --- a/plugins/vpp/l2plugin/l2idx/bd_index.go +++ b/plugins/vpp/l2plugin/l2idx/bd_index.go @@ -15,7 +15,6 @@ package l2idx import ( - "github.com/ligato/cn-infra/core" "github.com/ligato/vpp-agent/idxvpp" "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/vpp/model/l2" @@ -39,7 +38,7 @@ type BDIndex interface { LookupConfiguredIfsForBd(bdName string) ([]string, bool) // WatchNameToIdx allows to subscribe for watching changes in bdIndex mapping - WatchNameToIdx(subscriber core.PluginName, pluginChannel chan BdChangeDto) + WatchNameToIdx(subscriber string, pluginChannel chan BdChangeDto) } // BDIndexRW is mapping between indices (used internally in VPP) and Bridge Domain names. @@ -65,14 +64,14 @@ type bdIndex struct { mapping idxvpp.NameToIdxRW } -// ChangeDto represents an item sent through watch channel in bdIndex. +// BdChangeDto represents an item sent through watch channel in bdIndex. // In contrast to NameToIdxDto, it contains typed metadata. type BdChangeDto struct { idxvpp.NameToIdxDtoWithoutMeta Metadata *BdMetadata } -// Bridge domain metadata consists from base bridge domain data and a list of interfaces which were +// BdMetadata is bridge domain metadata and consists from base bridge domain data and a list of interfaces which were // (according to L2 bridge domain configurator) already configured as a part of bridge domain type BdMetadata struct { BridgeDomain *l2.BridgeDomains_BridgeDomain @@ -191,7 +190,7 @@ func (bdi *bdIndex) LookupConfiguredIfsForBd(bdName string) ([]string, bool) { } // WatchNameToIdx allows to subscribe for watching changes in bdIndex mapping. -func (bdi *bdIndex) WatchNameToIdx(subscriber core.PluginName, pluginChannel chan BdChangeDto) { +func (bdi *bdIndex) WatchNameToIdx(subscriber string, pluginChannel chan BdChangeDto) { ch := make(chan idxvpp.NameToIdxDto) bdi.mapping.Watch(subscriber, nametoidx.ToChan(ch)) go func() { diff --git a/plugins/vpp/l2plugin/l2idx/cache_bd.go b/plugins/vpp/l2plugin/l2idx/cache_bd.go index 6ef6ee9ab9..5e1b624182 100644 --- a/plugins/vpp/l2plugin/l2idx/cache_bd.go +++ b/plugins/vpp/l2plugin/l2idx/cache_bd.go @@ -30,7 +30,7 @@ func Cache(watcher datasync.KeyValProtoWatcher) BDIndex { bdIdx := NewBDIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), resyncName, IndexMetadata)) helper := cacheutil.CacheHelper{ - Prefix: l2.BridgeDomainKeyPrefix(), + Prefix: l2.BdPrefix, IDX: bdIdx.GetMapping(), DataPrototype: &l2.BridgeDomains_BridgeDomain{}, ParseName: l2.ParseBDNameFromKey} diff --git a/plugins/vpp/l2plugin/l2idx/doc.go b/plugins/vpp/l2plugin/l2idx/doc.go index 422504073e..240a205bf2 100644 --- a/plugins/vpp/l2plugin/l2idx/doc.go +++ b/plugins/vpp/l2plugin/l2idx/doc.go @@ -1,3 +1,3 @@ -// Package bdidx implements name-to-index mapping registry and cache +// Package l2idx implements name-to-index mapping registry and cache // for bridge-domains. package l2idx diff --git a/plugins/vpp/l2plugin/l2idx/fib_index.go b/plugins/vpp/l2plugin/l2idx/fib_index.go index 3d13634e31..82ceb7f04a 100644 --- a/plugins/vpp/l2plugin/l2idx/fib_index.go +++ b/plugins/vpp/l2plugin/l2idx/fib_index.go @@ -15,7 +15,6 @@ package l2idx import ( - "github.com/ligato/cn-infra/core" "github.com/ligato/vpp-agent/idxvpp" "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/vpp/model/l2" @@ -33,7 +32,7 @@ type FIBIndex interface { LookupName(idx uint32) (name string, metadata *l2.FibTable_FibEntry, exists bool) // WatchNameToIdx allows to subscribe for watching changes in fibIndex mapping - WatchNameToIdx(subscriber core.PluginName, pluginChannel chan FibChangeDto) + WatchNameToIdx(subscriber string, pluginChannel chan FibChangeDto) } // FIBIndexRW is mapping between indices (used internally in VPP) and FIB entries. @@ -116,7 +115,7 @@ func (fib *fibIndex) LookupName(idx uint32) (name string, metadata *l2.FibTable_ } // WatchNameToIdx allows to subscribe for watching changes in fibIndex mapping. -func (fib *fibIndex) WatchNameToIdx(subscriber core.PluginName, pluginChannel chan FibChangeDto) { +func (fib *fibIndex) WatchNameToIdx(subscriber string, pluginChannel chan FibChangeDto) { ch := make(chan idxvpp.NameToIdxDto) fib.mapping.Watch(subscriber, nametoidx.ToChan(ch)) go func() { diff --git a/plugins/vpp/l2plugin/l2idx/xc_index.go b/plugins/vpp/l2plugin/l2idx/xc_index.go index 12ed17318c..f1dc507301 100644 --- a/plugins/vpp/l2plugin/l2idx/xc_index.go +++ b/plugins/vpp/l2plugin/l2idx/xc_index.go @@ -15,7 +15,6 @@ package l2idx import ( - "github.com/ligato/cn-infra/core" "github.com/ligato/vpp-agent/idxvpp" "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/vpp/model/l2" @@ -33,7 +32,7 @@ type XcIndex interface { LookupName(idx uint32) (name string, metadata *l2.XConnectPairs_XConnectPair, exists bool) // WatchNameToIdx allows to subscribe for watching changes in xcIndex mapping - WatchNameToIdx(subscriber core.PluginName, pluginChannel chan XcChangeDto) + WatchNameToIdx(subscriber string, pluginChannel chan XcChangeDto) } // XcIndexRW is mapping between indices (used internally in VPP) and cross connect entries. @@ -116,7 +115,7 @@ func (xc *xcIndex) LookupName(idx uint32) (name string, metadata *l2.XConnectPai } // WatchNameToIdx allows to subscribe for watching changes in xcIndex mapping. -func (xc *xcIndex) WatchNameToIdx(subscriber core.PluginName, pluginChannel chan XcChangeDto) { +func (xc *xcIndex) WatchNameToIdx(subscriber string, pluginChannel chan XcChangeDto) { ch := make(chan idxvpp.NameToIdxDto) xc.mapping.Watch(subscriber, nametoidx.ToChan(ch)) go func() { diff --git a/plugins/vpp/l2plugin/vppcalls/api_vppcalls.go b/plugins/vpp/l2plugin/vppcalls/api_vppcalls.go new file mode 100644 index 0000000000..cb2cb69624 --- /dev/null +++ b/plugins/vpp/l2plugin/vppcalls/api_vppcalls.go @@ -0,0 +1,170 @@ +// Copyright (c) 2017 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vppcalls + +import ( + govppapi "git.fd.io/govpp.git/api" + "github.com/ligato/cn-infra/logging" + "github.com/ligato/cn-infra/logging/measure" + "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" + "github.com/ligato/vpp-agent/plugins/vpp/l2plugin/l2idx" + "github.com/ligato/vpp-agent/plugins/vpp/model/l2" +) + +// BridgeDomainVppAPI provides methods for managing bridge domains +type BridgeDomainVppAPI interface { + BridgeDomainVppWrite + BridgeDomainVppRead +} + +// BridgeDomainVppWrite provides write methods for bridge domains +type BridgeDomainVppWrite interface { + // VppAddBridgeDomain adds new bridge domain. + VppAddBridgeDomain(bdIdx uint32, bd *l2.BridgeDomains_BridgeDomain) error + // VppDeleteBridgeDomain removes existing bridge domain. + VppDeleteBridgeDomain(bdIdx uint32) error + // SetInterfacesToBridgeDomain attempts to set all provided interfaces to bridge domain. It returns a list of interfaces + // which were successfully set. + SetInterfacesToBridgeDomain(bdName string, bdIdx uint32, bdIfs []*l2.BridgeDomains_BridgeDomain_Interfaces, + swIfIndices ifaceidx.SwIfIndex) (ifs []string, wasErr error) + // UnsetInterfacesFromBridgeDomain removes all interfaces from bridge domain. It returns a list of interfaces + // which were successfully unset. + UnsetInterfacesFromBridgeDomain(bdName string, bdIdx uint32, bdIfs []*l2.BridgeDomains_BridgeDomain_Interfaces, + swIfIndices ifaceidx.SwIfIndex) (ifs []string, wasErr error) + // VppAddArpTerminationTableEntry creates ARP termination entry for bridge domain. + VppAddArpTerminationTableEntry(bdID uint32, mac string, ip string) error + // VppRemoveArpTerminationTableEntry removes ARP termination entry from bridge domain + VppRemoveArpTerminationTableEntry(bdID uint32, mac string, ip string) error +} + +// BridgeDomainVppRead provides read methods for bridge domains +type BridgeDomainVppRead interface { + // DumpBridgeDomainIDs lists all configured bridge domains. Auxiliary method for LookupFIBEntries. + // returns list of bridge domain IDs (BD IDs). First element of returned slice is 0. It is default BD to which all + // interfaces belong + DumpBridgeDomainIDs() ([]uint32, error) + // DumpBridgeDomains dumps VPP bridge domain data into the northbound API data structure + // map indexed by bridge domain ID. + // + // LIMITATIONS: + // - not able to dump ArpTerminationTable - missing binary API + // + DumpBridgeDomains() (map[uint32]*BridgeDomainDetails, error) +} + +// FibVppAPI provides methods for managing FIBs +type FibVppAPI interface { + FibVppWrite + FibVppRead +} + +// FibVppWrite provides write methods for FIBs +type FibVppWrite interface { + // Add creates L2 FIB table entry. + Add(mac string, bdID uint32, ifIdx uint32, bvi bool, static bool, callback func(error)) error + // Delete removes existing L2 FIB table entry. + Delete(mac string, bdID uint32, ifIdx uint32, callback func(error)) error +} + +// FibVppRead provides read methods for FIBs +type FibVppRead interface { + // DumpFIBTableEntries dumps VPP FIB table entries into the northbound API data structure + // map indexed by destination MAC address. + DumpFIBTableEntries() (map[string]*FibTableDetails, error) + // WatchFIBReplies handles L2 FIB add/del requests + WatchFIBReplies() +} + +// XConnectVppAPI provides methods for managing cross connects +type XConnectVppAPI interface { + XConnectVppWrite + XConnectVppRead +} + +// XConnectVppWrite provides write methods for cross connects +type XConnectVppWrite interface { + // AddL2XConnect creates xConnect between two existing interfaces. + AddL2XConnect(rxIfIdx uint32, txIfIdx uint32) error + // DeleteL2XConnect removes xConnect between two interfaces. + DeleteL2XConnect(rxIfIdx uint32, txIfIdx uint32) error +} + +// XConnectVppRead provides read methods for cross connects +type XConnectVppRead interface { + // DumpXConnectPairs dumps VPP xconnect pair data into the northbound API data structure + // map indexed by rx interface index. + DumpXConnectPairs() (map[uint32]*XConnectDetails, error) +} + +// BridgeDomainVppHandler is accessor for bridge domain-related vppcalls methods +type BridgeDomainVppHandler struct { + stopwatch *measure.Stopwatch + callsChannel govppapi.Channel + ifIndexes ifaceidx.SwIfIndex + log logging.Logger +} + +// FibVppHandler is accessor for FIB-related vppcalls methods +type FibVppHandler struct { + stopwatch *measure.Stopwatch + syncCallsChannel govppapi.Channel + asyncCallsChannel govppapi.Channel + requestChan chan *FibLogicalReq + ifIndexes ifaceidx.SwIfIndex + bdIndexes l2idx.BDIndex + log logging.Logger +} + +// XConnectVppHandler is accessor for cross-connect-related vppcalls methods +type XConnectVppHandler struct { + stopwatch *measure.Stopwatch + callsChannel govppapi.Channel + ifIndexes ifaceidx.SwIfIndex + log logging.Logger +} + +// NewBridgeDomainVppHandler creates new instance of bridge domain vppcalls handler +func NewBridgeDomainVppHandler(callsChan govppapi.Channel, ifIndexes ifaceidx.SwIfIndex, log logging.Logger, stopwatch *measure.Stopwatch) *BridgeDomainVppHandler { + return &BridgeDomainVppHandler{ + callsChannel: callsChan, + stopwatch: stopwatch, + ifIndexes: ifIndexes, + log: log, + } +} + +// NewFibVppHandler creates new instance of FIB vppcalls handler +func NewFibVppHandler(syncChan, asyncChan govppapi.Channel, ifIndexes ifaceidx.SwIfIndex, bdIndexes l2idx.BDIndex, + log logging.Logger, stopwatch *measure.Stopwatch) *FibVppHandler { + return &FibVppHandler{ + syncCallsChannel: syncChan, + asyncCallsChannel: asyncChan, + requestChan: make(chan *FibLogicalReq), + stopwatch: stopwatch, + ifIndexes: ifIndexes, + bdIndexes: bdIndexes, + log: log, + } +} + +// NewXConnectVppHandler creates new instance of cross connect vppcalls handler +func NewXConnectVppHandler(callsChan govppapi.Channel, ifIndexes ifaceidx.SwIfIndex, log logging.Logger, stopwatch *measure.Stopwatch) *XConnectVppHandler { + return &XConnectVppHandler{ + callsChannel: callsChan, + stopwatch: stopwatch, + ifIndexes: ifIndexes, + log: log, + } +} diff --git a/plugins/vpp/l2plugin/vppcalls/arp_term_vppcalls.go b/plugins/vpp/l2plugin/vppcalls/arp_term_vppcalls.go index 942c7eb0a2..59cac9bdb4 100644 --- a/plugins/vpp/l2plugin/vppcalls/arp_term_vppcalls.go +++ b/plugins/vpp/l2plugin/vppcalls/arp_term_vppcalls.go @@ -19,20 +19,19 @@ import ( "net" "time" - govppapi "git.fd.io/govpp.git/api" "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/cn-infra/utils/addrs" l2ba "github.com/ligato/vpp-agent/plugins/vpp/binapi/l2" ) -func callBdIPMacAddDel(isAdd bool, bdID uint32, mac string, ip string, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +func (handler *BridgeDomainVppHandler) callBdIPMacAddDel(isAdd bool, bdID uint32, mac string, ip string) error { defer func(t time.Time) { - stopwatch.TimeLog(l2ba.BdIPMacAddDel{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(l2ba.BdIPMacAddDel{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &l2ba.BdIPMacAddDel{ - BdID: bdID, + BdID: bdID, + IsAdd: boolToUint(isAdd), } macAddr, err := net.ParseMAC(mac) @@ -47,56 +46,47 @@ func callBdIPMacAddDel(isAdd bool, bdID uint32, mac string, ip string, vppChan g } ipAddr := net.ParseIP(ip) if isIpv6 { - req.IsIpv6 = 1 + req.IsIPv6 = 1 req.IPAddress = []byte(ipAddr.To16()) } else { - req.IsIpv6 = 0 + req.IsIPv6 = 0 req.IPAddress = []byte(ipAddr.To4()) } - - if isAdd { - req.IsAdd = 1 - } else { - req.IsAdd = 0 - } - reply := &l2ba.BdIPMacAddDelReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return nil } -// VppAddArpTerminationTableEntry creates ARP termination entry for bridge domain. -func VppAddArpTerminationTableEntry(bdID uint32, mac string, ip string, log logging.Logger, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - log.Info("Adding ARP termination entry") +// VppAddArpTerminationTableEntry implements bridge domain handler. +func (handler *BridgeDomainVppHandler) VppAddArpTerminationTableEntry(bdID uint32, mac string, ip string) error { + handler.log.Info("Adding ARP termination entry") - err := callBdIPMacAddDel(true, bdID, mac, ip, vppChan, stopwatch) + err := handler.callBdIPMacAddDel(true, bdID, mac, ip) if err != nil { return err } - log.WithFields(logging.Fields{"bdID": bdID, "MAC": mac, "IP": ip}). - Debug("ARP termination entry added") + handler.log.WithFields(logging.Fields{"bdID": bdID, "MAC": mac, "IP": ip}).Debug("ARP termination entry added") return nil } -// VppRemoveArpTerminationTableEntry removes ARP termination entry from bridge domain -func VppRemoveArpTerminationTableEntry(bdID uint32, mac string, ip string, log logging.Logger, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - log.Info("Removing ARP termination entry") +// VppRemoveArpTerminationTableEntry implements bridge domain handler. +func (handler *BridgeDomainVppHandler) VppRemoveArpTerminationTableEntry(bdID uint32, mac string, ip string) error { + handler.log.Info("Removing ARP termination entry") - err := callBdIPMacAddDel(false, bdID, mac, ip, vppChan, stopwatch) + err := handler.callBdIPMacAddDel(false, bdID, mac, ip) if err != nil { return err } - log.WithFields(logging.Fields{"bdID": bdID, "MAC": mac, "IP": ip}). - Debug("ARP termination entry removed") + handler.log.WithFields(logging.Fields{"bdID": bdID, "MAC": mac, "IP": ip}).Debug("ARP termination entry removed") return nil } diff --git a/plugins/vpp/l2plugin/vppcalls/arp_term_vppcalls_test.go b/plugins/vpp/l2plugin/vppcalls/arp_term_vppcalls_test.go index 79bd7b9a49..5024e353c5 100644 --- a/plugins/vpp/l2plugin/vppcalls/arp_term_vppcalls_test.go +++ b/plugins/vpp/l2plugin/vppcalls/arp_term_vppcalls_test.go @@ -17,126 +17,104 @@ package vppcalls_test import ( "testing" - "github.com/ligato/cn-infra/logging/logrus" l2ba "github.com/ligato/vpp-agent/plugins/vpp/binapi/l2" - "github.com/ligato/vpp-agent/plugins/vpp/l2plugin/vppcalls" - "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" ) -var dummyLogger = logrus.NewLogger("dummy") - func TestVppAddArpTerminationTableEntry(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, _ := bdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&l2ba.BdIPMacAddDelReply{}) - err := vppcalls.VppAddArpTerminationTableEntry( - 4, "FF:FF:FF:FF:FF:FF", "192.168.4.4", - dummyLogger, ctx.MockChannel, nil) + err := bdHandler.VppAddArpTerminationTableEntry( + 4, "FF:FF:FF:FF:FF:FF", "192.168.4.4") Expect(err).ShouldNot(HaveOccurred()) Expect(ctx.MockChannel.Msg).To(Equal(&l2ba.BdIPMacAddDel{ BdID: 4, IsAdd: 1, - IsIpv6: 0, + IsIPv6: 0, IPAddress: []byte{192, 168, 4, 4}, MacAddress: []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, })) } func TestVppAddArpTerminationTableEntryIPv6(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, _ := bdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&l2ba.BdIPMacAddDelReply{}) - err := vppcalls.VppAddArpTerminationTableEntry( - 4, "FF:FF:FF:FF:FF:FF", "2001:db9::54", - dummyLogger, ctx.MockChannel, nil) + err := bdHandler.VppAddArpTerminationTableEntry(4, "FF:FF:FF:FF:FF:FF", "2001:db9::54") Expect(err).ShouldNot(HaveOccurred()) Expect(ctx.MockChannel.Msg).To(Equal(&l2ba.BdIPMacAddDel{ BdID: 4, IsAdd: 1, - IsIpv6: 1, + IsIPv6: 1, IPAddress: []byte{32, 1, 13, 185, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84}, MacAddress: []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, })) } func TestVppRemoveArpTerminationTableEntry(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, _ := bdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&l2ba.BdIPMacAddDelReply{}) - err := vppcalls.VppRemoveArpTerminationTableEntry( - 4, "FF:FF:FF:FF:FF:FF", "192.168.4.4", - dummyLogger, ctx.MockChannel, nil) + err := bdHandler.VppRemoveArpTerminationTableEntry(4, "FF:FF:FF:FF:FF:FF", "192.168.4.4") Expect(err).ShouldNot(HaveOccurred()) Expect(ctx.MockChannel.Msg).To(Equal(&l2ba.BdIPMacAddDel{ BdID: 4, IsAdd: 0, - IsIpv6: 0, + IsIPv6: 0, IPAddress: []byte{192, 168, 4, 4}, MacAddress: []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, })) } func TestVppArpTerminationTableEntryMacError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, _ := bdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&l2ba.BdIPMacAddDelReply{}) - err := vppcalls.VppAddArpTerminationTableEntry( - 4, "in:va:li:d:ma:c", "192.168.4.4", - dummyLogger, ctx.MockChannel, nil) + err := bdHandler.VppAddArpTerminationTableEntry(4, "in:va:li:d:ma:c", "192.168.4.4") Expect(err).Should(HaveOccurred()) - err = vppcalls.VppRemoveArpTerminationTableEntry( - 4, "in:va:li:d:ma:c", "192.168.4.4", - dummyLogger, ctx.MockChannel, nil) + err = bdHandler.VppRemoveArpTerminationTableEntry(4, "in:va:li:d:ma:c", "192.168.4.4") Expect(err).Should(HaveOccurred()) } func TestVppArpTerminationTableEntryIpError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, _ := bdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&l2ba.BdIPMacAddDelReply{}) - err := vppcalls.VppAddArpTerminationTableEntry( - 4, "FF:FF:FF:FF:FF:FF", "", - dummyLogger, ctx.MockChannel, nil) + err := bdHandler.VppAddArpTerminationTableEntry(4, "FF:FF:FF:FF:FF:FF", "") Expect(err).Should(HaveOccurred()) - err = vppcalls.VppRemoveArpTerminationTableEntry( - 4, "FF:FF:FF:FF:FF:FF", "", - dummyLogger, ctx.MockChannel, nil) + err = bdHandler.VppRemoveArpTerminationTableEntry(4, "FF:FF:FF:FF:FF:FF", "") Expect(err).Should(HaveOccurred()) } func TestVppArpTerminationTableEntryError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, _ := bdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&l2ba.BdIPMacAddDelReply{ Retval: 1, }) - err := vppcalls.VppAddArpTerminationTableEntry( - 4, "FF:FF:FF:FF:FF:FF", "192.168.4.4", - dummyLogger, ctx.MockChannel, nil) + err := bdHandler.VppAddArpTerminationTableEntry(4, "FF:FF:FF:FF:FF:FF", "192.168.4.4") Expect(err).Should(HaveOccurred()) ctx.MockVpp.MockReply(&l2ba.BridgeDomainAddDelReply{}) - err = vppcalls.VppRemoveArpTerminationTableEntry( - 4, "FF:FF:FF:FF:FF:FF", "192.168.4.4", - dummyLogger, ctx.MockChannel, nil) + err = bdHandler.VppRemoveArpTerminationTableEntry(4, "FF:FF:FF:FF:FF:FF", "192.168.4.4") Expect(err).Should(HaveOccurred()) } diff --git a/plugins/vpp/l2plugin/vppcalls/bridge_domain_vppcalls.go b/plugins/vpp/l2plugin/vppcalls/bridge_domain_vppcalls.go index e55c538b5d..bcc0fee197 100644 --- a/plugins/vpp/l2plugin/vppcalls/bridge_domain_vppcalls.go +++ b/plugins/vpp/l2plugin/vppcalls/bridge_domain_vppcalls.go @@ -18,26 +18,14 @@ import ( "fmt" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" l2ba "github.com/ligato/vpp-agent/plugins/vpp/binapi/l2" "github.com/ligato/vpp-agent/plugins/vpp/model/l2" ) -// BridgeDomainMessages is list of used VPP messages for compatibility check -var BridgeDomainMessages = []govppapi.Message{ - &l2ba.BridgeDomainAddDel{}, - &l2ba.BridgeDomainAddDelReply{}, - &l2ba.BdIPMacAddDel{}, - &l2ba.BdIPMacAddDelReply{}, - &l2ba.SwInterfaceSetL2Bridge{}, - &l2ba.SwInterfaceSetL2BridgeReply{}, -} - -// VppAddBridgeDomain adds new bridge domain. -func VppAddBridgeDomain(bdIdx uint32, bd *l2.BridgeDomains_BridgeDomain, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +// VppAddBridgeDomain implements bridge domain handler. +func (handler *BridgeDomainVppHandler) VppAddBridgeDomain(bdIdx uint32, bd *l2.BridgeDomains_BridgeDomain) error { defer func(t time.Time) { - stopwatch.TimeLog(l2ba.BridgeDomainAddDel{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(l2ba.BridgeDomainAddDel{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &l2ba.BridgeDomainAddDel{ @@ -51,34 +39,32 @@ func VppAddBridgeDomain(bdIdx uint32, bd *l2.BridgeDomains_BridgeDomain, vppChan MacAge: uint8(bd.MacAge), BdTag: []byte(bd.Name), } - reply := &l2ba.BridgeDomainAddDelReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return nil } -// VppDeleteBridgeDomain removes existing bridge domain. -func VppDeleteBridgeDomain(bdIdx uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +// VppDeleteBridgeDomain implements bridge domain handler. +func (handler *BridgeDomainVppHandler) VppDeleteBridgeDomain(bdIdx uint32) error { defer func(t time.Time) { - stopwatch.TimeLog(l2ba.BridgeDomainAddDel{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(l2ba.BridgeDomainAddDel{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &l2ba.BridgeDomainAddDel{ IsAdd: 0, BdID: bdIdx, } - reply := &l2ba.BridgeDomainAddDelReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } diff --git a/plugins/vpp/l2plugin/vppcalls/bridge_domain_vppcalls_test.go b/plugins/vpp/l2plugin/vppcalls/bridge_domain_vppcalls_test.go index b3ef357e18..216ae53c92 100644 --- a/plugins/vpp/l2plugin/vppcalls/bridge_domain_vppcalls_test.go +++ b/plugins/vpp/l2plugin/vppcalls/bridge_domain_vppcalls_test.go @@ -17,7 +17,10 @@ package vppcalls_test import ( "testing" + "github.com/ligato/cn-infra/logging/logrus" + "github.com/ligato/vpp-agent/idxvpp/nametoidx" l2ba "github.com/ligato/vpp-agent/plugins/vpp/binapi/l2" + "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" "github.com/ligato/vpp-agent/plugins/vpp/l2plugin/vppcalls" "github.com/ligato/vpp-agent/plugins/vpp/model/l2" "github.com/ligato/vpp-agent/tests/vppcallmock" @@ -83,51 +86,59 @@ var deleteTestDataOutBd *l2ba.BridgeDomainAddDel = &l2ba.BridgeDomainAddDel{ } func TestVppAddBridgeDomain(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, _ := bdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&l2ba.BridgeDomainAddDelReply{}) - err := vppcalls.VppAddBridgeDomain(dummyBridgeDomain, createTestDataInBD, ctx.MockChannel, nil) + err := bdHandler.VppAddBridgeDomain(dummyBridgeDomain, createTestDataInBD) Expect(err).ShouldNot(HaveOccurred()) Expect(ctx.MockChannel.Msg).To(Equal(createTestDataOutBD)) } func TestVppAddBridgeDomainError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, _ := bdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&l2ba.BridgeDomainAddDelReply{Retval: 1}) ctx.MockVpp.MockReply(&l2ba.SwInterfaceSetL2Bridge{}) - err := vppcalls.VppAddBridgeDomain(dummyBridgeDomain, createTestDataInBD, ctx.MockChannel, nil) + err := bdHandler.VppAddBridgeDomain(dummyBridgeDomain, createTestDataInBD) Expect(err).Should(HaveOccurred()) - err = vppcalls.VppAddBridgeDomain(dummyBridgeDomain, createTestDataInBD, ctx.MockChannel, nil) + err = bdHandler.VppAddBridgeDomain(dummyBridgeDomain, createTestDataInBD) Expect(err).Should(HaveOccurred()) } func TestVppDeleteBridgeDomain(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, _ := bdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&l2ba.BridgeDomainAddDelReply{}) - err := vppcalls.VppDeleteBridgeDomain(dummyBridgeDomain, ctx.MockChannel, nil) + err := bdHandler.VppDeleteBridgeDomain(dummyBridgeDomain) Expect(err).ShouldNot(HaveOccurred()) Expect(ctx.MockChannel.Msg).To(Equal(deleteTestDataOutBd)) } func TestVppDeleteBridgeDomainError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, _ := bdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&l2ba.BridgeDomainAddDelReply{Retval: 1}) ctx.MockVpp.MockReply(&l2ba.SwInterfaceSetL2Bridge{}) - err := vppcalls.VppDeleteBridgeDomain(dummyBridgeDomain, ctx.MockChannel, nil) + err := bdHandler.VppDeleteBridgeDomain(dummyBridgeDomain) Expect(err).Should(HaveOccurred()) - err = vppcalls.VppDeleteBridgeDomain(dummyBridgeDomain, ctx.MockChannel, nil) + err = bdHandler.VppDeleteBridgeDomain(dummyBridgeDomain) Expect(err).Should(HaveOccurred()) } + +func bdTestSetup(t *testing.T) (*vppcallmock.TestCtx, vppcalls.BridgeDomainVppAPI, ifaceidx.SwIfIndexRW) { + ctx := vppcallmock.SetupTestCtx(t) + log := logrus.NewLogger("test-log") + ifIndex := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(log, "bd-test-ifidx", nil)) + bdHandler := vppcalls.NewBridgeDomainVppHandler(ctx.MockChannel, ifIndex, log, nil) + return ctx, bdHandler, ifIndex +} diff --git a/plugins/vpp/l2plugin/vppcalls/doc.go b/plugins/vpp/l2plugin/vppcalls/doc.go index 2406999863..eb649f3844 100644 --- a/plugins/vpp/l2plugin/vppcalls/doc.go +++ b/plugins/vpp/l2plugin/vppcalls/doc.go @@ -1,3 +1,3 @@ // Package vppcalls contains wrappers over VPP binary APIs for bridge-domains, -// and L2 FIBs and XConnect pairs. +// and L2 FIBs and XConnect pairs and helpers for dumping them. package vppcalls diff --git a/plugins/vpp/l2plugin/vppcalls/dump_vppcalls.go b/plugins/vpp/l2plugin/vppcalls/dump_vppcalls.go new file mode 100644 index 0000000000..15996896d1 --- /dev/null +++ b/plugins/vpp/l2plugin/vppcalls/dump_vppcalls.go @@ -0,0 +1,253 @@ +// Copyright (c) 2017 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vppcalls + +import ( + "bytes" + "net" + "time" + + l2ba "github.com/ligato/vpp-agent/plugins/vpp/binapi/l2" + l2nb "github.com/ligato/vpp-agent/plugins/vpp/model/l2" +) + +// BridgeDomainDetails is the wrapper structure for the bridge domain northbound API structure. +// NOTE: Interfaces in BridgeDomains_BridgeDomain is overridden by the local Interfaces member. +type BridgeDomainDetails struct { + Bd *l2nb.BridgeDomains_BridgeDomain `json:"bridge_domain"` + Meta *BridgeDomainMeta `json:"bridge_domain_meta"` +} + +// BridgeDomainMeta contains bridge domain interface name/index map +type BridgeDomainMeta struct { + BdID uint32 `json:"bridge_domain_id"` + BdIfIdxToName map[uint32]string `json:"bridge_domain_id_to_name"` +} + +// DumpBridgeDomains implements bridge domain handler. +func (handler *BridgeDomainVppHandler) DumpBridgeDomains() (map[uint32]*BridgeDomainDetails, error) { + defer func(t time.Time) { + handler.stopwatch.TimeLog(l2ba.BridgeDomainDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + // map for the resulting BDs + bds := make(map[uint32]*BridgeDomainDetails) + + // First, dump all interfaces to create initial data. + reqCtx := handler.callsChannel.SendMultiRequest(&l2ba.BridgeDomainDump{BdID: ^uint32(0)}) + + for { + bdDetails := &l2ba.BridgeDomainDetails{} + stop, err := reqCtx.ReceiveReply(bdDetails) + if stop { + break // Break from the loop. + } + if err != nil { + return nil, err + } + + // base bridge domain details + bds[bdDetails.BdID] = &BridgeDomainDetails{ + Bd: &l2nb.BridgeDomains_BridgeDomain{ + Name: string(bytes.Replace(bdDetails.BdTag, []byte{0x00}, []byte{}, -1)), + Flood: bdDetails.Flood > 0, + UnknownUnicastFlood: bdDetails.UuFlood > 0, + Forward: bdDetails.Forward > 0, + Learn: bdDetails.Learn > 0, + ArpTermination: bdDetails.ArpTerm > 0, + MacAge: uint32(bdDetails.MacAge), + }, + Meta: &BridgeDomainMeta{ + BdID: bdDetails.BdID, + BdIfIdxToName: make(map[uint32]string), + }, + } + + // bridge domain interfaces and metadata + for _, iface := range bdDetails.SwIfDetails { + ifName, _, exists := handler.ifIndexes.LookupName(iface.SwIfIndex) + if !exists { + handler.log.Warnf("Bridge domain dump: interface name for index %d not found", iface.SwIfIndex) + continue + } + // Bvi + var bvi bool + if iface.SwIfIndex == bdDetails.BviSwIfIndex { + bvi = true + } + // Add metadata entry + bds[bdDetails.BdID].Meta.BdIfIdxToName[iface.SwIfIndex] = ifName + // Add interface entry + bds[bdDetails.BdID].Bd.Interfaces = append(bds[bdDetails.BdID].Bd.Interfaces, &l2nb.BridgeDomains_BridgeDomain_Interfaces{ + Name: ifName, + BridgedVirtualInterface: bvi, + SplitHorizonGroup: uint32(iface.Shg), + }) + } + } + + return bds, nil +} + +// DumpBridgeDomainIDs implements bridge domain handler. +func (handler *BridgeDomainVppHandler) DumpBridgeDomainIDs() ([]uint32, error) { + defer func(t time.Time) { + handler.stopwatch.TimeLog(l2ba.BridgeDomainDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + req := &l2ba.BridgeDomainDump{BdID: ^uint32(0)} + var activeDomains []uint32 + reqCtx := handler.callsChannel.SendMultiRequest(req) + for { + msg := &l2ba.BridgeDomainDetails{} + stop, err := reqCtx.ReceiveReply(msg) + if err != nil { + return nil, err + } + if stop { + break + } + activeDomains = append(activeDomains, msg.BdID) + } + + return activeDomains, nil +} + +// FibTableDetails is the wrapper structure for the FIB table entry northbound API structure. +type FibTableDetails struct { + Fib *l2nb.FibTable_FibEntry `json:"fib"` + Meta *FibMeta `json:"fib_meta"` +} + +// FibMeta contains FIB interface and bridge domain name/index map +type FibMeta struct { + BdID uint32 `json:"bridge_domain_id"` + IfIdx uint32 `json:"outgoing_interface_sw_if_idx"` +} + +// DumpFIBTableEntries implements fib handler. +func (handler *FibVppHandler) DumpFIBTableEntries() (map[string]*FibTableDetails, error) { + defer func(t time.Time) { + handler.stopwatch.TimeLog(l2ba.L2FibTableDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + // map for the resulting FIBs + fibs := make(map[string]*FibTableDetails) + + reqCtx := handler.syncCallsChannel.SendMultiRequest(&l2ba.L2FibTableDump{BdID: ^uint32(0)}) + for { + fibDetails := &l2ba.L2FibTableDetails{} + stop, err := reqCtx.ReceiveReply(fibDetails) + if stop { + break // Break from the loop. + } + if err != nil { + return nil, err + } + + mac := net.HardwareAddr(fibDetails.Mac).String() + var action l2nb.FibTable_FibEntry_Action + if fibDetails.FilterMac > 0 { + action = l2nb.FibTable_FibEntry_DROP + } else { + action = l2nb.FibTable_FibEntry_FORWARD + } + + // Interface name + ifName, _, exists := handler.ifIndexes.LookupName(fibDetails.SwIfIndex) + if !exists { + handler.log.Warnf("FIB dump: interface name for index %s not found", fibDetails.SwIfIndex) + } + // Bridge domain name + bdName, _, exists := handler.bdIndexes.LookupName(fibDetails.BdID) + if !exists { + handler.log.Warnf("FIB dump: bridge domain name for index %s not found", fibDetails.BdID) + } + + fibs[mac] = &FibTableDetails{ + Fib: &l2nb.FibTable_FibEntry{ + PhysAddress: mac, + BridgeDomain: bdName, + Action: action, + OutgoingInterface: ifName, + StaticConfig: fibDetails.StaticMac > 0, + BridgedVirtualInterface: fibDetails.BviMac > 0, + }, + Meta: &FibMeta{ + BdID: fibDetails.BdID, + IfIdx: fibDetails.SwIfIndex, + }, + } + } + + return fibs, nil +} + +// XConnectDetails is the wrapper structure for the l2 xconnect northbound API structure. +type XConnectDetails struct { + Xc *l2nb.XConnectPairs_XConnectPair `json:"x_connect"` + Meta *XcMeta `json:"x_connect_meta"` +} + +// XcMeta contains cross connect rx/tx interface indexes +type XcMeta struct { + ReceiveInterfaceSwIfIdx uint32 `json:"receive_interface_sw_if_idx"` + TransmitInterfaceSwIfIdx uint32 `json:"transmit_interface_sw_if_idx"` +} + +// DumpXConnectPairs implements xconnect handler. +func (handler *XConnectVppHandler) DumpXConnectPairs() (map[uint32]*XConnectDetails, error) { + defer func(t time.Time) { + handler.stopwatch.TimeLog(l2ba.L2XconnectDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + // map for the resulting xconnect pairs + xpairs := make(map[uint32]*XConnectDetails) + + reqCtx := handler.callsChannel.SendMultiRequest(&l2ba.L2XconnectDump{}) + for { + pairs := &l2ba.L2XconnectDetails{} + stop, err := reqCtx.ReceiveReply(pairs) + if stop { + break // Break from the loop. + } + if err != nil { + return nil, err + } + + // Find interface names + rxIfaceName, _, exists := handler.ifIndexes.LookupName(pairs.RxSwIfIndex) + if !exists { + handler.log.Warnf("XConnect dump: rx interface name for index %s not found", pairs.RxSwIfIndex) + } + txIfaceName, _, exists := handler.ifIndexes.LookupName(pairs.TxSwIfIndex) + if !exists { + handler.log.Warnf("XConnect dump: tx interface name for index %s not found", pairs.TxSwIfIndex) + } + + xpairs[pairs.RxSwIfIndex] = &XConnectDetails{ + Xc: &l2nb.XConnectPairs_XConnectPair{ + ReceiveInterface: rxIfaceName, + TransmitInterface: txIfaceName, + }, + Meta: &XcMeta{ + ReceiveInterfaceSwIfIdx: pairs.RxSwIfIndex, + TransmitInterfaceSwIfIdx: pairs.TxSwIfIndex, + }, + } + } + + return xpairs, nil +} diff --git a/plugins/vpp/l2plugin/vppdump/dump_vppcalls_test.go b/plugins/vpp/l2plugin/vppcalls/dump_vppcalls_test.go similarity index 63% rename from plugins/vpp/l2plugin/vppdump/dump_vppcalls_test.go rename to plugins/vpp/l2plugin/vppcalls/dump_vppcalls_test.go index 2752cbd519..1a0dee48f8 100644 --- a/plugins/vpp/l2plugin/vppdump/dump_vppcalls_test.go +++ b/plugins/vpp/l2plugin/vppcalls/dump_vppcalls_test.go @@ -12,16 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -package vppdump +package vppcalls_test import ( "testing" govppapi "git.fd.io/govpp.git/api" - "git.fd.io/govpp.git/core/bin_api/vpe" l2ba "github.com/ligato/vpp-agent/plugins/vpp/binapi/l2" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/vpe" + "github.com/ligato/vpp-agent/plugins/vpp/l2plugin/vppcalls" l2nb "github.com/ligato/vpp-agent/plugins/vpp/model/l2" - "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" ) @@ -44,31 +44,59 @@ var testDataInMessagesBDs = []govppapi.Message{ }, } -var testDataOutMessage = []*BridgeDomain{ +var testDataOutMessage = []*vppcalls.BridgeDomainDetails{ { - Interfaces: []*BridgeDomainInterface{ - {SwIfIndex: 5}, - {SwIfIndex: 7}, - }, - BridgeDomains_BridgeDomain: l2nb.BridgeDomains_BridgeDomain{ + Bd: &l2nb.BridgeDomains_BridgeDomain{ Flood: true, UnknownUnicastFlood: true, Forward: true, Learn: true, ArpTermination: true, - MacAge: 140}, - }, { - Interfaces: []*BridgeDomainInterface{ - {SwIfIndex: 5}, - {SwIfIndex: 8}, + MacAge: 140, + Interfaces: []*l2nb.BridgeDomains_BridgeDomain_Interfaces{ + { + Name: "if1", + }, + { + Name: "if2", + }, + }, + }, + Meta: &vppcalls.BridgeDomainMeta{ + BdID: 4, + BdIfIdxToName: func() map[uint32]string { + meta := make(map[uint32]string) + meta[5] = "if1" + meta[7] = "if2" + return meta + }(), }, - BridgeDomains_BridgeDomain: l2nb.BridgeDomains_BridgeDomain{ + }, { + Bd: &l2nb.BridgeDomains_BridgeDomain{ Flood: false, UnknownUnicastFlood: false, Forward: false, Learn: false, ArpTermination: false, - MacAge: 141}, + MacAge: 141, + Interfaces: []*l2nb.BridgeDomains_BridgeDomain_Interfaces{ + { + Name: "if1", + }, + { + Name: "if3", + }, + }, + }, + Meta: &vppcalls.BridgeDomainMeta{ + BdID: 5, + BdIfIdxToName: func() map[uint32]string { + meta := make(map[uint32]string) + meta[5] = "if1" + meta[8] = "if3" + return meta + }(), + }, }, } @@ -76,19 +104,22 @@ var testDataOutMessage = []*BridgeDomain{ // - 2 bridge domains + 1 default in VPP // TestDumpBridgeDomainIDs tests DumpBridgeDomainIDs method func TestDumpBridgeDomainIDs(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, ifIndexes := bdTestSetup(t) defer ctx.TeardownTestCtx() + ifIndexes.RegisterName("if1", 5, nil) + ifIndexes.RegisterName("if2", 7, nil) + ctx.MockVpp.MockReply(testDataInMessagesBDs...) ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - activeDomains, err := DumpBridgeDomainIDs(ctx.MockChannel, nil) + activeDomains, err := bdHandler.DumpBridgeDomainIDs() Expect(err).To(BeNil()) - Expect(activeDomains).To(Equal([]uint32{0, 4, 5})) + Expect(activeDomains).To(Equal([]uint32{4, 5})) ctx.MockVpp.MockReply(&l2ba.BridgeDomainAddDelReply{}) - _, err = DumpBridgeDomainIDs(ctx.MockChannel, nil) + _, err = bdHandler.DumpBridgeDomainIDs() Expect(err).Should(HaveOccurred()) } @@ -96,13 +127,17 @@ func TestDumpBridgeDomainIDs(t *testing.T) { // - 2 bridge domains + 1 default in VPP // TestDumpBridgeDomains tests DumpBridgeDomains method func TestDumpBridgeDomains(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, ifIndexes := bdTestSetup(t) defer ctx.TeardownTestCtx() + ifIndexes.RegisterName("if1", 5, nil) + ifIndexes.RegisterName("if2", 7, nil) + ifIndexes.RegisterName("if3", 8, nil) + ctx.MockVpp.MockReply(testDataInMessagesBDs...) ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - bridgeDomains, err := DumpBridgeDomains(ctx.MockChannel, nil) + bridgeDomains, err := bdHandler.DumpBridgeDomains() Expect(err).To(BeNil()) Expect(bridgeDomains).To(HaveLen(2)) @@ -110,7 +145,7 @@ func TestDumpBridgeDomains(t *testing.T) { Expect(bridgeDomains[5]).To(Equal(testDataOutMessage[1])) ctx.MockVpp.MockReply(&l2ba.BridgeDomainAddDelReply{}) - _, err = DumpBridgeDomains(ctx.MockChannel, nil) + _, err = bdHandler.DumpBridgeDomains() Expect(err).Should(HaveOccurred()) } @@ -127,25 +162,33 @@ var testDataInMessagesFIBs = []govppapi.Message{ }, } -var testDataOutFIBs = []*FIBTableEntry{ +var testDataOutFIBs = []*vppcalls.FibTableDetails{ { - BridgeDomainIdx: 10, - OutgoingInterfaceSwIfIdx: 1, - FibTable_FibEntry: l2nb.FibTable_FibEntry{ + Fib: &l2nb.FibTable_FibEntry{ PhysAddress: "aa:aa:aa:aa:aa:aa", + BridgeDomain: "bd1", Action: l2nb.FibTable_FibEntry_DROP, StaticConfig: true, BridgedVirtualInterface: true, + OutgoingInterface: "if1", + }, + Meta: &vppcalls.FibMeta{ + BdID: 10, + IfIdx: 1, }, }, { - BridgeDomainIdx: 20, - OutgoingInterfaceSwIfIdx: 2, - FibTable_FibEntry: l2nb.FibTable_FibEntry{ + Fib: &l2nb.FibTable_FibEntry{ PhysAddress: "bb:bb:bb:bb:bb:bb", + BridgeDomain: "bd2", Action: l2nb.FibTable_FibEntry_FORWARD, StaticConfig: false, BridgedVirtualInterface: false, + OutgoingInterface: "if2", + }, + Meta: &vppcalls.FibMeta{ + BdID: 20, + IfIdx: 2, }, }, } @@ -154,44 +197,78 @@ var testDataOutFIBs = []*FIBTableEntry{ // - 2 FIB entries in VPP // TestDumpFIBTableEntries tests DumpFIBTableEntries method func TestDumpFIBTableEntries(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, fibHandler, ifIndexes, bdIndexes := fibTestSetup(t) defer ctx.TeardownTestCtx() + ifIndexes.RegisterName("if1", 1, nil) + ifIndexes.RegisterName("if2", 2, nil) + bdIndexes.RegisterName("bd1", 10, nil) + bdIndexes.RegisterName("bd2", 20, nil) + ctx.MockVpp.MockReply(testDataInMessagesFIBs...) ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - fibTable, err := DumpFIBTableEntries(ctx.MockChannel, nil) + fibTable, err := fibHandler.DumpFIBTableEntries() Expect(err).To(BeNil()) Expect(fibTable).To(HaveLen(2)) Expect(fibTable["aa:aa:aa:aa:aa:aa"]).To(Equal(testDataOutFIBs[0])) Expect(fibTable["bb:bb:bb:bb:bb:bb"]).To(Equal(testDataOutFIBs[1])) ctx.MockVpp.MockReply(&l2ba.BridgeDomainAddDelReply{}) - _, err = DumpFIBTableEntries(ctx.MockChannel, nil) + _, err = fibHandler.DumpFIBTableEntries() Expect(err).Should(HaveOccurred()) } var testDataInXConnect = []govppapi.Message{ - &l2ba.L2XconnectDetails{1, 2}, - &l2ba.L2XconnectDetails{3, 4}, + &l2ba.L2XconnectDetails{ + RxSwIfIndex: 1, + TxSwIfIndex: 2, + }, + &l2ba.L2XconnectDetails{ + RxSwIfIndex: 3, + TxSwIfIndex: 4, + }, } -var testDataOutXconnect = []*XConnectPairs{ - {1, 2}, - {3, 4}, +var testDataOutXconnect = []*vppcalls.XConnectDetails{ + { + Xc: &l2nb.XConnectPairs_XConnectPair{ + ReceiveInterface: "if1", + TransmitInterface: "if2", + }, + Meta: &vppcalls.XcMeta{ + ReceiveInterfaceSwIfIdx: 1, + TransmitInterfaceSwIfIdx: 2, + }, + }, + { + Xc: &l2nb.XConnectPairs_XConnectPair{ + ReceiveInterface: "if3", + TransmitInterface: "if4", + }, + Meta: &vppcalls.XcMeta{ + ReceiveInterfaceSwIfIdx: 3, + TransmitInterfaceSwIfIdx: 4, + }, + }, } // Scenario: // - 2 Xconnect entries in VPP // TestDumpXConnectPairs tests DumpXConnectPairs method func TestDumpXConnectPairs(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, xcHandler, ifIndex := xcTestSetup(t) defer ctx.TeardownTestCtx() + ifIndex.RegisterName("if1", 1, nil) + ifIndex.RegisterName("if2", 2, nil) + ifIndex.RegisterName("if3", 3, nil) + ifIndex.RegisterName("if4", 4, nil) + ctx.MockVpp.MockReply(testDataInXConnect...) ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - xConnectPairs, err := DumpXConnectPairs(ctx.MockChannel, nil) + xConnectPairs, err := xcHandler.DumpXConnectPairs() Expect(err).To(BeNil()) Expect(xConnectPairs).To(HaveLen(2)) @@ -199,7 +276,7 @@ func TestDumpXConnectPairs(t *testing.T) { Expect(xConnectPairs[3]).To(Equal(testDataOutXconnect[1])) ctx.MockVpp.MockReply(&l2ba.BridgeDomainAddDelReply{}) - _, err = DumpXConnectPairs(ctx.MockChannel, nil) + _, err = xcHandler.DumpXConnectPairs() Expect(err).Should(HaveOccurred()) } diff --git a/plugins/vpp/l2plugin/vppcalls/interface_vppcalls.go b/plugins/vpp/l2plugin/vppcalls/interface_vppcalls.go index 2c74074ad3..7d9a99f5bd 100644 --- a/plugins/vpp/l2plugin/vppcalls/interface_vppcalls.go +++ b/plugins/vpp/l2plugin/vppcalls/interface_vppcalls.go @@ -18,25 +18,21 @@ import ( "fmt" "time" - govppapi "git.fd.io/govpp.git/api" "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/measure" l2ba "github.com/ligato/vpp-agent/plugins/vpp/binapi/l2" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" "github.com/ligato/vpp-agent/plugins/vpp/model/l2" ) -// SetInterfacesToBridgeDomain attempts to set all provided interfaces to bridge domain. It returns a list of interfaces -// which were successfully set. -func SetInterfacesToBridgeDomain(bdName string, bdIdx uint32, bdIfs []*l2.BridgeDomains_BridgeDomain_Interfaces, - swIfIndices ifaceidx.SwIfIndex, log logging.Logger, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (ifs []string, wasErr error) { - +// SetInterfacesToBridgeDomain implements bridge domain handler. +func (handler *BridgeDomainVppHandler) SetInterfacesToBridgeDomain(bdName string, bdIdx uint32, bdIfs []*l2.BridgeDomains_BridgeDomain_Interfaces, + swIfIndices ifaceidx.SwIfIndex) (ifs []string, wasErr error) { defer func(t time.Time) { - stopwatch.TimeLog(l2ba.SwInterfaceSetL2Bridge{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(l2ba.SwInterfaceSetL2Bridge{}).LogTimeEntry(time.Since(t)) }(time.Now()) if len(bdIfs) == 0 { - log.Debugf("Bridge domain %v has no new interface to set", bdName) + handler.log.Debugf("Bridge domain %v has no new interface to set", bdName) return nil, nil } @@ -44,14 +40,14 @@ func SetInterfacesToBridgeDomain(bdName string, bdIdx uint32, bdIfs []*l2.Bridge // Verify that interface exists, otherwise skip it. ifIdx, _, found := swIfIndices.LookupIdx(bdIf.Name) if !found { - log.Debugf("Required bridge domain %v interface %v not found", bdName, bdIf.Name) + handler.log.Debugf("Required bridge domain %v interface %v not found", bdName, bdIf.Name) continue } - if err := addDelInterfaceToBridgeDomain(bdName, bdIdx, bdIf, ifIdx, log, vppChan, true); err != nil { + if err := handler.addDelInterfaceToBridgeDomain(bdName, bdIdx, bdIf, ifIdx, true); err != nil { wasErr = err - log.Error(wasErr) + handler.log.Error(wasErr) } else { - log.WithFields(logging.Fields{"Interface": bdIf.Name, "BD": bdName}).Debug("Interface set to bridge domain") + handler.log.WithFields(logging.Fields{"Interface": bdIf.Name, "BD": bdName}).Debug("Interface set to bridge domain") ifs = append(ifs, bdIf.Name) } } @@ -59,17 +55,16 @@ func SetInterfacesToBridgeDomain(bdName string, bdIdx uint32, bdIfs []*l2.Bridge return ifs, wasErr } -// UnsetInterfacesFromBridgeDomain removes all interfaces from bridge domain. It returns a list of interfaces -// which were successfully unset. -func UnsetInterfacesFromBridgeDomain(bdName string, bdIdx uint32, bdIfs []*l2.BridgeDomains_BridgeDomain_Interfaces, - swIfIndices ifaceidx.SwIfIndex, log logging.Logger, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (ifs []string, wasErr error) { +// UnsetInterfacesFromBridgeDomain implements bridge domain handler. +func (handler *BridgeDomainVppHandler) UnsetInterfacesFromBridgeDomain(bdName string, bdIdx uint32, bdIfs []*l2.BridgeDomains_BridgeDomain_Interfaces, + swIfIndices ifaceidx.SwIfIndex) (ifs []string, wasErr error) { defer func(t time.Time) { - stopwatch.TimeLog(l2ba.SwInterfaceSetL2Bridge{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(l2ba.SwInterfaceSetL2Bridge{}).LogTimeEntry(time.Since(t)) }(time.Now()) if len(bdIfs) == 0 { - log.Debugf("Bridge domain %v has no obsolete interface to unset", bdName) + handler.log.Debugf("Bridge domain %v has no obsolete interface to unset", bdName) return nil, nil } @@ -77,14 +72,14 @@ func UnsetInterfacesFromBridgeDomain(bdName string, bdIdx uint32, bdIfs []*l2.Br // Verify that interface exists, otherwise skip it. ifIdx, _, found := swIfIndices.LookupIdx(bdIf.Name) if !found { - log.Debugf("Required bridge domain %v interface %v not found", bdName, bdIf.Name) + handler.log.Debugf("Required bridge domain %v interface %v not found", bdName, bdIf.Name) continue } - if err := addDelInterfaceToBridgeDomain(bdName, bdIdx, bdIf, ifIdx, log, vppChan, false); err != nil { + if err := handler.addDelInterfaceToBridgeDomain(bdName, bdIdx, bdIf, ifIdx, false); err != nil { wasErr = err - log.Error(wasErr) + handler.log.Error(wasErr) } else { - log.WithFields(logging.Fields{"Interface": bdIf.Name, "BD": bdName}).Debug("Interface unset from bridge domain") + handler.log.WithFields(logging.Fields{"Interface": bdIf.Name, "BD": bdName}).Debug("Interface unset from bridge domain") ifs = append(ifs, bdIf.Name) } } @@ -92,28 +87,24 @@ func UnsetInterfacesFromBridgeDomain(bdName string, bdIdx uint32, bdIfs []*l2.Br return ifs, wasErr } -func addDelInterfaceToBridgeDomain(bdName string, bdIdx uint32, bdIf *l2.BridgeDomains_BridgeDomain_Interfaces, - ifIdx uint32, log logging.Logger, vppChan govppapi.Channel, add bool) error { +func (handler *BridgeDomainVppHandler) addDelInterfaceToBridgeDomain(bdName string, bdIdx uint32, bdIf *l2.BridgeDomains_BridgeDomain_Interfaces, + ifIdx uint32, add bool) error { req := &l2ba.SwInterfaceSetL2Bridge{ BdID: bdIdx, RxSwIfIndex: ifIdx, Shg: uint8(bdIf.SplitHorizonGroup), - } - // Enable - if add { - req.Enable = 1 + Enable: boolToUint(add), } // Set as BVI. if bdIf.BridgedVirtualInterface { req.Bvi = 1 - log.Debugf("Interface %v set as BVI", bdIf.Name) + handler.log.Debugf("Interface %v set as BVI", bdIf.Name) } - reply := &l2ba.SwInterfaceSetL2BridgeReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return fmt.Errorf("error while assigning/removing interface %v to bd %v: %v", bdIf.Name, bdName, err) - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d while assigning/removing interface %v (idx %v) to bd %v", reply.GetMessageName(), reply.Retval, bdIf.Name, ifIdx, bdName) } diff --git a/plugins/vpp/l2plugin/vppcalls/interface_vppcalls_test.go b/plugins/vpp/l2plugin/vppcalls/interface_vppcalls_test.go index 0572a9b7dc..8d82635e52 100644 --- a/plugins/vpp/l2plugin/vppcalls/interface_vppcalls_test.go +++ b/plugins/vpp/l2plugin/vppcalls/interface_vppcalls_test.go @@ -17,19 +17,16 @@ package vppcalls_test import ( "testing" - "github.com/ligato/vpp-agent/tests/vppcallmock" - "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/idxvpp/nametoidx" l2Api "github.com/ligato/vpp-agent/plugins/vpp/binapi/l2" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" - "github.com/ligato/vpp-agent/plugins/vpp/l2plugin/vppcalls" "github.com/ligato/vpp-agent/plugins/vpp/model/l2" . "github.com/onsi/gomega" ) func TestSetInterfacesToBridgeDomain(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, _ := bdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&l2Api.SwInterfaceSetL2BridgeReply{}) @@ -41,7 +38,7 @@ func TestSetInterfacesToBridgeDomain(t *testing.T) { swIfIndexes.RegisterName("if2", 2, nil) swIfIndexes.RegisterName("if3", 3, nil) - configured, err := vppcalls.SetInterfacesToBridgeDomain("bd1", 1, []*l2.BridgeDomains_BridgeDomain_Interfaces{ + configured, err := bdHandler.SetInterfacesToBridgeDomain("bd1", 1, []*l2.BridgeDomains_BridgeDomain_Interfaces{ { Name: "if1", BridgedVirtualInterface: true, @@ -57,7 +54,7 @@ func TestSetInterfacesToBridgeDomain(t *testing.T) { BridgedVirtualInterface: false, SplitHorizonGroup: 2, }, - }, swIfIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + }, swIfIndexes) Expect(err).To(BeNil()) Expect(len(ctx.MockChannel.Msgs)).To(BeEquivalentTo(3)) @@ -78,13 +75,13 @@ func TestSetInterfacesToBridgeDomain(t *testing.T) { } func TestSetInterfacesToBridgeDomainNoInterfaceToSet(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, _ := bdTestSetup(t) defer ctx.TeardownTestCtx() swIfIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "bd", nil)) - configured, err := vppcalls.SetInterfacesToBridgeDomain("bd1", 1, []*l2.BridgeDomains_BridgeDomain_Interfaces{}, - swIfIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + configured, err := bdHandler.SetInterfacesToBridgeDomain("bd1", 1, []*l2.BridgeDomains_BridgeDomain_Interfaces{}, + swIfIndexes) Expect(err).To(BeNil()) Expect(len(ctx.MockChannel.Msgs)).To(BeEquivalentTo(0)) @@ -92,7 +89,7 @@ func TestSetInterfacesToBridgeDomainNoInterfaceToSet(t *testing.T) { } func TestSetInterfacesToBridgeDomainMissingInterface(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, _ := bdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&l2Api.SwInterfaceSetL2BridgeReply{}) @@ -102,14 +99,14 @@ func TestSetInterfacesToBridgeDomainMissingInterface(t *testing.T) { swIfIndexes.RegisterName("if1", 1, nil) // Metadata are not required for test purpose // Interface "if2" is not registered - configured, err := vppcalls.SetInterfacesToBridgeDomain("bd1", 1, []*l2.BridgeDomains_BridgeDomain_Interfaces{ + configured, err := bdHandler.SetInterfacesToBridgeDomain("bd1", 1, []*l2.BridgeDomains_BridgeDomain_Interfaces{ { Name: "if1", }, { Name: "if2", }, - }, swIfIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + }, swIfIndexes) Expect(err).To(BeNil()) Expect(len(ctx.MockChannel.Msgs)).To(BeEquivalentTo(1)) @@ -117,7 +114,7 @@ func TestSetInterfacesToBridgeDomainMissingInterface(t *testing.T) { } func TestSetInterfacesToBridgeDomainError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, _ := bdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&l2Api.SwInterfaceSetL2Bridge{}) @@ -125,18 +122,18 @@ func TestSetInterfacesToBridgeDomainError(t *testing.T) { swIfIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "bd", nil)) swIfIndexes.RegisterName("if1", 1, nil) // Metadata are not required for test purpose - configured, err := vppcalls.SetInterfacesToBridgeDomain("bd1", 1, []*l2.BridgeDomains_BridgeDomain_Interfaces{ + configured, err := bdHandler.SetInterfacesToBridgeDomain("bd1", 1, []*l2.BridgeDomains_BridgeDomain_Interfaces{ { Name: "if1", }, - }, swIfIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + }, swIfIndexes) Expect(err).ToNot(BeNil()) Expect(configured).To(BeNil()) } func TestSetInterfacesToBridgeDomainRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, _ := bdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&l2Api.SwInterfaceSetL2BridgeReply{ @@ -146,18 +143,18 @@ func TestSetInterfacesToBridgeDomainRetval(t *testing.T) { swIfIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "bd", nil)) swIfIndexes.RegisterName("if1", 1, nil) // Metadata are not required for test purpose - configured, err := vppcalls.SetInterfacesToBridgeDomain("bd1", 1, []*l2.BridgeDomains_BridgeDomain_Interfaces{ + configured, err := bdHandler.SetInterfacesToBridgeDomain("bd1", 1, []*l2.BridgeDomains_BridgeDomain_Interfaces{ { Name: "if1", }, - }, swIfIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + }, swIfIndexes) Expect(err).ToNot(BeNil()) Expect(configured).To(BeNil()) } func TestUnsetInterfacesFromBridgeDomain(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, _ := bdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&l2Api.SwInterfaceSetL2BridgeReply{}) @@ -169,7 +166,7 @@ func TestUnsetInterfacesFromBridgeDomain(t *testing.T) { swIfIndexes.RegisterName("if2", 2, nil) swIfIndexes.RegisterName("if3", 3, nil) - configured, err := vppcalls.UnsetInterfacesFromBridgeDomain("bd1", 1, []*l2.BridgeDomains_BridgeDomain_Interfaces{ + configured, err := bdHandler.UnsetInterfacesFromBridgeDomain("bd1", 1, []*l2.BridgeDomains_BridgeDomain_Interfaces{ { Name: "if1", SplitHorizonGroup: 0, @@ -182,7 +179,7 @@ func TestUnsetInterfacesFromBridgeDomain(t *testing.T) { Name: "if3", SplitHorizonGroup: 2, }, - }, swIfIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + }, swIfIndexes) Expect(err).To(BeNil()) Expect(len(ctx.MockChannel.Msgs)).To(BeEquivalentTo(3)) @@ -198,13 +195,13 @@ func TestUnsetInterfacesFromBridgeDomain(t *testing.T) { } func TestUnsetInterfacesFromBridgeDomainNoInterfaceToUnset(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, _ := bdTestSetup(t) defer ctx.TeardownTestCtx() swIfIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "bd", nil)) - configured, err := vppcalls.UnsetInterfacesFromBridgeDomain("bd1", 1, []*l2.BridgeDomains_BridgeDomain_Interfaces{}, - swIfIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + configured, err := bdHandler.UnsetInterfacesFromBridgeDomain("bd1", 1, []*l2.BridgeDomains_BridgeDomain_Interfaces{}, + swIfIndexes) Expect(err).To(BeNil()) Expect(len(ctx.MockChannel.Msgs)).To(BeEquivalentTo(0)) @@ -212,7 +209,7 @@ func TestUnsetInterfacesFromBridgeDomainNoInterfaceToUnset(t *testing.T) { } func TestUnsetInterfacesFromBridgeDomainMissingInterface(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, _ := bdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&l2Api.SwInterfaceSetL2BridgeReply{}) @@ -222,14 +219,14 @@ func TestUnsetInterfacesFromBridgeDomainMissingInterface(t *testing.T) { swIfIndexes.RegisterName("if1", 1, nil) // Metadata are not required for test purpose // Interface "if2" is not registered - configured, err := vppcalls.UnsetInterfacesFromBridgeDomain("bd1", 1, []*l2.BridgeDomains_BridgeDomain_Interfaces{ + configured, err := bdHandler.UnsetInterfacesFromBridgeDomain("bd1", 1, []*l2.BridgeDomains_BridgeDomain_Interfaces{ { Name: "if1", }, { Name: "if2", }, - }, swIfIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + }, swIfIndexes) Expect(err).To(BeNil()) Expect(len(ctx.MockChannel.Msgs)).To(BeEquivalentTo(1)) @@ -237,7 +234,7 @@ func TestUnsetInterfacesFromBridgeDomainMissingInterface(t *testing.T) { } func TestUnsetInterfacesFromBridgeDomainError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, _ := bdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&l2Api.SwInterfaceSetL2Bridge{}) @@ -245,18 +242,18 @@ func TestUnsetInterfacesFromBridgeDomainError(t *testing.T) { swIfIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "bd", nil)) swIfIndexes.RegisterName("if1", 1, nil) // Metadata are not required for test purpose - configured, err := vppcalls.UnsetInterfacesFromBridgeDomain("bd1", 1, []*l2.BridgeDomains_BridgeDomain_Interfaces{ + configured, err := bdHandler.UnsetInterfacesFromBridgeDomain("bd1", 1, []*l2.BridgeDomains_BridgeDomain_Interfaces{ { Name: "if1", }, - }, swIfIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + }, swIfIndexes) Expect(err).ToNot(BeNil()) Expect(configured).To(BeNil()) } func TestUnsetInterfacesFromBridgeDomainRetval(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, bdHandler, _ := bdTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&l2Api.SwInterfaceSetL2BridgeReply{ @@ -266,11 +263,11 @@ func TestUnsetInterfacesFromBridgeDomainRetval(t *testing.T) { swIfIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "bd", nil)) swIfIndexes.RegisterName("if1", 1, nil) // Metadata are not required for test purpose - configured, err := vppcalls.UnsetInterfacesFromBridgeDomain("bd1", 1, []*l2.BridgeDomains_BridgeDomain_Interfaces{ + configured, err := bdHandler.UnsetInterfacesFromBridgeDomain("bd1", 1, []*l2.BridgeDomains_BridgeDomain_Interfaces{ { Name: "if1", }, - }, swIfIndexes, logrus.DefaultLogger(), ctx.MockChannel, nil) + }, swIfIndexes) Expect(err).ToNot(BeNil()) Expect(configured).To(BeNil()) diff --git a/plugins/vpp/l2plugin/vppcalls/l2fib_vppcalls.go b/plugins/vpp/l2plugin/vppcalls/l2fib_vppcalls.go index 42e82ffa65..9825c250bd 100644 --- a/plugins/vpp/l2plugin/vppcalls/l2fib_vppcalls.go +++ b/plugins/vpp/l2plugin/vppcalls/l2fib_vppcalls.go @@ -19,22 +19,10 @@ import ( "net" "time" - govppapi "git.fd.io/govpp.git/api" "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/measure" l2ba "github.com/ligato/vpp-agent/plugins/vpp/binapi/l2" ) -// L2FibMessages is list of used VPP messages for compatibility check -var L2FibMessages = []govppapi.Message{ - &l2ba.BridgeDomainDump{}, - &l2ba.BridgeDomainDetails{}, - &l2ba.L2FibTableDump{}, - &l2ba.L2FibTableDetails{}, - &l2ba.L2fibAddDel{}, - &l2ba.L2fibAddDelReply{}, -} - // FibLogicalReq groups multiple fields so that all of them do // not enumerate in one function call (request, reply/callback). type FibLogicalReq struct { @@ -47,29 +35,11 @@ type FibLogicalReq struct { callback func(error) } -// L2FibVppCalls aggregates vpp calls related to l2 fib. -type L2FibVppCalls struct { - log logging.Logger - vppChan govppapi.Channel - stopwatch *measure.Stopwatch - requestChan chan *FibLogicalReq -} - -// NewL2FibVppCalls is a constructor. -func NewL2FibVppCalls(log logging.Logger, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) *L2FibVppCalls { - return &L2FibVppCalls{ - log: log, - vppChan: vppChan, - stopwatch: stopwatch, - requestChan: make(chan *FibLogicalReq), - } -} - -// Add creates L2 FIB table entry. -func (fib *L2FibVppCalls) Add(mac string, bdID uint32, ifIdx uint32, bvi bool, static bool, callback func(error)) error { - fib.log.Debug("Adding L2 FIB table entry, mac: ", mac) +// Add implements fib handler. +func (handler *FibVppHandler) Add(mac string, bdID uint32, ifIdx uint32, bvi bool, static bool, callback func(error)) error { + handler.log.Debug("Adding L2 FIB table entry, mac: ", mac) - fib.requestChan <- &FibLogicalReq{ + handler.requestChan <- &FibLogicalReq{ IsAdd: true, MAC: mac, BDIdx: bdID, @@ -81,11 +51,11 @@ func (fib *L2FibVppCalls) Add(mac string, bdID uint32, ifIdx uint32, bvi bool, s return nil } -// Delete removes existing L2 FIB table entry. -func (fib *L2FibVppCalls) Delete(mac string, bdID uint32, ifIdx uint32, callback func(error)) error { - fib.log.Debug("Removing L2 fib table entry, mac: ", mac) +// Delete implements fib handler. +func (handler *FibVppHandler) Delete(mac string, bdID uint32, ifIdx uint32, callback func(error)) error { + handler.log.Debug("Removing L2 fib table entry, mac: ", mac) - fib.requestChan <- &FibLogicalReq{ + handler.requestChan <- &FibLogicalReq{ IsAdd: false, MAC: mac, BDIdx: bdID, @@ -95,18 +65,18 @@ func (fib *L2FibVppCalls) Delete(mac string, bdID uint32, ifIdx uint32, callback return nil } -// WatchFIBReplies handles L2 FIB add/del requests -func (fib *L2FibVppCalls) WatchFIBReplies() { +// WatchFIBReplies implements fib handler. +func (handler *FibVppHandler) WatchFIBReplies() { for { select { - case r := <-fib.requestChan: - fib.log.Debug("VPP L2FIB request: ", r) - err := l2fibAddDel(r.MAC, r.BDIdx, r.SwIfIdx, r.BVI, r.Static, r.IsAdd, fib.vppChan, fib.stopwatch) + case r := <-handler.requestChan: + handler.log.Debug("VPP L2FIB request: ", r) + err := handler.l2fibAddDel(r.MAC, r.BDIdx, r.SwIfIdx, r.BVI, r.Static, r.IsAdd) if err != nil { - fib.log.WithFields(logging.Fields{"mac": r.MAC, "bdIdx": r.BDIdx}). + handler.log.WithFields(logging.Fields{"mac": r.MAC, "bdIdx": r.BDIdx}). Error("Static fib entry add/delete failed:", err) } else { - fib.log.WithFields(logging.Fields{"mac": r.MAC, "bdIdx": r.BDIdx}). + handler.log.WithFields(logging.Fields{"mac": r.MAC, "bdIdx": r.BDIdx}). Debug("Static fib entry added/deleted.") } r.callback(err) @@ -114,9 +84,9 @@ func (fib *L2FibVppCalls) WatchFIBReplies() { } } -func l2fibAddDel(macstr string, bdIdx, swIfIdx uint32, bvi, static, isAdd bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (err error) { +func (handler *FibVppHandler) l2fibAddDel(macstr string, bdIdx, swIfIdx uint32, bvi, static, isAdd bool) (err error) { defer func(t time.Time) { - stopwatch.TimeLog(l2ba.L2fibAddDel{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(l2ba.L2fibAddDel{}).LogTimeEntry(time.Since(t)) }(time.Now()) var mac []byte @@ -135,12 +105,11 @@ func l2fibAddDel(macstr string, bdIdx, swIfIdx uint32, bvi, static, isAdd bool, BviMac: boolToUint(bvi), StaticMac: boolToUint(static), } - reply := &l2ba.L2fibAddDelReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.asyncCallsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } diff --git a/plugins/vpp/l2plugin/vppcalls/l2fib_vppcalls_test.go b/plugins/vpp/l2plugin/vppcalls/l2fib_vppcalls_test.go index b42fde7530..8892d64e3a 100644 --- a/plugins/vpp/l2plugin/vppcalls/l2fib_vppcalls_test.go +++ b/plugins/vpp/l2plugin/vppcalls/l2fib_vppcalls_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package vppcalls +package vppcalls_test import ( "log" @@ -22,7 +22,11 @@ import ( govppcore "git.fd.io/govpp.git/core" "github.com/ligato/cn-infra/logging/logrus" + "github.com/ligato/vpp-agent/idxvpp/nametoidx" l2ba "github.com/ligato/vpp-agent/plugins/vpp/binapi/l2" + "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" + "github.com/ligato/vpp-agent/plugins/vpp/l2plugin/l2idx" + "github.com/ligato/vpp-agent/plugins/vpp/l2plugin/vppcalls" "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" logrus2 "github.com/sirupsen/logrus" @@ -53,11 +57,10 @@ var deleteTestDataOutFib = &l2ba.L2fibAddDel{ } func TestL2FibAdd(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, fibHandler, _, _ := fibTestSetup(t) defer ctx.TeardownTestCtx() - l2FibVppCalls := NewL2FibVppCalls(logrus.DefaultLogger(), ctx.MockChannel, nil) - go l2FibVppCalls.WatchFIBReplies() + go fibHandler.WatchFIBReplies() errc := make(chan error, len(testDataInFib)) cb := func(err error) { @@ -65,7 +68,7 @@ func TestL2FibAdd(t *testing.T) { } for i := 0; i < len(testDataInFib); i++ { ctx.MockVpp.MockReply(&l2ba.L2fibAddDelReply{}) - l2FibVppCalls.Add(testDataInFib[i].mac, testDataInFib[i].bdID, testDataInFib[i].ifIdx, + fibHandler.Add(testDataInFib[i].mac, testDataInFib[i].bdID, testDataInFib[i].ifIdx, testDataInFib[i].bvi, testDataInFib[i].static, cb) err := <-errc Expect(err).ShouldNot(HaveOccurred()) @@ -74,38 +77,36 @@ func TestL2FibAdd(t *testing.T) { } func TestL2FibAddError(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, fibHandler, _, _ := fibTestSetup(t) defer ctx.TeardownTestCtx() - l2FibVppCalls := NewL2FibVppCalls(logrus.DefaultLogger(), ctx.MockChannel, nil) - go l2FibVppCalls.WatchFIBReplies() + go fibHandler.WatchFIBReplies() errc := make(chan error, len(testDataInFib)) cb := func(err error) { errc <- err } - l2FibVppCalls.Add("not:mac:addr", 4, 10, false, false, cb) + fibHandler.Add("not:mac:addr", 4, 10, false, false, cb) err := <-errc Expect(err).Should(HaveOccurred()) ctx.MockVpp.MockReply(&l2ba.L2fibAddDelReply{Retval: 1}) - l2FibVppCalls.Add("FF:FF:FF:FF:FF:FF", 4, 10, false, false, cb) + fibHandler.Add("FF:FF:FF:FF:FF:FF", 4, 10, false, false, cb) err = <-errc Expect(err).Should(HaveOccurred()) ctx.MockVpp.MockReply(&l2ba.BridgeDomainAddDelReply{}) - l2FibVppCalls.Add("FF:FF:FF:FF:FF:FF", 4, 10, false, false, cb) + fibHandler.Add("FF:FF:FF:FF:FF:FF", 4, 10, false, false, cb) err = <-errc Expect(err).Should(HaveOccurred()) } func TestL2FibDelete(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, fibHandler, _, _ := fibTestSetup(t) defer ctx.TeardownTestCtx() - l2FibVppCalls := NewL2FibVppCalls(logrus.DefaultLogger(), ctx.MockChannel, nil) - go l2FibVppCalls.WatchFIBReplies() + go fibHandler.WatchFIBReplies() errc := make(chan error, len(testDataInFib)) cb := func(err error) { @@ -113,7 +114,7 @@ func TestL2FibDelete(t *testing.T) { } for i := 0; i < len(testDataInFib); i++ { ctx.MockVpp.MockReply(&l2ba.L2fibAddDelReply{}) - l2FibVppCalls.Delete(testDataInFib[i].mac, testDataInFib[i].bdID, testDataInFib[i].ifIdx, cb) + fibHandler.Delete(testDataInFib[i].mac, testDataInFib[i].bdID, testDataInFib[i].ifIdx, cb) err := <-errc Expect(err).ShouldNot(HaveOccurred()) Expect(ctx.MockChannel.Msg).To(Equal(deleteTestDataOutFib)) @@ -121,11 +122,10 @@ func TestL2FibDelete(t *testing.T) { } func TestWatchFIBReplies(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, fibHandler, _, _ := fibTestSetup(t) defer ctx.TeardownTestCtx() - l2FibVppCalls := NewL2FibVppCalls(logrus.DefaultLogger(), ctx.MockChannel, nil) - go l2FibVppCalls.WatchFIBReplies() + go fibHandler.WatchFIBReplies() ctx.MockVpp.MockReply(&l2ba.L2fibAddDelReply{}) @@ -134,7 +134,7 @@ func TestWatchFIBReplies(t *testing.T) { log.Println("dummyCallback:", err) errc <- err } - l2FibVppCalls.Add("FF:FF:FF:FF:FF:FF", 4, 45, false, false, cb) + fibHandler.Add("FF:FF:FF:FF:FF:FF", 4, 45, false, false, cb) select { case err := <-errc: @@ -145,7 +145,7 @@ func TestWatchFIBReplies(t *testing.T) { } func benchmarkWatchFIBReplies(reqN int, b *testing.B) { - ctx := vppcallmock.SetupTestCtx(nil) + ctx, fibHandler, _, _ := fibTestSetup(nil) defer ctx.TeardownTestCtx() // debug logs slow down benchmarks @@ -154,8 +154,7 @@ func benchmarkWatchFIBReplies(reqN int, b *testing.B) { govpplogger.Level = logrus2.WarnLevel govppcore.SetLogger(govpplogger) - l2FibVppCalls := NewL2FibVppCalls(logrus.DefaultLogger(), ctx.MockChannel, nil) - go l2FibVppCalls.WatchFIBReplies() + go fibHandler.WatchFIBReplies() errc := make(chan error, reqN) cb := func(err error) { @@ -165,7 +164,7 @@ func benchmarkWatchFIBReplies(reqN int, b *testing.B) { for n := 0; n < b.N; n++ { for i := 0; i < reqN; i++ { ctx.MockVpp.MockReply(&l2ba.L2fibAddDelReply{}) - l2FibVppCalls.Add("FF:FF:FF:FF:FF:FF", 4, 45, false, false, cb) + fibHandler.Add("FF:FF:FF:FF:FF:FF", 4, 45, false, false, cb) } count := 0 @@ -190,3 +189,12 @@ func BenchmarkWatchFIBReplies1(b *testing.B) { benchmarkWatchFIBReplies(1, b) func BenchmarkWatchFIBReplies10(b *testing.B) { benchmarkWatchFIBReplies(10, b) } func BenchmarkWatchFIBReplies100(b *testing.B) { benchmarkWatchFIBReplies(100, b) } func BenchmarkWatchFIBReplies1000(b *testing.B) { benchmarkWatchFIBReplies(1000, b) } + +func fibTestSetup(t *testing.T) (*vppcallmock.TestCtx, vppcalls.FibVppAPI, ifaceidx.SwIfIndexRW, l2idx.BDIndexRW) { + ctx := vppcallmock.SetupTestCtx(t) + logger := logrus.NewLogger("test-log") + ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logger, "fib-if-idx", nil)) + bdIndexes := l2idx.NewBDIndex(nametoidx.NewNameToIdx(logger, "fib-bd-idx", nil)) + fibHandler := vppcalls.NewFibVppHandler(ctx.MockChannel, ctx.MockChannel, ifIndexes, bdIndexes, logger, nil) + return ctx, fibHandler, ifIndexes, bdIndexes +} diff --git a/plugins/vpp/l2plugin/vppcalls/xconnect_vppcalls.go b/plugins/vpp/l2plugin/vppcalls/xconnect_vppcalls.go index b1066ff973..e00314ce85 100644 --- a/plugins/vpp/l2plugin/vppcalls/xconnect_vppcalls.go +++ b/plugins/vpp/l2plugin/vppcalls/xconnect_vppcalls.go @@ -18,32 +18,22 @@ import ( "fmt" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" l2ba "github.com/ligato/vpp-agent/plugins/vpp/binapi/l2" ) -// XConnectMessages is list of used VPP messages for compatibility check -var XConnectMessages = []govppapi.Message{ - &l2ba.L2XconnectDump{}, - &l2ba.L2XconnectDetails{}, - &l2ba.SwInterfaceSetL2Xconnect{}, - &l2ba.SwInterfaceSetL2XconnectReply{}, +// AddL2XConnect implements xconnect handler. +func (handler *XConnectVppHandler) AddL2XConnect(rxIfIdx uint32, txIfIdx uint32) error { + return handler.addDelXConnect(rxIfIdx, txIfIdx, true) } -// AddL2XConnect creates xConnect between two existing interfaces. -func AddL2XConnect(rxIfIdx uint32, txIfIdx uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return addDelXConnect(rxIfIdx, txIfIdx, true, vppChan, stopwatch) +// DeleteL2XConnect implements xconnect handler. +func (handler *XConnectVppHandler) DeleteL2XConnect(rxIfIdx uint32, txIfIdx uint32) error { + return handler.addDelXConnect(rxIfIdx, txIfIdx, false) } -// DeleteL2XConnect removes xConnect between two interfaces. -func DeleteL2XConnect(rxIfIdx uint32, txIfIdx uint32, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return addDelXConnect(rxIfIdx, txIfIdx, false, vppChan, stopwatch) -} - -func addDelXConnect(rxIfaceIdx uint32, txIfaceIdx uint32, enable bool, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { +func (handler *XConnectVppHandler) addDelXConnect(rxIfaceIdx uint32, txIfaceIdx uint32, enable bool) error { defer func(t time.Time) { - stopwatch.TimeLog(l2ba.SwInterfaceSetL2Xconnect{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(l2ba.SwInterfaceSetL2Xconnect{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &l2ba.SwInterfaceSetL2Xconnect{ @@ -51,12 +41,11 @@ func addDelXConnect(rxIfaceIdx uint32, txIfaceIdx uint32, enable bool, vppChan g TxSwIfIndex: txIfaceIdx, RxSwIfIndex: rxIfaceIdx, } - reply := &l2ba.SwInterfaceSetL2XconnectReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } diff --git a/plugins/vpp/l2plugin/vppcalls/xconnect_vppcalls_test.go b/plugins/vpp/l2plugin/vppcalls/xconnect_vppcalls_test.go index f5cd284fa5..8aef72b514 100644 --- a/plugins/vpp/l2plugin/vppcalls/xconnect_vppcalls_test.go +++ b/plugins/vpp/l2plugin/vppcalls/xconnect_vppcalls_test.go @@ -12,13 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -package vppcalls +package vppcalls_test import ( "testing" govppapi "git.fd.io/govpp.git/api" + "github.com/ligato/cn-infra/logging/logrus" + "github.com/ligato/vpp-agent/idxvpp/nametoidx" l2ba "github.com/ligato/vpp-agent/plugins/vpp/binapi/l2" + "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" + "github.com/ligato/vpp-agent/plugins/vpp/l2plugin/vppcalls" "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" ) @@ -37,9 +41,21 @@ var setTestDataOutXConnect = []struct { outData *l2ba.SwInterfaceSetL2Xconnect isResultOk bool }{ - {&l2ba.SwInterfaceSetL2Xconnect{100, 200, 1}, true}, - {&l2ba.SwInterfaceSetL2Xconnect{100, 200, 1}, false}, - {&l2ba.SwInterfaceSetL2Xconnect{100, 200, 1}, false}, + {&l2ba.SwInterfaceSetL2Xconnect{ + RxSwIfIndex: 100, + TxSwIfIndex: 200, + Enable: 1, + }, true}, + {&l2ba.SwInterfaceSetL2Xconnect{ + RxSwIfIndex: 100, + TxSwIfIndex: 200, + Enable: 1, + }, false}, + {&l2ba.SwInterfaceSetL2Xconnect{ + RxSwIfIndex: 100, + TxSwIfIndex: 200, + Enable: 1, + }, false}, } /** @@ -51,13 +67,13 @@ scenarios: */ // TestVppSetL2XConnect tests VppSetL2XConnect method func TestVppSetL2XConnect(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, xcHandler, _ := xcTestSetup(t) defer ctx.TeardownTestCtx() for i := 0; i < len(setTestDataInXConnect); i++ { ctx.MockVpp.MockReply(setTestDataInXConnect[i].message) - err := AddL2XConnect(setTestDataInXConnect[i].receiveIfaceIndex, - setTestDataInXConnect[i].transmitIfaceIndex, ctx.MockChannel, nil) + err := xcHandler.AddL2XConnect(setTestDataInXConnect[i].receiveIfaceIndex, + setTestDataInXConnect[i].transmitIfaceIndex) if setTestDataOutXConnect[i].isResultOk { Expect(err).To(BeNil()) @@ -82,9 +98,21 @@ var unsetTestDataOutXConnect = []struct { outData *l2ba.SwInterfaceSetL2Xconnect isResultOk bool }{ - {&l2ba.SwInterfaceSetL2Xconnect{100, 200, 0}, true}, - {&l2ba.SwInterfaceSetL2Xconnect{100, 200, 0}, false}, - {&l2ba.SwInterfaceSetL2Xconnect{100, 200, 0}, false}, + {&l2ba.SwInterfaceSetL2Xconnect{ + RxSwIfIndex: 100, + TxSwIfIndex: 200, + Enable: 0, + }, true}, + {&l2ba.SwInterfaceSetL2Xconnect{ + RxSwIfIndex: 100, + TxSwIfIndex: 200, + Enable: 0, + }, false}, + {&l2ba.SwInterfaceSetL2Xconnect{ + RxSwIfIndex: 100, + TxSwIfIndex: 200, + Enable: 0, + }, false}, } /** @@ -96,13 +124,13 @@ scenarios: */ // TestVppUnsetL2XConnect tests VppUnsetL2XConnect method func TestVppUnsetL2XConnect(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, xcHandler, _ := xcTestSetup(t) defer ctx.TeardownTestCtx() for i := 0; i < len(unsetTestDataInXConnect); i++ { ctx.MockVpp.MockReply(unsetTestDataInXConnect[i].message) - err := DeleteL2XConnect(unsetTestDataInXConnect[i].receiveIfaceIndex, - unsetTestDataInXConnect[i].transmitIfaceIndex, ctx.MockChannel, nil) + err := xcHandler.DeleteL2XConnect(unsetTestDataInXConnect[i].receiveIfaceIndex, + unsetTestDataInXConnect[i].transmitIfaceIndex) if unsetTestDataOutXConnect[i].isResultOk { Expect(err).To(BeNil()) @@ -112,3 +140,11 @@ func TestVppUnsetL2XConnect(t *testing.T) { Expect(ctx.MockChannel.Msg).To(Equal(unsetTestDataOutXConnect[i].outData)) } } + +func xcTestSetup(t *testing.T) (*vppcallmock.TestCtx, vppcalls.XConnectVppAPI, ifaceidx.SwIfIndexRW) { + ctx := vppcallmock.SetupTestCtx(t) + log := logrus.NewLogger("test-log") + ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(log, "xc-if-idx", nil)) + xcHandler := vppcalls.NewXConnectVppHandler(ctx.MockChannel, ifIndexes, log, nil) + return ctx, xcHandler, ifIndexes +} diff --git a/plugins/vpp/l2plugin/vppdump/doc.go b/plugins/vpp/l2plugin/vppdump/doc.go deleted file mode 100644 index 93494dde3d..0000000000 --- a/plugins/vpp/l2plugin/vppdump/doc.go +++ /dev/null @@ -1,3 +0,0 @@ -// Package vppdump provides helpers for dumping all bridge-domains, L2 FIBs and -// XConnect pairs configured in VPP. -package vppdump diff --git a/plugins/vpp/l2plugin/vppdump/dump_vppcalls.go b/plugins/vpp/l2plugin/vppdump/dump_vppcalls.go deleted file mode 100644 index 57e3475501..0000000000 --- a/plugins/vpp/l2plugin/vppdump/dump_vppcalls.go +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright (c) 2017 Cisco and/or its affiliates. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at: -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package vppdump - -import ( - "bytes" - "net" - "time" - - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" - l2ba "github.com/ligato/vpp-agent/plugins/vpp/binapi/l2" - l2nb "github.com/ligato/vpp-agent/plugins/vpp/model/l2" -) - -// DumpBridgeDomainIDs lists all configured bridge domains. Auxiliary method for LookupFIBEntries. -// returns list of bridge domain IDs (BD IDs). First element of returned slice is 0. It is default BD to which all -// interfaces belong -func DumpBridgeDomainIDs(vppChannel govppapi.Channel, stopwatch *measure.Stopwatch) ([]uint32, error) { - defer func(t time.Time) { - stopwatch.TimeLog(l2ba.BridgeDomainDump{}).LogTimeEntry(time.Since(t)) - }(time.Now()) - - req := &l2ba.BridgeDomainDump{BdID: ^uint32(0)} - activeDomains := make([]uint32, 1) - reqCtx := vppChannel.SendMultiRequest(req) - for { - msg := &l2ba.BridgeDomainDetails{} - stop, err := reqCtx.ReceiveReply(msg) - if err != nil { - return nil, err - } - if stop { - break - } - activeDomains = append(activeDomains, msg.BdID) - } - - return activeDomains, nil -} - -// BridgeDomain is the wrapper structure for the bridge domain northbound API structure. -// NOTE: Interfaces in BridgeDomains_BridgeDomain is overridden by the local Interfaces member. -type BridgeDomain struct { - Interfaces []*BridgeDomainInterface `json:"interfaces"` - l2nb.BridgeDomains_BridgeDomain -} - -// BridgeDomainInterface is the wrapper structure for the bridge domain interface northbound API structure. -type BridgeDomainInterface struct { - SwIfIndex uint32 `json:"sw_if_index"` - l2nb.BridgeDomains_BridgeDomain_Interfaces -} - -// DumpBridgeDomains dumps VPP bridge domain data into the northbound API data structure -// map indexed by bridge domain ID. -// -// LIMITATIONS: -// - not able to dump ArpTerminationTable - missing binary API -// -func DumpBridgeDomains(vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (map[uint32]*BridgeDomain, error) { - defer func(t time.Time) { - stopwatch.TimeLog(l2ba.BridgeDomainDump{}).LogTimeEntry(time.Since(t)) - }(time.Now()) - - // map for the resulting BDs - bds := make(map[uint32]*BridgeDomain) - - // First, dump all interfaces to create initial data. - reqCtx := vppChan.SendMultiRequest(&l2ba.BridgeDomainDump{BdID: ^uint32(0)}) - - for { - bdDetails := &l2ba.BridgeDomainDetails{} - stop, err := reqCtx.ReceiveReply(bdDetails) - if stop { - break // Break from the loop. - } - if err != nil { - return nil, err - } - - // bridge domain details - bds[bdDetails.BdID] = &BridgeDomain{ - Interfaces: []*BridgeDomainInterface{}, - BridgeDomains_BridgeDomain: l2nb.BridgeDomains_BridgeDomain{ - Name: string(bytes.Replace(bdDetails.BdTag, []byte{0x00}, []byte{}, -1)), - Flood: bdDetails.Flood > 0, - UnknownUnicastFlood: bdDetails.UuFlood > 0, - Forward: bdDetails.Forward > 0, - Learn: bdDetails.Learn > 0, - ArpTermination: bdDetails.ArpTerm > 0, - MacAge: uint32(bdDetails.MacAge), - }, - } - - // bridge domain interfaces - for _, iface := range bdDetails.SwIfDetails { - bds[bdDetails.BdID].Interfaces = append(bds[bdDetails.BdID].Interfaces, &BridgeDomainInterface{ - SwIfIndex: iface.SwIfIndex, - }) - } - - } - - return bds, nil -} - -// FIBTableEntry is the wrapper structure for the FIB table entry northbound API structure. -type FIBTableEntry struct { - BridgeDomainIdx uint32 `json:"bridge_domain_idx"` - OutgoingInterfaceSwIfIdx uint32 `json:"outgoing_interface_sw_if_idx"` - l2nb.FibTable_FibEntry -} - -// DumpFIBTableEntries dumps VPP FIB table entries into the northbound API data structure -// map indexed by destination MAC address. -func DumpFIBTableEntries(vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (map[string]*FIBTableEntry, error) { - defer func(t time.Time) { - stopwatch.TimeLog(l2ba.L2FibTableDump{}).LogTimeEntry(time.Since(t)) - }(time.Now()) - - // map for the resulting FIBs - fibs := make(map[string]*FIBTableEntry) - - reqCtx := vppChan.SendMultiRequest(&l2ba.L2FibTableDump{BdID: ^uint32(0)}) - for { - fibDetails := &l2ba.L2FibTableDetails{} - stop, err := reqCtx.ReceiveReply(fibDetails) - if stop { - break // Break from the loop. - } - if err != nil { - return nil, err - } - - mac := net.HardwareAddr(fibDetails.Mac).String() - var action l2nb.FibTable_FibEntry_Action - if fibDetails.FilterMac > 0 { - action = l2nb.FibTable_FibEntry_DROP - } else { - action = l2nb.FibTable_FibEntry_FORWARD - } - - fibs[mac] = &FIBTableEntry{ - BridgeDomainIdx: uint32(fibDetails.BdID), - OutgoingInterfaceSwIfIdx: fibDetails.SwIfIndex, - FibTable_FibEntry: l2nb.FibTable_FibEntry{ - PhysAddress: mac, - Action: action, - StaticConfig: fibDetails.StaticMac > 0, - BridgedVirtualInterface: fibDetails.BviMac > 0, - }, - } - } - - return fibs, nil -} - -// XConnectPairs is the wrapper structure for the l2 xconnect northbound API structure. -type XConnectPairs struct { - ReceiveInterfaceSwIfIdx uint32 `json:"receive_interface_sw_if_idx"` - TransmitInterfaceSwIfIdx uint32 `json:"transmit_interface_sw_if_idx"` -} - -// DumpXConnectPairs dumps VPP xconnect pair data into the northbound API data structure -// map indexed by rx interface index. -func DumpXConnectPairs(vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (map[uint32]*XConnectPairs, error) { - defer func(t time.Time) { - stopwatch.TimeLog(l2ba.L2XconnectDump{}).LogTimeEntry(time.Since(t)) - }(time.Now()) - - // map for the resulting xconnect pairs - xpairs := make(map[uint32]*XConnectPairs) - - reqCtx := vppChan.SendMultiRequest(&l2ba.L2XconnectDump{}) - for { - pairs := &l2ba.L2XconnectDetails{} - stop, err := reqCtx.ReceiveReply(pairs) - if stop { - break // Break from the loop. - } - if err != nil { - return nil, err - } - - xpairs[pairs.RxSwIfIndex] = &XConnectPairs{ - ReceiveInterfaceSwIfIdx: pairs.RxSwIfIndex, - TransmitInterfaceSwIfIdx: pairs.TxSwIfIndex, - } - } - - return xpairs, nil -} diff --git a/plugins/vpp/l2plugin/xconnect_config.go b/plugins/vpp/l2plugin/xconnect_config.go index cef26597df..bdfd5a6afd 100644 --- a/plugins/vpp/l2plugin/xconnect_config.go +++ b/plugins/vpp/l2plugin/xconnect_config.go @@ -41,6 +41,7 @@ type XConnectConfigurator struct { xcIndexSeq uint32 vppChan govppapi.Channel + xcHandler vppcalls.XConnectVppAPI stopwatch *measure.Stopwatch // Timer used to measure and store time } @@ -51,6 +52,11 @@ func (plugin *XConnectConfigurator) Init(logger logging.PluginLogger, goVppMux g plugin.log = logger.NewLogger("-xc-conf") plugin.log.Info("Initializing L2 xConnect configurator") + // Stopwatch + if enableStopwatch { + plugin.stopwatch = measure.NewStopwatch("XCConfigurator", plugin.log) + } + // Mappings plugin.ifIndexes = swIfIndexes plugin.xcIndexes = l2idx.NewXcIndex(nametoidx.NewNameToIdx(plugin.log, "xc-indexes", nil)) @@ -64,16 +70,8 @@ func (plugin *XConnectConfigurator) Init(logger logging.PluginLogger, goVppMux g return err } - // Stopwatch - if enableStopwatch { - plugin.stopwatch = measure.NewStopwatch("BFDConfigurator", plugin.log) - } - - // Message compatibility - if err = plugin.vppChan.CheckMessageCompatibility(vppcalls.XConnectMessages...); err != nil { - plugin.log.Error(err) - return err - } + // Cross-connect VPP API handler + plugin.xcHandler = vppcalls.NewXConnectVppHandler(plugin.vppChan, plugin.ifIndexes, plugin.log, plugin.stopwatch) return nil } @@ -125,7 +123,7 @@ func (plugin *XConnectConfigurator) ConfigureXConnectPair(xc *l2.XConnectPairs_X return nil } // XConnect can be configured now - if err := vppcalls.AddL2XConnect(rxIfIdx, txIfIdx, plugin.vppChan, plugin.stopwatch); err != nil { + if err := plugin.xcHandler.AddL2XConnect(rxIfIdx, txIfIdx); err != nil { plugin.log.Errorf("Adding l2xConnect failed: %v", err) return err } @@ -166,7 +164,7 @@ func (plugin *XConnectConfigurator) ModifyXConnectPair(newXc, oldXc *l2.XConnect return nil // Nothing more can be done } plugin.log.Debugf("Removing obsolete l2xConnect %s-%s", oldXc.ReceiveInterface, oldXc.TransmitInterface) - if err := vppcalls.DeleteL2XConnect(rxIfIdx, oldTxIfIdx, plugin.vppChan, plugin.stopwatch); err != nil { + if err := plugin.xcHandler.DeleteL2XConnect(rxIfIdx, oldTxIfIdx); err != nil { plugin.log.Errorf("Deleted obsolete l2xConnect failed: %v", err) return err } @@ -174,7 +172,7 @@ func (plugin *XConnectConfigurator) ModifyXConnectPair(newXc, oldXc *l2.XConnect return nil } // Replace existing entry - if err := vppcalls.AddL2XConnect(rxIfIdx, txIfIdx, plugin.vppChan, plugin.stopwatch); err != nil { + if err := plugin.xcHandler.AddL2XConnect(rxIfIdx, txIfIdx); err != nil { plugin.log.Errorf("Replacing l2xConnect failed: %v", err) return err } @@ -214,7 +212,7 @@ func (plugin *XConnectConfigurator) DeleteXConnectPair(xc *l2.XConnectPairs_XCon return nil } // XConnect can be removed now - if err := vppcalls.DeleteL2XConnect(rxIfIdx, txIfIdx, plugin.vppChan, plugin.stopwatch); err != nil { + if err := plugin.xcHandler.DeleteL2XConnect(rxIfIdx, txIfIdx); err != nil { plugin.log.Errorf("Removing l2xConnect failed: %v", err) return err } diff --git a/plugins/vpp/l2plugin/xconnect_config_test.go b/plugins/vpp/l2plugin/xconnect_config_test.go index a0c17c3e3d..88d2c60e4a 100644 --- a/plugins/vpp/l2plugin/xconnect_config_test.go +++ b/plugins/vpp/l2plugin/xconnect_config_test.go @@ -20,7 +20,6 @@ import ( "git.fd.io/govpp.git/adapter/mock" "git.fd.io/govpp.git/core" "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/idxvpp/nametoidx" l2api "github.com/ligato/vpp-agent/plugins/vpp/binapi/l2" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" @@ -33,26 +32,6 @@ import ( /* XConnect configurator init and close */ -// Test init function -func TestXConnectConfiguratorInit(t *testing.T) { - var err error - // Setup - RegisterTestingT(t) - ctx := &vppcallmock.TestCtx{ - MockVpp: &mock.VppAdapter{}, - } - connection, _ := core.Connect(ctx.MockVpp) - defer connection.Disconnect() - plugin := &l2plugin.XConnectConfigurator{} - // Test init - err = plugin.Init(logging.ForPlugin("test-log", logrus.NewLogRegistry()), connection, - nil, false) - Expect(err).To(BeNil()) - // Test close - err = plugin.Close() - Expect(err).To(BeNil()) -} - /* XConnect configurator test cases */ // Basic configuration of cross connect pair @@ -620,7 +599,7 @@ func xcTestSetup(t *testing.T) (*vppcallmock.TestCtx, *core.Connection, *l2plugi connection, err := core.Connect(ctx.MockVpp) Expect(err).ShouldNot(HaveOccurred()) // Logger - log := logging.ForPlugin("test-log", logrus.NewLogRegistry()) + log := logging.ForPlugin("test-log") log.SetLevel(logging.DebugLevel) // Interface indices swIfIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(log, "xc-if", nil)) @@ -636,6 +615,7 @@ func xcTestTeardown(connection *core.Connection, plugin *l2plugin.XConnectConfig connection.Disconnect() err := plugin.Close() Expect(err).To(BeNil()) + logging.DefaultRegistry.ClearRegistry() } /* XConnect Test Data */ diff --git a/plugins/vpp/l3plugin/arp_config.go b/plugins/vpp/l3plugin/arp_config.go index 2164a1d764..da4f37de20 100644 --- a/plugins/vpp/l3plugin/arp_config.go +++ b/plugins/vpp/l3plugin/arp_config.go @@ -52,6 +52,8 @@ type ArpConfigurator struct { // VPP channel vppChan govppapi.Channel + // VPP API handler + arpHandler vppcalls.ArpVppAPI // Timer used to measure and store time stopwatch *measure.Stopwatch @@ -64,6 +66,11 @@ func (plugin *ArpConfigurator) Init(logger logging.PluginLogger, goVppMux govppm plugin.log = logger.NewLogger("-l3-arp-conf") plugin.log.Debug("Initializing ARP configurator") + // Configurator-wide stopwatch instance + if enableStopwatch { + plugin.stopwatch = measure.NewStopwatch("ARP-configurator", plugin.log) + } + // Mappings plugin.ifIndexes = swIfIndexes plugin.arpIndexes = l3idx.NewARPIndex(nametoidx.NewNameToIdx(plugin.log, "arp_indexes", nil)) @@ -77,16 +84,8 @@ func (plugin *ArpConfigurator) Init(logger logging.PluginLogger, goVppMux govppm return err } - // Stopwatch - if enableStopwatch { - plugin.stopwatch = measure.NewStopwatch("ARPConfigurator", plugin.log) - } - - // Message compatibility - if err := plugin.vppChan.CheckMessageCompatibility(vppcalls.ArpMessages...); err != nil { - plugin.log.Error(err) - return err - } + // VPP API handler + plugin.arpHandler = vppcalls.NewArpVppHandler(plugin.vppChan, plugin.ifIndexes, plugin.log, plugin.stopwatch) return nil } @@ -160,7 +159,7 @@ func (plugin *ArpConfigurator) AddArp(entry *l3.ArpTable_ArpEntry) error { plugin.log.Debugf("adding ARP: %+v", *arp) // Create and register new arp entry - if err = vppcalls.VppAddArp(arp, plugin.vppChan, plugin.stopwatch); err != nil { + if err = plugin.arpHandler.VppAddArp(arp); err != nil { return err } @@ -235,7 +234,7 @@ func (plugin *ArpConfigurator) DeleteArp(entry *l3.ArpTable_ArpEntry) error { plugin.log.Debugf("deleting ARP: %+v", arp) // Delete and un-register new arp - if err = vppcalls.VppDelArp(arp, plugin.vppChan, plugin.stopwatch); err != nil { + if err = plugin.arpHandler.VppDelArp(arp); err != nil { return err } _, _, found = plugin.arpIndexes.UnregisterName(arpID) @@ -319,14 +318,10 @@ func isValidARP(arpInput *l3.ArpTable_ArpEntry, log logging.Logger) bool { // transformArp converts raw entry data to ARP object func transformArp(arpInput *l3.ArpTable_ArpEntry, ifIndex uint32) (*vppcalls.ArpEntry, error) { ipAddr := net.ParseIP(arpInput.IpAddress) - macAddr, err := net.ParseMAC(arpInput.PhysAddress) - if err != nil { - return nil, err - } arp := &vppcalls.ArpEntry{ Interface: ifIndex, IPAddress: ipAddr, - MacAddress: macAddr, + MacAddress: arpInput.PhysAddress, Static: arpInput.Static, } return arp, nil diff --git a/plugins/vpp/l3plugin/arp_config_test.go b/plugins/vpp/l3plugin/arp_config_test.go index 5e1ec9f7af..8d15d38cfa 100644 --- a/plugins/vpp/l3plugin/arp_config_test.go +++ b/plugins/vpp/l3plugin/arp_config_test.go @@ -15,10 +15,11 @@ package l3plugin_test import ( + "testing" + "git.fd.io/govpp.git/adapter/mock" "git.fd.io/govpp.git/core" "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" @@ -26,27 +27,8 @@ import ( "github.com/ligato/vpp-agent/plugins/vpp/model/l3" "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" - "testing" ) -// Test ArpConfigurator initialization -func TestArpConfiguratorInit(t *testing.T) { - RegisterTestingT(t) - ctx := &vppcallmock.TestCtx{ - MockVpp: &mock.VppAdapter{}, - } - connection, _ := core.Connect(ctx.MockVpp) - defer connection.Disconnect() - - plugin := &l3plugin.ArpConfigurator{} - - // Test init - err := plugin.Init(logging.ForPlugin("test-log", logrus.NewLogRegistry()), connection, nil, false) - Expect(err).To(BeNil()) - err = plugin.Close() - Expect(err).To(BeNil()) -} - // Test adding of ARP entry to cached indexes func TestAddArpCached(t *testing.T) { // Setup @@ -313,9 +295,9 @@ func arpTestSetup(t *testing.T) (*vppcallmock.TestCtx, *core.Connection, *l3plug Expect(err).ShouldNot(HaveOccurred()) plugin := &l3plugin.ArpConfigurator{} - ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logging.ForPlugin("test-log", logrus.NewLogRegistry()), "l3-plugin", nil)) + ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logging.ForPlugin("test-log"), "l3-plugin", nil)) - err = plugin.Init(logging.ForPlugin("test-log", logrus.NewLogRegistry()), connection, ifIndexes, false) + err = plugin.Init(logging.ForPlugin("test-log"), connection, ifIndexes, false) Expect(err).To(BeNil()) return ctx, connection, plugin, ifIndexes @@ -324,6 +306,6 @@ func arpTestSetup(t *testing.T) (*vppcallmock.TestCtx, *core.Connection, *l3plug // Test Teardown func arpTestTeardown(connection *core.Connection, plugin *l3plugin.ArpConfigurator) { connection.Disconnect() - err := plugin.Close() - Expect(err).To(BeNil()) + Expect(plugin.Close()).To(BeNil()) + logging.DefaultRegistry.ClearRegistry() } diff --git a/plugins/vpp/l3plugin/arp_proxy_config.go b/plugins/vpp/l3plugin/arp_proxy_config.go index 19261182cb..52a05db5d7 100644 --- a/plugins/vpp/l3plugin/arp_proxy_config.go +++ b/plugins/vpp/l3plugin/arp_proxy_config.go @@ -51,18 +51,25 @@ type ProxyArpConfigurator struct { // VPP channel vppChan govppapi.Channel + // VPP API channel + pArpHandler vppcalls.ProxyArpVppAPI // Timer used to measure and store time stopwatch *measure.Stopwatch } -// Init VPP channel and check message compatibility +// Init VPP channel and vppcalls handler func (plugin *ProxyArpConfigurator) Init(logger logging.PluginLogger, goVppMux govppmux.API, swIfIndexes ifaceidx.SwIfIndex, enableStopwatch bool) (err error) { // Logger plugin.log = logger.NewLogger("-l3-proxy-arp-conf") plugin.log.Debugf("Initializing proxy ARP configurator") + // Configurator-wide stopwatch instance + if enableStopwatch { + plugin.stopwatch = measure.NewStopwatch("ARP-proxy-configurator", plugin.log) + } + // Mappings plugin.ifIndexes = swIfIndexes plugin.pArpIfIndexes = nametoidx.NewNameToIdx(plugin.log, "proxyarp_if_indices", nil) @@ -75,16 +82,8 @@ func (plugin *ProxyArpConfigurator) Init(logger logging.PluginLogger, goVppMux g return err } - // Stopwatch - if enableStopwatch { - plugin.stopwatch = measure.NewStopwatch("ProxyARPConfigurator", plugin.log) - } - - // Message compatibility - if err := plugin.vppChan.CheckMessageCompatibility(vppcalls.ProxyArpMessages...); err != nil { - plugin.log.Error(err) - return err - } + // VPP API handler + plugin.pArpHandler = vppcalls.NewProxyArpVppHandler(plugin.vppChan, plugin.ifIndexes, plugin.log, plugin.stopwatch) return nil } @@ -115,6 +114,7 @@ func (plugin *ProxyArpConfigurator) GetArpIfCache() []string { return plugin.pArpIfCache } +// AddInterface implements proxy arp handler. func (plugin *ProxyArpConfigurator) AddInterface(pArpIf *l3.ProxyArpInterfaces_InterfaceList) error { plugin.log.Infof("Enabling interfaces from proxy ARP config %s", pArpIf.Label) @@ -134,7 +134,7 @@ func (plugin *ProxyArpConfigurator) AddInterface(pArpIf *l3.ProxyArpInterfaces_I } // Call VPP API to enable interface for proxy ARP - if err := vppcalls.EnableProxyArpInterface(ifIdx, plugin.vppChan, plugin.log, plugin.stopwatch); err == nil { + if err := plugin.pArpHandler.EnableProxyArpInterface(ifIdx); err == nil { plugin.log.Debugf("Interface %s enabled for proxy ARP", ifName) } else { err := fmt.Errorf("enabling interface %s for proxy ARP failed: %v", ifName, err) @@ -168,7 +168,7 @@ func (plugin *ProxyArpConfigurator) ModifyInterface(newPArpIf, oldPArpIf *l3.Pro ifIdx, _, found := plugin.ifIndexes.LookupIdx(ifName) // If interface is not found, there is nothing to do if found { - if err := vppcalls.DisableProxyArpInterface(ifIdx, plugin.vppChan, plugin.log, plugin.stopwatch); err == nil { + if err := plugin.pArpHandler.DisableProxyArpInterface(ifIdx); err == nil { plugin.log.Debugf("Interface %s disabled for proxy ARP", ifName) } else { err = fmt.Errorf("disabling interface %s for proxy ARP failed: %v", ifName, err) @@ -187,7 +187,7 @@ func (plugin *ProxyArpConfigurator) ModifyInterface(newPArpIf, oldPArpIf *l3.Pro continue } // Configure - if err := vppcalls.EnableProxyArpInterface(ifIdx, plugin.vppChan, plugin.log, plugin.stopwatch); err == nil { + if err := plugin.pArpHandler.EnableProxyArpInterface(ifIdx); err == nil { plugin.log.Debugf("Interface %s enabled for proxy ARP", ifName) } else { err := fmt.Errorf("enabling interface %s for proxy ARP failed: %v", ifName, err) @@ -222,7 +222,7 @@ ProxyArpIfLoop: continue } // Call VPP API to disable interface for proxy ARP - if err := vppcalls.DisableProxyArpInterface(ifIdx, plugin.vppChan, plugin.log, plugin.stopwatch); err == nil { + if err := plugin.pArpHandler.DisableProxyArpInterface(ifIdx); err == nil { plugin.log.Debugf("Interface %s disabled for proxy ARP", ifName) } else { err = fmt.Errorf("disabling interface %s for proxy ARP failed: %v", ifName, err) @@ -257,7 +257,7 @@ func (plugin *ProxyArpConfigurator) AddRange(pArpRng *l3.ProxyArpRanges_RangeLis bFirstIP := net.ParseIP(firstIP).To4() bLastIP := net.ParseIP(lastIP).To4() // Call VPP API to configure IP range for proxy ARP - if err := vppcalls.AddProxyArpRange(bFirstIP, bLastIP, plugin.vppChan, plugin.log, plugin.stopwatch); err == nil { + if err := plugin.pArpHandler.AddProxyArpRange(bFirstIP, bLastIP); err == nil { plugin.log.Debugf("Address range %s - %s configured for proxy ARP", firstIP, lastIP) } else { err := fmt.Errorf("failed to configure proxy ARP address range %s - %s: %v", firstIP, lastIP, err) @@ -295,7 +295,7 @@ func (plugin *ProxyArpConfigurator) ModifyRange(newPArpRng, oldPArpRng *l3.Proxy bFirstIP := net.ParseIP(firstIP).To4() bLastIP := net.ParseIP(lastIP).To4() // Call VPP API to configure IP range for proxy ARP - if err := vppcalls.DeleteProxyArpRange(bFirstIP, bLastIP, plugin.vppChan, plugin.log, plugin.stopwatch); err == nil { + if err := plugin.pArpHandler.DeleteProxyArpRange(bFirstIP, bLastIP); err == nil { plugin.log.Debugf("Address range %s - %s removed from proxy ARP setup", firstIP, lastIP) } else { err = fmt.Errorf("failed to remove proxy ARP address range %s - %s: %v", firstIP, lastIP, err) @@ -320,7 +320,7 @@ func (plugin *ProxyArpConfigurator) ModifyRange(newPArpRng, oldPArpRng *l3.Proxy bFirstIP := net.ParseIP(firstIP).To4() bLastIP := net.ParseIP(lastIP).To4() // Call VPP API to configure IP range for proxy ARP - if err := vppcalls.AddProxyArpRange(bFirstIP, bLastIP, plugin.vppChan, plugin.log, plugin.stopwatch); err == nil { + if err := plugin.pArpHandler.AddProxyArpRange(bFirstIP, bLastIP); err == nil { plugin.log.Debugf("Address range %s - %s configured for proxy ARP", firstIP, lastIP) } else { err := fmt.Errorf("failed to configure proxy ARP address range %s - %s: %v", firstIP, lastIP, err) @@ -333,6 +333,7 @@ func (plugin *ProxyArpConfigurator) ModifyRange(newPArpRng, oldPArpRng *l3.Proxy return nil } +// DeleteRange implements proxy arp handler. func (plugin *ProxyArpConfigurator) DeleteRange(pArpRng *l3.ProxyArpRanges_RangeList) error { plugin.log.Infof("Removing proxy ARP IP range config %s", pArpRng.Label) @@ -352,7 +353,7 @@ func (plugin *ProxyArpConfigurator) DeleteRange(pArpRng *l3.ProxyArpRanges_Range bFirstIP := net.ParseIP(firstIP).To4() bLastIP := net.ParseIP(lastIP).To4() // Call VPP API to configure IP range for proxy ARP - if err := vppcalls.DeleteProxyArpRange(bFirstIP, bLastIP, plugin.vppChan, plugin.log, plugin.stopwatch); err == nil { + if err := plugin.pArpHandler.DeleteProxyArpRange(bFirstIP, bLastIP); err == nil { plugin.log.Debugf("Address range %s - %s removed from proxy ARP setup", firstIP, lastIP) } else { err = fmt.Errorf("failed to remove proxy ARP address range %s - %s: %v", firstIP, lastIP, err) @@ -375,7 +376,7 @@ func (plugin *ProxyArpConfigurator) ResolveCreatedInterface(ifName string, ifIdx for idx, cachedIf := range plugin.pArpIfCache { if cachedIf == ifName { // Configure cached interface - if err := vppcalls.EnableProxyArpInterface(ifIdx, plugin.vppChan, plugin.log, plugin.stopwatch); err != nil { + if err := plugin.pArpHandler.EnableProxyArpInterface(ifIdx); err != nil { plugin.log.Error(err) return err } diff --git a/plugins/vpp/l3plugin/arp_proxy_config_test.go b/plugins/vpp/l3plugin/arp_proxy_config_test.go index 978f7b5886..d56f46e743 100644 --- a/plugins/vpp/l3plugin/arp_proxy_config_test.go +++ b/plugins/vpp/l3plugin/arp_proxy_config_test.go @@ -15,10 +15,11 @@ package l3plugin_test import ( + "testing" + "git.fd.io/govpp.git/adapter/mock" "git.fd.io/govpp.git/core" "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" @@ -26,27 +27,8 @@ import ( "github.com/ligato/vpp-agent/plugins/vpp/model/l3" "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" - "testing" ) -// Test ProxyArpConfigurator initialization -func TestProxyArpConfiguratorInit(t *testing.T) { - RegisterTestingT(t) - ctx := &vppcallmock.TestCtx{ - MockVpp: &mock.VppAdapter{}, - } - connection, _ := core.Connect(ctx.MockVpp) - defer connection.Disconnect() - - plugin := &l3plugin.ProxyArpConfigurator{} - - // Test init - err := plugin.Init(logging.ForPlugin("test-log", logrus.NewLogRegistry()), connection, nil, false) - Expect(err).To(BeNil()) - err = plugin.Close() - Expect(err).To(BeNil()) -} - // Test adding of ARP proxy entry func TestAddInterface(t *testing.T) { // Setup @@ -428,9 +410,9 @@ func proxyarpTestSetup(t *testing.T) (*vppcallmock.TestCtx, *core.Connection, *l Expect(err).ShouldNot(HaveOccurred()) plugin := &l3plugin.ProxyArpConfigurator{} - ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logging.ForPlugin("test-log", logrus.NewLogRegistry()), "l3-plugin", nil)) + ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logging.ForPlugin("test-log"), "l3-plugin", nil)) - err = plugin.Init(logging.ForPlugin("test-log", logrus.NewLogRegistry()), connection, ifIndexes, false) + err = plugin.Init(logging.ForPlugin("test-log"), connection, ifIndexes, false) Expect(err).To(BeNil()) return ctx, connection, plugin, ifIndexes @@ -439,6 +421,6 @@ func proxyarpTestSetup(t *testing.T) (*vppcallmock.TestCtx, *core.Connection, *l // Test Teardown func proxyarpTestTeardown(connection *core.Connection, plugin *l3plugin.ProxyArpConfigurator) { connection.Disconnect() - err := plugin.Close() - Expect(err).To(BeNil()) + Expect(plugin.Close()).To(BeNil()) + logging.DefaultRegistry.ClearRegistry() } diff --git a/plugins/vpp/l3plugin/data_resync.go b/plugins/vpp/l3plugin/data_resync.go index 2fbe33385c..56caa596ff 100644 --- a/plugins/vpp/l3plugin/data_resync.go +++ b/plugins/vpp/l3plugin/data_resync.go @@ -15,9 +15,12 @@ package l3plugin import ( - "github.com/ligato/cn-infra/logging/measure" - l3ba "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" - "github.com/ligato/vpp-agent/plugins/vpp/l3plugin/vppdump" + "fmt" + + "net" + + "github.com/ligato/cn-infra/utils/addrs" + "github.com/ligato/vpp-agent/plugins/vpp/l3plugin/vppcalls" "github.com/ligato/vpp-agent/plugins/vpp/model/l3" ) @@ -35,43 +38,57 @@ func (plugin *RouteConfigurator) Resync(nbRoutes []*l3.StaticRoutes_Route) error plugin.clearMapping() // Retrieve VPP route configuration - vppRoutes, err := vppdump.DumpStaticRoutes(plugin.log, plugin.vppChan, measure.GetTimeLog(l3ba.IPFibDump{}, plugin.stopwatch)) + vppRouteDetails, err := plugin.rtHandler.DumpStaticRoutes() if err != nil { return err } - plugin.log.Debugf("Found %d routes configured on the VPP", len(vppRoutes)) + plugin.log.Debugf("Found %d routes configured on the VPP", len(vppRouteDetails)) // Correlate NB and VPP configuration for _, nbRoute := range nbRoutes { nbRouteID := routeIdentifier(nbRoute.VrfId, nbRoute.DstIpAddr, nbRoute.NextHopAddr) nbIfIdx, _, found := plugin.ifIndexes.LookupIdx(nbRoute.OutgoingInterface) if !found { - plugin.log.Debugf("RESYNC routes: outgoing interface not found for %s", nbRouteID) - plugin.rtCachedIndexes.RegisterName(nbRouteID, plugin.rtIndexSeq, nbRoute) - plugin.rtIndexSeq++ - continue + if nbRoute.Type == l3.StaticRoutes_Route_INTER_VRF { + // expected by inter VRF-routes + nbIfIdx = vppcalls.NextHopOutgoingIfUnset + } else { + plugin.log.Debugf("RESYNC routes: outgoing interface not found for %s", nbRouteID) + plugin.rtCachedIndexes.RegisterName(nbRouteID, plugin.rtIndexSeq, nbRoute) + plugin.rtIndexSeq++ + continue + } } // Default VPP value for weight in case it is not set if nbRoute.Weight == 0 { nbRoute.Weight = 1 } // Look for the same route in the configuration - for _, vppRoute := range vppRoutes { - vppRouteID := routeIdentifier(vppRoute.VrfID, vppRoute.DstAddr.String(), vppRoute.NextHopAddr.String()) + for _, vppRouteDetail := range vppRouteDetails { + if vppRouteDetail.Route == nil { + continue + } + vppRoute := vppRouteDetail.Route + vppRouteID := routeIdentifier(vppRoute.VrfId, vppRoute.DstIpAddr, vppRoute.NextHopAddr) plugin.log.Debugf("RESYNC routes: comparing %s and %s", nbRouteID, vppRouteID) - if vppRoute.OutIface != nbIfIdx { + if int32(vppRoute.Type) != int32(nbRoute.Type) { + plugin.log.Debugf("RESYNC routes: route type is different (NB: %d, VPP %d)", + nbRoute.Type, vppRoute.Type) + continue + } + if vppRoute.OutgoingInterface != nbRoute.OutgoingInterface { plugin.log.Debugf("RESYNC routes: interface index is different (NB: %d, VPP %d)", - nbIfIdx, vppRoute.OutIface) + nbIfIdx, vppRoute.OutgoingInterface) continue } - if vppRoute.DstAddr.String() != nbRoute.DstIpAddr { + if vppRoute.DstIpAddr != nbRoute.DstIpAddr { plugin.log.Debugf("RESYNC routes: dst address is different (NB: %s, VPP %s)", - nbRoute.DstIpAddr, vppRoute.DstAddr.String()) + nbRoute.DstIpAddr, vppRoute.DstIpAddr) continue } - if vppRoute.VrfID != nbRoute.VrfId { + if vppRoute.VrfId != nbRoute.VrfId { plugin.log.Debugf("RESYNC routes: VRF ID is different (NB: %d, VPP %d)", - nbRoute.VrfId, vppRoute.VrfID) + nbRoute.VrfId, vppRoute.VrfId) continue } if vppRoute.Weight != nbRoute.Weight { @@ -84,9 +101,18 @@ func (plugin *RouteConfigurator) Resync(nbRoutes []*l3.StaticRoutes_Route) error nbRoute.Preference, vppRoute.Preference) continue } - if vppRoute.NextHopAddr.String() != nbRoute.NextHopAddr { - plugin.log.Debugf("RESYNC routes: next hop address is different (NB: %d, VPP %d)", - nbRoute.NextHopAddr, vppRoute.NextHopAddr.String()) + // Set zero address in correct format if not defined + if nbRoute.NextHopAddr == "" { + nbRoute.NextHopAddr = plugin.fillEmptyNextHop(nbRoute.DstIpAddr) + } + if vppRoute.NextHopAddr != nbRoute.NextHopAddr { + plugin.log.Debugf("RESYNC routes: next hop address is different (NB: %s, VPP %s)", + nbRoute.NextHopAddr, vppRoute.NextHopAddr) + continue + } + if vppRoute.ViaVrfId != nbRoute.ViaVrfId { + plugin.log.Debugf("RESYNC routes: via VRF ID is different (NB: %d, VPP %d)", + nbRoute.ViaVrfId, vppRoute.ViaVrfId) continue } // Register existing routes @@ -99,24 +125,55 @@ func (plugin *RouteConfigurator) Resync(nbRoutes []*l3.StaticRoutes_Route) error // Add missing route configuration var wasError error - if len(nbRoutes) > 0 { - for _, nbRoute := range nbRoutes { - routeID := routeIdentifier(nbRoute.VrfId, nbRoute.DstIpAddr, nbRoute.NextHopAddr) + for _, nbRoute := range nbRoutes { + routeID := routeIdentifier(nbRoute.VrfId, nbRoute.DstIpAddr, nbRoute.NextHopAddr) + _, _, found := plugin.rtIndexes.LookupIdx(routeID) + if !found { + // create new route if does not exist yet. VRF ID is already validated at this point. + if err := plugin.ConfigureRoute(nbRoute, fmt.Sprintf("%d", nbRoute.VrfId)); err != nil { + plugin.log.Error(err) + wasError = err + } + plugin.log.Debugf("RESYNC routes: route %s was configured", routeID) + } + } + + // Remove other routes except DROP type + for _, vppRoute := range vppRouteDetails { + if routeMayBeRemoved(vppRoute) { + route := vppRoute.Route + routeID := routeIdentifier(route.VrfId, route.DstIpAddr, route.NextHopAddr) _, _, found := plugin.rtIndexes.LookupIdx(routeID) if !found { - // create new route if does not exist yet. VRF ID is already validated at this point. - plugin.log.Debugf("RESYNC routes: route %s not found and will be configured", routeID) - if err := plugin.ConfigureRoute(nbRoute, string(nbRoute.VrfId)); err != nil { + // Register before removal + plugin.rtIndexes.RegisterName(routeID, plugin.rtIndexSeq, route) + plugin.rtIndexSeq++ + if err := plugin.DeleteRoute(route, fmt.Sprintf("%d", route.VrfId)); err != nil { plugin.log.Error(err) wasError = err } + plugin.log.Debugf("RESYNC routes: vpp route %s removed", routeID) } } } + plugin.log.WithField("cfg", plugin).Debug("RESYNC routes end. ", wasError) return wasError } +// Following rules are currently applied: +// - no DROP type route can be removed in order to prevent removal of VPP default routes +// - IPv6 link local route cannot be removed +func routeMayBeRemoved(route *vppcalls.RouteDetails) bool { + if route.Route.Type == l3.StaticRoutes_Route_DROP { + return false + } + if route.Meta.IsIPv6 && net.ParseIP(route.Route.DstIpAddr).IsLinkLocalUnicast() { + return false + } + return true +} + // Resync confgures the empty VPP (overwrites the arp entries) func (plugin *ArpConfigurator) Resync(arpEntries []*l3.ArpTable_ArpEntry) error { plugin.log.WithField("cfg", plugin).Debug("RESYNC arp begin. ") @@ -141,7 +198,7 @@ func (plugin *ArpConfigurator) Resync(arpEntries []*l3.ArpTable_ArpEntry) error return nil } -// Resync confgures the empty VPP (overwrites the proxy arp entries) +// ResyncInterfaces confgures the empty VPP (overwrites the proxy arp entries) func (plugin *ProxyArpConfigurator) ResyncInterfaces(nbProxyArpIfs []*l3.ProxyArpInterfaces_InterfaceList) error { plugin.log.Debug("RESYNC proxy ARP interfaces begin. ") defer func() { @@ -166,7 +223,7 @@ func (plugin *ProxyArpConfigurator) ResyncInterfaces(nbProxyArpIfs []*l3.ProxyAr return nil } -// Resync confgures the empty VPP (overwrites the proxy arp ranges) +// ResyncRanges confgures the empty VPP (overwrites the proxy arp ranges) func (plugin *ProxyArpConfigurator) ResyncRanges(nbProxyArpRanges []*l3.ProxyArpRanges_RangeList) error { plugin.log.Debug("RESYNC proxy ARP ranges begin. ") defer func() { @@ -187,3 +244,34 @@ func (plugin *ProxyArpConfigurator) ResyncRanges(nbProxyArpRanges []*l3.ProxyArp plugin.log.Debug("RESYNC proxy ARP ranges end. ", wasError) return nil } + +// Resync configures the empty VPP (adds IP scan neigh config) +func (p *IPNeighConfigurator) Resync(config *l3.IPScanNeighbor) error { + p.log.Debug("RESYNC IP neighbor begin. ") + defer func() { + if p.stopwatch != nil { + p.stopwatch.PrintLog() + } + }() + + var wasError error + if err := p.Set(config); err != nil { + return err + } + + p.log.Debug("RESYNC IP neighbor end. ", wasError) + return nil +} + +// Takes route destination address used to derive IP version and returns zero IP without mask +func (plugin *RouteConfigurator) fillEmptyNextHop(dstIP string) string { + _, isIPv6, err := addrs.ParseIPWithPrefix(dstIP) + if err != nil { + plugin.log.Errorf("route resync error: failed to parse IP address %s", dstIP) + return "" + } + if isIPv6 { + return net.IPv6zero.String() + } + return net.IPv4zero.String() +} diff --git a/plugins/vpp/l3plugin/ip_neigh_config.go b/plugins/vpp/l3plugin/ip_neigh_config.go new file mode 100644 index 0000000000..e780ac6c49 --- /dev/null +++ b/plugins/vpp/l3plugin/ip_neigh_config.go @@ -0,0 +1,95 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package l3plugin + +import ( + govppapi "git.fd.io/govpp.git/api" + "github.com/ligato/cn-infra/logging" + "github.com/ligato/cn-infra/logging/measure" + "github.com/ligato/cn-infra/utils/safeclose" + "github.com/ligato/vpp-agent/plugins/govppmux" + "github.com/ligato/vpp-agent/plugins/vpp/l3plugin/vppcalls" + "github.com/ligato/vpp-agent/plugins/vpp/model/l3" +) + +// IPNeighConfigurator runs in the background in its own goroutine where it watches for any changes +// in the configuration of L3 IP scan neighbor, as modelled by the proto file "../model/l3/l3.proto" and stored +// in ETCD under the key "/vnf-agent/{vnf-agent}/vpp/config/v1/ipneigh". Configuration uses single key, since +// the configuration is global-like. +type IPNeighConfigurator struct { + log logging.Logger + + // VPP channel + vppChan govppapi.Channel + // VPP API channel + ipNeighHandler vppcalls.IPNeighVppAPI + + // Timer used to measure and store time + stopwatch *measure.Stopwatch +} + +// Init VPP channel and vppcalls handler +func (p *IPNeighConfigurator) Init(logger logging.PluginLogger, goVppMux govppmux.API, enableStopwatch bool) (err error) { + // Logger + p.log = logger.NewLogger("-l3-ip-neigh-conf") + p.log.Debugf("Initializing proxy ARP configurator") + + // Configurator-wide stopwatch instance + if enableStopwatch { + p.stopwatch = measure.NewStopwatch("IPScan-Neigh-configurator", p.log) + } + + // VPP channel + p.vppChan, err = goVppMux.NewAPIChannel() + if err != nil { + return err + } + + // VPP API handler + p.ipNeighHandler = vppcalls.NewIPNeighVppHandler(p.vppChan, p.log, p.stopwatch) + + return nil +} + +// Close VPP channel +func (p *IPNeighConfigurator) Close() error { + return safeclose.Close(p.vppChan) +} + +// Set puts desired IP scan neighbor configuration to the VPP +func (p *IPNeighConfigurator) Set(config *l3.IPScanNeighbor) error { + if err := p.ipNeighHandler.SetIPScanNeighbor(config); err != nil { + return err + } + + p.log.Debugf("IP scan neighbor set to %v", config.Mode) + + return nil +} + +// Unset returns IP scan neighbor configuration to default +func (p *IPNeighConfigurator) Unset() error { + defaultCfg := &l3.IPScanNeighbor{ + Mode: l3.IPScanNeighbor_DISABLED, + } + + if err := p.ipNeighHandler.SetIPScanNeighbor(defaultCfg); err != nil { + return err + } + + p.log.Debug("IP scan neighbor set to default") + + return nil +} diff --git a/plugins/vpp/l3plugin/l3idx/l3_arp_index.go b/plugins/vpp/l3plugin/l3idx/l3_arp_index.go index a18356d9b4..763e47ff01 100644 --- a/plugins/vpp/l3plugin/l3idx/l3_arp_index.go +++ b/plugins/vpp/l3plugin/l3idx/l3_arp_index.go @@ -15,7 +15,6 @@ package l3idx import ( - "github.com/ligato/cn-infra/core" "github.com/ligato/vpp-agent/idxvpp" "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/vpp/model/l3" @@ -36,7 +35,7 @@ type ARPIndex interface { LookupNamesByInterface(ifName string) []*l3.ArpTable_ArpEntry // WatchNameToIdx allows to subscribe for watching changes in SwIfIndex mapping - WatchNameToIdx(subscriber core.PluginName, pluginChannel chan ARPIndexDto) + WatchNameToIdx(subscriber string, pluginChannel chan ARPIndexDto) } // ARPIndexRW is mapping between software ARP indexes (used internally in VPP) @@ -124,7 +123,7 @@ func (arpIndex *ArpIndex) Clear() { } // WatchNameToIdx allows to subscribe for watching changes in SwIfIndex mapping -func (arpIndex *ArpIndex) WatchNameToIdx(subscriber core.PluginName, pluginChannel chan ARPIndexDto) { +func (arpIndex *ArpIndex) WatchNameToIdx(subscriber string, pluginChannel chan ARPIndexDto) { ch := make(chan idxvpp.NameToIdxDto) arpIndex.mapping.Watch(subscriber, nametoidx.ToChan(ch)) go func() { diff --git a/plugins/vpp/l3plugin/route_config.go b/plugins/vpp/l3plugin/route_config.go index 0e7eadc8e3..b4abaa8869 100644 --- a/plugins/vpp/l3plugin/route_config.go +++ b/plugins/vpp/l3plugin/route_config.go @@ -21,6 +21,10 @@ import ( "fmt" "strconv" + "strings" + + "sort" + govppapi "git.fd.io/govpp.git/api" "github.com/ligato/cn-infra/logging" "github.com/ligato/cn-infra/logging/measure" @@ -28,11 +32,34 @@ import ( "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/govppmux" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" + ifvppcalls "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" "github.com/ligato/vpp-agent/plugins/vpp/l3plugin/l3idx" "github.com/ligato/vpp-agent/plugins/vpp/l3plugin/vppcalls" "github.com/ligato/vpp-agent/plugins/vpp/model/l3" ) +// SortedRoutes type is used to implement sort interface for slice of Route. +type SortedRoutes []*l3.StaticRoutes_Route + +// Return length of slice. +// Implements sort.Interface +func (arr SortedRoutes) Len() int { + return len(arr) +} + +// Swap swaps two items in slice identified by indices. +// Implements sort.Interface +func (arr SortedRoutes) Swap(i, j int) { + arr[i], arr[j] = arr[j], arr[i] +} + +// Less returns true if the item at index i in slice +// should be sorted before the element with index j. +// Implements sort.Interface +func (arr SortedRoutes) Less(i, j int) bool { + return lessRoute(arr[i], arr[j]) +} + // RouteConfigurator runs in the background in its own goroutine where it watches for any changes // in the configuration of L3 routes as modelled by the proto file "../model/l3/l3.proto" and stored // in ETCD under the key "/vnf-agent/{vnf-agent}/vpp/config/v1routes". Updates received from the northbound API @@ -48,6 +75,9 @@ type RouteConfigurator struct { // VPP channels vppChan govppapi.Channel + // VPP API handlers + ifHandler ifvppcalls.IfVppWrite + rtHandler vppcalls.RouteVppAPI // Timer used to measure and store time stopwatch *measure.Stopwatch @@ -60,6 +90,11 @@ func (plugin *RouteConfigurator) Init(logger logging.PluginLogger, goVppMux govp plugin.log = logger.NewLogger("-l3-route-conf") plugin.log.Debug("Initializing L3 Route configurator") + // Configurator-wide stopwatch instance + if enableStopwatch { + plugin.stopwatch = measure.NewStopwatch("Route-configurator", plugin.log) + } + // Mappings plugin.ifIndexes = swIfIndexes plugin.rtIndexes = l3idx.NewRouteIndex(nametoidx.NewNameToIdx(plugin.log, "route_indexes", nil)) @@ -72,16 +107,9 @@ func (plugin *RouteConfigurator) Init(logger logging.PluginLogger, goVppMux govp return err } - // Stopwatch - if enableStopwatch { - plugin.stopwatch = measure.NewStopwatch("RouteConfigurator", plugin.log) - } - - // Message compatibility - if err := plugin.vppChan.CheckMessageCompatibility(vppcalls.RouteMessages...); err != nil { - plugin.log.Error(err) - return err - } + // VPP API handlers + plugin.ifHandler = ifvppcalls.NewIfVppHandler(plugin.vppChan, plugin.log, plugin.stopwatch) + plugin.rtHandler = vppcalls.NewRouteVppHandler(plugin.vppChan, plugin.ifIndexes, plugin.log, plugin.stopwatch) return nil } @@ -109,51 +137,50 @@ func (plugin *RouteConfigurator) clearMapping() { // Create unique identifier which serves as a name in name-to-index mapping. func routeIdentifier(vrf uint32, destination string, nextHop string) string { + if nextHop == "" { + nextHop = "" + } return fmt.Sprintf("vrf%v-%v-%v", vrf, destination, nextHop) } // ConfigureRoute processes the NB config and propagates it to bin api calls. -func (plugin *RouteConfigurator) ConfigureRoute(config *l3.StaticRoutes_Route, vrfFromKey string) error { - plugin.log.Infof("Configuring new route %v -> %v", config.DstIpAddr, config.NextHopAddr) - +func (plugin *RouteConfigurator) ConfigureRoute(route *l3.StaticRoutes_Route, vrfFromKey string) error { + plugin.log.Infof("Configuring new route %v -> %v", route.DstIpAddr, route.NextHopAddr) // Validate VRF index from key and it's value in data. - if err := plugin.validateVrfFromKey(config, vrfFromKey); err != nil { + if err := plugin.validateVrfFromKey(route, vrfFromKey); err != nil { return err } - routeID := routeIdentifier(config.VrfId, config.DstIpAddr, config.NextHopAddr) + routeID := routeIdentifier(route.VrfId, route.DstIpAddr, route.NextHopAddr) - swIdx, err := resolveInterfaceSwIndex(config.OutgoingInterface, plugin.ifIndexes) + swIdx, err := resolveInterfaceSwIndex(route.OutgoingInterface, plugin.ifIndexes) if err != nil { - plugin.rtCachedIndexes.RegisterName(routeID, plugin.rtIndexSeq, config) + plugin.rtCachedIndexes.RegisterName(routeID, plugin.rtIndexSeq, route) plugin.rtIndexSeq++ plugin.log.Debugf("Route %v registered to cache", routeID) return nil } - // Transform route data. - route, err := TransformRoute(config, swIdx, plugin.log) - if err != nil { - return err + // Check mandatory destination address + if route.DstIpAddr == "" { + return fmt.Errorf("route %v does not contain destination address", routeID) } - // Create and register new route. - if route != nil { - err := vppcalls.VppAddRoute(route, plugin.vppChan, plugin.stopwatch) - if err != nil { - return err - } + // Create new route. + err = plugin.rtHandler.VppAddRoute(plugin.ifHandler, route, swIdx) + if err != nil { + return err } // Register configured route _, _, routeExists := plugin.rtIndexes.LookupIdx(routeID) if !routeExists { - plugin.rtIndexes.RegisterName(routeID, plugin.rtIndexSeq, config) + plugin.rtIndexes.RegisterName(routeID, plugin.rtIndexSeq, route) plugin.rtIndexSeq++ plugin.log.Infof("Route %v registered", routeID) } - plugin.log.Infof("Route %v -> %v configured", config.DstIpAddr, config.NextHopAddr) + plugin.log.Infof("Route %v -> %v configured", route.DstIpAddr, route.NextHopAddr) return nil } @@ -190,9 +217,9 @@ func (plugin *RouteConfigurator) ModifyRoute(newConfig *l3.StaticRoutes_Route, o return nil } -func (plugin *RouteConfigurator) deleteOldRoute(oldConfig *l3.StaticRoutes_Route, vrfFromKey string) error { +func (plugin *RouteConfigurator) deleteOldRoute(route *l3.StaticRoutes_Route, vrfFromKey string) error { // Check if route entry is not just cached - routeID := routeIdentifier(oldConfig.VrfId, oldConfig.DstIpAddr, oldConfig.NextHopAddr) + routeID := routeIdentifier(route.VrfId, route.DstIpAddr, route.NextHopAddr) _, _, found := plugin.rtCachedIndexes.LookupIdx(routeID) if found { plugin.log.Debugf("Route entry %v found in cache, removed", routeID) @@ -201,78 +228,64 @@ func (plugin *RouteConfigurator) deleteOldRoute(oldConfig *l3.StaticRoutes_Route return nil } - swIdx, err := resolveInterfaceSwIndex(oldConfig.OutgoingInterface, plugin.ifIndexes) - if err != nil { - return err - } - - // Transform old route data. - oldRoute, err := TransformRoute(oldConfig, swIdx, plugin.log) + swIdx, err := resolveInterfaceSwIndex(route.OutgoingInterface, plugin.ifIndexes) if err != nil { return err } // Validate old cachedRoute data Vrf. - if err := plugin.validateVrfFromKey(oldConfig, vrfFromKey); err != nil { + if err := plugin.validateVrfFromKey(route, vrfFromKey); err != nil { return err } // Remove and unregister old route. - if err := vppcalls.VppDelRoute(oldRoute, plugin.vppChan, plugin.stopwatch); err != nil { + if err := plugin.rtHandler.VppDelRoute(route, swIdx); err != nil { return err } - - oldRouteIdentifier := routeIdentifier(oldRoute.VrfID, oldRoute.DstAddr.String(), oldRoute.NextHopAddr.String()) - - _, _, found = plugin.rtIndexes.UnregisterName(oldRouteIdentifier) + _, _, found = plugin.rtIndexes.UnregisterName(routeID) if found { - plugin.log.Infof("Old route %v unregistered", oldRouteIdentifier) + plugin.log.Infof("Old route %v unregistered", routeID) } else { - plugin.log.Warnf("Unregister failed, old route %v not found", oldRouteIdentifier) + plugin.log.Warnf("Unregister failed, old route %v not found", routeID) } return nil } -func (plugin *RouteConfigurator) addNewRoute(newConfig *l3.StaticRoutes_Route, vrfFromKey string) error { +func (plugin *RouteConfigurator) addNewRoute(route *l3.StaticRoutes_Route, vrfFromKey string) error { // Validate new route data Vrf. - if err := plugin.validateVrfFromKey(newConfig, vrfFromKey); err != nil { + if err := plugin.validateVrfFromKey(route, vrfFromKey); err != nil { return err } - swIdx, err := resolveInterfaceSwIndex(newConfig.OutgoingInterface, plugin.ifIndexes) + swIdx, err := resolveInterfaceSwIndex(route.OutgoingInterface, plugin.ifIndexes) if err != nil { return err } - // Transform new route data. - newRoute, err := TransformRoute(newConfig, swIdx, plugin.log) - if err != nil { - return err - } // Create and register new route. - if err = vppcalls.VppAddRoute(newRoute, plugin.vppChan, plugin.stopwatch); err != nil { + if err = plugin.rtHandler.VppAddRoute(plugin.ifHandler, route, swIdx); err != nil { return err } - newRouteIdentifier := routeIdentifier(newConfig.VrfId, newConfig.DstIpAddr, newConfig.NextHopAddr) - plugin.rtIndexes.RegisterName(newRouteIdentifier, plugin.rtIndexSeq, newConfig) + routeID := routeIdentifier(route.VrfId, route.DstIpAddr, route.NextHopAddr) + plugin.rtIndexes.RegisterName(routeID, plugin.rtIndexSeq, route) plugin.rtIndexSeq++ - plugin.log.Infof("New route %v registered", newRouteIdentifier) + plugin.log.Infof("New route %v registered", routeID) return nil } // DeleteRoute processes the NB config and propagates it to bin api calls. -func (plugin *RouteConfigurator) DeleteRoute(config *l3.StaticRoutes_Route, vrfFromKey string) (wasError error) { - plugin.log.Infof("Removing route %v -> %v", config.DstIpAddr, config.NextHopAddr) +func (plugin *RouteConfigurator) DeleteRoute(route *l3.StaticRoutes_Route, vrfFromKey string) (wasError error) { + plugin.log.Infof("Removing route %v -> %v", route.DstIpAddr, route.NextHopAddr) // Validate VRF index from key and it's value in data. - if err := plugin.validateVrfFromKey(config, vrfFromKey); err != nil { + if err := plugin.validateVrfFromKey(route, vrfFromKey); err != nil { return err } // Check if route entry is not just cached - routeID := routeIdentifier(config.VrfId, config.DstIpAddr, config.NextHopAddr) + routeID := routeIdentifier(route.VrfId, route.DstIpAddr, route.NextHopAddr) _, _, found := plugin.rtCachedIndexes.LookupIdx(routeID) if found { plugin.log.Debugf("Route entry %v found in cache, removed", routeID) @@ -281,27 +294,17 @@ func (plugin *RouteConfigurator) DeleteRoute(config *l3.StaticRoutes_Route, vrfF return nil } - swIdx, err := resolveInterfaceSwIndex(config.OutgoingInterface, plugin.ifIndexes) + swIdx, err := resolveInterfaceSwIndex(route.OutgoingInterface, plugin.ifIndexes) if err != nil { return err } - // Transform route data. - route, err := TransformRoute(config, swIdx, plugin.log) - if err != nil { - return err - } - if route == nil { - return nil - } - plugin.log.Debugf("deleting route: %+v", route) - // Remove and unregister route. - if err = vppcalls.VppDelRoute(route, plugin.vppChan, plugin.stopwatch); err != nil { + if err := plugin.rtHandler.VppDelRoute(route, swIdx); err != nil { return err } - routeIdentifier := routeIdentifier(config.VrfId, config.DstIpAddr, config.NextHopAddr) + routeIdentifier := routeIdentifier(route.VrfId, route.DstIpAddr, route.NextHopAddr) _, _, found = plugin.rtIndexes.UnregisterName(routeIdentifier) if found { plugin.log.Infof("Route %v unregistered", routeIdentifier) @@ -309,21 +312,41 @@ func (plugin *RouteConfigurator) DeleteRoute(config *l3.StaticRoutes_Route, vrfF plugin.log.Warnf("Unregister failed, route %v not found", routeIdentifier) } - plugin.log.Infof("Route %v -> %v removed", config.DstIpAddr, config.NextHopAddr) + plugin.log.Infof("Route %v -> %v removed", route.DstIpAddr, route.NextHopAddr) return nil } -func (plugin *RouteConfigurator) validateVrfFromKey(config *l3.StaticRoutes_Route, vrfFromKey string) error { - intVrfFromKey, err := strconv.Atoi(vrfFromKey) - if intVrfFromKey != int(config.VrfId) { - if err != nil { - return err +// DiffRoutes calculates route diff from two sets of routes and returns routes to be added and removed +func (plugin *RouteConfigurator) DiffRoutes(new, old []*l3.StaticRoutes_Route) (toBeDeleted, toBeAdded []*l3.StaticRoutes_Route) { + oldSorted, newSorted := SortedRoutes(old), SortedRoutes(new) + sort.Sort(newSorted) + sort.Sort(oldSorted) + + // Compare. + i, j := 0, 0 + for i < len(newSorted) && j < len(oldSorted) { + if *newSorted[i] == *oldSorted[j] { + i++ + j++ + } else { + if lessRoute(newSorted[i], oldSorted[j]) { + toBeAdded = append(toBeAdded, newSorted[i]) + i++ + } else { + toBeDeleted = append(toBeDeleted, oldSorted[j]) + j++ + } } - plugin.log.Warnf("VRF index from key (%v) and from config (%v) does not match, using value from the key", - intVrfFromKey, config.VrfId) - config.VrfId = uint32(intVrfFromKey) } - return nil + + for ; i < len(newSorted); i++ { + toBeAdded = append(toBeAdded, newSorted[i]) + } + + for ; j < len(oldSorted); j++ { + toBeDeleted = append(toBeDeleted, oldSorted[j]) + } + return } // ResolveCreatedInterface is responsible for reconfiguring cached routes and then from removing them from route cache @@ -342,27 +365,13 @@ func (plugin *RouteConfigurator) ResolveCreatedInterface(ifName string, swIdx ui "dstIPAddr": route.DstIpAddr, }).Debug("Remove routes from route cache - outgoing interface was added.") vrf := strconv.FormatUint(uint64(route.VrfId), 10) - plugin.recreateRoute(route, vrf) + if err := plugin.recreateRoute(route, vrf); err != nil { + plugin.log.Errorf("Error recreating interface %s: %v", ifName, err) + } plugin.rtCachedIndexes.UnregisterName(routeWithIndex.RouteID) } } -/** -recreateRoute calls delete and configure route. - -This is type of workaround because when outgoing interface is deleted then it isn't possible to remove -associated routes. they stay in following state: -- oper-flags:drop -- routing section: unresolved -It is neither possible to recreate interface and then create route. -It is only possible to recreate interface, delete old associated routes (like clean old mess) -and then add them again. -*/ -func (plugin *RouteConfigurator) recreateRoute(route *l3.StaticRoutes_Route, vrf string) { - plugin.DeleteRoute(route, vrf) - plugin.ConfigureRoute(route, vrf) -} - // ResolveDeletedInterface is responsible for moving routes of deleted interface to cache func (plugin *RouteConfigurator) ResolveDeletedInterface(ifName string, swIdx uint32) { routesWithIndex := plugin.rtIndexes.LookupRouteAndIDByOutgoingIfc(ifName) @@ -382,6 +391,37 @@ func (plugin *RouteConfigurator) ResolveDeletedInterface(ifName string, swIdx ui } } +func (plugin *RouteConfigurator) validateVrfFromKey(config *l3.StaticRoutes_Route, vrfFromKey string) error { + intVrfFromKey, err := strconv.Atoi(vrfFromKey) + if intVrfFromKey != int(config.VrfId) { + if err != nil { + return err + } + plugin.log.Warnf("VRF index from key (%v) and from config (%v) does not match, using value from the key", + intVrfFromKey, config.VrfId) + config.VrfId = uint32(intVrfFromKey) + } + return nil +} + +/** +recreateRoute calls delete and configure route. + +This is type of workaround because when outgoing interface is deleted then it isn't possible to remove +associated routes. they stay in following state: +- oper-flags:drop +- routing section: unresolved +It is neither possible to recreate interface and then create route. +It is only possible to recreate interface, delete old associated routes (like clean old mess) +and then add them again. +*/ +func (plugin *RouteConfigurator) recreateRoute(route *l3.StaticRoutes_Route, vrf string) error { + if err := plugin.DeleteRoute(route, vrf); err != nil { + return nil + } + return plugin.ConfigureRoute(route, vrf) +} + func (plugin *RouteConfigurator) moveRouteToCache(config *l3.StaticRoutes_Route) (wasError error) { routeID := routeIdentifier(config.VrfId, config.DstIpAddr, config.NextHopAddr) _, _, found := plugin.rtIndexes.UnregisterName(routeID) @@ -397,3 +437,41 @@ func (plugin *RouteConfigurator) moveRouteToCache(config *l3.StaticRoutes_Route) return nil } + +func resolveInterfaceSwIndex(ifName string, index ifaceidx.SwIfIndex) (uint32, error) { + ifIndex := vppcalls.NextHopOutgoingIfUnset + if ifName != "" { + var exists bool + ifIndex, _, exists = index.LookupIdx(ifName) + if !exists { + return ifIndex, fmt.Errorf("route outgoing interface %v not found", ifName) + } + } + return ifIndex, nil +} + +func lessRoute(a, b *l3.StaticRoutes_Route) bool { + if a.Type != b.Type { + return a.Type < b.Type + } + if a.VrfId != b.VrfId { + return a.VrfId < b.VrfId + } + if !strings.EqualFold(a.DstIpAddr, b.DstIpAddr) { + return strings.Compare(a.DstIpAddr, b.DstIpAddr) < 0 + } + if !strings.EqualFold(a.NextHopAddr, b.NextHopAddr) { + return strings.Compare(a.NextHopAddr, b.NextHopAddr) < 0 + } + if a.ViaVrfId != b.ViaVrfId { + return a.ViaVrfId < b.ViaVrfId + } + if a.OutgoingInterface != b.OutgoingInterface { + return a.OutgoingInterface < b.OutgoingInterface + } + if a.Preference != b.Preference { + return a.Preference < b.Preference + } + return a.Weight < b.Weight + +} diff --git a/plugins/vpp/l3plugin/route_config_test.go b/plugins/vpp/l3plugin/route_config_test.go index 37b15e18d6..594a7774b2 100644 --- a/plugins/vpp/l3plugin/route_config_test.go +++ b/plugins/vpp/l3plugin/route_config_test.go @@ -15,10 +15,11 @@ package l3plugin_test import ( + "testing" + "git.fd.io/govpp.git/adapter/mock" "git.fd.io/govpp.git/core" "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" "github.com/ligato/vpp-agent/plugins/vpp/binapi/vpe" @@ -27,27 +28,8 @@ import ( "github.com/ligato/vpp-agent/plugins/vpp/model/l3" "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" - "testing" ) -// Test RouteConfigurator initialization -func TestRouteConfiguratorInit(t *testing.T) { - RegisterTestingT(t) - ctx := &vppcallmock.TestCtx{ - MockVpp: &mock.VppAdapter{}, - } - connection, _ := core.Connect(ctx.MockVpp) - defer connection.Disconnect() - - plugin := &l3plugin.RouteConfigurator{} - - // Test init - err := plugin.Init(logging.ForPlugin("test-log", logrus.NewLogRegistry()), connection, nil, false) - Expect(err).To(BeNil()) - err = plugin.Close() - Expect(err).To(BeNil()) -} - // Test adding of routes entry func TestConfigureRoute(t *testing.T) { // Setup @@ -407,17 +389,167 @@ func routeTestSetup(t *testing.T) (*vppcallmock.TestCtx, *core.Connection, *l3pl Expect(err).ShouldNot(HaveOccurred()) plugin := &l3plugin.RouteConfigurator{} - ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logging.ForPlugin("test-log", logrus.NewLogRegistry()), "l3-plugin", nil)) + ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logging.ForPlugin("test-log"), "l3-plugin", nil)) - err = plugin.Init(logging.ForPlugin("test-log", logrus.NewLogRegistry()), connection, ifIndexes, false) + err = plugin.Init(logging.ForPlugin("test-log"), connection, ifIndexes, false) Expect(err).To(BeNil()) return ctx, connection, plugin, ifIndexes } +func TestDiffRoutesAddedOnly(t *testing.T) { + RegisterTestingT(t) + + var routesOld []*l3.StaticRoutes_Route + + routes := []*l3.StaticRoutes_Route{ + routeOne, + routeTwo, + } + + cfg := l3plugin.RouteConfigurator{} + del, add := cfg.DiffRoutes(routes, routesOld) + Expect(del).To(BeEmpty()) + Expect(add).NotTo(BeEmpty()) + Expect(add[0]).To(BeEquivalentTo(routeOne)) + Expect(add[1]).To(BeEquivalentTo(routeTwo)) +} + +func TestDiffRoutesDeleteOnly(t *testing.T) { + RegisterTestingT(t) + + routesOld := []*l3.StaticRoutes_Route{ + routeOne, + routeTwo, + } + + var routes []*l3.StaticRoutes_Route + + cfg := l3plugin.RouteConfigurator{} + del, add := cfg.DiffRoutes(routes, routesOld) + Expect(add).To(BeEmpty()) + Expect(del).NotTo(BeEmpty()) + Expect(del[0]).To(BeEquivalentTo(routeOne)) + Expect(del[1]).To(BeEquivalentTo(routeTwo)) +} + +func TestDiffRoutesOneAdded(t *testing.T) { + RegisterTestingT(t) + + routesOld := []*l3.StaticRoutes_Route{ + routeOne, + } + + routes := []*l3.StaticRoutes_Route{ + routeOne, + routeTwo, + } + + cfg := l3plugin.RouteConfigurator{} + del, add := cfg.DiffRoutes(routes, routesOld) + Expect(del).To(BeEmpty()) + Expect(add).NotTo(BeEmpty()) + Expect(add[0]).To(BeEquivalentTo(routeTwo)) +} + +func TestDiffRoutesNoChange(t *testing.T) { + RegisterTestingT(t) + + routesOld := []*l3.StaticRoutes_Route{ + routeTwo, + routeOne, + } + + routes := []*l3.StaticRoutes_Route{ + routeOne, + routeTwo, + } + + cfg := l3plugin.RouteConfigurator{} + del, add := cfg.DiffRoutes(routes, routesOld) + Expect(del).To(BeEmpty()) + Expect(add).To(BeEmpty()) +} + +func TestDiffRoutesWeightChange(t *testing.T) { + RegisterTestingT(t) + + routesOld := []*l3.StaticRoutes_Route{ + routeThree, + } + + routes := []*l3.StaticRoutes_Route{ + routeThreeW, + } + + cfg := l3plugin.RouteConfigurator{} + del, add := cfg.DiffRoutes(routes, routesOld) + Expect(del).NotTo(BeEmpty()) + Expect(add).NotTo(BeEmpty()) + Expect(add[0]).To(BeEquivalentTo(routeThreeW)) + Expect(del[0]).To(BeEquivalentTo(routeThree)) + +} + +func TestDiffRoutesMultipleChanges(t *testing.T) { + RegisterTestingT(t) + + routesOld := []*l3.StaticRoutes_Route{ + routeOne, + routeTwo, + routeThree, + } + + routes := []*l3.StaticRoutes_Route{ + routeThreeW, + routeTwo, + } + + cfg := l3plugin.RouteConfigurator{} + del, add := cfg.DiffRoutes(routes, routesOld) + Expect(del).NotTo(BeEmpty()) + Expect(add).NotTo(BeEmpty()) + Expect(add[0]).To(BeEquivalentTo(routeThreeW)) + Expect(del[0]).To(BeEquivalentTo(routeOne)) + Expect(del[1]).To(BeEquivalentTo(routeThree)) +} + // Test Teardown func routeTestTeardown(connection *core.Connection, plugin *l3plugin.RouteConfigurator) { connection.Disconnect() err := plugin.Close() Expect(err).To(BeNil()) + logging.DefaultRegistry.ClearRegistry() +} + +var routeOne = &l3.StaticRoutes_Route{ + VrfId: 0, + DstIpAddr: "10.1.1.0/24", + NextHopAddr: "192.168.1.1", + OutgoingInterface: "if1", + Weight: 5, +} + +var routeTwo = &l3.StaticRoutes_Route{ + VrfId: 0, + DstIpAddr: "172.16.1.0/24", + NextHopAddr: "10.10.1.1", + OutgoingInterface: "if2", + Weight: 5, +} + +var routeThree = &l3.StaticRoutes_Route{ + VrfId: 0, + DstIpAddr: "172.16.1.0/24", + NextHopAddr: "10.10.1.1", + OutgoingInterface: "if2", + Weight: 5, +} + +var routeThreeW = &l3.StaticRoutes_Route{ + VrfId: 0, + DstIpAddr: "172.16.1.0/24", + NextHopAddr: "10.10.1.1", + OutgoingInterface: "if2", + Weight: 10, } diff --git a/plugins/vpp/l3plugin/route_utils.go b/plugins/vpp/l3plugin/route_utils.go deleted file mode 100644 index 65cde9168d..0000000000 --- a/plugins/vpp/l3plugin/route_utils.go +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright (c) 2017 Cisco and/or its affiliates. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at: -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package l3plugin - -import ( - "bytes" - "fmt" - "net" - "sort" - - "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/utils/addrs" - "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" - "github.com/ligato/vpp-agent/plugins/vpp/l3plugin/vppcalls" - "github.com/ligato/vpp-agent/plugins/vpp/model/l3" -) - -// SortedRoutes type is used to implement sort interface for slice of Route. -type SortedRoutes []*vppcalls.Route - -// Return length of slice. -// Implements sort.Interface -func (arr SortedRoutes) Len() int { - return len(arr) -} - -// Swap swaps two items in slice identified by indices. -// Implements sort.Interface -func (arr SortedRoutes) Swap(i, j int) { - arr[i], arr[j] = arr[j], arr[i] -} - -// Less returns true if the item at index i in slice -// should be sorted before the element with index j. -// Implements sort.Interface -func (arr SortedRoutes) Less(i, j int) bool { - return lessRoute(arr[i], arr[j]) -} - -func eqRoutes(a *vppcalls.Route, b *vppcalls.Route) bool { - return a.VrfID == b.VrfID && - bytes.Equal(a.DstAddr.IP, b.DstAddr.IP) && - bytes.Equal(a.DstAddr.Mask, b.DstAddr.Mask) && - bytes.Equal(a.NextHopAddr, b.NextHopAddr) && - a.OutIface == b.OutIface && - a.Weight == b.Weight && - a.Preference == b.Preference -} - -func lessRoute(a *vppcalls.Route, b *vppcalls.Route) bool { - if a.VrfID != b.VrfID { - return a.VrfID < b.VrfID - } - if !bytes.Equal(a.DstAddr.IP, b.DstAddr.IP) { - return bytes.Compare(a.DstAddr.IP, b.DstAddr.IP) < 0 - } - if !bytes.Equal(a.DstAddr.Mask, b.DstAddr.Mask) { - return bytes.Compare(a.DstAddr.Mask, b.DstAddr.Mask) < 0 - } - if !bytes.Equal(a.NextHopAddr, b.NextHopAddr) { - return bytes.Compare(a.NextHopAddr, b.NextHopAddr) < 0 - } - if a.OutIface != b.OutIface { - return a.OutIface < b.OutIface - } - if a.Preference != b.Preference { - return a.Preference < b.Preference - } - return a.Weight < b.Weight - -} - -// TransformRoute converts raw route data to Route object. -func TransformRoute(routeInput *l3.StaticRoutes_Route, swIndex uint32, log logging.Logger) (*vppcalls.Route, error) { - if routeInput == nil { - log.Infof("Route input is empty") - return nil, nil - } - if routeInput.DstIpAddr == "" { - log.Infof("Route does not contain destination address") - return nil, nil - } - parsedDestIP, isIpv6, err := addrs.ParseIPWithPrefix(routeInput.DstIpAddr) - if err != nil { - return nil, err - } - vrfID := routeInput.VrfId - - nextHopIP := net.ParseIP(routeInput.NextHopAddr) - if isIpv6 { - nextHopIP = nextHopIP.To16() - } else { - nextHopIP = nextHopIP.To4() - } - route := &vppcalls.Route{ - VrfID: vrfID, - DstAddr: *parsedDestIP, - NextHopAddr: nextHopIP, - OutIface: swIndex, - Weight: routeInput.Weight, - Preference: routeInput.Preference, - } - return route, nil -} - -func resolveInterfaceSwIndex(ifName string, index ifaceidx.SwIfIndex) (uint32, error) { - ifIndex := vppcalls.NextHopOutgoingIfUnset - if ifName != "" { - var exists bool - ifIndex, _, exists = index.LookupIdx(ifName) - if !exists { - return ifIndex, fmt.Errorf("route outgoing interface %v not found", ifName) - } - } - return ifIndex, nil -} - -func (plugin *RouteConfigurator) diffRoutes(new []*vppcalls.Route, old []*vppcalls.Route) (toBeDeleted []*vppcalls.Route, toBeAdded []*vppcalls.Route) { - newSorted := SortedRoutes(new) - oldSorted := SortedRoutes(old) - sort.Sort(newSorted) - sort.Sort(oldSorted) - - // Compare. - i := 0 - j := 0 - for i < len(newSorted) && j < len(oldSorted) { - if eqRoutes(newSorted[i], oldSorted[j]) { - i++ - j++ - } else { - if lessRoute(newSorted[i], oldSorted[j]) { - toBeAdded = append(toBeAdded, newSorted[i]) - i++ - } else { - toBeDeleted = append(toBeDeleted, oldSorted[j]) - j++ - } - } - } - - for ; i < len(newSorted); i++ { - toBeAdded = append(toBeAdded, newSorted[i]) - } - - for ; j < len(oldSorted); j++ { - toBeDeleted = append(toBeDeleted, oldSorted[j]) - } - return -} diff --git a/plugins/vpp/l3plugin/route_utils_test.go b/plugins/vpp/l3plugin/route_utils_test.go deleted file mode 100644 index 78eef3e7e0..0000000000 --- a/plugins/vpp/l3plugin/route_utils_test.go +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright (c) 2017 Cisco and/or its affiliates. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at: -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package l3plugin - -import ( - "github.com/ligato/vpp-agent/plugins/vpp/l3plugin/vppcalls" - "github.com/onsi/gomega" - "net" - "testing" -) - -var routeOne = &vppcalls.Route{ - VrfID: 0, - DstAddr: net.IPNet{ - IP: net.ParseIP("10.1.1.0").To4(), - Mask: net.CIDRMask(24, 8*net.IPv4len), - }, - NextHopAddr: net.ParseIP("192.168.1.1").To4(), - OutIface: 1, - Weight: 5, -} - -var routeTwo = &vppcalls.Route{ - VrfID: 0, - DstAddr: net.IPNet{ - IP: net.ParseIP("172.16.1.0").To4(), - Mask: net.CIDRMask(24, 8*net.IPv4len), - }, - NextHopAddr: net.ParseIP("10.10.1.1").To4(), - OutIface: 2, - Weight: 5, -} - -var routeThree = &vppcalls.Route{ - VrfID: 0, - DstAddr: net.IPNet{ - IP: net.ParseIP("172.16.1.0").To4(), - Mask: net.CIDRMask(24, 8*net.IPv4len), - }, - NextHopAddr: net.ParseIP("10.10.1.1").To4(), - OutIface: 2, - Weight: 5, -} - -var routeThreeW = &vppcalls.Route{ - VrfID: 0, - DstAddr: net.IPNet{ - IP: net.ParseIP("172.16.1.0").To4(), - Mask: net.CIDRMask(24, 8*net.IPv4len), - }, - NextHopAddr: net.ParseIP("10.10.1.1").To4(), - OutIface: 2, - Weight: 10, -} - -func TestDiffRoutesAddedOnly(t *testing.T) { - gomega.RegisterTestingT(t) - - routesOld := []*vppcalls.Route{} - - routes := []*vppcalls.Route{ - routeOne, - routeTwo, - } - - cfg := RouteConfigurator{} - del, add := cfg.diffRoutes(routes, routesOld) - gomega.Expect(del).To(gomega.BeEmpty()) - gomega.Expect(add).NotTo(gomega.BeEmpty()) - gomega.Expect(add[0]).To(gomega.BeEquivalentTo(routeOne)) - gomega.Expect(add[1]).To(gomega.BeEquivalentTo(routeTwo)) -} - -func TestDiffRoutesDeleteOnly(t *testing.T) { - gomega.RegisterTestingT(t) - - routesOld := []*vppcalls.Route{ - routeOne, - routeTwo, - } - - routes := []*vppcalls.Route{} - - cfg := RouteConfigurator{} - del, add := cfg.diffRoutes(routes, routesOld) - gomega.Expect(add).To(gomega.BeEmpty()) - gomega.Expect(del).NotTo(gomega.BeEmpty()) - gomega.Expect(del[0]).To(gomega.BeEquivalentTo(routeOne)) - gomega.Expect(del[1]).To(gomega.BeEquivalentTo(routeTwo)) -} - -func TestDiffRoutesOneAdded(t *testing.T) { - gomega.RegisterTestingT(t) - - routesOld := []*vppcalls.Route{ - routeOne, - } - - routes := []*vppcalls.Route{ - routeOne, - routeTwo, - } - - cfg := RouteConfigurator{} - del, add := cfg.diffRoutes(routes, routesOld) - gomega.Expect(del).To(gomega.BeEmpty()) - gomega.Expect(add).NotTo(gomega.BeEmpty()) - gomega.Expect(add[0]).To(gomega.BeEquivalentTo(routeTwo)) -} - -func TestDiffRoutesNoChange(t *testing.T) { - gomega.RegisterTestingT(t) - - routesOld := []*vppcalls.Route{ - routeTwo, - routeOne, - } - - routes := []*vppcalls.Route{ - routeOne, - routeTwo, - } - - cfg := RouteConfigurator{} - del, add := cfg.diffRoutes(routes, routesOld) - gomega.Expect(del).To(gomega.BeEmpty()) - gomega.Expect(add).To(gomega.BeEmpty()) -} - -func TestDiffRoutesWeightChange(t *testing.T) { - gomega.RegisterTestingT(t) - - routesOld := []*vppcalls.Route{ - routeThree, - } - - routes := []*vppcalls.Route{ - routeThreeW, - } - - cfg := RouteConfigurator{} - del, add := cfg.diffRoutes(routes, routesOld) - gomega.Expect(del).NotTo(gomega.BeEmpty()) - gomega.Expect(add).NotTo(gomega.BeEmpty()) - gomega.Expect(add[0]).To(gomega.BeEquivalentTo(routeThreeW)) - gomega.Expect(del[0]).To(gomega.BeEquivalentTo(routeThree)) - -} - -func TestDiffRoutesMultipleChanges(t *testing.T) { - gomega.RegisterTestingT(t) - - routesOld := []*vppcalls.Route{ - routeOne, - routeTwo, - routeThree, - } - - routes := []*vppcalls.Route{ - routeThreeW, - routeTwo, - } - - cfg := RouteConfigurator{} - del, add := cfg.diffRoutes(routes, routesOld) - gomega.Expect(del).NotTo(gomega.BeEmpty()) - gomega.Expect(add).NotTo(gomega.BeEmpty()) - gomega.Expect(add[0]).To(gomega.BeEquivalentTo(routeThreeW)) - gomega.Expect(del[0]).To(gomega.BeEquivalentTo(routeOne)) - gomega.Expect(del[1]).To(gomega.BeEquivalentTo(routeThree)) -} diff --git a/plugins/vpp/l3plugin/vppcalls/api_vppcalls.go b/plugins/vpp/l3plugin/vppcalls/api_vppcalls.go new file mode 100644 index 0000000000..a6b10f703e --- /dev/null +++ b/plugins/vpp/l3plugin/vppcalls/api_vppcalls.go @@ -0,0 +1,166 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vppcalls + +import ( + govppapi "git.fd.io/govpp.git/api" + "github.com/ligato/cn-infra/logging" + "github.com/ligato/cn-infra/logging/measure" + "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" + "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" + "github.com/ligato/vpp-agent/plugins/vpp/model/l3" +) + +// ArpVppAPI provides methods for managing ARP entries +type ArpVppAPI interface { + ArpVppWrite + ArpVppRead +} + +// ArpVppWrite provides write methods for ARPs +type ArpVppWrite interface { + // VppAddArp adds ARP entry according to provided input + VppAddArp(entry *ArpEntry) error + // VppDelArp removes old ARP entry according to provided input + VppDelArp(entry *ArpEntry) error +} + +// ArpVppRead provides read methods for ARPs +type ArpVppRead interface { + // DumpArpEntries dumps ARPs from VPP and fills them into the provided static route map. + DumpArpEntries() ([]*ArpDetails, error) +} + +// ProxyArpVppAPI provides methods for managing proxy ARP entries +type ProxyArpVppAPI interface { + ProxyArpVppWrite + ProxyArpVppRead +} + +// ProxyArpVppWrite provides write methods for proxy ARPs +type ProxyArpVppWrite interface { + // EnableProxyArpInterface enables interface for proxy ARP + EnableProxyArpInterface(swIfIdx uint32) error + // DisableProxyArpInterface disables interface for proxy ARP + DisableProxyArpInterface(swIfIdx uint32) error + // AddProxyArpRange adds new IP range for proxy ARP + AddProxyArpRange(firstIP, lastIP []byte) error + // DeleteProxyArpRange removes proxy ARP IP range + DeleteProxyArpRange(firstIP, lastIP []byte) error +} + +// ProxyArpVppRead provides read methods for proxy ARPs +type ProxyArpVppRead interface { + // DumpProxyArpRanges returns configured proxy ARP ranges + DumpProxyArpRanges() ([]*ProxyArpRangesDetails, error) + // DumpProxyArpRanges returns configured proxy ARP interfaces + DumpProxyArpInterfaces() ([]*ProxyArpInterfaceDetails, error) +} + +// RouteVppAPI provides methods for managing routes +type RouteVppAPI interface { + RouteVppWrite + RouteVppRead +} + +// RouteVppWrite provides write methods for routes +type RouteVppWrite interface { + // VppAddRoute adds new route, according to provided input. Every route has to contain VRF ID (default is 0). + VppAddRoute(ifHandler vppcalls.IfVppWrite, route *l3.StaticRoutes_Route, rtIfIdx uint32) error + // VppDelRoute removes old route, according to provided input. Every route has to contain VRF ID (default is 0). + VppDelRoute(route *l3.StaticRoutes_Route, rtIfIdx uint32) error +} + +// RouteVppRead provides read methods for routes +type RouteVppRead interface { + // DumpStaticRoutes dumps l3 routes from VPP and fills them into the provided static route map. + DumpStaticRoutes() ([]*RouteDetails, error) +} + +// IPNeighVppAPI provides methods for managing IP scan neighbor configuration +type IPNeighVppAPI interface { + // SetIPScanNeighbor configures IP scan neighbor to the VPP + SetIPScanNeighbor(data *l3.IPScanNeighbor) error +} + +// ArpVppHandler is accessor for ARP-related vppcalls methods +type ArpVppHandler struct { + stopwatch *measure.Stopwatch + callsChannel govppapi.Channel + ifIndexes ifaceidx.SwIfIndex + log logging.Logger +} + +// ProxyArpVppHandler is accessor for proxy ARP-related vppcalls methods +type ProxyArpVppHandler struct { + stopwatch *measure.Stopwatch + callsChannel govppapi.Channel + ifIndexes ifaceidx.SwIfIndex + log logging.Logger +} + +// RouteHandler is accessor for route-related vppcalls methods +type RouteHandler struct { + stopwatch *measure.Stopwatch + callsChannel govppapi.Channel + ifIndexes ifaceidx.SwIfIndex + log logging.Logger +} + +// IPNeighHandler is accessor for ip-neighbor-related vppcalls methods +type IPNeighHandler struct { + stopwatch *measure.Stopwatch + callsChannel govppapi.Channel + log logging.Logger +} + +// NewArpVppHandler creates new instance of IPsec vppcalls handler +func NewArpVppHandler(callsChan govppapi.Channel, ifIndexes ifaceidx.SwIfIndex, log logging.Logger, stopwatch *measure.Stopwatch) *ArpVppHandler { + return &ArpVppHandler{ + callsChannel: callsChan, + stopwatch: stopwatch, + ifIndexes: ifIndexes, + log: log, + } +} + +// NewProxyArpVppHandler creates new instance of proxy ARP vppcalls handler +func NewProxyArpVppHandler(callsChan govppapi.Channel, ifIndexes ifaceidx.SwIfIndex, log logging.Logger, stopwatch *measure.Stopwatch) *ProxyArpVppHandler { + return &ProxyArpVppHandler{ + callsChannel: callsChan, + stopwatch: stopwatch, + ifIndexes: ifIndexes, + log: log, + } +} + +// NewRouteVppHandler creates new instance of route vppcalls handler +func NewRouteVppHandler(callsChan govppapi.Channel, ifIndexes ifaceidx.SwIfIndex, log logging.Logger, stopwatch *measure.Stopwatch) *RouteHandler { + return &RouteHandler{ + callsChannel: callsChan, + stopwatch: stopwatch, + ifIndexes: ifIndexes, + log: log, + } +} + +// NewIPNeighVppHandler creates new instance of ip neighbor vppcalls handler +func NewIPNeighVppHandler(callsChan govppapi.Channel, log logging.Logger, stopwatch *measure.Stopwatch) *IPNeighHandler { + return &IPNeighHandler{ + callsChannel: callsChan, + stopwatch: stopwatch, + log: log, + } +} diff --git a/plugins/vpp/l3plugin/vppcalls/arp_dump.go b/plugins/vpp/l3plugin/vppcalls/arp_dump.go new file mode 100644 index 0000000000..f2b1e597b4 --- /dev/null +++ b/plugins/vpp/l3plugin/vppcalls/arp_dump.go @@ -0,0 +1,102 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vppcalls + +import ( + "fmt" + "net" + "time" + + l3binapi "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" + "github.com/ligato/vpp-agent/plugins/vpp/model/l3" +) + +// ArpDetails holds info about ARP entry as a proto model +type ArpDetails struct { + Arp *l3.ArpTable_ArpEntry + Meta *ArpMeta +} + +// ArpMeta contains interface index of the ARP interface +type ArpMeta struct { + SwIfIndex uint32 +} + +// DumpArpEntries implements arp handler. +func (handler *ArpVppHandler) DumpArpEntries() ([]*ArpDetails, error) { + // ArpDump time measurement + defer func(t time.Time) { + handler.stopwatch.TimeLog(l3binapi.IPNeighborDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + var entries []*ArpDetails + + // Dump ARPs. + reqCtx := handler.callsChannel.SendMultiRequest(&l3binapi.IPNeighborDump{ + SwIfIndex: 0xffffffff, // Send multirequest to get all ARP entries + }) + + for { + arpDetails := &l3binapi.IPNeighborDetails{} + stop, err := reqCtx.ReceiveReply(arpDetails) + if stop { + break + } + if err != nil { + handler.log.Error(err) + return nil, err + } + + // ARP interface + ifName, _, exists := handler.ifIndexes.LookupName(arpDetails.SwIfIndex) + if !exists { + handler.log.Warnf("ARP dump: interface name not found for index %d", arpDetails.SwIfIndex) + } + // IP & MAC address + var ip, mac string + if uintToBool(arpDetails.IsIPv6) { + ip = fmt.Sprintf("%s", net.IP(arpDetails.IPAddress).To16().String()) + } else { + ip = fmt.Sprintf("%s", net.IP(arpDetails.IPAddress[:4]).To4().String()) + } + mac = net.HardwareAddr(arpDetails.MacAddress).String() + + // ARP entry + arp := &l3.ArpTable_ArpEntry{ + Interface: ifName, + IpAddress: ip, + PhysAddress: mac, + Static: uintToBool(arpDetails.IsStatic), + } + // ARP meta + meta := &ArpMeta{ + SwIfIndex: arpDetails.SwIfIndex, + } + + entries = append(entries, &ArpDetails{ + Arp: arp, + Meta: meta, + }) + } + + return entries, nil +} + +func uintToBool(value uint8) bool { + if value == 0 { + return false + } + return true +} diff --git a/plugins/vpp/l3plugin/vppcalls/arp_vppcalls.go b/plugins/vpp/l3plugin/vppcalls/arp_vppcalls.go index 60854be54d..405cf07459 100644 --- a/plugins/vpp/l3plugin/vppcalls/arp_vppcalls.go +++ b/plugins/vpp/l3plugin/vppcalls/arp_vppcalls.go @@ -19,33 +19,28 @@ import ( "net" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/cn-infra/utils/addrs" "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" ) -// ArpMessages is list of used VPP messages for compatibility check -var ArpMessages = []govppapi.Message{ - &ip.IPNeighborAddDel{}, - &ip.IPNeighborAddDelReply{}, -} - // ArpEntry represents ARP entry for interface type ArpEntry struct { Interface uint32 IPAddress net.IP - MacAddress net.HardwareAddr + MacAddress string Static bool } // vppAddDelArp adds or removes ARP entry according to provided input -func vppAddDelArp(entry *ArpEntry, vppChan govppapi.Channel, delete bool, stopwatch *measure.Stopwatch) error { +func (handler *ArpVppHandler) vppAddDelArp(entry *ArpEntry, delete bool) error { defer func(t time.Time) { - stopwatch.TimeLog(ip.IPNeighborAddDel{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(ip.IPNeighborAddDel{}).LogTimeEntry(time.Since(t)) }(time.Now()) - req := &ip.IPNeighborAddDel{} + req := &ip.IPNeighborAddDel{ + SwIfIndex: entry.Interface, + IsNoAdjFib: 1, + } if delete { req.IsAdd = 0 } else { @@ -57,10 +52,10 @@ func vppAddDelArp(entry *ArpEntry, vppChan govppapi.Channel, delete bool, stopwa return err } if isIpv6 { - req.IsIpv6 = 1 + req.IsIPv6 = 1 req.DstAddress = []byte(entry.IPAddress.To16()) } else { - req.IsIpv6 = 0 + req.IsIPv6 = 0 req.DstAddress = []byte(entry.IPAddress.To4()) } if entry.Static { @@ -68,28 +63,29 @@ func vppAddDelArp(entry *ArpEntry, vppChan govppapi.Channel, delete bool, stopwa } else { req.IsStatic = 0 } - req.MacAddress = []byte(entry.MacAddress) - req.IsNoAdjFib = 1 - req.SwIfIndex = entry.Interface + macAddr, err := net.ParseMAC(entry.MacAddress) + if err != nil { + return err + } + req.MacAddress = []byte(macAddr) + reply := &ip.IPNeighborAddDelReply{} // Send message - reply := &ip.IPNeighborAddDelReply{} - if err = vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + if err = handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } return nil } -// VppAddArp adds ARP entry according to provided input -func VppAddArp(entry *ArpEntry, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return vppAddDelArp(entry, vppChan, false, stopwatch) +// VppAddArp implements arp handler. +func (handler *ArpVppHandler) VppAddArp(entry *ArpEntry) error { + return handler.vppAddDelArp(entry, false) } -// VppDelArp removes old ARP entry according to provided input -func VppDelArp(entry *ArpEntry, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return vppAddDelArp(entry, vppChan, true, stopwatch) +// VppDelArp implements arp handler. +func (handler *ArpVppHandler) VppDelArp(entry *ArpEntry) error { + return handler.vppAddDelArp(entry, true) } diff --git a/plugins/vpp/l3plugin/vppcalls/arp_vppcalls_test.go b/plugins/vpp/l3plugin/vppcalls/arp_vppcalls_test.go index b8669ec9b0..c862a8db60 100644 --- a/plugins/vpp/l3plugin/vppcalls/arp_vppcalls_test.go +++ b/plugins/vpp/l3plugin/vppcalls/arp_vppcalls_test.go @@ -15,60 +15,72 @@ package vppcalls_test import ( + "testing" + + "github.com/ligato/cn-infra/logging/logrus" + "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" + "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" "github.com/ligato/vpp-agent/plugins/vpp/l3plugin/vppcalls" "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" - "testing" ) var arpEntries = []vppcalls.ArpEntry{ { Interface: 1, IPAddress: []byte{192, 168, 10, 21}, - MacAddress: []byte{0x59, 0x6C, 0xde, 0xad, 0x00, 0x01}, + MacAddress: "59:6C:45:59:8E:BD", Static: true, }, { Interface: 1, IPAddress: []byte{192, 168, 10, 22}, - MacAddress: []byte{0x59, 0x6C, 0xde, 0xad, 0x00, 0x02}, + MacAddress: "6C:45:59:59:8E:BD", Static: false, }, { Interface: 1, IPAddress: []byte{0xde, 0xad, 0, 0, 0, 0, 0, 0, 0xde, 0xad, 0, 0, 0, 0, 0, 1}, - MacAddress: []byte{0x59, 0x6C, 0xde, 0xad, 0x00, 0x02}, + MacAddress: "8E:BD:6C:45:59:59", Static: false, }, } // Test adding of ARP func TestAddArp(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, arpHandler := arpTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&ip.IPNeighborAddDelReply{}) - err := vppcalls.VppAddArp(&arpEntries[0], ctx.MockChannel, nil) + err := arpHandler.VppAddArp(&arpEntries[0]) Expect(err).To(Succeed()) ctx.MockVpp.MockReply(&ip.IPNeighborAddDelReply{}) - err = vppcalls.VppAddArp(&arpEntries[1], ctx.MockChannel, nil) + err = arpHandler.VppAddArp(&arpEntries[1]) Expect(err).To(Succeed()) ctx.MockVpp.MockReply(&ip.IPNeighborAddDelReply{}) - err = vppcalls.VppAddArp(&arpEntries[2], ctx.MockChannel, nil) + err = arpHandler.VppAddArp(&arpEntries[2]) Expect(err).To(Succeed()) ctx.MockVpp.MockReply(&ip.IPNeighborAddDelReply{Retval: 1}) - err = vppcalls.VppAddArp(&arpEntries[0], ctx.MockChannel, nil) + err = arpHandler.VppAddArp(&arpEntries[0]) Expect(err).To(Not(BeNil())) } // Test deleting of ARP func TestDelArp(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, arpHandler := arpTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&ip.IPNeighborAddDelReply{}) - err := vppcalls.VppDelArp(&arpEntries[0], ctx.MockChannel, nil) + err := arpHandler.VppDelArp(&arpEntries[0]) Expect(err).To(Succeed()) } + +func arpTestSetup(t *testing.T) (*vppcallmock.TestCtx, vppcalls.ArpVppAPI) { + ctx := vppcallmock.SetupTestCtx(t) + log := logrus.NewLogger("test-log") + ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(log, "arp-if-idx", nil)) + arpHandler := vppcalls.NewArpVppHandler(ctx.MockChannel, ifIndexes, log, nil) + return ctx, arpHandler +} diff --git a/plugins/vpp/l3plugin/vppcalls/doc.go b/plugins/vpp/l3plugin/vppcalls/doc.go index 5d38aca191..8ff27a465a 100644 --- a/plugins/vpp/l3plugin/vppcalls/doc.go +++ b/plugins/vpp/l3plugin/vppcalls/doc.go @@ -1,2 +1,2 @@ -// Package vppcalls contains wrappers over VPP binary APIs for L3 FIBs. +// Package vppcalls contains wrappers over VPP binary APIs for ARPs, proxy ARPs, L3 FIBs and helpers for dumping them. package vppcalls diff --git a/plugins/vpp/l3plugin/vppcalls/ipneigh_vppcalls.go b/plugins/vpp/l3plugin/vppcalls/ipneigh_vppcalls.go new file mode 100644 index 0000000000..b6c445792f --- /dev/null +++ b/plugins/vpp/l3plugin/vppcalls/ipneigh_vppcalls.go @@ -0,0 +1,48 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vppcalls + +import ( + "fmt" + "time" + + "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" + "github.com/ligato/vpp-agent/plugins/vpp/model/l3" +) + +// SetIPScanNeighbor implements ip neigh handler. +func (h *IPNeighHandler) SetIPScanNeighbor(data *l3.IPScanNeighbor) error { + defer func(t time.Time) { + h.stopwatch.TimeLog(ip.IPScanNeighborEnableDisable{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + req := &ip.IPScanNeighborEnableDisable{ + Mode: uint8(data.Mode), + ScanInterval: uint8(data.ScanInterval), + MaxProcTime: uint8(data.MaxProcTime), + MaxUpdate: uint8(data.MaxUpdate), + ScanIntDelay: uint8(data.ScanIntDelay), + StaleThreshold: uint8(data.StaleThreshold), + } + reply := &ip.IPScanNeighborEnableDisableReply{} + + if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { + return err + } else if reply.Retval != 0 { + return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) + } + + return nil +} diff --git a/plugins/vpp/l3plugin/vppcalls/proxyarp_dump.go b/plugins/vpp/l3plugin/vppcalls/proxyarp_dump.go new file mode 100644 index 0000000000..baa4821a61 --- /dev/null +++ b/plugins/vpp/l3plugin/vppcalls/proxyarp_dump.go @@ -0,0 +1,113 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vppcalls + +import ( + "fmt" + "net" + "time" + + l3binapi "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" + "github.com/ligato/vpp-agent/plugins/vpp/model/l3" +) + +// ProxyArpRangesDetails holds info about proxy ARP range as a proto modeled data +type ProxyArpRangesDetails struct { + Range *l3.ProxyArpRanges_RangeList_Range +} + +// DumpProxyArpRanges implements proxy arp handler. +func (handler *ProxyArpVppHandler) DumpProxyArpRanges() (pArpRngs []*ProxyArpRangesDetails, err error) { + // ArpDump time measurement + defer func(t time.Time) { + handler.stopwatch.TimeLog(l3binapi.ProxyArpDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + // Dump proxy ARP rages + reqCtx := handler.callsChannel.SendMultiRequest(&l3binapi.ProxyArpDump{}) + + for { + proxyArpDetails := &l3binapi.ProxyArpDetails{} + stop, err := reqCtx.ReceiveReply(proxyArpDetails) + if stop { + break + } + if err != nil { + handler.log.Error(err) + return nil, err + } + + pArpRngs = append(pArpRngs, &ProxyArpRangesDetails{ + Range: &l3.ProxyArpRanges_RangeList_Range{ + FirstIp: fmt.Sprintf("%s", net.IP(proxyArpDetails.Proxy.LowAddress[:4]).To4().String()), + LastIp: fmt.Sprintf("%s", net.IP(proxyArpDetails.Proxy.HiAddress[:4]).To4().String()), + }, + }) + } + + return pArpRngs, nil +} + +// ProxyArpInterfaceDetails holds info about proxy ARP interfaces as a proto modeled data +type ProxyArpInterfaceDetails struct { + Interface *l3.ProxyArpInterfaces_InterfaceList_Interface + Meta *ProxyArpInterfaceMeta +} + +// ProxyArpInterfaceMeta contains interface vpp index +type ProxyArpInterfaceMeta struct { + SwIfIndex uint32 +} + +// DumpProxyArpInterfaces implements proxy arp handler. +func (handler *ProxyArpVppHandler) DumpProxyArpInterfaces() (pArpIfs []*ProxyArpInterfaceDetails, err error) { + defer func(t time.Time) { + handler.stopwatch.TimeLog(l3binapi.ProxyArpIntfcDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + // Dump proxy ARP interfaces + reqCtx := handler.callsChannel.SendMultiRequest(&l3binapi.ProxyArpIntfcDump{}) + + for { + proxyArpDetails := &l3binapi.ProxyArpIntfcDetails{} + stop, err := reqCtx.ReceiveReply(proxyArpDetails) + if stop { + break + } + if err != nil { + handler.log.Error(err) + return nil, err + } + + // Interface + ifName, _, exists := handler.ifIndexes.LookupName(proxyArpDetails.SwIfIndex) + if !exists { + handler.log.Warnf("Proxy ARP interface dump: missing name for interface index %d", proxyArpDetails.SwIfIndex) + } + + // Create entry + pArpIfs = append(pArpIfs, &ProxyArpInterfaceDetails{ + Interface: &l3.ProxyArpInterfaces_InterfaceList_Interface{ + Name: ifName, + }, + Meta: &ProxyArpInterfaceMeta{ + SwIfIndex: proxyArpDetails.SwIfIndex, + }, + }) + + } + + return pArpIfs, nil +} diff --git a/plugins/vpp/l3plugin/vppcalls/proxyarp_vppcalls.go b/plugins/vpp/l3plugin/vppcalls/proxyarp_vppcalls.go index 7a666e5b0e..fab2e6fc6e 100644 --- a/plugins/vpp/l3plugin/vppcalls/proxyarp_vppcalls.go +++ b/plugins/vpp/l3plugin/vppcalls/proxyarp_vppcalls.go @@ -18,44 +18,33 @@ import ( "fmt" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" ) -// ProxyArpMessages is list of used VPP messages for compatibility check -var ProxyArpMessages = []govppapi.Message{ - &ip.ProxyArpIntfcEnableDisable{}, - &ip.ProxyArpIntfcEnableDisableReply{}, - &ip.ProxyArpAddDel{}, - &ip.ProxyArpAddDelReply{}, +// EnableProxyArpInterface implements proxy arp handler. +func (handler *ProxyArpVppHandler) EnableProxyArpInterface(swIfIdx uint32) error { + return handler.vppAddDelProxyArpInterface(swIfIdx, true) } -// EnableProxyArpInterface enables interface for proxy ARP -func EnableProxyArpInterface(swIfIdx uint32, vppChan govppapi.Channel, log logging.Logger, stopwatch *measure.Stopwatch) error { - return vppAddDelProxyArpInterface(swIfIdx, vppChan, true, log, stopwatch) +// DisableProxyArpInterface implements proxy arp handler. +func (handler *ProxyArpVppHandler) DisableProxyArpInterface(swIfIdx uint32) error { + return handler.vppAddDelProxyArpInterface(swIfIdx, false) } -// DisableProxyArpInterface disables interface for proxy ARP -func DisableProxyArpInterface(swIfIdx uint32, vppChan govppapi.Channel, log logging.Logger, stopwatch *measure.Stopwatch) error { - return vppAddDelProxyArpInterface(swIfIdx, vppChan, false, log, stopwatch) +// AddProxyArpRange implements proxy arp handler. +func (handler *ProxyArpVppHandler) AddProxyArpRange(firstIP, lastIP []byte) error { + return handler.vppAddDelProxyArpRange(firstIP, lastIP, true) } -// AddProxyArpRange adds new IP range for proxy ARP -func AddProxyArpRange(firstIP, lastIP []byte, vppChan govppapi.Channel, log logging.Logger, stopwatch *measure.Stopwatch) error { - return vppAddDelProxyArpRange(firstIP, lastIP, vppChan, true, log, stopwatch) -} - -// DeleteProxyArpRange removes proxy ARP IP range -func DeleteProxyArpRange(firstIP, lastIP []byte, vppChan govppapi.Channel, log logging.Logger, stopwatch *measure.Stopwatch) error { - return vppAddDelProxyArpRange(firstIP, lastIP, vppChan, false, log, stopwatch) +// DeleteProxyArpRange implements proxy arp handler. +func (handler *ProxyArpVppHandler) DeleteProxyArpRange(firstIP, lastIP []byte) error { + return handler.vppAddDelProxyArpRange(firstIP, lastIP, false) } // vppAddDelProxyArpInterface adds or removes proxy ARP interface entry according to provided input -func vppAddDelProxyArpInterface(swIfIdx uint32, vppChan govppapi.Channel, enable bool, log logging.Logger, stopwatch *measure.Stopwatch) error { +func (handler *ProxyArpVppHandler) vppAddDelProxyArpInterface(swIfIdx uint32, enable bool) error { defer func(t time.Time) { - stopwatch.TimeLog(ip.ProxyArpIntfcEnableDisable{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(ip.ProxyArpIntfcEnableDisable{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &ip.ProxyArpIntfcEnableDisable{} @@ -68,22 +57,22 @@ func vppAddDelProxyArpInterface(swIfIdx uint32, vppChan govppapi.Channel, enable // Send message reply := &ip.ProxyArpIntfcEnableDisableReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err } if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } - log.Debugf("interface %v enabled for proxy arp: %v", req.SwIfIndex, enable) + handler.log.Debugf("interface %v enabled for proxy arp: %v", req.SwIfIndex, enable) return nil } // vppAddDelProxyArpRange adds or removes proxy ARP range according to provided input -func vppAddDelProxyArpRange(firstIP, lastIP []byte, vppChan govppapi.Channel, isAdd bool, log logging.Logger, stopwatch *measure.Stopwatch) error { +func (handler *ProxyArpVppHandler) vppAddDelProxyArpRange(firstIP, lastIP []byte, isAdd bool) error { defer func(t time.Time) { - stopwatch.TimeLog(ip.ProxyArpAddDel{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(ip.ProxyArpAddDel{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &ip.ProxyArpAddDel{} @@ -96,17 +85,16 @@ func vppAddDelProxyArpRange(firstIP, lastIP []byte, vppChan govppapi.Channel, is LowAddress: firstIP, HiAddress: lastIP, } + reply := &ip.ProxyArpAddDelReply{} // Send message - reply := &ip.ProxyArpAddDelReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval) } - log.Debugf("proxy arp range: %v - %v added: %v", req.Proxy.LowAddress, req.Proxy.HiAddress, isAdd) + handler.log.Debugf("proxy arp range: %v - %v added: %v", req.Proxy.LowAddress, req.Proxy.HiAddress, isAdd) return nil } diff --git a/plugins/vpp/l3plugin/vppcalls/proxyarp_vppcalls_test.go b/plugins/vpp/l3plugin/vppcalls/proxyarp_vppcalls_test.go index 6b90946534..bf40f8b325 100644 --- a/plugins/vpp/l3plugin/vppcalls/proxyarp_vppcalls_test.go +++ b/plugins/vpp/l3plugin/vppcalls/proxyarp_vppcalls_test.go @@ -15,46 +15,58 @@ package vppcalls_test import ( + "testing" + "github.com/ligato/cn-infra/logging/logrus" + "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" + "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" "github.com/ligato/vpp-agent/plugins/vpp/l3plugin/vppcalls" "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" - "testing" ) // Test enable/disable proxy arp func TestProxyArp(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, arpHandler, pArpHandler := pArpTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&ip.ProxyArpIntfcEnableDisableReply{}) - err := vppcalls.EnableProxyArpInterface(0, ctx.MockChannel, logrus.DefaultLogger(), nil) + err := pArpHandler.EnableProxyArpInterface(0) Expect(err).To(Succeed()) ctx.MockVpp.MockReply(&ip.ProxyArpIntfcEnableDisableReply{}) - err = vppcalls.DisableProxyArpInterface(0, ctx.MockChannel, logrus.DefaultLogger(), nil) + err = pArpHandler.DisableProxyArpInterface(0) Expect(err).To(Succeed()) ctx.MockVpp.MockReply(&ip.ProxyArpIntfcEnableDisableReply{Retval: 1}) - err = vppcalls.VppAddArp(&arpEntries[0], ctx.MockChannel, nil) + err = arpHandler.VppAddArp(&arpEntries[0]) Expect(err).To(Not(BeNil())) } // Test add/delete ip range for proxy arp func TestProxyArpRange(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, _, pArpHandler := pArpTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&ip.ProxyArpAddDelReply{}) - err := vppcalls.AddProxyArpRange([]byte{192, 168, 10, 20}, []byte{192, 168, 10, 30}, ctx.MockChannel, logrus.DefaultLogger(), nil) + err := pArpHandler.AddProxyArpRange([]byte{192, 168, 10, 20}, []byte{192, 168, 10, 30}) Expect(err).To(Succeed()) ctx.MockVpp.MockReply(&ip.ProxyArpAddDelReply{}) - err = vppcalls.DeleteProxyArpRange([]byte{192, 168, 10, 23}, []byte{192, 168, 10, 27}, ctx.MockChannel, logrus.DefaultLogger(), nil) + err = pArpHandler.DeleteProxyArpRange([]byte{192, 168, 10, 23}, []byte{192, 168, 10, 27}) Expect(err).To(Succeed()) ctx.MockVpp.MockReply(&ip.ProxyArpAddDelReply{Retval: 1}) - err = vppcalls.AddProxyArpRange([]byte{192, 168, 10, 23}, []byte{192, 168, 10, 27}, ctx.MockChannel, logrus.DefaultLogger(), nil) + err = pArpHandler.AddProxyArpRange([]byte{192, 168, 10, 23}, []byte{192, 168, 10, 27}) Expect(err).To(Not(BeNil())) } + +func pArpTestSetup(t *testing.T) (*vppcallmock.TestCtx, vppcalls.ArpVppAPI, vppcalls.ProxyArpVppAPI) { + ctx := vppcallmock.SetupTestCtx(t) + log := logrus.NewLogger("test-log") + ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(log, "proxy-arp-if-idx", nil)) + arpHandler := vppcalls.NewArpVppHandler(ctx.MockChannel, ifIndexes, log, nil) + pArpHandler := vppcalls.NewProxyArpVppHandler(ctx.MockChannel, ifIndexes, log, nil) + return ctx, arpHandler, pArpHandler +} diff --git a/plugins/vpp/l3plugin/vppcalls/route_dump.go b/plugins/vpp/l3plugin/vppcalls/route_dump.go new file mode 100644 index 0000000000..532882a3d1 --- /dev/null +++ b/plugins/vpp/l3plugin/vppcalls/route_dump.go @@ -0,0 +1,211 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vppcalls + +import ( + "bytes" + "fmt" + "net" + "time" + + l3binapi "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" + "github.com/ligato/vpp-agent/plugins/vpp/model/l3" +) + +// RouteDetails is object returned as a VPP dump. It contains static route data in proto format, and VPP-specific +// metadata +type RouteDetails struct { + Route *l3.StaticRoutes_Route + Meta *RouteMeta +} + +// RouteMeta holds fields returned from the VPP as details which are not in the model +type RouteMeta struct { + TableName string + OutgoingIfIdx uint32 + IsIPv6 bool + Afi uint8 + IsLocal bool + IsUDPEncap bool + IsUnreach bool + IsProhibit bool + IsResolveHost bool + IsResolveAttached bool + IsDvr bool + IsSourceLookup bool + NextHopID uint32 + RpfID uint32 + LabelStack []l3binapi.FibMplsLabel +} + +// DumpStaticRoutes implements route handler. +func (handler *RouteHandler) DumpStaticRoutes() ([]*RouteDetails, error) { + // IPFibDump time measurement + defer func(t time.Time) { + handler.stopwatch.TimeLog(l3binapi.IPFibDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + var routes []*RouteDetails + + // Dump IPv4 l3 FIB. + reqCtx := handler.callsChannel.SendMultiRequest(&l3binapi.IPFibDump{}) + for { + fibDetails := &l3binapi.IPFibDetails{} + stop, err := reqCtx.ReceiveReply(fibDetails) + if stop { + break + } + if err != nil { + return nil, err + } + ipv4Route, err := handler.dumpStaticRouteIPv4Details(fibDetails) + if err != nil { + return nil, err + } + routes = append(routes, ipv4Route...) + } + + // Dump IPv6 l3 FIB. + reqCtx = handler.callsChannel.SendMultiRequest(&l3binapi.IP6FibDump{}) + for { + fibDetails := &l3binapi.IP6FibDetails{} + stop, err := reqCtx.ReceiveReply(fibDetails) + if stop { + break + } + if err != nil { + return nil, err + } + ipv6Route, err := handler.dumpStaticRouteIPv6Details(fibDetails) + if err != nil { + return nil, err + } + routes = append(routes, ipv6Route...) + } + + return routes, nil +} + +func (handler *RouteHandler) dumpStaticRouteIPv4Details(fibDetails *l3binapi.IPFibDetails) ([]*RouteDetails, error) { + return handler.dumpStaticRouteIPDetails(fibDetails.TableID, fibDetails.TableName, fibDetails.Address, fibDetails.AddressLength, fibDetails.Path, false) +} + +func (handler *RouteHandler) dumpStaticRouteIPv6Details(fibDetails *l3binapi.IP6FibDetails) ([]*RouteDetails, error) { + return handler.dumpStaticRouteIPDetails(fibDetails.TableID, fibDetails.TableName, fibDetails.Address, fibDetails.AddressLength, fibDetails.Path, true) +} + +// dumpStaticRouteIPDetails processes static route details and returns a route objects. Number of routes returned +// depends on size of path list. +func (handler *RouteHandler) dumpStaticRouteIPDetails(tableID uint32, tableName []byte, address []byte, prefixLen uint8, paths []l3binapi.FibPath, ipv6 bool) ([]*RouteDetails, error) { + // Common fields for every route path (destination IP, VRF) + var dstIP string + if ipv6 { + dstIP = fmt.Sprintf("%s/%d", net.IP(address).To16().String(), uint32(prefixLen)) + } else { + dstIP = fmt.Sprintf("%s/%d", net.IP(address[:4]).To4().String(), uint32(prefixLen)) + } + + var routeDetails []*RouteDetails + + // Paths + if len(paths) > 0 { + for _, path := range paths { + // Next hop IP address + var nextHopIP string + if ipv6 { + nextHopIP = fmt.Sprintf("%s", net.IP(path.NextHop).To16().String()) + } else { + nextHopIP = fmt.Sprintf("%s", net.IP(path.NextHop[:4]).To4().String()) + } + + // Route type (if via VRF is used) + var routeType l3.StaticRoutes_Route_RouteType + var viaVrfID uint32 + if path.SwIfIndex == NextHopOutgoingIfUnset && path.TableID != tableID { + // outgoing interface not specified and path table id not equal to route table id = inter-VRF route + routeType = l3.StaticRoutes_Route_INTER_VRF + viaVrfID = path.TableID + } else if uintToBool(path.IsDrop) { + routeType = l3.StaticRoutes_Route_DROP + } else { + routeType = l3.StaticRoutes_Route_INTRA_VRF // default + } + + // Outgoing interface + var ifName string + var ifIdx uint32 + if path.SwIfIndex != ^uint32(0) { + var exists bool + ifIdx = path.SwIfIndex + if ifName, _, exists = handler.ifIndexes.LookupName(path.SwIfIndex); !exists { + handler.log.Warnf("Static route dump: interface name for index %d not found", path.SwIfIndex) + } + } + + // Route configuration + route := &l3.StaticRoutes_Route{ + Type: routeType, + VrfId: tableID, + DstIpAddr: dstIP, + NextHopAddr: nextHopIP, + OutgoingInterface: ifName, + Weight: uint32(path.Weight), + Preference: uint32(path.Preference), + ViaVrfId: viaVrfID, + } + + // Route metadata + meta := &RouteMeta{ + TableName: string(bytes.SplitN(tableName, []byte{0x00}, 2)[0]), + OutgoingIfIdx: ifIdx, + NextHopID: path.NextHopID, + IsIPv6: ipv6, + RpfID: path.RpfID, + Afi: path.Afi, + IsLocal: uintToBool(path.IsLocal), + IsUDPEncap: uintToBool(path.IsUDPEncap), + IsDvr: uintToBool(path.IsDvr), + IsProhibit: uintToBool(path.IsProhibit), + IsResolveAttached: uintToBool(path.IsResolveAttached), + IsResolveHost: uintToBool(path.IsResolveHost), + IsSourceLookup: uintToBool(path.IsSourceLookup), + IsUnreach: uintToBool(path.IsUnreach), + LabelStack: path.LabelStack, + } + + routeDetails = append(routeDetails, &RouteDetails{ + Route: route, + Meta: meta, + }) + } + } else { + // Return route without path fields, but this is not a valid configuration + handler.log.Warnf("Route with destination IP %s (VRF %d) has no path specified", dstIP, tableID) + route := &l3.StaticRoutes_Route{ + Type: l3.StaticRoutes_Route_INTRA_VRF, // default + VrfId: tableID, + DstIpAddr: dstIP, + } + meta := &RouteMeta{ + TableName: string(bytes.SplitN(tableName, []byte{0x00}, 2)[0]), + } + routeDetails = append(routeDetails, &RouteDetails{ + Route: route, + Meta: meta, + }) + } + + return routeDetails, nil +} diff --git a/plugins/vpp/l3plugin/vppdump/dump_vppcalls_test.go b/plugins/vpp/l3plugin/vppcalls/route_dump_test.go similarity index 67% rename from plugins/vpp/l3plugin/vppdump/dump_vppcalls_test.go rename to plugins/vpp/l3plugin/vppcalls/route_dump_test.go index 584ad743cd..ff12ca4ca5 100644 --- a/plugins/vpp/l3plugin/vppdump/dump_vppcalls_test.go +++ b/plugins/vpp/l3plugin/vppcalls/route_dump_test.go @@ -12,23 +12,30 @@ // See the License for the specific language governing permissions and // limitations under the License. -package vppdump_test +package vppcalls import ( + "testing" + "github.com/ligato/cn-infra/logging/logrus" + "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" "github.com/ligato/vpp-agent/plugins/vpp/binapi/vpe" - "github.com/ligato/vpp-agent/plugins/vpp/l3plugin/vppdump" + "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" - "testing" ) // Test dumping routes func TestDumpStaticRoutes(t *testing.T) { ctx := vppcallmock.SetupTestCtx(t) + ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "rt-dump-if-idx", nil)) + l3handler := NewRouteVppHandler(ctx.MockChannel, ifIndexes, logrus.DefaultLogger(), nil) defer ctx.TeardownTestCtx() + ifIndexes.RegisterName("if1", 2, nil) + ifIndexes.RegisterName("if2", 3, nil) + ctx.MockVpp.MockReply(&ip.IPFibDetails{ Path: []ip.FibPath{{SwIfIndex: 3}}, }) @@ -38,9 +45,9 @@ func TestDumpStaticRoutes(t *testing.T) { }) ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) - routes, err := vppdump.DumpStaticRoutes(logrus.DefaultLogger(), ctx.MockChannel, nil) + rtDetails, err := l3handler.DumpStaticRoutes() Expect(err).To(Succeed()) - Expect(routes).To(HaveLen(2)) - Expect(routes[0].OutIface).To(Equal(uint32(3))) - Expect(routes[1].OutIface).To(Equal(uint32(2))) + Expect(rtDetails).To(HaveLen(2)) + Expect(rtDetails[0].Route.OutgoingInterface).To(Equal("if2")) + Expect(rtDetails[1].Route.OutgoingInterface).To(Equal("if1")) } diff --git a/plugins/vpp/l3plugin/vppcalls/route_vppcalls.go b/plugins/vpp/l3plugin/vppcalls/route_vppcalls.go index ecd221a260..a052b314ae 100644 --- a/plugins/vpp/l3plugin/vppcalls/route_vppcalls.go +++ b/plugins/vpp/l3plugin/vppcalls/route_vppcalls.go @@ -16,37 +16,16 @@ package vppcalls import ( "fmt" - "net" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" + "net" + "github.com/ligato/cn-infra/utils/addrs" "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" ifvppcalls "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" + "github.com/ligato/vpp-agent/plugins/vpp/model/l3" ) -var RouteMessages = []govppapi.Message{ - &ip.IPAddDelRoute{}, - &ip.IPAddDelRouteReply{}, - &ip.IPFibDump{}, - &ip.IPFibDetails{}, - &ip.IP6FibDump{}, - &ip.IP6FibDetails{}, -} - -// Route represents a forward IP route entry with the parameters of gateway -// to which packets should be forwarded when a given routing table entry is applied. -type Route struct { - VrfID uint32 `json:"vrf_id"` - TableName string `json:"table_name"` - DstAddr net.IPNet `json:"dst_addr"` - NextHopAddr net.IP `json:"next_hop_addr"` - OutIface uint32 `json:"out_iface"` - Weight uint32 `json:"weight"` - Preference uint32 `json:"preference"` -} - const ( // NextHopViaLabelUnset constant has to be assigned into the field next hop // via label in ip_add_del_route binary message if next hop via label is not defined. @@ -62,9 +41,9 @@ const ( ) // vppAddDelRoute adds or removes route, according to provided input. Every route has to contain VRF ID (default is 0). -func vppAddDelRoute(route *Route, vppChan govppapi.Channel, delete bool, stopwatch *measure.Stopwatch) error { +func (handler *RouteHandler) vppAddDelRoute(route *l3.StaticRoutes_Route, rtIfIdx uint32, delete bool) error { defer func(t time.Time) { - stopwatch.TimeLog(ip.IPAddDelRoute{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(ip.IPAddDelRoute{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &ip.IPAddDelRoute{} @@ -75,40 +54,47 @@ func vppAddDelRoute(route *Route, vppChan govppapi.Channel, delete bool, stopwat } // Destination address (route set identifier) - ipAddr := route.DstAddr.IP - prefix, _ := route.DstAddr.Mask.Size() - isIpv6, err := addrs.IsIPv6(ipAddr.String()) + parsedDstIP, isIpv6, err := addrs.ParseIPWithPrefix(route.DstIpAddr) if err != nil { return err } + parsedNextHopIP := net.ParseIP(route.NextHopAddr) + prefix, _ := parsedDstIP.Mask.Size() if isIpv6 { - req.IsIpv6 = 1 - req.DstAddress = []byte(ipAddr.To16()) + req.IsIPv6 = 1 + req.DstAddress = []byte(parsedDstIP.IP.To16()) + req.NextHopAddress = []byte(parsedNextHopIP.To16()) } else { - req.IsIpv6 = 0 - req.DstAddress = []byte(ipAddr.To4()) + req.IsIPv6 = 0 + req.DstAddress = []byte(parsedDstIP.IP.To4()) + req.NextHopAddress = []byte(parsedNextHopIP.To4()) } req.DstAddressLength = byte(prefix) - // Next hop address and parameters - req.NextHopAddress = []byte(route.NextHopAddr) - req.NextHopSwIfIndex = route.OutIface + // Common route parameters req.NextHopWeight = uint8(route.Weight) req.NextHopPreference = uint8(route.Preference) - req.NextHopTableID = route.VrfID req.NextHopViaLabel = NextHopViaLabelUnset req.ClassifyTableIndex = ClassifyTableIndexUnset - req.IsDrop = 0 - // VRF - req.TableID = route.VrfID + // VRF/Other route parameters based on type + req.TableID = route.VrfId + if route.Type == l3.StaticRoutes_Route_INTER_VRF { + req.NextHopSwIfIndex = rtIfIdx + req.NextHopTableID = route.ViaVrfId + } else if route.Type == l3.StaticRoutes_Route_DROP { + req.IsDrop = 1 + } else { + req.NextHopSwIfIndex = rtIfIdx + req.NextHopTableID = route.VrfId + } // Multi path is always true req.IsMultipath = 1 // Send message reply := &ip.IPAddDelRouteReply{} - if err = vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err } if reply.Retval != 0 { @@ -118,15 +104,39 @@ func vppAddDelRoute(route *Route, vppChan govppapi.Channel, delete bool, stopwat return nil } -// VppAddRoute adds new route, according to provided input. Every route has to contain VRF ID (default is 0). -func VppAddRoute(route *Route, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - if err := ifvppcalls.CreateVrfIfNeeded(route.VrfID, vppChan); err != nil { +// VppAddRoute implements route handler. +func (handler *RouteHandler) VppAddRoute(ifHandler ifvppcalls.IfVppWrite, route *l3.StaticRoutes_Route, rtIfIdx uint32) error { + // Evaluate route IP version + _, isIPv6, err := addrs.ParseIPWithPrefix(route.DstIpAddr) + if err != nil { return err } - return vppAddDelRoute(route, vppChan, false, stopwatch) + + if isIPv6 { + // Configure IPv6 VRF + if err := ifHandler.CreateVrfIPv6(route.VrfId); err != nil { + return err + } + if route.Type == l3.StaticRoutes_Route_INTER_VRF { + if err := ifHandler.CreateVrfIPv6(route.ViaVrfId); err != nil { + return err + } + } + } else { + // Configure IPv4 VRF + if err := ifHandler.CreateVrf(route.VrfId); err != nil { + return err + } + if route.Type == l3.StaticRoutes_Route_INTER_VRF { + if err := ifHandler.CreateVrf(route.ViaVrfId); err != nil { + return err + } + } + } + return handler.vppAddDelRoute(route, rtIfIdx, false) } -// VppDelRoute removes old route, according to provided input. Every route has to contain VRF ID (default is 0). -func VppDelRoute(route *Route, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) error { - return vppAddDelRoute(route, vppChan, true, stopwatch) +// VppDelRoute implements route handler. +func (handler *RouteHandler) VppDelRoute(route *l3.StaticRoutes_Route, rtIfIdx uint32) error { + return handler.vppAddDelRoute(route, rtIfIdx, true) } diff --git a/plugins/vpp/l3plugin/vppcalls/route_vppcalls_test.go b/plugins/vpp/l3plugin/vppcalls/route_vppcalls_test.go index 7d5fc4ee7a..62a5765c85 100644 --- a/plugins/vpp/l3plugin/vppcalls/route_vppcalls_test.go +++ b/plugins/vpp/l3plugin/vppcalls/route_vppcalls_test.go @@ -15,59 +15,73 @@ package vppcalls_test import ( + "testing" + + "github.com/ligato/cn-infra/logging/logrus" + "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" "github.com/ligato/vpp-agent/plugins/vpp/binapi/vpe" + "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" + ifvppcalls "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/vppcalls" "github.com/ligato/vpp-agent/plugins/vpp/l3plugin/vppcalls" + "github.com/ligato/vpp-agent/plugins/vpp/model/l3" "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" - "net" - "testing" ) -var routes = []vppcalls.Route{ +var routes = []*l3.StaticRoutes_Route{ { - VrfID: 1, - DstAddr: net.IPNet{IP: []byte{192, 168, 10, 21}, Mask: []byte{255, 255, 255, 0}}, - NextHopAddr: []byte{192, 168, 30, 1}, + VrfId: 1, + DstIpAddr: "192.168.10.21/24", + NextHopAddr: "192.168.30.1", }, { - VrfID: 2, - DstAddr: net.IPNet{IP: []byte{0xde, 0xad, 0, 0, 0, 0, 0, 0, 0xde, 0xad, 0, 0, 0, 0, 0, 1}, Mask: []byte{}}, - NextHopAddr: []byte{192, 168, 30, 1}, + VrfId: 2, + DstIpAddr: "10.0.0.1/24", + NextHopAddr: "192.168.30.1", }, } // Test adding routes func TestAddRoute(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, ifHandler, rtHandler := routeTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&ip.IPFibDetails{}) ctx.MockVpp.MockReply(&vpe.ControlPingReply{}) ctx.MockVpp.MockReply(&ip.IPTableAddDelReply{}) ctx.MockVpp.MockReply(&ip.IPAddDelRouteReply{}) - err := vppcalls.VppAddRoute(&routes[0], ctx.MockChannel, nil) + err := rtHandler.VppAddRoute(ifHandler, routes[0], 0) Expect(err).To(Succeed()) ctx.MockVpp.MockReply(&ip.IPAddDelRouteReply{}) - err = vppcalls.VppAddRoute(&routes[0], ctx.MockChannel, nil) + err = rtHandler.VppAddRoute(ifHandler, routes[0], 0) Expect(err).To(Not(BeNil())) } -// Test deleteing routes +// Test deleting routes func TestDeleteRoute(t *testing.T) { - ctx := vppcallmock.SetupTestCtx(t) + ctx, _, rtHandler := routeTestSetup(t) defer ctx.TeardownTestCtx() ctx.MockVpp.MockReply(&ip.IPAddDelRouteReply{}) - err := vppcalls.VppDelRoute(&routes[0], ctx.MockChannel, nil) + err := rtHandler.VppDelRoute(routes[0], ^uint32(0)) Expect(err).To(Succeed()) ctx.MockVpp.MockReply(&ip.IPAddDelRouteReply{}) - err = vppcalls.VppDelRoute(&routes[1], ctx.MockChannel, nil) + err = rtHandler.VppDelRoute(routes[1], ^uint32(0)) Expect(err).To(Succeed()) - ctx.MockVpp.MockReply(&ip.IPAddDelRouteReply{1}) - err = vppcalls.VppDelRoute(&routes[0], ctx.MockChannel, nil) + ctx.MockVpp.MockReply(&ip.IPAddDelRouteReply{Retval: 1}) + err = rtHandler.VppDelRoute(routes[0], ^uint32(0)) Expect(err).To(Not(BeNil())) } + +func routeTestSetup(t *testing.T) (*vppcallmock.TestCtx, ifvppcalls.IfVppAPI, vppcalls.RouteVppAPI) { + ctx := vppcallmock.SetupTestCtx(t) + log := logrus.NewLogger("test-log") + ifHandler := ifvppcalls.NewIfVppHandler(ctx.MockChannel, log, nil) + ifIndexes := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(log, "rt-if-idx", nil)) + rtHandler := vppcalls.NewRouteVppHandler(ctx.MockChannel, ifIndexes, log, nil) + return ctx, ifHandler, rtHandler +} diff --git a/plugins/vpp/l3plugin/vppdump/doc.go b/plugins/vpp/l3plugin/vppdump/doc.go deleted file mode 100644 index f390e50fe1..0000000000 --- a/plugins/vpp/l3plugin/vppdump/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package vppdump provides helpers for dumping all L3 FIBs configured in VPP. -package vppdump diff --git a/plugins/vpp/l3plugin/vppdump/dump_vppcalls.go b/plugins/vpp/l3plugin/vppdump/dump_vppcalls.go deleted file mode 100644 index 85689fa17a..0000000000 --- a/plugins/vpp/l3plugin/vppdump/dump_vppcalls.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (c) 2017 Cisco and/or its affiliates. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at: -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package vppdump - -import ( - "fmt" - "net" - - "time" - - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/measure" - "github.com/ligato/cn-infra/utils/addrs" - l3ba "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" - "github.com/ligato/vpp-agent/plugins/vpp/l3plugin/vppcalls" -) - -// DumpStaticRoutes dumps l3 routes from VPP and fills them into the provided static route map. -func DumpStaticRoutes(log logging.Logger, vppChan govppapi.Channel, timeLog measure.StopWatchEntry) ([]*vppcalls.Route, error) { - // IPFibDump time measurement - start := time.Now() - defer func() { - if timeLog != nil { - timeLog.LogTimeEntry(time.Since(start)) - } - }() - - var routes []*vppcalls.Route - - // Dump IPv4 l3 FIB. - reqCtx := vppChan.SendMultiRequest(&l3ba.IPFibDump{}) - for { - fibDetails := &l3ba.IPFibDetails{} - stop, err := reqCtx.ReceiveReply(fibDetails) - if stop { - break // Break from the loop. - } - if err != nil { - log.Error(err) - return nil, err - } - - ipv4Route, err := dumpStaticRouteIPv4Details(fibDetails) - if err != nil { - return nil, err - } - routes = append(routes, ipv4Route) - } - - // Dump IPv6 l3 FIB. - reqCtx = vppChan.SendMultiRequest(&l3ba.IP6FibDump{}) - for { - fibDetails := &l3ba.IP6FibDetails{} - stop, err := reqCtx.ReceiveReply(fibDetails) - if stop { - break // break out of the loop - } - if err != nil { - log.Error(err) - return nil, err - } - ipv6Route, err := dumpStaticRouteIPv6Details(fibDetails) - if err != nil { - return nil, err - } - routes = append(routes, ipv6Route) - } - - return routes, nil -} - -func dumpStaticRouteIPv4Details(fibDetails *l3ba.IPFibDetails) (*vppcalls.Route, error) { - return dumpStaticRouteIPDetails(fibDetails.TableID, fibDetails.TableName, fibDetails.Address, fibDetails.AddressLength, fibDetails.Path, false) -} - -func dumpStaticRouteIPv6Details(fibDetails *l3ba.IP6FibDetails) (*vppcalls.Route, error) { - return dumpStaticRouteIPDetails(fibDetails.TableID, fibDetails.TableName, fibDetails.Address, fibDetails.AddressLength, fibDetails.Path, true) -} - -// dumpStaticRouteIPDetails processes static route details and returns a route object -func dumpStaticRouteIPDetails(tableID uint32, tableName []byte, address []byte, prefixLen uint8, path []l3ba.FibPath, ipv6 bool) (*vppcalls.Route, error) { - // route details - var ipAddr string - if ipv6 { - ipAddr = fmt.Sprintf("%s/%d", net.IP(address).To16().String(), uint32(prefixLen)) - } else { - ipAddr = fmt.Sprintf("%s/%d", net.IP(address[:4]).To4().String(), uint32(prefixLen)) - } - - rt := &vppcalls.Route{} - - // IP net - parsedIP, _, err := addrs.ParseIPWithPrefix(ipAddr) - if err != nil { - return nil, err - } - - rt.TableName = string(tableName) - rt.VrfID = tableID - rt.DstAddr = *parsedIP - - if len(path) > 0 { - var nextHopAddr net.IP - if ipv6 { - nextHopAddr = net.IP(path[0].NextHop).To16() - } else { - nextHopAddr = net.IP(path[0].NextHop[:4]).To4() - } - - rt.NextHopAddr = nextHopAddr - rt.OutIface = path[0].SwIfIndex - rt.Preference = uint32(path[0].Preference) - rt.Weight = uint32(path[0].Weight) - } - - return rt, nil -} diff --git a/plugins/vpp/l4plugin/appns_config.go b/plugins/vpp/l4plugin/appns_config.go index 2df5453d99..18d25091d8 100644 --- a/plugins/vpp/l4plugin/appns_config.go +++ b/plugins/vpp/l4plugin/appns_config.go @@ -47,7 +47,10 @@ type AppNsConfigurator struct { appNsIdxSeq uint32 // VPP channel - vppChan govppapi.Channel + vppChan govppapi.Channel + // VPP API handler + l4Handler vppcalls.L4VppAPI + stopwatch *measure.Stopwatch // Feature flag - internal state whether the L4 features are enabled or disabled @@ -77,11 +80,8 @@ func (plugin *AppNsConfigurator) Init(logger logging.PluginLogger, goVppMux govp return err } - // Message compatibility - if err = plugin.vppChan.CheckMessageCompatibility(vppcalls.AppNsMessages...); err != nil { - plugin.log.Error(err) - return err - } + // VPP API handler + plugin.l4Handler = vppcalls.NewL4VppHandler(plugin.vppChan, plugin.log, plugin.stopwatch) return nil } @@ -111,18 +111,15 @@ func (plugin *AppNsConfigurator) ConfigureL4FeatureFlag(features *l4.L4Features) return err } return plugin.resolveCachedNamespaces() - } else { - return plugin.DeleteL4FeatureFlag() } - - return nil + return plugin.DeleteL4FeatureFlag() } // configureL4FeatureFlag process the NB Features config and propagates it to bin api calls func (plugin *AppNsConfigurator) configureL4FeatureFlag() error { plugin.log.Info("Configuring L4 features") - if err := vppcalls.EnableL4Features(plugin.vppChan); err != nil { + if err := plugin.l4Handler.EnableL4Features(); err != nil { plugin.log.Errorf("Enabling L4 features failed: %v", err) return err } @@ -136,7 +133,7 @@ func (plugin *AppNsConfigurator) configureL4FeatureFlag() error { func (plugin *AppNsConfigurator) DeleteL4FeatureFlag() error { plugin.log.Info("Removing L4 features") - if err := vppcalls.DisableL4Features(plugin.vppChan); err != nil { + if err := plugin.l4Handler.DisableL4Features(); err != nil { plugin.log.Errorf("Disabling L4 features failed: %v", err) return err } @@ -271,7 +268,7 @@ func (plugin *AppNsConfigurator) configureAppNamespace(ns *l4.AppNamespaces_AppN plugin.log.Debugf("Adding App Namespace %v to interface %v", ns.NamespaceId, ifIdx) - appNsIdx, err := vppcalls.AddAppNamespace(ns.Secret, ifIdx, ns.Ipv4FibId, ns.Ipv6FibId, nsID, plugin.vppChan, plugin.stopwatch) + appNsIdx, err := plugin.l4Handler.AddAppNamespace(ns.Secret, ifIdx, ns.Ipv4FibId, ns.Ipv6FibId, nsID) if err != nil { return err } diff --git a/plugins/vpp/l4plugin/nsidx/ns_index.go b/plugins/vpp/l4plugin/nsidx/ns_index.go index d215d0a6fe..ae8472f040 100644 --- a/plugins/vpp/l4plugin/nsidx/ns_index.go +++ b/plugins/vpp/l4plugin/nsidx/ns_index.go @@ -15,7 +15,6 @@ package nsidx import ( - "github.com/ligato/cn-infra/core" "github.com/ligato/vpp-agent/idxvpp" "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/vpp/model/l4" @@ -39,7 +38,7 @@ type AppNsIndex interface { ListNames() (names []string) // WatchNameToIdx allows to subscribe for watching changes in appNsIndex mapping - WatchNameToIdx(subscriber core.PluginName, pluginChannel chan ChangeDto) + WatchNameToIdx(subscriber string, pluginChannel chan ChangeDto) } // AppNsIndexRW is mapping between indexes (used internally in VPP) and AppNamespace indexes. @@ -131,7 +130,7 @@ func (appNs *appNsIndex) ListNames() (names []string) { } // WatchNameToIdx allows to subscribe for watching changes in appNsIndex mapping -func (appNs *appNsIndex) WatchNameToIdx(subscriber core.PluginName, pluginChannel chan ChangeDto) { +func (appNs *appNsIndex) WatchNameToIdx(subscriber string, pluginChannel chan ChangeDto) { ch := make(chan idxvpp.NameToIdxDto) appNs.mapping.Watch(subscriber, nametoidx.ToChan(ch)) go func() { diff --git a/plugins/vpp/l4plugin/vppcalls/api_vppcalls.go b/plugins/vpp/l4plugin/vppcalls/api_vppcalls.go new file mode 100644 index 0000000000..0cc4f2f5ed --- /dev/null +++ b/plugins/vpp/l4plugin/vppcalls/api_vppcalls.go @@ -0,0 +1,59 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vppcalls + +import ( + govppapi "git.fd.io/govpp.git/api" + "github.com/ligato/cn-infra/logging" + "github.com/ligato/cn-infra/logging/measure" +) + +// L4VppAPI provides methods for managing L4 layer configuration +type L4VppAPI interface { + L4VppWrite + L4VppRead +} + +// L4VppWrite provides write methods for L4 +type L4VppWrite interface { + // EnableL4Features sets L4 feature flag on VPP to true + EnableL4Features() error + // DisableL4Features sets L4 feature flag on VPP to false + DisableL4Features() error + // AddAppNamespace calls respective VPP binary api to configure AppNamespace + AddAppNamespace(secret uint64, swIfIdx, ip4FibID, ip6FibID uint32, id []byte) (appNsIdx uint32, err error) +} + +// L4VppRead provides read methods for L4 +type L4VppRead interface { + // DumpL4Config returns L4 configuration + DumpL4Config() ([]*SessionDetails, error) +} + +// L4VppHandler is accessor for l4-related vppcalls methods +type L4VppHandler struct { + stopwatch *measure.Stopwatch + callsChannel govppapi.Channel + log logging.Logger +} + +// NewL4VppHandler creates new instance of L4 vppcalls handler +func NewL4VppHandler(callsChan govppapi.Channel, log logging.Logger, stopwatch *measure.Stopwatch) *L4VppHandler { + return &L4VppHandler{ + callsChannel: callsChan, + stopwatch: stopwatch, + log: log, + } +} diff --git a/plugins/vpp/l4plugin/vppcalls/app_namespace_vppcalls.go b/plugins/vpp/l4plugin/vppcalls/app_namespace_vppcalls.go index e962922ba8..4fed32d4c0 100644 --- a/plugins/vpp/l4plugin/vppcalls/app_namespace_vppcalls.go +++ b/plugins/vpp/l4plugin/vppcalls/app_namespace_vppcalls.go @@ -18,23 +18,13 @@ import ( "fmt" "time" - govppapi "git.fd.io/govpp.git/api" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/vpp-agent/plugins/vpp/binapi/session" ) -// AppNsMessages is list of used VPP messages for compatibility check -var AppNsMessages = []govppapi.Message{ - &session.AppNamespaceAddDel{}, - &session.AppNamespaceAddDelReply{}, - &session.SessionEnableDisable{}, - &session.SessionEnableDisableReply{}, -} - -// AddAppNamespace calls respective VPP binary api to configure AppNamespace -func AddAppNamespace(secret uint64, swIfIdx, ip4FibID, ip6FibID uint32, id []byte, vppChan govppapi.Channel, stopwatch *measure.Stopwatch) (appNsIdx uint32, err error) { +// AddAppNamespace adds app namespace. +func (handler *L4VppHandler) AddAppNamespace(secret uint64, swIfIdx, ip4FibID, ip6FibID uint32, id []byte) (appNsIdx uint32, err error) { defer func(t time.Time) { - stopwatch.TimeLog(session.AppNamespaceAddDel{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(session.AppNamespaceAddDel{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &session.AppNamespaceAddDel{ @@ -45,12 +35,11 @@ func AddAppNamespace(secret uint64, swIfIdx, ip4FibID, ip6FibID uint32, id []byt NamespaceID: id, NamespaceIDLen: uint8(len(id)), } - reply := &session.AppNamespaceAddDelReply{} - if err = vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err = handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return 0, err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return 0, fmt.Errorf("%s returned %v", reply.GetMessageName(), reply.Retval) } diff --git a/plugins/vpp/l4plugin/vppcalls/dump_vppcalls.go b/plugins/vpp/l4plugin/vppcalls/dump_vppcalls.go new file mode 100644 index 0000000000..761715ed17 --- /dev/null +++ b/plugins/vpp/l4plugin/vppcalls/dump_vppcalls.go @@ -0,0 +1,95 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vppcalls + +import ( + "bytes" + "fmt" + "net" + "time" + + "github.com/ligato/vpp-agent/plugins/vpp/binapi/session" +) + +// SessionDetails represents session details. +type SessionDetails struct { + TransportProto uint8 + LocalIP string + LocalPort uint16 + RemoteIP string + RemotePort uint16 + ActionIndex uint32 + AppnsIndex uint32 + Scope uint8 + Tag string +} + +// DumpL4Config implements L4VppRead. +func (handler *L4VppHandler) DumpL4Config() ([]*SessionDetails, error) { + // ArpDump time measurement + defer func(t time.Time) { + handler.stopwatch.TimeLog(session.SessionRulesDump{}).LogTimeEntry(time.Since(t)) + }(time.Now()) + + var appNsDetails []*SessionDetails + + // Dump ARPs. + reqCtx := handler.callsChannel.SendMultiRequest(&session.SessionRulesDump{}) + + for { + sessions := &session.SessionRulesDetails{} + stop, err := reqCtx.ReceiveReply(sessions) + if stop { + break + } + if err != nil { + handler.log.Error(err) + return nil, err + } + + // IP addresses + var localIP, remoteIP string + if uintToBool(sessions.IsIP4) { + localIP = fmt.Sprintf("%s", net.IP(sessions.LclIP[:4]).To4().String()) + remoteIP = fmt.Sprintf("%s", net.IP(sessions.RmtIP[:4]).To4().String()) + } else { + localIP = fmt.Sprintf("%s", net.IP(sessions.LclIP).To16().String()) + remoteIP = fmt.Sprintf("%s", net.IP(sessions.RmtIP).To16().String()) + } + + l4Session := &SessionDetails{ + TransportProto: sessions.TransportProto, + LocalIP: localIP, + LocalPort: sessions.LclPort, + RemoteIP: remoteIP, + RemotePort: sessions.RmtPort, + ActionIndex: sessions.ActionIndex, + AppnsIndex: sessions.AppnsIndex, + Scope: sessions.Scope, + Tag: string(bytes.SplitN(sessions.Tag, []byte{0x00}, 2)[0]), + } + + appNsDetails = append(appNsDetails, l4Session) + } + + return appNsDetails, nil +} + +func uintToBool(value uint8) bool { + if value == 0 { + return false + } + return true +} diff --git a/plugins/vpp/l4plugin/vppcalls/features_vppcalls.go b/plugins/vpp/l4plugin/vppcalls/features_vppcalls.go index ae486f9ed6..e81eac167c 100644 --- a/plugins/vpp/l4plugin/vppcalls/features_vppcalls.go +++ b/plugins/vpp/l4plugin/vppcalls/features_vppcalls.go @@ -17,38 +17,35 @@ package vppcalls import ( "fmt" - govppapi "git.fd.io/govpp.git/api" "github.com/ligato/vpp-agent/plugins/vpp/binapi/session" ) -// EnableL4Features sets L4 feature flag on VPP to true -func EnableL4Features(vppChan govppapi.Channel) error { +// EnableL4Features enables L4 features. +func (handler *L4VppHandler) EnableL4Features() error { req := &session.SessionEnableDisable{ IsEnable: 1, } - reply := &session.SessionEnableDisableReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %v", reply.GetMessageName(), reply.Retval) } return nil } -// DisableL4Features sets L4 feature flag on VPP to false -func DisableL4Features(vppChan govppapi.Channel) error { +// DisableL4Features disables L4 features. +func (handler *L4VppHandler) DisableL4Features() error { req := &session.SessionEnableDisable{ IsEnable: 0, } - reply := &session.SessionEnableDisableReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err - } - if reply.Retval != 0 { + } else if reply.Retval != 0 { return fmt.Errorf("%s returned %v", reply.GetMessageName(), reply.Retval) } diff --git a/plugins/vpp/model/acl/acl.pb.go b/plugins/vpp/model/acl/acl.pb.go index 3708d126da..9b107b183d 100644 --- a/plugins/vpp/model/acl/acl.pb.go +++ b/plugins/vpp/model/acl/acl.pb.go @@ -509,18 +509,18 @@ func (m *AccessLists_Acl_Interfaces) GetIngress() []string { func init() { proto.RegisterType((*AccessLists)(nil), "acl.AccessLists") - proto.RegisterType((*AccessLists_Acl)(nil), "acl.AccessLists.Acl") - proto.RegisterType((*AccessLists_Acl_Rule)(nil), "acl.AccessLists.Acl.Rule") - proto.RegisterType((*AccessLists_Acl_Rule_Match)(nil), "acl.AccessLists.Acl.Rule.Match") - proto.RegisterType((*AccessLists_Acl_Rule_Match_IpRule)(nil), "acl.AccessLists.Acl.Rule.Match.IpRule") - proto.RegisterType((*AccessLists_Acl_Rule_Match_IpRule_Ip)(nil), "acl.AccessLists.Acl.Rule.Match.IpRule.Ip") - proto.RegisterType((*AccessLists_Acl_Rule_Match_IpRule_Icmp)(nil), "acl.AccessLists.Acl.Rule.Match.IpRule.Icmp") - proto.RegisterType((*AccessLists_Acl_Rule_Match_IpRule_Icmp_Range)(nil), "acl.AccessLists.Acl.Rule.Match.IpRule.Icmp.Range") - proto.RegisterType((*AccessLists_Acl_Rule_Match_IpRule_PortRange)(nil), "acl.AccessLists.Acl.Rule.Match.IpRule.PortRange") - proto.RegisterType((*AccessLists_Acl_Rule_Match_IpRule_Tcp)(nil), "acl.AccessLists.Acl.Rule.Match.IpRule.Tcp") - proto.RegisterType((*AccessLists_Acl_Rule_Match_IpRule_Udp)(nil), "acl.AccessLists.Acl.Rule.Match.IpRule.Udp") - proto.RegisterType((*AccessLists_Acl_Rule_Match_MacIpRule)(nil), "acl.AccessLists.Acl.Rule.Match.MacIpRule") - proto.RegisterType((*AccessLists_Acl_Interfaces)(nil), "acl.AccessLists.Acl.Interfaces") + proto.RegisterType((*AccessLists_Acl)(nil), "acl.AccessLists.ACL") + proto.RegisterType((*AccessLists_Acl_Rule)(nil), "acl.AccessLists.ACL.Rule") + proto.RegisterType((*AccessLists_Acl_Rule_Match)(nil), "acl.AccessLists.ACL.Rule.Match") + proto.RegisterType((*AccessLists_Acl_Rule_Match_IpRule)(nil), "acl.AccessLists.ACL.Rule.Match.IpRule") + proto.RegisterType((*AccessLists_Acl_Rule_Match_IpRule_Ip)(nil), "acl.AccessLists.ACL.Rule.Match.IpRule.Ip") + proto.RegisterType((*AccessLists_Acl_Rule_Match_IpRule_Icmp)(nil), "acl.AccessLists.ACL.Rule.Match.IpRule.Icmp") + proto.RegisterType((*AccessLists_Acl_Rule_Match_IpRule_Icmp_Range)(nil), "acl.AccessLists.ACL.Rule.Match.IpRule.Icmp.Range") + proto.RegisterType((*AccessLists_Acl_Rule_Match_IpRule_PortRange)(nil), "acl.AccessLists.ACL.Rule.Match.IpRule.PortRange") + proto.RegisterType((*AccessLists_Acl_Rule_Match_IpRule_Tcp)(nil), "acl.AccessLists.ACL.Rule.Match.IpRule.Tcp") + proto.RegisterType((*AccessLists_Acl_Rule_Match_IpRule_Udp)(nil), "acl.AccessLists.ACL.Rule.Match.IpRule.Udp") + proto.RegisterType((*AccessLists_Acl_Rule_Match_MacIpRule)(nil), "acl.AccessLists.ACL.Rule.Match.MacIpRule") + proto.RegisterType((*AccessLists_Acl_Interfaces)(nil), "acl.AccessLists.ACL.Interfaces") proto.RegisterEnum("acl.AclAction", AclAction_name, AclAction_value) } diff --git a/plugins/vpp/model/acl/keys_agent_acl.go b/plugins/vpp/model/acl/keys_agent_acl.go index f15233058c..684d94d33c 100644 --- a/plugins/vpp/model/acl/keys_agent_acl.go +++ b/plugins/vpp/model/acl/keys_agent_acl.go @@ -14,15 +14,13 @@ package acl -const aclPrefix = "vpp/config/v1/acl/" - -// KeyPrefix returns the prefix used in ETCD to store vpp ACLs config. -func KeyPrefix() string { - return aclPrefix -} +const ( + // Prefix is ACL key prefix + Prefix = "vpp/config/v1/acl/" +) // Key returns the prefix used in ETCD to store vpp ACL config // of a particular ACL in selected vpp instance. func Key(aclName string) string { - return aclPrefix + aclName + return Prefix + aclName } diff --git a/plugins/vpp/model/bfd/keys_agent.go b/plugins/vpp/model/bfd/keys_agent.go index 3b06442f63..2b5afcf993 100644 --- a/plugins/vpp/model/bfd/keys_agent.go +++ b/plugins/vpp/model/bfd/keys_agent.go @@ -14,44 +14,29 @@ package bfd -// BfdSessionPrefix bfd-session/ -const BfdSessionPrefix = "vpp/config/v1/bfd/session/" - -// BfdAuthKeysPrefix bfd-key/ -const BfdAuthKeysPrefix = "vpp/config/v1/bfd/auth-key/" - -// BfdEchoFunctionPrefix bfd-echo-function/ -const BfdEchoFunctionPrefix = "vpp/config/v1/bfd/echo-function" - -// SessionKeyPrefix returns the prefix used in ETCD to store vpp bfd config. -func SessionKeyPrefix() string { - return BfdSessionPrefix -} - -// AuthKeysKeyPrefix returns the prefix used in ETCD to store vpp bfd config. -func AuthKeysKeyPrefix() string { - return BfdAuthKeysPrefix -} - -// EchoFunctionKeyPrefix returns the prefix used in ETCD to store vpp bfd config. -func EchoFunctionKeyPrefix() string { - return BfdEchoFunctionPrefix -} +const ( + // SessionPrefix bfd-session/ + SessionPrefix = "vpp/config/v1/bfd/session/" + // AuthKeysPrefix bfd-key/ + AuthKeysPrefix = "vpp/config/v1/bfd/auth-key/" + // EchoFunctionPrefix bfd-echo-function/ + EchoFunctionPrefix = "vpp/config/v1/bfd/echo-function/" +) // SessionKey returns the prefix used in ETCD to store vpp bfd config // of a particular bfd session in selected vpp instance. func SessionKey(bfdSessionIfaceLabel string) string { - return BfdSessionPrefix + bfdSessionIfaceLabel + return SessionPrefix + bfdSessionIfaceLabel } // AuthKeysKey returns the prefix used in ETCD to store vpp bfd config // of a particular bfd key in selected vpp instance. func AuthKeysKey(bfdKeyIDLabel string) string { - return BfdAuthKeysPrefix + bfdKeyIDLabel + return AuthKeysPrefix + bfdKeyIDLabel } // EchoFunctionKey returns the prefix used in ETCD to store vpp bfd config // of a particular bfd echo function in selected vpp instance. func EchoFunctionKey(bfdEchoIfaceLabel string) string { - return BfdEchoFunctionPrefix + bfdEchoIfaceLabel + return EchoFunctionPrefix + bfdEchoIfaceLabel } diff --git a/plugins/vpp/model/interfaces/interfaces.pb.go b/plugins/vpp/model/interfaces/interfaces.pb.go index d6f77c46ec..39939cf978 100644 --- a/plugins/vpp/model/interfaces/interfaces.pb.go +++ b/plugins/vpp/model/interfaces/interfaces.pb.go @@ -873,7 +873,7 @@ func (m *InterfacesState_Interface_Statistics) GetOutErrorPackets() uint64 { } type InterfaceNotification struct { - Type InterfaceNotification_NotifType `protobuf:"varint,1,opt,name=Type,json=type,proto3,enum=interfaces.InterfaceNotification_NotifType" json:"Type,omitempty"` + Type InterfaceNotification_NotifType `protobuf:"varint,1,opt,name=Type,proto3,enum=interfaces.InterfaceNotification_NotifType" json:"Type,omitempty"` State *InterfacesState_Interface `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"` } @@ -1000,7 +1000,7 @@ func init() { func init() { proto.RegisterFile("interfaces.proto", fileDescriptorInterfaces) } var fileDescriptorInterfaces = []byte{ - // 1648 bytes of a gzipped FileDescriptorProto + // 1650 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0x4d, 0x93, 0xdb, 0xb6, 0x19, 0x36, 0xf5, 0xad, 0x57, 0x5f, 0x34, 0x6c, 0xa7, 0xb4, 0xd2, 0x8e, 0x95, 0x4d, 0xe2, 0x6e, 0xdd, 0x74, 0xed, 0xd9, 0x66, 0x7c, 0x49, 0x67, 0x5a, 0x45, 0xe2, 0x36, 0xaa, 0xb5, 0x92, 0x0a, @@ -1085,23 +1085,24 @@ var fileDescriptorInterfaces = []byte{ 0x79, 0xf1, 0x70, 0x31, 0x1b, 0xdb, 0x5f, 0x9b, 0xf7, 0xa4, 0xe8, 0xab, 0xfe, 0xf8, 0x4c, 0xcb, 0xcf, 0x16, 0xe3, 0xb1, 0x59, 0x38, 0xfa, 0xa7, 0x01, 0x8f, 0xb2, 0x74, 0x9a, 0x84, 0x82, 0x2d, 0x99, 0xe7, 0xaa, 0xa7, 0xfc, 0x6f, 0xa1, 0x24, 0x0b, 0x42, 0xf2, 0x76, 0xb8, 0xfd, 0xdd, 0x9a, - 0x17, 0x9c, 0xa8, 0x46, 0xae, 0x86, 0x7c, 0x01, 0x65, 0x99, 0x92, 0xba, 0x1e, 0x1d, 0x5c, 0xfb, - 0xb4, 0x46, 0x5e, 0x6a, 0x99, 0x9f, 0x9c, 0x63, 0x32, 0x19, 0xf3, 0x1e, 0x02, 0xa8, 0x2c, 0x66, - 0x6a, 0xf2, 0x86, 0xbc, 0xed, 0x06, 0xd3, 0xc5, 0xc4, 0xb1, 0xf1, 0xdc, 0x2c, 0x1c, 0xfd, 0xab, - 0x90, 0xab, 0xc2, 0x6a, 0x51, 0xf9, 0x7b, 0x54, 0x61, 0x2d, 0xf8, 0x91, 0x2a, 0xfc, 0x5f, 0x23, - 0x5f, 0x85, 0x3f, 0x85, 0xf6, 0xfe, 0x61, 0x96, 0xab, 0xc7, 0xad, 0x0c, 0x55, 0x35, 0x77, 0x02, - 0xa0, 0xb7, 0xdc, 0x77, 0x85, 0x6b, 0x15, 0x54, 0xdf, 0xcf, 0x0f, 0xea, 0xfb, 0x44, 0x01, 0x43, - 0x57, 0xb8, 0xb8, 0x4e, 0xd3, 0xcf, 0x6e, 0x0c, 0xf5, 0x0c, 0x97, 0x27, 0x53, 0x57, 0x38, 0x22, - 0xd2, 0x5d, 0xaa, 0x63, 0xd0, 0x90, 0x5a, 0xb4, 0x8f, 0xa1, 0xa5, 0x7b, 0xdf, 0x50, 0xce, 0xdd, - 0xcb, 0xec, 0x5a, 0x50, 0xe0, 0xb9, 0xc6, 0xde, 0x2e, 0x96, 0xc5, 0xb7, 0x8b, 0xe5, 0xb3, 0xbf, - 0x19, 0xd0, 0xba, 0x71, 0x41, 0xa0, 0x47, 0x70, 0x7f, 0x3e, 0x3d, 0x73, 0xde, 0xf4, 0xb1, 0x4d, - 0xc6, 0xd3, 0xe9, 0xec, 0xcb, 0xfe, 0xe0, 0x95, 0x79, 0x0f, 0x3d, 0x80, 0x4e, 0xfa, 0xf0, 0x20, - 0x83, 0xf9, 0x79, 0x7f, 0x30, 0x34, 0x0d, 0xf4, 0x10, 0xcc, 0x73, 0xfb, 0x7c, 0x8a, 0xbf, 0x21, - 0x23, 0xb9, 0x49, 0x67, 0xfd, 0x81, 0x6d, 0x16, 0xd0, 0x7d, 0x68, 0x39, 0xfd, 0x59, 0x0e, 0x2a, - 0xa2, 0x9f, 0xc0, 0x83, 0xfe, 0x19, 0x99, 0xf5, 0x07, 0xaf, 0x6c, 0x27, 0x17, 0x28, 0x21, 0x13, - 0x9a, 0xaf, 0xbf, 0x1e, 0xf7, 0x27, 0xc4, 0x59, 0x4c, 0x26, 0xf6, 0xd8, 0x2c, 0x3f, 0x9b, 0x01, - 0xec, 0xdf, 0xae, 0x37, 0x53, 0xa3, 0x01, 0xd5, 0xd9, 0x74, 0x3c, 0x1e, 0x4d, 0x7e, 0x6f, 0x1a, - 0xa8, 0x05, 0x75, 0x65, 0x84, 0x17, 0x33, 0xc7, 0x2c, 0xc8, 0x54, 0xe9, 0x0f, 0xfb, 0x33, 0x67, - 0xf4, 0x5a, 0xf6, 0xa7, 0x4e, 0xcd, 0x59, 0x7f, 0x31, 0x76, 0xcc, 0xd2, 0x45, 0x45, 0xfd, 0xb9, - 0xfe, 0xf5, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0xe2, 0xa9, 0x5c, 0xb0, 0x70, 0x0f, 0x00, 0x00, + 0x17, 0x9c, 0xa8, 0x86, 0xae, 0x21, 0xf2, 0x17, 0x7d, 0x01, 0x65, 0x99, 0x92, 0xba, 0x1e, 0x1d, + 0x5c, 0xfb, 0xb4, 0x46, 0x5e, 0x6a, 0x99, 0x9f, 0x9c, 0x63, 0x32, 0x19, 0xf3, 0x1e, 0x02, 0xa8, + 0x2c, 0x66, 0x6a, 0xf2, 0x86, 0xbc, 0xed, 0x06, 0xd3, 0xc5, 0xc4, 0xb1, 0xf1, 0xdc, 0x2c, 0x1c, + 0xfd, 0xab, 0x90, 0xab, 0xc2, 0x6a, 0x51, 0xf9, 0x7b, 0x54, 0x61, 0x2d, 0xf8, 0x91, 0x2a, 0xfc, + 0x5f, 0x23, 0x5f, 0x85, 0x3f, 0x85, 0xf6, 0xfe, 0x61, 0x96, 0xab, 0xc7, 0xad, 0x0c, 0x55, 0x35, + 0x77, 0x02, 0xa0, 0xb7, 0xdc, 0x77, 0x85, 0x6b, 0x15, 0x54, 0xdf, 0xcf, 0x0f, 0xea, 0xfb, 0x44, + 0x01, 0x43, 0x57, 0xb8, 0xb8, 0x4e, 0xd3, 0xcf, 0x6e, 0x0c, 0xf5, 0x0c, 0x97, 0x27, 0x53, 0x57, + 0x38, 0x22, 0xd2, 0x5d, 0xaa, 0x63, 0xd0, 0x90, 0x5a, 0xb4, 0x8f, 0xa1, 0xa5, 0x7b, 0xdf, 0x50, + 0xce, 0xdd, 0xcb, 0xec, 0x5a, 0x50, 0xe0, 0xb9, 0xc6, 0xde, 0x2e, 0x96, 0xc5, 0xb7, 0x8b, 0xe5, + 0xb3, 0xbf, 0x19, 0xd0, 0xba, 0x71, 0x41, 0xa0, 0x47, 0x70, 0x7f, 0x3e, 0x3d, 0x73, 0xde, 0xf4, + 0xb1, 0x4d, 0xc6, 0xd3, 0xe9, 0xec, 0xcb, 0xfe, 0xe0, 0x95, 0x79, 0x0f, 0x3d, 0x80, 0x4e, 0xfa, + 0xf0, 0x20, 0x83, 0xf9, 0x79, 0x7f, 0x30, 0x34, 0x0d, 0xf4, 0x10, 0xcc, 0x73, 0xfb, 0x7c, 0x8a, + 0xbf, 0x21, 0x23, 0xb9, 0x49, 0x67, 0xfd, 0x81, 0x6d, 0x16, 0xd0, 0x7d, 0x68, 0x39, 0xfd, 0x59, + 0x0e, 0x2a, 0xa2, 0x9f, 0xc0, 0x83, 0xfe, 0x19, 0x99, 0xf5, 0x07, 0xaf, 0x6c, 0x27, 0x17, 0x28, + 0x21, 0x13, 0x9a, 0xaf, 0xbf, 0x1e, 0xf7, 0x27, 0xc4, 0x59, 0x4c, 0x26, 0xf6, 0xd8, 0x2c, 0x3f, + 0x9b, 0x01, 0xec, 0xdf, 0xae, 0x37, 0x53, 0xa3, 0x01, 0xd5, 0xd9, 0x74, 0x3c, 0x1e, 0x4d, 0x7e, + 0x6f, 0x1a, 0xa8, 0x05, 0x75, 0x65, 0x84, 0x17, 0x33, 0xc7, 0x2c, 0xc8, 0x54, 0xe9, 0x0f, 0xfb, + 0x33, 0x67, 0xf4, 0x5a, 0xf6, 0xa7, 0x4e, 0xcd, 0x59, 0x7f, 0x31, 0x76, 0xcc, 0xd2, 0x45, 0x45, + 0xfd, 0xb9, 0xfe, 0xf5, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0xb1, 0xec, 0x10, 0x72, 0x70, 0x0f, + 0x00, 0x00, } diff --git a/plugins/vpp/model/interfaces/keys_agent_interfaces.go b/plugins/vpp/model/interfaces/keys_agent_interfaces.go index 59d50106ca..a4b54e5c83 100644 --- a/plugins/vpp/model/interfaces/keys_agent_interfaces.go +++ b/plugins/vpp/model/interfaces/keys_agent_interfaces.go @@ -20,19 +20,14 @@ import ( ) const ( - // InterfacePrefix vpp/config/v1/interface/ - InterfacePrefix = "vpp/config/v1/interface/" - // IfStatePrefix vpp/status/v1/interface/ - IfStatePrefix = "vpp/status/v1/interface/" - // IfErrorPrefix vpp/status/v1/interface/error - IfErrorPrefix = "vpp/status/v1/interface/error/" + // Prefix is interface prefix + Prefix = "vpp/config/v1/interface/" + // StatePrefix is interface state prefix + StatePrefix = "vpp/status/v1/interface/" + // ErrorPrefix is interface error prefix + ErrorPrefix = "vpp/status/v1/interface/error/" ) -// InterfaceKeyPrefix returns the prefix used in ETCD to store vpp interfaces config. -func InterfaceKeyPrefix() string { - return InterfacePrefix -} - // ParseNameFromKey returns suffix of the key. func ParseNameFromKey(key string) (name string, err error) { lastSlashPos := strings.LastIndex(key, "/") @@ -46,26 +41,16 @@ func ParseNameFromKey(key string) (name string, err error) { // InterfaceKey returns the prefix used in ETCD to store the vpp interface config // of a particular interface in selected vpp instance. func InterfaceKey(ifaceLabel string) string { - return InterfacePrefix + ifaceLabel -} - -// InterfaceErrorPrefix returns the prefix used in ETCD to store the interface errors. -func InterfaceErrorPrefix() string { - return IfErrorPrefix + return Prefix + ifaceLabel } // InterfaceErrorKey returns the key used in ETCD to store the interface errors. func InterfaceErrorKey(ifaceLabel string) string { - return IfErrorPrefix + ifaceLabel -} - -// InterfaceStateKeyPrefix returns the prefix used in ETCD to store the vpp interfaces state data. -func InterfaceStateKeyPrefix() string { - return IfStatePrefix + return ErrorPrefix + ifaceLabel } // InterfaceStateKey returns the prefix used in ETCD to store the vpp interface state data // of particular interface in selected vpp instance. func InterfaceStateKey(ifaceLabel string) string { - return IfStatePrefix + ifaceLabel + return StatePrefix + ifaceLabel } diff --git a/plugins/vpp/model/l2/keys_agent_l2.go b/plugins/vpp/model/l2/keys_agent_l2.go index 80d0aa7ebc..a353686292 100644 --- a/plugins/vpp/model/l2/keys_agent_l2.go +++ b/plugins/vpp/model/l2/keys_agent_l2.go @@ -21,45 +21,30 @@ import ( // Prefixes const ( - // BdPrefix is the relative key prefix for bridge domains. + // bdPrefix is the relative key prefix for bridge domains. BdPrefix = "vpp/config/v1/bd/" - // BdStatePrefix is the relative key prefix for bridge domain state. + // bdStatePrefix is the relative key prefix for bridge domain state. BdStatePrefix = "vpp/status/v1/bd/" - // BdErrPrefix is the relative key prefix for the bridge domain error. + // bdErrPrefix is the relative key prefix for the bridge domain error. BdErrPrefix = "vpp/status/v1/bd/error/" - // FIBPrefix is the relative key prefix for FIB table entries. - FIBPrefix = "vpp/config/v1/bd/{bd}/fib/" - // XconnectPrefix is the relative key prefix for xconnects. - XconnectPrefix = "vpp/config/v1/xconnect/" + // fibPrefix is the relative key prefix for FIB table entries. + FibPrefix = "vpp/config/v1/bd/{bd}/fib/" + // xConnectPrefix is the relative key prefix for xconnects. + XConnectPrefix = "vpp/config/v1/xconnect/" ) -// BridgeDomainKeyPrefix returns the prefix used in ETCD to store vpp bridge domain config. -func BridgeDomainKeyPrefix() string { - return BdPrefix -} - // BridgeDomainKey returns the prefix used in ETCD to store vpp bridge domain config // of a particular bridge domain in selected vpp instance. func BridgeDomainKey(bdName string) string { return BdPrefix + bdName } -// BridgeDomainStateKeyPrefix returns the prefix used in ETCD to store vpp bridge domain state data. -func BridgeDomainStateKeyPrefix() string { - return BdStatePrefix -} - // BridgeDomainStateKey returns the prefix used in ETCD to store vpp bridge domain state data // of a particular bridge domain in selected vpp instance. func BridgeDomainStateKey(ifaceLabel string) string { return BdStatePrefix + ifaceLabel } -// BridgeDomainErrorPrefix returns the prefix used in ETCD to store bridge domain errors. -func BridgeDomainErrorPrefix() string { - return BdErrPrefix -} - // BridgeDomainErrorKey returns the key used in ETCD to store bridge domain errors. func BridgeDomainErrorKey(bdLabel string) string { return BdErrPrefix + bdLabel @@ -75,21 +60,16 @@ func ParseBDNameFromKey(key string) (name string, err error) { return key, fmt.Errorf("wrong format of the key %s", key) } -// FibKeyPrefix returns the prefix used in ETCD to store vpp fib table entry config. -func FibKeyPrefix() string { - return FIBPrefix -} - // FibKey returns the prefix used in ETCD to store vpp fib table entry config // of a particular fib in selected vpp instance. func FibKey(bdLabel string, fibMac string) string { - return strings.Replace(FIBPrefix, "{bd}", bdLabel, 1) + fibMac + return strings.Replace(FibPrefix, "{bd}", bdLabel, 1) + fibMac } // ParseFibKey parses bridge domain label and FIB MAC address from a FIB key. func ParseFibKey(key string) (isFibKey bool, bdName string, fibMac string) { - if strings.HasPrefix(key, BridgeDomainKeyPrefix()) { - bdSuffix := strings.TrimPrefix(key, BridgeDomainKeyPrefix()) + if strings.HasPrefix(key, BdPrefix) { + bdSuffix := strings.TrimPrefix(key, BdPrefix) fibComps := strings.Split(bdSuffix, "/") if len(fibComps) == 3 && fibComps[1] == "fib" { return true, fibComps[0], fibComps[2] @@ -98,13 +78,8 @@ func ParseFibKey(key string) (isFibKey bool, bdName string, fibMac string) { return false, "", "" } -// XConnectKeyPrefix returns the prefix used in ETCD to store vpp xConnect pair config. -func XConnectKeyPrefix() string { - return XconnectPrefix -} - // XConnectKey returns the prefix used in ETCD to store vpp xConnect pair config // of particular xConnect pair in selected vpp instance. func XConnectKey(rxIface string) string { - return XconnectPrefix + rxIface + return XConnectPrefix + rxIface } diff --git a/plugins/vpp/model/l3/keys_agent_l3.go b/plugins/vpp/model/l3/keys_agent_l3.go index 86f933a27b..3cd8f8ae8e 100644 --- a/plugins/vpp/model/l3/keys_agent_l3.go +++ b/plugins/vpp/model/l3/keys_agent_l3.go @@ -39,33 +39,10 @@ const ( ProxyARPRangeKey = ProxyARPRangePrefix + "{label}" // ProxyARPInterfacePrefix is the relative key prefix for proxy ARP-enabled interfaces. ProxyARPInterfaceKey = ProxyARPInterfacePrefix + "{label}" + // IPScanNeighPrefix it the relative key prefix for IP scan neighbor feature + IPScanNeighPrefix = "vpp/config/v1/ipneigh/" ) -// VrfKeyPrefix returns the prefix used in ETCD to store VRFs for vpp instance. -func VrfKeyPrefix() string { - return VrfPrefix -} - -// RouteKeyPrefix returns the prefix used in ETCD to store vpp routes for vpp instance. -func RouteKeyPrefix() string { - return RoutesPrefix -} - -// ArpKeyPrefix returns the prefix used in ETCD to store vpp APR tables for vpp instance. -func ArpKeyPrefix() string { - return ArpPrefix -} - -// ProxyArpPrefix returns the prefix used in ETCD to store proxy APR ranges for vpp instance. -func ProxyArpRangePrefix() string { - return ProxyARPRangePrefix -} - -// ProxyArpPrefix returns the prefix used in ETCD to store proxy APR interfaces for vpp instance. -func ProxyArpInterfacePrefix() string { - return ProxyARPInterfacePrefix -} - // RouteKey returns the key used in ETCD to store vpp route for vpp instance. func RouteKey(vrf uint32, dstAddr string, nextHopAddr string) string { _, dstNet, _ := net.ParseCIDR(dstAddr) @@ -81,13 +58,17 @@ func RouteKey(vrf uint32, dstAddr string, nextHopAddr string) string { // ParseRouteKey parses VRF label and route address from a route key. func ParseRouteKey(key string) (isRouteKey bool, vrfIndex string, dstNetAddr string, dstNetMask int, nextHopAddr string) { - if strings.HasPrefix(key, VrfKeyPrefix()) { - vrfSuffix := strings.TrimPrefix(key, VrfKeyPrefix()) + if strings.HasPrefix(key, VrfPrefix) { + vrfSuffix := strings.TrimPrefix(key, VrfPrefix) routeComps := strings.Split(vrfSuffix, "/") if len(routeComps) >= 5 && routeComps[1] == "fib" { if mask, err := strconv.Atoi(routeComps[3]); err == nil { return true, routeComps[0], routeComps[2], mask, routeComps[4] } + } else if len(routeComps) == 4 && routeComps[1] == "fib" { + if mask, err := strconv.Atoi(routeComps[3]); err == nil { + return true, routeComps[0], routeComps[2], mask, "" + } } } return false, "", "", 0, "" diff --git a/plugins/vpp/model/l3/l3.pb.go b/plugins/vpp/model/l3/l3.pb.go index c66e42da8e..057b3c9960 100644 --- a/plugins/vpp/model/l3/l3.pb.go +++ b/plugins/vpp/model/l3/l3.pb.go @@ -13,6 +13,7 @@ It has these top-level messages: ProxyArpRanges ProxyArpInterfaces STNTable + IPScanNeighbor */ package l3 @@ -31,6 +32,59 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package +type StaticRoutes_Route_RouteType int32 + +const ( + StaticRoutes_Route_INTRA_VRF StaticRoutes_Route_RouteType = 0 + StaticRoutes_Route_INTER_VRF StaticRoutes_Route_RouteType = 1 + StaticRoutes_Route_DROP StaticRoutes_Route_RouteType = 2 +) + +var StaticRoutes_Route_RouteType_name = map[int32]string{ + 0: "INTRA_VRF", + 1: "INTER_VRF", + 2: "DROP", +} +var StaticRoutes_Route_RouteType_value = map[string]int32{ + "INTRA_VRF": 0, + "INTER_VRF": 1, + "DROP": 2, +} + +func (x StaticRoutes_Route_RouteType) String() string { + return proto.EnumName(StaticRoutes_Route_RouteType_name, int32(x)) +} +func (StaticRoutes_Route_RouteType) EnumDescriptor() ([]byte, []int) { + return fileDescriptorL3, []int{0, 0, 0} +} + +type IPScanNeighbor_Mode int32 + +const ( + IPScanNeighbor_DISABLED IPScanNeighbor_Mode = 0 + IPScanNeighbor_IPv4 IPScanNeighbor_Mode = 1 + IPScanNeighbor_IPv6 IPScanNeighbor_Mode = 2 + IPScanNeighbor_BOTH IPScanNeighbor_Mode = 3 +) + +var IPScanNeighbor_Mode_name = map[int32]string{ + 0: "DISABLED", + 1: "IPv4", + 2: "IPv6", + 3: "BOTH", +} +var IPScanNeighbor_Mode_value = map[string]int32{ + "DISABLED": 0, + "IPv4": 1, + "IPv6": 2, + "BOTH": 3, +} + +func (x IPScanNeighbor_Mode) String() string { + return proto.EnumName(IPScanNeighbor_Mode_name, int32(x)) +} +func (IPScanNeighbor_Mode) EnumDescriptor() ([]byte, []int) { return fileDescriptorL3, []int{5, 0} } + // Static routes type StaticRoutes struct { Routes []*StaticRoutes_Route `protobuf:"bytes,1,rep,name=routes" json:"routes,omitempty"` @@ -49,13 +103,16 @@ func (m *StaticRoutes) GetRoutes() []*StaticRoutes_Route { } type StaticRoutes_Route struct { - VrfId uint32 `protobuf:"varint,1,opt,name=vrf_id,json=vrfId,proto3" json:"vrf_id,omitempty"` - Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` - DstIpAddr string `protobuf:"bytes,3,opt,name=dst_ip_addr,json=dstIpAddr,proto3" json:"dst_ip_addr,omitempty"` - NextHopAddr string `protobuf:"bytes,4,opt,name=next_hop_addr,json=nextHopAddr,proto3" json:"next_hop_addr,omitempty"` - OutgoingInterface string `protobuf:"bytes,5,opt,name=outgoing_interface,json=outgoingInterface,proto3" json:"outgoing_interface,omitempty"` - Weight uint32 `protobuf:"varint,6,opt,name=weight,proto3" json:"weight,omitempty"` - Preference uint32 `protobuf:"varint,7,opt,name=preference,proto3" json:"preference,omitempty"` + Type StaticRoutes_Route_RouteType `protobuf:"varint,10,opt,name=type,proto3,enum=l3.StaticRoutes_Route_RouteType" json:"type,omitempty"` + VrfId uint32 `protobuf:"varint,1,opt,name=vrf_id,json=vrfId,proto3" json:"vrf_id,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + DstIpAddr string `protobuf:"bytes,3,opt,name=dst_ip_addr,json=dstIpAddr,proto3" json:"dst_ip_addr,omitempty"` + NextHopAddr string `protobuf:"bytes,4,opt,name=next_hop_addr,json=nextHopAddr,proto3" json:"next_hop_addr,omitempty"` + OutgoingInterface string `protobuf:"bytes,5,opt,name=outgoing_interface,json=outgoingInterface,proto3" json:"outgoing_interface,omitempty"` + Weight uint32 `protobuf:"varint,6,opt,name=weight,proto3" json:"weight,omitempty"` + Preference uint32 `protobuf:"varint,7,opt,name=preference,proto3" json:"preference,omitempty"` + // (a poor man's primary and backup) + ViaVrfId uint32 `protobuf:"varint,8,opt,name=via_vrf_id,json=viaVrfId,proto3" json:"via_vrf_id,omitempty"` } func (m *StaticRoutes_Route) Reset() { *m = StaticRoutes_Route{} } @@ -63,6 +120,13 @@ func (m *StaticRoutes_Route) String() string { return proto.CompactTe func (*StaticRoutes_Route) ProtoMessage() {} func (*StaticRoutes_Route) Descriptor() ([]byte, []int) { return fileDescriptorL3, []int{0, 0} } +func (m *StaticRoutes_Route) GetType() StaticRoutes_Route_RouteType { + if m != nil { + return m.Type + } + return StaticRoutes_Route_INTRA_VRF +} + func (m *StaticRoutes_Route) GetVrfId() uint32 { if m != nil { return m.VrfId @@ -112,6 +176,13 @@ func (m *StaticRoutes_Route) GetPreference() uint32 { return 0 } +func (m *StaticRoutes_Route) GetViaVrfId() uint32 { + if m != nil { + return m.ViaVrfId + } + return 0 +} + // IP ARP entries type ArpTable struct { ArpEntries []*ArpTable_ArpEntry `protobuf:"bytes,1,rep,name=arp_entries,json=arpEntries" json:"arp_entries,omitempty"` @@ -342,6 +413,63 @@ func (m *STNTable_STNTableEntry) GetInterface() string { return "" } +// Enables/disables IP neighbor scanning +type IPScanNeighbor struct { + Mode IPScanNeighbor_Mode `protobuf:"varint,1,opt,name=mode,proto3,enum=l3.IPScanNeighbor_Mode" json:"mode,omitempty"` + ScanInterval uint32 `protobuf:"varint,2,opt,name=scan_interval,json=scanInterval,proto3" json:"scan_interval,omitempty"` + MaxProcTime uint32 `protobuf:"varint,3,opt,name=max_proc_time,json=maxProcTime,proto3" json:"max_proc_time,omitempty"` + MaxUpdate uint32 `protobuf:"varint,4,opt,name=max_update,json=maxUpdate,proto3" json:"max_update,omitempty"` + ScanIntDelay uint32 `protobuf:"varint,5,opt,name=scan_int_delay,json=scanIntDelay,proto3" json:"scan_int_delay,omitempty"` + StaleThreshold uint32 `protobuf:"varint,6,opt,name=stale_threshold,json=staleThreshold,proto3" json:"stale_threshold,omitempty"` +} + +func (m *IPScanNeighbor) Reset() { *m = IPScanNeighbor{} } +func (m *IPScanNeighbor) String() string { return proto.CompactTextString(m) } +func (*IPScanNeighbor) ProtoMessage() {} +func (*IPScanNeighbor) Descriptor() ([]byte, []int) { return fileDescriptorL3, []int{5} } + +func (m *IPScanNeighbor) GetMode() IPScanNeighbor_Mode { + if m != nil { + return m.Mode + } + return IPScanNeighbor_DISABLED +} + +func (m *IPScanNeighbor) GetScanInterval() uint32 { + if m != nil { + return m.ScanInterval + } + return 0 +} + +func (m *IPScanNeighbor) GetMaxProcTime() uint32 { + if m != nil { + return m.MaxProcTime + } + return 0 +} + +func (m *IPScanNeighbor) GetMaxUpdate() uint32 { + if m != nil { + return m.MaxUpdate + } + return 0 +} + +func (m *IPScanNeighbor) GetScanIntDelay() uint32 { + if m != nil { + return m.ScanIntDelay + } + return 0 +} + +func (m *IPScanNeighbor) GetStaleThreshold() uint32 { + if m != nil { + return m.StaleThreshold + } + return 0 +} + func init() { proto.RegisterType((*StaticRoutes)(nil), "l3.StaticRoutes") proto.RegisterType((*StaticRoutes_Route)(nil), "l3.StaticRoutes.Route") @@ -355,46 +483,65 @@ func init() { proto.RegisterType((*ProxyArpInterfaces_InterfaceList_Interface)(nil), "l3.ProxyArpInterfaces.InterfaceList.Interface") proto.RegisterType((*STNTable)(nil), "l3.STNTable") proto.RegisterType((*STNTable_STNTableEntry)(nil), "l3.STNTable.STNTableEntry") + proto.RegisterType((*IPScanNeighbor)(nil), "l3.IPScanNeighbor") + proto.RegisterEnum("l3.StaticRoutes_Route_RouteType", StaticRoutes_Route_RouteType_name, StaticRoutes_Route_RouteType_value) + proto.RegisterEnum("l3.IPScanNeighbor_Mode", IPScanNeighbor_Mode_name, IPScanNeighbor_Mode_value) } func init() { proto.RegisterFile("l3.proto", fileDescriptorL3) } var fileDescriptorL3 = []byte{ - // 569 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0xc1, 0x6e, 0xd3, 0x40, - 0x10, 0xd5, 0xa6, 0x8d, 0x13, 0x8f, 0x9b, 0x22, 0x46, 0x34, 0x18, 0xab, 0x94, 0x60, 0x71, 0xc8, - 0x05, 0x1f, 0x88, 0xc4, 0x81, 0x8a, 0x43, 0x0e, 0x48, 0x44, 0x2a, 0x15, 0x72, 0x7b, 0xb7, 0x9c, - 0x78, 0x93, 0xac, 0x64, 0xec, 0xd5, 0xee, 0xb6, 0x34, 0x57, 0xfe, 0x01, 0x0e, 0x7c, 0x03, 0xff, - 0xc1, 0xc7, 0xc0, 0x27, 0x70, 0x40, 0xde, 0x5d, 0x3b, 0x4e, 0x24, 0x50, 0x4f, 0x7e, 0x33, 0xf3, - 0x76, 0xbc, 0xef, 0xe5, 0xc5, 0xd0, 0xcf, 0x27, 0x11, 0x17, 0xa5, 0x2a, 0xb1, 0x93, 0x4f, 0xc2, - 0x1f, 0x1d, 0x38, 0xba, 0x52, 0xa9, 0x62, 0x8b, 0xb8, 0xbc, 0x51, 0x54, 0x62, 0x04, 0x8e, 0xd0, - 0xc8, 0x27, 0xa3, 0x83, 0xb1, 0xf7, 0x6a, 0x18, 0xe5, 0x93, 0xa8, 0xcd, 0x88, 0xf4, 0x23, 0xb6, - 0xac, 0xe0, 0x17, 0x81, 0xae, 0xee, 0xe0, 0x09, 0x38, 0xb7, 0x62, 0x99, 0xb0, 0xcc, 0x27, 0x23, - 0x32, 0x1e, 0xc4, 0xdd, 0x5b, 0xb1, 0x9c, 0x65, 0x38, 0x02, 0x2f, 0xa3, 0x72, 0x21, 0x18, 0x57, - 0xac, 0x2c, 0xfc, 0xce, 0x88, 0x8c, 0xdd, 0xb8, 0xdd, 0xc2, 0x33, 0xf0, 0x32, 0xa9, 0x12, 0xc6, - 0x93, 0x34, 0xcb, 0x84, 0x7f, 0xa0, 0x19, 0x6e, 0x26, 0xd5, 0x8c, 0x4f, 0xb3, 0x4c, 0x60, 0x08, - 0x83, 0x82, 0xde, 0xa9, 0x64, 0x5d, 0x5a, 0xc6, 0xa1, 0xd9, 0x51, 0x35, 0xdf, 0x97, 0x86, 0xf3, - 0x12, 0xb0, 0xbc, 0x51, 0xab, 0x92, 0x15, 0xab, 0x84, 0x15, 0x8a, 0x8a, 0x65, 0xba, 0xa0, 0x7e, - 0x57, 0x13, 0x1f, 0xd6, 0x93, 0x59, 0x3d, 0xc0, 0x21, 0x38, 0x9f, 0x29, 0x5b, 0xad, 0x95, 0xef, - 0xe8, 0xbb, 0xda, 0x0a, 0xcf, 0x00, 0xb8, 0xa0, 0x4b, 0x2a, 0x68, 0xb1, 0xa0, 0x7e, 0x4f, 0xcf, - 0x5a, 0x9d, 0xf0, 0x27, 0x81, 0xfe, 0x54, 0xf0, 0xeb, 0x74, 0x9e, 0x53, 0x7c, 0x0d, 0x5e, 0x2a, - 0x78, 0x42, 0x0b, 0x25, 0x58, 0xe3, 0xd7, 0x49, 0xe5, 0x57, 0x4d, 0xa9, 0xc0, 0xbb, 0x42, 0x89, - 0x4d, 0x0c, 0xa9, 0x41, 0x8c, 0xca, 0xe0, 0x8b, 0x59, 0xa2, 0x07, 0x78, 0x0a, 0xee, 0xf6, 0xbe, - 0xc4, 0x48, 0x6f, 0x1a, 0xf8, 0x14, 0xc0, 0xda, 0x42, 0xa5, 0xb4, 0xde, 0xb9, 0x4c, 0x4b, 0xa6, - 0x52, 0xe2, 0x73, 0x38, 0xe2, 0xeb, 0x8d, 0x6c, 0x08, 0xc6, 0x3a, 0xaf, 0xea, 0xd5, 0x94, 0x21, - 0x38, 0x52, 0xff, 0x7a, 0xda, 0xb5, 0x7e, 0x6c, 0xab, 0xf0, 0x37, 0x81, 0xe3, 0x8f, 0xa2, 0xbc, - 0xdb, 0x4c, 0x05, 0x8f, 0xd3, 0x62, 0x45, 0x25, 0xbe, 0x05, 0x4f, 0x54, 0x28, 0xc9, 0x99, 0x54, - 0xb5, 0x9e, 0xd3, 0x4a, 0xcf, 0x2e, 0x31, 0xd2, 0x8f, 0x0b, 0x26, 0x55, 0x0c, 0xa2, 0x86, 0x32, - 0xf8, 0x4e, 0xc0, 0x6d, 0x26, 0xf8, 0x08, 0xba, 0x79, 0x3a, 0xa7, 0xb9, 0xd5, 0x64, 0x0a, 0x7c, - 0x03, 0x8e, 0x3e, 0x51, 0x69, 0xa9, 0xb6, 0x87, 0xff, 0xdb, 0x6e, 0x50, 0x6c, 0x4f, 0x04, 0xe7, - 0xd0, 0xd5, 0x0d, 0x7c, 0x02, 0xfd, 0x25, 0x13, 0x3a, 0x31, 0x76, 0x7b, 0x4f, 0xd7, 0x33, 0x8e, - 0x8f, 0xa1, 0x97, 0xa7, 0x66, 0x62, 0xcc, 0x72, 0xaa, 0x72, 0xc6, 0xc3, 0x3f, 0x04, 0xb0, 0x7e, - 0x4f, 0x13, 0x03, 0x89, 0x1f, 0xe0, 0x41, 0x63, 0xf6, 0x8e, 0xec, 0x17, 0xed, 0x8b, 0x6d, 0x0f, - 0x44, 0x0d, 0xd4, 0xf2, 0x8f, 0x59, 0xbb, 0x94, 0xc1, 0x37, 0x02, 0x83, 0x1d, 0xc6, 0x3f, 0x6c, - 0xb8, 0x04, 0x68, 0x4e, 0xd6, 0x56, 0x44, 0xf7, 0x79, 0xe3, 0xb6, 0x8a, 0x5b, 0x1b, 0x82, 0x67, - 0xe0, 0x6e, 0xb3, 0x8d, 0x70, 0x58, 0xa4, 0x9f, 0xea, 0x30, 0x69, 0x1c, 0x7e, 0x25, 0xd0, 0xbf, - 0xba, 0xbe, 0x34, 0xb9, 0x3d, 0x07, 0x4f, 0xaa, 0x62, 0x2f, 0xb7, 0x81, 0xfe, 0x9f, 0x5b, 0x4a, - 0x03, 0x6c, 0x78, 0xa5, 0x2a, 0xea, 0xf0, 0x5e, 0xc0, 0x60, 0x67, 0xb8, 0x17, 0x51, 0xb2, 0x1f, - 0xd1, 0x9d, 0x7c, 0x77, 0xf6, 0xf2, 0x3d, 0x77, 0xf4, 0x97, 0x68, 0xf2, 0x37, 0x00, 0x00, 0xff, - 0xff, 0x3d, 0x02, 0x34, 0xb3, 0x95, 0x04, 0x00, 0x00, + // 826 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x55, 0xcd, 0x8e, 0xe3, 0x44, + 0x10, 0x5e, 0x67, 0x12, 0x8f, 0x5d, 0x1e, 0x67, 0x43, 0x8b, 0x9d, 0x35, 0xd1, 0xb0, 0x04, 0xb3, + 0x12, 0x23, 0x21, 0x7c, 0x98, 0xac, 0xf6, 0xc0, 0x8a, 0x43, 0x56, 0x33, 0x68, 0x2d, 0xcd, 0x66, + 0xa3, 0x4e, 0x98, 0xab, 0xd5, 0xb1, 0x3b, 0x49, 0x4b, 0x8e, 0x6d, 0x75, 0xf7, 0x84, 0xe4, 0xca, + 0x3b, 0xc0, 0x81, 0x27, 0xe0, 0x05, 0x78, 0x06, 0x5e, 0x86, 0x23, 0x47, 0x0e, 0xa8, 0xdb, 0x3f, + 0xf9, 0x11, 0x20, 0x2e, 0x71, 0xd5, 0x57, 0x5f, 0x57, 0x77, 0x55, 0x7f, 0x5d, 0x01, 0x2b, 0x1d, + 0x06, 0x05, 0xcf, 0x65, 0x8e, 0x5a, 0xe9, 0xd0, 0xff, 0xed, 0x0c, 0x2e, 0xa6, 0x92, 0x48, 0x16, + 0xe3, 0xfc, 0x51, 0x52, 0x81, 0x02, 0x30, 0xb9, 0xb6, 0x3c, 0x63, 0x70, 0x76, 0xed, 0xdc, 0x5c, + 0x06, 0xe9, 0x30, 0x38, 0x64, 0x04, 0xfa, 0x83, 0x2b, 0x56, 0xff, 0xcf, 0x16, 0x74, 0x34, 0x82, + 0x5e, 0x41, 0x5b, 0xee, 0x0a, 0xea, 0xc1, 0xc0, 0xb8, 0xee, 0xde, 0x0c, 0xfe, 0x79, 0x5d, 0xf9, + 0x3b, 0xdb, 0x15, 0x14, 0x6b, 0x36, 0x7a, 0x06, 0xe6, 0x86, 0x2f, 0x22, 0x96, 0x78, 0xc6, 0xc0, + 0xb8, 0x76, 0x71, 0x67, 0xc3, 0x17, 0x61, 0x82, 0x06, 0xe0, 0x24, 0x54, 0xc4, 0x9c, 0x15, 0x92, + 0xe5, 0x99, 0xd7, 0x1a, 0x18, 0xd7, 0x36, 0x3e, 0x84, 0xd0, 0x0b, 0x70, 0x12, 0x21, 0x23, 0x56, + 0x44, 0x24, 0x49, 0xb8, 0x77, 0xa6, 0x19, 0x76, 0x22, 0x64, 0x58, 0x8c, 0x92, 0x84, 0x23, 0x1f, + 0xdc, 0x8c, 0x6e, 0x65, 0xb4, 0xca, 0x2b, 0x46, 0xbb, 0xcc, 0xa1, 0xc0, 0x77, 0x79, 0xc9, 0xf9, + 0x1a, 0x50, 0xfe, 0x28, 0x97, 0x39, 0xcb, 0x96, 0x11, 0xcb, 0x24, 0xe5, 0x0b, 0x12, 0x53, 0xaf, + 0xa3, 0x89, 0x1f, 0xd5, 0x91, 0xb0, 0x0e, 0xa0, 0x4b, 0x30, 0x7f, 0xa0, 0x6c, 0xb9, 0x92, 0x9e, + 0xa9, 0xcf, 0x5a, 0x79, 0xe8, 0x05, 0x40, 0xc1, 0xe9, 0x82, 0x72, 0x9a, 0xc5, 0xd4, 0x3b, 0xd7, + 0xb1, 0x03, 0x04, 0x5d, 0x01, 0x6c, 0x18, 0x89, 0xaa, 0x3a, 0x2d, 0x1d, 0xb7, 0x36, 0x8c, 0x3c, + 0xa8, 0x52, 0xfd, 0x21, 0xd8, 0x4d, 0x53, 0x90, 0x0b, 0x76, 0x38, 0x9e, 0xe1, 0x51, 0xf4, 0x80, + 0xbf, 0xeb, 0x3d, 0xa9, 0xdc, 0x3b, 0xac, 0x5d, 0x03, 0x59, 0xd0, 0xbe, 0xc5, 0x1f, 0x26, 0xbd, + 0x96, 0xff, 0xbb, 0x01, 0xd6, 0x88, 0x17, 0x33, 0x32, 0x4f, 0x29, 0x7a, 0x0d, 0x0e, 0xe1, 0x45, + 0x44, 0x33, 0xc9, 0x59, 0x73, 0x71, 0xcf, 0xd4, 0x05, 0xd4, 0x14, 0x65, 0xdc, 0x65, 0x92, 0xef, + 0x30, 0x90, 0xd2, 0x62, 0x54, 0xf4, 0x7f, 0x2c, 0x93, 0xe8, 0x00, 0xba, 0x02, 0x7b, 0xdf, 0x02, + 0xa3, 0xec, 0x66, 0x03, 0xa0, 0x4f, 0x01, 0xaa, 0x4e, 0x53, 0x21, 0xaa, 0xeb, 0xb0, 0x99, 0xee, + 0x22, 0x15, 0x02, 0x7d, 0x0e, 0x17, 0xc5, 0x6a, 0x27, 0x1a, 0x42, 0x79, 0x1b, 0x8e, 0xc2, 0x6a, + 0xca, 0x25, 0x98, 0x42, 0xcb, 0x41, 0x5f, 0x84, 0x85, 0x2b, 0xcf, 0xff, 0xc3, 0x80, 0xee, 0x84, + 0xe7, 0xdb, 0xdd, 0x88, 0x17, 0x98, 0x64, 0x4b, 0x2a, 0xd0, 0xb7, 0xe0, 0x70, 0x65, 0x45, 0x29, + 0x13, 0xb2, 0xae, 0xe7, 0x4a, 0xd5, 0x73, 0x4c, 0x0c, 0xf4, 0xe7, 0x9e, 0x09, 0x89, 0x81, 0xd7, + 0xa6, 0xe8, 0xff, 0x62, 0x80, 0xdd, 0x44, 0xd0, 0xc7, 0xd0, 0x49, 0xc9, 0x9c, 0xa6, 0x55, 0x4d, + 0xa5, 0x83, 0xbe, 0x01, 0x53, 0xaf, 0x50, 0xb5, 0xa8, 0xec, 0xfe, 0x7f, 0x65, 0x2f, 0x2d, 0x5c, + 0xad, 0xe8, 0xbf, 0x81, 0x8e, 0x06, 0xd0, 0x27, 0x60, 0x2d, 0x18, 0xd7, 0x22, 0xac, 0xb2, 0x9f, + 0x6b, 0x3f, 0x2c, 0xd0, 0x73, 0x38, 0x4f, 0x49, 0x19, 0x29, 0x9b, 0x65, 0x2a, 0x37, 0x2c, 0xfc, + 0xbf, 0x0c, 0x40, 0xf5, 0x3e, 0x8d, 0xb2, 0x04, 0x7a, 0x0f, 0x4f, 0x9b, 0x66, 0x1f, 0x95, 0xfd, + 0xf2, 0xf0, 0x60, 0xfb, 0x05, 0x41, 0x63, 0xea, 0xf2, 0xbb, 0xec, 0xd0, 0x15, 0xfd, 0x9f, 0x0d, + 0x70, 0x8f, 0x18, 0xff, 0xd2, 0x86, 0x31, 0x40, 0xb3, 0xb2, 0x6e, 0x45, 0xf0, 0x7f, 0x76, 0xdc, + 0x7b, 0xf8, 0x20, 0x43, 0xff, 0x33, 0xb0, 0xf7, 0xcf, 0x05, 0x41, 0x3b, 0x23, 0xeb, 0x5a, 0x4c, + 0xda, 0xf6, 0x7f, 0x32, 0xc0, 0x9a, 0xce, 0xc6, 0xa5, 0x6e, 0xdf, 0x80, 0x23, 0x64, 0x76, 0xa2, + 0xdb, 0xbe, 0x1e, 0x1c, 0x15, 0xa5, 0x31, 0x2a, 0xf1, 0x0a, 0x99, 0xd5, 0xe2, 0xbd, 0x07, 0xf7, + 0x28, 0x78, 0x22, 0x51, 0xe3, 0x54, 0xa2, 0x47, 0xfa, 0x6e, 0x9d, 0xe8, 0xdb, 0xff, 0xb5, 0x05, + 0xdd, 0x70, 0x32, 0x8d, 0x49, 0x36, 0x56, 0x6f, 0x7a, 0x9e, 0x73, 0xf4, 0x15, 0xb4, 0xd7, 0x79, + 0x52, 0x1e, 0xbf, 0x7b, 0xf3, 0x5c, 0x1d, 0xeb, 0x98, 0x11, 0xbc, 0xcf, 0x13, 0x8a, 0x35, 0x09, + 0x7d, 0x01, 0xae, 0x88, 0x49, 0x56, 0x4e, 0x91, 0x0d, 0x49, 0xf5, 0x0e, 0x2e, 0xbe, 0x50, 0x60, + 0x58, 0x61, 0x6a, 0x24, 0xad, 0xc9, 0x36, 0x2a, 0x78, 0x1e, 0x47, 0x92, 0xad, 0xa9, 0x7e, 0x26, + 0x2e, 0x76, 0xd6, 0x64, 0x3b, 0xe1, 0x79, 0x3c, 0x63, 0x6b, 0xfd, 0xd0, 0x14, 0xe7, 0xb1, 0x48, + 0x88, 0xa4, 0xfa, 0xa9, 0xb8, 0xd8, 0x5e, 0x93, 0xed, 0xf7, 0x1a, 0x40, 0x2f, 0xa1, 0x5b, 0xef, + 0x13, 0x25, 0x34, 0x25, 0x3b, 0x3d, 0xad, 0xf6, 0x1b, 0xdd, 0x2a, 0x0c, 0x7d, 0x09, 0x4f, 0x85, + 0x24, 0x29, 0x8d, 0xe4, 0x8a, 0x53, 0xb1, 0xca, 0xd3, 0xa4, 0x9a, 0x58, 0x5d, 0x0d, 0xcf, 0x6a, + 0xd4, 0xbf, 0x81, 0xb6, 0x2a, 0x02, 0x5d, 0x80, 0x75, 0x1b, 0x4e, 0x47, 0x6f, 0xef, 0xef, 0x6e, + 0x7b, 0x4f, 0xd4, 0x98, 0x09, 0x27, 0x9b, 0x57, 0xe5, 0xc0, 0x09, 0x27, 0x9b, 0xd7, 0xbd, 0x96, + 0xb2, 0xde, 0x7e, 0x98, 0xbd, 0xeb, 0x9d, 0xcd, 0x4d, 0xfd, 0xef, 0x31, 0xfc, 0x3b, 0x00, 0x00, + 0xff, 0xff, 0x3f, 0x9d, 0x00, 0x97, 0x49, 0x06, 0x00, 0x00, } diff --git a/plugins/vpp/model/l3/l3.proto b/plugins/vpp/model/l3/l3.proto index 86aa2e7a50..3fd987b786 100644 --- a/plugins/vpp/model/l3/l3.proto +++ b/plugins/vpp/model/l3/l3.proto @@ -5,6 +5,17 @@ package l3; /* Static routes */ message StaticRoutes { message Route { + enum RouteType { + INTRA_VRF = 0; /* Forwarding is being done in the specified vrf_id only, or according to + the specified outgoing interface. */ + INTER_VRF = 1; /* Forwarding is being done by lookup into a different VRF, + specified as via_vrf_id field. In case of these routes, the outgoing + interface should not be specified. The next hop IP address + does not have to be specified either, in that case VPP does full + recursive lookup in the via_vrf_id VRF. */ + DROP = 2; /* Drops the network communication designated for specific IP address */ + } + RouteType type = 10; uint32 vrf_id = 1; /* VRF identifier, field required for remote client. This value should be consistent with VRF ID in static route key. If it is not, value from key will be preffered and this field will be overriden. */ @@ -16,6 +27,7 @@ message StaticRoutes { uint32 preference = 7; /* The preference of the path. Lowest preference is preferred. */ /* Only paths with the best preference contribute to forwarding. */ /* (a poor man's primary and backup) */ + uint32 via_vrf_id = 8; /* Specifies VRF ID for the next hop lookup / recursive lookup */ } repeated Route routes = 1; /* list of IP static routes */ } @@ -63,4 +75,22 @@ message STNTable { string interface = 2; /* interface where the packets will be punted */ } repeated STNTableEntry stn_entries = 1; /* list of STN entries */ +} + +/* Enables/disables IP neighbor scanning */ +message IPScanNeighbor { + enum Mode { /* IP scan neighbor mode. Disabled by default, it can be enabled + for IPv4 or IPv6 separately, or for both of them*/ + DISABLED = 0; + IPv4 = 1; + IPv6 = 2; + BOTH = 3; + } + Mode mode = 1; + + uint32 scan_interval = 2; + uint32 max_proc_time = 3; + uint32 max_update = 4; + uint32 scan_int_delay = 5; + uint32 stale_threshold = 6; } \ No newline at end of file diff --git a/plugins/vpp/model/l4/keys_agent_l4.go b/plugins/vpp/model/l4/keys_agent_l4.go index 732673d147..f5e7b025a7 100644 --- a/plugins/vpp/model/l4/keys_agent_l4.go +++ b/plugins/vpp/model/l4/keys_agent_l4.go @@ -16,32 +16,22 @@ package l4 // Prefixes const ( - // L4Prefix is the relative key prefix for VPP L4 plugin. - L4Prefix = "vpp/config/v1/l4/" + // Prefix is common relative key for VPP L4 plugin. + Prefix = "vpp/config/v1/l4/" // L4FeaturesPrefix is the relative key prefix for VPP L4 features. - L4FeaturesPrefix = L4Prefix + "features/" + FeaturesPrefix = Prefix + "features/" // L4NamespacesPrefix is the relative key prefix for VPP L4 application namespaces. - L4NamespacesPrefix = L4Prefix + "namespaces/" + NamespacesPrefix = Prefix + "namespaces/" ) -// AppNamespacesKeyPrefix returns the prefix used in ETCD to store l4 namespaces -func AppNamespacesKeyPrefix() string { - return L4NamespacesPrefix -} - // AppNamespacesKey returns the key used in ETCD to store namespaces func AppNamespacesKey(namespaceID string) string { - return L4NamespacesPrefix + namespaceID -} - -// FeatureKeyPrefix returns the prefix used in ETCD to store l4 features value -func FeatureKeyPrefix() string { - return L4FeaturesPrefix + return NamespacesPrefix + namespaceID } // FeatureKey returns the key used in ETCD to store L4Feature flag func FeatureKey() string { - return L4FeaturesPrefix + "feature" + return FeaturesPrefix + "feature" } diff --git a/plugins/vpp/model/nat/keys_nat.go b/plugins/vpp/model/nat/keys_nat.go index aceaf7fd3b..1ef0c7444a 100644 --- a/plugins/vpp/model/nat/keys_nat.go +++ b/plugins/vpp/model/nat/keys_nat.go @@ -15,43 +15,22 @@ package nat const ( - // natPrefix - prefix = "vpp/config/v1/nat" - // globalConfigPrefix is relative prefix for global config - globalConfig = prefix + "/global/" - // sNatPrefix is relative prefix for SNAT setup - sNatPrefix = prefix + "/snat/" - // dNatPrefix is relative prefix for DNAT setup - dNatPrefix = prefix + "/dnat/" + // Prefix is NAT prefix + Prefix = "vpp/config/v1/nat/" + // GlobalPrefix is relative prefix for global config + GlobalPrefix = Prefix + "global/" + // SNatPrefix is relative prefix for SNAT setup + SNatPrefix = Prefix + "snat/" + // DNatPrefix is relative prefix for DNAT setup + DNatPrefix = Prefix + "dnat/" ) -// GlobalConfigPrefix returns the prefix used in ETCD to store NAT global config -func GlobalConfigPrefix() string { - return globalConfig -} - -// GlobalConfigKey returns the key used in ETCD to store NAT global config. Global config can be stored only once, -// so the prefix == key -func GlobalConfigKey() string { - return globalConfig -} - -// SNatPrefix returns the prefix used in ETCD to store SNAT config -func SNatPrefix() string { - return sNatPrefix -} - // SNatKey returns the key used in ETCD to store SNAT config func SNatKey(label string) string { - return sNatPrefix + label -} - -// DNatPrefix returns the prefix used in ETCD to store NAT DNAT config -func DNatPrefix() string { - return dNatPrefix + return SNatPrefix + label } // DNatKey returns the key used in ETCD to store DNAT config func DNatKey(label string) string { - return dNatPrefix + label + return DNatPrefix + label } diff --git a/plugins/vpp/model/nat/nat.pb.go b/plugins/vpp/model/nat/nat.pb.go index e8a8568f32..bcc4e53dd9 100644 --- a/plugins/vpp/model/nat/nat.pb.go +++ b/plugins/vpp/model/nat/nat.pb.go @@ -79,9 +79,11 @@ func (TwiceNatMode) EnumDescriptor() ([]byte, []int) { return fileDescriptorNat, // NAT44 global config type Nat44Global struct { - Forwarding bool `protobuf:"varint,2,opt,name=forwarding,proto3" json:"forwarding,omitempty"` - NatInterfaces []*Nat44Global_NatInterface `protobuf:"bytes,3,rep,name=nat_interfaces,json=natInterfaces" json:"nat_interfaces,omitempty"` - AddressPools []*Nat44Global_AddressPool `protobuf:"bytes,5,rep,name=address_pools,json=addressPools" json:"address_pools,omitempty"` + Forwarding bool `protobuf:"varint,2,opt,name=forwarding,proto3" json:"forwarding,omitempty"` + NatInterfaces []*Nat44Global_NatInterface `protobuf:"bytes,3,rep,name=nat_interfaces,json=natInterfaces" json:"nat_interfaces,omitempty"` + AddressPools []*Nat44Global_AddressPool `protobuf:"bytes,5,rep,name=address_pools,json=addressPools" json:"address_pools,omitempty"` + VirtualReassemblyIpv4 *Nat44Global_VirtualReassembly `protobuf:"bytes,6,opt,name=virtual_reassembly_ipv4,json=virtualReassemblyIpv4" json:"virtual_reassembly_ipv4,omitempty"` + VirtualReassemblyIpv6 *Nat44Global_VirtualReassembly `protobuf:"bytes,7,opt,name=virtual_reassembly_ipv6,json=virtualReassemblyIpv6" json:"virtual_reassembly_ipv6,omitempty"` } func (m *Nat44Global) Reset() { *m = Nat44Global{} } @@ -110,6 +112,20 @@ func (m *Nat44Global) GetAddressPools() []*Nat44Global_AddressPool { return nil } +func (m *Nat44Global) GetVirtualReassemblyIpv4() *Nat44Global_VirtualReassembly { + if m != nil { + return m.VirtualReassemblyIpv4 + } + return nil +} + +func (m *Nat44Global) GetVirtualReassemblyIpv6() *Nat44Global_VirtualReassembly { + if m != nil { + return m.VirtualReassemblyIpv6 + } + return nil +} + type Nat44Global_NatInterface struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` IsInside bool `protobuf:"varint,2,opt,name=is_inside,json=isInside,proto3" json:"is_inside,omitempty"` @@ -182,6 +198,48 @@ func (m *Nat44Global_AddressPool) GetTwiceNat() bool { return false } +type Nat44Global_VirtualReassembly struct { + Timeout uint32 `protobuf:"varint,1,opt,name=timeout,proto3" json:"timeout,omitempty"` + MaxReass uint32 `protobuf:"varint,2,opt,name=max_reass,json=maxReass,proto3" json:"max_reass,omitempty"` + MaxFrag uint32 `protobuf:"varint,3,opt,name=max_frag,json=maxFrag,proto3" json:"max_frag,omitempty"` + DropFrag bool `protobuf:"varint,4,opt,name=drop_frag,json=dropFrag,proto3" json:"drop_frag,omitempty"` +} + +func (m *Nat44Global_VirtualReassembly) Reset() { *m = Nat44Global_VirtualReassembly{} } +func (m *Nat44Global_VirtualReassembly) String() string { return proto.CompactTextString(m) } +func (*Nat44Global_VirtualReassembly) ProtoMessage() {} +func (*Nat44Global_VirtualReassembly) Descriptor() ([]byte, []int) { + return fileDescriptorNat, []int{0, 2} +} + +func (m *Nat44Global_VirtualReassembly) GetTimeout() uint32 { + if m != nil { + return m.Timeout + } + return 0 +} + +func (m *Nat44Global_VirtualReassembly) GetMaxReass() uint32 { + if m != nil { + return m.MaxReass + } + return 0 +} + +func (m *Nat44Global_VirtualReassembly) GetMaxFrag() uint32 { + if m != nil { + return m.MaxFrag + } + return 0 +} + +func (m *Nat44Global_VirtualReassembly) GetDropFrag() bool { + if m != nil { + return m.DropFrag + } + return false +} + // Many-to-one (SNAT) setup type Nat44SNat struct { SnatConfigs []*Nat44SNat_SNatConfig `protobuf:"bytes,1,rep,name=snat_configs,json=snatConfigs" json:"snat_configs,omitempty"` @@ -265,7 +323,6 @@ func (m *Nat44DNat_DNatConfig) GetIdMappings() []*Nat44DNat_DNatConfig_IdentityM } type Nat44DNat_DNatConfig_StaticMapping struct { - VrfId uint32 `protobuf:"varint,1,opt,name=vrf_id,json=vrfId,proto3" json:"vrf_id,omitempty"` ExternalInterface string `protobuf:"bytes,2,opt,name=external_interface,json=externalInterface,proto3" json:"external_interface,omitempty"` ExternalIp string `protobuf:"bytes,3,opt,name=external_ip,json=externalIp,proto3" json:"external_ip,omitempty"` ExternalPort uint32 `protobuf:"varint,4,opt,name=external_port,json=externalPort,proto3" json:"external_port,omitempty"` @@ -281,13 +338,6 @@ func (*Nat44DNat_DNatConfig_StaticMapping) Descriptor() ([]byte, []int) { return fileDescriptorNat, []int{2, 0, 0} } -func (m *Nat44DNat_DNatConfig_StaticMapping) GetVrfId() uint32 { - if m != nil { - return m.VrfId - } - return 0 -} - func (m *Nat44DNat_DNatConfig_StaticMapping) GetExternalInterface() string { if m != nil { return m.ExternalInterface @@ -331,6 +381,7 @@ func (m *Nat44DNat_DNatConfig_StaticMapping) GetTwiceNat() TwiceNatMode { } type Nat44DNat_DNatConfig_StaticMapping_LocalIP struct { + VrfId uint32 `protobuf:"varint,4,opt,name=vrf_id,json=vrfId,proto3" json:"vrf_id,omitempty"` LocalIp string `protobuf:"bytes,1,opt,name=local_ip,json=localIp,proto3" json:"local_ip,omitempty"` LocalPort uint32 `protobuf:"varint,3,opt,name=local_port,json=localPort,proto3" json:"local_port,omitempty"` Probability uint32 `protobuf:"varint,2,opt,name=probability,proto3" json:"probability,omitempty"` @@ -347,6 +398,13 @@ func (*Nat44DNat_DNatConfig_StaticMapping_LocalIP) Descriptor() ([]byte, []int) return fileDescriptorNat, []int{2, 0, 0, 0} } +func (m *Nat44DNat_DNatConfig_StaticMapping_LocalIP) GetVrfId() uint32 { + if m != nil { + return m.VrfId + } + return 0 +} + func (m *Nat44DNat_DNatConfig_StaticMapping_LocalIP) GetLocalIp() string { if m != nil { return m.LocalIp @@ -422,6 +480,7 @@ func init() { proto.RegisterType((*Nat44Global)(nil), "nat.Nat44Global") proto.RegisterType((*Nat44Global_NatInterface)(nil), "nat.Nat44Global.NatInterface") proto.RegisterType((*Nat44Global_AddressPool)(nil), "nat.Nat44Global.AddressPool") + proto.RegisterType((*Nat44Global_VirtualReassembly)(nil), "nat.Nat44Global.VirtualReassembly") proto.RegisterType((*Nat44SNat)(nil), "nat.Nat44SNat") proto.RegisterType((*Nat44SNat_SNatConfig)(nil), "nat.Nat44SNat.SNatConfig") proto.RegisterType((*Nat44DNat)(nil), "nat.Nat44DNat") @@ -436,50 +495,58 @@ func init() { func init() { proto.RegisterFile("nat.proto", fileDescriptorNat) } var fileDescriptorNat = []byte{ - // 720 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0xdd, 0x4e, 0xdb, 0x48, - 0x14, 0xc6, 0xf9, 0x75, 0x8e, 0xe3, 0x10, 0x66, 0x77, 0x25, 0x93, 0x5d, 0x76, 0xa3, 0xac, 0xda, - 0x06, 0xa4, 0x06, 0x09, 0xb8, 0xec, 0x0d, 0x25, 0xd0, 0xba, 0x0a, 0x51, 0xe4, 0xd0, 0x6b, 0x6b, - 0x62, 0x8f, 0xd1, 0x48, 0xc6, 0x63, 0xcd, 0x0c, 0x50, 0x9e, 0xa4, 0xb7, 0xbd, 0xef, 0x03, 0xb4, - 0x0f, 0xd5, 0x87, 0xa8, 0x3c, 0x1e, 0xc7, 0x06, 0x04, 0xed, 0x4d, 0x74, 0xe6, 0x9c, 0xcf, 0xdf, - 0x77, 0x7e, 0x03, 0x9d, 0x04, 0xcb, 0x49, 0xca, 0x99, 0x64, 0xa8, 0x9e, 0x60, 0x39, 0xfa, 0x5e, - 0x07, 0x6b, 0x8e, 0xe5, 0xd1, 0xd1, 0xbb, 0x98, 0xad, 0x70, 0x8c, 0xfe, 0x05, 0x88, 0x18, 0xbf, - 0xc5, 0x3c, 0xa4, 0xc9, 0xa5, 0x53, 0x1b, 0x1a, 0x63, 0xd3, 0xab, 0x78, 0xd0, 0x14, 0x7a, 0x09, - 0x96, 0x3e, 0x4d, 0x24, 0xe1, 0x11, 0x0e, 0x88, 0x70, 0xea, 0xc3, 0xfa, 0xd8, 0x3a, 0xd8, 0x99, - 0x64, 0xc4, 0x15, 0xa6, 0xcc, 0x76, 0x0b, 0x94, 0x67, 0x27, 0x95, 0x97, 0x40, 0xc7, 0x60, 0xe3, - 0x30, 0xe4, 0x44, 0x08, 0x3f, 0x65, 0x2c, 0x16, 0x4e, 0x53, 0x91, 0xfc, 0xf3, 0x88, 0xe4, 0x38, - 0x47, 0x2d, 0x18, 0x8b, 0xbd, 0x2e, 0x2e, 0x1f, 0x62, 0x10, 0x41, 0xb7, 0xaa, 0x80, 0x10, 0x34, - 0x12, 0x7c, 0x45, 0x1c, 0x63, 0x68, 0x8c, 0x3b, 0x9e, 0xb2, 0xd1, 0xdf, 0xd0, 0xa1, 0xc2, 0xa7, - 0x89, 0xa0, 0x21, 0xd1, 0xb5, 0x98, 0x54, 0xb8, 0xea, 0x8d, 0x5e, 0x40, 0x8f, 0x5d, 0xcb, 0xf4, - 0x5a, 0xfa, 0x11, 0xc1, 0xf2, 0x9a, 0x13, 0xa7, 0xae, 0x10, 0x76, 0xee, 0x3d, 0xcb, 0x9d, 0x83, - 0xcf, 0x06, 0x58, 0x95, 0x2c, 0xd0, 0x1e, 0x6c, 0x45, 0x94, 0x0b, 0xe9, 0x0b, 0x1e, 0xf8, 0x3a, - 0x23, 0x2d, 0xba, 0xa9, 0x02, 0x4b, 0x1e, 0x68, 0x3c, 0x1a, 0x43, 0x3f, 0xc6, 0x0f, 0xa0, 0x35, - 0x05, 0xed, 0x65, 0xfe, 0x0a, 0xf2, 0x2f, 0x68, 0xdd, 0xf0, 0xc8, 0xa7, 0xa1, 0x4a, 0xc2, 0xf6, - 0x9a, 0x37, 0x3c, 0x72, 0xc3, 0xac, 0x00, 0x79, 0x4b, 0x03, 0xe2, 0x27, 0x58, 0x3a, 0x8d, 0xbc, - 0x00, 0xe5, 0x98, 0x63, 0x39, 0xba, 0x82, 0x8e, 0x6a, 0xd5, 0x72, 0x8e, 0x25, 0x7a, 0x03, 0x5d, - 0x91, 0x0d, 0x26, 0x60, 0x49, 0x44, 0x2f, 0xb3, 0x8c, 0xb2, 0x86, 0x6e, 0x97, 0x0d, 0xcd, 0x50, - 0x93, 0xec, 0xe7, 0x44, 0x21, 0x3c, 0x2b, 0x83, 0xe7, 0xb6, 0x18, 0x8c, 0x00, 0xca, 0x10, 0xfa, - 0x13, 0x9a, 0x31, 0x5e, 0x91, 0x58, 0x97, 0x95, 0x3f, 0x46, 0x3f, 0x5a, 0x5a, 0x6f, 0xaa, 0xf5, - 0xc2, 0x67, 0xf5, 0x32, 0xd4, 0x64, 0x5a, 0xd1, 0x0b, 0x2b, 0x7a, 0x5f, 0x5a, 0x00, 0xd3, 0x5f, - 0x08, 0xa2, 0xf7, 0x60, 0x09, 0xe9, 0x5f, 0xe1, 0x34, 0xa5, 0xc9, 0xa5, 0x70, 0x1a, 0x4a, 0xe1, - 0xd5, 0x93, 0x0a, 0x93, 0xa5, 0xc4, 0x92, 0x06, 0xe7, 0x39, 0xde, 0x03, 0x21, 0xb5, 0x29, 0xd0, - 0x07, 0xb0, 0x68, 0x58, 0x32, 0xb5, 0x14, 0xd3, 0xee, 0xd3, 0x4c, 0x6e, 0x48, 0x12, 0x49, 0xe5, - 0xdd, 0x9a, 0x8b, 0x86, 0x05, 0xd7, 0xe0, 0x6b, 0x1d, 0xec, 0x7b, 0x4a, 0x95, 0xd9, 0x19, 0xd5, - 0xd9, 0xbd, 0x06, 0x44, 0x3e, 0x49, 0xc2, 0x13, 0x1c, 0x97, 0xe7, 0xa2, 0xc7, 0xbf, 0x55, 0x44, - 0xca, 0xfd, 0xfd, 0x0f, 0xac, 0x12, 0x9e, 0xaa, 0x35, 0xe8, 0x78, 0xb0, 0xc6, 0xa5, 0xe8, 0x7f, - 0xb0, 0xd7, 0x80, 0x94, 0xf1, 0x7c, 0x1f, 0x6c, 0xaf, 0x5b, 0x38, 0x17, 0x8c, 0x4b, 0x34, 0x83, - 0x4e, 0xcc, 0x02, 0x45, 0x51, 0x1c, 0xd5, 0xfe, 0x6f, 0x76, 0x6c, 0x32, 0xcb, 0x3e, 0x74, 0x17, - 0x9e, 0xa9, 0x18, 0xdc, 0x54, 0xa0, 0x5d, 0x30, 0xd5, 0x5f, 0x45, 0xc0, 0x62, 0xa7, 0x35, 0x34, - 0xc6, 0xbd, 0x03, 0x5b, 0x91, 0x2d, 0xb4, 0xd3, 0x5b, 0x87, 0xd1, 0xa4, 0xba, 0xa9, 0x6d, 0x85, - 0xdd, 0x52, 0xd8, 0x0b, 0xbd, 0xae, 0xe7, 0x2c, 0x24, 0xe5, 0xf2, 0x0e, 0x08, 0xb4, 0xb5, 0x1e, - 0xda, 0x06, 0xb3, 0xc8, 0x59, 0x2f, 0x40, 0x5b, 0x67, 0x80, 0x76, 0x00, 0xf2, 0x90, 0x2a, 0x38, - 0x3f, 0x8d, 0xbc, 0x40, 0x55, 0xed, 0x10, 0xac, 0x94, 0xb3, 0x15, 0x5e, 0xd1, 0x98, 0xca, 0x3b, - 0xd5, 0x5b, 0xdb, 0xab, 0xba, 0x06, 0xdf, 0x0c, 0xd8, 0x7c, 0x30, 0xcd, 0xa7, 0xe6, 0xb5, 0x0f, - 0x7f, 0xe8, 0x1b, 0x25, 0xe1, 0xa3, 0x81, 0xa1, 0x75, 0xa8, 0x9c, 0xd8, 0x0e, 0x00, 0x4d, 0xd7, - 0x77, 0x9d, 0x0f, 0xac, 0x43, 0xd3, 0xe2, 0xa4, 0x11, 0x34, 0x2a, 0x63, 0x52, 0xf6, 0xbd, 0x86, - 0x36, 0x9f, 0x6d, 0xe8, 0xde, 0x4b, 0x30, 0x0b, 0x2f, 0x6a, 0x43, 0xfd, 0xe2, 0x64, 0xd1, 0xdf, - 0xc8, 0x8c, 0x8f, 0xd3, 0x45, 0xdf, 0x40, 0x26, 0x34, 0xdc, 0x93, 0xf3, 0x45, 0xbf, 0xb6, 0x77, - 0x08, 0xdd, 0x6a, 0x8b, 0x51, 0x17, 0xcc, 0xa9, 0xbb, 0x3c, 0x7e, 0x3b, 0x3b, 0x9d, 0xf6, 0x37, - 0x90, 0x05, 0xed, 0xd3, 0x79, 0xfe, 0x50, 0x1f, 0x2d, 0x4f, 0x67, 0x67, 0xfd, 0xda, 0xaa, 0xa5, - 0x64, 0x0e, 0x7f, 0x06, 0x00, 0x00, 0xff, 0xff, 0x46, 0x7f, 0x74, 0xc4, 0x0e, 0x06, 0x00, 0x00, + // 846 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0x4f, 0x6f, 0xe3, 0x44, + 0x14, 0x5f, 0x37, 0xff, 0x9c, 0xe7, 0xb8, 0x9b, 0x0e, 0xac, 0x70, 0x03, 0x85, 0x28, 0x08, 0xc8, + 0x56, 0x22, 0x2b, 0x75, 0xab, 0x3d, 0x71, 0x29, 0x4d, 0x0b, 0x46, 0x6d, 0x15, 0x39, 0x0b, 0x07, + 0x2e, 0xd6, 0x24, 0x1e, 0x47, 0x23, 0x39, 0x1e, 0x6b, 0x66, 0x92, 0x6d, 0x25, 0x4e, 0x7c, 0x09, + 0xae, 0xdc, 0xf9, 0x00, 0x7c, 0x29, 0xae, 0xdc, 0xd1, 0x8c, 0xc7, 0xf1, 0x6c, 0xab, 0x16, 0x24, + 0x2e, 0xd6, 0x9b, 0xf7, 0x7e, 0xfe, 0xbd, 0x37, 0xbf, 0x37, 0xef, 0x41, 0x37, 0xc7, 0x72, 0x52, + 0x70, 0x26, 0x19, 0x6a, 0xe4, 0x58, 0x8e, 0xfe, 0x6e, 0x81, 0x77, 0x83, 0xe5, 0xe9, 0xe9, 0x77, + 0x19, 0x5b, 0xe0, 0x0c, 0x7d, 0x0a, 0x90, 0x32, 0xfe, 0x0e, 0xf3, 0x84, 0xe6, 0xab, 0x60, 0x6f, + 0xe8, 0x8c, 0xdd, 0xc8, 0xf2, 0xa0, 0x29, 0xec, 0xe7, 0x58, 0xc6, 0x34, 0x97, 0x84, 0xa7, 0x78, + 0x49, 0x44, 0xd0, 0x18, 0x36, 0xc6, 0xde, 0xc9, 0xd1, 0x44, 0x11, 0x5b, 0x4c, 0xca, 0x0e, 0x2b, + 0x54, 0xe4, 0xe7, 0xd6, 0x49, 0xa0, 0x33, 0xf0, 0x71, 0x92, 0x70, 0x22, 0x44, 0x5c, 0x30, 0x96, + 0x89, 0xa0, 0xa5, 0x49, 0x3e, 0x79, 0x40, 0x72, 0x56, 0xa2, 0x66, 0x8c, 0x65, 0x51, 0x0f, 0xd7, + 0x07, 0x81, 0x7e, 0x86, 0x8f, 0xb6, 0x94, 0xcb, 0x0d, 0xce, 0x62, 0x4e, 0xb0, 0x10, 0x64, 0xbd, + 0xc8, 0xee, 0x62, 0x5a, 0x6c, 0x4f, 0x83, 0xf6, 0xd0, 0x19, 0x7b, 0x27, 0xa3, 0x07, 0x64, 0x3f, + 0x95, 0xf8, 0x68, 0x07, 0x8f, 0x5e, 0x6c, 0xef, 0xbb, 0xc2, 0x62, 0x7b, 0xfa, 0x38, 0xf7, 0x9b, + 0xa0, 0xf3, 0xff, 0xb8, 0xdf, 0x0c, 0x52, 0xe8, 0xd9, 0xca, 0x20, 0x04, 0xcd, 0x1c, 0xaf, 0x49, + 0xe0, 0x0c, 0x9d, 0x71, 0x37, 0xd2, 0x36, 0xfa, 0x18, 0xba, 0x54, 0xc4, 0x34, 0x17, 0x34, 0x21, + 0xa6, 0x07, 0x2e, 0x15, 0xa1, 0x3e, 0xa3, 0x2f, 0x60, 0x9f, 0x6d, 0x64, 0xb1, 0x91, 0x71, 0x4a, + 0xb0, 0xdc, 0x70, 0x12, 0x34, 0x34, 0xc2, 0x2f, 0xbd, 0x97, 0xa5, 0x73, 0xf0, 0x9b, 0x03, 0x9e, + 0xa5, 0x1e, 0x3a, 0x86, 0x83, 0x94, 0x72, 0x21, 0x63, 0xc1, 0x97, 0xb1, 0x51, 0xd2, 0x24, 0x7d, + 0xae, 0x03, 0x73, 0xbe, 0x34, 0x78, 0x34, 0x86, 0x7e, 0x86, 0xef, 0x41, 0xf7, 0x34, 0x74, 0x5f, + 0xf9, 0x2d, 0xe4, 0x0b, 0x68, 0x6f, 0x79, 0x1a, 0xd3, 0x44, 0x17, 0xe1, 0x47, 0xad, 0x2d, 0x4f, + 0xc3, 0x44, 0x5d, 0x40, 0xbe, 0xa3, 0x4b, 0x12, 0xe7, 0x58, 0x06, 0xcd, 0xf2, 0x02, 0xda, 0x71, + 0x83, 0xe5, 0xe0, 0x57, 0x07, 0x0e, 0x1e, 0xc8, 0x85, 0x02, 0xe8, 0x48, 0xba, 0x26, 0x6c, 0x23, + 0x75, 0x55, 0x7e, 0x54, 0x1d, 0x15, 0xd9, 0x1a, 0xdf, 0x96, 0x9d, 0xd0, 0x65, 0xf8, 0x91, 0xbb, + 0xc6, 0xb7, 0xfa, 0x5f, 0x74, 0x08, 0xca, 0x8e, 0x53, 0x8e, 0x57, 0xa6, 0x84, 0xce, 0x1a, 0xdf, + 0x5e, 0x72, 0xbc, 0x52, 0xff, 0x25, 0x9c, 0x15, 0x65, 0xcc, 0x14, 0xa1, 0x1c, 0x2a, 0x38, 0x5a, + 0x43, 0x57, 0xb7, 0x6f, 0x7e, 0x83, 0x25, 0xfa, 0x06, 0x7a, 0x42, 0xbd, 0xea, 0x25, 0xcb, 0x53, + 0xba, 0x52, 0xb2, 0xa8, 0xd7, 0x78, 0x58, 0x37, 0x59, 0xa1, 0x26, 0xea, 0x73, 0xae, 0x11, 0x91, + 0xa7, 0xe0, 0xa5, 0x2d, 0x06, 0x23, 0x80, 0x3a, 0x84, 0x3e, 0x84, 0x56, 0x86, 0x17, 0x24, 0x33, + 0xda, 0x96, 0x87, 0xd1, 0x5f, 0x6d, 0x93, 0x6f, 0x6a, 0xf2, 0x25, 0x4f, 0xe6, 0x53, 0xa8, 0xc9, + 0xd4, 0xca, 0x97, 0x58, 0xf9, 0x7e, 0x6f, 0x03, 0x4c, 0xff, 0x25, 0x21, 0xfa, 0x1e, 0x3c, 0x21, + 0xe3, 0x35, 0x2e, 0x0a, 0x9a, 0xaf, 0x44, 0xd0, 0xd4, 0x19, 0xbe, 0x7a, 0x34, 0xc3, 0x64, 0x2e, + 0xb1, 0xa4, 0xcb, 0xeb, 0x12, 0x1f, 0x81, 0x90, 0xc6, 0x14, 0xe8, 0x07, 0xf0, 0x68, 0x52, 0x33, + 0xb5, 0x35, 0xd3, 0xcb, 0xc7, 0x99, 0xc2, 0x84, 0xe4, 0x92, 0xca, 0xbb, 0x1d, 0x17, 0x4d, 0x2a, + 0xae, 0xc1, 0x1f, 0x0d, 0xf0, 0xdf, 0xcb, 0x84, 0xbe, 0x06, 0x44, 0x6e, 0x25, 0xe1, 0x39, 0xce, + 0xea, 0xa5, 0x62, 0x1e, 0xdb, 0x41, 0x15, 0xa9, 0xa7, 0xe5, 0x33, 0xf0, 0x6a, 0x78, 0xa1, 0x3b, + 0xde, 0x8d, 0x60, 0x87, 0x2b, 0xd0, 0xe7, 0xe0, 0xef, 0x00, 0x05, 0xe3, 0xe5, 0xeb, 0xf3, 0xa3, + 0x5e, 0xe5, 0x9c, 0x31, 0x2e, 0xd1, 0x15, 0x74, 0x33, 0xb6, 0xd4, 0x14, 0xd5, 0xea, 0x79, 0xf5, + 0x1f, 0xa5, 0x99, 0x5c, 0xa9, 0x1f, 0xc3, 0x59, 0xe4, 0x6a, 0x86, 0xb0, 0x10, 0xe8, 0x25, 0xb8, + 0x7a, 0xa1, 0x2e, 0x59, 0xa6, 0x57, 0xcf, 0xfe, 0x89, 0xaf, 0xc9, 0x66, 0xc6, 0x19, 0xed, 0xc2, + 0x68, 0x62, 0xcf, 0x45, 0x47, 0x63, 0x0f, 0x34, 0xf6, 0xad, 0x19, 0x8e, 0x6b, 0x96, 0x10, 0x6b, + 0x54, 0x7e, 0x81, 0x8e, 0xc9, 0x67, 0x4d, 0x5a, 0xd3, 0x9e, 0xb4, 0x43, 0x70, 0xab, 0xab, 0x98, + 0x07, 0xd0, 0x31, 0x85, 0xa1, 0x23, 0x80, 0x32, 0xa4, 0x75, 0x28, 0x87, 0xa3, 0xbc, 0xb7, 0x16, + 0x61, 0x08, 0x5e, 0xc1, 0xd9, 0x02, 0x2f, 0x68, 0x46, 0xe5, 0x9d, 0x19, 0x2c, 0xdb, 0x35, 0xf8, + 0xd3, 0x81, 0xe7, 0xf7, 0xba, 0x69, 0x95, 0xe1, 0xd8, 0x65, 0xbc, 0x82, 0x0f, 0xcc, 0xa2, 0x20, + 0xc9, 0x83, 0x3e, 0xa2, 0x5d, 0xa8, 0x6e, 0xe4, 0x11, 0x00, 0x2d, 0x76, 0xcb, 0xa5, 0xec, 0x63, + 0x97, 0x16, 0xd5, 0x5e, 0x41, 0xd0, 0xb4, 0xba, 0xa7, 0xed, 0xf7, 0x74, 0x6e, 0x3d, 0xa9, 0xf3, + 0xf1, 0x97, 0xe0, 0x56, 0x5e, 0xd4, 0x81, 0xc6, 0xdb, 0xf3, 0x59, 0xff, 0x99, 0x32, 0x7e, 0x9c, + 0xce, 0xfa, 0x0e, 0x72, 0xa1, 0x19, 0x9e, 0x5f, 0xcf, 0xfa, 0x7b, 0xc7, 0xaf, 0xa1, 0x67, 0x2b, + 0x8f, 0x7a, 0xe0, 0x4e, 0xc3, 0xf9, 0xd9, 0xb7, 0x57, 0x17, 0xd3, 0xfe, 0x33, 0xe4, 0x41, 0xe7, + 0xe2, 0xa6, 0x3c, 0xe8, 0x9f, 0xe6, 0x17, 0x57, 0x97, 0xfd, 0xbd, 0x45, 0x5b, 0xa7, 0x79, 0xfd, + 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7c, 0x74, 0x6d, 0xb7, 0x4b, 0x07, 0x00, 0x00, } diff --git a/plugins/vpp/model/nat/nat.proto b/plugins/vpp/model/nat/nat.proto index 6d5916bcd7..b51f90d0de 100644 --- a/plugins/vpp/model/nat/nat.proto +++ b/plugins/vpp/model/nat/nat.proto @@ -32,6 +32,15 @@ message Nat44Global { bool twice_nat = 4; /* Enable/disable twice NAT. */ } repeated AddressPool address_pools = 5; + + message VirtualReassembly { /* NAT virtual reassembly */ + uint32 timeout = 1; /* Reassembly timeout */ + uint32 max_reass = 2; /* Maximum number of concurrent reassemblies */ + uint32 max_frag = 3; /* Maximum number of fragments per reassembly */ + bool drop_frag = 4; /* If set to true fragments are dropped, translated otherwise*/ + } + VirtualReassembly virtual_reassembly_ipv4 = 6; + VirtualReassembly virtual_reassembly_ipv6 = 7; } /* Many-to-one (SNAT) setup */ @@ -48,16 +57,16 @@ message Nat44DNat { message DNatConfig { /* DNat configuration list. */ string label = 1; /* Unique identifier of the DNAT config. */ - message StaticMapping { /* A list of static mappings in DNAT. */ - uint32 vrf_id = 1; /* VRF (table) ID. */ + message StaticMapping { /* A list of static mappings in DNAT. */ string external_interface = 2; /* External interface may be used together with IP addresses. */ string external_ip = 3; /* External address. */ uint32 external_port = 4; /* Port (do not set for address mapping). */ message LocalIP { + uint32 vrf_id = 4; /* VRF (table) ID. */ string local_ip = 1; /* Local IP address). */ uint32 local_port = 3; /* port (do not set for address mapping). */ - uint32 probability = 2; /* Probability mode. */ + uint32 probability = 2; /* Probability mode. */ } repeated LocalIP local_ips = 5; /* List of local IP addresses. If there is more than one entry, Load ballancer is enabled. */ diff --git a/plugins/vpp/model/rpc/doc.go b/plugins/vpp/model/rpc/doc.go index 4d9dfcd657..46ce044356 100644 --- a/plugins/vpp/model/rpc/doc.go +++ b/plugins/vpp/model/rpc/doc.go @@ -12,6 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package model is the parent for packages defining various GRPC +// Package rpc is the parent for packages defining various GRPC // services generated from protobuf data models. package rpc diff --git a/plugins/vpp/model/rpc/rpc.pb.go b/plugins/vpp/model/rpc/rpc.pb.go index a160b0bb28..5286de2d2d 100644 --- a/plugins/vpp/model/rpc/rpc.pb.go +++ b/plugins/vpp/model/rpc/rpc.pb.go @@ -571,61 +571,60 @@ var _NotificationService_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("rpc.proto", fileDescriptorRpc) } var fileDescriptorRpc = []byte{ - // 894 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xe1, 0x6f, 0xe3, 0x34, - 0x14, 0xd7, 0x28, 0x77, 0x30, 0x97, 0xed, 0x86, 0xef, 0x86, 0xcc, 0x40, 0xa3, 0x4c, 0x20, 0x36, - 0x04, 0x0e, 0x4a, 0x7b, 0x20, 0x01, 0x93, 0x68, 0x97, 0xeb, 0x56, 0x6d, 0x94, 0xca, 0xed, 0x87, - 0x13, 0xf7, 0xc9, 0x4d, 0x9d, 0xce, 0x92, 0x6b, 0x87, 0xd8, 0x39, 0xad, 0x7f, 0x33, 0xff, 0x04, - 0xb2, 0x93, 0xb4, 0x4e, 0x57, 0xa4, 0x49, 0xdb, 0x87, 0x2c, 0x7e, 0xef, 0xfd, 0x7e, 0xbf, 0x3c, - 0xfb, 0x3d, 0xbf, 0x15, 0xec, 0x66, 0x69, 0x8c, 0xd3, 0x4c, 0x19, 0x05, 0x1b, 0x59, 0x1a, 0x1f, - 0xfd, 0x39, 0xe7, 0xe6, 0x36, 0x9f, 0xe2, 0x58, 0x2d, 0x02, 0xc1, 0xe7, 0xd4, 0xa8, 0xe0, 0x7d, - 0x9a, 0xfe, 0x48, 0xe7, 0x4c, 0x9a, 0x20, 0x15, 0xf9, 0x9c, 0x4b, 0x1d, 0xcc, 0x58, 0x42, 0x73, - 0x61, 0x2a, 0x33, 0x56, 0x8b, 0x85, 0x92, 0xc1, 0x42, 0xcd, 0x98, 0x08, 0x68, 0xec, 0x9e, 0x42, - 0xf3, 0xf1, 0x72, 0xd3, 0x64, 0x66, 0x9f, 0x52, 0xee, 0xdd, 0x63, 0xe5, 0xb8, 0x34, 0x2c, 0x4b, - 0x68, 0xcc, 0xb4, 0xb7, 0x2c, 0xc5, 0xaf, 0x1f, 0x2b, 0x2e, 0xc2, 0x40, 0x84, 0x4f, 0x26, 0xd6, - 0x0e, 0x44, 0xfb, 0xc9, 0xc4, 0x3a, 0x81, 0xe8, 0x3c, 0x55, 0x49, 0x24, 0x35, 0xf6, 0x79, 0x2a, - 0x39, 0x6d, 0xa4, 0x7d, 0x4a, 0xb9, 0xb7, 0x0f, 0x91, 0x13, 0x5c, 0xe6, 0x77, 0x85, 0xf1, 0xf0, - 0xf2, 0x5e, 0x3d, 0x4a, 0xd9, 0x2b, 0xc7, 0xc9, 0xbf, 0xbb, 0xa0, 0x19, 0x51, 0x43, 0x09, 0xfb, - 0x27, 0x67, 0xda, 0xc0, 0x9f, 0x41, 0xb3, 0x1b, 0xc7, 0x4c, 0xeb, 0x1b, 0xae, 0x8d, 0x46, 0xa0, - 0xd5, 0x38, 0x6d, 0x86, 0xaf, 0xb0, 0xbd, 0x05, 0x9e, 0x1f, 0x77, 0x63, 0x41, 0x7c, 0x20, 0xfc, - 0x03, 0x80, 0xc1, 0x2a, 0x4b, 0xf4, 0xca, 0xd1, 0x5a, 0xd8, 0x4b, 0x7c, 0xb0, 0x65, 0x49, 0x3c, - 0x0e, 0xfc, 0x0d, 0x34, 0x7b, 0xc9, 0x6c, 0xcc, 0xb4, 0xe6, 0x4a, 0x6a, 0x74, 0xec, 0x24, 0x3e, - 0xc7, 0xf6, 0xc2, 0x8c, 0xb9, 0x9c, 0x0b, 0x76, 0xa5, 0xd2, 0x5e, 0x3f, 0xc2, 0x25, 0x82, 0xf8, - 0x68, 0xf8, 0x8b, 0x23, 0x77, 0x73, 0x73, 0x7b, 0xcd, 0x96, 0x1a, 0x7d, 0xe5, 0xc8, 0x87, 0xf7, - 0xc9, 0xd7, 0x6c, 0x49, 0x7c, 0x24, 0xbc, 0x02, 0x2f, 0x7a, 0xc9, 0xec, 0x4d, 0x7c, 0xab, 0xfa, - 0xb9, 0x8c, 0x0d, 0x57, 0x12, 0xb5, 0x5a, 0x3b, 0xa7, 0xcd, 0xf0, 0xf8, 0x3e, 0xd9, 0x47, 0x91, - 0x4d, 0x1a, 0x8c, 0xc0, 0x5e, 0x2f, 0xe3, 0xb3, 0x39, 0x8b, 0xd4, 0x82, 0x72, 0xa9, 0xd1, 0xa9, - 0x4b, 0xe2, 0x18, 0x8b, 0x10, 0xd7, 0x02, 0x35, 0x8b, 0xd4, 0x49, 0xf0, 0x0c, 0x7c, 0xd8, 0x1f, - 0xf4, 0x34, 0x3a, 0x2b, 0x77, 0x20, 0x42, 0xdc, 0xe7, 0xd3, 0x09, 0x9d, 0x0a, 0x66, 0x17, 0x6f, - 0xa4, 0xc9, 0x96, 0xc4, 0x41, 0x60, 0x07, 0x3c, 0x7b, 0x7b, 0x61, 0x8f, 0xea, 0xfb, 0xf5, 0x87, - 0xac, 0x43, 0xb2, 0xd8, 0x8c, 0x28, 0xcf, 0x74, 0xcd, 0x22, 0x05, 0x18, 0xfe, 0x0a, 0x3e, 0x19, - 0x1b, 0x6a, 0x78, 0x4c, 0x54, 0x6e, 0x98, 0x46, 0xa1, 0x23, 0x7f, 0x86, 0x45, 0x1b, 0xfb, 0x7e, - 0xec, 0x5e, 0xa4, 0x86, 0x85, 0xaf, 0x01, 0xe8, 0x66, 0xa9, 0xcd, 0x81, 0x33, 0x8d, 0xda, 0x55, - 0x8a, 0x6d, 0xdc, 0xcd, 0xd2, 0x22, 0xc5, 0x32, 0xbc, 0x24, 0x1e, 0x10, 0x4e, 0x00, 0x1c, 0x65, - 0xea, 0x6e, 0xd9, 0xcd, 0x52, 0xaf, 0x47, 0x3a, 0x8e, 0xfe, 0x8d, 0xa5, 0xdf, 0x8f, 0xae, 0x7b, - 0xc4, 0xb6, 0x17, 0xd9, 0xc2, 0x87, 0x11, 0xd8, 0xaf, 0xbc, 0x84, 0xca, 0x39, 0xd3, 0xe8, 0xb5, - 0x53, 0xfc, 0xd2, 0x57, 0x2c, 0x22, 0xd8, 0xbd, 0x9c, 0xd2, 0x06, 0x07, 0xfe, 0x00, 0x76, 0x6f, - 0x3a, 0x7d, 0x46, 0x4d, 0x9e, 0x31, 0xf4, 0xbb, 0xab, 0xfc, 0x3e, 0x16, 0x1d, 0xbc, 0x72, 0x6a, - 0xb2, 0x06, 0xc0, 0x09, 0x38, 0xec, 0xa6, 0xa9, 0xe0, 0x31, 0xb5, 0x25, 0x1f, 0xd2, 0x05, 0xd3, - 0xa9, 0xdb, 0xcc, 0x79, 0x55, 0x82, 0x0e, 0xee, 0xa6, 0xe9, 0x3a, 0x50, 0xb3, 0xc8, 0x76, 0x32, - 0x3c, 0x03, 0x1f, 0x8f, 0x8d, 0x24, 0xb9, 0x60, 0x1a, 0xf5, 0x9d, 0xd0, 0x1e, 0xb6, 0x53, 0x64, - 0x3c, 0x19, 0x62, 0xeb, 0x25, 0xab, 0x30, 0xc4, 0x60, 0x77, 0x48, 0xcd, 0xa5, 0x50, 0x53, 0x2a, - 0xd0, 0xa5, 0x4b, 0xf7, 0x00, 0xdb, 0x01, 0x36, 0xa4, 0xa6, 0xd3, 0x29, 0xfc, 0x64, 0x0d, 0x81, - 0x01, 0x78, 0x16, 0x0d, 0xbb, 0x13, 0x8d, 0xae, 0xca, 0xeb, 0xb4, 0xc2, 0x46, 0x43, 0x6a, 0xb0, - 0xfd, 0x73, 0xa1, 0x64, 0xc2, 0xe7, 0xa4, 0xc0, 0xc1, 0xbf, 0xc0, 0x8b, 0x1b, 0x3b, 0x37, 0xbc, - 0x42, 0x8d, 0x1c, 0xf5, 0x5b, 0xff, 0x32, 0x6f, 0x40, 0xbc, 0x1b, 0xbd, 0xc9, 0x86, 0x37, 0xa5, - 0xa0, 0xd7, 0x38, 0x7f, 0x3b, 0xc1, 0x13, 0x5b, 0x27, 0x17, 0x2a, 0x7a, 0x6c, 0x0d, 0x58, 0x77, - 0xd1, 0x26, 0x15, 0x9e, 0x83, 0xa6, 0x73, 0x95, 0xcd, 0xfb, 0xce, 0x29, 0x7d, 0xb1, 0xa1, 0x54, - 0xeb, 0x60, 0x1f, 0x7f, 0xf2, 0x1d, 0x78, 0x39, 0x54, 0x86, 0x27, 0x65, 0x0d, 0xaa, 0xa1, 0x77, - 0x00, 0x1a, 0x7c, 0x76, 0x87, 0x76, 0x5a, 0x3b, 0xa7, 0x7b, 0xc4, 0x2e, 0x4f, 0xf6, 0x40, 0x73, - 0x94, 0x1b, 0xc2, 0x74, 0xaa, 0xa4, 0x66, 0xd6, 0x8c, 0x98, 0x58, 0x99, 0x07, 0x60, 0x9f, 0x30, - 0xbd, 0x94, 0xf1, 0xca, 0x93, 0x80, 0x43, 0x5f, 0x58, 0x57, 0x01, 0x88, 0xc0, 0x47, 0x92, 0xdd, - 0x99, 0xc1, 0x4a, 0xbe, 0x32, 0x61, 0x1b, 0x34, 0xe4, 0x20, 0x41, 0x1f, 0xb8, 0x22, 0x7e, 0xbd, - 0x75, 0x54, 0xd6, 0x72, 0xb5, 0xe8, 0x90, 0x83, 0x4f, 0xed, 0xb4, 0xbe, 0xb8, 0xb5, 0xdd, 0x3b, - 0x66, 0xd9, 0x7b, 0x1e, 0x33, 0x78, 0x06, 0x1a, 0xa3, 0xdc, 0xc0, 0x03, 0x6c, 0x7f, 0xff, 0x78, - 0xc3, 0xfc, 0xa8, 0xf0, 0x78, 0x1b, 0xb1, 0xd0, 0x88, 0x89, 0xff, 0x85, 0x7a, 0x9b, 0x0c, 0xa3, - 0xe2, 0x53, 0xc5, 0x46, 0xab, 0x4f, 0x05, 0xe0, 0x79, 0xe1, 0xd8, 0x22, 0xf1, 0xd2, 0x79, 0xea, - 0x07, 0x13, 0x4e, 0xea, 0x27, 0x5e, 0xe9, 0x9c, 0x83, 0xc6, 0x25, 0x33, 0x10, 0x39, 0xca, 0x96, - 0x92, 0x1c, 0x1d, 0xdd, 0x8b, 0xac, 0xce, 0xf4, 0xa7, 0x9d, 0xe9, 0x73, 0xf7, 0xcf, 0xab, 0xfd, - 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x9b, 0x2d, 0xbf, 0xc6, 0xf2, 0x09, 0x00, 0x00, + // 879 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0x51, 0x6f, 0x23, 0x35, + 0x10, 0x56, 0x09, 0x77, 0xd0, 0x09, 0xed, 0x15, 0xdf, 0x15, 0x99, 0x82, 0x4a, 0xa9, 0x40, 0xb4, + 0x08, 0xbc, 0x68, 0x93, 0x03, 0x41, 0xa9, 0xc4, 0xa6, 0x7b, 0x69, 0xa3, 0x56, 0x21, 0x72, 0xf2, + 0x80, 0xe0, 0xc9, 0xd9, 0x38, 0xa9, 0x25, 0xd7, 0xbb, 0xac, 0xbd, 0xa7, 0xe6, 0x37, 0xf3, 0x27, + 0x90, 0xbd, 0x9b, 0xc4, 0x9b, 0xe6, 0xa4, 0x6b, 0x1f, 0xdc, 0xb5, 0x67, 0xbe, 0xef, 0xdb, 0xf1, + 0xcc, 0xec, 0x34, 0xb0, 0x9d, 0x67, 0x09, 0xc9, 0xf2, 0xd4, 0xa4, 0xa8, 0x91, 0x67, 0xc9, 0xc1, + 0xd9, 0x4c, 0x98, 0xdb, 0x62, 0x4c, 0x92, 0xf4, 0x2e, 0x90, 0x62, 0xc6, 0x4c, 0x1a, 0xbc, 0xcd, + 0xb2, 0x1f, 0xd9, 0x8c, 0x2b, 0x13, 0x64, 0xb2, 0x98, 0x09, 0xa5, 0xad, 0x25, 0xb8, 0x4b, 0x27, + 0x5c, 0x06, 0x2c, 0x71, 0xab, 0x54, 0x78, 0x2c, 0x79, 0x3c, 0x9d, 0xd8, 0x55, 0x91, 0x7b, 0x8f, + 0x23, 0x0b, 0x65, 0x78, 0x3e, 0x65, 0x09, 0xd7, 0xde, 0xb6, 0x92, 0xfa, 0xf5, 0x71, 0x52, 0x32, + 0x0c, 0x64, 0xf8, 0x44, 0x6a, 0x2b, 0x90, 0xad, 0x27, 0x52, 0xdb, 0x81, 0x6c, 0x3f, 0x2d, 0x71, + 0x8a, 0x19, 0xbb, 0x9e, 0x46, 0xd6, 0x46, 0xd9, 0x55, 0x91, 0xaf, 0xdf, 0x87, 0x2c, 0x85, 0x2a, + 0xee, 0xdf, 0x23, 0xef, 0x67, 0x8f, 0x15, 0xf3, 0xd2, 0x77, 0xfc, 0xdf, 0x36, 0x34, 0x63, 0x66, + 0x18, 0xe5, 0xff, 0x16, 0x5c, 0x1b, 0xf4, 0x33, 0x34, 0xa3, 0x24, 0xe1, 0x5a, 0xdf, 0x08, 0x6d, + 0x34, 0x86, 0xa3, 0xc6, 0x49, 0x33, 0x7c, 0x45, 0x6c, 0xb7, 0x79, 0x76, 0x12, 0x25, 0x92, 0xfa, + 0x40, 0xf4, 0x07, 0x40, 0x6f, 0x19, 0x18, 0x7e, 0xe5, 0x68, 0x47, 0xc4, 0x8b, 0xb5, 0xb7, 0x61, + 0x4b, 0x3d, 0x0e, 0x3a, 0x83, 0x66, 0x67, 0x3a, 0x19, 0x72, 0xad, 0x45, 0xaa, 0x34, 0x3e, 0x74, + 0x12, 0x9f, 0x13, 0xdb, 0xaa, 0x43, 0xa1, 0x66, 0x92, 0x5f, 0xa5, 0x59, 0xa7, 0x1b, 0x93, 0x0a, + 0x41, 0x7d, 0x34, 0xfa, 0xc5, 0x91, 0xa3, 0xc2, 0xdc, 0x5e, 0xf3, 0xb9, 0xc6, 0x5f, 0x39, 0xf2, + 0xfe, 0x43, 0xf2, 0x35, 0x9f, 0x53, 0x1f, 0x89, 0xae, 0xe0, 0x45, 0x67, 0x3a, 0x79, 0x93, 0xdc, + 0xa6, 0xdd, 0x42, 0x25, 0x46, 0xa4, 0x0a, 0x1f, 0x1d, 0x6d, 0x9d, 0x34, 0xc3, 0xc3, 0x87, 0x64, + 0x1f, 0x45, 0xd7, 0x69, 0x28, 0x86, 0x9d, 0x4e, 0x2e, 0x26, 0x33, 0x1e, 0xa7, 0x77, 0x4c, 0x28, + 0x8d, 0x4f, 0x5c, 0x10, 0x87, 0x44, 0x86, 0xa4, 0xe6, 0xa8, 0x9d, 0x68, 0x9d, 0x84, 0x4e, 0xe1, + 0xc3, 0x6e, 0xaf, 0xa3, 0xf1, 0x69, 0x75, 0x03, 0x19, 0x92, 0xae, 0x18, 0x8f, 0xd8, 0x58, 0x72, + 0xbb, 0x79, 0xa3, 0x4c, 0x3e, 0xa7, 0x0e, 0x82, 0xda, 0xf0, 0xec, 0xaf, 0x0b, 0x9b, 0xaa, 0xef, + 0x57, 0x2f, 0xb2, 0x06, 0xc5, 0x13, 0x33, 0x60, 0x22, 0xd7, 0xb5, 0x13, 0x2d, 0xc1, 0xe8, 0x37, + 0xf8, 0x64, 0x68, 0x98, 0x11, 0x09, 0x4d, 0x0b, 0xc3, 0x35, 0x0e, 0x1d, 0xf9, 0x33, 0x22, 0x5b, + 0xc4, 0xb7, 0x13, 0xf7, 0xa0, 0x35, 0x2c, 0x7a, 0x0d, 0x10, 0xe5, 0x99, 0x8d, 0x41, 0x70, 0x8d, + 0x5b, 0x8b, 0x10, 0x5b, 0x24, 0xca, 0xb3, 0x32, 0xc4, 0xca, 0x3d, 0xa7, 0x1e, 0x10, 0x8d, 0x00, + 0x0d, 0xf2, 0xf4, 0x7e, 0x1e, 0xe5, 0x99, 0xd7, 0x23, 0x6d, 0x47, 0xff, 0xc6, 0xd2, 0x1f, 0x7a, + 0x57, 0x3d, 0x62, 0xdb, 0x8b, 0x6e, 0xe0, 0xa3, 0x18, 0x76, 0x17, 0x56, 0xca, 0xd4, 0x8c, 0x6b, + 0xfc, 0xda, 0x29, 0x7e, 0xe9, 0x2b, 0x96, 0x1e, 0xe2, 0x1e, 0x4e, 0x69, 0x8d, 0x83, 0x7e, 0x80, + 0xed, 0x9b, 0x76, 0x97, 0x33, 0x53, 0xe4, 0x1c, 0xff, 0xee, 0x2a, 0xbf, 0x4b, 0x64, 0x9b, 0x2c, + 0x8d, 0x9a, 0xae, 0x00, 0x68, 0x04, 0xfb, 0x51, 0x96, 0x49, 0x91, 0x30, 0x5b, 0xf2, 0x3e, 0xbb, + 0xe3, 0x3a, 0x73, 0x97, 0x39, 0x5f, 0x94, 0xa0, 0x4d, 0xa2, 0x2c, 0x5b, 0x39, 0x6a, 0x27, 0xba, + 0x99, 0x8c, 0x4e, 0xe1, 0xe3, 0xa1, 0x51, 0xb4, 0x90, 0x5c, 0xe3, 0xae, 0x13, 0xda, 0x21, 0x76, + 0x56, 0x0c, 0x47, 0x7d, 0x62, 0xad, 0x74, 0xe9, 0x46, 0x04, 0xb6, 0xfb, 0xcc, 0x5c, 0xca, 0x74, + 0xcc, 0x24, 0xbe, 0x74, 0xe1, 0xee, 0x11, 0x3b, 0x94, 0xfa, 0xcc, 0xb4, 0xdb, 0xa5, 0x9d, 0xae, + 0x20, 0x28, 0x80, 0x67, 0x71, 0x3f, 0x1a, 0x69, 0x7c, 0x55, 0x7d, 0x4e, 0x4b, 0x6c, 0xdc, 0x67, + 0x86, 0xd8, 0x3f, 0x17, 0xa9, 0x9a, 0x8a, 0x19, 0x2d, 0x71, 0xe8, 0x4f, 0x78, 0x71, 0x63, 0x47, + 0x85, 0x57, 0xa8, 0x81, 0xa3, 0x7e, 0xeb, 0x7f, 0xcc, 0x6b, 0x10, 0xef, 0x8b, 0x5e, 0x67, 0xa3, + 0x9b, 0x4a, 0xd0, 0x6b, 0x9c, 0xbf, 0x9d, 0xe0, 0xb1, 0xad, 0x93, 0x73, 0x95, 0x3d, 0xb6, 0x02, + 0xac, 0xba, 0x68, 0x9d, 0x8a, 0xce, 0xa1, 0xe9, 0x4c, 0x55, 0xf3, 0xfe, 0xe3, 0x94, 0xbe, 0x58, + 0x53, 0xaa, 0x75, 0xb0, 0x8f, 0x3f, 0xfe, 0x0e, 0x5e, 0xf6, 0x53, 0x23, 0xa6, 0x55, 0x0d, 0x16, + 0x43, 0x6f, 0x0f, 0x1a, 0x62, 0x72, 0x8f, 0xb7, 0x8e, 0xb6, 0x4e, 0x76, 0xa8, 0xdd, 0x1e, 0xef, + 0x40, 0x73, 0x50, 0x18, 0xca, 0x75, 0x96, 0x2a, 0xcd, 0xed, 0x31, 0xe6, 0x72, 0x79, 0xdc, 0x83, + 0x5d, 0xca, 0xf5, 0x5c, 0x25, 0x4b, 0xcb, 0x14, 0xf6, 0x7d, 0x61, 0xbd, 0x70, 0x20, 0x0c, 0x1f, + 0x29, 0x7e, 0x6f, 0x7a, 0x4b, 0xf9, 0xc5, 0x11, 0xb5, 0xa0, 0xa1, 0x7a, 0x53, 0xfc, 0x81, 0x2b, + 0xe2, 0xd7, 0x1b, 0x47, 0x65, 0x2d, 0x56, 0x8b, 0x0e, 0x05, 0x7c, 0x6a, 0xa7, 0xf5, 0xc5, 0xad, + 0xed, 0xde, 0x21, 0xcf, 0xdf, 0x8a, 0x84, 0xa3, 0x53, 0x68, 0x0c, 0x0a, 0x83, 0xf6, 0x88, 0xfd, + 0x55, 0xe1, 0x0d, 0xf3, 0x83, 0xd2, 0xe2, 0x5d, 0xc4, 0x42, 0x63, 0x2e, 0xdf, 0x09, 0xf5, 0x2e, + 0x19, 0xc6, 0xe5, 0xab, 0xca, 0x8b, 0x2e, 0x5e, 0x15, 0xc0, 0xf3, 0xd2, 0xb0, 0x41, 0xe2, 0xa5, + 0xb3, 0xd4, 0x13, 0x13, 0x8e, 0xea, 0x19, 0x5f, 0xe8, 0x9c, 0x43, 0xe3, 0x92, 0x1b, 0x84, 0x1d, + 0x65, 0x43, 0x49, 0x0e, 0x0e, 0x1e, 0x78, 0x96, 0x39, 0xfd, 0x69, 0x6b, 0xfc, 0xdc, 0xfd, 0xf3, + 0x6a, 0xfd, 0x1f, 0x00, 0x00, 0xff, 0xff, 0x78, 0x23, 0x1c, 0x57, 0x48, 0x09, 0x00, 0x00, } diff --git a/plugins/vpp/model/stn/keys_agent_stn.go b/plugins/vpp/model/stn/keys_agent_stn.go index 135ee59358..d3e1e90d8c 100644 --- a/plugins/vpp/model/stn/keys_agent_stn.go +++ b/plugins/vpp/model/stn/keys_agent_stn.go @@ -14,16 +14,11 @@ package stn -// StnRulesPrefix stn key/ -const StnRulesPrefix = "vpp/config/v1/stn/rules/" - -// KeyPrefix returns the prefix used in ETCD to store vpp STN config -func KeyPrefix() string { - return StnRulesPrefix -} +// Prefix stn key/ +const Prefix = "vpp/config/v1/stn/rules/" // Key returns the prefix used in ETCD to store vpp STN config // of a particular rule in selected vpp instance. func Key(ruleName string) string { - return StnRulesPrefix + ruleName + return Prefix + ruleName } diff --git a/plugins/vpp/options.go b/plugins/vpp/options.go new file mode 100644 index 0000000000..2cfc09bea5 --- /dev/null +++ b/plugins/vpp/options.go @@ -0,0 +1,58 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vpp + +import ( + "github.com/ligato/cn-infra/config" + "github.com/ligato/cn-infra/health/statuscheck" + "github.com/ligato/cn-infra/logging" + "github.com/ligato/cn-infra/servicelabel" + "github.com/ligato/vpp-agent/plugins/govppmux" +) + +// NewPlugin creates a new Plugin with the provides Options +func NewPlugin(opts ...Option) *Plugin { + p := &Plugin{} + + p.PluginName = "vpp" + p.StatusCheck = &statuscheck.DefaultPlugin + p.ServiceLabel = &servicelabel.DefaultPlugin + p.GoVppmux = &govppmux.DefaultPlugin + + for _, o := range opts { + o(p) + } + + if p.Log == nil { + p.Log = logging.ForPlugin(p.String()) + } + if p.Cfg == nil { + p.Cfg = config.ForPlugin(p.String(), + config.WithCustomizedFlag(config.FlagName(p.String()), "vpp-plugin.conf"), + ) + } + + return p +} + +// Option is a function that can be used in NewPlugin to customize Plugin. +type Option func(*Plugin) + +// UseDeps returns Option that can inject custom dependencies. +func UseDeps(f func(*Deps)) Option { + return func(p *Plugin) { + f(&p.Deps) + } +} diff --git a/plugins/vpp/plugin_impl_vpp.go b/plugins/vpp/plugin_impl_vpp.go index e92593c490..6951e19c9c 100644 --- a/plugins/vpp/plugin_impl_vpp.go +++ b/plugins/vpp/plugin_impl_vpp.go @@ -21,9 +21,10 @@ import ( govppapi "git.fd.io/govpp.git/api" "github.com/ligato/cn-infra/datasync" - "github.com/ligato/cn-infra/flavors/local" - "github.com/ligato/cn-infra/logging/measure" + "github.com/ligato/cn-infra/health/statuscheck" + "github.com/ligato/cn-infra/infra" "github.com/ligato/cn-infra/messaging" + "github.com/ligato/cn-infra/servicelabel" "github.com/ligato/cn-infra/utils/safeclose" "github.com/ligato/vpp-agent/idxvpp" "github.com/ligato/vpp-agent/idxvpp/nametoidx" @@ -44,7 +45,6 @@ import ( "github.com/ligato/vpp-agent/plugins/vpp/model/nat" "github.com/ligato/vpp-agent/plugins/vpp/rpc" "github.com/ligato/vpp-agent/plugins/vpp/srplugin" - "github.com/ligato/vpp-agent/plugins/vpp/srplugin/vppcalls" "github.com/namsral/flag" ) @@ -57,11 +57,11 @@ var ( var ( // noopWriter (no operation writer) helps avoiding NIL pointer based segmentation fault. // It is used as default if some dependency was not injected. - noopWriter = &datasync.CompositeKVProtoWriter{Adapters: []datasync.KeyProtoValWriter{}} + noopWriter = datasync.KVProtoWriters{} // noopWatcher (no operation watcher) helps avoiding NIL pointer based segmentation fault. // It is used as default if some dependency was not injected. - noopWatcher = &datasync.CompositeKVProtoWatcher{Adapters: []datasync.KeyValProtoWatcher{}} + noopWatcher = datasync.KVProtoWatchers{} ) // VPP resync strategy. Can be set in vpp-plugin.conf. If no strategy is set, the default behavior is defined by 'fullResync' @@ -93,6 +93,7 @@ type Plugin struct { arpConfigurator *l3plugin.ArpConfigurator proxyArpConfigurator *l3plugin.ProxyArpConfigurator routeConfigurator *l3plugin.RouteConfigurator + ipNeighConfigurator *l3plugin.IPNeighConfigurator appNsConfigurator *l4plugin.AppNsConfigurator srv6Configurator *srplugin.SRv6Configurator @@ -101,11 +102,10 @@ type Plugin struct { bdStateUpdater *l2plugin.BridgeDomainStateUpdater // Shared indexes - swIfIndexes ifaceidx.SwIfIndexRW - linuxIfIndexes ifaceLinux.LinuxIfIndex - bdIndexes l2idx.BDIndexRW - errorIndexes idxvpp.NameToIdxRW - errorIdxSeq uint32 + swIfIndexes ifaceidx.SwIfIndexRW + bdIndexes l2idx.BDIndexRW + errorIndexes idxvpp.NameToIdxRW + errorIdxSeq uint32 // Channels (watch, notification, ...) which should be closed ifStateChan chan *intf.InterfaceNotification @@ -129,9 +129,9 @@ type Plugin struct { omittedPrefixes []string // list of keys which won't be resynced // From config file + enableStopwatch bool ifMtu uint32 resyncStrategy string - enableStopwatch bool // Common statusCheckReg bool @@ -142,30 +142,32 @@ type Plugin struct { // Deps groups injected dependencies of plugin so that they do not mix with // other plugin fieldsMtu. type Deps struct { - // inject all below - local.PluginInfraDeps + infra.PluginDeps + StatusCheck statuscheck.PluginStatusWriter + ServiceLabel servicelabel.ReaderAPI Publish datasync.KeyProtoValWriter PublishStatistics datasync.KeyProtoValWriter - Watch datasync.KeyValProtoWatcher + Watcher datasync.KeyValProtoWatcher IfStatePub datasync.KeyProtoValWriter GoVppmux govppmux.API - Linux linuxpluginAPI + Linux LinuxPluginAPI GRPCSvc rpc.GRPCService DataSyncs map[string]datasync.KeyProtoValWriter WatchEventsMutex *sync.Mutex } -// PluginConfig holds the vpp-plugin configuration. -type PluginConfig struct { +// Config holds the vpp-plugin configuration. +type Config struct { Mtu uint32 `json:"mtu"` Stopwatch bool `json:"stopwatch"` Strategy string `json:"strategy"` StatusPublishers []string `json:"status-publishers"` } -type linuxpluginAPI interface { +// LinuxPluginAPI is interface for Linux plugin. +type LinuxPluginAPI interface { // GetLinuxIfIndexes gives access to mapping of logical names (used in ETCD configuration) to corresponding Linux // interface indexes. This mapping is especially helpful for plugins that need to watch for newly added or deleted // Linux interfaces. @@ -250,12 +252,12 @@ func (plugin *Plugin) DumpNat44DNat() (*nat.Nat44DNat, error) { return plugin.natConfigurator.DumpNatDNat() } -// GetIPSecSAIndexes +// GetIPSecSAIndexes returns SA indexes. func (plugin *Plugin) GetIPSecSAIndexes() idxvpp.NameToIdx { return plugin.ipSecConfigurator.GetSaIndexes() } -// GetIPSecSPDIndexes +// GetIPSecSPDIndexes returns SPD indexes. func (plugin *Plugin) GetIPSecSPDIndexes() ipsecidx.SPDIndex { return plugin.ipSecConfigurator.GetSpdIndexes() } @@ -263,7 +265,6 @@ func (plugin *Plugin) GetIPSecSPDIndexes() ipsecidx.SPDIndex { // Init gets handlers for ETCD and Messaging and delegates them to ifConfigurator & ifStateUpdater. func (plugin *Plugin) Init() error { plugin.Log.Debug("Initializing default plugins") - flag.Parse() // Read config file and set all related fields plugin.fromConfigFile() @@ -363,11 +364,11 @@ func (plugin *Plugin) Close() error { // Configurators plugin.aclConfigurator, plugin.ifConfigurator, plugin.bfdConfigurator, plugin.natConfigurator, plugin.stnConfigurator, plugin.ipSecConfigurator, plugin.bdConfigurator, plugin.fibConfigurator, plugin.xcConfigurator, plugin.arpConfigurator, - plugin.proxyArpConfigurator, plugin.routeConfigurator, plugin.appNsConfigurator, + plugin.proxyArpConfigurator, plugin.routeConfigurator, plugin.ipNeighConfigurator, plugin.appNsConfigurator, // State updaters plugin.ifStateUpdater, plugin.bdStateUpdater, // Channels - plugin.ifStateChan, plugin.ifVppNotifChan, plugin.ifIdxWatchCh, plugin.bdStateChan, plugin.bdVppNotifChan, + plugin.ifStateChan, plugin.ifVppNotifChan, plugin.bdStateChan, plugin.bdVppNotifChan, plugin.bdIdxWatchCh, plugin.linuxIfIdxWatchCh, plugin.resyncStatusChan, plugin.resyncConfigChan, plugin.changeChan, plugin.errorChannel, // Registrations @@ -403,22 +404,15 @@ func (plugin *Plugin) fixNilPointers() { plugin.Deps.IfStatePub = noopWriter plugin.Log.Debug("setting default noop writer for IfStatePub dependency") } - if plugin.Deps.Watch == nil { - plugin.Deps.Watch = noopWatcher - plugin.Log.Debug("setting default noop watcher for Watch dependency") + if plugin.Deps.Watcher == nil { + plugin.Deps.Watcher = noopWatcher + plugin.Log.Debug("setting default noop watcher for Watcher dependency") } } func (plugin *Plugin) initIF(ctx context.Context) error { plugin.Log.Infof("Init interface plugin") - // Get pointer to the map with Linux interface indices. - if plugin.Linux != nil { - plugin.linuxIfIndexes = plugin.Linux.GetLinuxIfIndexes() - } else { - plugin.linuxIfIndexes = nil - } - // Interface configurator plugin.ifVppNotifChan = make(chan govppapi.Message, 100) plugin.ifConfigurator = &ifplugin.InterfaceConfigurator{} @@ -434,7 +428,7 @@ func (plugin *Plugin) initIF(ctx context.Context) error { } // Interface state updater plugin.ifStateUpdater = &ifplugin.InterfaceStateUpdater{} - plugin.ifStateUpdater.Init(plugin.Log, plugin.GoVppmux, ctx, plugin.swIfIndexes, plugin.ifVppNotifChan, func(state *intf.InterfaceNotification) { + plugin.ifStateUpdater.Init(ctx, plugin.Log, plugin.GoVppmux, plugin.swIfIndexes, plugin.ifVppNotifChan, func(state *intf.InterfaceNotification) { select { case plugin.ifStateChan <- state: // OK @@ -513,7 +507,7 @@ func (plugin *Plugin) initL2(ctx context.Context) error { // Bridge domain state updater plugin.bdStateUpdater = &l2plugin.BridgeDomainStateUpdater{} - if err := plugin.bdStateUpdater.Init(plugin.Log, plugin.GoVppmux, ctx, plugin.bdIndexes, plugin.swIfIndexes, plugin.bdVppNotifChan, + if err := plugin.bdStateUpdater.Init(ctx, plugin.Log, plugin.GoVppmux, plugin.bdIndexes, plugin.swIfIndexes, plugin.bdVppNotifChan, func(state *l2plugin.BridgeDomainStateNotification) { select { case plugin.bdStateChan <- state: @@ -527,8 +521,7 @@ func (plugin *Plugin) initL2(ctx context.Context) error { // L2 FIB configurator plugin.fibConfigurator = &l2plugin.FIBConfigurator{} - err = plugin.fibConfigurator.Init(plugin.Log, plugin.GoVppmux, plugin.swIfIndexes, plugin.bdIndexes, plugin.enableStopwatch) - if err != nil { + if err := plugin.fibConfigurator.Init(plugin.Log, plugin.GoVppmux, plugin.swIfIndexes, plugin.bdIndexes, plugin.enableStopwatch); err != nil { return err } plugin.Log.Debug("fibConfigurator Initialized") @@ -567,13 +560,20 @@ func (plugin *Plugin) initL3(ctx context.Context) error { } plugin.Log.Debug("routeConfigurator Initialized") + // IP neighbor configurator + plugin.ipNeighConfigurator = &l3plugin.IPNeighConfigurator{} + if err := plugin.ipNeighConfigurator.Init(plugin.Log, plugin.GoVppmux, plugin.enableStopwatch); err != nil { + return err + } + plugin.Log.Debug("ipNeighConfigurator Initialized") + return nil } func (plugin *Plugin) initL4(ctx context.Context) error { plugin.Log.Infof("Init L4 plugin") - // Application namespace conifgurator + // Application namespace configurator plugin.appNsConfigurator = &l4plugin.AppNsConfigurator{} if err := plugin.appNsConfigurator.Init(plugin.Log, plugin.GoVppmux, plugin.swIfIndexes, plugin.enableStopwatch); err != nil { return err @@ -586,22 +586,9 @@ func (plugin *Plugin) initL4(ctx context.Context) error { func (plugin *Plugin) initSR(ctx context.Context) (err error) { plugin.Log.Infof("Init SR plugin") - // logger - srLogger := plugin.Log.NewLogger("-sr-plugin") - - var stopwatch *measure.Stopwatch - if plugin.enableStopwatch { - stopwatch = measure.NewStopwatch("SRConfigurator", srLogger) - } - // configuring configurators - plugin.srv6Configurator = &srplugin.SRv6Configurator{ - Log: srLogger, - GoVppmux: plugin.GoVppmux, - SwIfIndexes: plugin.swIfIndexes, - VppCalls: vppcalls.NewSRv6Calls(srLogger, stopwatch), - } - // Init SR plugin - if err := plugin.srv6Configurator.Init(); err != nil { + // Init SR configurator + plugin.srv6Configurator = &srplugin.SRv6Configurator{} + if err := plugin.srv6Configurator.Init(plugin.Log, plugin.GoVppmux, plugin.swIfIndexes, plugin.enableStopwatch, nil); err != nil { return err } @@ -625,14 +612,14 @@ func (plugin *Plugin) fromConfigFile() { return } if config != nil { - publishers := &datasync.CompositeKVProtoWriter{} + publishers := datasync.KVProtoWriters{} for _, pub := range config.StatusPublishers { db, found := plugin.Deps.DataSyncs[pub] if !found { plugin.Log.Warnf("Unknown status publisher %q from config", pub) continue } - publishers.Adapters = append(publishers.Adapters, db) + publishers = append(publishers, db) plugin.Log.Infof("Added status publisher %q from config", pub) } plugin.Deps.PublishStatistics = publishers @@ -640,11 +627,12 @@ func (plugin *Plugin) fromConfigFile() { plugin.ifMtu = config.Mtu plugin.Log.Infof("Default MTU set to %v", plugin.ifMtu) } - plugin.enableStopwatch = config.Stopwatch - if plugin.enableStopwatch { - plugin.Log.Infof("stopwatch enabled for %v", plugin.PluginName) + + if config.Stopwatch { + plugin.enableStopwatch = true + plugin.Log.Info("stopwatch enabled for VPP plugins") } else { - plugin.Log.Infof("stopwatch disabled for %v", plugin.PluginName) + plugin.Log.Info("stopwatch disabled VPP plugins") } // return skip (if set) or value from config plugin.resyncStrategy = plugin.resolveResyncStrategy(config.Strategy) @@ -657,10 +645,10 @@ func (plugin *Plugin) fromConfigFile() { } } -func (plugin *Plugin) retrieveVPPConfig() (*PluginConfig, error) { - config := &PluginConfig{} +func (plugin *Plugin) retrieveVPPConfig() (*Config, error) { + config := &Config{} - found, err := plugin.PluginConfig.GetValue(config) + found, err := plugin.Cfg.LoadValue(config) if err != nil { return nil, err } else if !found { diff --git a/plugins/vpp/rpc/options.go b/plugins/vpp/rpc/options.go new file mode 100644 index 0000000000..98588d57c0 --- /dev/null +++ b/plugins/vpp/rpc/options.go @@ -0,0 +1,34 @@ +package rpc + +import ( + "github.com/ligato/cn-infra/rpc/grpc" +) + +// DefaultPlugin is default instance of Plugin +var DefaultPlugin = *NewPlugin() + +// NewPlugin creates a new Plugin with the provides Options +func NewPlugin(opts ...Option) *Plugin { + p := &Plugin{} + + p.PluginName = "vpp-grpc" + p.GRPCServer = &grpc.DefaultPlugin + + for _, o := range opts { + o(p) + } + + p.PluginDeps.Setup() + + return p +} + +// Option is a function that acts on a Plugin to inject Dependencies or configuration +type Option func(*Plugin) + +// UseDeps returns Option that can inject custom dependencies. +func UseDeps(cb func(*Deps)) Option { + return func(p *Plugin) { + cb(&p.Deps) + } +} diff --git a/plugins/vpp/rpc/services.go b/plugins/vpp/rpc/services.go index 949dbee4d1..7c11b9d5d6 100644 --- a/plugins/vpp/rpc/services.go +++ b/plugins/vpp/rpc/services.go @@ -19,7 +19,7 @@ package rpc import ( "fmt" - "github.com/ligato/cn-infra/flavors/local" + "github.com/ligato/cn-infra/infra" "github.com/ligato/cn-infra/logging" "github.com/ligato/cn-infra/rpc/grpc" "github.com/ligato/vpp-agent/clientv1/linux" @@ -29,9 +29,9 @@ import ( "golang.org/x/net/context" ) -// GRPCSvcPlugin registers VPP GRPC services in *grpc.Server. -type GRPCSvcPlugin struct { - Deps GRPCSvcPluginDeps +// Plugin registers VPP GRPC services in *grpc.Server. +type Plugin struct { + Deps // Services changeVppSvc ChangeVppSvc @@ -39,9 +39,9 @@ type GRPCSvcPlugin struct { notifSvc NotificationSvc } -// GRPCSvcPluginDeps - dependencies of GRPCSvcPlugin -type GRPCSvcPluginDeps struct { - local.PluginLogDeps +// Deps - dependencies of Plugin +type Deps struct { + infra.PluginDeps GRPCServer grpc.Server } @@ -56,24 +56,24 @@ type ResyncVppSvc struct { } // Init sets plugin child loggers for changeVppSvc & resyncVppSvc. -func (plugin *GRPCSvcPlugin) Init() error { +func (plugin *Plugin) Init() error { // Data change - plugin.changeVppSvc.log = plugin.Deps.Log.NewLogger("changeVppSvc") + plugin.changeVppSvc.log = plugin.Log.NewLogger("changeVppSvc") // Data resync - plugin.resyncVppSvc.log = plugin.Deps.Log.NewLogger("resyncVppSvc") + plugin.resyncVppSvc.log = plugin.Log.NewLogger("resyncVppSvc") // Notification service (represents GRPC client) - plugin.notifSvc.log = plugin.Deps.Log.NewLogger("notifSvc") + plugin.notifSvc.log = plugin.Log.NewLogger("notifSvc") return nil } // AfterInit registers all GRPC services in vppscv package // (be sure that defaultvppplugins are completely initialized). -func (plugin *GRPCSvcPlugin) AfterInit() error { - if plugin.Deps.GRPCServer == nil { +func (plugin *Plugin) AfterInit() error { + if plugin.GRPCServer == nil { return nil } - grpcServer := plugin.Deps.GRPCServer.GetServer() + grpcServer := plugin.GRPCServer.GetServer() if grpcServer != nil { rpc.RegisterDataChangeServiceServer(grpcServer, &plugin.changeVppSvc) rpc.RegisterDataResyncServiceServer(grpcServer, &plugin.resyncVppSvc) @@ -84,12 +84,12 @@ func (plugin *GRPCSvcPlugin) AfterInit() error { } // Close does nothing. -func (plugin *GRPCSvcPlugin) Close() error { +func (plugin *Plugin) Close() error { return nil } // UpdateNotifications stores new notification data -func (plugin *GRPCSvcPlugin) UpdateNotifications(ctx context.Context, notification *interfaces.InterfaceNotification) { +func (plugin *Plugin) UpdateNotifications(ctx context.Context, notification *interfaces.InterfaceNotification) { if notification == nil { return } diff --git a/plugins/vpp/srplugin/data_resync.go b/plugins/vpp/srplugin/data_resync.go index 84e69485c1..25855196fe 100644 --- a/plugins/vpp/srplugin/data_resync.go +++ b/plugins/vpp/srplugin/data_resync.go @@ -18,12 +18,14 @@ import ( "github.com/ligato/vpp-agent/plugins/vpp/model/srv6" ) -// TODO move unique identifiable name into srv6 models +// NamedPolicySegment represents named policy segment. +// TODO: move unique identifiable name into srv6 models type NamedPolicySegment struct { Name string /* unique identifiable name */ Segment *srv6.PolicySegment } +// NamedSteering represents named steetring. type NamedSteering struct { Name string /* unique identifiable name */ Steering *srv6.Steering @@ -31,7 +33,7 @@ type NamedSteering struct { // Resync writes missing segment routing configs to the VPP and removes obsolete ones. func (plugin *SRv6Configurator) Resync(localSids []*srv6.LocalSID, policies []*srv6.Policy, namedSegments []*NamedPolicySegment, namedSteerings []*NamedSteering) error { - plugin.Log.Debug("RESYNC SR begin.") + plugin.log.Debug("RESYNC SR begin.") // Re-initialize cache plugin.clearMapping() @@ -40,32 +42,32 @@ func (plugin *SRv6Configurator) Resync(localSids []*srv6.LocalSID, policies []*s for _, localsid := range localSids { if err := plugin.AddLocalSID(localsid); err != nil { - plugin.Log.Error(err) + plugin.log.Error(err) continue } } for _, policy := range policies { if err := plugin.AddPolicy(policy); err != nil { - plugin.Log.Error(err) + plugin.log.Error(err) continue } } for _, namedSegment := range namedSegments { if err := plugin.AddPolicySegment(namedSegment.Name, namedSegment.Segment); err != nil { - plugin.Log.Error(err) + plugin.log.Error(err) continue } } for _, namedSteering := range namedSteerings { if err := plugin.AddSteering(namedSteering.Name, namedSteering.Steering); err != nil { - plugin.Log.Error(err) + plugin.log.Error(err) continue } } - plugin.Log.Debug("RESYNC SR end.") + plugin.log.Debug("RESYNC SR end.") return nil } diff --git a/plugins/vpp/srplugin/srv6_config.go b/plugins/vpp/srplugin/srv6_config.go index 5854c09402..3d521e1903 100644 --- a/plugins/vpp/srplugin/srv6_config.go +++ b/plugins/vpp/srplugin/srv6_config.go @@ -24,6 +24,7 @@ import ( govppapi "git.fd.io/govpp.git/api" "github.com/ligato/cn-infra/logging" + "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/cn-infra/utils/safeclose" "github.com/ligato/vpp-agent/idxvpp" "github.com/ligato/vpp-agent/idxvpp/nametoidx" @@ -40,13 +41,14 @@ import ( // modelled by the proto file "../model/srv6/srv6.proto" and stored in ETCD under the key "/vnf-agent/{vnf-agent}/vpp/config/v1/srv6". type SRv6Configurator struct { // injectable/public fields - Log logging.Logger - GoVppmux govppmux.API - SwIfIndexes ifaceidx.SwIfIndex // SwIfIndexes from default plugins - VppCalls vppcalls.SRv6Calls + log logging.Logger + swIfIndexes ifaceidx.SwIfIndex // SwIfIndexes from default plugins // channels - Channel govppapi.Channel // channel to communicate with VPP + vppChan govppapi.Channel // channel to communicate with VPP + + // vpp api handler + srHandler vppcalls.SRv6VppAPI // caches policyCache *cache.PolicyCache // Cache for SRv6 policies @@ -59,43 +61,65 @@ type SRv6Configurator struct { policyIndexes idxvpp.NameToIdxRW // Mapping between policy bsid and index inside VPP policySegmentIndexSeq *gaplessSequence policySegmentIndexes idxvpp.NameToIdxRW // Mapping between policy segment name as defined in ETCD key and index inside VPP + + // stopwatch + stopwatch *measure.Stopwatch } // Init members -func (plugin *SRv6Configurator) Init() (err error) { +func (plugin *SRv6Configurator) Init(logger logging.PluginLogger, goVppMux govppmux.API, swIfIndexes ifaceidx.SwIfIndex, + enableStopwatch bool, srHandler vppcalls.SRv6VppAPI) (err error) { + // Logger + plugin.log = logger.NewLogger("-sr-plugin") + // NewAPIChannel returns a new API channel for communication with VPP via govpp core. // It uses default buffer sizes for the request and reply Go channels. - plugin.Channel, err = plugin.GoVppmux.NewAPIChannel() + plugin.vppChan, err = goVppMux.NewAPIChannel() if err != nil { return } + // Init stopwatch + if enableStopwatch { + plugin.stopwatch = measure.NewStopwatch("SRConfigurator", plugin.log) + } + + // VPP API handler + if srHandler != nil { + plugin.srHandler = srHandler + } else { + plugin.srHandler = vppcalls.NewSRv6VppHandler(plugin.vppChan, plugin.log, plugin.stopwatch) + } + + // Interface indexes + plugin.swIfIndexes = swIfIndexes + // Create caches - plugin.policyCache = cache.NewPolicyCache(plugin.Log) - plugin.policySegmentsCache = cache.NewPolicySegmentCache(plugin.Log) - plugin.steeringCache = cache.NewSteeringCache(plugin.Log) + plugin.policyCache = cache.NewPolicyCache(plugin.log) + plugin.policySegmentsCache = cache.NewPolicySegmentCache(plugin.log) + plugin.steeringCache = cache.NewSteeringCache(plugin.log) plugin.createdPolicies = make(map[string]struct{}) // Create indexes plugin.policySegmentIndexSeq = newSequence() - plugin.policySegmentIndexes = nametoidx.NewNameToIdx(plugin.Log, "policy-segment-indexes", nil) + plugin.policySegmentIndexes = nametoidx.NewNameToIdx(plugin.log, "policy-segment-indexes", nil) plugin.policyIndexSeq = newSequence() - plugin.policyIndexes = nametoidx.NewNameToIdx(plugin.Log, "policy-indexes", nil) + plugin.policyIndexes = nametoidx.NewNameToIdx(plugin.log, "policy-indexes", nil) return } // Close closes GOVPP channel func (plugin *SRv6Configurator) Close() error { - return safeclose.Close(plugin.Channel) + return safeclose.Close(plugin.vppChan) } // clearMapping prepares all in-memory-mappings and other cache fields. All previous cached entries are removed. func (plugin *SRv6Configurator) clearMapping() { // Clear caches - plugin.policyCache = cache.NewPolicyCache(plugin.Log) - plugin.policySegmentsCache = cache.NewPolicySegmentCache(plugin.Log) - plugin.steeringCache = cache.NewSteeringCache(plugin.Log) + plugin.policyCache = cache.NewPolicyCache(plugin.log) + plugin.policySegmentsCache = cache.NewPolicySegmentCache(plugin.log) + plugin.steeringCache = cache.NewSteeringCache(plugin.log) plugin.createdPolicies = make(map[string]struct{}) // Clear indexes @@ -111,7 +135,7 @@ func (plugin *SRv6Configurator) AddLocalSID(value *srv6.LocalSID) error { if err != nil { return fmt.Errorf("sid should be valid ipv6 address: %v", err) } - return plugin.VppCalls.AddLocalSid(sid, value, plugin.SwIfIndexes, plugin.Channel) + return plugin.srHandler.AddLocalSid(sid, value, plugin.swIfIndexes) } // DeleteLocalSID removes Local SID from VPP using VPP's binary api @@ -120,7 +144,7 @@ func (plugin *SRv6Configurator) DeleteLocalSID(value *srv6.LocalSID) error { if err != nil { return fmt.Errorf("sid should be valid ipv6 address: %v", err) } - return plugin.VppCalls.DeleteLocalSid(sid, plugin.Channel) + return plugin.srHandler.DeleteLocalSid(sid) } // ModifyLocalSID modifies Local SID from to in VPP using VPP's binary api @@ -145,13 +169,13 @@ func (plugin *SRv6Configurator) AddPolicy(policy *srv6.Policy) error { plugin.policyCache.Put(bsid, policy) segments, segmentNames := plugin.policySegmentsCache.LookupByPolicy(bsid) if len(segments) == 0 { - plugin.Log.Debugf("addition of policy (%v) postponed until first policy segment is defined for it", bsid.String()) + plugin.log.Debugf("addition of policy (%v) postponed until first policy segment is defined for it", bsid.String()) return nil } plugin.addPolicyToIndexes(bsid) plugin.addSegmentToIndexes(bsid, segmentNames[0]) - err = plugin.VppCalls.AddPolicy(bsid, policy, segments[0], plugin.Channel) + err = plugin.srHandler.AddPolicy(bsid, policy, segments[0]) if err != nil { return fmt.Errorf("can't write policy (%v) with first segment (%v): %v", bsid, segments[0].Segments, err) } @@ -211,7 +235,7 @@ func (plugin *SRv6Configurator) RemovePolicy(policy *srv6.Policy) error { plugin.policySegmentIndexSeq.delete(index) } } - return plugin.VppCalls.DeletePolicy(bsid, plugin.Channel) // expecting that policy delete will also delete policy segments in vpp + return plugin.srHandler.DeletePolicy(bsid) // expecting that policy delete will also delete policy segments in vpp } // ModifyPolicy modifies policy in VPP using VPP's binary api @@ -247,7 +271,7 @@ func (plugin *SRv6Configurator) AddPolicySegment(segmentName string, policySegme plugin.policySegmentsCache.Put(bsid, segmentName, policySegment) policy, exists := plugin.policyCache.GetValue(bsid) if !exists { - plugin.Log.Debugf("addition of policy segment (%v) postponed until policy with %v bsid is created", policySegment.GetSegments(), bsid.String()) + plugin.log.Debugf("addition of policy segment (%v) postponed until policy with %v bsid is created", policySegment.GetSegments(), bsid.String()) return nil } @@ -266,7 +290,7 @@ func (plugin *SRv6Configurator) AddPolicySegment(segmentName string, policySegme } // FIXME there is no API contract saying what happens to VPP indexes if addition fails (also different fail code can rollback or not rollback indexes) => no way how to handle this without being dependent on internal implementation inside VPP and that is just very fragile -> API should tell this but it doesn't! plugin.addSegmentToIndexes(bsid, segmentName) - return plugin.VppCalls.AddPolicySegment(bsid, policy, policySegment, plugin.Channel) + return plugin.srHandler.AddPolicySegment(bsid, policy, policySegment) } // RemovePolicySegment removes policy segment with name from referenced policy in VPP using @@ -282,7 +306,7 @@ func (plugin *SRv6Configurator) RemovePolicySegment(segmentName string, policySe siblings, _ := plugin.policySegmentsCache.LookupByPolicy(bsid) // sibling segments in the same policy if len(siblings) == 0 { // last segment for policy - plugin.Log.Debugf("removal of policy segment (%v) postponed until policy with %v bsid is deleted", policySegment.GetSegments(), bsid.String()) + plugin.log.Debugf("removal of policy segment (%v) postponed until policy with %v bsid is deleted", policySegment.GetSegments(), bsid.String()) return nil } @@ -296,7 +320,7 @@ func (plugin *SRv6Configurator) RemovePolicySegment(segmentName string, policySe } // FIXME there is no API contract saying what happens to VPP indexes if removal fails (also different fail code can rollback or not rollback indexes) => no way how to handle this without being dependent on internal implementation inside VPP and that is just very fragile -> API should tell this but it doesn't! plugin.policySegmentIndexSeq.delete(index) - return plugin.VppCalls.DeletePolicySegment(bsid, policy, policySegment, index, plugin.Channel) + return plugin.srHandler.DeletePolicySegment(bsid, policy, policySegment, index) } // ModifyPolicySegment modifies existing policy segment with name from to in referenced policy. @@ -356,7 +380,7 @@ func (plugin *SRv6Configurator) AddSteering(name string, steering *srv6.Steering var exists bool bsidStr, _, exists = plugin.policyIndexes.LookupName(steering.PolicyIndex) if !exists { - plugin.Log.Debugf("addition of steering (index %v) postponed until referenced policy is defined", steering.PolicyIndex) + plugin.log.Debugf("addition of steering (index %v) postponed until referenced policy is defined", steering.PolicyIndex) return nil } } @@ -366,17 +390,17 @@ func (plugin *SRv6Configurator) AddSteering(name string, steering *srv6.Steering return fmt.Errorf("can't parse policy BSID string ('%v') into IPv6 address", steering.PolicyBsid) } if _, exists := plugin.policyCache.GetValue(bsid); !exists { - plugin.Log.Debugf("addition of steering (bsid %v) postponed until referenced policy is defined", name) + plugin.log.Debugf("addition of steering (bsid %v) postponed until referenced policy is defined", name) return nil } - return plugin.VppCalls.AddSteering(steering, plugin.SwIfIndexes, plugin.Channel) + return plugin.srHandler.AddSteering(steering, plugin.swIfIndexes) } // RemoveSteering removes steering from VPP using VPP's binary api func (plugin *SRv6Configurator) RemoveSteering(name string, steering *srv6.Steering) error { plugin.steeringCache.Delete(name) - return plugin.VppCalls.RemoveSteering(steering, plugin.SwIfIndexes, plugin.Channel) + return plugin.srHandler.RemoveSteering(steering, plugin.swIfIndexes) } // ModifySteering modifies existing steering in VPP using VPP's binary api diff --git a/plugins/vpp/srplugin/srv6_config_test.go b/plugins/vpp/srplugin/srv6_config_test.go index 5a04c115a7..28b2c136f6 100644 --- a/plugins/vpp/srplugin/srv6_config_test.go +++ b/plugins/vpp/srplugin/srv6_config_test.go @@ -21,12 +21,10 @@ import ( "git.fd.io/govpp.git/adapter/mock" "git.fd.io/govpp.git/core" "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/logrus" "github.com/ligato/vpp-agent/idxvpp/nametoidx" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" "github.com/ligato/vpp-agent/plugins/vpp/model/srv6" "github.com/ligato/vpp-agent/plugins/vpp/srplugin" - "github.com/ligato/vpp-agent/tests/vppcallfake" "github.com/ligato/vpp-agent/tests/vppcallmock" . "github.com/onsi/gomega" ) @@ -53,13 +51,13 @@ func TestAddLocalSID(t *testing.T) { // Prepare different cases cases := []struct { Name string - Verify func(srv6.SID, *srv6.LocalSID, error, *vppcallfake.SRv6Calls) + Verify func(srv6.SID, *srv6.LocalSID, error, *SRv6Calls) FailIn interface{} FailWith error }{ { Name: "simple addition of local sid", - Verify: func(sid srv6.SID, data *srv6.LocalSID, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(sid srv6.SID, data *srv6.LocalSID, err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) state := fakeVPPCalls.LocalSIDState() recordedData, exists := state[sid.String()] @@ -69,9 +67,9 @@ func TestAddLocalSID(t *testing.T) { }, { Name: "failure propagation from VPPCall's AddLocalSid", - FailIn: vppcallfake.AddLocalSidFuncCall{}, + FailIn: AddLocalSidFuncCall{}, FailWith: fmt.Errorf(errorMessage), - Verify: func(sid srv6.SID, data *srv6.LocalSID, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(sid srv6.SID, data *srv6.LocalSID, err error, fakeVPPCalls *SRv6Calls) { Expect(err).NotTo(BeNil()) Expect(err.Error()).To(ContainSubstring(errorMessage)) }, @@ -99,22 +97,22 @@ func TestDeleteLocalSID(t *testing.T) { // Prepare different cases cases := []struct { Name string - Verify func(error, *vppcallfake.SRv6Calls) + Verify func(error, *SRv6Calls) FailIn interface{} FailWith error }{ { Name: "simple deletion of local sid", - Verify: func(err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) Expect(fakeVPPCalls.LocalSIDState()).To(BeEmpty()) }, }, { Name: "failure propagation from VPPCall's DeleteLocalSid", - FailIn: vppcallfake.DeleteLocalSidFuncCall{}, + FailIn: DeleteLocalSidFuncCall{}, FailWith: fmt.Errorf(errorMessage), - Verify: func(err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(err error, fakeVPPCalls *SRv6Calls) { Expect(err).NotTo(BeNil()) Expect(err.Error()).To(ContainSubstring(errorMessage)) }, @@ -145,13 +143,13 @@ func TestModifyLocalSID(t *testing.T) { // Prepare different cases cases := []struct { Name string - Verify func(srv6.SID, *srv6.LocalSID, *srv6.LocalSID, error, *vppcallfake.SRv6Calls) + Verify func(srv6.SID, *srv6.LocalSID, *srv6.LocalSID, error, *SRv6Calls) FailIn interface{} FailWith error }{ { Name: "simple modify of local sid", - Verify: func(sid srv6.SID, data *srv6.LocalSID, prevData *srv6.LocalSID, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(sid srv6.SID, data *srv6.LocalSID, prevData *srv6.LocalSID, err error, fakeVPPCalls *SRv6Calls) { state := fakeVPPCalls.LocalSIDState() recordedData, exists := state[sid.String()] Expect(exists).To(BeTrue()) @@ -160,18 +158,18 @@ func TestModifyLocalSID(t *testing.T) { }, { Name: "failure propagation from VPPCall's AddLocalSid", - FailIn: vppcallfake.AddLocalSidFuncCall{}, + FailIn: AddLocalSidFuncCall{}, FailWith: fmt.Errorf(errorMessage), - Verify: func(sid srv6.SID, data *srv6.LocalSID, prevData *srv6.LocalSID, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(sid srv6.SID, data *srv6.LocalSID, prevData *srv6.LocalSID, err error, fakeVPPCalls *SRv6Calls) { Expect(err).NotTo(BeNil()) Expect(err.Error()).To(ContainSubstring(errorMessage)) }, }, { Name: "failure propagation from VPPCall's DeleteLocalSid", - FailIn: vppcallfake.DeleteLocalSidFuncCall{}, + FailIn: DeleteLocalSidFuncCall{}, FailWith: fmt.Errorf(errorMessage), - Verify: func(sid srv6.SID, data *srv6.LocalSID, prevData *srv6.LocalSID, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(sid srv6.SID, data *srv6.LocalSID, prevData *srv6.LocalSID, err error, fakeVPPCalls *SRv6Calls) { Expect(err).NotTo(BeNil()) Expect(err.Error()).To(ContainSubstring(errorMessage)) }, @@ -217,24 +215,24 @@ func TestAddPolicy(t *testing.T) { // Prepare different cases cases := []struct { Name string - VerifyAfterAddPolicy func(*srv6.Policy, *srv6.PolicySegment, *srv6.PolicySegment, error, *vppcallfake.SRv6Calls) - VerifyAfterFirstAddPolicySegment func(*srv6.Policy, *srv6.PolicySegment, *srv6.PolicySegment, error, *vppcallfake.SRv6Calls) - VerifyAfterSecondAddPolicySegment func(*srv6.Policy, *srv6.PolicySegment, *srv6.PolicySegment, error, *vppcallfake.SRv6Calls) + VerifyAfterAddPolicy func(*srv6.Policy, *srv6.PolicySegment, *srv6.PolicySegment, error, *SRv6Calls) + VerifyAfterFirstAddPolicySegment func(*srv6.Policy, *srv6.PolicySegment, *srv6.PolicySegment, error, *SRv6Calls) + VerifyAfterSecondAddPolicySegment func(*srv6.Policy, *srv6.PolicySegment, *srv6.PolicySegment, error, *SRv6Calls) FailIn interface{} FailWith error SetPolicySegmentsFirst bool }{ { Name: "add policy and add 2 segment", // handling of first segment is special -> adding 2 segments - VerifyAfterAddPolicy: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterAddPolicy: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) Expect(fakeVPPCalls.PoliciesState()).To(BeEmpty()) }, - VerifyAfterFirstAddPolicySegment: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterFirstAddPolicySegment: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) verifyOnePolicyWithSegments(fakeVPPCalls, policy, segment) }, - VerifyAfterSecondAddPolicySegment: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterSecondAddPolicySegment: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) verifyOnePolicyWithSegments(fakeVPPCalls, policy, segment, segment2) }, @@ -242,34 +240,34 @@ func TestAddPolicy(t *testing.T) { { Name: "add 2 segments to nonexisting policy and add policy", // handling of first segment is special -> adding 2 segments SetPolicySegmentsFirst: true, - VerifyAfterFirstAddPolicySegment: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterFirstAddPolicySegment: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) Expect(fakeVPPCalls.PoliciesState()).To(HaveLen(0)) }, - VerifyAfterSecondAddPolicySegment: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterSecondAddPolicySegment: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) Expect(fakeVPPCalls.PoliciesState()).To(HaveLen(0)) }, - VerifyAfterAddPolicy: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterAddPolicy: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) verifyOnePolicyWithSegments(fakeVPPCalls, policy, segment, segment2) }, }, { Name: "failure propagation from VPPCall's AddPolicy", - FailIn: vppcallfake.AddPolicyFuncCall{}, + FailIn: AddPolicyFuncCall{}, FailWith: fmt.Errorf(errorMessage), - VerifyAfterFirstAddPolicySegment: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterFirstAddPolicySegment: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).NotTo(BeNil()) Expect(err.Error()).To(ContainSubstring(errorMessage)) }, }, { Name: "failure propagation from VPPCall's AddPolicySegment", - FailIn: vppcallfake.AddPolicySegmentFuncCall{}, + FailIn: AddPolicySegmentFuncCall{}, FailWith: fmt.Errorf(errorMessage), SetPolicySegmentsFirst: true, - VerifyAfterAddPolicy: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterAddPolicy: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).NotTo(BeNil()) Expect(err.Error()).To(ContainSubstring(errorMessage)) }, @@ -328,16 +326,16 @@ func TestDeletePolicy(t *testing.T) { // Prepare different cases cases := []struct { Name string - VerifyAfterRemovePolicy func(*srv6.Policy, *srv6.PolicySegment, *srv6.PolicySegment, error, *vppcallfake.SRv6Calls) - VerifyAfterFirstRemovePolicySegment func(*srv6.Policy, *srv6.PolicySegment, *srv6.PolicySegment, error, *vppcallfake.SRv6Calls) - VerifyAfterSecondRemovePolicySegment func(*srv6.Policy, *srv6.PolicySegment, *srv6.PolicySegment, error, *vppcallfake.SRv6Calls) + VerifyAfterRemovePolicy func(*srv6.Policy, *srv6.PolicySegment, *srv6.PolicySegment, error, *SRv6Calls) + VerifyAfterFirstRemovePolicySegment func(*srv6.Policy, *srv6.PolicySegment, *srv6.PolicySegment, error, *SRv6Calls) + VerifyAfterSecondRemovePolicySegment func(*srv6.Policy, *srv6.PolicySegment, *srv6.PolicySegment, error, *SRv6Calls) FailIn interface{} FailWith error RemovePoliceSegment bool }{ { Name: "remove policy (without removing segments)", - VerifyAfterRemovePolicy: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterRemovePolicy: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) Expect(fakeVPPCalls.PoliciesState()).To(BeEmpty()) }, @@ -345,34 +343,34 @@ func TestDeletePolicy(t *testing.T) { { Name: "remove segments and remove policy", RemovePoliceSegment: true, - VerifyAfterFirstRemovePolicySegment: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterFirstRemovePolicySegment: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) Expect(fakeVPPCalls.PoliciesState()).ToNot(BeEmpty()) }, - VerifyAfterSecondRemovePolicySegment: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterSecondRemovePolicySegment: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) Expect(fakeVPPCalls.PoliciesState()).ToNot(BeEmpty()) }, - VerifyAfterRemovePolicy: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterRemovePolicy: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) Expect(fakeVPPCalls.PoliciesState()).To(BeEmpty()) }, }, { Name: "failure propagation from VPPCall's DeletePolicy", - FailIn: vppcallfake.DeletePolicyFuncCall{}, + FailIn: DeletePolicyFuncCall{}, FailWith: fmt.Errorf(errorMessage), - VerifyAfterRemovePolicy: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterRemovePolicy: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).NotTo(BeNil()) Expect(err.Error()).To(ContainSubstring(errorMessage)) }, }, { Name: "failure propagation from VPPCall's DeletePolicySegment", - FailIn: vppcallfake.DeletePolicySegmentFuncCall{}, + FailIn: DeletePolicySegmentFuncCall{}, FailWith: fmt.Errorf(errorMessage), RemovePoliceSegment: true, - VerifyAfterFirstRemovePolicySegment: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterFirstRemovePolicySegment: func(policy *srv6.Policy, segment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).NotTo(BeNil()) Expect(err.Error()).To(ContainSubstring(errorMessage)) }, @@ -421,31 +419,31 @@ func TestModifyPolicy(t *testing.T) { // Prepare different cases cases := []struct { Name string - Verify func(*srv6.Policy, *srv6.Policy, *srv6.PolicySegment, error, *vppcallfake.SRv6Calls) + Verify func(*srv6.Policy, *srv6.Policy, *srv6.PolicySegment, error, *SRv6Calls) FailIn interface{} FailWith error }{ { Name: "policy attributes modification", - Verify: func(policy *srv6.Policy, prevPolicy *srv6.Policy, segment *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(policy *srv6.Policy, prevPolicy *srv6.Policy, segment *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) verifyOnePolicyWithSegments(fakeVPPCalls, policy, segment) }, }, { Name: "failure propagation from VPPCall's AddPolicy", - FailIn: vppcallfake.AddPolicyFuncCall{}, + FailIn: AddPolicyFuncCall{}, FailWith: fmt.Errorf(errorMessage), - Verify: func(policy *srv6.Policy, prevPolicy *srv6.Policy, segment *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(policy *srv6.Policy, prevPolicy *srv6.Policy, segment *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).NotTo(BeNil()) Expect(err.Error()).To(ContainSubstring(errorMessage)) }, }, { Name: "failure propagation from VPPCall's DeletePolicy", - FailIn: vppcallfake.DeletePolicyFuncCall{}, + FailIn: DeletePolicyFuncCall{}, FailWith: fmt.Errorf(errorMessage), - Verify: func(policy *srv6.Policy, prevPolicy *srv6.Policy, segment *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(policy *srv6.Policy, prevPolicy *srv6.Policy, segment *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).NotTo(BeNil()) Expect(err.Error()).To(ContainSubstring(errorMessage)) }, @@ -493,14 +491,14 @@ func TestModifyPolicySegment(t *testing.T) { // Prepare different cases cases := []struct { Name string - Verify func(*srv6.Policy, *srv6.PolicySegment, *srv6.PolicySegment, *srv6.PolicySegment, error, *vppcallfake.SRv6Calls) + Verify func(*srv6.Policy, *srv6.PolicySegment, *srv6.PolicySegment, *srv6.PolicySegment, error, *SRv6Calls) FailIn interface{} FailWith error OnlyOneSegment bool }{ { Name: "policy segment modification (non-last segment)", // last segment is handled differently - Verify: func(policy *srv6.Policy, segment *srv6.PolicySegment, prevSegment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(policy *srv6.Policy, segment *srv6.PolicySegment, prevSegment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) verifyOnePolicyWithSegments(fakeVPPCalls, policy, segment2, segment) }, @@ -508,7 +506,7 @@ func TestModifyPolicySegment(t *testing.T) { { Name: "policy segment modification (last segment)", // last segment is handled differently OnlyOneSegment: true, - Verify: func(policy *srv6.Policy, segment *srv6.PolicySegment, prevSegment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(policy *srv6.Policy, segment *srv6.PolicySegment, prevSegment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) verifyOnePolicyWithSegments(fakeVPPCalls, policy, segment) }, @@ -516,9 +514,9 @@ func TestModifyPolicySegment(t *testing.T) { { Name: "failure propagation from VPPCall's AddPolicy", OnlyOneSegment: true, - FailIn: vppcallfake.AddPolicyFuncCall{}, + FailIn: AddPolicyFuncCall{}, FailWith: fmt.Errorf(errorMessage), - Verify: func(policy *srv6.Policy, segment *srv6.PolicySegment, prevSegment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(policy *srv6.Policy, segment *srv6.PolicySegment, prevSegment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).NotTo(BeNil()) Expect(err.Error()).To(ContainSubstring(errorMessage)) }, @@ -526,27 +524,27 @@ func TestModifyPolicySegment(t *testing.T) { { Name: "failure propagation from VPPCall's DeletePolicy", OnlyOneSegment: true, - FailIn: vppcallfake.DeletePolicyFuncCall{}, + FailIn: DeletePolicyFuncCall{}, FailWith: fmt.Errorf(errorMessage), - Verify: func(policy *srv6.Policy, segment *srv6.PolicySegment, prevSegment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(policy *srv6.Policy, segment *srv6.PolicySegment, prevSegment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).NotTo(BeNil()) Expect(err.Error()).To(ContainSubstring(errorMessage)) }, }, { Name: "failure propagation from VPPCall's DeletePolicySegment", - FailIn: vppcallfake.DeletePolicySegmentFuncCall{}, + FailIn: DeletePolicySegmentFuncCall{}, FailWith: fmt.Errorf(errorMessage), - Verify: func(policy *srv6.Policy, segment *srv6.PolicySegment, prevSegment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(policy *srv6.Policy, segment *srv6.PolicySegment, prevSegment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).NotTo(BeNil()) Expect(err.Error()).To(ContainSubstring(errorMessage)) }, }, { Name: "failure propagation from VPPCall's AddPolicySegment", - FailIn: vppcallfake.AddPolicySegmentFuncCall{}, + FailIn: AddPolicySegmentFuncCall{}, FailWith: fmt.Errorf(errorMessage), - Verify: func(policy *srv6.Policy, segment *srv6.PolicySegment, prevSegment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(policy *srv6.Policy, segment *srv6.PolicySegment, prevSegment *srv6.PolicySegment, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).NotTo(BeNil()) Expect(err.Error()).To(ContainSubstring(errorMessage)) }, @@ -589,22 +587,22 @@ func TestFillingAlreadyCreatedSegmentEmptyPolicy(t *testing.T) { // Prepare different cases cases := []struct { Name string - Verify func(*srv6.Policy, *srv6.PolicySegment, error, *vppcallfake.SRv6Calls) + Verify func(*srv6.Policy, *srv6.PolicySegment, error, *SRv6Calls) FailIn interface{} FailWith error }{ { Name: "all segments removal and adding new onw", // last segment is handled differently - Verify: func(policy *srv6.Policy, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(policy *srv6.Policy, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) verifyOnePolicyWithSegments(fakeVPPCalls, policy, segment2) }, }, { Name: "failure propagation from VPPCall's DeletePolicy", - FailIn: vppcallfake.DeletePolicyFuncCall{}, + FailIn: DeletePolicyFuncCall{}, FailWith: fmt.Errorf(errorMessage), - Verify: func(policy *srv6.Policy, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(policy *srv6.Policy, segment2 *srv6.PolicySegment, err error, fakeVPPCalls *SRv6Calls) { Expect(err).NotTo(BeNil()) Expect(err.Error()).To(ContainSubstring(errorMessage)) }, @@ -641,8 +639,8 @@ func TestAddSteering(t *testing.T) { // Prepare different cases cases := []struct { Name string - VerifyAfterAddPolicy func(*srv6.Steering, *vppcallfake.SRv6Calls) - VerifyAfterAddSteering func(*srv6.Steering, error, *vppcallfake.SRv6Calls) + VerifyAfterAddPolicy func(*srv6.Steering, *SRv6Calls) + VerifyAfterAddSteering func(*srv6.Steering, error, *SRv6Calls) FailIn interface{} FailWith error ReferencePolicyByIndex bool @@ -651,10 +649,10 @@ func TestAddSteering(t *testing.T) { }{ { Name: "addition of steering (with already existing BSID-referenced policy)", - VerifyAfterAddPolicy: func(steering *srv6.Steering, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterAddPolicy: func(steering *srv6.Steering, fakeVPPCalls *SRv6Calls) { Expect(fakeVPPCalls.SteeringState()).To(BeEmpty()) }, - VerifyAfterAddSteering: func(steering *srv6.Steering, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterAddSteering: func(steering *srv6.Steering, err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) state := fakeVPPCalls.SteeringState() _, exists := state[*steering] @@ -664,11 +662,11 @@ func TestAddSteering(t *testing.T) { { Name: "addition of steering (with BSID-referenced policy added later)", CreatePolicyAfter: true, - VerifyAfterAddSteering: func(steering *srv6.Steering, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterAddSteering: func(steering *srv6.Steering, err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) Expect(fakeVPPCalls.SteeringState()).To(BeEmpty()) }, - VerifyAfterAddPolicy: func(steering *srv6.Steering, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterAddPolicy: func(steering *srv6.Steering, fakeVPPCalls *SRv6Calls) { state := fakeVPPCalls.SteeringState() _, exists := state[*steering] Expect(exists).To(BeTrue()) @@ -677,10 +675,10 @@ func TestAddSteering(t *testing.T) { { Name: "addition of steering (with already existing Index-referenced policy)", ReferencePolicyByIndex: true, - VerifyAfterAddPolicy: func(steering *srv6.Steering, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterAddPolicy: func(steering *srv6.Steering, fakeVPPCalls *SRv6Calls) { Expect(fakeVPPCalls.SteeringState()).To(BeEmpty()) }, - VerifyAfterAddSteering: func(steering *srv6.Steering, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterAddSteering: func(steering *srv6.Steering, err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) state := fakeVPPCalls.SteeringState() _, exists := state[*steering] @@ -691,11 +689,11 @@ func TestAddSteering(t *testing.T) { Name: "addition of steering (with Index-referenced policy added later)", ReferencePolicyByIndex: true, CreatePolicyAfter: true, - VerifyAfterAddSteering: func(steering *srv6.Steering, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterAddSteering: func(steering *srv6.Steering, err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) Expect(fakeVPPCalls.SteeringState()).To(BeEmpty()) }, - VerifyAfterAddPolicy: func(steering *srv6.Steering, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterAddPolicy: func(steering *srv6.Steering, fakeVPPCalls *SRv6Calls) { state := fakeVPPCalls.SteeringState() _, exists := state[*steering] Expect(exists).To(BeTrue()) @@ -704,15 +702,15 @@ func TestAddSteering(t *testing.T) { { Name: "invalid BSID as policy reference", CustomSteeringData: steeringWithPolicyBsidRef("XYZ"), // valid binding sid = valid IPv6 - VerifyAfterAddSteering: func(steering *srv6.Steering, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterAddSteering: func(steering *srv6.Steering, err error, fakeVPPCalls *SRv6Calls) { Expect(err).NotTo(BeNil()) }, }, { Name: "failure propagation from VPPCall's AddSteering", - FailIn: vppcallfake.AddSteeringFuncCall{}, + FailIn: AddSteeringFuncCall{}, FailWith: fmt.Errorf(errorMessage), - VerifyAfterAddSteering: func(steering *srv6.Steering, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + VerifyAfterAddSteering: func(steering *srv6.Steering, err error, fakeVPPCalls *SRv6Calls) { Expect(err).NotTo(BeNil()) Expect(err.Error()).To(ContainSubstring(errorMessage)) }, @@ -770,22 +768,22 @@ func TestRemoveSteering(t *testing.T) { // Prepare different cases cases := []struct { Name string - Verify func(error, *vppcallfake.SRv6Calls) + Verify func(error, *SRv6Calls) FailIn interface{} FailWith error }{ { Name: "simple steering removal", - Verify: func(err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) Expect(fakeVPPCalls.SteeringState()).To(BeEmpty()) }, }, { Name: "failure propagation from VPPCall's RemoveSteering", - FailIn: vppcallfake.RemoveSteeringFuncCall{}, + FailIn: RemoveSteeringFuncCall{}, FailWith: fmt.Errorf(errorMessage), - Verify: func(err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(err error, fakeVPPCalls *SRv6Calls) { Expect(err).NotTo(BeNil()) Expect(err.Error()).To(ContainSubstring(errorMessage)) }, @@ -823,13 +821,13 @@ func TestModifySteering(t *testing.T) { // Prepare different cases cases := []struct { Name string - Verify func(*srv6.Steering, error, *vppcallfake.SRv6Calls) + Verify func(*srv6.Steering, error, *SRv6Calls) FailIn interface{} FailWith error }{ { Name: "simple modification of steering", - Verify: func(steering *srv6.Steering, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(steering *srv6.Steering, err error, fakeVPPCalls *SRv6Calls) { Expect(err).To(BeNil()) state := fakeVPPCalls.SteeringState() _, exists := state[*steering] @@ -838,18 +836,18 @@ func TestModifySteering(t *testing.T) { }, { Name: "failure propagation from VPPCall's AddSteering", - FailIn: vppcallfake.AddSteeringFuncCall{}, + FailIn: AddSteeringFuncCall{}, FailWith: fmt.Errorf(errorMessage), - Verify: func(steering *srv6.Steering, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(steering *srv6.Steering, err error, fakeVPPCalls *SRv6Calls) { Expect(err).NotTo(BeNil()) Expect(err.Error()).To(ContainSubstring(errorMessage)) }, }, { Name: "failure propagation from VPPCall's RemoveSteering", - FailIn: vppcallfake.RemoveSteeringFuncCall{}, + FailIn: RemoveSteeringFuncCall{}, FailWith: fmt.Errorf(errorMessage), - Verify: func(steering *srv6.Steering, err error, fakeVPPCalls *vppcallfake.SRv6Calls) { + Verify: func(steering *srv6.Steering, err error, fakeVPPCalls *SRv6Calls) { Expect(err).NotTo(BeNil()) Expect(err.Error()).To(ContainSubstring(errorMessage)) }, @@ -897,7 +895,7 @@ func TestModifySteering(t *testing.T) { /* Srv6 Test Setup */ -func srv6TestSetup(t *testing.T) (*srplugin.SRv6Configurator, *vppcallfake.SRv6Calls, *core.Connection) { +func srv6TestSetup(t *testing.T) (*srplugin.SRv6Configurator, *SRv6Calls, *core.Connection) { RegisterTestingT(t) // connection ctx := &vppcallmock.TestCtx{ @@ -906,19 +904,14 @@ func srv6TestSetup(t *testing.T) (*srplugin.SRv6Configurator, *vppcallfake.SRv6C connection, err := core.Connect(ctx.MockVpp) Expect(err).ShouldNot(HaveOccurred()) // Logger - log := logging.ForPlugin("test-log", logrus.NewLogRegistry()) + log := logging.ForPlugin("test-log") log.SetLevel(logging.DebugLevel) // Interface index from default plugins swIndex := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(log, "sw_if_indexes", ifaceidx.IndexMetadata)) // Configurator - fakeVPPCalls := vppcallfake.NewSRv6Calls() - configurator := &srplugin.SRv6Configurator{ - Log: log, - GoVppmux: connection, - SwIfIndexes: swIndex, - VppCalls: fakeVPPCalls, - } - err = configurator.Init() + fakeVPPCalls := NewSRv6Calls() + configurator := &srplugin.SRv6Configurator{} + err = configurator.Init(log, connection, swIndex, false, fakeVPPCalls) Expect(err).To(BeNil()) return configurator, fakeVPPCalls, connection @@ -930,9 +923,10 @@ func srv6TestTeardown(connection *core.Connection, plugin *srplugin.SRv6Configur connection.Disconnect() err := plugin.Close() Expect(err).To(BeNil()) + logging.DefaultRegistry.ClearRegistry() } -func verifyOnePolicyWithSegments(fakeVPPCalls *vppcallfake.SRv6Calls, policy *srv6.Policy, segments ...*srv6.PolicySegment) { +func verifyOnePolicyWithSegments(fakeVPPCalls *SRv6Calls, policy *srv6.Policy, segments ...*srv6.PolicySegment) { policiesState := fakeVPPCalls.PoliciesState() Expect(policiesState).To(HaveLen(1)) policyState, exists := policiesState[policy.Bsid] diff --git a/tests/vppcallfake/srv6calls.go b/plugins/vpp/srplugin/srv6calls_test.go similarity index 90% rename from tests/vppcallfake/srv6calls.go rename to plugins/vpp/srplugin/srv6calls_test.go index e2906ff3ae..aced6cdd4e 100644 --- a/tests/vppcallfake/srv6calls.go +++ b/plugins/vpp/srplugin/srv6calls_test.go @@ -12,15 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package vppcallfake contains fake implementation of interface vppcalls.SRv6Calls -package vppcallfake +package srplugin_test import ( "fmt" "net" "strings" - govppapi "git.fd.io/govpp.git/api" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" "github.com/ligato/vpp-agent/plugins/vpp/model/srv6" ) @@ -111,7 +109,7 @@ type AddSteeringFuncCall struct{} type RemoveSteeringFuncCall struct{} // AddLocalSid adds local sid given by and into VPP -func (fake *SRv6Calls) AddLocalSid(sidAddr net.IP, localSID *srv6.LocalSID, swIfIndex ifaceidx.SwIfIndex, vppChan govppapi.Channel) error { +func (fake *SRv6Calls) AddLocalSid(sidAddr net.IP, localSID *srv6.LocalSID, swIfIndex ifaceidx.SwIfIndex) error { if _, ok := fake.failCall.(AddLocalSidFuncCall); ok { return fake.failError } @@ -120,7 +118,7 @@ func (fake *SRv6Calls) AddLocalSid(sidAddr net.IP, localSID *srv6.LocalSID, swIf } // DeleteLocalSid delets local sid given by in VPP -func (fake *SRv6Calls) DeleteLocalSid(sidAddr net.IP, vppChan govppapi.Channel) error { +func (fake *SRv6Calls) DeleteLocalSid(sidAddr net.IP) error { if _, ok := fake.failCall.(DeleteLocalSidFuncCall); ok { return fake.failError } @@ -129,7 +127,7 @@ func (fake *SRv6Calls) DeleteLocalSid(sidAddr net.IP, vppChan govppapi.Channel) } // SetEncapsSourceAddress sets for SRv6 in VPP the source address used for encapsulated packet -func (fake *SRv6Calls) SetEncapsSourceAddress(address string, vppChan govppapi.Channel) error { +func (fake *SRv6Calls) SetEncapsSourceAddress(address string) error { if _, ok := fake.failCall.(SetEncapsSourceAddressFuncCall); ok { return fake.failError } @@ -137,7 +135,7 @@ func (fake *SRv6Calls) SetEncapsSourceAddress(address string, vppChan govppapi.C } // AddPolicy adds SRv6 policy given by identified ,initial segment for policy and other policy settings in -func (fake *SRv6Calls) AddPolicy(bindingSid net.IP, policy *srv6.Policy, policySegment *srv6.PolicySegment, vppChan govppapi.Channel) error { +func (fake *SRv6Calls) AddPolicy(bindingSid net.IP, policy *srv6.Policy, policySegment *srv6.PolicySegment) error { if _, ok := fake.failCall.(AddPolicyFuncCall); ok { return fake.failError } @@ -151,7 +149,7 @@ func (fake *SRv6Calls) AddPolicy(bindingSid net.IP, policy *srv6.Policy, policyS } // DeletePolicy deletes SRv6 policy given by binding SID -func (fake *SRv6Calls) DeletePolicy(bindingSid net.IP, vppChan govppapi.Channel) error { +func (fake *SRv6Calls) DeletePolicy(bindingSid net.IP) error { if _, ok := fake.failCall.(DeletePolicyFuncCall); ok { return fake.failError } @@ -165,7 +163,7 @@ func (fake *SRv6Calls) DeletePolicy(bindingSid net.IP, vppChan govppapi.Channel) } // AddPolicySegment adds segment to SRv6 policy that has policy BSID -func (fake *SRv6Calls) AddPolicySegment(bindingSid net.IP, policy *srv6.Policy, policySegment *srv6.PolicySegment, vppChan govppapi.Channel) error { +func (fake *SRv6Calls) AddPolicySegment(bindingSid net.IP, policy *srv6.Policy, policySegment *srv6.PolicySegment) error { if _, ok := fake.failCall.(AddPolicySegmentFuncCall); ok { return fake.failError } @@ -180,7 +178,7 @@ func (fake *SRv6Calls) AddPolicySegment(bindingSid net.IP, policy *srv6.Policy, // DeletePolicySegment removes segment (with segment index ) from SRv6 policy that has policy BSID func (fake *SRv6Calls) DeletePolicySegment(bindingSid net.IP, policy *srv6.Policy, policySegment *srv6.PolicySegment, - segmentIndex uint32, vppChan govppapi.Channel) error { + segmentIndex uint32) error { if _, ok := fake.failCall.(DeletePolicySegmentFuncCall); ok { return fake.failError } @@ -204,7 +202,7 @@ func removeSegment(segments []*srv6.PolicySegment, segment *srv6.PolicySegment) } // AddSteering sets in VPP steering into SRv6 policy. -func (fake *SRv6Calls) AddSteering(steering *srv6.Steering, swIfIndex ifaceidx.SwIfIndex, vppChan govppapi.Channel) error { +func (fake *SRv6Calls) AddSteering(steering *srv6.Steering, swIfIndex ifaceidx.SwIfIndex) error { if _, ok := fake.failCall.(AddSteeringFuncCall); ok { return fake.failError } @@ -224,7 +222,7 @@ func (fake *SRv6Calls) AddSteering(steering *srv6.Steering, swIfIndex ifaceidx.S } // RemoveSteering removes in VPP steering into SRv6 policy. -func (fake *SRv6Calls) RemoveSteering(steering *srv6.Steering, swIfIndex ifaceidx.SwIfIndex, vppChan govppapi.Channel) error { +func (fake *SRv6Calls) RemoveSteering(steering *srv6.Steering, swIfIndex ifaceidx.SwIfIndex) error { if _, ok := fake.failCall.(RemoveSteeringFuncCall); ok { return fake.failError } diff --git a/plugins/vpp/srplugin/vppcalls/api_vppcalls.go b/plugins/vpp/srplugin/vppcalls/api_vppcalls.go new file mode 100644 index 0000000000..487764a47a --- /dev/null +++ b/plugins/vpp/srplugin/vppcalls/api_vppcalls.go @@ -0,0 +1,74 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package vppcalls + +import ( + "net" + + govppapi "git.fd.io/govpp.git/api" + "github.com/ligato/cn-infra/logging" + "github.com/ligato/cn-infra/logging/measure" + "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" + "github.com/ligato/vpp-agent/plugins/vpp/model/srv6" +) + +// SRv6VppAPI is API boundary for vppcall package access, introduced to properly test code dependent on vppcalls package +type SRv6VppAPI interface { + SRv6VPPWrite + SRv6VPPRead +} + +// SRv6VPPWrite provides write methods for segment routing +type SRv6VPPWrite interface { + // AddLocalSid adds local sid given by and into VPP + AddLocalSid(sidAddr net.IP, localSID *srv6.LocalSID, swIfIndex ifaceidx.SwIfIndex) error + // DeleteLocalSid delets local sid given by in VPP + DeleteLocalSid(sidAddr net.IP) error + // SetEncapsSourceAddress sets for SRv6 in VPP the source address used for encapsulated packet + SetEncapsSourceAddress(address string) error + // AddPolicy adds SRv6 policy given by identified ,initial segment for policy and other policy settings in + AddPolicy(bindingSid net.IP, policy *srv6.Policy, policySegment *srv6.PolicySegment) error + // DeletePolicy deletes SRv6 policy given by binding SID + DeletePolicy(bindingSid net.IP) error + // AddPolicySegment adds segment to SRv6 policy that has policy BSID + AddPolicySegment(bindingSid net.IP, policy *srv6.Policy, policySegment *srv6.PolicySegment) error + // DeletePolicySegment removes segment (with segment index ) from SRv6 policy that has policy BSID + DeletePolicySegment(bindingSid net.IP, policy *srv6.Policy, policySegment *srv6.PolicySegment, segmentIndex uint32) error + // AddSteering sets in VPP steering into SRv6 policy. + AddSteering(steering *srv6.Steering, swIfIndex ifaceidx.SwIfIndex) error + // RemoveSteering removes in VPP steering into SRv6 policy. + RemoveSteering(steering *srv6.Steering, swIfIndex ifaceidx.SwIfIndex) error +} + +// SRv6VPPRead provides read methods for segment routing +type SRv6VPPRead interface { + // TODO: implement dump methods +} + +// SRv6VppHandler is accessor for SRv6-related vppcalls methods +type SRv6VppHandler struct { + log logging.Logger + callsChannel govppapi.Channel + stopwatch *measure.Stopwatch +} + +// NewSRv6VppHandler creates new instance of SRv6 vppcalls handler +func NewSRv6VppHandler(vppChan govppapi.Channel, log logging.Logger, stopwatch *measure.Stopwatch) *SRv6VppHandler { + return &SRv6VppHandler{ + callsChannel: vppChan, + log: log, + stopwatch: stopwatch, + } +} diff --git a/plugins/vpp/srplugin/vppcalls/srv6.go b/plugins/vpp/srplugin/vppcalls/srv6.go index 6f589f9fea..2f6d809077 100644 --- a/plugins/vpp/srplugin/vppcalls/srv6.go +++ b/plugins/vpp/srplugin/vppcalls/srv6.go @@ -20,9 +20,7 @@ import ( "strings" "time" - govppapi "git.fd.io/govpp.git/api" "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/measure" "github.com/ligato/vpp-agent/plugins/vpp/binapi/sr" "github.com/ligato/vpp-agent/plugins/vpp/ifplugin/ifaceidx" "github.com/ligato/vpp-agent/plugins/vpp/model/srv6" @@ -58,91 +56,56 @@ const ( ModifyWeightOfSRList // Modify the weight of an existing SR List ) -// SRv6Calls is API boundary for vppcall package access, introduced to properly test code dependent on vppcalls package -type SRv6Calls interface { - // AddLocalSid adds local sid given by and into VPP - AddLocalSid(sidAddr net.IP, localSID *srv6.LocalSID, swIfIndex ifaceidx.SwIfIndex, vppChan govppapi.Channel) error - // DeleteLocalSid delets local sid given by in VPP - DeleteLocalSid(sidAddr net.IP, vppChan govppapi.Channel) error - // SetEncapsSourceAddress sets for SRv6 in VPP the source address used for encapsulated packet - SetEncapsSourceAddress(address string, vppChan govppapi.Channel) error - // AddPolicy adds SRv6 policy given by identified ,initial segment for policy and other policy settings in - AddPolicy(bindingSid net.IP, policy *srv6.Policy, policySegment *srv6.PolicySegment, vppChan govppapi.Channel) error - // DeletePolicy deletes SRv6 policy given by binding SID - DeletePolicy(bindingSid net.IP, vppChan govppapi.Channel) error - // AddPolicySegment adds segment to SRv6 policy that has policy BSID - AddPolicySegment(bindingSid net.IP, policy *srv6.Policy, policySegment *srv6.PolicySegment, vppChan govppapi.Channel) error - // DeletePolicySegment removes segment (with segment index ) from SRv6 policy that has policy BSID - DeletePolicySegment(bindingSid net.IP, policy *srv6.Policy, policySegment *srv6.PolicySegment, segmentIndex uint32, vppChan govppapi.Channel) error - // AddSteering sets in VPP steering into SRv6 policy. - AddSteering(steering *srv6.Steering, swIfIndex ifaceidx.SwIfIndex, vppChan govppapi.Channel) error - // RemoveSteering removes in VPP steering into SRv6 policy. - RemoveSteering(steering *srv6.Steering, swIfIndex ifaceidx.SwIfIndex, vppChan govppapi.Channel) error -} - -type srv6Calls struct { - log logging.Logger - stopwatch *measure.Stopwatch -} - -// NewSRv6Calls creates implementation of SRv6Calls interface -func NewSRv6Calls(log logging.Logger, stopwatch *measure.Stopwatch) SRv6Calls { - return &srv6Calls{ - log: log, - stopwatch: stopwatch, - } -} - // AddLocalSid adds local sid given by and into VPP -func (calls *srv6Calls) AddLocalSid(sidAddr net.IP, localSID *srv6.LocalSID, swIfIndex ifaceidx.SwIfIndex, vppChan govppapi.Channel) error { - return calls.addDelLocalSid(false, sidAddr, localSID, swIfIndex, vppChan) +func (handler *SRv6VppHandler) AddLocalSid(sidAddr net.IP, localSID *srv6.LocalSID, swIfIndex ifaceidx.SwIfIndex) error { + return handler.addDelLocalSid(false, sidAddr, localSID, swIfIndex) } // DeleteLocalSid delets local sid given by in VPP -func (calls *srv6Calls) DeleteLocalSid(sidAddr net.IP, vppChan govppapi.Channel) error { - return calls.addDelLocalSid(true, sidAddr, nil, nil, vppChan) +func (handler *SRv6VppHandler) DeleteLocalSid(sidAddr net.IP) error { + return handler.addDelLocalSid(true, sidAddr, nil, nil) } -func (calls *srv6Calls) addDelLocalSid(deletion bool, sidAddr net.IP, localSID *srv6.LocalSID, swIfIndex ifaceidx.SwIfIndex, vppChan govppapi.Channel) error { - calls.log.WithFields(logging.Fields{"localSID": sidAddr, "delete": deletion, "FIB table ID": calls.fibTableID(localSID), "end function": calls.endFunction(localSID)}). +func (handler *SRv6VppHandler) addDelLocalSid(deletion bool, sidAddr net.IP, localSID *srv6.LocalSID, swIfIndex ifaceidx.SwIfIndex) error { + handler.log.WithFields(logging.Fields{"localSID": sidAddr, "delete": deletion, "FIB table ID": handler.fibTableID(localSID), "end function": handler.endFunction(localSID)}). Debug("Adding/deleting Local SID", sidAddr) defer func(t time.Time) { - calls.stopwatch.TimeLog(sr.SrLocalsidAddDel{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(sr.SrLocalsidAddDel{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &sr.SrLocalsidAddDel{ - IsDel: boolToUint(deletion), - LocalsidAddr: []byte(sidAddr), + IsDel: boolToUint(deletion), + Localsid: sr.Srv6Sid{Addr: []byte(sidAddr)}, } if !deletion { req.FibTable = localSID.FibTableId // where to install localsid entry - if err := calls.writeEndFunction(req, sidAddr, localSID, swIfIndex); err != nil { + if err := handler.writeEndFunction(req, sidAddr, localSID, swIfIndex); err != nil { return err } } reply := &sr.SrLocalsidAddDelReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err } if reply.Retval != 0 { return fmt.Errorf("vpp call %q returned: %d", reply.GetMessageName(), reply.Retval) } - calls.log.WithFields(logging.Fields{"localSID": sidAddr, "delete": deletion, "FIB table ID": calls.fibTableID(localSID), "end function": calls.endFunction(localSID)}). + handler.log.WithFields(logging.Fields{"localSID": sidAddr, "delete": deletion, "FIB table ID": handler.fibTableID(localSID), "end function": handler.endFunction(localSID)}). Debug("Added/deleted Local SID ", sidAddr) return nil } -func (calls *srv6Calls) fibTableID(localSID *srv6.LocalSID) string { +func (handler *SRv6VppHandler) fibTableID(localSID *srv6.LocalSID) string { if localSID != nil { return string(localSID.FibTableId) } return "" } -func (calls *srv6Calls) endFunction(localSID *srv6.LocalSID) string { +func (handler *SRv6VppHandler) endFunction(localSID *srv6.LocalSID) string { if localSID == nil { return "" } else if localSID.BaseEndFunction != nil { @@ -165,7 +128,7 @@ func (calls *srv6Calls) endFunction(localSID *srv6.LocalSID) string { return "unknown end function" } -func (calls *srv6Calls) writeEndFunction(req *sr.SrLocalsidAddDel, sidAddr net.IP, localSID *srv6.LocalSID, swIfIndex ifaceidx.SwIfIndex) error { +func (handler *SRv6VppHandler) writeEndFunction(req *sr.SrLocalsidAddDel, sidAddr net.IP, localSID *srv6.LocalSID, swIfIndex ifaceidx.SwIfIndex) error { if localSID.BaseEndFunction != nil { req.Behavior = BehaviorEnd req.EndPsp = boolToUint(localSID.BaseEndFunction.Psp) @@ -177,11 +140,15 @@ func (calls *srv6Calls) writeEndFunction(req *sr.SrLocalsidAddDel, sidAddr net.I return fmt.Errorf("for interface %v doesn't exist sw index", localSID.EndFunction_X.OutgoingInterface) } req.SwIfIndex = interfaceSwIndex - nhAddr, err := parseIPv6(localSID.EndFunction_X.NextHop) + nhAddr, err := parseIPv6(localSID.EndFunction_X.NextHop) // parses also ipv4 addresses but into ipv6 address form if err != nil { return err } - req.NhAddr = []byte(nhAddr) + if nhAddr4 := nhAddr.To4(); nhAddr4 != nil { // ipv4 address in ipv6 address form? + req.NhAddr4 = nhAddr4 + } else { + req.NhAddr6 = []byte(nhAddr) + } } else if localSID.EndFunction_T != nil { req.Behavior = BehaviorT req.EndPsp = boolToUint(localSID.EndFunction_T.Psp) @@ -193,11 +160,15 @@ func (calls *srv6Calls) writeEndFunction(req *sr.SrLocalsidAddDel, sidAddr net.I return fmt.Errorf("for interface %v doesn't exist sw index", localSID.EndFunction_DX2.OutgoingInterface) } req.SwIfIndex = interfaceSwIndex - nhAddr, err := parseIPv6(localSID.EndFunction_DX2.NextHop) + nhAddr, err := parseIPv6(localSID.EndFunction_DX2.NextHop) // parses also ipv4 addresses but into ipv6 address form if err != nil { return err } - req.NhAddr = []byte(nhAddr) + if nhAddr4 := nhAddr.To4(); nhAddr4 != nil { // ipv4 address in ipv6 address form? + req.NhAddr4 = nhAddr4 + } else { + req.NhAddr6 = []byte(nhAddr) + } } else if localSID.EndFunction_DX4 != nil { req.Behavior = BehaviorDX4 interfaceSwIndex, _, exists := swIfIndex.LookupIdx(localSID.EndFunction_DX4.OutgoingInterface) @@ -209,10 +180,11 @@ func (calls *srv6Calls) writeEndFunction(req *sr.SrLocalsidAddDel, sidAddr net.I if err != nil { return err } - if nhAddr.To4() == nil { + nhAddr4 := nhAddr.To4() + if nhAddr4 == nil { return fmt.Errorf("next hop of DX4 end function (%v) is not valid IPv4 address", localSID.EndFunction_DX4.NextHop) } - req.NhAddr = []byte(nhAddr) + req.NhAddr4 = []byte(nhAddr4) } else if localSID.EndFunction_DX6 != nil { req.Behavior = BehaviorDX6 interfaceSwIndex, _, exists := swIfIndex.LookupIdx(localSID.EndFunction_DX6.OutgoingInterface) @@ -220,11 +192,11 @@ func (calls *srv6Calls) writeEndFunction(req *sr.SrLocalsidAddDel, sidAddr net.I return fmt.Errorf("for interface %v doesn't exist sw index", localSID.EndFunction_DX6.OutgoingInterface) } req.SwIfIndex = interfaceSwIndex - nhAddr, err := parseIPv6(localSID.EndFunction_DX6.NextHop) + nhAddr6, err := parseIPv6(localSID.EndFunction_DX6.NextHop) if err != nil { return err } - req.NhAddr = []byte(nhAddr) + req.NhAddr6 = []byte(nhAddr6) } else if localSID.EndFunction_DT4 != nil { req.Behavior = BehaviorDT4 } else if localSID.EndFunction_DT6 != nil { @@ -236,10 +208,10 @@ func (calls *srv6Calls) writeEndFunction(req *sr.SrLocalsidAddDel, sidAddr net.I } // SetEncapsSourceAddress sets for SRv6 in VPP the source address used for encapsulated packet -func (calls *srv6Calls) SetEncapsSourceAddress(address string, vppChan govppapi.Channel) error { - calls.log.Debugf("Configuring encapsulation source address to address %v", address) +func (handler *SRv6VppHandler) SetEncapsSourceAddress(address string) error { + handler.log.Debugf("Configuring encapsulation source address to address %v", address) defer func(t time.Time) { - calls.stopwatch.TimeLog(sr.SrSetEncapSource{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(sr.SrSetEncapSource{}).LogTimeEntry(time.Since(t)) }(time.Now()) ipAddress, err := parseIPv6(address) @@ -251,118 +223,116 @@ func (calls *srv6Calls) SetEncapsSourceAddress(address string, vppChan govppapi. } reply := &sr.SrSetEncapSourceReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err } if reply.Retval != 0 { return fmt.Errorf("vpp call %q returned: %d", reply.GetMessageName(), reply.Retval) } - calls.log.WithFields(logging.Fields{"Encapsulation source address": address}). + handler.log.WithFields(logging.Fields{"Encapsulation source address": address}). Debug("Encapsulation source address configured.") return nil } // AddPolicy adds SRv6 policy given by identified ,initial segment for policy and other policy settings in -func (calls *srv6Calls) AddPolicy(bindingSid net.IP, policy *srv6.Policy, policySegment *srv6.PolicySegment, vppChan govppapi.Channel) error { - calls.log.Debugf("Adding SR policy with binding SID %v and list of next SIDs %v", bindingSid, policySegment.Segments) +func (handler *SRv6VppHandler) AddPolicy(bindingSid net.IP, policy *srv6.Policy, policySegment *srv6.PolicySegment) error { + handler.log.Debugf("Adding SR policy with binding SID %v and list of next SIDs %v", bindingSid, policySegment.Segments) defer func(t time.Time) { - calls.stopwatch.TimeLog(sr.SrPolicyAdd{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(sr.SrPolicyAdd{}).LogTimeEntry(time.Since(t)) }(time.Now()) - segmentsCount, segments, err := calls.convertNextSidList(policySegment.Segments) + sids, err := handler.convertPolicySegment(policySegment) if err != nil { return err } + // Note: Weight in sr.SrPolicyAdd is leftover from API changes that moved weight into sr.Srv6SidList (it is weight of sid list not of the whole policy) req := &sr.SrPolicyAdd{ - BsidAddr: []byte(bindingSid), - Weight: policySegment.Weight, - NSegments: segmentsCount, - Segments: segments, - IsEncap: boolToUint(policy.SrhEncapsulation), - Type: boolToUint(policy.SprayBehaviour), - FibTable: policy.FibTableId, + BsidAddr: []byte(bindingSid), + Sids: *sids, + IsEncap: boolToUint(policy.SrhEncapsulation), + Type: boolToUint(policy.SprayBehaviour), + FibTable: policy.FibTableId, } reply := &sr.SrPolicyAddReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err } if reply.Retval != 0 { return fmt.Errorf("vpp call %q returned: %d", reply.GetMessageName(), reply.Retval) } - calls.log.WithFields(logging.Fields{"binding SID": bindingSid, "list of next SIDs": policySegment.Segments}). + handler.log.WithFields(logging.Fields{"binding SID": bindingSid, "list of next SIDs": policySegment.Segments}). Debug("SR policy added") return nil } // DeletePolicy deletes SRv6 policy given by binding SID -func (calls *srv6Calls) DeletePolicy(bindingSid net.IP, vppChan govppapi.Channel) error { - calls.log.Debugf("Deleting SR policy with binding SID %v ", bindingSid) +func (handler *SRv6VppHandler) DeletePolicy(bindingSid net.IP) error { + handler.log.Debugf("Deleting SR policy with binding SID %v ", bindingSid) defer func(t time.Time) { - calls.stopwatch.TimeLog(sr.SrPolicyDel{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(sr.SrPolicyDel{}).LogTimeEntry(time.Since(t)) }(time.Now()) req := &sr.SrPolicyDel{ - BsidAddr: []byte(bindingSid), // TODO add ability to define policy also by index (SrPolicyIndex) + BsidAddr: sr.Srv6Sid{Addr: []byte(bindingSid)}, // TODO add ability to define policy also by index (SrPolicyIndex) } reply := &sr.SrPolicyDelReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err } if reply.Retval != 0 { return fmt.Errorf("vpp call %q returned: %d", reply.GetMessageName(), reply.Retval) } - calls.log.WithFields(logging.Fields{"binding SID": bindingSid}). + handler.log.WithFields(logging.Fields{"binding SID": bindingSid}). Debug("SR policy deleted") return nil } // AddPolicySegment adds segment to SRv6 policy that has policy BSID -func (calls *srv6Calls) AddPolicySegment(bindingSid net.IP, policy *srv6.Policy, policySegment *srv6.PolicySegment, vppChan govppapi.Channel) error { - calls.log.Debugf("Adding segment %v to SR policy with binding SID %v", policySegment.Segments, bindingSid) - err := calls.modPolicy(AddSRList, bindingSid, policy, policySegment, 0, vppChan) +func (handler *SRv6VppHandler) AddPolicySegment(bindingSid net.IP, policy *srv6.Policy, policySegment *srv6.PolicySegment) error { + handler.log.Debugf("Adding segment %v to SR policy with binding SID %v", policySegment.Segments, bindingSid) + err := handler.modPolicy(AddSRList, bindingSid, policy, policySegment, 0) if err == nil { - calls.log.WithFields(logging.Fields{"binding SID": bindingSid, "list of next SIDs": policySegment.Segments}). + handler.log.WithFields(logging.Fields{"binding SID": bindingSid, "list of next SIDs": policySegment.Segments}). Debug("SR policy modified(added another segment list)") } return err } // DeletePolicySegment removes segment (with segment index ) from SRv6 policy that has policy BSID -func (calls *srv6Calls) DeletePolicySegment(bindingSid net.IP, policy *srv6.Policy, policySegment *srv6.PolicySegment, - segmentIndex uint32, vppChan govppapi.Channel) error { - calls.log.Debugf("Removing segment %v (index %v) from SR policy with binding SID %v", policySegment.Segments, segmentIndex, bindingSid) - err := calls.modPolicy(DeleteSRList, bindingSid, policy, policySegment, segmentIndex, vppChan) +func (handler *SRv6VppHandler) DeletePolicySegment(bindingSid net.IP, policy *srv6.Policy, policySegment *srv6.PolicySegment, + segmentIndex uint32) error { + handler.log.Debugf("Removing segment %v (index %v) from SR policy with binding SID %v", policySegment.Segments, segmentIndex, bindingSid) + err := handler.modPolicy(DeleteSRList, bindingSid, policy, policySegment, segmentIndex) if err == nil { - calls.log.WithFields(logging.Fields{"binding SID": bindingSid, "list of next SIDs": policySegment.Segments, "segmentIndex": segmentIndex}). + handler.log.WithFields(logging.Fields{"binding SID": bindingSid, "list of next SIDs": policySegment.Segments, "segmentIndex": segmentIndex}). Debug("SR policy modified(removed segment list)") } return err } -func (calls *srv6Calls) modPolicy(operation uint8, bindingSid net.IP, policy *srv6.Policy, policySegment *srv6.PolicySegment, - segmentIndex uint32, vppChan govppapi.Channel) error { +func (handler *SRv6VppHandler) modPolicy(operation uint8, bindingSid net.IP, policy *srv6.Policy, policySegment *srv6.PolicySegment, + segmentIndex uint32) error { defer func(t time.Time) { - calls.stopwatch.TimeLog(sr.SrPolicyMod{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(sr.SrPolicyMod{}).LogTimeEntry(time.Since(t)) }(time.Now()) - segmentsCount, segments, err := calls.convertNextSidList(policySegment.Segments) + sids, err := handler.convertPolicySegment(policySegment) if err != nil { return err } + // Note: Weight in sr.SrPolicyMod is leftover from API changes that moved weight into sr.Srv6SidList (it is weight of sid list not of the whole policy) req := &sr.SrPolicyMod{ BsidAddr: []byte(bindingSid), // TODO add ability to define policy also by index (SrPolicyIndex) Operation: operation, - Weight: policySegment.Weight, - NSegments: segmentsCount, - Segments: segments, + Sids: *sids, FibTable: policy.FibTableId, } if operation == DeleteSRList || operation == ModifyWeightOfSRList { @@ -371,7 +341,7 @@ func (calls *srv6Calls) modPolicy(operation uint8, bindingSid net.IP, policy *sr reply := &sr.SrPolicyModReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err } if reply.Retval != 0 { @@ -380,40 +350,42 @@ func (calls *srv6Calls) modPolicy(operation uint8, bindingSid net.IP, policy *sr return nil } -func (calls *srv6Calls) convertNextSidList(nextSidList []string) (uint8, []sr.SrIP6Address, error) { - segments := make([]sr.SrIP6Address, 0) - for _, sid := range nextSidList { +func (handler *SRv6VppHandler) convertPolicySegment(policySegment *srv6.PolicySegment) (*sr.Srv6SidList, error) { + var segments []sr.Srv6Sid + for _, sid := range policySegment.Segments { // parse to IPv6 address parserSid, err := parseIPv6(sid) if err != nil { - return 0, []sr.SrIP6Address{}, err + return nil, err } // add sid to segment list - ipv6Segment := sr.SrIP6Address{ - Data: make([]byte, 16), // sr.SrIP6Address.Data = [16]byte + ipv6Segment := sr.Srv6Sid{ + Addr: make([]byte, 16), // sr.Srv6Sid.Addr = [16]byte } - copy(ipv6Segment.Data, parserSid) + copy(ipv6Segment.Addr, parserSid) segments = append(segments, ipv6Segment) } - return uint8(len(nextSidList)), segments, nil + return &sr.Srv6SidList{ + NumSids: uint8(len(segments)), + Sids: segments, + Weight: policySegment.Weight, + }, nil } // AddSteering sets in VPP steering into SRv6 policy. -func (calls *srv6Calls) AddSteering(steering *srv6.Steering, swIfIndex ifaceidx.SwIfIndex, - vppChan govppapi.Channel) error { - return calls.addDelSteering(false, steering, swIfIndex, vppChan) +func (handler *SRv6VppHandler) AddSteering(steering *srv6.Steering, swIfIndex ifaceidx.SwIfIndex) error { + return handler.addDelSteering(false, steering, swIfIndex) } // RemoveSteering removes in VPP steering into SRv6 policy. -func (calls *srv6Calls) RemoveSteering(steering *srv6.Steering, swIfIndex ifaceidx.SwIfIndex, - vppChan govppapi.Channel) error { - return calls.addDelSteering(true, steering, swIfIndex, vppChan) +func (handler *SRv6VppHandler) RemoveSteering(steering *srv6.Steering, swIfIndex ifaceidx.SwIfIndex) error { + return handler.addDelSteering(true, steering, swIfIndex) } -func (calls *srv6Calls) addDelSteering(delete bool, steering *srv6.Steering, swIfIndex ifaceidx.SwIfIndex, vppChan govppapi.Channel) error { +func (handler *SRv6VppHandler) addDelSteering(delete bool, steering *srv6.Steering, swIfIndex ifaceidx.SwIfIndex) error { defer func(t time.Time) { - calls.stopwatch.TimeLog(sr.SrSteeringAddDel{}).LogTimeEntry(time.Since(t)) + handler.stopwatch.TimeLog(sr.SrSteeringAddDel{}).LogTimeEntry(time.Since(t)) }(time.Now()) // defining operation strings for logging @@ -424,15 +396,15 @@ func (calls *srv6Calls) addDelSteering(delete bool, steering *srv6.Steering, swI // logging info about operation with steering if steering.L3Traffic != nil { - calls.log.Debugf("%v steering for l3 traffic with destination %v to SR policy (binding SID %v, policy index %v)", + handler.log.Debugf("%v steering for l3 traffic with destination %v to SR policy (binding SID %v, policy index %v)", operationProgressing, steering.L3Traffic.PrefixAddress, steering.PolicyBsid, steering.PolicyIndex) } else { - calls.log.Debugf("%v steering for l2 traffic from interface %v to SR policy (binding SID %v, policy index %v)", + handler.log.Debugf("%v steering for l2 traffic from interface %v to SR policy (binding SID %v, policy index %v)", operationProgressing, steering.L2Traffic.InterfaceName, steering.PolicyBsid, steering.PolicyIndex) } // converting policy reference - bsidAddr := make([]byte, 0) + var bsidAddr []byte if len(strings.Trim(steering.PolicyBsid, " ")) > 0 { bsid, err := parseIPv6(steering.PolicyBsid) if err != nil { @@ -479,14 +451,14 @@ func (calls *srv6Calls) addDelSteering(delete bool, steering *srv6.Steering, swI } reply := &sr.SrSteeringAddDelReply{} - if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil { + if err := handler.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { return err } if reply.Retval != 0 { return fmt.Errorf("vpp call %q returned: %d", reply.GetMessageName(), reply.Retval) } - calls.log.WithFields(logging.Fields{"steer type": steerType, "L3 prefix address bytes": prefixAddr, + handler.log.WithFields(logging.Fields{"steer type": steerType, "L3 prefix address bytes": prefixAddr, "L2 interface index": intIndex, "policy binding SID": bsidAddr, "policy index": steering.PolicyIndex}). Debugf("%v steering to SR policy ", operationFinished) diff --git a/plugins/vpp/srplugin/vppcalls/srv6_test.go b/plugins/vpp/srplugin/vppcalls/srv6_test.go index 5b647f5f3d..2848e53ac7 100644 --- a/plugins/vpp/srplugin/vppcalls/srv6_test.go +++ b/plugins/vpp/srplugin/vppcalls/srv6_test.go @@ -39,11 +39,11 @@ const ( ) var ( - sidA = sid("A::") - sidB = sid("B::") - sidC = sid("C::") + sidA = *sid("A::") + sidB = *sid("B::") + sidC = *sid("C::") nextHop = net.ParseIP("B::").To16() - nextHopIPv4 = net.ParseIP("1.2.3.4") + nextHopIPv4 = net.ParseIP("1.2.3.4").To4() ) var swIfIndex = ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), "sw_if_indexes", ifaceidx.IndexMetadata)) @@ -52,6 +52,7 @@ func init() { swIfIndex.RegisterName(ifaceA, swIndexA, nil) } +// TODO add tests for new nhAddr4 field in end behaviours // TestAddLocalSID tests all cases for method AddLocalSID func TestAddLocalSID(t *testing.T) { // Prepare different cases @@ -71,15 +72,15 @@ func TestAddLocalSID(t *testing.T) { }, }, Expected: &sr.SrLocalsidAddDel{ - IsDel: 0, - LocalsidAddr: sidA, - Behavior: vppcalls.BehaviorEnd, - FibTable: 10, - EndPsp: 1, + IsDel: 0, + Localsid: sidA, + Behavior: vppcalls.BehaviorEnd, + FibTable: 10, + EndPsp: 1, }, }, { - Name: "addition with endX behaviour", + Name: "addition with endX behaviour (ipv6 next hop address)", Input: &srv6.LocalSID{ FibTableId: 10, EndFunction_X: &srv6.LocalSID_EndX{ @@ -89,13 +90,33 @@ func TestAddLocalSID(t *testing.T) { }, }, Expected: &sr.SrLocalsidAddDel{ - IsDel: 0, - LocalsidAddr: sidA, - Behavior: vppcalls.BehaviorX, - FibTable: 10, - EndPsp: 1, - SwIfIndex: swIndexA, - NhAddr: nextHop, + IsDel: 0, + Localsid: sidA, + Behavior: vppcalls.BehaviorX, + FibTable: 10, + EndPsp: 1, + SwIfIndex: swIndexA, + NhAddr6: nextHop, + }, + }, + { + Name: "addition with endX behaviour (ipv4 next hop address)", + Input: &srv6.LocalSID{ + FibTableId: 10, + EndFunction_X: &srv6.LocalSID_EndX{ + Psp: true, + NextHop: nextHopIPv4.String(), + OutgoingInterface: ifaceA, + }, + }, + Expected: &sr.SrLocalsidAddDel{ + IsDel: 0, + Localsid: sidA, + Behavior: vppcalls.BehaviorX, + FibTable: 10, + EndPsp: 1, + SwIfIndex: swIndexA, + NhAddr4: nextHopIPv4, }, }, { @@ -107,15 +128,15 @@ func TestAddLocalSID(t *testing.T) { }, }, Expected: &sr.SrLocalsidAddDel{ - IsDel: 0, - LocalsidAddr: sidA, - Behavior: vppcalls.BehaviorT, - FibTable: 10, - EndPsp: 1, + IsDel: 0, + Localsid: sidA, + Behavior: vppcalls.BehaviorT, + FibTable: 10, + EndPsp: 1, }, }, { - Name: "addition with endDX2 behaviour", + Name: "addition with endDX2 behaviour (ipv6 next hop address)", Input: &srv6.LocalSID{ FibTableId: 10, EndFunction_DX2: &srv6.LocalSID_EndDX2{ @@ -125,14 +146,35 @@ func TestAddLocalSID(t *testing.T) { }, }, Expected: &sr.SrLocalsidAddDel{ - IsDel: 0, - LocalsidAddr: sidA, - Behavior: vppcalls.BehaviorDX2, - FibTable: 10, - EndPsp: 0, - VlanIndex: 1, - SwIfIndex: swIndexA, - NhAddr: nextHop, + IsDel: 0, + Localsid: sidA, + Behavior: vppcalls.BehaviorDX2, + FibTable: 10, + EndPsp: 0, + VlanIndex: 1, + SwIfIndex: swIndexA, + NhAddr6: nextHop, + }, + }, + { + Name: "addition with endDX2 behaviour (ipv4 next hop address)", + Input: &srv6.LocalSID{ + FibTableId: 10, + EndFunction_DX2: &srv6.LocalSID_EndDX2{ + VlanTag: 1, + NextHop: nextHopIPv4.String(), + OutgoingInterface: ifaceA, + }, + }, + Expected: &sr.SrLocalsidAddDel{ + IsDel: 0, + Localsid: sidA, + Behavior: vppcalls.BehaviorDX2, + FibTable: 10, + EndPsp: 0, + VlanIndex: 1, + SwIfIndex: swIndexA, + NhAddr4: nextHopIPv4, }, }, { @@ -145,13 +187,13 @@ func TestAddLocalSID(t *testing.T) { }, }, Expected: &sr.SrLocalsidAddDel{ - IsDel: 0, - LocalsidAddr: sidA, - Behavior: vppcalls.BehaviorDX4, - FibTable: 10, - EndPsp: 0, - SwIfIndex: swIndexA, - NhAddr: nextHopIPv4, + IsDel: 0, + Localsid: sidA, + Behavior: vppcalls.BehaviorDX4, + FibTable: 10, + EndPsp: 0, + SwIfIndex: swIndexA, + NhAddr4: nextHopIPv4, }, }, { @@ -164,13 +206,13 @@ func TestAddLocalSID(t *testing.T) { }, }, Expected: &sr.SrLocalsidAddDel{ - IsDel: 0, - LocalsidAddr: sidA, - Behavior: vppcalls.BehaviorDX6, - FibTable: 10, - EndPsp: 0, - SwIfIndex: swIndexA, - NhAddr: nextHop, + IsDel: 0, + Localsid: sidA, + Behavior: vppcalls.BehaviorDX6, + FibTable: 10, + EndPsp: 0, + SwIfIndex: swIndexA, + NhAddr6: nextHop, }, }, // endDT4 and endDT6 are not fully modelled yet -> testing only current implementation @@ -181,11 +223,11 @@ func TestAddLocalSID(t *testing.T) { EndFunction_DT4: &srv6.LocalSID_EndDT4{}, }, Expected: &sr.SrLocalsidAddDel{ - IsDel: 0, - LocalsidAddr: sidA, - Behavior: vppcalls.BehaviorDT4, - FibTable: 10, - EndPsp: 0, + IsDel: 0, + Localsid: sidA, + Behavior: vppcalls.BehaviorDT4, + FibTable: 10, + EndPsp: 0, }, }, { @@ -195,11 +237,11 @@ func TestAddLocalSID(t *testing.T) { EndFunction_DT6: &srv6.LocalSID_EndDT6{}, }, Expected: &sr.SrLocalsidAddDel{ - IsDel: 0, - LocalsidAddr: sidA, - Behavior: vppcalls.BehaviorDT6, - FibTable: 10, - EndPsp: 0, + IsDel: 0, + Localsid: sidA, + Behavior: vppcalls.BehaviorDT6, + FibTable: 10, + EndPsp: 0, }, }, { @@ -337,7 +379,7 @@ func TestAddLocalSID(t *testing.T) { ctx.MockVpp.MockReply(&sr.SrLocalsidAddDelReply{}) } // make the call - err := vppCalls.AddLocalSid(sidA, td.Input, swIfIndex, ctx.MockChannel) + err := vppCalls.AddLocalSid(sidA.Addr, td.Input, swIfIndex) // verify result if td.ExpectFailure { Expect(err).Should(HaveOccurred()) @@ -361,19 +403,19 @@ func TestDeleteLocalSID(t *testing.T) { }{ { Name: "simple delete of local sid", - Sid: sidA, + Sid: sidA.Addr, MockReply: &sr.SrLocalsidAddDelReply{}, Verify: func(err error, catchedMsg govppapi.Message) { Expect(err).ShouldNot(HaveOccurred()) Expect(catchedMsg).To(Equal(&sr.SrLocalsidAddDel{ - IsDel: 1, - LocalsidAddr: sidA, + IsDel: 1, + Localsid: sidA, })) }, }, { Name: "failure propagation from VPP", - Sid: sidA, + Sid: sidA.Addr, MockReply: &sr.SrLocalsidAddDelReply{Retval: 1}, Verify: func(err error, msg govppapi.Message) { Expect(err).Should(HaveOccurred()) @@ -393,10 +435,10 @@ func TestDeleteLocalSID(t *testing.T) { Psp: true, }, } - vppCalls.AddLocalSid(td.Sid, localsid, swIfIndex, ctx.MockChannel) + vppCalls.AddLocalSid(td.Sid, localsid, swIfIndex) ctx.MockVpp.MockReply(td.MockReply) // make the call and verify - err := vppCalls.DeleteLocalSid(td.Sid, ctx.MockChannel) + err := vppCalls.DeleteLocalSid(td.Sid) td.Verify(err, ctx.MockChannel.Msg) }) } @@ -448,7 +490,7 @@ func TestSetEncapsSourceAddress(t *testing.T) { defer teardown(ctx) ctx.MockVpp.MockReply(td.MockReply) - err := vppCalls.SetEncapsSourceAddress(td.Address, ctx.MockChannel) + err := vppCalls.SetEncapsSourceAddress(td.Address) td.Verify(err, ctx.MockChannel.Msg) }) } @@ -468,30 +510,32 @@ func TestAddPolicy(t *testing.T) { }{ { Name: "simple SetAddPolicy", - BSID: sidA, + BSID: sidA.Addr, Policy: policy(10, false, true), - PolicySegment: policySegment(1, sidA, sidB, sidC), + PolicySegment: policySegment(1, sidA.Addr, sidB.Addr, sidC.Addr), MockReply: &sr.SrPolicyAddReply{}, Verify: func(err error, catchedMsg govppapi.Message) { Expect(err).ShouldNot(HaveOccurred()) Expect(catchedMsg).To(Equal(&sr.SrPolicyAdd{ - BsidAddr: sidA, - FibTable: 10, - Type: boolToUint(false), - IsEncap: boolToUint(true), - Weight: 1, - NSegments: 3, - Segments: []sr.SrIP6Address{{Data: sidA}, {Data: sidB}, {Data: sidC}}, + BsidAddr: sidA.Addr, + FibTable: 10, + Type: boolToUint(false), + IsEncap: boolToUint(true), + Sids: sr.Srv6SidList{ + Weight: 1, + NumSids: 3, + Sids: []sr.Srv6Sid{{Addr: sidA.Addr}, {Addr: sidB.Addr}, {Addr: sidC.Addr}}, + }, })) }, }, { Name: "invalid SID (not IP address) in segment list", - BSID: sidA, + BSID: sidA.Addr, Policy: policy(10, false, true), PolicySegment: &srv6.PolicySegment{ Weight: 1, - Segments: []string{sidA.String(), invalidIPAddress, sidC.String()}, + Segments: []string{sidToStr(sidA), invalidIPAddress, sidToStr(sidC)}, }, MockReply: &sr.SrPolicyAddReply{}, Verify: func(err error, catchedMsg govppapi.Message) { @@ -500,9 +544,9 @@ func TestAddPolicy(t *testing.T) { }, { Name: "failure propagation from VPP", - BSID: sidA, + BSID: sidA.Addr, Policy: policy(0, true, true), - PolicySegment: policySegment(1, sidA, sidB, sidC), + PolicySegment: policySegment(1, sidA.Addr, sidB.Addr, sidC.Addr), MockReply: &sr.SrPolicyAddReply{Retval: 1}, Verify: func(err error, msg govppapi.Message) { Expect(err).Should(HaveOccurred()) @@ -517,7 +561,7 @@ func TestAddPolicy(t *testing.T) { defer teardown(ctx) // prepare reply, make call and verify ctx.MockVpp.MockReply(td.MockReply) - err := vppCalls.AddPolicy(td.BSID, td.Policy, td.PolicySegment, ctx.MockChannel) + err := vppCalls.AddPolicy(td.BSID, td.Policy, td.PolicySegment) td.Verify(err, ctx.MockChannel.Msg) }) } @@ -534,7 +578,7 @@ func TestDeletePolicy(t *testing.T) { }{ { Name: "simple delete of policy", - BSID: sidA, + BSID: sidA.Addr, MockReply: &sr.SrPolicyDelReply{}, Verify: func(err error, catchedMsg govppapi.Message) { Expect(err).ShouldNot(HaveOccurred()) @@ -545,7 +589,7 @@ func TestDeletePolicy(t *testing.T) { }, { Name: "failure propagation from VPP", - BSID: sidA, + BSID: sidA.Addr, MockReply: &sr.SrPolicyDelReply{Retval: 1}, Verify: func(err error, msg govppapi.Message) { Expect(err).Should(HaveOccurred()) @@ -560,11 +604,11 @@ func TestDeletePolicy(t *testing.T) { defer teardown(ctx) // data and prepare case policy := policy(0, true, true) - segment := policySegment(1, sidA, sidB, sidC) - vppCalls.AddPolicy(td.BSID, policy, segment, ctx.MockChannel) + segment := policySegment(1, sidA.Addr, sidB.Addr, sidC.Addr) + vppCalls.AddPolicy(td.BSID, policy, segment) ctx.MockVpp.MockReply(td.MockReply) // make the call and verify - err := vppCalls.DeletePolicy(td.BSID, ctx.MockChannel) + err := vppCalls.DeletePolicy(td.BSID) td.Verify(err, ctx.MockChannel.Msg) }) } @@ -583,29 +627,31 @@ func TestAddPolicySegment(t *testing.T) { }{ { Name: "simple addition of policy segment", - BSID: sidA, + BSID: sidA.Addr, Policy: policy(10, false, true), - PolicySegment: policySegment(1, sidA, sidB, sidC), + PolicySegment: policySegment(1, sidA.Addr, sidB.Addr, sidC.Addr), MockReply: &sr.SrPolicyModReply{}, Verify: func(err error, catchedMsg govppapi.Message) { Expect(err).ShouldNot(HaveOccurred()) Expect(catchedMsg).To(Equal(&sr.SrPolicyMod{ - BsidAddr: sidA, + BsidAddr: sidA.Addr, Operation: vppcalls.AddSRList, FibTable: 10, - Weight: 1, - NSegments: 3, - Segments: []sr.SrIP6Address{{Data: sidA}, {Data: sidB}, {Data: sidC}}, + Sids: sr.Srv6SidList{ + Weight: 1, + NumSids: 3, + Sids: []sr.Srv6Sid{{Addr: sidA.Addr}, {Addr: sidB.Addr}, {Addr: sidC.Addr}}, + }, })) }, }, { Name: "invalid SID (not IP address) in segment list", - BSID: sidA, + BSID: sidA.Addr, Policy: policy(10, false, true), PolicySegment: &srv6.PolicySegment{ Weight: 1, - Segments: []string{sidA.String(), invalidIPAddress, sidC.String()}, + Segments: []string{sidToStr(sidA), invalidIPAddress, sidToStr(sidC)}, }, MockReply: &sr.SrPolicyModReply{}, Verify: func(err error, catchedMsg govppapi.Message) { @@ -614,9 +660,9 @@ func TestAddPolicySegment(t *testing.T) { }, { Name: "failure propagation from VPP", - BSID: sidA, + BSID: sidA.Addr, Policy: policy(0, true, true), - PolicySegment: policySegment(1, sidA, sidB, sidC), + PolicySegment: policySegment(1, sidA.Addr, sidB.Addr, sidC.Addr), MockReply: &sr.SrPolicyModReply{Retval: 1}, Verify: func(err error, msg govppapi.Message) { Expect(err).Should(HaveOccurred()) @@ -631,7 +677,7 @@ func TestAddPolicySegment(t *testing.T) { defer teardown(ctx) // prepare reply, make call and verify ctx.MockVpp.MockReply(td.MockReply) - err := vppCalls.AddPolicySegment(td.BSID, td.Policy, td.PolicySegment, ctx.MockChannel) + err := vppCalls.AddPolicySegment(td.BSID, td.Policy, td.PolicySegment) td.Verify(err, ctx.MockChannel.Msg) }) } @@ -651,31 +697,33 @@ func TestDeletePolicySegment(t *testing.T) { }{ { Name: "simple deletion of policy segment", - BSID: sidA, + BSID: sidA.Addr, Policy: policy(10, false, true), - PolicySegment: policySegment(1, sidA, sidB, sidC), + PolicySegment: policySegment(1, sidA.Addr, sidB.Addr, sidC.Addr), SegmentIndex: 111, MockReply: &sr.SrPolicyModReply{}, Verify: func(err error, catchedMsg govppapi.Message) { Expect(err).ShouldNot(HaveOccurred()) Expect(catchedMsg).To(Equal(&sr.SrPolicyMod{ - BsidAddr: sidA, + BsidAddr: sidA.Addr, Operation: vppcalls.DeleteSRList, SlIndex: 111, FibTable: 10, - Weight: 1, - NSegments: 3, - Segments: []sr.SrIP6Address{{Data: sidA}, {Data: sidB}, {Data: sidC}}, + Sids: sr.Srv6SidList{ + Weight: 1, + NumSids: 3, + Sids: []sr.Srv6Sid{{Addr: sidA.Addr}, {Addr: sidB.Addr}, {Addr: sidC.Addr}}, + }, })) }, }, { Name: "invalid SID (not IP address) in segment list", - BSID: sidA, + BSID: sidA.Addr, Policy: policy(10, false, true), PolicySegment: &srv6.PolicySegment{ Weight: 1, - Segments: []string{sidA.String(), invalidIPAddress, sidC.String()}, + Segments: []string{sidToStr(sidA), invalidIPAddress, sidToStr(sidC)}, }, SegmentIndex: 111, MockReply: &sr.SrPolicyModReply{}, @@ -685,9 +733,9 @@ func TestDeletePolicySegment(t *testing.T) { }, { Name: "failure propagation from VPP", - BSID: sidA, + BSID: sidA.Addr, Policy: policy(0, true, true), - PolicySegment: policySegment(1, sidA, sidB, sidC), + PolicySegment: policySegment(1, sidA.Addr, sidB.Addr, sidC.Addr), SegmentIndex: 111, MockReply: &sr.SrPolicyModReply{Retval: 1}, Verify: func(err error, msg govppapi.Message) { @@ -703,7 +751,7 @@ func TestDeletePolicySegment(t *testing.T) { defer teardown(ctx) // prepare reply, make call and verify ctx.MockVpp.MockReply(td.MockReply) - err := vppCalls.DeletePolicySegment(td.BSID, td.Policy, td.PolicySegment, td.SegmentIndex, ctx.MockChannel) + err := vppCalls.DeletePolicySegment(td.BSID, td.Policy, td.PolicySegment, td.SegmentIndex) td.Verify(err, ctx.MockChannel.Msg) }) } @@ -734,7 +782,7 @@ func testAddRemoveSteering(t *testing.T, removal bool) { { Name: action + " of IPv6 L3 steering", Steering: &srv6.Steering{ - PolicyBsid: sidA.String(), + PolicyBsid: sidToStr(sidA), L3Traffic: &srv6.Steering_L3Traffic{ FibTableId: 10, PrefixAddress: "1::/64", @@ -745,7 +793,7 @@ func testAddRemoveSteering(t *testing.T, removal bool) { Expect(err).ShouldNot(HaveOccurred()) Expect(catchedMsg).To(Equal(&sr.SrSteeringAddDel{ IsDel: boolToUint(removal), - BsidAddr: sidA, + BsidAddr: sidA.Addr, TableID: 10, TrafficType: vppcalls.SteerTypeIPv6, PrefixAddr: net.ParseIP("1::").To16(), @@ -756,7 +804,7 @@ func testAddRemoveSteering(t *testing.T, removal bool) { { Name: action + " of IPv4 L3 steering", Steering: &srv6.Steering{ - PolicyBsid: sidA.String(), + PolicyBsid: sidToStr(sidA), L3Traffic: &srv6.Steering_L3Traffic{ FibTableId: 10, PrefixAddress: "1.2.3.4/24", @@ -767,7 +815,7 @@ func testAddRemoveSteering(t *testing.T, removal bool) { Expect(err).ShouldNot(HaveOccurred()) Expect(catchedMsg).To(Equal(&sr.SrSteeringAddDel{ IsDel: boolToUint(removal), - BsidAddr: sidA, + BsidAddr: sidA.Addr, TableID: 10, TrafficType: vppcalls.SteerTypeIPv4, PrefixAddr: net.ParseIP("1.2.3.4").To16(), @@ -778,7 +826,7 @@ func testAddRemoveSteering(t *testing.T, removal bool) { { Name: action + " of L2 steering", Steering: &srv6.Steering{ - PolicyBsid: sidA.String(), + PolicyBsid: sidToStr(sidA), L2Traffic: &srv6.Steering_L2Traffic{ InterfaceName: ifaceA, }, @@ -788,7 +836,7 @@ func testAddRemoveSteering(t *testing.T, removal bool) { Expect(err).ShouldNot(HaveOccurred()) Expect(catchedMsg).To(Equal(&sr.SrSteeringAddDel{ IsDel: boolToUint(removal), - BsidAddr: sidA, + BsidAddr: sidA.Addr, TrafficType: vppcalls.SteerTypeL2, SwIfIndex: swIndexA, })) @@ -797,7 +845,7 @@ func testAddRemoveSteering(t *testing.T, removal bool) { { Name: "invalid prefix (" + action + " of IPv4 L3 steering)", Steering: &srv6.Steering{ - PolicyBsid: sidA.String(), + PolicyBsid: sidToStr(sidA), L3Traffic: &srv6.Steering_L3Traffic{ FibTableId: 10, PrefixAddress: invalidIPAddress, @@ -811,7 +859,7 @@ func testAddRemoveSteering(t *testing.T, removal bool) { { Name: "interface without index (" + action + " of L2 steering)", Steering: &srv6.Steering{ - PolicyBsid: sidA.String(), + PolicyBsid: sidToStr(sidA), L2Traffic: &srv6.Steering_L2Traffic{ InterfaceName: ifaceBOutOfidxs, }, @@ -838,7 +886,7 @@ func testAddRemoveSteering(t *testing.T, removal bool) { { Name: "failure propagation from VPP", Steering: &srv6.Steering{ - PolicyBsid: sidA.String(), + PolicyBsid: sidToStr(sidA), L3Traffic: &srv6.Steering_L3Traffic{ FibTableId: 10, PrefixAddress: "1::/64", @@ -860,18 +908,18 @@ func testAddRemoveSteering(t *testing.T, removal bool) { ctx.MockVpp.MockReply(td.MockReply) var err error if removal { - err = vppCalls.RemoveSteering(td.Steering, swIfIndex, ctx.MockChannel) + err = vppCalls.RemoveSteering(td.Steering, swIfIndex) } else { - err = vppCalls.AddSteering(td.Steering, swIfIndex, ctx.MockChannel) + err = vppCalls.AddSteering(td.Steering, swIfIndex) } td.Verify(err, ctx.MockChannel.Msg) }) } } -func setup(t *testing.T) (*vppcallmock.TestCtx, vppcalls.SRv6Calls) { +func setup(t *testing.T) (*vppcallmock.TestCtx, vppcalls.SRv6VppAPI) { ctx := vppcallmock.SetupTestCtx(t) - vppCalls := vppcalls.NewSRv6Calls(logrus.DefaultLogger(), nil) + vppCalls := vppcalls.NewSRv6VppHandler(ctx.MockChannel, logrus.DefaultLogger(), nil) return ctx, vppCalls } @@ -879,12 +927,14 @@ func teardown(ctx *vppcallmock.TestCtx) { ctx.TeardownTestCtx() } -func sid(str string) srv6.SID { +func sid(str string) *sr.Srv6Sid { bsid, err := srplugin.ParseIPv6(str) if err != nil { panic(fmt.Sprintf("can't parse %q into SRv6 BSID (IPv6 address)", str)) } - return bsid + return &sr.Srv6Sid{ + Addr: bsid, + } } func policy(fibtableID uint32, sprayBehaviour bool, srhEncapsulation bool) *srv6.Policy { @@ -913,3 +963,7 @@ func boolToUint(input bool) uint8 { } return uint8(0) } + +func sidToStr(sid sr.Srv6Sid) string { + return srv6.SID(sid.Addr).String() +} diff --git a/plugins/vpp/vpp-plugin.conf b/plugins/vpp/vpp-plugin.conf index d718e4dd0f..f10ad2e04c 100644 --- a/plugins/vpp/vpp-plugin.conf +++ b/plugins/vpp/vpp-plugin.conf @@ -3,11 +3,11 @@ # Default maximum transmission unit. The value is used if an interface without MTU is created (it means MTU in # interface configuration is preferred). -mtu: 1478 +mtu: 0 # Enable or disable feature to measure binary API call duration. Measured time is shown directly in log (info level). # Measurement is taken also for certain procedures, like resync of plugin startup. Turned off by default. -stopwatch: true +stopwatch: false # VPP plugin resync strategy. Available options are [full] and [optimize]. Full strategy is default, and always performs # the resync, optimize can be used for cold start; it looks for interface configuration looking for interfaces. If there @@ -15,5 +15,5 @@ stopwatch: true strategy: full # VPP agent allows to send status data back to ETCD. To allow it, add desired status publishers. Currently supported -# for [etcd] and [redis] (both options can be chosen) -status-publishers: [redis] \ No newline at end of file +# for [etcd] and [redis] (both options can be chosen together) +status-publishers: \ No newline at end of file diff --git a/plugins/vpp/watch_events.go b/plugins/vpp/watch_events.go index 01e0c7447b..79fbf48eeb 100644 --- a/plugins/vpp/watch_events.go +++ b/plugins/vpp/watch_events.go @@ -98,7 +98,7 @@ func (plugin *Plugin) onStatusResyncEvent(e datasync.ResyncEvent) { var wasError error for key, vals := range e.GetValues() { plugin.Log.Debugf("trying to delete obsolete status for key %v begin ", key) - if strings.HasPrefix(key, interfaces.IfStatePrefix) { + if strings.HasPrefix(key, interfaces.StatePrefix) { var keys []string for { x, stop := vals.GetNext() diff --git a/scripts/check_links.sh b/scripts/check_links.sh index 7b6ea8adc4..402c81d674 100755 --- a/scripts/check_links.sh +++ b/scripts/check_links.sh @@ -8,11 +8,11 @@ do continue fi - echo $i; - if ! markdown-link-check $i; then + out=$(FORCE_COLOR=1 markdown-link-check -q "$i") + if [ "$?" -ne 0 ]; then + echo "${out}" res=1 fi - echo ""; done -exit $res \ No newline at end of file +exit ${res} diff --git a/scripts/gofmt.sh b/scripts/gofmt.sh index a3135e18fa..48b6446398 100755 --- a/scripts/gofmt.sh +++ b/scripts/gofmt.sh @@ -1,3 +1,7 @@ #!/bin/bash -find $(pwd) -mount -name "*.go" -type f -not -path $(pwd)"/vendor/*" -not -name "pkgreflect.go" -not -name "bindata.go" -exec gofmt -w -s {} + +find $(pwd) -mount -name "*.go" -type f \ + -not -path $(pwd)"/vendor/*" \ + -not -name "pkgreflect.go" \ + -not -name "bindata.go" \ + -exec gofmt -w -s {} + diff --git a/scripts/static_analysis.sh b/scripts/static_analysis.sh index e6583bf932..7d6eebcf77 100755 --- a/scripts/static_analysis.sh +++ b/scripts/static_analysis.sh @@ -11,5 +11,14 @@ do enabledLinters="$enabledLinters --enable=$linterName" done +params=-tags="${GO_BUILD_TAGS}" + # running linters (excluding vendor,...) -gometalinter --vendor --deadline 1m --enable-gc --disable-all "$enabledLinters" --exclude="should not use dot imports" --exclude="$filesToExclude" ./... +gometalinter \ + --vendor \ + --linter="vet:go vet ${params}:^(?:vet:.*?\.go:\s+(?P.*?\.go):(?P\d+):(?P\d+):\s*(?P.*))|(?:(?P.*?\.go):(?P\d+):\s*(?P.*))$" \ + --deadline 3m \ + --enable-gc \ + --disable-all $enabledLinters \ + --exclude="should not use dot imports" \ + ./... diff --git a/tests/go/itest/idxtst/idx_assert.go b/tests/go/itest/idxtst/idx_assert.go deleted file mode 100644 index b7079f1e4f..0000000000 --- a/tests/go/itest/idxtst/idx_assert.go +++ /dev/null @@ -1,48 +0,0 @@ -package idxtst - -import ( - "time" - - idx "github.com/ligato/vpp-agent/idxvpp" - . "github.com/onsi/gomega" -) - -func lookupIdx(mapping idx.NameToIdx, lookupName string) func() uint32 { - return func() uint32 { - swIdx, _, _ := mapping.LookupIdx(lookupName) - return swIdx - } -} - -// ContainsName verifies lookup name presence in provided mapping. -func ContainsName(mapping idx.NameToIdx, lookupName string) uint32 { - // Block until Eventually's timeout elapses. - Eventually(lookupIdx(mapping, lookupName), 1000*time.Millisecond, 25*time.Millisecond). - ShouldNot(BeZero()) - return lookupIdx(mapping, lookupName)() -} - -// ContainsMeta verifies lookup meta presence in provided mapping. -func ContainsMeta(mapping idx.NameToIdx, lookupName string) interface{} { - var exists bool - var meta interface{} - for i := 0; i < 5; i++ { - _, meta, exists = mapping.LookupIdx(lookupName) - if !exists { - time.Sleep(100 * time.Millisecond) - } else { - break - } - } - if exists { - return meta - } - return nil -} - -// NotContainsNameAfter verifies that name is not present in mapping after specified time. -func NotContainsNameAfter(mapping idx.NameToIdx, lookupName string) { - time.Sleep(100 * time.Millisecond) - swIdx := lookupIdx(mapping, lookupName)() - Expect(swIdx).To(BeZero()) -} diff --git a/tests/go/itest/iftst/data.go b/tests/go/itest/iftst/data.go deleted file mode 100644 index cedec57534..0000000000 --- a/tests/go/itest/iftst/data.go +++ /dev/null @@ -1,180 +0,0 @@ -// Package iftst provides tools and input data for unit testing of ifplugin. -// What remains to be defined are scenarios. -package iftst - -import ( - "github.com/ligato/vpp-agent/plugins/vpp/model/bfd" - "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" - "github.com/ligato/vpp-agent/plugins/vpp/model/l2" -) - -var ( - // Memif100011Master is an example of a memory interface configuration. (Master=true) - Memif100011Master = interfaces.Interfaces_Interface{ - Name: "memif1", - Type: interfaces.InterfaceType_MEMORY_INTERFACE, - Enabled: true, - Memif: &interfaces.Interfaces_Interface_Memif{ - Master: true, - SocketFilename: "/tmp/memif1.sock", - }, - Mtu: 1500, - IpAddresses: []string{"10.0.0.11/24"}, - } - - // Memif100011Slave is an example of a memory interface configuration. It is - // intentionally similar to Memif100011. The only difference is that Master=false. - Memif100011Slave = interfaces.Interfaces_Interface{ - Name: "memif1", - Type: interfaces.InterfaceType_MEMORY_INTERFACE, - Enabled: true, - Memif: &interfaces.Interfaces_Interface_Memif{ - Master: false, - SocketFilename: "/tmp/memif1.sock", - }, - Mtu: 1500, - IpAddresses: []string{"10.0.0.11/24"}, - } - - // Memif100012 is an example of a memory interface configuration. - Memif100012 = interfaces.Interfaces_Interface{ - Name: "memif100012", - Type: interfaces.InterfaceType_MEMORY_INTERFACE, - Enabled: true, - Memif: &interfaces.Interfaces_Interface_Memif{ - Master: true, - SocketFilename: "/tmp/memif1.sock", - }, - Mtu: 1500, - IpAddresses: []string{"10.0.0.12/24"}, - } - - // Memif100013 is an example of a memory interface configuration. - Memif100013 = interfaces.Interfaces_Interface{ - Name: "memif100013", - Type: interfaces.InterfaceType_MEMORY_INTERFACE, - Enabled: true, - Memif: &interfaces.Interfaces_Interface_Memif{ - Master: true, - SocketFilename: "/tmp/memif1.sock", - }, - Mtu: 1500, - IpAddresses: []string{"10.0.0.13/24"}, - } - - // VxlanVni5 is an example of a memory interface configuration. - VxlanVni5 = interfaces.Interfaces_Interface{ - Name: "VxlanVni5", - Type: interfaces.InterfaceType_VXLAN_TUNNEL, - Enabled: true, - Vxlan: &interfaces.Interfaces_Interface_Vxlan{ - SrcAddress: "192.168.1.1", - DstAddress: "192.168.1.2", - Vni: 5, - }, - } - - // AfPacketVeth1 is an example of a memory interface configuration. - AfPacketVeth1 = interfaces.Interfaces_Interface{ - Name: "AfPacketVeth1", - Type: interfaces.InterfaceType_AF_PACKET_INTERFACE, - Enabled: true, - Afpacket: &interfaces.Interfaces_Interface_Afpacket{ - HostIfName: "veth1", - }, - } - - // BDMemif100011ToMemif100012 is an example of a bridge domain configuration. - BDMemif100011ToMemif100012 = l2.BridgeDomains_BridgeDomain{ - Name: "aaa", - Flood: false, - UnknownUnicastFlood: false, - Forward: true, - Learn: true, - ArpTermination: false, - MacAge: 0, /*means disable aging*/ - } -) - -// TapInterfaceBuilder serves to create a test interface. -func TapInterfaceBuilder(name string, ip string) interfaces.Interfaces_Interface { - return interfaces.Interfaces_Interface{ - Name: name, - Type: interfaces.InterfaceType_TAP_INTERFACE, - Enabled: true, - Mtu: 1500, - IpAddresses: []string{ip}, - Tap: &interfaces.Interfaces_Interface_Tap{HostIfName: name}, - } -} - -// MemifBuilder creates a new instance for testing purposes. -func MemifBuilder(ifname string, ipAddr string, master bool, id uint32) *interfaces.Interfaces_Interface { - return &interfaces.Interfaces_Interface{ - Name: ifname, - Type: interfaces.InterfaceType_MEMORY_INTERFACE, - Enabled: true, - Memif: &interfaces.Interfaces_Interface_Memif{ - Id: id, - Master: master, - SocketFilename: "/tmp/" + ifname + ".sock", - }, - IpAddresses: []string{ipAddr}, - } - -} - -// LoopbackBuilder creates a new instance for testing purposes. -func LoopbackBuilder(ifname string, ipAddr string) *interfaces.Interfaces_Interface { - return &interfaces.Interfaces_Interface{ - Name: ifname, - Type: interfaces.InterfaceType_SOFTWARE_LOOPBACK, - Enabled: true, - IpAddresses: []string{ipAddr}, - } - -} - -// BfdSessionBuilder creates BFD session without authentication. -func BfdSessionBuilder(iface string, srcAddr string, dstAddr string, desInt uint32, reqInt uint32, multiplier uint32) bfd.SingleHopBFD_Session { - return bfd.SingleHopBFD_Session{ - Interface: iface, - SourceAddress: srcAddr, - DestinationAddress: dstAddr, - DesiredMinTxInterval: desInt, - RequiredMinRxInterval: reqInt, - DetectMultiplier: multiplier, - } -} - -// BfdAuthSessionBuilder creates BFD session including authentication. -func BfdAuthSessionBuilder(iface string, srcAddr string, dstAddr string, desInt uint32, reqInt uint32, multiplier uint32) bfd.SingleHopBFD_Session { - return bfd.SingleHopBFD_Session{ - Interface: iface, - SourceAddress: srcAddr, - DestinationAddress: dstAddr, - DesiredMinTxInterval: desInt, - RequiredMinRxInterval: reqInt, - DetectMultiplier: multiplier, - Authentication: &bfd.SingleHopBFD_Session_Authentication{ - KeyId: 1, - AdvertisedKeyId: 1, - }, - } -} - -// BfdAuthKeyBuilder creates BFD authentication key. -func BfdAuthKeyBuilder(id uint32, authType bfd.SingleHopBFD_Key_AuthenticationType, secret string) bfd.SingleHopBFD_Key { - return bfd.SingleHopBFD_Key{ - Id: id, - AuthenticationType: authType, - Secret: secret, - } -} - -// BfdEchoFunctionBuilder builds BFD echo source. -func BfdEchoFunctionBuilder(iface string) bfd.SingleHopBFD_EchoFunction { - return bfd.SingleHopBFD_EchoFunction{ - EchoSourceInterface: iface, - } -} diff --git a/tests/go/itest/iftst/given.go b/tests/go/itest/iftst/given.go deleted file mode 100644 index 6cb80b519e..0000000000 --- a/tests/go/itest/iftst/given.go +++ /dev/null @@ -1,81 +0,0 @@ -package iftst - -import ( - "reflect" - "strings" - - govppmock "git.fd.io/govpp.git/adapter/mock" - "git.fd.io/govpp.git/adapter/mock/binapi" - "github.com/ligato/cn-infra/logging/logrus" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/acl" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/af_packet" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/bfd" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/ipsec" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/memif" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/session" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/stats" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/tap" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/tapv2" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/vpe" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/vxlan" -) - -var swIfIndexSeq uint32 - -// RepliesSuccess replies with success binary API message. -func RepliesSuccess(vppMock *govppmock.VppAdapter) { - vppMock.RegisterBinAPITypes(acl.Types) - vppMock.RegisterBinAPITypes(af_packet.Types) - vppMock.RegisterBinAPITypes(bfd.Types) - vppMock.RegisterBinAPITypes(interfaces.Types) - vppMock.RegisterBinAPITypes(ipsec.Types) - vppMock.RegisterBinAPITypes(memif.Types) - vppMock.RegisterBinAPITypes(session.Types) - vppMock.RegisterBinAPITypes(stats.Types) - vppMock.RegisterBinAPITypes(tap.Types) - vppMock.RegisterBinAPITypes(tapv2.Types) - vppMock.RegisterBinAPITypes(vpe.Types) - vppMock.RegisterBinAPITypes(vxlan.Types) - - vppMock.MockReplyHandler(VppMockHandler(vppMock)) -} - -// VppMockHandler returns reply handler for mock adapter -func VppMockHandler(vppMock *govppmock.VppAdapter) govppmock.ReplyHandler { - return func(request govppmock.MessageDTO) (reply []byte, msgID uint16, prepared bool) { - reqName, found := vppMock.GetMsgNameByID(request.MsgID) - if !found { - logrus.DefaultLogger().Error("Not existing req msg name for MsgID=", request.MsgID) - return reply, 0, false - } - logrus.DefaultLogger().Debug("MockReplyHandler ", request.MsgID, " ", reqName) - - //TODO refactor this to several funcs - if strings.HasSuffix(reqName, "_dump") { - // Do not reply to the dump message and reply to the following control_ping. - } else { - if replyMsg, msgID, ok := vppMock.ReplyFor(reqName); ok { - val := reflect.ValueOf(replyMsg) - valType := val.Type() - if binapi.HasSwIfIdx(valType) { - swIfIndexSeq++ - logrus.DefaultLogger().Debug("Succ default reply for ", reqName, " ", msgID, " sw_if_idx=", swIfIndexSeq) - binapi.SetSwIfIdx(val, swIfIndexSeq) - } else { - logrus.DefaultLogger().Debug("Succ default reply for ", reqName, " ", msgID) - } - - reply, err := vppMock.ReplyBytes(request, replyMsg) - if err == nil { - return reply, msgID, true - } - logrus.DefaultLogger().Error("Error creating bytes ", err) - } else { - logrus.DefaultLogger().Warn("No default reply for ", reqName, ", ", request.MsgID) - } - } - - return reply, 0, false - } -} diff --git a/tests/go/itest/iftst/then.go b/tests/go/itest/iftst/then.go deleted file mode 100644 index dc71b0ace2..0000000000 --- a/tests/go/itest/iftst/then.go +++ /dev/null @@ -1,110 +0,0 @@ -package iftst - -import ( - "fmt" - "time" - - intf "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" - "github.com/ligato/vpp-agent/tests/go/itest/idxtst" - - "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/logrus" - idx "github.com/ligato/vpp-agent/idxvpp" - "github.com/ligato/vpp-agent/plugins/vpp" - . "github.com/onsi/gomega" -) - -// ThenIface is a collection of test step methods (see Behavior Driven Development) -// (methods that will be called from test scenarios). -type ThenIface struct { - //NewChange func(name core.PluginName) vppclient.DataChangeDSL - OperState ifstateGetter - - Log logging.Logger - VPP vpp.API -} - -type ifstateGetter interface { - // InterfaceState reads operational state of network interface - // and fills it to ifState input parameter. - InterfaceState(ifaceName string, ifState *intf.InterfacesState_Interface) (found bool, err error) -} - -// SwIfIndexes is a constructor for interfaces. -func (step *ThenIface) SwIfIndexes() *SwIfIndexesAssertions { - return &SwIfIndexesAssertions{VPP: step.VPP} -} - -// BfdIndexes is a constructor for interfaces. -func (step *ThenIface) BfdIndexes() *BfdIndexesAssertions { - return &BfdIndexesAssertions{} -} - -// ContainsName checks several times if sw_if_index - ifName mapping exists. -func (step *ThenIface) ContainsIPSecSA(name string) bool { - idx := idxtst.ContainsName(step.VPP.GetIPSecSAIndexes(), name) - return idx != 0 -} - -// ContainsName checks several times if sw_if_index - ifName mapping exists. -func (step *ThenIface) ContainsIPSecSPD(name string) bool { - idx := idxtst.ContainsName(step.VPP.GetIPSecSPDIndexes().GetMapping(), name) - return idx != 0 -} - -// SwIfIndexesAssertions is a helper struct for fluent DSL in tests for interfaces. -type SwIfIndexesAssertions struct { - VPP vpp.API -} - -// BfdIndexesAssertions is a helper struct for fluent DSL in tests for bfd. -type BfdIndexesAssertions struct { -} - -// ContainsName checks several times if sw_if_index - ifName mapping exists. -func (a *SwIfIndexesAssertions) ContainsName(ifName string) { - idxtst.ContainsName(a.VPP.GetSwIfIndexes().GetMapping(), ifName) -} - -// ContainsName checks several times if there is an entry with the given name in bfd_index. -func (a *BfdIndexesAssertions) ContainsName(mapping idx.NameToIdx, bfdIface string) { - idxtst.ContainsName(mapping, bfdIface) -} - -// NotContainsName checks several times the sw_if_index - ifName mapping does not exist. -func (a *SwIfIndexesAssertions) NotContainsName(ifName string) { - idxtst.NotContainsNameAfter(a.VPP.GetSwIfIndexes().GetMapping(), ifName) -} - -// NotContainsName checks several times if there is no entry with the given name in bfd_index. -func (a *BfdIndexesAssertions) NotContainsName(mapping idx.NameToIdx, bfdInterface string) { - idxtst.NotContainsNameAfter(mapping, bfdInterface) -} - -// IfStateInDB asserts that there is InterfacesState_Interface_DOWN in ETCD for particular Interfaces_Interface. -func (step *ThenIface) IfStateInDB(status intf.InterfacesState_Interface_Status, data *intf.Interfaces_Interface) { - logrus.DefaultLogger().Debug("IfStateDownInDB begin") - - time.Sleep(time.Second / 10) - - ifState := &intf.InterfacesState_Interface{} - var found bool - var err error - for i := 0; i < 12; i++ { - found, err = step.OperState.InterfaceState(data.Name, ifState) - - if err != nil { - logrus.DefaultLogger().Panic(err) - } - if found { - break - } - time.Sleep(time.Second / 4) - } - Expect(found).Should(BeTrue(), - "not found operational state "+data.Name) - Expect(ifState.OperStatus).Should(BeEquivalentTo(status), - fmt.Sprintf("Status needs to be %v for %v", status, data.Name)) - - logrus.DefaultLogger().Debug("IfStateDownInDB end") -} diff --git a/tests/go/itest/iftst/when.go b/tests/go/itest/iftst/when.go deleted file mode 100644 index 6257a28f45..0000000000 --- a/tests/go/itest/iftst/when.go +++ /dev/null @@ -1,170 +0,0 @@ -package iftst - -import ( - govppmock "git.fd.io/govpp.git/adapter/mock" - "github.com/ligato/cn-infra/core" - "github.com/ligato/cn-infra/logging" - "github.com/ligato/cn-infra/logging/logrus" - vppclient "github.com/ligato/vpp-agent/clientv1/vpp" - "github.com/ligato/vpp-agent/clientv1/vpp/localclient" - "github.com/ligato/vpp-agent/plugins/vpp" - "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" - intf "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" -) - -const pluginName = core.PluginName("when_iface") - -// WhenIface is a collection of test step methods (see Behavior Driven Development) -// (methods that will be called from test scenarios). -type WhenIface struct { - NewChange func(name core.PluginName) vppclient.DataChangeDSL - NewResync func(name core.PluginName) vppclient.DataResyncDSL - Log logging.Logger - VPP vpp.API - MockVpp *govppmock.VppAdapter -} - -// ResyncIf stores configuration of a given interface in ETCD. -func (when *WhenIface) ResyncIf(data1, data2 *intf.Interfaces_Interface) { - when.Log.Debug("When_ResyncIf begin") - err := when.NewResync(pluginName).Interface(data1).Interface(data2).Send().ReceiveReply() - if err != nil { - when.Log.Panic(err) - } - when.Log.Debug("When_ResyncIf end") -} - -// StoreIf stores configuration of a given interface in ETCD. -func (when *WhenIface) StoreIf(data *intf.Interfaces_Interface, opts ...interface{}) { - when.Log.Debug("When_StoreIf begin") - err := when.NewChange(pluginName).Put().Interface(data).Send().ReceiveReply() - if err != nil { - when.Log.Panic(err) - } - when.Log.Debug("When_StoreIf end") -} - -// StoreIf stores configuration of a given interface in ETCD. -func (when *WhenIface) Put(fn func(dsl vppclient.PutDSL) vppclient.PutDSL) { - err := fn(when.NewChange(pluginName).Put()).Send().ReceiveReply() - if err != nil { - when.Log.Panic(err) - } -} - -// DelIf removes configuration of a given interface from ETCD. -func (when *WhenIface) DelIf(data *intf.Interfaces_Interface) { - when.Log.Debug("When_StoreIf begin") - err := localclient.DataChangeRequest(pluginName).Delete().Interface(data.Name).Send().ReceiveReply() - if err != nil { - when.Log.Panic(err) - } - when.Log.Debug("When_StoreIf end") -} - -// VppLinkUp sends interface event link up using VPP mock. -func (when *WhenIface) VppLinkUp(data *intf.Interfaces_Interface) { - idx, _, exists := when.VPP.GetSwIfIndexes().LookupIdx(data.Name) - if !exists { - when.Log.Panicf("swIfIndex for %q doesnt exist", data.Name) - } - - logrus.DefaultLogger().Infof("- VppLinkUp idx:%v", idx) - - // mock the notification and force its delivery - when.MockVpp.MockReply(&interfaces.SwInterfaceEvent{ - SwIfIndex: idx, - //AdminUpDown: 1, - LinkUpDown: 1, - }) - when.MockVpp.SendMsg(0, []byte("")) - - logrus.DefaultLogger().Info("~ VppLinkUp") -} - -// VppLinkDown sends interface event link down using VPP mock. -func (when *WhenIface) VppLinkDown(data *intf.Interfaces_Interface) { - idx, _, exists := when.VPP.GetSwIfIndexes().LookupIdx(data.Name) - if !exists { - when.Log.Panicf("swIfIndex for %q doesnt exist", data.Name) - } - - logrus.DefaultLogger().Info("- VppLinkDown") - - // mock the notification and force its delivery - when.MockVpp.MockReply(&interfaces.SwInterfaceEvent{ - SwIfIndex: idx, - LinkUpDown: 0, - }) - when.MockVpp.SendMsg(0, []byte("")) - - logrus.DefaultLogger().Info("~ VppLinkDown") -} - -/* -// StoreBfdSession stores configuration of a given BFD session in ETCD. -func (step *WhenIface) StoreBfdSession(data *bfd.SingleHopBFD_Session) { - log.Debug("When_StoreBfdSession begin") - k := bfd.SessionKey(data.Interface) - err := etcdmux.NewRootBroker().Put(servicelabel.GetAgentPrefix()+k, data) - if err != nil { - log.Panic(err) - } - log.Debug("When_StoreBfdSession end") -} - -// StoreBfdAuthKey stores configuration of a given BFD key in ETCD. -func (step *WhenIface) StoreBfdAuthKey(data *bfd.SingleHopBFD_Key) { - log.Debug("When_StoreBfdKey begin") - k := bfd.AuthKeysKey(strconv.FormatUint(uint64(data.Id), 10)) - err := etcdmux.NewRootBroker().Put(servicelabel.GetAgentPrefix()+k, data) - if err != nil { - log.Panic(err) - } - log.Debug("When_StoreBfdKey end") -} - -// StoreBfdEchoFunction stores configuration of a given BFD echo function in ETCD. -func (step *WhenIface) StoreBfdEchoFunction(data *bfd.SingleHopBFD_EchoFunction) { - log.Debug("When_StoreBfdEchoFunction begin") - k := bfd.EchoFunctionKey(data.EchoSourceInterface) - err := etcdmux.NewRootBroker().Put(servicelabel.GetAgentPrefix()+k, data) - if err != nil { - log.Panic(err) - } - log.Debug("When_StoreBfdEchoFunction end") -} - -// DelBfdSession removes configuration of a given BFD session from ETCD. -func (step *WhenIface) DelBfdSession(data *bfd.SingleHopBFD_Session) { - log.Debug("When_DelBfdSession begin") - k := bfd.SessionKey(data.Interface) - _, err := etcdmux.NewRootBroker().Delete(servicelabel.GetAgentPrefix() + k) - if err != nil { - log.Panic(err) - } - log.Debug("When_DelBfdSession end") -} - -// DelBfdAuthKey removes configuration of a given BFD key from ETCD. -func (step *WhenIface) DelBfdAuthKey(data *bfd.SingleHopBFD_Key) { - log.Debug("When_DelBfdKey begin") - k := bfd.AuthKeysKey(strconv.FormatUint(uint64(data.Id), 10)) - _, err := etcdmux.NewRootBroker().Delete(servicelabel.GetAgentPrefix() + k) - if err != nil { - log.Panic(err) - } - log.Debug("When_DelBfdKey end") -} - -// DelBfdEchoFunction removes configuration of a given BFD echo function from ETCD. -func (step *WhenIface) DelBfdEchoFunction(data *bfd.SingleHopBFD_EchoFunction) { - log.Debug("When_DelBfdEchoFunction begin") - k := bfd.EchoFunctionKey(data.EchoSourceInterface) - _, err := etcdmux.NewRootBroker().Delete(servicelabel.GetAgentPrefix() + k) - if err != nil { - log.Panic(err) - } - log.Debug("When_DelBfdEchoFunction end") -} -*/ diff --git a/tests/go/itest/l2tst/data.go b/tests/go/itest/l2tst/data.go deleted file mode 100644 index 4cc4e13196..0000000000 --- a/tests/go/itest/l2tst/data.go +++ /dev/null @@ -1,116 +0,0 @@ -// Package l2tst provides tools and input data for unit testing of the -// l2plugin. What remains to be defined are scenarios. -package l2tst - -import ( - "github.com/ligato/vpp-agent/plugins/vpp/model/l2" - "github.com/ligato/vpp-agent/tests/go/itest/iftst" -) - -var ( - // BDMemif100011ToMemif100012 is an example bridge domain configuration. - BDMemif100011ToMemif100012 = l2.BridgeDomains_BridgeDomain{ - Name: "br2", - Flood: false, - UnknownUnicastFlood: false, - Forward: true, - Learn: true, - ArpTermination: false, - MacAge: 0, /*means disable aging*/ - Interfaces: []*l2.BridgeDomains_BridgeDomain_Interfaces{ - { - Name: "memif1", - BridgedVirtualInterface: true, - }, { - Name: "memif4", - BridgedVirtualInterface: false, - }, - }, - } - - // BDAfPacketVeth1VxlanVni5 is an example bridge domain configuration. - BDAfPacketVeth1VxlanVni5 = l2.BridgeDomains_BridgeDomain{ - Name: "br1", - Flood: false, - UnknownUnicastFlood: false, - Forward: true, - Learn: true, - ArpTermination: false, - MacAge: 0, /*means disable aging*/ - Interfaces: []*l2.BridgeDomains_BridgeDomain_Interfaces{ - { - Name: iftst.VxlanVni5.Name, - BridgedVirtualInterface: false, - }, { - Name: iftst.AfPacketVeth1.Name, - BridgedVirtualInterface: false, - }, - }, - } - - // XConMemif100011ToMemif100012 is an example of cross connect configuration. - XConMemif100011ToMemif100012 = l2.XConnectPairs_XConnectPair{ - ReceiveInterface: iftst.Memif100011Master.Name, - TransmitInterface: iftst.Memif100011Master.Name, - } -) - -// SimpleBridgeDomain1XIfaceBuilder creates a simple bridge domain with defined name and one interface. -func SimpleBridgeDomain1XIfaceBuilder(name string, iface1 string, bvi1 bool) l2.BridgeDomains_BridgeDomain { - return l2.BridgeDomains_BridgeDomain{ - Name: name, - Flood: false, - UnknownUnicastFlood: false, - Forward: true, - Learn: true, - ArpTermination: false, - MacAge: 0, - Interfaces: []*l2.BridgeDomains_BridgeDomain_Interfaces{ - { - Name: iface1, - BridgedVirtualInterface: bvi1, - }, - }, - } -} - -// SimpleBridgeDomain2XIfaceBuilder creates a simple bridge domain with defined name and two interfaces. -func SimpleBridgeDomain2XIfaceBuilder(name string, iface1 string, iface2 string, bvi1 bool, bvi2 bool) l2.BridgeDomains_BridgeDomain { - return l2.BridgeDomains_BridgeDomain{ - Name: name, - Flood: false, - UnknownUnicastFlood: false, - Forward: true, - Learn: true, - ArpTermination: false, - MacAge: 0, - Interfaces: []*l2.BridgeDomains_BridgeDomain_Interfaces{ - { - Name: iface1, - BridgedVirtualInterface: bvi1, - }, { - Name: iface2, - BridgedVirtualInterface: bvi2, - }, - }, - } -} - -// FIBBuilder builds FIB table entry. -func FIBBuilder(mac string, bdName string, iface string, bvi bool) l2.FibTable_FibEntry { - return l2.FibTable_FibEntry{ - PhysAddress: mac, - BridgeDomain: bdName, - OutgoingInterface: iface, - StaticConfig: true, - BridgedVirtualInterface: bvi, - } -} - -// XconnectBuilder prepares xConnect interface pair. -func XconnectBuilder(rIface string, tIface string) l2.XConnectPairs_XConnectPair { - return l2.XConnectPairs_XConnectPair{ - ReceiveInterface: rIface, - TransmitInterface: tIface, - } -} diff --git a/tests/go/itest/memif_tcs.go b/tests/go/itest/memif_tcs.go deleted file mode 100644 index a65ab65b94..0000000000 --- a/tests/go/itest/memif_tcs.go +++ /dev/null @@ -1,189 +0,0 @@ -package itest - -import ( - "testing" - - "git.fd.io/govpp.git/adapter/mock" - "github.com/ligato/cn-infra/datasync/kvdbsync/local" - "github.com/ligato/cn-infra/datasync/syncbase" - "github.com/ligato/vpp-agent/clientv1/vpp" - "github.com/ligato/vpp-agent/clientv1/vpp/localclient" - "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" - "github.com/ligato/vpp-agent/plugins/vpp/model/ipsec" - "github.com/ligato/vpp-agent/tests/go/itest/iftst" - "github.com/ligato/vpp-agent/tests/go/itest/testutil" -) - -type suiteMemif struct { - T *testing.T - testutil.VppAgentT - testutil.Given - testutil.When - testutil.Then -} - -func forMemif(t *testing.T) *suiteMemif { - return &suiteMemif{T: t, - When: testutil.When{ - WhenIface: iftst.WhenIface{ - Log: testutil.NewLogger("WhenIface", t), - NewChange: localclient.DataChangeRequest, - NewResync: localclient.DataResyncRequest, - }}, - Then: testutil.Then{ - ThenIface: iftst.ThenIface{ - Log: testutil.NewLogger("ThenIface", t), - //NewChange: localclient.DataChangeRequest, - //OperState: testutil.NewStatePub(), - }}, - } -} - -func (s *suiteMemif) setupTestingFlavor(flavor *testutil.VppOnlyTestingFlavor) { - local.DefaultTransport = syncbase.NewRegistry() - mockVpp := &mock.VppAdapter{} - flavor.GoVPP = *testutil.VppMock(mockVpp, iftst.RepliesSuccess) - //mockVpp.MockReplyHandler(iftst.VppMockHandler(mockVpp)) - /*s.When.NewChange = func(caller core.PluginName) vppplugin.DataChangeDSL { - return dbadapter.NewDataChangeDSL(local.NewProtoTxn(local.Get().PropagateChanges)) - }*/ - s.Setup(flavor) - s.When.VPP = &flavor.VPP - s.When.MockVpp = mockVpp - s.Then.VPP = &flavor.VPP - s.Then.OperState = flavor.IfStatePub -} - -// TC01EmptyVppCrudEtcd asserts that data written to ETCD after Agent Starts are processed. -func (s *suiteMemif) TC01EmptyVppCrudEtcd() { - s.setupTestingFlavor(s.SetupDefault()) - defer s.Teardown() - - s.When.StoreIf(&iftst.Memif100011Slave) - s.Then.SwIfIndexes().ContainsName(iftst.Memif100011Slave.Name) - - s.When.StoreIf(&iftst.Memif100012) - s.Then.SwIfIndexes().ContainsName(iftst.Memif100012.Name) - - s.When.DelIf(&iftst.Memif100012) - s.Then.SwIfIndexes().NotContainsName(iftst.Memif100012.Name) - - //TODO simulate that dump return local interface -} - -// TC02EmptyVppResyncAtStartup tests that data written to ETCD before Agent Starts are processed (startup RESYNC). -func (s *suiteMemif) TC02EmptyVppResyncAtStartup() { - s.setupTestingFlavor(s.SetupDefault()) - defer s.Teardown() - - s.When.ResyncIf(&iftst.Memif100011Slave, &iftst.Memif100012) - s.Then.SwIfIndexes().ContainsName(iftst.Memif100011Slave.Name) - s.Then.SwIfIndexes().ContainsName(iftst.Memif100012.Name) -} - -// TC03VppNotificaitonIfDown tests that if state down notification is handled correctly -func (s *suiteMemif) TC03VppNotificaitonIfDown() { - s.setupTestingFlavor(s.SetupDefault()) - defer s.Teardown() - - s.When.StoreIf(&iftst.Memif100011Slave) - s.When.StoreIf(&iftst.Memif100012) - s.Then.SwIfIndexes().ContainsName(iftst.Memif100011Slave.Name) - - s.When.VppLinkDown(&iftst.Memif100011Slave) - s.Then.IfStateInDB(interfaces.InterfacesState_Interface_DOWN, &iftst.Memif100011Slave) - - s.When.VppLinkDown(&iftst.Memif100012) - s.Then.IfStateInDB(interfaces.InterfacesState_Interface_DOWN, &iftst.Memif100012) - s.Then.IfStateInDB(interfaces.InterfacesState_Interface_DOWN, &iftst.Memif100011Slave) - - s.When.VppLinkUp(&iftst.Memif100012) - s.Then.IfStateInDB(interfaces.InterfacesState_Interface_UP, &iftst.Memif100012) - s.Then.IfStateInDB(interfaces.InterfacesState_Interface_DOWN, &iftst.Memif100011Slave) - - s.When.VppLinkUp(&iftst.Memif100011Slave) - s.Then.IfStateInDB(interfaces.InterfacesState_Interface_UP, &iftst.Memif100011Slave) - s.Then.IfStateInDB(interfaces.InterfacesState_Interface_UP, &iftst.Memif100012) -} - -// TC04 -func (s *suiteMemif) TC04() { - s.setupTestingFlavor(s.SetupDefault()) - defer s.Teardown() - - s.When.Put(func(put vppclient.PutDSL) vppclient.PutDSL { - return put.IPSecSA(&IPsecSA20) - }) - s.When.Put(func(put vppclient.PutDSL) vppclient.PutDSL { - return put.IPSecSA(&IPsecSA10) - }) - s.When.Put(func(put vppclient.PutDSL) vppclient.PutDSL { - return put.IPSecSPD(&IPsecSPD1) - }) - s.Then.ContainsIPSecSA(IPsecSA10.Name) - s.Then.ContainsIPSecSA(IPsecSA20.Name) - s.Then.ContainsIPSecSPD(IPsecSPD1.Name) - - s.When.StoreIf(&iftst.Memif100011Master) - s.Then.SwIfIndexes().ContainsName(iftst.Memif100011Master.Name) - s.When.DelIf(&iftst.Memif100011Master) - s.When.StoreIf(&iftst.Memif100011Master) -} - -var IPsecSA10 = ipsec.SecurityAssociations_SA{ - Name: "sa10", - Spi: 1001, - Protocol: ipsec.SecurityAssociations_SA_ESP, - CryptoAlg: ipsec.CryptoAlgorithm_AES_CBC_128, - CryptoKey: "4a506a794f574265564551694d653768", - IntegAlg: ipsec.IntegAlgorithm_SHA1_96, - IntegKey: "4339314b55523947594d6d3547666b45764e6a58", -} - -var IPsecSA20 = ipsec.SecurityAssociations_SA{ - Name: "sa20", - Spi: 1000, - Protocol: ipsec.SecurityAssociations_SA_ESP, - CryptoAlg: ipsec.CryptoAlgorithm_AES_CBC_128, - CryptoKey: "4a506a794f574265564551694d653768", - IntegAlg: ipsec.IntegAlgorithm_SHA1_96, - IntegKey: "4339314b55523947594d6d3547666b45764e6a58", -} - -var IPsecSPD1 = ipsec.SecurityPolicyDatabases_SPD{ - Name: "spd1", - Interfaces: []*ipsec.SecurityPolicyDatabases_SPD_Interface{ - {Name: "memif1"}, - }, - PolicyEntries: []*ipsec.SecurityPolicyDatabases_SPD_PolicyEntry{ - { - Priority: 100, - IsOutbound: false, - Action: ipsec.SecurityPolicyDatabases_SPD_PolicyEntry_BYPASS, - Protocol: 50, - }, { - Priority: 100, - IsOutbound: true, - Action: ipsec.SecurityPolicyDatabases_SPD_PolicyEntry_BYPASS, - Protocol: 50, - }, { - Priority: 10, - IsOutbound: false, - Action: ipsec.SecurityPolicyDatabases_SPD_PolicyEntry_PROTECT, - RemoteAddrStart: "10.0.0.1", - RemoteAddrStop: "10.0.0.1", - LocalAddrStart: "10.0.0.2", - LocalAddrStop: "10.0.0.2", - Sa: "sa20", - }, { - Priority: 10, - IsOutbound: true, - Action: ipsec.SecurityPolicyDatabases_SPD_PolicyEntry_PROTECT, - RemoteAddrStart: "10.0.0.1", - RemoteAddrStop: "10.0.0.1", - LocalAddrStart: "10.0.0.2", - LocalAddrStop: "10.0.0.2", - Sa: "sa10", - }, - }, -} diff --git a/tests/go/itest/run_all_test.go b/tests/go/itest/run_all_test.go deleted file mode 100644 index dd86c1167e..0000000000 --- a/tests/go/itest/run_all_test.go +++ /dev/null @@ -1,65 +0,0 @@ -package itest - -import ( - "os" - "reflect" - "strings" - "testing" - - govppcore "git.fd.io/govpp.git/core" - "github.com/onsi/gomega" - "github.com/sirupsen/logrus" -) - -func init() { - govpplogger := logrus.New() - govpplogger.Out = os.Stdout - govpplogger.Level = logrus.DebugLevel - govppcore.SetLogger(govpplogger) -} - -// Test runs all TC methods of multiple test suites in a sequence. -func Test(t *testing.T) { - RunTestSuite(forMemif(t), t) -} - -// RunTestSuite uses reflection to run each method prefixed with "TC". -func RunTestSuite(testSuite interface{}, t *testing.T, teardowns ...func()) { - vppInstanceCounter := 0 // Each test uses different ETCD subtree. - - suite := reflect.ValueOf(testSuite) - suiteName := reflect.TypeOf(testSuite).Elem().Name() - - t.Log("Suite:", suiteName) - t.Run(suiteName, func(t *testing.T) { - for i := 0; i < suite.NumMethod(); i++ { - tc := suite.Method(i) - tcName := suite.Type().Method(i).Name - - if strings.HasPrefix(tcName, "TC") { - //TODO: currently the repeated modification of env var are ignore by flags - vppInstanceCounter++ - - //TODO inject the Microservice Label - //os.Setenv(servicelabel.MicroserviceLabelEnvVar, fmt.Sprintf( - // "TEST_VPP_%d", vppInstanceCounter)) - - t.Log("Case :", tcName) - ok := t.Run(tcName, func(t *testing.T) { - gomega.RegisterTestingT(t) - tc.Call([]reflect.Value{}) - - t.Log("Finished TC ", suiteName, " ", tcName) - }) - for _, teardown := range teardowns { - teardown() - } - if !ok { - t.Log("FAILED TC ", suiteName, " ", tcName) - break - } - } - } - - }) -} diff --git a/tests/go/itest/testutil/logger.go b/tests/go/itest/testutil/logger.go deleted file mode 100644 index 043bc539a2..0000000000 --- a/tests/go/itest/testutil/logger.go +++ /dev/null @@ -1,244 +0,0 @@ -// Copyright (c) 2017 Cisco and/or its affiliates. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at: -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package testutil - -import ( - "fmt" - "regexp" - "sync" - "testing" - - "github.com/ligato/cn-infra/logging" -) - -// Logger is a wrapper of Logrus logger. In addition to Logrus functionality, -// it allows to define static log fields that are added to all subsequent log entries. It also automatically -// appends file name and line from which the log comes. In order to distinguish logs from different -// go routines, a tag (number that is based on the stack address) is computed. To achieve better readability, -// numeric value of a tag can be replaced with a string using SetTag function. -type Logger struct { - access sync.RWMutex - name string - std *testing.T - level logging.LogLevel -} - -// NewLogger is a constructor which creates instances of named logger. -// This constructor is called from logRegistry which is useful -// when log levels need to be changed by management API (such as REST). -// -// Example: -// -// logger := NewLogger("loggerXY") -// logger.Info() -// -func NewLogger(name string, t *testing.T) *Logger { - logger := &Logger{ - std: t, - name: name, - } - logger.SetLevel(logging.DebugLevel) - return logger -} - -var validLoggerName = regexp.MustCompile(`^[a-zA-Z0-9.-]+$`).MatchString - -func checkLoggerName(name string) error { - if !validLoggerName(name) { - return fmt.Errorf("logger name can contain only alphanum characters, dash and comma") - } - return nil -} - -// GetName returns the logger name. -func (logger *Logger) GetName() string { - return logger.name -} - -// SetLevel sets the standard logger level. -func (logger *Logger) SetLevel(level logging.LogLevel) { - logger.access.Lock() - defer logger.access.Unlock() - logger.level = level -} - -// GetLevel returns the standard logger level. -func (logger *Logger) GetLevel() logging.LogLevel { - return logger.level -} - -func (logger *Logger) withField(key string, value interface{}) *logMsg { - return logger.withFields(logging.Fields{key: value}) -} - -// logMsg represent an item to be logged. -type logMsg struct { - *Logger - fields logging.Fields -} - -// WithField creates an entry from the standard logger and adds a field to -// it. If you want multiple fields, use `WithFields`. -// -// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal -// or Panic on the logMsg it returns. -func (logger *Logger) WithField(key string, value interface{}) logging.LogWithLevel { - return logger.withFields(logging.Fields{key: value}) -} - -func (logger *Logger) withFields(fields logging.Fields) *logMsg { - f := make(logging.Fields, len(fields)) - - for k, v := range fields { - f[k] = v - } - - return &logMsg{ - Logger: logger, - fields: f, - } -} - -// WithFields creates an entry from the standard logger and adds multiple -// fields to it. This is simply a helper for `WithField`, invoking it -// once for each field. -// -// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal -// or Panic on the logMsg it returns. -func (logger *Logger) WithFields(fields map[string]interface{}) logging.LogWithLevel { - return logger.withFields(logging.Fields(fields)) -} - -// Debug logs a message at level Debug on the standard logger. -func (logger *Logger) Debug(args ...interface{}) { - logger.std.Log(append([]interface{}{"Debug"}, args...)...) -} - -// Print logs a message at level Info on the standard logger. -func (logger *Logger) Print(args ...interface{}) { - logger.std.Log(args...) -} - -// Info logs a message at level Info on the standard logger. -func (logger *Logger) Info(args ...interface{}) { - logger.std.Log(append([]interface{}{"Info"}, args...)...) -} - -// Warn logs a message at level Warn on the standard logger. -func (logger *Logger) Warn(args ...interface{}) { - logger.std.Log(append([]interface{}{"Warn"}, args...)...) -} - -// Warning logs a message at level Warn on the standard logger. -func (logger *Logger) Warning(args ...interface{}) { - logger.std.Log(append([]interface{}{"Warning"}, args...)...) -} - -// Error logs a message at level Error on the standard logger. -func (logger *Logger) Error(args ...interface{}) { - logger.std.Error(append([]interface{}{"Error"}, args...)...) -} - -// Panic logs a message at level Panic on the standard logger. -func (logger *Logger) Panic(args ...interface{}) { - logger.std.Log(append([]interface{}{"Panic"}, args)...) - panic(args[0]) -} - -// Fatal logs a message at level Fatal on the standard logger. -func (logger *Logger) Fatal(args ...interface{}) { - logger.std.Log(append([]interface{}{"Fatal"}, args...)...) - panic(args[0]) -} - -// Debugf logs a message at level Debug on the standard logger. -func (logger *Logger) Debugf(format string, args ...interface{}) { - logger.std.Logf("Debug "+format, args...) -} - -// Printf logs a message at level Info on the standard logger. -func (logger *Logger) Printf(format string, args ...interface{}) { - logger.std.Logf(format, args...) -} - -// Infof logs a message at level Info on the standard logger. -func (logger *Logger) Infof(format string, args ...interface{}) { - logger.std.Logf("Info"+format, args...) -} - -// Warnf logs a message at level Warn on the standard logger. -func (logger *Logger) Warnf(format string, args ...interface{}) { - logger.std.Logf("Warn"+format, args...) -} - -// Warningf logs a message at level Warn on the standard logger. -func (logger *Logger) Warningf(format string, args ...interface{}) { - logger.std.Logf("Warning"+format, args...) -} - -// Errorf logs a message at level Error on the standard logger. -func (logger *Logger) Errorf(format string, args ...interface{}) { - logger.std.Errorf(format, args...) -} - -// Panicf logs a message at level Panic on the standard logger. -func (logger *Logger) Panicf(format string, args ...interface{}) { - logger.std.Logf("Panic"+format, args...) -} - -// Fatalf logs a message at level Fatal on the standard logger. -func (logger *Logger) Fatalf(format string, args ...interface{}) { - logger.std.Logf("Fatal"+format, args...) -} - -// Debugln logs a message at level Debug on the standard logger. -func (logger *Logger) Debugln(args ...interface{}) { - logger.std.Log(append([]interface{}{"Debug"}, args...)...) -} - -// Println logs a message at level Info on the standard logger. -func (logger *Logger) Println(args ...interface{}) { - logger.std.Log(args...) -} - -// Infoln logs a message at level Info on the standard logger. -func (logger *Logger) Infoln(args ...interface{}) { - logger.std.Log(append([]interface{}{"Info"}, args)...) -} - -// Warnln logs a message at level Warn on the standard logger. -func (logger *Logger) Warnln(args ...interface{}) { - logger.std.Log(append([]interface{}{"Warn"}, args...)...) -} - -// Warningln logs a message at level Warn on the standard logger. -func (logger *Logger) Warningln(args ...interface{}) { - logger.std.Log(append([]interface{}{"Warning"}, args...)...) -} - -// Errorln logs a message at level Error on the standard logger. -func (logger *Logger) Errorln(args ...interface{}) { - logger.std.Log(append([]interface{}{"Error"}, args...)...) -} - -// Panicln logs a message at level Panic on the standard logger. -func (logger *Logger) Panicln(args ...interface{}) { - logger.std.Log(append([]interface{}{"Panic"}, args...)...) -} - -// Fatalln logs a message at level Fatal on the standard logger. -func (logger *Logger) Fatalln(args ...interface{}) { - logger.std.Log(append([]interface{}{"Fatall"}, args...)...) -} diff --git a/tests/go/itest/testutil/vpp_agent.go b/tests/go/itest/testutil/vpp_agent.go deleted file mode 100644 index 0b3a748554..0000000000 --- a/tests/go/itest/testutil/vpp_agent.go +++ /dev/null @@ -1,201 +0,0 @@ -package testutil - -import ( - "git.fd.io/govpp.git/adapter/mock" - "github.com/golang/protobuf/proto" - "github.com/ligato/cn-infra/core" - "github.com/ligato/cn-infra/datasync" - localsync "github.com/ligato/cn-infra/datasync/kvdbsync/local" - "github.com/ligato/cn-infra/flavors/local" - "github.com/ligato/cn-infra/logging/logrus" - "github.com/ligato/vpp-agent/plugins/govppmux" - "github.com/ligato/vpp-agent/plugins/vpp" - intf "github.com/ligato/vpp-agent/plugins/vpp/model/interfaces" - "github.com/ligato/vpp-agent/tests/go/itest/iftst" -) - -// VppAgentT is similar to testing.T in golang packages. -type VppAgentT struct { - //*testing.T - agent *core.Agent -} - -// Given is a composition of multiple test step methods (see BDD Given keyword). -type Given struct { - //MockVpp *mock.VppAdapter -} - -// When is a composition of multiple test step methods (see BDD When keyword). -type When struct { - iftst.WhenIface - //when_l2.WhenL2 - //when_l3.WhenL3 -} - -// Then is a composition of multiple test step methods (see BDD Then keyword). -type Then struct { - iftst.ThenIface - //then_l2.ThenL2 - //then_l3.ThenL3 -} - -// SetupDefault setups default behaviour of mocks and delegates to Setup(Flavor). -func (t *VppAgentT) SetupDefault() (flavor *VppOnlyTestingFlavor) { - flavor = &VppOnlyTestingFlavor{ - IfStatePub: NewIfStatePub(), - //GoVPP: *VppMock(t.MockVpp, iftst.RepliesSuccess /*, given_l3.RepliesSuccess*/), - } - - //t.Setup(flavor) - return flavor -} - -// Setup registers gomega and starts the agent with the flavor argument. -func (t *VppAgentT) Setup(flavor core.Flavor) { - //gomega.RegisterTestingT(t.T) - - t.agent = core.NewAgent(flavor) - err := t.agent.Start() - if err != nil { - logrus.DefaultLogger().Panic(err) - } -} - -// Teardown stops the agent. -func (t *VppAgentT) Teardown() { - if t.agent != nil { - if err := t.agent.Stop(); err != nil { - logrus.DefaultLogger().Panic(err) - } - } -} - -// VppMock allows to mock go VPP plugin in a flavor. -func VppMock(vppMock *mock.VppAdapter, vppMockSetups ...func(adapter *mock.VppAdapter)) *govppmux.GOVPPPlugin { - //vppMock := &mock.VppAdapter{} - for _, vppMockSetup := range vppMockSetups { - vppMockSetup(vppMock) - } - return govppmux.FromExistingAdapter(vppMock) -} - -// VppOnlyTestingFlavor glues together multiple plugins to mange VPP and linux interfaces configuration using local client. -type VppOnlyTestingFlavor struct { - *local.FlavorLocal - - IfStatePub *MockIfStatePub - - GoVPP govppmux.GOVPPPlugin - VPP vpp.Plugin - - injected bool -} - -// MockIfStatePub is mocking for interface state publishing. -type MockIfStatePub struct { - states map[string]*intf.InterfacesState_Interface -} - -// Put is mocked implementation for interface state publishing. -func (m *MockIfStatePub) Put(key string, data proto.Message, opts ...datasync.PutOption) error { - logrus.DefaultLogger().Warnf("-> MyStatePub.Put(key: %v, data: %#v, opts: %v)", key, data, opts) - //var state intf.InterfacesState_Interface - if state, ok := data.(*intf.InterfacesState_Interface); ok { - m.states[state.Name] = state - } else { - logrus.DefaultLogger().Warnf("invalid type received") - } - return nil -} - -// InterfaceState returns state from mocked interface state publisher. -func (m *MockIfStatePub) InterfaceState(ifaceName string, ifState *intf.InterfacesState_Interface) (bool, error) { - state, found := m.states[ifaceName] - logrus.DefaultLogger().Warnf("-> InterfaceState(%v) - %+v", ifaceName, state) - if found { - *ifState = *state - } - return found, nil -} - -// NewIfStatePub returns new instance of MockIfStatePub. -func NewIfStatePub() *MockIfStatePub { - return &MockIfStatePub{ - states: make(map[string]*intf.InterfacesState_Interface), - } -} - -// Inject sets object references. -func (f *VppOnlyTestingFlavor) Inject() bool { - if f.injected { - return true - } - f.injected = true - - if f.FlavorLocal == nil { - f.FlavorLocal = &local.FlavorLocal{} - } - f.FlavorLocal.Inject() - - f.GoVPP.Deps.PluginInfraDeps = *f.FlavorLocal.InfraDeps("govpp") - f.VPP.Deps.PluginInfraDeps = *f.FlavorLocal.InfraDeps("vpp-plugin") - //nil: f.VPP.Deps.Linux - f.VPP.Deps.GoVppmux = &f.GoVPP - f.VPP.Deps.Watch = localsync.Get() - //nil: f.VPP.Deps.Messaging - f.VPP.Deps.IfStatePub = f.IfStatePub - //f.VPP.Deps.Publish = StatePub - - //TODO f.VPP.Deps.Publish = local_sync.Get() - - return false -} - -// Plugins combines Generic Plugins and Standard VPP Plugins. -func (f *VppOnlyTestingFlavor) Plugins() []*core.NamedPlugin { - f.Inject() - return core.ListPluginsInFlavor(f) -} - -/* -// SetupDefault setups default behaviour of mocks and delegates to Setup(Flavor). -func (t *VppAgentT) SetupDefault() (flavor *VppOnlyTestingFlavor) { - flavor = &VppOnlyTestingFlavor{ - GoVPP: *VppMock(iftst.RepliesSuccess), - } - - t.Setup(flavor) - - return flavor -} - -// Setup registers gomega and starts the agent with the flavor argument. -func (t *VppAgentT) Setup(flavor core.Flavor) { - //gomega.RegisterTestingT(t.T) - - t.agent = core.NewAgent(flavor) - err := t.agent.Start() - if err != nil { - logrus.DefaultLogger().Panic(err) - } -} - -// Teardown stops the agent. -func (t *VppAgentT) Teardown() { - if t.agent != nil { - err := t.agent.Stop() - if err != nil { - logrus.DefaultLogger().Panic(err) - } - } -} - -// VppMock allows to mock go VPP plugin in a flavor. -func VppMock(vppMockSetups ...func(adapter *mock.VppAdapter)) *govppmux.GOVPPPlugin { - vppMock := &mock.VppAdapter{} - for _, vppMockSetup := range vppMockSetups { - vppMockSetup(vppMock) - } - return govppmux.FromExistingAdapter(vppMock) -} -*/ diff --git a/tests/linuxmock/namespace_mock.go b/tests/linuxmock/namespace_mock.go index 36dd5dcf38..00bf7976ac 100644 --- a/tests/linuxmock/namespace_mock.go +++ b/tests/linuxmock/namespace_mock.go @@ -8,7 +8,7 @@ import ( // NamespacePluginMock allows to mock namespace plugin methods to manage namespaces and microservices type NamespacePluginMock struct { - responses []*whenNsResp + responses []*WhenNsResp respCurr int respMax int } @@ -16,20 +16,20 @@ type NamespacePluginMock struct { // NewNamespacePluginMock creates new instance of the mock and initializes response list func NewNamespacePluginMock() *NamespacePluginMock { return &NamespacePluginMock{ - responses: make([]*whenNsResp, 0), + responses: make([]*WhenNsResp, 0), } } -// Helper struct with single method call and desired response items -type whenNsResp struct { +// WhenNsResp is helper struct with single method call and desired response items +type WhenNsResp struct { methodName string items []interface{} } -// When defines name of the related method. It creates a new instance of whenNsResp with provided method name and +// When defines name of the related method. It creates a new instance of WhenNsResp with provided method name and // stores it to the mock. -func (mock *NamespacePluginMock) When(methodName string) *whenNsResp { - resp := &whenNsResp{ +func (mock *NamespacePluginMock) When(methodName string) *WhenNsResp { + resp := &WhenNsResp{ methodName: methodName, } mock.responses = append(mock.responses, resp) @@ -48,7 +48,7 @@ func (mock *NamespacePluginMock) When(methodName string) *whenNsResp { // - When('method1').ThenReturn('val1') // // All mocked methods are evaluated in same order they were assigned. -func (when *whenNsResp) ThenReturn(item ...interface{}) { +func (when *WhenNsResp) ThenReturn(item ...interface{}) { when.items = item } @@ -67,11 +67,13 @@ func (mock *NamespacePluginMock) getReturnValues(name string) (response []interf /* Mocked netlink handler methods */ //todo define other +// IsNamespaceAvailable implements NsManagement. func (mock *NamespacePluginMock) IsNamespaceAvailable(ns *interfaces.LinuxInterfaces_Interface_Namespace) bool { items := mock.getReturnValues("IsNamespaceAvailable") return items[0].(bool) } +// SwitchNamespace implements NsManagement. func (mock *NamespacePluginMock) SwitchNamespace(ns *nsplugin.Namespace, ctx *nsplugin.NamespaceMgmtCtx) (func(), error) { items := mock.getReturnValues("SwitchNamespace") if len(items) == 1 { @@ -87,6 +89,7 @@ func (mock *NamespacePluginMock) SwitchNamespace(ns *nsplugin.Namespace, ctx *ns return func() {}, nil } +// SwitchToNamespace implements NsManagement. func (mock *NamespacePluginMock) SwitchToNamespace(nsMgmtCtx *nsplugin.NamespaceMgmtCtx, ns *interfaces.LinuxInterfaces_Interface_Namespace) (func(), error) { items := mock.getReturnValues("SwitchToNamespace") if len(items) == 1 { @@ -102,6 +105,7 @@ func (mock *NamespacePluginMock) SwitchToNamespace(nsMgmtCtx *nsplugin.Namespace return func() {}, nil } +// SetInterfaceNamespace implements NsManagement. func (mock *NamespacePluginMock) SetInterfaceNamespace(ctx *nsplugin.NamespaceMgmtCtx, ifName string, namespace *interfaces.LinuxInterfaces_Interface_Namespace) error { items := mock.getReturnValues("SetInterfaceNamespace") if len(items) >= 1 { @@ -110,6 +114,7 @@ func (mock *NamespacePluginMock) SetInterfaceNamespace(ctx *nsplugin.NamespaceMg return nil } +// GetConfigNamespace implements NsManagement. func (mock *NamespacePluginMock) GetConfigNamespace() *interfaces.LinuxInterfaces_Interface_Namespace { items := mock.getReturnValues("GetConfigNamespace") if len(items) >= 1 { @@ -118,6 +123,7 @@ func (mock *NamespacePluginMock) GetConfigNamespace() *interfaces.LinuxInterface return nil } +// IfaceNsToString implements NsConvertor. func (mock *NamespacePluginMock) IfaceNsToString(namespace *interfaces.LinuxInterfaces_Interface_Namespace) string { items := mock.getReturnValues("IfaceNsToString") if len(items) >= 1 { @@ -126,6 +132,7 @@ func (mock *NamespacePluginMock) IfaceNsToString(namespace *interfaces.LinuxInte return "" } +// IfNsToGeneric implements NsConvertor. func (mock *NamespacePluginMock) IfNsToGeneric(ns *interfaces.LinuxInterfaces_Interface_Namespace) *nsplugin.Namespace { items := mock.getReturnValues("IfNsToGeneric") if len(items) >= 1 { @@ -134,6 +141,7 @@ func (mock *NamespacePluginMock) IfNsToGeneric(ns *interfaces.LinuxInterfaces_In return nil } +// ArpNsToGeneric implements NsConvertor. func (mock *NamespacePluginMock) ArpNsToGeneric(ns *l3.LinuxStaticArpEntries_ArpEntry_Namespace) *nsplugin.Namespace { items := mock.getReturnValues("ArpNsToGeneric") if len(items) >= 1 { @@ -142,6 +150,7 @@ func (mock *NamespacePluginMock) ArpNsToGeneric(ns *l3.LinuxStaticArpEntries_Arp return nil } +// GenericToArpNs implements NsConvertor. func (mock *NamespacePluginMock) GenericToArpNs(ns *nsplugin.Namespace) (*l3.LinuxStaticArpEntries_ArpEntry_Namespace, error) { items := mock.getReturnValues("GenericToArpNs") if len(items) == 1 { @@ -157,6 +166,7 @@ func (mock *NamespacePluginMock) GenericToArpNs(ns *nsplugin.Namespace) (*l3.Lin return nil, nil } +// RouteNsToGeneric implements NsConvertor. func (mock *NamespacePluginMock) RouteNsToGeneric(ns *l3.LinuxStaticRoutes_Route_Namespace) *nsplugin.Namespace { items := mock.getReturnValues("RouteNsToGeneric") if len(items) >= 1 { @@ -165,4 +175,5 @@ func (mock *NamespacePluginMock) RouteNsToGeneric(ns *l3.LinuxStaticRoutes_Route return nil } +// HandleMicroservices implements Microservices. func (mock *NamespacePluginMock) HandleMicroservices(ctx *nsplugin.MicroserviceCtx) {} diff --git a/tests/linuxmock/netlink_if_handler_mock.go b/tests/linuxmock/netlink_if_handler_mock.go index 8a7293d32c..fd0dc489d5 100644 --- a/tests/linuxmock/netlink_if_handler_mock.go +++ b/tests/linuxmock/netlink_if_handler_mock.go @@ -15,35 +15,43 @@ package linuxmock import ( + "net" + "github.com/ligato/cn-infra/logging/measure" "github.com/vishvananda/netlink" - "net" ) -// NetlinkHandlerMock allows to mock netlink-related methods +// IfNetlinkHandlerMock allows to mock netlink-related methods type IfNetlinkHandlerMock struct { - responses []*whenIfResp + responses []*WhenIfResp + calls []*called respCurr int respMax int } -// NewNetlinkHandlerMock creates new instance of the mock and initializes response list +// NewIfNetlinkHandlerMock creates new instance of the mock and initializes response list func NewIfNetlinkHandlerMock() *IfNetlinkHandlerMock { return &IfNetlinkHandlerMock{ - responses: make([]*whenIfResp, 0), + responses: make([]*WhenIfResp, 0), } } -// Helper struct with single method call and desired response items -type whenIfResp struct { +// WhenIfResp is helper struct with single method call and desired response items +type WhenIfResp struct { methodName string items []interface{} } -// When defines name of the related method. It creates a new instance of whenIfResp with provided method name and +// called is helper struct with method name which was called including parameters +type called struct { + methodName string + params []interface{} +} + +// When defines name of the related method. It creates a new instance of WhenIfResp with provided method name and // stores it to the mock. -func (mock *IfNetlinkHandlerMock) When(name string) *whenIfResp { - resp := &whenIfResp{ +func (mock *IfNetlinkHandlerMock) When(name string) *WhenIfResp { + resp := &WhenIfResp{ methodName: name, } mock.responses = append(mock.responses, resp) @@ -62,10 +70,23 @@ func (mock *IfNetlinkHandlerMock) When(name string) *whenIfResp { // - When('method1').ThenReturn('val1') // // All mocked methods are evaluated in same order they were assigned. -func (when *whenIfResp) ThenReturn(item ...interface{}) { +func (when *WhenIfResp) ThenReturn(item ...interface{}) { when.items = item } +// GetCallsFor returns number of calls for specific method including parameters used for every call +func (mock *IfNetlinkHandlerMock) GetCallsFor(name string) (numCalls int, params map[int][]interface{}) { + params = make(map[int][]interface{}) + index := 0 + for _, call := range mock.calls { + if call.methodName == name { + index++ + params[index] = call.params + } + } + return index, params +} + // Auxiliary method returns next return value for provided method as generic type func (mock *IfNetlinkHandlerMock) getReturnValues(name string) (response []interface{}) { for i, resp := range mock.responses { @@ -79,8 +100,16 @@ func (mock *IfNetlinkHandlerMock) getReturnValues(name string) (response []inter return } +// Auxiliary method adds method/params entry to the mock +func (mock *IfNetlinkHandlerMock) addCalled(name string, params ...interface{}) { + var parameters []interface{} + parameters = append(parameters, params) + mock.calls = append(mock.calls, &called{methodName: name, params: params}) +} + /* Mocked netlink handler methods */ +// AddVethInterfacePair implements NetlinkAPI. func (mock *IfNetlinkHandlerMock) AddVethInterfacePair(ifName, peerIfName string) error { items := mock.getReturnValues("AddVethInterfacePair") if len(items) >= 1 { @@ -89,6 +118,7 @@ func (mock *IfNetlinkHandlerMock) AddVethInterfacePair(ifName, peerIfName string return nil } +// DelVethInterfacePair implements NetlinkAPI. func (mock *IfNetlinkHandlerMock) DelVethInterfacePair(ifName, peerIfName string) error { items := mock.getReturnValues("DelVethInterfacePair") if len(items) >= 1 { @@ -97,6 +127,7 @@ func (mock *IfNetlinkHandlerMock) DelVethInterfacePair(ifName, peerIfName string return nil } +// SetInterfaceUp implements NetlinkAPI. func (mock *IfNetlinkHandlerMock) SetInterfaceUp(ifName string) error { items := mock.getReturnValues("SetInterfaceUp") if len(items) >= 1 { @@ -105,6 +136,7 @@ func (mock *IfNetlinkHandlerMock) SetInterfaceUp(ifName string) error { return nil } +// SetInterfaceDown implements NetlinkAPI. func (mock *IfNetlinkHandlerMock) SetInterfaceDown(ifName string) error { items := mock.getReturnValues("SetInterfaceDown") if len(items) >= 1 { @@ -113,7 +145,9 @@ func (mock *IfNetlinkHandlerMock) SetInterfaceDown(ifName string) error { return nil } +// AddInterfaceIP implements NetlinkAPI. func (mock *IfNetlinkHandlerMock) AddInterfaceIP(ifName string, addr *net.IPNet) error { + mock.addCalled("AddInterfaceIP", ifName, addr) items := mock.getReturnValues("AddInterfaceIP") if len(items) >= 1 { return items[0].(error) @@ -121,6 +155,7 @@ func (mock *IfNetlinkHandlerMock) AddInterfaceIP(ifName string, addr *net.IPNet) return nil } +// DelInterfaceIP implements NetlinkAPI. func (mock *IfNetlinkHandlerMock) DelInterfaceIP(ifName string, addr *net.IPNet) error { items := mock.getReturnValues("DelInterfaceIP") if len(items) >= 1 { @@ -129,6 +164,7 @@ func (mock *IfNetlinkHandlerMock) DelInterfaceIP(ifName string, addr *net.IPNet) return nil } +// SetInterfaceMac implements NetlinkAPI. func (mock *IfNetlinkHandlerMock) SetInterfaceMac(ifName string, macAddress string) error { items := mock.getReturnValues("SetInterfaceMac") if len(items) >= 1 { @@ -137,6 +173,7 @@ func (mock *IfNetlinkHandlerMock) SetInterfaceMac(ifName string, macAddress stri return nil } +// SetInterfaceMTU implements NetlinkAPI. func (mock *IfNetlinkHandlerMock) SetInterfaceMTU(ifName string, mtu int) error { items := mock.getReturnValues("SetInterfaceMTU") if len(items) >= 1 { @@ -145,6 +182,7 @@ func (mock *IfNetlinkHandlerMock) SetInterfaceMTU(ifName string, mtu int) error return nil } +// RenameInterface implements NetlinkAPI. func (mock *IfNetlinkHandlerMock) RenameInterface(ifName string, newName string) error { items := mock.getReturnValues("RenameInterface") if len(items) >= 1 { @@ -153,6 +191,7 @@ func (mock *IfNetlinkHandlerMock) RenameInterface(ifName string, newName string) return nil } +// GetLinkByName implements NetlinkAPI. func (mock *IfNetlinkHandlerMock) GetLinkByName(ifName string) (netlink.Link, error) { items := mock.getReturnValues("GetLinkByName") if len(items) == 1 { @@ -168,6 +207,7 @@ func (mock *IfNetlinkHandlerMock) GetLinkByName(ifName string) (netlink.Link, er return nil, nil } +// GetLinkList implements NetlinkAPI. func (mock *IfNetlinkHandlerMock) GetLinkList() ([]netlink.Link, error) { items := mock.getReturnValues("GetLinkList") if len(items) == 1 { @@ -183,6 +223,7 @@ func (mock *IfNetlinkHandlerMock) GetLinkList() ([]netlink.Link, error) { return nil, nil } +// GetAddressList implements NetlinkAPI. func (mock *IfNetlinkHandlerMock) GetAddressList(ifName string) ([]netlink.Addr, error) { items := mock.getReturnValues("GetAddressList") if len(items) == 1 { @@ -198,6 +239,7 @@ func (mock *IfNetlinkHandlerMock) GetAddressList(ifName string) ([]netlink.Addr, return nil, nil } +// InterfaceExists implements NetlinkAPI. func (mock *IfNetlinkHandlerMock) InterfaceExists(ifName string) (bool, error) { items := mock.getReturnValues("InterfaceExists") if len(items) == 1 { @@ -213,6 +255,7 @@ func (mock *IfNetlinkHandlerMock) InterfaceExists(ifName string) (bool, error) { return false, nil } +// GetInterfaceType implements NetlinkAPI. func (mock *IfNetlinkHandlerMock) GetInterfaceType(ifName string) (string, error) { items := mock.getReturnValues("GetInterfaceType") if len(items) == 1 { @@ -228,6 +271,7 @@ func (mock *IfNetlinkHandlerMock) GetInterfaceType(ifName string) (string, error return "", nil } +// GetVethPeerName implements NetlinkAPI. func (mock *IfNetlinkHandlerMock) GetVethPeerName(ifName string) (string, error) { items := mock.getReturnValues("GetVethPeerName") if len(items) == 1 { @@ -243,6 +287,7 @@ func (mock *IfNetlinkHandlerMock) GetVethPeerName(ifName string) (string, error) return "", nil } +// GetInterfaceByName implements NetlinkAPI. func (mock *IfNetlinkHandlerMock) GetInterfaceByName(ifName string) (*net.Interface, error) { items := mock.getReturnValues("GetInterfaceByName") if len(items) == 1 { @@ -258,4 +303,5 @@ func (mock *IfNetlinkHandlerMock) GetInterfaceByName(ifName string) (*net.Interf return nil, nil } +// SetStopwatch sets stopwatch. func (mock *IfNetlinkHandlerMock) SetStopwatch(stopwatch *measure.Stopwatch) {} diff --git a/tests/linuxmock/netlink_l3_handler_mock.go b/tests/linuxmock/netlink_l3_handler_mock.go index 0de30a8f50..b6929c4333 100644 --- a/tests/linuxmock/netlink_l3_handler_mock.go +++ b/tests/linuxmock/netlink_l3_handler_mock.go @@ -19,30 +19,30 @@ import ( "github.com/vishvananda/netlink" ) -// NetlinkHandlerMock allows to mock netlink-related methods +// L3NetlinkHandlerMock allows to mock netlink-related methods type L3NetlinkHandlerMock struct { - responses []*whenL3Resp + responses []*WhenL3Resp respCurr int respMax int } -// NewNetlinkHandlerMock creates new instance of the mock and initializes response list +// NewL3NetlinkHandlerMock creates new instance of the mock and initializes response list func NewL3NetlinkHandlerMock() *L3NetlinkHandlerMock { return &L3NetlinkHandlerMock{ - responses: make([]*whenL3Resp, 0), + responses: make([]*WhenL3Resp, 0), } } -// Helper struct with single method call and desired response items -type whenL3Resp struct { +// WhenL3Resp is helper struct with single method call and desired response items +type WhenL3Resp struct { methodName string items []interface{} } -// When defines name of the related method. It creates a new instance of whenL3Resp with provided method name and +// When defines name of the related method. It creates a new instance of WhenL3Resp with provided method name and // stores it to the mock. -func (mock *L3NetlinkHandlerMock) When(name string) *whenL3Resp { - resp := &whenL3Resp{ +func (mock *L3NetlinkHandlerMock) When(name string) *WhenL3Resp { + resp := &WhenL3Resp{ methodName: name, } mock.responses = append(mock.responses, resp) @@ -61,7 +61,7 @@ func (mock *L3NetlinkHandlerMock) When(name string) *whenL3Resp { // - When('method1').ThenReturn('val1') // // All mocked methods are evaluated in same order they were assigned. -func (when *whenL3Resp) ThenReturn(item ...interface{}) { +func (when *WhenL3Resp) ThenReturn(item ...interface{}) { when.items = item } @@ -80,6 +80,7 @@ func (mock *L3NetlinkHandlerMock) getReturnValues(name string) (response []inter /* Mocked netlink handler methods */ +// AddArpEntry implements NetlinkAPI. func (mock *L3NetlinkHandlerMock) AddArpEntry(name string, arpEntry *netlink.Neigh) error { items := mock.getReturnValues("AddArpEntry") if len(items) >= 1 { @@ -88,6 +89,7 @@ func (mock *L3NetlinkHandlerMock) AddArpEntry(name string, arpEntry *netlink.Nei return nil } +// SetArpEntry implements NetlinkAPI. func (mock *L3NetlinkHandlerMock) SetArpEntry(name string, arpEntry *netlink.Neigh) error { items := mock.getReturnValues("SetArpEntry") if len(items) >= 1 { @@ -96,6 +98,7 @@ func (mock *L3NetlinkHandlerMock) SetArpEntry(name string, arpEntry *netlink.Nei return nil } +// DelArpEntry implements NetlinkAPI. func (mock *L3NetlinkHandlerMock) DelArpEntry(name string, arpEntry *netlink.Neigh) error { items := mock.getReturnValues("DelArpEntry") if len(items) >= 1 { @@ -104,6 +107,7 @@ func (mock *L3NetlinkHandlerMock) DelArpEntry(name string, arpEntry *netlink.Nei return nil } +// GetArpEntries implements NetlinkAPI. func (mock *L3NetlinkHandlerMock) GetArpEntries(interfaceIdx int, family int) ([]netlink.Neigh, error) { items := mock.getReturnValues("GetArpEntries") if len(items) == 1 { @@ -119,6 +123,7 @@ func (mock *L3NetlinkHandlerMock) GetArpEntries(interfaceIdx int, family int) ([ return nil, nil } +// AddStaticRoute implements NetlinkAPI. func (mock *L3NetlinkHandlerMock) AddStaticRoute(name string, route *netlink.Route) error { items := mock.getReturnValues("AddStaticRoute") if len(items) >= 1 { @@ -127,6 +132,7 @@ func (mock *L3NetlinkHandlerMock) AddStaticRoute(name string, route *netlink.Rou return nil } +// ReplaceStaticRoute implements NetlinkAPI. func (mock *L3NetlinkHandlerMock) ReplaceStaticRoute(name string, route *netlink.Route) error { items := mock.getReturnValues("ReplaceStaticRoute") if len(items) >= 1 { @@ -135,6 +141,7 @@ func (mock *L3NetlinkHandlerMock) ReplaceStaticRoute(name string, route *netlink return nil } +// DelStaticRoute implements NetlinkAPI. func (mock *L3NetlinkHandlerMock) DelStaticRoute(name string, route *netlink.Route) error { items := mock.getReturnValues("DelStaticRoute") if len(items) >= 1 { @@ -143,4 +150,5 @@ func (mock *L3NetlinkHandlerMock) DelStaticRoute(name string, route *netlink.Rou return nil } +// SetStopwatch implements . func (mock *L3NetlinkHandlerMock) SetStopwatch(stopwatch *measure.Stopwatch) {} diff --git a/tests/linuxmock/system_mock.go b/tests/linuxmock/system_mock.go index 0bbd09a2fe..fdb98f74e5 100644 --- a/tests/linuxmock/system_mock.go +++ b/tests/linuxmock/system_mock.go @@ -15,13 +15,15 @@ package linuxmock import ( - "github.com/vishvananda/netns" "os" + + "github.com/vishvananda/netlink" + "github.com/vishvananda/netns" ) // SystemMock allows to mock netlink-related methods type SystemMock struct { - responses []*whenStResp + responses []*WhenStResp respCurr int respMax int } @@ -29,20 +31,20 @@ type SystemMock struct { // NewSystemMock creates new instance of the mock and initializes response list func NewSystemMock() *SystemMock { return &SystemMock{ - responses: make([]*whenStResp, 0), + responses: make([]*WhenStResp, 0), } } -// Helper struct with single method call and desired response items -type whenStResp struct { +// WhenStResp is helper struct with single method call and desired response items +type WhenStResp struct { methodName string items []interface{} } -// When defines name of the related method. It creates a new instance of whenStResp with provided method name and +// When defines name of the related method. It creates a new instance of WhenStResp with provided method name and // stores it to the mock. -func (mock *SystemMock) When(name string) *whenStResp { - resp := &whenStResp{ +func (mock *SystemMock) When(name string) *WhenStResp { + resp := &WhenStResp{ methodName: name, } mock.responses = append(mock.responses, resp) @@ -61,7 +63,7 @@ func (mock *SystemMock) When(name string) *whenStResp { // - When('method1').ThenReturn('val1') // // All mocked methods are evaluated in same order they were assigned. -func (when *whenStResp) ThenReturn(item ...interface{}) { +func (when *WhenStResp) ThenReturn(item ...interface{}) { when.items = item } @@ -78,6 +80,7 @@ func (mock *SystemMock) getReturnValues(name string) (response []interface{}) { return } +// OpenFile implements OperatingSystem. func (mock *SystemMock) OpenFile(name string, flag int, perm os.FileMode) (*os.File, error) { items := mock.getReturnValues("OpenFile") if len(items) == 1 { @@ -93,6 +96,7 @@ func (mock *SystemMock) OpenFile(name string, flag int, perm os.FileMode) (*os.F return nil, nil } +// MkDirAll implements OperatingSystem. func (mock *SystemMock) MkDirAll(path string, perm os.FileMode) error { items := mock.getReturnValues("MkDirAll") if len(items) >= 1 { @@ -101,6 +105,7 @@ func (mock *SystemMock) MkDirAll(path string, perm os.FileMode) error { return nil } +// Remove implements OperatingSystem. func (mock *SystemMock) Remove(name string) error { items := mock.getReturnValues("Remove") if len(items) >= 1 { @@ -109,6 +114,7 @@ func (mock *SystemMock) Remove(name string) error { return nil } +// Mount implements Syscall. func (mock *SystemMock) Mount(source string, target string, fsType string, flags uintptr, data string) error { items := mock.getReturnValues("Mount") if len(items) >= 1 { @@ -117,6 +123,7 @@ func (mock *SystemMock) Mount(source string, target string, fsType string, flags return nil } +// Unmount implements Syscall. func (mock *SystemMock) Unmount(target string, flags int) error { items := mock.getReturnValues("Unmount") if len(items) >= 1 { @@ -125,6 +132,7 @@ func (mock *SystemMock) Unmount(target string, flags int) error { return nil } +// NewNetworkNamespace implements NetlinkNamespace. func (mock *SystemMock) NewNetworkNamespace() (netns.NsHandle, error) { items := mock.getReturnValues("NewNetworkNamespace") if len(items) == 1 { @@ -140,6 +148,7 @@ func (mock *SystemMock) NewNetworkNamespace() (netns.NsHandle, error) { return 0, nil } +// GetNamespaceFromName implements NetNsNamespace. func (mock *SystemMock) GetNamespaceFromName(name string) (netns.NsHandle, error) { items := mock.getReturnValues("GetNamespaceFromName") if len(items) == 1 { @@ -155,6 +164,7 @@ func (mock *SystemMock) GetNamespaceFromName(name string) (netns.NsHandle, error return 0, nil } +// SetNamespace implements NetNsNamespace. func (mock *SystemMock) SetNamespace(ns netns.NsHandle) error { items := mock.getReturnValues("SetNamespace") if len(items) >= 1 { @@ -162,3 +172,12 @@ func (mock *SystemMock) SetNamespace(ns netns.NsHandle) error { } return nil } + +// LinkSetNsFd implements NetlinkNamespace. +func (mock *SystemMock) LinkSetNsFd(link netlink.Link, fd int) error { + items := mock.getReturnValues("LinkSetNsFd") + if len(items) >= 1 { + return items[0].(error) + } + return nil +} diff --git a/tests/perf/vnf-vpp.yaml b/tests/perf/vnf-vpp.yaml index f534a6770d..efddbe1f26 100644 --- a/tests/perf/vnf-vpp.yaml +++ b/tests/perf/vnf-vpp.yaml @@ -53,12 +53,12 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vnf-vpp-cfg - - name: agent-config - configMap: - name: vnf-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp + - name: vpp-config + configMap: + name: vnf-vpp-cfg + - name: agent-config + configMap: + name: vnf-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp diff --git a/tests/perf/vpp.yaml b/tests/perf/vpp.yaml index f603af0196..4bdc11b5ad 100644 --- a/tests/perf/vpp.yaml +++ b/tests/perf/vpp.yaml @@ -38,7 +38,7 @@ kind: ConfigMap metadata: name: vswitch-supervisord-cfg data: - supervisord.conf: | + supervisord.conf: | [supervisord] logfile=/var/log/supervisord.log loglevel=debug @@ -56,13 +56,13 @@ data: autorestart=false redirect_stderr=true priority=2 - + ; This event listener waits for event of vpp or agent exitting. Once received, it kills supervisord process and this makes ; subsequently the exit of docker container. You should also set agent autorestart=false. [eventlistener:vpp_or_agent_not_running] command=/usr/bin/supervisord_kill.py events=PROCESS_STATE_EXITED ---- +--- apiVersion: v1 kind: Pod metadata: @@ -89,15 +89,15 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vswitch-vpp-cfg - - name: agent-config - configMap: - name: vswitch-agent-cfg - - name: supervisor-config - configMap: - name: vswitch-supervisord-cfg - - name: memif-sockets - hostPath: - path: /tmp + - name: vpp-config + configMap: + name: vswitch-vpp-cfg + - name: agent-config + configMap: + name: vswitch-agent-cfg + - name: supervisor-config + configMap: + name: vswitch-supervisord-cfg + - name: memif-sockets + hostPath: + path: /tmp diff --git a/tests/perf/vswitch-vpp.yaml b/tests/perf/vswitch-vpp.yaml index 48c2578409..89bf915c84 100644 --- a/tests/perf/vswitch-vpp.yaml +++ b/tests/perf/vswitch-vpp.yaml @@ -30,14 +30,14 @@ data: vppplugin.conf: | stopwatch: true linuxplugin.conf: | - stopwatch: true + stopwatch: true --- apiVersion: v1 kind: ConfigMap metadata: name: vswitch-supervisord-cfg data: - supervisord.conf: | + supervisord.conf: | [supervisord] logfile=/var/log/supervisord.log loglevel=debug @@ -55,7 +55,7 @@ data: autorestart=false redirect_stderr=true priority=2 - + ; This event listener waits for event of vpp or agent exitting. Once received, it kills supervisord process and this makes ; subsequently the exit of docker container. You should also set agent autorestart=false. [eventlistener:vpp_or_agent_not_running] @@ -89,15 +89,15 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vswitch-vpp-cfg - - name: agent-config - configMap: - name: vswitch-agent-cfg - - name: supervisor-config - configMap: - name: vswitch-supervisord-cfg - - name: memif-sockets - hostPath: - path: /tmp \ No newline at end of file + - name: vpp-config + configMap: + name: vswitch-vpp-cfg + - name: agent-config + configMap: + name: vswitch-agent-cfg + - name: supervisor-config + configMap: + name: vswitch-supervisord-cfg + - name: memif-sockets + hostPath: + path: /tmp diff --git a/tests/robot/libraries/basic_operations.py b/tests/robot/libraries/basic_operations.py index c33512f11a..2dfa9ce07d 100644 --- a/tests/robot/libraries/basic_operations.py +++ b/tests/robot/libraries/basic_operations.py @@ -28,3 +28,8 @@ def file_exists(path): exists = False return exists +def replace_rn_n(mytext): + if mytext=="": + return "" + mytext=mytext.replace("\r\n", "\n") + return mytext diff --git a/tests/robot/libraries/pretty_keywords.robot b/tests/robot/libraries/pretty_keywords.robot index 1e49347148..b2c66ec3ea 100644 --- a/tests/robot/libraries/pretty_keywords.robot +++ b/tests/robot/libraries/pretty_keywords.robot @@ -69,6 +69,17 @@ Create Route On ${node} With IP ${ip}/${prefix} With Next Hop ${next_hop} And Vr ${out}= vpp_ctl: Put Json ${uri} ${data} Log Many ${out} +Create Route On ${node} With IP ${ip}/${prefix} With Next Hop VRF ${next_hop_vrf} From Vrf Id ${id} And Type ${type} + Log Many ${node} ${ip} ${prefix} ${next_hop_vrf} ${id} ${type} + ${data}= OperatingSystem.Get File ${CURDIR}/../../robot/resources/route_to_other_vrf.json + Log Many ${data} + ${data}= replace variables ${data} + Log Many ${data} + ${uri}= Set Variable /vnf-agent/${node}/vpp/config/v1/vrf/${id}/fib/${ip}/${prefix} + Log Many ${uri} + ${out}= vpp_ctl: Put Json ${uri} ${data} + Log Many ${out} + Delete IPsec On ${node} With Prefix ${prefix} And Name ${name} Log Many ${node} ${prefix} ${name} vpp_ctl: Delete IPsec ${node} ${prefix} ${name} diff --git a/tests/robot/libraries/setup-teardown.robot b/tests/robot/libraries/setup-teardown.robot index efd4a1af35..cc78b96b20 100644 --- a/tests/robot/libraries/setup-teardown.robot +++ b/tests/robot/libraries/setup-teardown.robot @@ -69,6 +69,7 @@ Discard old results Remove Directory ${RESULTS_FOLDER_SUITE} recursive=true Create Directory ${RESULTS_FOLDER} + Log All SSH Outputs [Documentation] *Log All SSH Outputs* ... Logs all connections outputs diff --git a/tests/robot/libraries/vpp_ctl.robot b/tests/robot/libraries/vpp_ctl.robot index ca1e465f1e..137d1fc80e 100644 --- a/tests/robot/libraries/vpp_ctl.robot +++ b/tests/robot/libraries/vpp_ctl.robot @@ -239,7 +239,6 @@ vpp_ctl: Put TAP Interface With IP ${data}= Replace Variables ${data} Log ${data} vpp_ctl: Put Json ${uri} ${data} - Sleep 10s Time to let etcd to get state of newly setup tap interface. vpp_ctl: Put TAP Unnumbered Interface [Arguments] ${node} ${name} ${mac} ${unnumbered} ${interface_with_ip_name} ${host_if_name} ${mtu}=1500 ${enabled}=true @@ -250,7 +249,7 @@ vpp_ctl: Put TAP Unnumbered Interface ${data}= Replace Variables ${data} Log ${data} vpp_ctl: Put Json ${uri} ${data} - Sleep 10s Time to let etcd to get state of newly setup tap interface. + vpp_ctl: Put Static Fib Entry [Arguments] ${node} ${bd_name} ${mac} ${outgoing_interface} ${static}=true @@ -310,6 +309,14 @@ vpp_ctl: Delete Linux Interface Log Many ${out} [Return] ${out} +vpp_ctl: Delete Route + [Arguments] ${node} ${id} ${ip} ${prefix} + ${uri}= Set Variable /vnf-agent/${node}/vpp/config/v1/vrf/${id}/fib/${ip}/${prefix} + Log Many ${uri} + ${out}= vpp_ctl: Delete key ${uri} + Log Many ${out} + [Return] ${out} + vpp_ctl: Delete Routes [Arguments] ${node} ${id} ${uri}= Set Variable /vnf-agent/${node}/vpp/config/v1/vrf/${id}/fib @@ -673,7 +680,6 @@ vpp_ctl: Put TAPv2 Interface With IP ${data}= Replace Variables ${data} Log ${data} vpp_ctl: Put Json ${uri} ${data} - Sleep 10s Time to let etcd to get state of newly setup tap interface. vpp_ctl: Put STN Rule [Arguments] ${node} ${interface} ${ip} ${rule_name} diff --git a/tests/robot/libraries/vpp_term.robot b/tests/robot/libraries/vpp_term.robot index fdd3d3b18d..b821fd549e 100644 --- a/tests/robot/libraries/vpp_term.robot +++ b/tests/robot/libraries/vpp_term.robot @@ -14,7 +14,9 @@ vpp_term: Check VPP Terminal [Arguments] ${node} [Documentation] Check terminal on node ${node} Log Many ${node} ${${node}_VPP_HOST_PORT} ${${node}_VPP_TERM_PROMPT} - ${command}= Set Variable telnet 0 ${${node}_VPP_HOST_PORT} + # using telnet does not work with latest VPP + #${command}= Set Variable telnet 0 ${${node}_VPP_HOST_PORT} + ${command}= Set Variable docker exec -it ${node} vppctl -s localhost:${${node}_VPP_PORT} ${out}= Write To Machine ${node}_term ${command} Should Contain ${out} ${${node}_VPP_TERM_PROMPT} [Return] ${out} @@ -492,6 +494,7 @@ vpp_term: Local SID exists ${localsidsStr}= vpp_term: Show Local SIDs ${node} Create File /tmp/srv6_sh_sr_localsid_output.txt ${localsidsStr} #FIXME remove dirty trick with saving string to file just to be able to match substring in string ${localsidsStr}= OperatingSystem.Get File /tmp/srv6_sh_sr_localsid_output.txt + ${localsidsStr}= Basic_Operations.Replace_Rn_N ${localsidsStr} #FIX for BUG with New Line ${localsidsStr}= Convert To Lowercase ${localsidsStr} Log ${localsidsStr} ${matchdata}= OperatingSystem.Get File ${CURDIR}/../suites/crud/test_data/srv6_sh_sr_localsid_output_match.txt @@ -540,6 +543,7 @@ vpp_term: SRv6 Policy exists ${policyStr}= vpp_term: Show SRv6 policies ${node} Create File /tmp/srv6_sh_sr_policies_output.txt ${policyStr} #FIXME remove dirty trick with saving string to file just to be able to match substring in string ${policyStr}= OperatingSystem.Get File /tmp/srv6_sh_sr_policies_output.txt + ${policyStr}= Basic_Operations.Replace_Rn_N ${policyStr} #FIX for BUG with New Line ${policyStr}= Convert To Lowercase ${policyStr} Log ${policyStr} ${policymatchdata}= OperatingSystem.Get File ${CURDIR}/../suites/crud/test_data/srv6_sh_sr_policies_output_match.txt diff --git a/tests/robot/resources/k8-yaml/etcd-k8.yaml b/tests/robot/resources/k8-yaml/etcd-k8.yaml index c5a3287f5a..e82bab424d 100644 --- a/tests/robot/resources/k8-yaml/etcd-k8.yaml +++ b/tests/robot/resources/k8-yaml/etcd-k8.yaml @@ -6,21 +6,21 @@ metadata: spec: hostNetwork: true containers: - - image: quay.io/coreos/etcd:v3.0.16 - imagePullPolicy: IfNotPresent - name: etcd - command: - - /usr/local/bin/etcd - - --advertise-client-urls - - http://0.0.0.0:22379 - - --listen-client-urls - - http://0.0.0.0:22379 - - --listen-peer-urls - - http://0.0.0.0:22380 - ports: - - containerPort: 22379 - hostPort: 22379 - name: serverport - env: - - name: ETCDCTL_API - value: "3" \ No newline at end of file + - image: quay.io/coreos/etcd:v3.0.16 + imagePullPolicy: IfNotPresent + name: etcd + command: + - /usr/local/bin/etcd + - --advertise-client-urls + - http://0.0.0.0:22379 + - --listen-client-urls + - http://0.0.0.0:22379 + - --listen-peer-urls + - http://0.0.0.0:22380 + ports: + - containerPort: 22379 + hostPort: 22379 + name: serverport + env: + - name: ETCDCTL_API + value: "3" diff --git a/tests/robot/resources/k8-yaml/novpp.yaml b/tests/robot/resources/k8-yaml/novpp.yaml index e70deba964..7b684c8515 100644 --- a/tests/robot/resources/k8-yaml/novpp.yaml +++ b/tests/robot/resources/k8-yaml/novpp.yaml @@ -30,6 +30,6 @@ spec: fieldRef: fieldPath: metadata.name volumes: - - name: veth-pair - hostPath: - path: /var/run/docker.sock + - name: veth-pair + hostPath: + path: /var/run/docker.sock diff --git a/tests/robot/resources/k8-yaml/sfc-k8.yaml b/tests/robot/resources/k8-yaml/sfc-k8.yaml index c42f0a90be..8aa41efac1 100644 --- a/tests/robot/resources/k8-yaml/sfc-k8.yaml +++ b/tests/robot/resources/k8-yaml/sfc-k8.yaml @@ -32,6 +32,6 @@ spec: - name: controller-config mountPath: /opt/sfc-controller/dev volumes: - - name: controller-config - configMap: - name: sfc-controller-cfg + - name: controller-config + configMap: + name: sfc-controller-cfg diff --git a/tests/robot/resources/k8-yaml/vnf-vpp.yaml b/tests/robot/resources/k8-yaml/vnf-vpp.yaml index 147c4a1ac8..add10afc59 100644 --- a/tests/robot/resources/k8-yaml/vnf-vpp.yaml +++ b/tests/robot/resources/k8-yaml/vnf-vpp.yaml @@ -102,15 +102,15 @@ spec: - name: memif-sockets mountPath: /tmp volumes: - - name: vpp-config - configMap: - name: vnf-vpp-cfg - - name: agent-config - configMap: - name: vswitch-k8-agent-cfg - - name: memif-sockets - hostPath: - path: /tmp - - name: supervisor-config - configMap: - name: vnf-supervisord-cfg \ No newline at end of file + - name: vpp-config + configMap: + name: vnf-vpp-cfg + - name: agent-config + configMap: + name: vswitch-k8-agent-cfg + - name: memif-sockets + hostPath: + path: /tmp + - name: supervisor-config + configMap: + name: vnf-supervisord-cfg diff --git a/tests/robot/resources/k8-yaml/vswitch.yaml b/tests/robot/resources/k8-yaml/vswitch.yaml index c092976736..5407513c84 100644 --- a/tests/robot/resources/k8-yaml/vswitch.yaml +++ b/tests/robot/resources/k8-yaml/vswitch.yaml @@ -131,19 +131,18 @@ spec: mountPath: /var/run/docker.sock volumes: - - name: vpp-config - configMap: - name: vswitch-k8-vpp-cfg - - name: agent-config - configMap: - name: vswitch-k8-agent-cfg - - name: supervisor-config - configMap: - name: vswitch-k8-supervisord-cfg - - name: memif-sockets - hostPath: - path: /tmp - - name: veth-pair - hostPath: - path: /var/run/docker.sock - + - name: vpp-config + configMap: + name: vswitch-k8-vpp-cfg + - name: agent-config + configMap: + name: vswitch-k8-agent-cfg + - name: supervisor-config + configMap: + name: vswitch-k8-supervisord-cfg + - name: memif-sockets + hostPath: + path: /tmp + - name: veth-pair + hostPath: + path: /var/run/docker.sock diff --git a/tests/robot/resources/route_to_other_vrf.json b/tests/robot/resources/route_to_other_vrf.json new file mode 100644 index 0000000000..dcc1823f28 --- /dev/null +++ b/tests/robot/resources/route_to_other_vrf.json @@ -0,0 +1,6 @@ +{ + "type": ${type}, + "dst_ip_addr": "${ip}/${prefix}", + "vrf_id": ${id}, + "via_vrf_id": ${next_hop_vrf} +} \ No newline at end of file diff --git a/tests/robot/suites/crud/acl_crud.robot b/tests/robot/suites/crud/acl_crud.robot index 065b1fdd53..2514431157 100644 --- a/tests/robot/suites/crud/acl_crud.robot +++ b/tests/robot/suites/crud/acl_crud.robot @@ -48,7 +48,8 @@ ${2DEST_PORT_L}= 2000 ${2DEST_PORT_U}= 2200 ${2SRC_PORT_L}= 20010 ${2SRC_PORT_U}= 20020 -${SYNC_SLEEP}= 1s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s ${NO_ACL}= @@ -62,102 +63,92 @@ Configure Environment Set Suite Variable ${API_HANDLER} ${api_handler} Show ACL Before Setup - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL1_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl_empty_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL1_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl_empty_term.txt Add ACL1_TCP vpp_ctl: Put ACL TCP agent_vpp_1 ${ACL1_NAME} ${E_INTF1} ${I_INTF1} ${ACTION_DENY} ${DEST_NTW} ${SRC_NTW} ${1DEST_PORT_L} ${1DEST_PORT_U} ${1SRC_PORT_L} ${1SRC_PORT_U} - Sleep ${SYNC_SLEEP} Check ACL1 is created - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL1_NAME} ${REPLY_DATA_FOLDER}/reply_acl1_tcp.txt ${REPLY_DATA_FOLDER}/reply_acl1_tcp_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL1_NAME} ${REPLY_DATA_FOLDER}/reply_acl1_tcp.txt ${REPLY_DATA_FOLDER}/reply_acl1_tcp_term.txt Add ACL2_TCP vpp_ctl: Put ACL TCP agent_vpp_1 ${ACL2_NAME} ${E_INTF1} ${I_INTF1} ${ACTION_DENY} ${DEST_NTW} ${SRC_NTW} ${2DEST_PORT_L} ${2DEST_PORT_U} ${2SRC_PORT_L} ${2SRC_PORT_U} - Sleep ${SYNC_SLEEP} + Check ACL2 is created and ACL1 still Configured - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL2_NAME} ${REPLY_DATA_FOLDER}/reply_acl2_tcp.txt ${REPLY_DATA_FOLDER}/reply_acl2_tcp_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL2_NAME} ${REPLY_DATA_FOLDER}/reply_acl2_tcp.txt ${REPLY_DATA_FOLDER}/reply_acl2_tcp_term.txt Update ACL1 vpp_ctl: Put ACL TCP agent_vpp_1 ${ACL1_NAME} ${E_INTF1} ${I_INTF1} ${ACTION_PERMIT} ${DEST_NTW} ${SRC_NTW} ${1DEST_PORT_L} ${1DEST_PORT_U} ${1SRC_PORT_L} ${1SRC_PORT_U} - Sleep ${SYNC_SLEEP} + Check ACL1 Is Changed and ACL2 not changed - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL1_NAME} ${REPLY_DATA_FOLDER}/reply_acl1_update_tcp.txt ${REPLY_DATA_FOLDER}/reply_acl1_update_tcp_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL1_NAME} ${REPLY_DATA_FOLDER}/reply_acl1_update_tcp.txt ${REPLY_DATA_FOLDER}/reply_acl1_update_tcp_term.txt Delete ACL2 vpp_ctl: Delete ACL agent_vpp_1 ${ACL2_NAME} - Sleep ${SYNC_SLEEP} Check ACL2 Is Deleted and ACL1 Is Not Changed - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL2_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl2_delete_tcp_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL2_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl2_delete_tcp_term.txt Delete ACL1 vpp_ctl: Delete ACL agent_vpp_1 ${ACL1_NAME} - Sleep ${SYNC_SLEEP} Check ACL1 Is Deleted - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL1_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl_empty_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL1_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl_empty_term.txt ADD ACL3_UDP vpp_ctl: Put ACL UDP agent_vpp_1 ${ACL3_NAME} ${E_INTF1} ${I_INTF1} ${E_INTF2} ${I_INTF2} ${ACTION_DENY} ${DEST_NTW} ${SRC_NTW} ${1DEST_PORT_L} ${1DEST_PORT_U} ${1SRC_PORT_L} ${1SRC_PORT_U} - Sleep ${SYNC_SLEEP} Check ACL3 Is Created - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL3_NAME} ${REPLY_DATA_FOLDER}/reply_acl3_udp.txt ${REPLY_DATA_FOLDER}/reply_acl3_udp_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL3_NAME} ${REPLY_DATA_FOLDER}/reply_acl3_udp.txt ${REPLY_DATA_FOLDER}/reply_acl3_udp_term.txt ADD ACL4_UDP vpp_ctl: Put ACL UDP agent_vpp_1 ${ACL4_NAME} ${E_INTF1} ${I_INTF1} ${E_INTF2} ${I_INTF2} ${ACTION_DENY} ${DEST_NTW} ${SRC_NTW} ${1DEST_PORT_L} ${1DEST_PORT_U} ${1SRC_PORT_L} ${1SRC_PORT_U} - Sleep ${SYNC_SLEEP} + Check ACL4 Is Created And ACL3 Still Configured - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL4_NAME} ${REPLY_DATA_FOLDER}/reply_acl4_udp.txt ${REPLY_DATA_FOLDER}/reply_acl4_udp_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL4_NAME} ${REPLY_DATA_FOLDER}/reply_acl4_udp.txt ${REPLY_DATA_FOLDER}/reply_acl4_udp_term.txt Delete ACL4 vpp_ctl: Delete ACL agent_vpp_1 ${ACL4_NAME} - Sleep ${SYNC_SLEEP} Check ACL4 Is Deleted and ACL3 Is Not Changed - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL4_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl3_udp_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL4_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl3_udp_term.txt Delete ACL3 vpp_ctl: Delete ACL agent_vpp_1 ${ACL3_NAME} - Sleep ${SYNC_SLEEP} Check ACL3 Is Deleted - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL3_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl_empty_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL3_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl_empty_term.txt ADD ACL5_ICMP vpp_ctl: Put ACL UDP agent_vpp_1 ${ACL5_NAME} ${E_INTF1} ${I_INTF1} ${E_INTF2} ${I_INTF2} ${ACTION_DENY} ${DEST_NTW} ${SRC_NTW} ${1DEST_PORT_L} ${1DEST_PORT_U} ${1SRC_PORT_L} ${1SRC_PORT_U} - Sleep ${SYNC_SLEEP} Check ACL5 Is Created - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL5_NAME} ${REPLY_DATA_FOLDER}/reply_acl5_icmp.txt ${REPLY_DATA_FOLDER}/reply_acl5_icmp_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL5_NAME} ${REPLY_DATA_FOLDER}/reply_acl5_icmp.txt ${REPLY_DATA_FOLDER}/reply_acl5_icmp_term.txt ADD ACL6_ICMP vpp_ctl: Put ACL UDP agent_vpp_1 ${ACL6_NAME} ${E_INTF1} ${I_INTF1} ${E_INTF2} ${I_INTF2} ${ACTION_DENY} ${DEST_NTW} ${SRC_NTW} ${1DEST_PORT_L} ${1DEST_PORT_U} ${1SRC_PORT_L} ${1SRC_PORT_U} - Sleep ${SYNC_SLEEP} Check ACL6 Is Created And ACL5 Still Configured - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL6_NAME} ${REPLY_DATA_FOLDER}/reply_acl6_icmp.txt ${REPLY_DATA_FOLDER}/reply_acl6_icmp_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL6_NAME} ${REPLY_DATA_FOLDER}/reply_acl6_icmp.txt ${REPLY_DATA_FOLDER}/reply_acl6_icmp_term.txt Delete ACL6 vpp_ctl: Delete ACL agent_vpp_1 ${ACL6_NAME} - Sleep ${SYNC_SLEEP} Check ACL6 Is Deleted and ACL5 Is Not Changed - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL6_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl5_icmp_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL6_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl5_icmp_term.txt Delete ACL5 vpp_ctl: Delete ACL agent_vpp_1 ${ACL5_NAME} - Sleep ${SYNC_SLEEP} Check ACL5 Is Deleted - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL5_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl_empty_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL5_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl_empty_term.txt Add 6 ACL @@ -169,7 +160,7 @@ Add 6 ACL vpp_ctl: Put ACL UDP agent_vpp_1 ${ACL6_NAME} ${E_INTF1} ${I_INTF1} ${E_INTF2} ${I_INTF2} ${ACTION_DENY} ${DEST_NTW} ${SRC_NTW} ${1DEST_PORT_L} ${1DEST_PORT_U} ${1SRC_PORT_L} ${1SRC_PORT_U} Check All 6 ACLs Added - Check ACL All Reply agent_vpp_1 ${REPLY_DATA_FOLDER}/reply_acl_all.txt ${REPLY_DATA_FOLDER}/reply_acl_all_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check ACL All Reply agent_vpp_1 ${REPLY_DATA_FOLDER}/reply_acl_all.txt ${REPLY_DATA_FOLDER}/reply_acl_all_term.txt *** Keywords *** diff --git a/tests/robot/suites/crud/afpacket_crud.robot b/tests/robot/suites/crud/afpacket_crud.robot index 45074400b8..5de4cb0179 100644 --- a/tests/robot/suites/crud/afpacket_crud.robot +++ b/tests/robot/suites/crud/afpacket_crud.robot @@ -24,6 +24,8 @@ ${VETH4_MAC}= 4a:00:00:44:44:44 ${AFP1_MAC}= a2:01:01:01:01:01 ${AFP2_MAC}= a2:02:02:02:02:02 ${AFP2_SEC_MAC}= a2:22:22:22:22:22 +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment @@ -43,13 +45,13 @@ Add Afpacket1 Interface Check That Afpacket1 Interface Is Created vpp_term: Interface Is Created node=agent_vpp_1 mac=${AFP1_MAC} - vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket1 enabled=1 mac=${AFP1_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket1 enabled=1 mac=${AFP1_MAC} Check That Veth1 And Veth2 Interfaces Are Created And Not Affected By Afpacket1 Interface linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_MAC} linux: Interface Is Created node=agent_vpp_1 mac=${VETH2_MAC} - linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv4=10.10.1.1/24 mtu=1500 state=up - linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv4=10.10.1.1/24 mtu=1500 state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up Add Afpacket2 Interface Before Veth3 And Veth4 Interfaces vpp_term: Interface Not Exists node=agent_vpp_1 mac=${AFP2_MAC} @@ -72,13 +74,13 @@ Add Veth4 Interface Check That Afpacket2 Interface Is Created vpp_term: Interface Is Created node=agent_vpp_1 mac=${AFP2_MAC} - vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket2 enabled=1 mac=${AFP2_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket2 enabled=1 mac=${AFP2_MAC} Check That Veth3 And Veth4 Interfaces Are Created And Not Affected By Afpacket2 Interface linux: Interface Is Created node=agent_vpp_1 mac=${VETH3_MAC} linux: Interface Is Created node=agent_vpp_1 mac=${VETH4_MAC} - linux: Check Veth Interface State agent_vpp_1 vpp1_veth3 mac=${VETH3_MAC} ipv4=20.20.1.1/24 mtu=1500 state=lowerlayerdown - linux: Check Veth Interface State agent_vpp_1 vpp1_veth4 mac=${VETH4_MAC} state=down + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth3 mac=${VETH3_MAC} ipv4=20.20.1.1/24 mtu=1500 state=lowerlayerdown + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth4 mac=${VETH4_MAC} state=down Check That Afpacket1 Interface Is Still Configured vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket1 enabled=1 mac=${AFP1_MAC} @@ -87,14 +89,14 @@ Update Afpacket2 Interface vpp_ctl: Put Afpacket Interface node=agent_vpp_1 name=vpp1_afpacket2 mac=${AFP2_SEC_MAC} host_int=vpp1_veth4 vpp_term: Interface Is Deleted node=agent_vpp_1 mac=${AFP2_MAC} vpp_term: Interface Is Created node=agent_vpp_1 mac=${AFP2_SEC_MAC} - vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket2 enabled=1 mac=${AFP2_SEC_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket2 enabled=1 mac=${AFP2_SEC_MAC} Check That Afpacket1 Interface Is Still Configured After Update - vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket1 enabled=1 mac=${AFP1_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket1 enabled=1 mac=${AFP1_MAC} Check That Veth3 And Veth4 Interfaces Are Not Affected By Change Of Afpacket2 Interface - linux: Check Veth Interface State agent_vpp_1 vpp1_veth3 mac=${VETH3_MAC} ipv4=20.20.1.1/24 mtu=1500 state=lowerlayerdown - linux: Check Veth Interface State agent_vpp_1 vpp1_veth4 mac=${VETH4_MAC} state=down + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth3 mac=${VETH3_MAC} ipv4=20.20.1.1/24 mtu=1500 state=lowerlayerdown + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth4 mac=${VETH4_MAC} state=down Delete Afpacket1 Interface vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=vpp1_afpacket1 @@ -104,8 +106,8 @@ Check That Afpacket2 Interface Is Still Configured vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket2 enabled=1 mac=${AFP2_SEC_MAC} Check That Veth1 And Veth2 Interfaces Are Not Affected By Delete Of Afpacket1 Interface - linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv4=10.10.1.1/24 mtu=1500 state=up - linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv4=10.10.1.1/24 mtu=1500 state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up Delete Veth3 Interface vpp_ctl: Delete Linux Interface node=agent_vpp_1 name=vpp1_veth3 diff --git a/tests/robot/suites/crud/app_namespaces_crud.robot b/tests/robot/suites/crud/app_namespaces_crud.robot index 17c1b7812b..c2640dd2fd 100644 --- a/tests/robot/suites/crud/app_namespaces_crud.robot +++ b/tests/robot/suites/crud/app_namespaces_crud.robot @@ -47,7 +47,8 @@ ${PREFIX}= 24 ${MTU}= 1500 ${VARIABLES}= common ${ENV}= common -${SYNC_SLEEP}= 10s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s # wait for resync vpps after restart ${RESYNC_WAIT}= 50s @@ -76,7 +77,7 @@ Put Interface TAP1 And Namespace NS1 Associated With TAP1 And Check The Namespac Log ${out} ${out_lines1}= Get Line Count ${out} Set Suite Variable ${out_lines1} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET1} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET1} ${TAP1_SW_IF_INDEX} Put Already Existing Namespace NS1 And Check Namespace Was Not Added To Namespaces List vpp_ctl: Put Application Namespace node=agent_vpp_1 id=${NS1_ID} secret=${SECRET1} interface=${TAP1_NAME} @@ -84,41 +85,41 @@ Put Already Existing Namespace NS1 And Check Namespace Was Not Added To Namespac Log ${out} ${out_lines2}= Get Line Count ${out} Should Be Equal ${out_lines1} ${out_lines2} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET1} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET1} ${TAP1_SW_IF_INDEX} Update Namespace NS1 Secret And Check The Namespace's Update Is Reflected In Namespaces List vpp_ctl: Put Application Namespace node=agent_vpp_1 id=${NS1_ID} secret=${SECRET2} interface=${TAP1_NAME} ${out}= vpp_term: Show Application Namespaces node=agent_vpp_1 Log ${out} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} Put New NS2 Namespace And Check The Namespace Is Present In Namespaces List And Namespace NS1 Is Still Configured vpp_ctl: Put Application Namespace node=agent_vpp_1 id=${NS2_ID} secret=${SECRET3} interface=${TAP1_NAME} ${out}= vpp_term: Show Application Namespaces node=agent_vpp_1 Log ${out} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS2_ID} 2 ${SECRET3} ${TAP1_SW_IF_INDEX} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS2_ID} 2 ${SECRET3} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} Put Interface TAP2 And Namespace NS3 Associated With TAP2 And Check The Namespace Is Present In Namespaces List vpp_ctl: Put TAP Interface With IP node=agent_vpp_1 name=${TAP2_NAME} mac=${TAP2_MAC} ip=${TAP2_IP} prefix=${PREFIX} host_if_name=linux_${TAP2_NAME} vpp_ctl: Put Application Namespace node=agent_vpp_1 id=${NS3_ID} secret=${SECRET4} interface=${TAP2_NAME} ${out}= vpp_term: Show Application Namespaces node=agent_vpp_1 Log ${out} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS3_ID} 3 ${SECRET4} ${TAP2_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS3_ID} 3 ${SECRET4} ${TAP2_SW_IF_INDEX} Check NS1 And NS2 Namespaces Remained Configured - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS2_ID} 2 ${SECRET3} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS2_ID} 2 ${SECRET3} ${TAP1_SW_IF_INDEX} Update Namespace NS2 Associated Interface To TAP2 And Secret And Check The Namespace's Update Is Reflected In Namespaces List vpp_ctl: Put Application Namespace node=agent_vpp_1 id=${NS2_ID} secret=${SECRET1} interface=${TAP2_NAME} ${out}= vpp_term: Show Application Namespaces node=agent_vpp_1 Log ${out} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS2_ID} 2 ${SECRET1} ${TAP2_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS2_ID} 2 ${SECRET1} ${TAP2_SW_IF_INDEX} Check NS1 And NS3 Namespaces Are Still Configured - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS3_ID} 3 ${SECRET4} ${TAP2_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS3_ID} 3 ${SECRET4} ${TAP2_SW_IF_INDEX} Do RESYNC 1 Remove All Nodes @@ -135,9 +136,9 @@ Get Interfaces Sw If Index After Resync 1 Set Suite Variable ${TAP2_SW_IF_INDEX} Check NS1, NS2 And NS3 Were Automatically Configured After Resync - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS2_ID} 2 ${SECRET1} ${TAP2_SW_IF_INDEX} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS3_ID} 3 ${SECRET4} ${TAP2_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS2_ID} 2 ${SECRET1} ${TAP2_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS3_ID} 3 ${SECRET4} ${TAP2_SW_IF_INDEX} Disable L4 Features And Check They Are Disabled vpp_ctl: Set L4 Features On Node node=agent_vpp_1 enabled=false @@ -150,7 +151,7 @@ Put Namespace NS4 While L4 Features Are Disabled Enable L4 Features And Check Namespaces NS1, NS2, NS3 And NS4 Are Present In Namespaces List vpp_ctl: Set L4 Features On Node node=agent_vpp_1 enabled=true ${out}= vpp_term: Show Application Namespaces node=agent_vpp_1 - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS2_ID} 2 ${SECRET1} ${TAP2_SW_IF_INDEX} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS3_ID} 3 ${SECRET4} ${TAP2_SW_IF_INDEX} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS4_ID} 4 ${SECRET4} ${TAP1_SW_IF_INDEX} @@ -162,8 +163,7 @@ Put Namespace NS5 Associated With MEMIF1 Interface That Is Not Created And Check Put MEMIF1 Interface And Check Namespace NS5 Is Present In Namespaces List vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=memif1 mac=${MEMIF1_MAC} master=true id=1 ip=192.168.1.2 prefix=28 socket=default.sock - Sleep 1 - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS5_ID} 5 ${SECRET1} ${MEMIF1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS5_ID} 5 ${SECRET1} ${MEMIF1_SW_IF_INDEX} Put Namespace NS6 Associated With LOOP1 Interface That Is Not Created And Check NS6 Is Not Present In Namespaces List vpp_ctl: Put Application Namespace node=agent_vpp_1 id=${NS6_ID} secret=${SECRET1} interface=${LOOP1_NAME} @@ -173,7 +173,7 @@ Put Namespace NS6 Associated With LOOP1 Interface That Is Not Created And Check Put LOOP1 Interface And Check Namespace NS6 Is Present In Namespaces List vpp_ctl: Put Loopback Interface With IP node=agent_vpp_1 name=${LOOP1_NAME} mac=${LOOP1_MAC} ip=${LOOP1_IP} prefix=${PREFIX} mtu=${MTU} enabled=true Sleep 1 - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS6_ID} 6 ${SECRET1} ${LOOP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS6_ID} 6 ${SECRET1} ${LOOP1_SW_IF_INDEX} Put Namespace NS7 Associated With VXLAN1 Interface That Is Not Created And Check NS7 Is Not Present In Namespaces List vpp_ctl: Put Application Namespace node=agent_vpp_1 id=${NS7_ID} secret=${SECRET1} interface=${VXLAN1_NAME} @@ -183,7 +183,7 @@ Put Namespace NS7 Associated With VXLAN1 Interface That Is Not Created And Check Put VXLAN1 Interface And Check Namespace NS7 Is Present In Namespaces List vpp_ctl: Put VXLan Interface node=agent_vpp_1 name=${VXLAN1_NAME} src=${VXLAN1_SRC} dst=${VXLAN1_DST} vni=${VXLAN1_VNI} Sleep 1 - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS7_ID} 7 ${SECRET1} ${VXLAN1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS7_ID} 7 ${SECRET1} ${VXLAN1_SW_IF_INDEX} Do RESYNC 2 Remove All Nodes @@ -209,12 +209,12 @@ Get Interfaces Sw If Index After Resync 2 Set Suite Variable ${VXLAN1_SW_IF_INDEX} Check Namespaces NS1, NS2, NS3, NS4, NS5, NS6 AND NS7 Are Present In Namespaces List - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS2_ID} 2 ${SECRET1} ${TAP2_SW_IF_INDEX} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS3_ID} 3 ${SECRET4} ${TAP2_SW_IF_INDEX} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS4_ID} 4 ${SECRET4} ${TAP1_SW_IF_INDEX} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS5_ID} 5 ${SECRET1} ${MEMIF1_SW_IF_INDEX} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS6_ID} 6 ${SECRET1} ${LOOP1_SW_IF_INDEX} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS7_ID} 7 ${SECRET1} ${VXLAN1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS2_ID} 2 ${SECRET1} ${TAP2_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS3_ID} 3 ${SECRET4} ${TAP2_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS4_ID} 4 ${SECRET4} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS5_ID} 5 ${SECRET1} ${MEMIF1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS6_ID} 6 ${SECRET1} ${LOOP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS7_ID} 7 ${SECRET1} ${VXLAN1_SW_IF_INDEX} *** Keywords *** diff --git a/tests/robot/suites/crud/arp_crud.robot b/tests/robot/suites/crud/arp_crud.robot index 7e45014a59..d1d27dcc08 100644 --- a/tests/robot/suites/crud/arp_crud.robot +++ b/tests/robot/suites/crud/arp_crud.robot @@ -17,7 +17,8 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${SYNC_SLEEP}= 6s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s ${VETH1_MAC}= 1a:00:00:11:11:11 ${VETH2_MAC}= 2a:00:00:22:22:22 ${AFP1_MAC}= a2:01:01:01:01:01 @@ -43,8 +44,8 @@ Add Veth2 Interface Check That Veth1 And Veth2 Interfaces Are Created linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_MAC} linux: Interface Is Created node=agent_vpp_1 mac=${VETH2_MAC} - linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv4=10.10.1.1/24 mtu=1500 state=up - linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv4=10.10.1.1/24 mtu=1500 state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up vpp_term: Show Interface Mode agent_vpp_1 vpp1_veth1@vpp1_veth2 vpp_term: Show Interface Mode agent_vpp_1 vpp1_veth2@vpp1_veth1 @@ -54,7 +55,7 @@ Add Memif Interface Check Memif Interface Created vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=1 ipv4=192.168.1.1/24 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=1 ipv4=192.168.1.1/24 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock Add VXLan Interface @@ -62,21 +63,21 @@ Add VXLan Interface Check VXLan Interface Created vxlan: Tunnel Is Created node=agent_vpp_1 src=192.168.1.1 dst=192.168.1.2 vni=5 - vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan1 enabled=1 src=192.168.1.1 dst=192.168.1.2 vni=5 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan1 enabled=1 src=192.168.1.1 dst=192.168.1.2 vni=5 Add Loopback Interface vpp_ctl: Put Loopback Interface With IP node=agent_vpp_1 name=vpp1_loop1 mac=12:21:21:11:11:11 ip=20.20.1.1 prefix=24 mtu=1400 Check Loopback Interface Created vpp_term: Interface Is Created node=agent_vpp_1 mac=12:21:21:11:11:11 - vat_term: Check Loopback Interface State agent_vpp_1 vpp1_loop1 enabled=1 mac=12:21:21:11:11:11 mtu=1400 ipv4=20.20.1.1/24 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 vpp1_loop1 enabled=1 mac=12:21:21:11:11:11 mtu=1400 ipv4=20.20.1.1/24 Add Tap Interface vpp_ctl: Put TAP Interface With IP node=agent_vpp_1 name=vpp1_tap1 mac=32:21:21:11:11:11 ip=30.30.1.1 prefix=24 host_if_name=linux_vpp1_tap1 Check TAP Interface Created vpp_term: Interface Is Created node=agent_vpp_1 mac=32:21:21:11:11:11 - vpp_term: Check TAP interface State agent_vpp_1 vpp1_tap1 mac=32:21:21:11:11:11 ipv4=30.30.1.1/24 state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check TAP interface State agent_vpp_1 vpp1_tap1 mac=32:21:21:11:11:11 ipv4=30.30.1.1/24 state=up Check Stuff Show Interfaces And Other Objects @@ -97,8 +98,8 @@ Add ARPs Sleep ${SYNC_SLEEP} Check Memif ARP - vpp_term: Check ARP agent_vpp_1 vpp1_memif1 155.155.155.155 32:51:51:51:51:51 True - vpp_term: Check ARP agent_vpp_1 vpp1_memif1 155.155.155.156 32:51:51:51:51:52 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_memif1 155.155.155.155 32:51:51:51:51:51 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_memif1 155.155.155.156 32:51:51:51:51:52 True #Check Veth1 ARP # vpp_term: Check ARP agent_vpp_1 vpp1_veth1 155.155.155.155 32:51:51:51:51:51 True @@ -109,38 +110,37 @@ Check Memif ARP # vpp_term: Check ARP agent_vpp_1 vpp1_veth2 155.155.155.150 32:51:51:51:51:5 True Check VXLan ARP - vpp_term: Check ARP agent_vpp_1 vpp1_vxlan1 155.155.155.155 32:51:51:51:51:51 True - vpp_term: Check ARP agent_vpp_1 vpp1_vxlan1 155.155.155.154 32:51:51:51:51:53 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_vxlan1 155.155.155.155 32:51:51:51:51:51 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_vxlan1 155.155.155.154 32:51:51:51:51:53 True Check Loopback ARP - vpp_term: Check ARP agent_vpp_1 vpp1_loop1 155.155.155.155 32:51:51:51:51:51 True - vpp_term: Check ARP agent_vpp_1 vpp1_loop1 155.155.155.152 32:51:51:51:51:55 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_loop1 155.155.155.155 32:51:51:51:51:51 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_loop1 155.155.155.152 32:51:51:51:51:55 True Check TAP ARP - vpp_term: Check ARP agent_vpp_1 vpp1_tap1 155.155.155.155 32:51:51:51:51:51 True - vpp_term: Check ARP agent_vpp_1 vpp1_tap1 155.155.155.150 32:51:51:51:51:5 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_tap1 155.155.155.155 32:51:51:51:51:51 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_tap1 155.155.155.150 32:51:51:51:51:5 True ADD Afpacket Interface vpp_ctl: Put Afpacket Interface node=agent_vpp_1 name=vpp1_afpacket1 mac=a2:a1:a1:a1:a1:a1 host_int=vpp1_veth2 Check AFpacket Interface Created vpp_term: Interface Is Created node=agent_vpp_1 mac=a2:a1:a1:a1:a1:a1 - vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket1 enabled=1 mac=a2:a1:a1:a1:a1:a1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket1 enabled=1 mac=a2:a1:a1:a1:a1:a1 Check Veth1 Veth2 Are Created After Afpacket is created linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_MAC} linux: Interface Is Created node=agent_vpp_1 mac=${VETH2_MAC} - linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv4=10.10.1.1/24 mtu=1500 state=up - linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv4=10.10.1.1/24 mtu=1500 state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up Add ARP for Afpacket vpp_ctl: Put ARP agent_vpp_1 host-vpp1_veth2 155.155.155.155 32:51:51:51:51:51 False vpp_ctl: Put ARP agent_vpp_1 host-vpp1_veth2 155.155.155.150 32:51:51:51:51:5 False - Sleep ${SYNC_SLEEP} Check Afpacket ARP - vpp_term: Check ARP agent_vpp_1 host-vpp1_veth2 155.155.155.155 32:51:51:51:51:51 True - vpp_term: Check ARP agent_vpp_1 host-vpp1_veth2 155.155.155.150 32:51:51:51:51:5 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 host-vpp1_veth2 155.155.155.155 32:51:51:51:51:51 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 host-vpp1_veth2 155.155.155.150 32:51:51:51:51:5 True Delete ARPs vpp_ctl: Delete ARP agent_vpp_1 vpp1_memif1 155.155.155.156 @@ -155,8 +155,8 @@ Delete ARPs Sleep ${SYNC_SLEEP} Check Memif ARP After Delete - vpp_term: Check ARP agent_vpp_1 vpp1_memif1 155.155.155.155 32:51:51:51:51:51 True - vpp_term: Check ARP agent_vpp_1 vpp1_memif1 155.155.155.156 32:51:51:51:51:52 False + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_memif1 155.155.155.155 32:51:51:51:51:51 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_memif1 155.155.155.156 32:51:51:51:51:52 False #Check Veth1 ARP After Delete # vpp_term: Check ARP agent_vpp_1 vpp1_veth1 155.155.155.155 32:51:51:51:51:51 True @@ -167,20 +167,20 @@ Check Memif ARP After Delete # vpp_term: Check ARP agent_vpp_1 vpp1_veth2 155.155.155.15 32:51:51:51:51:5 False Check VXLan ARP After Delete - vpp_term: Check ARP agent_vpp_1 vpp1_vxlan1 155.155.155.155 32:51:51:51:51:51 True - vpp_term: Check ARP agent_vpp_1 vpp1_vxlan1 155.155.155.154 32:51:51:51:51:53 False + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_vxlan1 155.155.155.155 32:51:51:51:51:51 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_vxlan1 155.155.155.154 32:51:51:51:51:53 False Check Loopback ARP After Delete - vpp_term: Check ARP agent_vpp_1 vpp1_loop1 155.155.155.155 32:51:51:51:51:51 True - vpp_term: Check ARP agent_vpp_1 vpp1_loop1 155.155.155.152 32:51:51:51:51:55 False + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_loop1 155.155.155.155 32:51:51:51:51:51 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_loop1 155.155.155.152 32:51:51:51:51:55 False Check TAP ARP After Delete - vpp_term: Check ARP agent_vpp_1 vpp1_tap1 155.155.155.155 32:51:51:51:51:51 True - vpp_term: Check ARP agent_vpp_1 vpp1_tap1 155.155.155.150 32:51:51:51:51:5 False + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_tap1 155.155.155.155 32:51:51:51:51:51 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_tap1 155.155.155.150 32:51:51:51:51:5 False Check Afpacket ARP After Delete - vpp_term: Check ARP agent_vpp_1 host-vpp1_veth2 155.155.155.155 32:51:51:51:51:51 True - vpp_term: Check ARP agent_vpp_1 host-vpp1_veth2 155.155.155.150 32:51:51:51:51:5 False + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 host-vpp1_veth2 155.155.155.155 32:51:51:51:51:51 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 host-vpp1_veth2 155.155.155.150 32:51:51:51:51:5 False Modify ARPs vpp_ctl: Put ARP agent_vpp_1 vpp1_memif1 155.155.155.155 32:51:51:51:51:58 false @@ -190,17 +190,17 @@ Modify ARPs # vpp_ctl: Put ARP agent_vpp_1 vpp1_veth2 155.155.155.155 32:51:51:51:51:58 false # vpp_term:Show ARP agent_vpp_1 vpp_ctl: Put ARP agent_vpp_1 vpp1_vxlan1 155.155.155.155 32:51:51:51:51:58 false - vpp_term:Show ARP agent_vpp_1 + vpp_term:Show ARP agent_vpp_1 vpp_term:Show ARP agent_vpp_1 + Sleep ${SYNC_SLEEP} vpp_ctl: Put ARP agent_vpp_1 vpp1_loop1 155.155.155.155 32:51:51:51:51:58 false vpp_term:Show ARP agent_vpp_1 vpp_ctl: Put ARP agent_vpp_1 vpp1_tap1 155.155.155.155 32:51:51:51:51:58 false vpp_term:Show ARP agent_vpp_1 vpp_ctl: Put ARP agent_vpp_1 host-vpp1_veth2 155.155.155.155 32:51:51:51:51:58 False - vpp_term:Show ARP agent_vpp_1 - Sleep ${SYNC_SLEEP} + Check Memif ARP After Modify - vpp_term: Check ARP agent_vpp_1 vpp1_memif1 155.155.155.155 32:51:51:51:51:58 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_memif1 155.155.155.155 32:51:51:51:51:58 True #Check Veth1 ARP After Modify # vpp_term: Check ARP agent_vpp_1 vpp1_veth1 155.155.155.155 32:51:51:51:51:5 True @@ -209,16 +209,16 @@ Check Memif ARP After Modify # vpp_term: Check ARP agent_vpp_1 vpp1_veth2 155.155.155.155 32:51:51:51:51:5 True Check VXLan ARP After Modify - vpp_term: Check ARP agent_vpp_1 vpp1_vxlan1 155.155.155.155 32:51:51:51:51:58 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_vxlan1 155.155.155.155 32:51:51:51:51:58 True Check Loopback ARP After Modify - vpp_term: Check ARP agent_vpp_1 vpp1_loop1 155.155.155.155 32:51:51:51:51:58 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_loop1 155.155.155.155 32:51:51:51:51:58 True Check TAP ARP After Modify - vpp_term: Check ARP agent_vpp_1 vpp1_tap1 155.155.155.155 32:51:51:51:51:58 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_tap1 155.155.155.155 32:51:51:51:51:58 True Check Afpacket ARP After Modify - vpp_term: Check ARP agent_vpp_1 host-vpp1_veth2 155.155.155.155 32:51:51:51:51:58 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 host-vpp1_veth2 155.155.155.155 32:51:51:51:51:58 True *** Keywords *** diff --git a/tests/robot/suites/crud/bd_crud.robot b/tests/robot/suites/crud/bd_crud.robot index e93ea3f59c..0937984b2e 100644 --- a/tests/robot/suites/crud/bd_crud.robot +++ b/tests/robot/suites/crud/bd_crud.robot @@ -17,7 +17,8 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common - +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment [Tags] setup @@ -42,23 +43,23 @@ Add Interfaces For BDs Add BD1 Bridge Domain @{ints}= Create List vpp1_memif1 vpp1_vxlan1 vpp1_afpacket1 vat_term: BD Not Exists agent_vpp_1 @{ints} - vpp_ctl: Put Bridge Domain node=agent_vpp_1 name=vpp1_bd1 ints=${ints} flood=true unicast=true forward=true learn=true arp_term=true + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Put Bridge Domain node=agent_vpp_1 name=vpp1_bd1 ints=${ints} flood=true unicast=true forward=true learn=true arp_term=true Check BD1 Is Created vat_term: BD Is Created agent_vpp_1 vpp1_memif1 vpp1_afpacket1 vpp1_vxlan1 - vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd1 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=vpp1_memif1 interface=vpp1_afpacket1 interface=vpp1_vxlan1 bvi_int=none + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd1 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=vpp1_memif1 interface=vpp1_afpacket1 interface=vpp1_vxlan1 bvi_int=none Add BD2 Bridge Domain @{ints}= Create List vpp1_memif2 vpp1_vxlan2 bvi_vpp1_loop3 vat_term: BD Not Exists agent_vpp_1 @{ints} - vpp_ctl: Put Bridge Domain node=agent_vpp_1 name=vpp1_bd2 ints=${ints} flood=true unicast=true forward=true learn=true arp_term=true + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Put Bridge Domain node=agent_vpp_1 name=vpp1_bd2 ints=${ints} flood=true unicast=true forward=true learn=true arp_term=true Check BD2 Is Created vat_term: BD Is Created agent_vpp_1 vpp1_memif2 vpp1_vxlan2 bvi_vpp1_loop3 - vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd2 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=vpp1_memif2 interface=vpp1_vxlan2 interface=bvi_vpp1_loop3 bvi_int=bvi_vpp1_loop3 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd2 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=vpp1_memif2 interface=vpp1_vxlan2 interface=bvi_vpp1_loop3 bvi_int=bvi_vpp1_loop3 Check That BD1 Is Not Affected By Adding BD2 - vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd1 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=vpp1_memif1 interface=vpp1_afpacket1 interface=vpp1_vxlan1 bvi_int=none + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd1 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=vpp1_memif1 interface=vpp1_afpacket1 interface=vpp1_vxlan1 bvi_int=none Update BD1 @{ints}= Create List vpp1_memif1 vpp1_vxlan1 bvi_vpp1_loop2 @@ -66,10 +67,10 @@ Update BD1 vpp_ctl: Put Bridge Domain node=agent_vpp_1 name=vpp1_bd1 ints=${ints} flood=false unicast=false forward=false learn=false arp_term=false vat_term: BD Is Deleted agent_vpp_1 vpp1_memif1 vpp1_afpacket1 vpp1_vxlan1 vat_term: BD Is Created agent_vpp_1 vpp1_memif1 vpp1_vxlan1 bvi_vpp1_loop2 - vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd1 flood=0 unicast=0 forward=0 learn=0 arp_term=0 interface=vpp1_memif1 interface=vpp1_vxlan1 interface=bvi_vpp1_loop2 bvi_int=bvi_vpp1_loop2 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd1 flood=0 unicast=0 forward=0 learn=0 arp_term=0 interface=vpp1_memif1 interface=vpp1_vxlan1 interface=bvi_vpp1_loop2 bvi_int=bvi_vpp1_loop2 Check That BD2 Is Not Affected By Updating BD1 - vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd2 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=vpp1_memif2 interface=vpp1_vxlan2 interface=bvi_vpp1_loop3 bvi_int=bvi_vpp1_loop3 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd2 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=vpp1_memif2 interface=vpp1_vxlan2 interface=bvi_vpp1_loop3 bvi_int=bvi_vpp1_loop3 Delete VXLan1 Interface vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=vpp1_vxlan1 @@ -77,21 +78,21 @@ Delete VXLan1 Interface Check That VXLan1 Interface Is Deleted From BD1 vat_term: BD Is Deleted agent_vpp_1 vpp1_memif1 vpp1_vxlan1 bvi_vpp1_loop2 - vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd1 flood=0 unicast=0 forward=0 learn=0 arp_term=0 interface=vpp1_memif1 interface=bvi_vpp1_loop2 bvi_int=bvi_vpp1_loop2 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd1 flood=0 unicast=0 forward=0 learn=0 arp_term=0 interface=vpp1_memif1 interface=bvi_vpp1_loop2 bvi_int=bvi_vpp1_loop2 Readd VXLan1 Interface vpp_ctl: Put VXLan Interface node=agent_vpp_1 name=vpp1_vxlan1 src=192.168.1.1 dst=192.168.1.2 vni=5 vxlan: Tunnel Is Created node=agent_vpp_1 src=192.168.1.1 dst=192.168.1.2 vni=5 Check That VXLan1 Interface Is Added To BD1 - vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd1 flood=0 unicast=0 forward=0 learn=0 arp_term=0 interface=vpp1_memif1 interface=vpp1_vxlan1 interface=bvi_vpp1_loop2 bvi_int=bvi_vpp1_loop2 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd1 flood=0 unicast=0 forward=0 learn=0 arp_term=0 interface=vpp1_memif1 interface=vpp1_vxlan1 interface=bvi_vpp1_loop2 bvi_int=bvi_vpp1_loop2 Delete BD1 Bridge Domain vpp_ctl: Delete Bridge Domain agent_vpp_1 vpp1_bd1 vat_term: BD Is Deleted agent_vpp_1 vpp1_memif1 vpp1_vxlan1 bvi_vpp1_loop2 Check That BD2 Is Not Affected By Deleting BD1 - vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd2 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=vpp1_memif2 interface=vpp1_vxlan2 interface=bvi_vpp1_loop3 bvi_int=bvi_vpp1_loop3 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd2 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=vpp1_memif2 interface=vpp1_vxlan2 interface=bvi_vpp1_loop3 bvi_int=bvi_vpp1_loop3 Show Interfaces And Other Objects After Test vpp_term: Show Interfaces agent_vpp_1 diff --git a/tests/robot/suites/crud/inter_vrf_routing_crud.robot b/tests/robot/suites/crud/inter_vrf_routing_crud.robot new file mode 100644 index 0000000000..d83a6e0c98 --- /dev/null +++ b/tests/robot/suites/crud/inter_vrf_routing_crud.robot @@ -0,0 +1,171 @@ +*** Settings *** + +Library OperatingSystem +Library String +#Library RequestsLibrary + +Resource ../../variables/${VARIABLES}_variables.robot +Resource ../../libraries/all_libs.robot +Resource ../../libraries/pretty_keywords.robot + +Force Tags trafficIPv4 +Suite Setup Run Keywords Discard old results Test Setup +Suite Teardown Test Teardown + +*** Variables *** +${VARIABLES}= common +${ENV}= common +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s +${FINAL_SLEEP}= 1s +${IP_1}= 10.1.1.1 +${IP_2}= 10.1.1.2 +${IP_3}= 10.1.2.1 +${IP_4}= 10.1.2.2 +${IP_5}= 10.1.3.1 +${IP_6}= 10.1.3.2 +${NET1}= 10.1.1.0 +${NET2}= 10.1.2.0 +${NET3}= 10.1.3.0 + +*** Test Cases *** +# Non default VRF table 2 used in Agent VPP Node agent_vpp_2 +Start Two Agents And Then Configure With Default And Non Default VRF + Add Agent VPP Node agent_vpp_1 + Add Agent VPP Node agent_vpp_2 + + Create Master memif0 on agent_vpp_1 with IP ${IP_1}, MAC 02:f1:be:90:00:00, key 1 and m0.sock socket + Create Slave memif0 on agent_vpp_2 with IP ${IP_2}, MAC 02:f1:be:90:00:02, key 1 and m0.sock socket + + Create Master memif1 on agent_vpp_1 with VRF 2, IP ${IP_3}, MAC 02:f1:be:90:02:00, key 1 and m1.sock socket + Create Slave memif1 on agent_vpp_2 with VRF 2, IP ${IP_4}, MAC 02:f1:be:90:02:02, key 1 and m1.sock socket + + Create Master memif2 on agent_vpp_1 with VRF 1, IP ${IP_5}, MAC 02:f1:be:90:04:00, key 1 and m2.sock socket + Create Slave memif2 on agent_vpp_2 with VRF 1, IP ${IP_6}, MAC 02:f1:be:90:04:02, key 1 and m2.sock socket + + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} List of interfaces On agent_vpp_1 Should Contain Interface memif1/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} List of interfaces On agent_vpp_2 Should Contain Interface memif1/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} List of interfaces On agent_vpp_1 Should Contain Interface memif2/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} List of interfaces On agent_vpp_2 Should Contain Interface memif2/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} List of interfaces On agent_vpp_1 Should Contain Interface memif3/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} List of interfaces On agent_vpp_2 Should Contain Interface memif3/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} IP Fib Table 0 On agent_vpp_1 Should Contain Route With IP ${IP_1}/32 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} IP Fib Table 2 On agent_vpp_1 Should Contain Route With IP ${IP_3}/32 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} IP Fib Table 0 On agent_vpp_2 Should Contain Route With IP ${IP_2}/32 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} IP Fib Table 2 On agent_vpp_2 Should Contain Route With IP ${IP_4}/32 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} IP Fib Table 1 On agent_vpp_1 Should Contain Route With IP ${IP_5}/32 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} IP Fib Table 1 On agent_vpp_2 Should Contain Route With IP ${IP_6}/32 + +Create Route For Inter Vrf Routing + Create Route On agent_vpp_1 With IP ${NET2}/24 With Next Hop ${IP_2} And Vrf Id 0 + Create Route On agent_vpp_1 With IP ${NET1}/24 With Next Hop ${IP_4} And Vrf Id 2 + Create Route On agent_vpp_2 With IP ${NET2}/24 With Next Hop VRF 2 From Vrf Id 0 And Type 1 + Create Route On agent_vpp_2 With IP ${NET1}/24 With Next Hop VRF 0 From Vrf Id 2 And Type 1 + +Config Done + No Operation + +Check Inter VRF Routing + Show IP Fib On agent_vpp_1 + IP Fib Table 0 On agent_vpp_1 Should Contain Route With IP ${NET2}/24 + IP Fib Table 0 On agent_vpp_1 Should Contain Vrf ipv4 via ${IP_2} memif1/1 + Show IP Fib On agent_vpp_2 + IP Fib Table 2 On agent_vpp_2 Should Contain Route With IP ${NET1}/24 + IP Fib Table 2 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv4-VRF: + IP Fib Table 0 On agent_vpp_2 Should Contain Route With IP ${NET2}/24 + IP Fib Table 0 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv4-VRF: + +Create Next Route For Inter Vrf Routing + Create Route On agent_vpp_2 With IP ${NET3}/24 With Next Hop VRF 1 From Vrf Id 0 And Type 1 + Create Route On agent_vpp_2 With IP ${NET3}/24 With Next Hop VRF 1 From Vrf Id 2 And Type 1 + Create Route On agent_vpp_2 With IP ${NET1}/24 With Next Hop VRF 0 From Vrf Id 1 And Type 1 + Create Route On agent_vpp_2 With IP ${NET2}/24 With Next Hop VRF 2 From Vrf Id 1 And Type 1 + +Check Inter VRF Routing Again + Show IP Fib On agent_vpp_1 + IP Fib Table 0 On agent_vpp_1 Should Contain Route With IP ${NET2}/24 + IP Fib Table 0 On agent_vpp_1 Should Contain Vrf ipv4 via ${IP_2} memif1/1 + Show IP Fib On agent_vpp_2 + IP Fib Table 2 On agent_vpp_2 Should Contain Route With IP ${NET1}/24 + IP Fib Table 2 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv4-VRF: + IP Fib Table 0 On agent_vpp_2 Should Contain Route With IP ${NET2}/24 + IP Fib Table 0 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv4-VRF: + + IP Fib Table 2 On agent_vpp_2 Should Contain Route With IP ${NET3}/24 + IP Fib Table 2 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv4-VRF: + IP Fib Table 0 On agent_vpp_2 Should Contain Route With IP ${NET3}/24 + IP Fib Table 0 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv4-VRF: + + IP Fib Table 1 On agent_vpp_2 Should Contain Route With IP ${NET1}/24 + IP Fib Table 1 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv4-VRF: + IP Fib Table 1 On agent_vpp_2 Should Contain Route With IP ${NET2}/24 + IP Fib Table 1 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv4-VRF: + +Delete Route VRF 1 + vpp_ctl: Delete Route agent_vpp_2 1 ${NET1} 24 + vpp_ctl: Delete Route agent_vpp_2 1 ${NET2} 24 + vpp_ctl: Delete Route agent_vpp_2 0 ${NET3} 24 + vpp_ctl: Delete Route agent_vpp_2 2 ${NET3} 24 + +Check State After Delete + Show IP Fib On agent_vpp_1 + IP Fib Table 0 On agent_vpp_1 Should Contain Route With IP ${NET2}/24 + IP Fib Table 0 On agent_vpp_1 Should Contain Vrf ipv4 via ${IP_2} memif1/1 + Show IP Fib On agent_vpp_2 + IP Fib Table 2 On agent_vpp_2 Should Contain Route With IP ${NET1}/24 + IP Fib Table 2 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv4-VRF: + IP Fib Table 0 On agent_vpp_2 Should Contain Route With IP ${NET2}/24 + IP Fib Table 0 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv4-VRF: + + ${status1}= Run Keyword And Return Status IP Fib Table 2 On agent_vpp_2 Should Contain Route With IP ${NET3}/24 + Should Not Be True ${status1} + + ${status2}= Run Keyword And Return Status IP Fib Table 0 On agent_vpp_2 Should Contain Route With IP ${NET3}/24 + Should Not Be True ${status2} + + ${status3}= Run Keyword And Return Status IP Fib Table 1 On agent_vpp_2 Should Contain Route With IP ${NET1}/24 + Should Not Be True ${status3} + + ${status4}= Run Keyword And Return Status IP Fib Table 1 On agent_vpp_2 Should Contain Route With IP ${NET2}/24 + Should Not Be True ${status4} + + ${status5}= Run Keyword And Return Status IP Fib Table 1 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv4-VRF: + Should Not Be True ${status5} + +Update Inter Vrf Route + Create Route On agent_vpp_2 With IP ${NET1}/24 With Next Hop VRF 0 From Vrf Id 1 And Type 1 + Create Route On agent_vpp_2 With IP ${NET1}/24 With Next Hop VRF 2 From Vrf Id 1 And Type 1 + +Check Route After Update + Show IP Fib On agent_vpp_2 + IP Fib Table 1 On agent_vpp_2 Should Contain Route With IP ${NET1}/24 + IP Fib Table 1 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv4-VRF:2 + +#can use in debug +#Check Route With Ping +# Ping On agent_vpp_1 With IP ${IP_4}, Source memif1/1 +# Ping On agent_vpp_1 With IP ${IP_4}, Source memif2/1 +# Ping On agent_vpp_1 With IP ${IP_3}, Source memif1/1 +# + +Final Sleep For Manual Checking + Sleep ${FINAL_SLEEP} + +*** Keywords *** +List of interfaces On ${node} Should Contain Interface ${int} + Log many ${node} ${int} + ${out}= vpp_term: Show Interfaces ${node} + log many ${out} + Should Match Regexp ${out} ${int} + +IP Fib Table ${table_id} On ${node} Should Contain Vrf ${inter_vrf_string} + Log many ${table_id} ${node} ${inter_vrf_string} + ${out}= vpp_term: Show IP Fib Table ${node} ${table_id} + log many ${out} + Should Contain ${out} ${inter_vrf_string} + +IP6 Fib Table ${table_id} On ${node} Should Contain Vrf ${inter_vrf_string} + Log many ${table_id} ${node} ${inter_vrf_string} + ${out}= vpp_term: Show IP6 Fib Table ${node} ${table_id} + log many ${out} + Should Contain ${out} ${inter_vrf_string} diff --git a/tests/robot/suites/crud/ip_route_crud.robot b/tests/robot/suites/crud/ip_route_crud.robot index 141353ecf2..3007887251 100644 --- a/tests/robot/suites/crud/ip_route_crud.robot +++ b/tests/robot/suites/crud/ip_route_crud.robot @@ -14,6 +14,8 @@ Suite Setup Run Keywords Discard old results *** Variables *** ${VARIABLES}= common ${ENV}= common +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** # CRUD tests for routing diff --git a/tests/robot/suites/crud/ipsec_crud.robot b/tests/robot/suites/crud/ipsec_crud.robot index e92d4498d2..a592ac4f92 100644 --- a/tests/robot/suites/crud/ipsec_crud.robot +++ b/tests/robot/suites/crud/ipsec_crud.robot @@ -12,7 +12,8 @@ Suite Teardown Testsuite Teardown *** Variables *** ${ENV}= common - +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** # CRUD tests for IPsec Add Agent Vpp Node diff --git a/tests/robot/suites/crud/l2xconnect_crud.robot b/tests/robot/suites/crud/l2xconnect_crud.robot index dff5bacde9..b205904138 100644 --- a/tests/robot/suites/crud/l2xconnect_crud.robot +++ b/tests/robot/suites/crud/l2xconnect_crud.robot @@ -23,7 +23,8 @@ ${RESYNC_SLEEP}= 20s ${VETH1_MAC}= 1a:00:00:11:11:11 ${VETH2_MAC}= 2a:00:00:22:22:22 ${AFP1_MAC}= a2:01:01:01:01:01 - +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment @@ -43,7 +44,6 @@ Add Veth1 Interface Add Veth2 Interface linux: Interface Not Exists node=agent_vpp_1 mac=${VETH2_MAC} vpp_ctl: Put Veth Interface node=agent_vpp_1 name=vpp1_veth2 mac=${VETH2_MAC} peer=vpp1_veth1 - Sleep ${SYNC_SLEEP} Add Memif Interface vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=true id=1 ip=192.168.1.1 prefix=24 socket=default.sock @@ -59,24 +59,20 @@ Add Loopback2 Interface Add Tap Interface vpp_ctl: Put TAP Interface With IP node=agent_vpp_1 name=vpp1_tap1 mac=32:21:21:11:11:11 ip=30.30.1.1 prefix=24 host_if_name=linux_vpp1_tap1 - Sleep ${SYNC_SLEEP} - Sleep ${SYNC_SLEEP} - Sleep ${SYNC_SLEEP} - Sleep ${SYNC_SLEEP} Check That Veth1 And Veth2 Interfaces Are Created linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_MAC} linux: Interface Is Created node=agent_vpp_1 mac=${VETH2_MAC} - linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv4=10.10.1.1/24 mtu=1500 state=up - linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv4=10.10.1.1/24 mtu=1500 state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up Check TAP Interface Created vpp_term: Interface Is Created node=agent_vpp_1 mac=32:21:21:11:11:11 - vpp_term: Check TAP interface State agent_vpp_1 vpp1_tap1 mac=32:21:21:11:11:11 ipv4=30.30.1.1/24 state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check TAP interface State agent_vpp_1 vpp1_tap1 mac=32:21:21:11:11:11 ipv4=30.30.1.1/24 state=up Check Memif Interface Created vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=1 ipv4=192.168.1.1/24 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=1 ipv4=192.168.1.1/24 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock Check VXLan Interface Created vxlan: Tunnel Is Created node=agent_vpp_1 src=192.168.1.1 dst=192.168.1.2 vni=5 @@ -88,7 +84,7 @@ Check Loopback1 Interface Created Check Loopback2 Interface Created vpp_term: Interface Is Created node=agent_vpp_1 mac=22:21:21:11:11:11 - vat_term: Check Loopback Interface State agent_vpp_1 vpp1_loop2 enabled=1 mac=22:21:21:11:11:11 mtu=1400 ipv4=22.20.1.1/24 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 vpp1_loop2 enabled=1 mac=22:21:21:11:11:11 mtu=1400 ipv4=22.20.1.1/24 Check Stuff Show Interfaces And Other Objects @@ -96,65 +92,59 @@ Check Stuff Add L2XConnect1 for Memif and Loopback1 vpp_ctl: Put L2XConnect agent_vpp_1 vpp1_memif1 vpp1_loop1 vpp_ctl: Put L2XConnect agent_vpp_1 vpp1_loop1 vpp1_memif1 - Sleep ${SYNC_SLEEP} Check L2XConnect1 Memif and Loopback1 in XConnect mode ${out}= vpp_term: Show Interface Mode agent_vpp_1 - Should Contain ${out} l2 xconnect memif1/1 loop0 - Should Contain ${out} l2 xconnect loop0 memif1/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect memif1/1 loop0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect loop0 memif1/1 Add L2XConnect2 for Tap and Loopback2 vpp_ctl: Put L2XConnect agent_vpp_1 vpp1_tap1 vpp1_loop2 vpp_ctl: Put L2XConnect agent_vpp_1 vpp1_loop2 vpp1_tap1 - Sleep ${SYNC_SLEEP} Check L2XConnect2 and L2XConnect1 still configured ${out}= vpp_term: Show Interface Mode agent_vpp_1 - Should Contain ${out} l2 xconnect memif1/1 loop0 - Should Contain ${out} l2 xconnect loop0 memif1/1 - Should Contain ${out} l2 xconnect tapcli-0 loop1 - Should Contain ${out} l2 xconnect loop1 tapcli-0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect memif1/1 loop0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect loop0 memif1/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect tapcli-0 loop1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect loop1 tapcli-0 Modify L2XConnect1 vpp_ctl: Delete L2XConnect agent_vpp_1 vpp1_memif1 vpp_ctl: Put L2XConnect agent_vpp_1 vpp1_vxlan1 vpp1_loop1 vpp_ctl: Put L2XConnect agent_vpp_1 vpp1_loop1 vpp1_vxlan1 - Sleep ${SYNC_SLEEP} Check L2XConnect1 Modified and L2XConnect2 still configured ${out}= vpp_term: Show Interface Mode agent_vpp_1 - Should Contain ${out} l2 xconnect vxlan_tunnel0 loop0 - Should Contain ${out} l2 xconnect loop0 vxlan_tunnel0 - Should Contain ${out} l2 xconnect tapcli-0 loop1 - Should Contain ${out} l2 xconnect loop1 tapcli-0 - Should Contain ${out} l3 memif1/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect vxlan_tunnel0 loop0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect loop0 vxlan_tunnel0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect tapcli-0 loop1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect loop1 tapcli-0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l3 memif1/1 Delete L2XConnect1 vpp_ctl: Delete L2XConnect agent_vpp_1 vpp1_vxlan1 vpp_ctl: Delete L2XConnect agent_vpp_1 vpp1_loop1 - Sleep ${SYNC_SLEEP} Check L2XConnect1 Deleted and L2XConnect2 still configured ${out}= vpp_term: Show Interface Mode agent_vpp_1 - Should Contain ${out} l3 memif1/1 - Should Contain ${out} l3 loop0 - Should Contain ${out} l3 vxlan_tunnel0 - Should Contain ${out} l2 xconnect tapcli-0 loop1 - Should Contain ${out} l2 xconnect loop1 tapcli-0 - + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l3 memif1/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l3 loop0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l3 vxlan_tunnel0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect tapcli-0 loop1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect loop1 tapcli-0 Delete L2XConnect2 vpp_ctl: Delete L2XConnect agent_vpp_1 vpp1_tap1 vpp_ctl: Delete L2XConnect agent_vpp_1 vpp1_loop2 - Sleep ${SYNC_SLEEP} Check L2XConnect1 and L2XConnect2 Deleted ${out}= vpp_term: Show Interface Mode agent_vpp_1 - Should Contain ${out} l3 memif1/1 - Should Contain ${out} l3 loop0 - Should Contain ${out} l3 vxlan_tunnel0 - Should Contain ${out} l3 tapcli-0 - Should Contain ${out} l3 loop1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l3 memif1/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l3 loop0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l3 vxlan_tunnel0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l3 tapcli-0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l3 loop1 *** Keywords *** Show Interfaces And Other Objects diff --git a/tests/robot/suites/crud/linux_arp_crud.robot b/tests/robot/suites/crud/linux_arp_crud.robot index 3eb00cb06a..a1cd9efa15 100644 --- a/tests/robot/suites/crud/linux_arp_crud.robot +++ b/tests/robot/suites/crud/linux_arp_crud.robot @@ -23,6 +23,8 @@ ${VETH2_MAC}= 2a:00:00:22:22:22 ${AFP1_MAC}= a2:01:01:01:01:01 ${NAMESPACE}= ${NSTYPE}= 3 +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment @@ -45,8 +47,8 @@ Add Veth2 Interface Check That Veth1 And Veth2 Interfaces Are Created linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_MAC} linux: Interface Is Created node=agent_vpp_1 mac=${VETH2_MAC} - linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv4=10.10.1.1/24 mtu=1500 state=up - linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv4=10.10.1.1/24 mtu=1500 state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up ADD Afpacket Interface @@ -54,38 +56,36 @@ ADD Afpacket Interface Check AFpacket Interface Created vpp_term: Interface Is Created node=agent_vpp_1 mac=a2:a1:a1:a1:a1:a1 - vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket1 enabled=1 mac=a2:a1:a1:a1:a1:a1 - Sleep ${SYNC_SLEEP} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket1 enabled=1 mac=a2:a1:a1:a1:a1:a1 + Add ARPs vpp_ctl: Put Linux ARP agent_vpp_1 vpp1_veth1 veth1_arp 155.155.155.155 32:51:51:51:51:51 vpp_ctl: Put Linux ARP agent_vpp_1 vpp1_veth2 veth2_arp 155.155.155.156 32:51:51:51:51:52 vpp_ctl: Put Linux ARP agent_vpp_1 lo loopback_arp 155.155.155.156 32:51:51:51:51:52 #vpp_ctl: Put Linux ARP agent_vpp_1 eth0 eth_arp 155.155.155.156 32:51:51:51:51:52 - Sleep ${SYNC_SLEEP} Check ARPSs ${out}= Execute In Container agent_vpp_1 ip neigh Log ${out} - Should Contain ${out} 155.155.155.156 dev vpp1_veth2 lladdr 32:51:51:51:51:52 PERMANENT - Should Contain ${out} 155.155.155.155 dev vpp1_veth1 lladdr 32:51:51:51:51:51 PERMANENT - #Should Contain ${out} 155.155.155.156 dev eth0 lladdr 32:51:51:51:51:52 PERMANENT - Should Contain ${out} 155.155.155.156 dev lo lladdr 32:51:51:51:51:52 PERMANENT + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} 155.155.155.156 dev vpp1_veth2 lladdr 32:51:51:51:51:52 PERMANENT + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} 155.155.155.155 dev vpp1_veth1 lladdr 32:51:51:51:51:51 PERMANENT + #Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} 155.155.155.156 dev eth0 lladdr 32:51:51:51:51:52 PERMANENT + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} 155.155.155.156 dev lo lladdr 32:51:51:51:51:52 PERMANENT Change ARPs vpp_ctl: Put Linux ARP agent_vpp_1 vpp1_veth1 veth1_arp 155.255.155.155 32:61:51:51:51:51 vpp_ctl: Put Linux ARP agent_vpp_1 vpp1_veth2 veth2_arp 155.255.155.156 32:61:51:51:51:52 vpp_ctl: Put Linux ARP agent_vpp_1 lo loopback_arp 155.255.155.156 32:61:51:51:51:52 #vpp_ctl: Put Linux ARP agent_vpp_1 eth0 eth_arp 155.255.155.156 32:61:51:51:51:52 - Sleep ${SYNC_SLEEP} Check ARPSs Again ${out}= Execute In Container agent_vpp_1 ip neigh Log ${out} - Should Contain ${out} 155.255.155.156 dev vpp1_veth2 lladdr 32:61:51:51:51:52 PERMANENT - Should Contain ${out} 155.255.155.155 dev vpp1_veth1 lladdr 32:61:51:51:51:51 PERMANENT - #Should Contain ${out} 155.255.155.156 dev eth0 lladdr 32:61:51:51:51:52 PERMANENT - Should Contain ${out} 155.255.155.156 dev lo lladdr 32:61:51:51:51:52 PERMANENT + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} 155.255.155.156 dev vpp1_veth2 lladdr 32:61:51:51:51:52 PERMANENT + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} 155.255.155.155 dev vpp1_veth1 lladdr 32:61:51:51:51:51 PERMANENT + #Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} 155.255.155.156 dev eth0 lladdr 32:61:51:51:51:52 PERMANENT + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} 155.255.155.156 dev lo lladdr 32:61:51:51:51:52 PERMANENT Delete ARPs vpp_ctl: Delete Linux ARP agent_vpp_1 veth1_arp @@ -96,10 +96,10 @@ Delete ARPs Check ARPSs After Delete ${out}= Execute In Container agent_vpp_1 ip neigh Log ${out} - Should Not Contain ${out} 155.255.155.156 dev vpp1_veth2 lladdr 32:61:51:51:51:52 PERMANENT - Should Not Contain ${out} 155.255.155.155 dev vpp1_veth1 lladdr 32:61:51:51:51:51 PERMANENT - #Should Not Contain ${out} 155.255.155.156 dev eth0 lladdr 32:61:51:51:51:52 PERMANENT - Should Not Contain ${out} 155.255.155.156 dev lo lladdr 32:61:51:51:51:52 PERMANENT + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Not Contain ${out} 155.255.155.156 dev vpp1_veth2 lladdr 32:61:51:51:51:52 PERMANENT + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Not Contain ${out} 155.255.155.155 dev vpp1_veth1 lladdr 32:61:51:51:51:51 PERMANENT + #Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Not Contain ${out} 155.255.155.156 dev eth0 lladdr 32:61:51:51:51:52 PERMANENT + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Not Contain ${out} 155.255.155.156 dev lo lladdr 32:61:51:51:51:52 PERMANENT *** Keywords *** diff --git a/tests/robot/suites/crud/linux_ip_route_crud.robot b/tests/robot/suites/crud/linux_ip_route_crud.robot index 9f637961e5..6ea413cec0 100644 --- a/tests/robot/suites/crud/linux_ip_route_crud.robot +++ b/tests/robot/suites/crud/linux_ip_route_crud.robot @@ -17,7 +17,8 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${CONFIG_SLEEP}= 1s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s ${RESYNC_SLEEP}= 1s # wait for resync vpps after restart ${RESYNC_WAIT}= 30s @@ -35,10 +36,8 @@ Setup Interfaces vpp_ctl: Put Veth Interface Via Linux Plugin node=agent_vpp_1 namespace=ns1 name=ns1_veth1 host_if_name=ns1_veth1_linux mac=d2:74:8c:12:67:d2 peer=ns2_veth2 ip=192.168.22.1 vpp_ctl: Put Veth Interface Via Linux Plugin node=agent_vpp_1 namespace=ns2 name=ns2_veth2 host_if_name=ns2_veth2_linux mac=92:c7:42:67:ab:cd peer=ns1_veth1 ip=192.168.22.2 - Sleep ${CONFIG_SLEEP} - - Check Linux Interfaces node=agent_vpp_1 namespace=ns1 interface=ns1_veth1 - Check Linux Interfaces node=agent_vpp_1 namespace=ns2 interface=ns2_veth2 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Interfaces node=agent_vpp_1 namespace=ns1 interface=ns1_veth1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Interfaces node=agent_vpp_1 namespace=ns2 interface=ns2_veth2 # This should work by default after veth interface setup Ping in namespace node=agent_vpp_1 namespace=ns1 ip=192.168.22.2 @@ -50,18 +49,16 @@ Create Linux Routes vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=ns1 interface=ns1_veth1 routename=pinginggoogl ip=8.8.8.8 prefix=32 next_hop=192.168.22.1 vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=ns2 interface=ns2_veth2 routename=pinging9 ip=9.9.9.9 prefix=32 next_hop=192.168.22.2 - Sleep ${CONFIG_SLEEP} - - Check Linux Routes node=agent_vpp_1 namespace=ns1 ip=192.168.22.2 - Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=192.168.22.1 - Check Linux Routes node=agent_vpp_1 namespace=ns1 ip=8.8.8.8 - Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=9.9.9.9 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns1 ip=192.168.22.2 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=192.168.22.1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns1 ip=8.8.8.8 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=9.9.9.9 # created routes should not exist in other namespace - Check Removed Linux Route node=agent_vpp_1 namespace=ns2 ip=192.168.22.2 - Check Removed Linux Route node=agent_vpp_1 namespace=ns1 ip=192.168.22.1 - Check Removed Linux Route node=agent_vpp_1 namespace=ns2 ip=8.8.8.8 - Check Removed Linux Route node=agent_vpp_1 namespace=ns1 ip=9.9.9.9 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Removed Linux Route node=agent_vpp_1 namespace=ns2 ip=192.168.22.2 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Removed Linux Route node=agent_vpp_1 namespace=ns1 ip=192.168.22.1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Removed Linux Route node=agent_vpp_1 namespace=ns2 ip=8.8.8.8 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Removed Linux Route node=agent_vpp_1 namespace=ns1 ip=9.9.9.9 Read Route Information From Setup Database vpp_ctl: Get Linux Route As Json node=agent_vpp_1 routename=pingingveth2 @@ -72,57 +69,52 @@ Read Route Information From Setup Database Change Linux Routes Without Deleting Key (Changing Metric) # changing of gateway - this is incorrect/ the record would not be put in the database - Let us change metric vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=ns1 interface=ns1_veth1 routename=pinginggoogl ip=8.8.8.8 prefix=32 next_hop=192.168.22.1 metric=55 - Sleep ${CONFIG_SLEEP} # testing if there is the new metric - Check Linux Routes Metric node=agent_vpp_1 namespace=ns1 ip=8.8.8.8 metric=55 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes Metric node=agent_vpp_1 namespace=ns1 ip=8.8.8.8 metric=55 Change Linux Routes At First Deleting Key And Putting The Same Secondly Deleting Key Then Putting It To Other Namespace vpp_ctl: Delete Linux Route node=agent_vpp_1 routename=pinging9 - Sleep ${CONFIG_SLEEP} - Check Removed Linux Route node=agent_vpp_1 namespace=ns2 ip=9.9.9.9 + + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Removed Linux Route node=agent_vpp_1 namespace=ns2 ip=9.9.9.9 # we create exactly the same as deleted route vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=ns2 interface=ns2_veth2 routename=pinging9 ip=9.9.9.9 prefix=32 next_hop=192.168.22.2 - Sleep ${CONFIG_SLEEP} - Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=9.9.9.9 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=9.9.9.9 # delete again vpp_ctl: Delete Linux Route node=agent_vpp_1 routename=pinging9 - Sleep ${CONFIG_SLEEP} - Check Removed Linux Route node=agent_vpp_1 namespace=ns2 ip=9.9.9.9 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Removed Linux Route node=agent_vpp_1 namespace=ns2 ip=9.9.9.9 # we try to transfer route to other namespace - there is also need to change appropriately gateway vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=ns1 interface=ns1_veth1 routename=pinging9 ip=9.9.9.9 prefix=32 next_hop=192.168.22.1 - Sleep ${CONFIG_SLEEP} - Check Removed Linux Route node=agent_vpp_1 namespace=ns2 ip=9.9.9.9 - Check Linux Routes Gateway node=agent_vpp_1 namespace=ns1 ip=9.9.9.9 next_hop=192.168.22.1 + + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Removed Linux Route node=agent_vpp_1 namespace=ns2 ip=9.9.9.9 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes Gateway node=agent_vpp_1 namespace=ns1 ip=9.9.9.9 next_hop=192.168.22.1 At first create route and after that create inteface in namespace 3 vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=ns3 interface=ns3_veth3 routename=pingingns2_veth3 ip=192.169.22.22 prefix=32 next_hop=192.169.22.3 vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=ns3 interface=ns3_veth3 routename=pingingns2_veth2 ip=192.168.22.2 prefix=32 next_hop=192.169.22.3 vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=ns3 interface=ns3_veth3 routename=pingingns1_veth1 ip=192.168.22.1 prefix=32 next_hop=192.169.22.3 vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=ns2 interface=ns2_veth3 routename=pingingns3_veth3 ip=192.169.22.3 prefix=32 next_hop=192.169.22.22 - Sleep ${CONFIG_SLEEP} vpp_ctl: Put Veth Interface Via Linux Plugin node=agent_vpp_1 namespace=ns3 name=ns3_veth3 host_if_name=ns3_veth3_linux mac=92:c7:42:67:ab:ce peer=ns2_veth3 ip=192.169.22.3 vpp_ctl: Put Veth Interface Via Linux Plugin node=agent_vpp_1 namespace=ns2 name=ns2_veth3 host_if_name=ns2_veth3_linux mac=92:c7:42:67:ab:cf peer=ns3_veth3 ip=192.169.22.22 - Sleep ${CONFIG_SLEEP} - Check Linux Interfaces node=agent_vpp_1 namespace=ns3 interface=ns3_veth3 - Check Linux Interfaces node=agent_vpp_1 namespace=ns2 interface=ns2_veth3 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Interfaces node=agent_vpp_1 namespace=ns3 interface=ns3_veth3 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Interfaces node=agent_vpp_1 namespace=ns2 interface=ns2_veth3 Ping in namespace node=agent_vpp_1 namespace=ns2 ip=192.169.22.3 Ping in namespace node=agent_vpp_1 namespace=ns3 ip=192.169.22.22 - Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=192.168.22.1 - Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=192.168.22.2 - Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=192.169.22.22 - Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=192.169.22.3 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=192.168.22.1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=192.168.22.2 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=192.169.22.22 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=192.169.22.3 # tested also above, but repeat after giving exact routes Ping in namespace node=agent_vpp_1 namespace=ns3 ip=192.169.22.22 @@ -139,14 +131,14 @@ At first create route and after that create inteface in namespace 3 # Ping in namespace node=agent_vpp_1 namespace=ns1 ip=192.169.22.3 Check linux Routes On VPP1 - Check Linux Routes node=agent_vpp_1 namespace=ns1 ip=192.168.22.2 - Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=192.168.22.1 - Check Linux Routes Gateway node=agent_vpp_1 namespace=ns1 ip=8.8.8.8 next_hop=192.168.22.1 - Check Linux Routes Gateway node=agent_vpp_1 namespace=ns1 ip=9.9.9.9 next_hop=192.168.22.1 - Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=192.168.22.1 - Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=192.168.22.2 - Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=192.169.22.22 - Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=192.169.22.3 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns1 ip=192.168.22.2 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=192.168.22.1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes Gateway node=agent_vpp_1 namespace=ns1 ip=8.8.8.8 next_hop=192.168.22.1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes Gateway node=agent_vpp_1 namespace=ns1 ip=9.9.9.9 next_hop=192.168.22.1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=192.168.22.1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=192.168.22.2 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=192.169.22.22 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=192.169.22.3 Remove VPP Nodes Remove All Nodes diff --git a/tests/robot/suites/crud/loopback_crud.robot b/tests/robot/suites/crud/loopback_crud.robot index b693781a88..b6a7c45d60 100644 --- a/tests/robot/suites/crud/loopback_crud.robot +++ b/tests/robot/suites/crud/loopback_crud.robot @@ -27,7 +27,8 @@ ${IP_LOOP1_2}= 21.20.1.2 ${IP_LOOP2}= 20.20.2.2 ${PREFIX}= 24 ${MTU}= 4800 -${SYNC_SLEEP}= 12s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment @@ -40,40 +41,38 @@ Show Interfaces Before Setup Add Loopback1 Interface vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_LOOP1} vpp_ctl: Put Loopback Interface With IP node=agent_vpp_1 name=${NAME_LOOP1} mac=${MAC_LOOP1} ip=${IP_LOOP1} prefix=${PREFIX} mtu=${MTU} enabled=true - Sleep ${SYNC_SLEEP} Check Loopback1 Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_LOOP1} - vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP1} enabled=1 mac=${MAC_LOOP1} mtu=${MTU} ipv4=${IP_LOOP1}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_LOOP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP1} enabled=1 mac=${MAC_LOOP1} mtu=${MTU} ipv4=${IP_LOOP1}/${PREFIX} Add Loopback2 Interface vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_LOOP2} vpp_ctl: Put Loopback Interface With IP node=agent_vpp_1 name=${NAME_LOOP2} mac=${MAC_LOOP2} ip=${IP_LOOP2} prefix=${PREFIX} mtu=${MTU} enabled=true - Sleep ${SYNC_SLEEP} Check Loopback2 Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_LOOP2} - vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP2} enabled=1 mac=${MAC_LOOP2} mtu=${MTU} ipv4=${IP_LOOP2}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_LOOP2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP2} enabled=1 mac=${MAC_LOOP2} mtu=${MTU} ipv4=${IP_LOOP2}/${PREFIX} Check Loopback1 Is Still Configured vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP1} enabled=1 mac=${MAC_LOOP1} mtu=${MTU} ipv4=${IP_LOOP1}/${PREFIX} Update Loopback1 vpp_ctl: Put Loopback Interface With IP node=agent_vpp_1 name=${NAME_LOOP1} mac=${MAC_LOOP1_2} ip=${IP_LOOP1_2} prefix=${PREFIX} mtu=${MTU} enabled=true - Sleep ${SYNC_SLEEP} - vpp_term: Interface Is Deleted node=agent_vpp_1 mac=${MAC_LOOP1} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_LOOP1_2} - vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP1} enabled=1 mac=${MAC_LOOP1_2} mtu=${MTU} ipv4=${IP_LOOP1_2}/${PREFIX} + + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_1 mac=${MAC_LOOP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_LOOP1_2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP1} enabled=1 mac=${MAC_LOOP1_2} mtu=${MTU} ipv4=${IP_LOOP1_2}/${PREFIX} Check Loopback2 Is Not Changed - vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP2} enabled=1 mac=${MAC_LOOP2} mtu=${MTU} ipv4=${IP_LOOP2}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP2} enabled=1 mac=${MAC_LOOP2} mtu=${MTU} ipv4=${IP_LOOP2}/${PREFIX} Delete Loopback1_2 Interface vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=${NAME_LOOP1} - vpp_term: Interface Is Deleted node=agent_vpp_1 mac=${MAC_LOOP1_2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_1 mac=${MAC_LOOP1_2} Check Loopback2 Interface Is Still Configured - vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP2} enabled=1 mac=${MAC_LOOP2} mtu=${MTU} ipv4=${IP_LOOP2}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP2} enabled=1 mac=${MAC_LOOP2} mtu=${MTU} ipv4=${IP_LOOP2}/${PREFIX} Show Interfaces And Other Objects After Setup vpp_term: Show Interfaces agent_vpp_1 diff --git a/tests/robot/suites/crud/memif_crud.robot b/tests/robot/suites/crud/memif_crud.robot index 72e81dea74..b0c3ed33ba 100644 --- a/tests/robot/suites/crud/memif_crud.robot +++ b/tests/robot/suites/crud/memif_crud.robot @@ -23,7 +23,8 @@ ${MEMIF21_MAC}= 2a:00:00:22:22:22 ${MEMIF21_SEC_MAC}= 2a:00:00:22:22:23 ${MEMIF12_MAC}= 3a:00:00:33:33:33 ${MEMIF22_MAC}= 4a:00:00:44:44:44 -${SYNC_SLEEP}= 6s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment @@ -36,93 +37,89 @@ Show Interfaces Before Setup Add VPP1_memif1 Interface vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MEMIF11_MAC} vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=${MEMIF11_MAC} master=true id=1 ip=192.168.1.1 prefix=24 socket=default.sock - Sleep ${SYNC_SLEEP} + Check That VPP1_memif1 Is Created But Not Connected - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MEMIF11_MAC} - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_MAC} role=master id=1 ipv4=192.168.1.1/24 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MEMIF11_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_MAC} role=master id=1 ipv4=192.168.1.1/24 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock Add VPP2_memif1 Interface vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MEMIF21_MAC} vpp_ctl: Put Memif Interface With IP node=agent_vpp_2 name=vpp2_memif1 mac=${MEMIF21_MAC} master=false id=1 ip=192.168.1.2 prefix=28 socket=default.sock - Sleep ${SYNC_SLEEP} Check That VPP2_memif1 Is Created And Connected With VPP1_memif1 - vpp_term: Interface Is Created node=agent_vpp_2 mac=${MEMIF21_MAC} - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_MAC} role=slave id=1 ipv4=192.168.1.2/28 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_MAC} role=master id=1 ipv4=192.168.1.1/24 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_2 mac=${MEMIF21_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_MAC} role=slave id=1 ipv4=192.168.1.2/28 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_MAC} role=master id=1 ipv4=192.168.1.1/24 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock Add VPP1_memif2 Interface vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MEMIF12_MAC} vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif2 mac=${MEMIF12_MAC} master=true id=2 ip=192.168.2.1 prefix=26 socket=default.sock - Sleep ${SYNC_SLEEP} Check That VPP1_memif2 Is Created But Not Connected - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MEMIF12_MAC} - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=${MEMIF12_MAC} role=master id=2 ipv4=192.168.2.1/26 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MEMIF12_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=${MEMIF12_MAC} role=master id=2 ipv4=192.168.2.1/26 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock Add VPP2_memif2 Interface vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MEMIF22_MAC} vpp_ctl: Put Memif Interface With IP node=agent_vpp_2 name=vpp2_memif2 mac=${MEMIF22_MAC} master=false id=2 ip=192.168.2.2 prefix=28 socket=default.sock - Sleep ${SYNC_SLEEP} Check That VPP2_memif2 Is Created And Connected With VPP1_memif2 - vpp_term: Interface Is Created node=agent_vpp_2 mac=${MEMIF22_MAC} - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif2 mac=${MEMIF22_MAC} role=slave id=2 ipv4=192.168.2.2/28 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=${MEMIF12_MAC} role=master id=2 ipv4=192.168.2.1/26 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_2 mac=${MEMIF22_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif2 mac=${MEMIF22_MAC} role=slave id=2 ipv4=192.168.2.2/28 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=${MEMIF12_MAC} role=master id=2 ipv4=192.168.2.1/26 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock Check That VPP1_memif1 And VPP2_memif1 Interfaces Are Not Affected By VPP1_memif2 And VPP2_memif2 Interfaces - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_MAC} role=master id=1 ipv4=192.168.1.1/24 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_MAC} role=slave id=1 ipv4=192.168.1.2/28 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_MAC} role=master id=1 ipv4=192.168.1.1/24 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_MAC} role=slave id=1 ipv4=192.168.1.2/28 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock Update VPP1_memif1 Interface vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=${MEMIF11_SEC_MAC} master=true id=1 ip=192.168.10.1 prefix=30 socket=default.sock - Sleep ${SYNC_SLEEP} - vpp_term: Interface Is Deleted node=agent_vpp_1 mac=${MEMIF11_MAC} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MEMIF11_SEC_MAC} - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_SEC_MAC} role=master id=1 ipv4=192.168.10.1/30 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_1 mac=${MEMIF11_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MEMIF11_SEC_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_SEC_MAC} role=master id=1 ipv4=192.168.10.1/30 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock Check That VPP2_memif1 Is Still Configured And Connected - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_MAC} role=slave id=1 ipv4=192.168.1.2/28 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_MAC} role=slave id=1 ipv4=192.168.1.2/28 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock Check That VPP1_memif2 And VPP2_memif2 Are Not Affected By VPP1_memif1 Update - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif2 mac=${MEMIF22_MAC} role=slave id=2 ipv4=192.168.2.2/28 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=${MEMIF12_MAC} role=master id=2 ipv4=192.168.2.1/26 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif2 mac=${MEMIF22_MAC} role=slave id=2 ipv4=192.168.2.2/28 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=${MEMIF12_MAC} role=master id=2 ipv4=192.168.2.1/26 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock Update VPP2_memif1 Interface vpp_ctl: Put Memif Interface With IP node=agent_vpp_2 name=vpp2_memif1 mac=${MEMIF21_SEC_MAC} master=false id=1 ip=192.168.10.2 prefix=24 socket=default.sock - Sleep ${SYNC_SLEEP} - vpp_term: Interface Is Deleted node=agent_vpp_2 mac=${MEMIF21_MAC} - vpp_term: Interface Is Created node=agent_vpp_2 mac=${MEMIF21_SEC_MAC} - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_SEC_MAC} role=slave id=1 ipv4=192.168.10.2/24 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock + + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_2 mac=${MEMIF21_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_2 mac=${MEMIF21_SEC_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_SEC_MAC} role=slave id=1 ipv4=192.168.10.2/24 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock Check That VPP1_memif1 Is Still Configured And Connected vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_SEC_MAC} role=master id=1 ipv4=192.168.10.1/30 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock Check That VPP1_memif2 And VPP2_memif2 Are Not Affected By VPP2_memif1 Update - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif2 mac=${MEMIF22_MAC} role=slave id=2 ipv4=192.168.2.2/28 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=${MEMIF12_MAC} role=master id=2 ipv4=192.168.2.1/26 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif2 mac=${MEMIF22_MAC} role=slave id=2 ipv4=192.168.2.2/28 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=${MEMIF12_MAC} role=master id=2 ipv4=192.168.2.1/26 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock Delete VPP1_memif2 Interface vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=vpp1_memif2 vpp_term: Interface Is Deleted node=agent_vpp_1 mac=${MEMIF12_MAC} - Sleep ${SYNC_SLEEP} Check That VPP2_memif2 Interface Is Disconnected - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif2 mac=${MEMIF22_MAC} role=slave id=2 ipv4=192.168.2.2/28 connected=0 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif2 mac=${MEMIF22_MAC} role=slave id=2 ipv4=192.168.2.2/28 connected=0 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock Check That VPP1_memif1 And VPP2_memif1 Are Not Affected By VPP1_memif2 Delete - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_SEC_MAC} role=master id=1 ipv4=192.168.10.1/30 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_SEC_MAC} role=slave id=1 ipv4=192.168.10.2/24 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_SEC_MAC} role=master id=1 ipv4=192.168.10.1/30 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_SEC_MAC} role=slave id=1 ipv4=192.168.10.2/24 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock Delete VPP2_memif2 Interface vpp_ctl: Delete VPP Interface node=agent_vpp_2 name=vpp2_memif2 - vpp_term: Interface Is Deleted node=agent_vpp_2 mac=${MEMIF22_MAC} - Sleep ${SYNC_SLEEP} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_2 mac=${MEMIF22_MAC} + Check That VPP1_memif1 And VPP2_memif1 Are Not Affected By VPP2_memif2 Delete - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_SEC_MAC} role=master id=1 ipv4=192.168.10.1/30 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_SEC_MAC} role=slave id=1 ipv4=192.168.10.2/24 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_SEC_MAC} role=master id=1 ipv4=192.168.10.1/30 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_SEC_MAC} role=slave id=1 ipv4=192.168.10.2/24 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock Show Interfaces And Other Objects After Setup vpp_term: Show Interfaces agent_vpp_1 diff --git a/tests/robot/suites/crud/physical_crud.robot b/tests/robot/suites/crud/physical_crud.robot index 57d7922340..43efd04211 100644 --- a/tests/robot/suites/crud/physical_crud.robot +++ b/tests/robot/suites/crud/physical_crud.robot @@ -17,6 +17,8 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment @@ -41,15 +43,15 @@ Add Physical1 Interface vpp_ctl: Put Physical Interface With IP node=agent_vpp_1 name=${DOCKER_PHYSICAL_INT_1_VPP_NAME} ip=10.11.1.2 prefix=28 mtu=1500 Check That Physical1 Interface Is Configured - vpp_term: Interface Is Enabled node=agent_vpp_1 interface=${DOCKER_PHYSICAL_INT_1_VPP_NAME} - vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_1_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_1_MAC} ipv4=10.11.1.2/28 mtu=1500 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Enabled node=agent_vpp_1 interface=${DOCKER_PHYSICAL_INT_1_VPP_NAME} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_1_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_1_MAC} ipv4=10.11.1.2/28 mtu=1500 Add Physical2 Interface vpp_ctl: Put Physical Interface With IP node=agent_vpp_1 name=${DOCKER_PHYSICAL_INT_2_VPP_NAME} ip=20.21.2.3 prefix=24 mtu=2500 Check That Physical2 Interface Is Configured - vpp_term: Interface Is Enabled node=agent_vpp_1 interface=${DOCKER_PHYSICAL_INT_2_VPP_NAME} - vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_2_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_2_MAC} ipv4=20.21.2.3/24 mtu=2500 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Enabled node=agent_vpp_1 interface=${DOCKER_PHYSICAL_INT_2_VPP_NAME} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_2_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_2_MAC} ipv4=20.21.2.3/24 mtu=2500 Check That Physical1 Interface Is Still Configured vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_1_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_1_MAC} ipv4=10.11.1.2/28 mtu=1500 @@ -59,7 +61,7 @@ Update Physical1 Interface vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_1_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_1_MAC} ipv4=30.31.3.3/26 mtu=1600 Check That Physical2 Interface Is Still Configured - vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_2_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_2_MAC} ipv4=20.21.2.3/24 mtu=2500 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_2_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_2_MAC} ipv4=20.21.2.3/24 mtu=2500 Delete Physical2 Interface vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=${DOCKER_PHYSICAL_INT_2_VPP_NAME} @@ -70,7 +72,7 @@ Check That Physical2 Interface Is Unconfigured Lists Should Be Equal ${ipv4_list} ${EMPTY} Check That Physical1 Interface Is Not Affected By Delete Physical2 - vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_1_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_1_MAC} ipv4=30.31.3.3/26 mtu=1600 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_1_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_1_MAC} ipv4=30.31.3.3/26 mtu=1600 Delete Physical1 interface vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=${DOCKER_PHYSICAL_INT_1_VPP_NAME} diff --git a/tests/robot/suites/crud/srv6_crud.robot b/tests/robot/suites/crud/srv6_crud.robot index 1b63b21121..263e7dca2a 100644 --- a/tests/robot/suites/crud/srv6_crud.robot +++ b/tests/robot/suites/crud/srv6_crud.robot @@ -17,9 +17,8 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${CONFIG_SLEEP}= 1s -${RESYNC_SLEEP}= 1s -${SYNC_SLEEP}= 10s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s # wait for resync vpps after restart ${RESYNC_WAIT}= 30s @{segmentList1} B:: C:: D:: @@ -40,36 +39,36 @@ Configure Environment Check Local SID CRUD vpp_ctl: Put Local SID node=agent_vpp_1 localsidName=A sidAddress=A:: fibtable=0 outinterface=vpp1_afpacket1 nexthop=A::1 - vpp_term: Check Local SID Presence node=agent_vpp_1 sidAddress=A:: interface=host-vpp1_veth2 nexthop=A::1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Local SID Presence node=agent_vpp_1 sidAddress=A:: interface=host-vpp1_veth2 nexthop=A::1 vpp_ctl: Put Local SID node=agent_vpp_1 localsidName=A sidAddress=A:: fibtable=0 outinterface=vpp1_afpacket1 nexthop=C::1 #modification - vpp_term: Check Local SID Presence node=agent_vpp_1 sidAddress=A:: interface=host-vpp1_veth2 nexthop=C::1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Local SID Presence node=agent_vpp_1 sidAddress=A:: interface=host-vpp1_veth2 nexthop=C::1 vpp_ctl: Delete Local SID node=agent_vpp_1 localsidName=A - vpp_term: Check Local SID Deleted node=agent_vpp_1 sidAddress=A:: + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Local SID Deleted node=agent_vpp_1 sidAddress=A:: Check Policy and Policy Segment CRUD vpp_ctl: Put SRv6 Policy node=agent_vpp_1 name=AtoE bsid=A::E fibtable=0 srhEncapsulation=true sprayBehaviour=true - Sleep 5s # checking that vpp doesn't change (if previous command affects VPP it takes time to arrive in VPP ) - vpp_term: Check SRv6 Policy Nonexistence node=agent_vpp_1 bsid=A::E + + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check SRv6 Policy Nonexistence node=agent_vpp_1 bsid=A::E vpp_ctl: Put SRv6 Policy Segment node=agent_vpp_1 name=firstSegment policyName=AtoE policyBSID=A::E weight=1 segmentlist=${segmentList1} - vpp_term: Check SRv6 Policy Presence node=agent_vpp_1 bsid=A::E fibtable=0 behaviour=Encapsulation type=Spray index=0 segmentlists=${segmentLists1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check SRv6 Policy Presence node=agent_vpp_1 bsid=A::E fibtable=0 behaviour=Encapsulation type=Spray index=0 segmentlists=${segmentLists1} vpp_ctl: Delete SRv6 Policy Segment node=agent_vpp_1 name=firstSegment policyName=AtoE - vpp_term: Check SRv6 Policy Presence node=agent_vpp_1 bsid=A::E fibtable=0 behaviour=Encapsulation type=Spray index=0 segmentlists=${segmentLists1} # special handling of empty policy (VPP doesn't allow this) + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check SRv6 Policy Presence node=agent_vpp_1 bsid=A::E fibtable=0 behaviour=Encapsulation type=Spray index=0 segmentlists=${segmentLists1} # special handling of empty policy (VPP doesn't allow this) vpp_ctl: Put SRv6 Policy Segment node=agent_vpp_1 name=secondSegment policyName=AtoE policyBSID=A::E weight=2 segmentlist=${segmentList2} - vpp_term: Check SRv6 Policy Presence node=agent_vpp_1 bsid=A::E fibtable=0 behaviour=Encapsulation type=Spray index=0 segmentlists=${segmentLists2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check SRv6 Policy Presence node=agent_vpp_1 bsid=A::E fibtable=0 behaviour=Encapsulation type=Spray index=0 segmentlists=${segmentLists2} vpp_ctl: Delete SRv6 Policy Segment node=agent_vpp_1 name=secondSegment policyName=AtoE - vpp_term: Check SRv6 Policy Presence node=agent_vpp_1 bsid=A::E fibtable=0 behaviour=Encapsulation type=Spray index=0 segmentlists=${segmentLists2} # special handling of empty policy (VPP doesn't allow this) + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check SRv6 Policy Presence node=agent_vpp_1 bsid=A::E fibtable=0 behaviour=Encapsulation type=Spray index=0 segmentlists=${segmentLists2} # special handling of empty policy (VPP doesn't allow this) vpp_ctl: Delete SRv6 Policy node=agent_vpp_1 name=AtoE - vpp_term: Check SRv6 Policy Nonexistence node=agent_vpp_1 bsid=A::E + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check SRv6 Policy Nonexistence node=agent_vpp_1 bsid=A::E Check Steering CRUD vpp_ctl: Put SRv6 Policy node=agent_vpp_1 name=AtoE bsid=A::E fibtable=0 srhEncapsulation=true sprayBehaviour=true vpp_ctl: Put SRv6 Policy Segment node=agent_vpp_1 name=firstSegment policyName=AtoE policyBSID=A::E weight=1 segmentlist=${segmentList1} vpp_ctl: Put SRv6 Steering node=agent_vpp_1 name=toE bsid=A::E fibtable=0 prefixAddress=B::/64 - vpp_term: Check SRv6 Steering Presence node=agent_vpp_1 bsid=A::E prefixAddress=B::/64 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check SRv6 Steering Presence node=agent_vpp_1 bsid=A::E prefixAddress=B::/64 vpp_ctl: Put SRv6 Steering node=agent_vpp_1 name=toE bsid=A::E fibtable=0 prefixAddress=C::/64 # modification - vpp_term: Check SRv6 Steering Presence node=agent_vpp_1 bsid=A::E prefixAddress=C::/64 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check SRv6 Steering Presence node=agent_vpp_1 bsid=A::E prefixAddress=C::/64 vpp_ctl: Delete SRv6 Steering node=agent_vpp_1 name=toE - vpp_term: Check SRv6 Steering NonExistence node=agent_vpp_1 bsid=A::E prefixAddress=B::/64 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check SRv6 Steering NonExistence node=agent_vpp_1 bsid=A::E prefixAddress=B::/64 vpp_ctl: Delete SRv6 Policy node=agent_vpp_1 name=AtoE #cleanup #TODO Steering can reference policy also by index -> add test (currently NOT WORKING on VPP side!) @@ -84,8 +83,8 @@ Check delayed configuration vpp_term: Check SRv6 Steering NonExistence node=agent_vpp_1 bsid=A::E prefixAddress=E::/64 vpp_term: Check SRv6 Policy Nonexistence node=agent_vpp_1 bsid=A::E vpp_ctl: Put SRv6 Policy Segment node=agent_vpp_1 name=firstSegment policyName=AtoE policyBSID=A::E weight=1 segmentlist=${segmentList1} - vpp_term: Check SRv6 Steering Presence node=agent_vpp_1 bsid=A::E prefixAddress=E::/64 - vpp_term: Check SRv6 Policy Presence node=agent_vpp_1 bsid=A::E fibtable=0 behaviour=Encapsulation type=Spray index=0 segmentlists=${segmentLists1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check SRv6 Steering Presence node=agent_vpp_1 bsid=A::E prefixAddress=E::/64 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check SRv6 Policy Presence node=agent_vpp_1 bsid=A::E fibtable=0 behaviour=Encapsulation type=Spray index=0 segmentlists=${segmentLists1} vpp_ctl: Delete SRv6 Steering node=agent_vpp_1 name=toE #cleanup vpp_ctl: Delete SRv6 Policy node=agent_vpp_1 name=AtoE #cleanup @@ -95,12 +94,12 @@ Check Resynchronization for clean VPP start vpp_ctl: Put SRv6 Policy Segment node=agent_vpp_1 name=firstSegment policyName=AtoE policyBSID=A::E weight=1 segmentlist=${segmentList1} vpp_ctl: Put SRv6 Steering node=agent_vpp_1 name=toE bsid=A::E fibtable=0 prefixAddress=E::/64 Remove All VPP Nodes - Sleep ${SYNC_SLEEP} + Sleep 3s Add Agent VPP Node agent_vpp_1 - Sleep ${RESYNC_WAIT} - vpp_term: Check Local SID Presence node=agent_vpp_1 sidAddress=A:: interface=host-vpp1_veth2 nexthop=A::1 - vpp_term: Check SRv6 Policy Presence node=agent_vpp_1 bsid=A::E fibtable=0 behaviour=Encapsulation type=Spray index=0 segmentlists=${segmentLists1} - vpp_term: Check SRv6 Steering Presence node=agent_vpp_1 bsid=A::E prefixAddress=E::/64 + + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Local SID Presence node=agent_vpp_1 sidAddress=A:: interface=host-vpp1_veth2 nexthop=A::1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check SRv6 Policy Presence node=agent_vpp_1 bsid=A::E fibtable=0 behaviour=Encapsulation type=Spray index=0 segmentlists=${segmentLists1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check SRv6 Steering Presence node=agent_vpp_1 bsid=A::E prefixAddress=E::/64 *** Keywords *** TestSetup diff --git a/tests/robot/suites/crud/stn_rule_crud.robot b/tests/robot/suites/crud/stn_rule_crud.robot index 8ba868ff3f..3a6ab7daad 100644 --- a/tests/robot/suites/crud/stn_rule_crud.robot +++ b/tests/robot/suites/crud/stn_rule_crud.robot @@ -15,8 +15,9 @@ Test Setup TestSetup Test Teardown TestTeardown *** Variables *** -${SYNC_SLEEP}= 20s -${RESYNC_SLEEP}= 45s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s +${RESYNC_SLEEP}= 15s ${VARIABLES}= common ${ENV}= common ${NAME_TAP1}= vpp1_tap1 @@ -46,14 +47,14 @@ Add TAP1 Interface Check TAP1 Interface Is Created ${interfaces}= vat_term: Interfaces Dump node=agent_vpp_1 Log ${interfaces} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1} ${actual_state}= vpp_term: Check TAP interface State agent_vpp_1 ${NAME_TAP1} mac=${MAC_TAP1} ipv4=${IP_TAP1}/${PREFIX} state=${UP_STATE} Add STN Rule vpp_ctl: Put STN Rule node=agent_vpp_1 interface=${NAME_TAP1} ip=${IP_STN_RULE} rule_name=${RULE_NAME} Check STN Rule Is Created - vpp_term: Check STN Rule State node=agent_vpp_1 interface=${NAME_TAP1} ip=${IP_STN_RULE} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check STN Rule State node=agent_vpp_1 interface=${NAME_TAP1} ip=${IP_STN_RULE} Check TAP1 Interface Is Still Configured ${actual_state}= vpp_term: Check TAP interface State agent_vpp_1 ${NAME_TAP1} mac=${MAC_TAP1} ipv4=${IP_TAP1}/${PREFIX} state=${UP_STATE} @@ -63,20 +64,20 @@ Add TAP2 Interface vpp_ctl: Put TAP Interface With IP node=agent_vpp_1 name=${NAME_TAP2} mac=${MAC_TAP2} ip=${IP_TAP2} prefix=${PREFIX} host_if_name=linux_${NAME_TAP2} Check TAP2 Interface Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP2} ${actual_state}= vpp_term: Check TAP interface State agent_vpp_1 ${NAME_TAP2} mac=${MAC_TAP2} ipv4=${IP_TAP2}/${PREFIX} state=${UP_STATE} Update STN Rule vpp_ctl: Put STN Rule node=agent_vpp_1 interface=${NAME_TAP2} ip=${IP_STN_RULE} rule_name=${RULE_NAME} Check STN Rule Is Updated - vpp_term: Check STN Rule State node=agent_vpp_1 interface=${NAME_TAP2} ip=${IP_STN_RULE} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check STN Rule State node=agent_vpp_1 interface=${NAME_TAP2} ip=${IP_STN_RULE} Delete STN Rule vpp_ctl: Delete STN Rule node=agent_vpp_1 rule_name=${RULE_NAME} Check Deleted STN Rule - vpp_term: Check STN Rule Deleted node=agent_vpp_1 interface=${NAME_TAP2} ip=${IP_STN_RULE} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check STN Rule Deleted node=agent_vpp_1 interface=${NAME_TAP2} ip=${IP_STN_RULE} @@ -84,11 +85,11 @@ Add STN Rule Again vpp_ctl: Put STN Rule node=agent_vpp_1 interface=${NAME_TAP1} ip=${IP_STN_RULE} rule_name=${RULE_NAME} Check STN Rule Is Created Again - vpp_term: Check STN Rule State node=agent_vpp_1 interface=${NAME_TAP1} ip=${IP_STN_RULE} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check STN Rule State node=agent_vpp_1 interface=${NAME_TAP1} ip=${IP_STN_RULE} Remove VPP And Two Nodes Remove Node agent_vpp_1 - Sleep ${SYNC_SLEEP} + Sleep 3s Start VPP And Two Nodes Add Agent VPP Node agent_vpp_1 vswitch=${TRUE} @@ -96,7 +97,7 @@ Start VPP And Two Nodes Show Interfaces And Other Objects Check STN Rule Is Created After Resync - vpp_term: Check STN Rule State node=agent_vpp_1 interface=${NAME_TAP1} ip=${IP_STN_RULE} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check STN Rule State node=agent_vpp_1 interface=${NAME_TAP1} ip=${IP_STN_RULE} *** Keywords *** diff --git a/tests/robot/suites/crud/tap_crud.robot b/tests/robot/suites/crud/tap_crud.robot index c6030bb3b6..8fb6a0662c 100644 --- a/tests/robot/suites/crud/tap_crud.robot +++ b/tests/robot/suites/crud/tap_crud.robot @@ -28,6 +28,8 @@ ${IP_TAP2}= 20.20.2.1 ${PREFIX}= 24 ${MTU}= 4800 ${UP_STATE}= up +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment @@ -44,7 +46,7 @@ Add TAP1 Interface Check TAP1 Interface Is Created ${interfaces}= vat_term: Interfaces Dump node=agent_vpp_1 Log ${interfaces} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1} ${actual_state}= vpp_term: Check TAP interface State agent_vpp_1 ${NAME_TAP1} mac=${MAC_TAP1} ipv4=${IP_TAP1}/${PREFIX} state=${UP_STATE} Add TAP2 Interface @@ -53,7 +55,7 @@ Add TAP2 Interface Sleep 5 Check TAP2 Interface Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP2} ${actual_state}= vpp_term: Check TAP interface State agent_vpp_1 ${NAME_TAP2} mac=${MAC_TAP2} ipv4=${IP_TAP2}/${PREFIX} state=${UP_STATE} Check TAP1 Interface Is Still Configured @@ -63,7 +65,7 @@ Update TAP1 Interface vpp_ctl: Put TAP Interface With IP node=agent_vpp_1 name=${NAME_TAP1} mac=${MAC_TAP1_2} ip=${IP_TAP1_2} prefix=${PREFIX} host_if_name=linux_${NAME_TAP1} Check TAP1_2 Interface Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1_2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1_2} ${actual_state}= vpp_term: Check TAP interface State agent_vpp_1 ${NAME_TAP1} mac=${MAC_TAP1_2} ipv4=${IP_TAP1_2}/${PREFIX} state=${UP_STATE} Check TAP2 Interface Has Not Changed @@ -73,7 +75,7 @@ Delete TAP1_2 Interface vpp_ctl: Delete VPP Interface agent_vpp_1 ${NAME_TAP1} Check TAP1_2 Interface Has Been Deleted - vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_TAP1_2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_TAP1_2} Check TAP2 Interface Is Still Configured ${actual_state}= vpp_term: Check TAP interface State agent_vpp_1 ${NAME_TAP2} mac=${MAC_TAP2} ipv4=${IP_TAP2}/${PREFIX} state=${UP_STATE} diff --git a/tests/robot/suites/crud/tap_unnumbered_crud.robot b/tests/robot/suites/crud/tap_unnumbered_crud.robot index 38e49164c9..066b4fadf0 100644 --- a/tests/robot/suites/crud/tap_unnumbered_crud.robot +++ b/tests/robot/suites/crud/tap_unnumbered_crud.robot @@ -31,6 +31,8 @@ ${IP_TAP3}= 33.20.1.1 ${PREFIX}= 24 ${MTU}= 4800 ${UP_STATE}= up +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment @@ -47,7 +49,7 @@ Add TAP1 Interface Check TAP1 Interface Is Created ${interfaces}= vat_term: Interfaces Dump node=agent_vpp_1 Log ${interfaces} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1} ${actual_state}= vpp_term: Check TAP interface State agent_vpp_1 ${NAME_TAP1} mac=${MAC_TAP1} ipv4=${IP_TAP1}/${PREFIX} state=${UP_STATE} Add TAP2 Unnumbered Interface @@ -55,7 +57,7 @@ Add TAP2 Unnumbered Interface vpp_ctl: Put TAP Unnumbered Interface node=agent_vpp_1 name=${NAME_TAP2} mac=${MAC_TAP2} unnumbered=true interface_with_ip_name=${NAME_TAP1} host_if_name=linux_${NAME_TAP2} Check TAP2 Unnumbered Interface Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP2} ${actual_state}= vpp_term: Check TAP interface State agent_vpp_1 ${NAME_TAP2} mac=${MAC_TAP2} ipv4=${IP_TAP1}/${PREFIX} state=${UP_STATE} Check TAP1 Interface Is Still Configured @@ -65,7 +67,7 @@ Update TAP1 Interface vpp_ctl: Put TAP Interface With IP node=agent_vpp_1 name=${NAME_TAP1} mac=${MAC_TAP1_2} ip=${IP_TAP1_2} prefix=${PREFIX} host_if_name=linux_${NAME_TAP1} Check TAP1_2 Interface Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1_2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1_2} ${actual_state}= vpp_term: Check TAP interface State agent_vpp_1 ${NAME_TAP1} mac=${MAC_TAP1_2} ipv4=${IP_TAP1_2}/${PREFIX} state=${UP_STATE} Check TAP2 Unnumbered Interface Is Changed @@ -78,7 +80,7 @@ Add TAP3 Interface Check TAP3 Interface Is Created ${interfaces}= vat_term: Interfaces Dump node=agent_vpp_1 Log ${interfaces} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP3} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP3} ${actual_state}= vpp_term: Check TAP interface State agent_vpp_1 ${NAME_TAP3} mac=${MAC_TAP3} ipv4=${IP_TAP3}/${PREFIX} state=${UP_STATE} Check TAP2 Unnumbered Interface IS Still Configuredl @@ -88,7 +90,7 @@ Update TAP2 Unnumbered Interface vpp_ctl: Put TAP Unnumbered Interface node=agent_vpp_1 name=${NAME_TAP2} mac=${MAC_TAP2} unnumbered=true interface_with_ip_name=${NAME_TAP3} host_if_name=linux_${NAME_TAP2} Check TAP2_2 Unnumbered Interface Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP2} ${actual_state}= vpp_term: Check TAP interface State agent_vpp_1 ${NAME_TAP2} mac=${MAC_TAP2} ipv4=${IP_TAP3}/${PREFIX} state=${UP_STATE} Check TAP1_2 Interface Is Still Configured @@ -101,7 +103,7 @@ Delete TAP1_2 Interface vpp_ctl: Delete VPP Interface agent_vpp_1 ${NAME_TAP1} Check TAP1_2 Interface Has Been Deleted - vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_TAP1_2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_TAP1_2} Check TAP2_2 Unnumbered Interface IS Still Configured ${actual_state}= vpp_term: Check TAP interface State agent_vpp_1 ${NAME_TAP2} mac=${MAC_TAP2} ipv4=${IP_TAP3}/${PREFIX} state=${UP_STATE} diff --git a/tests/robot/suites/crud/tapv2_crud.robot b/tests/robot/suites/crud/tapv2_crud.robot index a0b340b5b7..268f7f9335 100644 --- a/tests/robot/suites/crud/tapv2_crud.robot +++ b/tests/robot/suites/crud/tapv2_crud.robot @@ -28,7 +28,8 @@ ${IP_TAP2}= 20.20.1.2 ${PREFIX}= 24 ${MTU}= 4800 ${UP_STATE}= up - +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment [Tags] setup @@ -44,7 +45,7 @@ Add TAP1v2 Interface Check TAP1v2 Interface Is Created ${interfaces}= vat_term: Interfaces Dump node=agent_vpp_1 Log ${interfaces} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1} ${actual_state}= vpp_term: Check TAPv2 interface State agent_vpp_1 ${NAME_TAP1} mac=${MAC_TAP1} ipv4=${IP_TAP1}/${PREFIX} state=${UP_STATE} Add TAP2v2 Interface @@ -52,7 +53,7 @@ Add TAP2v2 Interface vpp_ctl: Put TAPv2 Interface With IP node=agent_vpp_1 name=${NAME_TAP2} mac=${MAC_TAP2} ip=${IP_TAP2} prefix=${PREFIX} host_if_name=linux_${NAME_TAP2} Check TAP2v2 Interface Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP2} ${actual_state}= vpp_term: Check TAPv2 interface State agent_vpp_1 ${NAME_TAP2} mac=${MAC_TAP2} ipv4=${IP_TAP2}/${PREFIX} state=${UP_STATE} Check TAP1v2 Interface Is Still Configured @@ -62,7 +63,7 @@ Update TAP1v2 Interface vpp_ctl: Put TAPv2 Interface With IP node=agent_vpp_1 name=${NAME_TAP1} mac=${MAC_TAP1_2} ip=${IP_TAP1_2} prefix=${PREFIX} host_if_name=linux_${NAME_TAP1} Check TAP1_2v2 Interface Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1_2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1_2} ${actual_state}= vpp_term: Check TAPv2 interface State agent_vpp_1 ${NAME_TAP1} mac=${MAC_TAP1_2} ipv4=${IP_TAP1_2}/${PREFIX} state=${UP_STATE} Check TAP2v2 Interface Has Not Changed @@ -72,7 +73,7 @@ Delete TAP1_2v2 Interface vpp_ctl: Delete VPP Interface agent_vpp_1 ${NAME_TAP1} Check TAP1_2v2 Interface Has Been Deleted - vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_TAP1_2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_TAP1_2} Check TAP2 Interface Is Still Configured ${actual_state}= vpp_term: Check TAPv2 interface State agent_vpp_1 ${NAME_TAP2} mac=${MAC_TAP2} ipv4=${IP_TAP2}/${PREFIX} state=${UP_STATE} diff --git a/tests/robot/suites/crud/veth_crud.robot b/tests/robot/suites/crud/veth_crud.robot index 8f8870d5d9..b746805d86 100644 --- a/tests/robot/suites/crud/veth_crud.robot +++ b/tests/robot/suites/crud/veth_crud.robot @@ -22,7 +22,8 @@ ${VETH1_SEC_MAC}= 1a:00:00:11:11:12 ${VETH2_MAC}= 2a:00:00:22:22:22 ${VETH3_MAC}= 3a:00:00:33:33:33 ${VETH4_MAC}= 4a:00:00:44:44:44 - +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment [Tags] setup @@ -41,8 +42,8 @@ Add Veth2 Interface vpp_ctl: Put Veth Interface node=agent_vpp_1 name=vpp1_veth2 mac=${VETH2_MAC} peer=vpp1_veth1 Check That Veth1 And Veth2 Interfaces Are Created - linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_MAC} - linux: Interface Is Created node=agent_vpp_1 mac=${VETH2_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH2_MAC} linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv4=10.10.1.1/24 mtu=1500 state=up linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up @@ -56,8 +57,8 @@ Add Veth4 Interface vpp_ctl: Put Veth Interface node=agent_vpp_1 name=vpp1_veth4 mac=${VETH4_MAC} peer=vpp1_veth3 enabled=false Check That Veth3 And Veth4 Interfaces Are Created - linux: Interface Is Created node=agent_vpp_1 mac=${VETH3_MAC} - linux: Interface Is Created node=agent_vpp_1 mac=${VETH4_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH3_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH4_MAC} linux: Check Veth Interface State agent_vpp_1 vpp1_veth3 mac=${VETH3_MAC} ipv4=20.20.1.1/24 mtu=1500 state=lowerlayerdown linux: Check Veth Interface State agent_vpp_1 vpp1_veth4 mac=${VETH4_MAC} state=down @@ -67,8 +68,8 @@ Check That Veth1 And Veth2 Interfaces Are Still Configured Update Veth1 Interface vpp_ctl: Put Veth Interface With IP node=agent_vpp_1 name=vpp1_veth1 mac=${VETH1_SEC_MAC} peer=vpp1_veth2 ip=11.11.1.1 prefix=28 mtu=1600 - linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH1_MAC} - linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_SEC_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH1_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_SEC_MAC} linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_SEC_MAC} ipv4=11.11.1.1/28 mtu=1600 state=up Check That Veth2 And Veth3 And Veth4 interfaces Are Still Configured @@ -78,8 +79,8 @@ Check That Veth2 And Veth3 And Veth4 interfaces Are Still Configured Delete Veth2 Interface vpp_ctl: Delete Linux Interface node=agent_vpp_1 name=vpp1_veth2 - linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH1_SEC_MAC} - linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH2_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH1_SEC_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH2_MAC} Check That Veth3 And Veth4 Are Still Configured linux: Check Veth Interface State agent_vpp_1 vpp1_veth3 mac=${VETH3_MAC} ipv4=20.20.1.1/24 mtu=1500 state=lowerlayerdown @@ -87,8 +88,8 @@ Check That Veth3 And Veth4 Are Still Configured Delete Veth3 Interface vpp_ctl: Delete Linux Interface node=agent_vpp_1 name=vpp1_veth3 - linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH3_MAC} - linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH4_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH3_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH4_MAC} Show Interfaces And Other Objects After Setup vpp_term: Show Interfaces agent_vpp_1 diff --git a/tests/robot/suites/crud/vxlan_crud.robot b/tests/robot/suites/crud/vxlan_crud.robot index d90ff01c4a..6ca1d9e41b 100644 --- a/tests/robot/suites/crud/vxlan_crud.robot +++ b/tests/robot/suites/crud/vxlan_crud.robot @@ -18,7 +18,8 @@ Test Teardown TestTeardown ${VARIABLES}= common ${ENV}= common -${SYNC_SLEEP}= 5s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment @@ -31,28 +32,22 @@ Show Interfaces Before Setup Add First VXLan Interface vxlan: Tunnel Not Exists node=agent_vpp_1 src=192.168.1.1 dst=192.168.1.2 vni=15 vpp_ctl: Put VXLan Interface node=agent_vpp_1 name=vpp1_vxlan1 src=192.168.1.1 dst=192.168.1.2 vni=15 - Sleep ${SYNC_SLEEP} - vxlan: Tunnel Is Created node=agent_vpp_1 src=192.168.1.1 dst=192.168.1.2 vni=15 - Sleep ${SYNC_SLEEP} - vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan1 enabled=1 src=192.168.1.1 dst=192.168.1.2 vni=15 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vxlan: Tunnel Is Created node=agent_vpp_1 src=192.168.1.1 dst=192.168.1.2 vni=15 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan1 enabled=1 src=192.168.1.1 dst=192.168.1.2 vni=15 Add Second VXLan Interface vxlan: Tunnel Not Exists node=agent_vpp_1 src=192.168.2.1 dst=192.168.2.2 vni=25 vpp_ctl: Put VXLan Interface node=agent_vpp_1 name=vpp1_vxlan2 src=192.168.2.1 dst=192.168.2.2 vni=25 - Sleep ${SYNC_SLEEP} - vxlan: Tunnel Is Created node=agent_vpp_1 src=192.168.2.1 dst=192.168.2.2 vni=25 - Sleep ${SYNC_SLEEP} - vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan2 enabled=1 src=192.168.2.1 dst=192.168.2.2 vni=25 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vxlan: Tunnel Is Created node=agent_vpp_1 src=192.168.2.1 dst=192.168.2.2 vni=25 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan2 enabled=1 src=192.168.2.1 dst=192.168.2.2 vni=25 Check That First VXLan Interface Is Still Configured vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan1 enabled=1 src=192.168.1.1 dst=192.168.1.2 vni=15 Update First VXLan Interface vpp_ctl: Put VXLan Interface node=agent_vpp_1 name=vpp1_vxlan1 src=192.168.1.10 dst=192.168.1.20 vni=150 - Sleep ${SYNC_SLEEP} - vxlan: Tunnel Is Deleted node=agent_vpp_1 src=192.168.1.1 dst=192.168.1.2 vni=15 - vxlan: Tunnel Is Created node=agent_vpp_1 src=192.168.1.10 dst=192.168.1.20 vni=150 - Sleep ${SYNC_SLEEP} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vxlan: Tunnel Is Deleted node=agent_vpp_1 src=192.168.1.1 dst=192.168.1.2 vni=15 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vxlan: Tunnel Is Created node=agent_vpp_1 src=192.168.1.10 dst=192.168.1.20 vni=150 vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan1 enabled=1 src=192.168.1.10 dst=192.168.1.20 vni=150 Check That Second VXLan Interface Is Not Changed @@ -60,8 +55,7 @@ Check That Second VXLan Interface Is Not Changed Delete First VXLan Interface vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=vpp1_vxlan1 - Sleep ${SYNC_SLEEP} - vxlan: Tunnel Is Deleted node=agent_vpp_1 src=192.168.1.10 dst=192.168.1.20 vni=150 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vxlan: Tunnel Is Deleted node=agent_vpp_1 src=192.168.1.10 dst=192.168.1.20 vni=150 Check That Second VXLan Interface Is Still Configured vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan2 enabled=1 src=192.168.2.1 dst=192.168.2.2 vni=25 diff --git a/tests/robot/suites/crudIPv6/acl_crudIPv6.robot b/tests/robot/suites/crudIPv6/acl_crudIPv6.robot index 4e985b8b27..d5070148c7 100644 --- a/tests/robot/suites/crudIPv6/acl_crudIPv6.robot +++ b/tests/robot/suites/crudIPv6/acl_crudIPv6.robot @@ -48,7 +48,8 @@ ${2DEST_PORT_L}= 2000 ${2DEST_PORT_U}= 2200 ${2SRC_PORT_L}= 20010 ${2SRC_PORT_U}= 20020 -${SYNC_SLEEP}= 1s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s ${NO_ACL}= @@ -61,102 +62,89 @@ Configure Environment Configure Environment 2 acl_basic.conf Show ACL Before Setup - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL1_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl_empty_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL1_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl_empty_term.txt Add ACL1_TCP vpp_ctl: Put ACL TCP agent_vpp_1 ${ACL1_NAME} ${E_INTF1} ${I_INTF1} ${ACTION_DENY} ${DEST_NTW} ${SRC_NTW} ${1DEST_PORT_L} ${1DEST_PORT_U} ${1SRC_PORT_L} ${1SRC_PORT_U} - Sleep ${SYNC_SLEEP} Check ACL1 is created - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL1_NAME} ${REPLY_DATA_FOLDER}/reply_acl1IPv6_tcp.txt ${REPLY_DATA_FOLDER}/reply_acl1IPv6_tcp_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL1_NAME} ${REPLY_DATA_FOLDER}/reply_acl1IPv6_tcp.txt ${REPLY_DATA_FOLDER}/reply_acl1IPv6_tcp_term.txt Add ACL2_TCP vpp_ctl: Put ACL TCP agent_vpp_1 ${ACL2_NAME} ${E_INTF1} ${I_INTF1} ${ACTION_DENY} ${DEST_NTW} ${SRC_NTW} ${2DEST_PORT_L} ${2DEST_PORT_U} ${2SRC_PORT_L} ${2SRC_PORT_U} - Sleep ${SYNC_SLEEP} Check ACL2 is created and ACL1 still Configured - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL2_NAME} ${REPLY_DATA_FOLDER}/reply_acl2IPv6_tcp.txt ${REPLY_DATA_FOLDER}/reply_acl2IPv6_tcp_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL2_NAME} ${REPLY_DATA_FOLDER}/reply_acl2IPv6_tcp.txt ${REPLY_DATA_FOLDER}/reply_acl2IPv6_tcp_term.txt Update ACL1 vpp_ctl: Put ACL TCP agent_vpp_1 ${ACL1_NAME} ${E_INTF1} ${I_INTF1} ${ACTION_PERMIT} ${DEST_NTW} ${SRC_NTW} ${1DEST_PORT_L} ${1DEST_PORT_U} ${1SRC_PORT_L} ${1SRC_PORT_U} - Sleep ${SYNC_SLEEP} Check ACL1 Is Changed and ACL2 not changed - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL1_NAME} ${REPLY_DATA_FOLDER}/reply_acl1IPv6_update_tcp.txt ${REPLY_DATA_FOLDER}/reply_acl1IPv6_update_tcp_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL1_NAME} ${REPLY_DATA_FOLDER}/reply_acl1IPv6_update_tcp.txt ${REPLY_DATA_FOLDER}/reply_acl1IPv6_update_tcp_term.txt Delete ACL2 vpp_ctl: Delete ACL agent_vpp_1 ${ACL2_NAME} - Sleep ${SYNC_SLEEP} Check ACL2 Is Deleted and ACL1 Is Not Changed - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL2_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl2IPv6_delete_tcp_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL2_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl2IPv6_delete_tcp_term.txt Delete ACL1 vpp_ctl: Delete ACL agent_vpp_1 ${ACL1_NAME} - Sleep ${SYNC_SLEEP} Check ACL1 Is Deleted - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL1_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl_empty_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL1_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl_empty_term.txt ADD ACL3_UDP vpp_ctl: Put ACL UDP agent_vpp_1 ${ACL3_NAME} ${E_INTF1} ${I_INTF1} ${E_INTF2} ${I_INTF2} ${ACTION_DENY} ${DEST_NTW} ${SRC_NTW} ${1DEST_PORT_L} ${1DEST_PORT_U} ${1SRC_PORT_L} ${1SRC_PORT_U} - Sleep ${SYNC_SLEEP} Check ACL3 Is Created - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL3_NAME} ${REPLY_DATA_FOLDER}/reply_acl3IPv6_udp.txt ${REPLY_DATA_FOLDER}/reply_acl3IPv6_udp_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL3_NAME} ${REPLY_DATA_FOLDER}/reply_acl3IPv6_udp.txt ${REPLY_DATA_FOLDER}/reply_acl3IPv6_udp_term.txt ADD ACL4_UDP vpp_ctl: Put ACL UDP agent_vpp_1 ${ACL4_NAME} ${E_INTF1} ${I_INTF1} ${E_INTF2} ${I_INTF2} ${ACTION_DENY} ${DEST_NTW} ${SRC_NTW} ${1DEST_PORT_L} ${1DEST_PORT_U} ${1SRC_PORT_L} ${1SRC_PORT_U} - Sleep ${SYNC_SLEEP} Check ACL4 Is Created And ACL3 Still Configured - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL4_NAME} ${REPLY_DATA_FOLDER}/reply_acl4IPv6_udp.txt ${REPLY_DATA_FOLDER}/reply_acl4IPv6_udp_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL4_NAME} ${REPLY_DATA_FOLDER}/reply_acl4IPv6_udp.txt ${REPLY_DATA_FOLDER}/reply_acl4IPv6_udp_term.txt Delete ACL4 vpp_ctl: Delete ACL agent_vpp_1 ${ACL4_NAME} - Sleep ${SYNC_SLEEP} Check ACL4 Is Deleted and ACL3 Is Not Changed - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL4_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl3IPv6_udp_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL4_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl3IPv6_udp_term.txt Delete ACL3 vpp_ctl: Delete ACL agent_vpp_1 ${ACL3_NAME} - Sleep ${SYNC_SLEEP} Check ACL3 Is Deleted - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL3_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl_empty_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL3_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl_empty_term.txt ADD ACL5_ICMP vpp_ctl: Put ACL UDP agent_vpp_1 ${ACL5_NAME} ${E_INTF1} ${I_INTF1} ${E_INTF2} ${I_INTF2} ${ACTION_DENY} ${DEST_NTW} ${SRC_NTW} ${1DEST_PORT_L} ${1DEST_PORT_U} ${1SRC_PORT_L} ${1SRC_PORT_U} - Sleep ${SYNC_SLEEP} Check ACL5 Is Created - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL5_NAME} ${REPLY_DATA_FOLDER}/reply_acl5IPv6_icmp.txt ${REPLY_DATA_FOLDER}/reply_acl5IPv6_icmp_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL5_NAME} ${REPLY_DATA_FOLDER}/reply_acl5IPv6_icmp.txt ${REPLY_DATA_FOLDER}/reply_acl5IPv6_icmp_term.txt ADD ACL6_ICMP vpp_ctl: Put ACL UDP agent_vpp_1 ${ACL6_NAME} ${E_INTF1} ${I_INTF1} ${E_INTF2} ${I_INTF2} ${ACTION_DENY} ${DEST_NTW} ${SRC_NTW} ${1DEST_PORT_L} ${1DEST_PORT_U} ${1SRC_PORT_L} ${1SRC_PORT_U} - Sleep ${SYNC_SLEEP} Check ACL6 Is Created And ACL5 Still Configured - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL6_NAME} ${REPLY_DATA_FOLDER}/reply_acl6IPv6_icmp.txt ${REPLY_DATA_FOLDER}/reply_acl6IPv6_icmp_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL6_NAME} ${REPLY_DATA_FOLDER}/reply_acl6IPv6_icmp.txt ${REPLY_DATA_FOLDER}/reply_acl6IPv6_icmp_term.txt Delete ACL6 vpp_ctl: Delete ACL agent_vpp_1 ${ACL6_NAME} - Sleep ${SYNC_SLEEP} Check ACL6 Is Deleted and ACL5 Is Not Changed - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL6_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl5IPv6_icmp_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL6_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl5IPv6_icmp_term.txt Delete ACL5 vpp_ctl: Delete ACL agent_vpp_1 ${ACL5_NAME} - Sleep ${SYNC_SLEEP} Check ACL5 Is Deleted - vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL5_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl_empty_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Check ACL Reply agent_vpp_1 ${ACL5_NAME} ${REPLY_DATA_FOLDER}/reply_acl_empty.txt ${REPLY_DATA_FOLDER}/reply_acl_empty_term.txt Add 6 ACL @@ -168,7 +156,7 @@ Add 6 ACL vpp_ctl: Put ACL UDP agent_vpp_1 ${ACL6_NAME} ${E_INTF1} ${I_INTF1} ${E_INTF2} ${I_INTF2} ${ACTION_DENY} ${DEST_NTW} ${SRC_NTW} ${1DEST_PORT_L} ${1DEST_PORT_U} ${1SRC_PORT_L} ${1SRC_PORT_U} Check All 6 ACLs Added - Check ACL All Reply agent_vpp_1 ${REPLY_DATA_FOLDER}/reply_aclIPv6_all.txt ${REPLY_DATA_FOLDER}/reply_aclIPv6_all_term.txt + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check ACL All Reply agent_vpp_1 ${REPLY_DATA_FOLDER}/reply_aclIPv6_all.txt ${REPLY_DATA_FOLDER}/reply_aclIPv6_all_term.txt *** Keywords *** diff --git a/tests/robot/suites/crudIPv6/afpacket_crudIPv6.robot b/tests/robot/suites/crudIPv6/afpacket_crudIPv6.robot index 8278c3ea1d..66dc78500e 100644 --- a/tests/robot/suites/crudIPv6/afpacket_crudIPv6.robot +++ b/tests/robot/suites/crudIPv6/afpacket_crudIPv6.robot @@ -28,6 +28,9 @@ ${IP_ADR}= fd30:0:0:1:e:: ${IP_ADR_MASK}= fd30:0:0:1:e::/64 ${IP_ADR2}= fd30:0:0:2:f:: ${IP_ADR_MASK2}= fd30:0:0:2:f::/64 +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s + *** Test Cases *** Configure Environment [Tags] setup @@ -47,21 +50,21 @@ Add Afpacket1 Interface vpp_term: Show Interfaces agent_vpp_1 Check That Afpacket1 Interface Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${AFP1_MAC} - vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket1 enabled=1 mac=${AFP1_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${AFP1_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket1 enabled=1 mac=${AFP1_MAC} Check That Veth1 And Veth2 Interfaces Are Created And Not Affected By Afpacket1 Interface - linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_MAC} - linux: Interface Is Created node=agent_vpp_1 mac=${VETH2_MAC} - linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv6=${IP_ADR_MASK} mtu=1500 state=up - linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH2_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv6=${IP_ADR_MASK} mtu=1500 state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up Add Afpacket2 Interface Before Veth3 And Veth4 Interfaces vpp_term: Interface Not Exists node=agent_vpp_1 mac=${AFP2_MAC} vpp_ctl: Put Afpacket Interface node=agent_vpp_1 name=vpp1_afpacket2 mac=${AFP2_MAC} host_int=vpp1_veth3 Check That Afpacket2 Interface Is Not Created Without Veth3 And Veth4 - vpp_term: Interface Not Exists node=agent_vpp_1 mac=${AFP2_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Not Exists node=agent_vpp_1 mac=${AFP2_MAC} Add Veth3 Interface linux: Interface Not Exists node=agent_vpp_1 mac=${VETH3_MAC} @@ -69,33 +72,33 @@ Add Veth3 Interface linux: Interface Not Exists node=agent_vpp_1 mac=${VETH3_MAC} Check That Afpacket2 Is Not Created Without Veth4 - vpp_term: Interface Not Exists node=agent_vpp_1 mac=${AFP2_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Not Exists node=agent_vpp_1 mac=${AFP2_MAC} Add Veth4 Interface linux: Interface Not Exists node=agent_vpp_1 mac=${VETH4_MAC} vpp_ctl: Put Veth Interface node=agent_vpp_1 name=vpp1_veth4 mac=${VETH4_MAC} peer=vpp1_veth3 enabled=false Check That Afpacket2 Interface Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${AFP2_MAC} - vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket2 enabled=1 mac=${AFP2_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${AFP2_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket2 enabled=1 mac=${AFP2_MAC} Check That Veth3 And Veth4 Interfaces Are Created And Not Affected By Afpacket2 Interface - linux: Interface Is Created node=agent_vpp_1 mac=${VETH3_MAC} - linux: Interface Is Created node=agent_vpp_1 mac=${VETH4_MAC} - linux: Check Veth Interface State agent_vpp_1 vpp1_veth3 mac=${VETH3_MAC} ipv6=${IP_ADR_MASK2} mtu=1500 state=lowerlayerdown - linux: Check Veth Interface State agent_vpp_1 vpp1_veth4 mac=${VETH4_MAC} state=down + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH3_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH4_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth3 mac=${VETH3_MAC} ipv6=${IP_ADR_MASK2} mtu=1500 state=lowerlayerdown + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth4 mac=${VETH4_MAC} state=down Check That Afpacket1 Interface Is Still Configured vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket1 enabled=1 mac=${AFP1_MAC} Update Afpacket2 Interface vpp_ctl: Put Afpacket Interface node=agent_vpp_1 name=vpp1_afpacket2 mac=${AFP2_SEC_MAC} host_int=vpp1_veth4 - vpp_term: Interface Is Deleted node=agent_vpp_1 mac=${AFP2_MAC} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${AFP2_SEC_MAC} - vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket2 enabled=1 mac=${AFP2_SEC_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_1 mac=${AFP2_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${AFP2_SEC_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket2 enabled=1 mac=${AFP2_SEC_MAC} Check That Afpacket1 Interface Is Still Configured After Update - vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket1 enabled=1 mac=${AFP1_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket1 enabled=1 mac=${AFP1_MAC} Check That Veth3 And Veth4 Interfaces Are Not Affected By Change Of Afpacket2 Interface linux: Check Veth Interface State agent_vpp_1 vpp1_veth3 mac=${VETH3_MAC} ipv6=${IP_ADR_MASK2} mtu=1500 state=lowerlayerdown @@ -106,16 +109,16 @@ Delete Afpacket1 Interface vpp_term: Interface Is Deleted node=agent_vpp_1 mac=${AFP1_MAC} Check That Afpacket2 Interface Is Still Configured - vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket2 enabled=1 mac=${AFP2_SEC_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket2 enabled=1 mac=${AFP2_SEC_MAC} Check That Veth1 And Veth2 Interfaces Are Not Affected By Delete Of Afpacket1 Interface - linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv4=${IP_ADR_MASK} mtu=1500 state=up - linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv4=${IP_ADR_MASK} mtu=1500 state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up Delete Veth3 Interface vpp_ctl: Delete Linux Interface node=agent_vpp_1 name=vpp1_veth3 - linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH3_MAC} - linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH4_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH3_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH4_MAC} Check That Afpacket2 Interface Is Deleted After Deleting Veth3 And Veth4 vpp_term: Interface Is Deleted node=agent_vpp_1 mac=${AFP2_SEC_MAC} diff --git a/tests/robot/suites/crudIPv6/app_namespaces_crudIPv6.robot b/tests/robot/suites/crudIPv6/app_namespaces_crudIPv6.robot index 9b7c086678..7ced67b411 100644 --- a/tests/robot/suites/crudIPv6/app_namespaces_crudIPv6.robot +++ b/tests/robot/suites/crudIPv6/app_namespaces_crudIPv6.robot @@ -47,7 +47,8 @@ ${PREFIX}= 64 ${MTU}= 1500 ${VARIABLES}= common ${ENV}= common -${SYNC_SLEEP}= 10s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s # wait for resync vpps after restart ${RESYNC_WAIT}= 50s @@ -76,7 +77,7 @@ Put Interface TAP1 And Namespace NS1 Associated With TAP1 And Check The Namespac Log ${out} ${out_lines1}= Get Line Count ${out} Set Suite Variable ${out_lines1} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET1} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET1} ${TAP1_SW_IF_INDEX} Put Already Existing Namespace NS1 And Check Namespace Was Not Added To Namespaces List vpp_ctl: Put Application Namespace node=agent_vpp_1 id=${NS1_ID} secret=${SECRET1} interface=${TAP1_NAME} @@ -84,41 +85,41 @@ Put Already Existing Namespace NS1 And Check Namespace Was Not Added To Namespac Log ${out} ${out_lines2}= Get Line Count ${out} Should Be Equal ${out_lines1} ${out_lines2} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET1} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET1} ${TAP1_SW_IF_INDEX} Update Namespace NS1 Secret And Check The Namespace's Update Is Reflected In Namespaces List vpp_ctl: Put Application Namespace node=agent_vpp_1 id=${NS1_ID} secret=${SECRET2} interface=${TAP1_NAME} ${out}= vpp_term: Show Application Namespaces node=agent_vpp_1 Log ${out} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} Put New NS2 Namespace And Check The Namespace Is Present In Namespaces List And Namespace NS1 Is Still Configured vpp_ctl: Put Application Namespace node=agent_vpp_1 id=${NS2_ID} secret=${SECRET3} interface=${TAP1_NAME} ${out}= vpp_term: Show Application Namespaces node=agent_vpp_1 Log ${out} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS2_ID} 2 ${SECRET3} ${TAP1_SW_IF_INDEX} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS2_ID} 2 ${SECRET3} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} Put Interface TAP2 And Namespace NS3 Associated With TAP2 And Check The Namespace Is Present In Namespaces List vpp_ctl: Put TAP Interface With IP node=agent_vpp_1 name=${TAP2_NAME} mac=${TAP2_MAC} ip=${TAP2_IP} prefix=${PREFIX} host_if_name=linux_${TAP2_NAME} vpp_ctl: Put Application Namespace node=agent_vpp_1 id=${NS3_ID} secret=${SECRET4} interface=${TAP2_NAME} ${out}= vpp_term: Show Application Namespaces node=agent_vpp_1 Log ${out} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS3_ID} 3 ${SECRET4} ${TAP2_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS3_ID} 3 ${SECRET4} ${TAP2_SW_IF_INDEX} Check NS1 And NS2 Namespaces Remained Configured - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS2_ID} 2 ${SECRET3} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS2_ID} 2 ${SECRET3} ${TAP1_SW_IF_INDEX} Update Namespace NS2 Associated Interface To TAP2 And Secret And Check The Namespace's Update Is Reflected In Namespaces List vpp_ctl: Put Application Namespace node=agent_vpp_1 id=${NS2_ID} secret=${SECRET1} interface=${TAP2_NAME} ${out}= vpp_term: Show Application Namespaces node=agent_vpp_1 Log ${out} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS2_ID} 2 ${SECRET1} ${TAP2_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS2_ID} 2 ${SECRET1} ${TAP2_SW_IF_INDEX} Check NS1 And NS3 Namespaces Are Still Configured - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS3_ID} 3 ${SECRET4} ${TAP2_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS3_ID} 3 ${SECRET4} ${TAP2_SW_IF_INDEX} Do RESYNC 1 Remove All Nodes @@ -135,9 +136,9 @@ Get Interfaces Sw If Index After Resync 1 Set Suite Variable ${TAP2_SW_IF_INDEX} Check NS1, NS2 And NS3 Were Automatically Configured After Resync - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS2_ID} 2 ${SECRET1} ${TAP2_SW_IF_INDEX} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS3_ID} 3 ${SECRET4} ${TAP2_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS2_ID} 2 ${SECRET1} ${TAP2_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS3_ID} 3 ${SECRET4} ${TAP2_SW_IF_INDEX} Disable L4 Features And Check They Are Disabled vpp_ctl: Set L4 Features On Node node=agent_vpp_1 enabled=false @@ -150,10 +151,10 @@ Put Namespace NS4 While L4 Features Are Disabled Enable L4 Features And Check Namespaces NS1, NS2, NS3 And NS4 Are Present In Namespaces List vpp_ctl: Set L4 Features On Node node=agent_vpp_1 enabled=true ${out}= vpp_term: Show Application Namespaces node=agent_vpp_1 - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS2_ID} 2 ${SECRET1} ${TAP2_SW_IF_INDEX} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS3_ID} 3 ${SECRET4} ${TAP2_SW_IF_INDEX} - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS4_ID} 4 ${SECRET4} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS1_ID} 1 ${SECRET2} ${TAP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS2_ID} 2 ${SECRET1} ${TAP2_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS3_ID} 3 ${SECRET4} ${TAP2_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS4_ID} 4 ${SECRET4} ${TAP1_SW_IF_INDEX} Put Namespace NS5 Associated With MEMIF1 Interface That Is Not Created And Check NS5 Is Not Present In Namespaces List vpp_ctl: Put Application Namespace node=agent_vpp_1 id=${NS5_ID} secret=${SECRET1} interface=${MEMIF1_NAME} @@ -163,7 +164,7 @@ Put Namespace NS5 Associated With MEMIF1 Interface That Is Not Created And Check Put MEMIF1 Interface And Check Namespace NS5 Is Present In Namespaces List vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=memif1 mac=${MEMIF1_MAC} master=true id=1 ip=fd30:0:0:1:e::2 prefix=${PREFIX} socket=default.sock Sleep 1 - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS5_ID} 5 ${SECRET1} ${MEMIF1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS5_ID} 5 ${SECRET1} ${MEMIF1_SW_IF_INDEX} Put Namespace NS6 Associated With LOOP1 Interface That Is Not Created And Check NS6 Is Not Present In Namespaces List vpp_ctl: Put Application Namespace node=agent_vpp_1 id=${NS6_ID} secret=${SECRET1} interface=${LOOP1_NAME} @@ -173,7 +174,7 @@ Put Namespace NS6 Associated With LOOP1 Interface That Is Not Created And Check Put LOOP1 Interface And Check Namespace NS6 Is Present In Namespaces List vpp_ctl: Put Loopback Interface With IP node=agent_vpp_1 name=${LOOP1_NAME} mac=${LOOP1_MAC} ip=${LOOP1_IP} prefix=${PREFIX} mtu=${MTU} enabled=true Sleep 1 - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS6_ID} 6 ${SECRET1} ${LOOP1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS6_ID} 6 ${SECRET1} ${LOOP1_SW_IF_INDEX} Put Namespace NS7 Associated With VXLAN1 Interface That Is Not Created And Check NS7 Is Not Present In Namespaces List vpp_ctl: Put Application Namespace node=agent_vpp_1 id=${NS7_ID} secret=${SECRET1} interface=${VXLAN1_NAME} @@ -183,7 +184,7 @@ Put Namespace NS7 Associated With VXLAN1 Interface That Is Not Created And Check Put VXLAN1 Interface And Check Namespace NS7 Is Present In Namespaces List vpp_ctl: Put VXLan Interface node=agent_vpp_1 name=${VXLAN1_NAME} src=${VXLAN1_SRC} dst=${VXLAN1_DST} vni=${VXLAN1_VNI} Sleep 1 - vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS7_ID} 7 ${SECRET1} ${VXLAN1_SW_IF_INDEX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check Data In Show Application Namespaces Output agent_vpp_1 ${NS7_ID} 7 ${SECRET1} ${VXLAN1_SW_IF_INDEX} Do RESYNC 2 Remove All Nodes diff --git a/tests/robot/suites/crudIPv6/arp_crudIPv6.robot b/tests/robot/suites/crudIPv6/arp_crudIPv6.robot index c26b427594..9ddbeb46b2 100644 --- a/tests/robot/suites/crudIPv6/arp_crudIPv6.robot +++ b/tests/robot/suites/crudIPv6/arp_crudIPv6.robot @@ -17,7 +17,8 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${SYNC_SLEEP}= 6s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s ${VETH1_MAC}= 1a:00:00:11:11:11 ${VETH2_MAC}= 2a:00:00:22:22:22 ${AFP1_MAC}= a2:01:01:01:01:01 @@ -51,8 +52,8 @@ Add Veth2 Interface vpp_ctl: Put Veth Interface node=agent_vpp_1 name=vpp1_veth2 mac=${VETH2_MAC} peer=vpp1_veth1 Check That Veth1 And Veth2 Interfaces Are Created - linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_MAC} - linux: Interface Is Created node=agent_vpp_1 mac=${VETH2_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH2_MAC} linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv6=${VETH1_IP_PREFIX} mtu=1500 state=up linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up vpp_term: Show Interface Mode agent_vpp_1 vpp1_veth1@vpp1_veth2 @@ -63,30 +64,30 @@ Add Memif Interface vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=true id=1 ip=${MEMIF1_IP} prefix=${PREFIX} socket=default.sock Check Memif Interface Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=1 ipv6=${MEMIF1_IP_PREFIX} connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=1 ipv6=${MEMIF1_IP_PREFIX} connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock Add VXLan Interface vpp_ctl: Put VXLan Interface node=agent_vpp_1 name=vpp1_vxlan1 src=${MEMIF1_IP} dst=${VXLAN_IP} vni=5 Check VXLan Interface Created - vxlan: Tunnel Is Created node=agent_vpp_1 src=${MEMIF1_IP} dst=${VXLAN_IP} vni=5 - vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan1 enabled=1 src=${MEMIF1_IP} dst=${VXLAN_IP} vni=5 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vxlan: Tunnel Is Created node=agent_vpp_1 src=${MEMIF1_IP} dst=${VXLAN_IP} vni=5 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan1 enabled=1 src=${MEMIF1_IP} dst=${VXLAN_IP} vni=5 Add Loopback Interface vpp_ctl: Put Loopback Interface With IP node=agent_vpp_1 name=vpp1_loop1 mac=12:21:21:11:11:11 ip=${LOOPBACK_IP} prefix=${PREFIX} mtu=1400 Check Loopback Interface Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=12:21:21:11:11:11 - vat_term: Check Loopback Interface State agent_vpp_1 vpp1_loop1 enabled=1 mac=12:21:21:11:11:11 mtu=1400 ipv6=${LOOPBACK_IP_PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=12:21:21:11:11:11 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 vpp1_loop1 enabled=1 mac=12:21:21:11:11:11 mtu=1400 ipv6=${LOOPBACK_IP_PREFIX} Add Tap Interface vpp_ctl: Put TAP Interface With IP node=agent_vpp_1 name=vpp1_tap1 mac=32:21:21:11:11:11 ip=${TAP_IP} prefix=${PREFIX} host_if_name=linux_vpp1_tap1 Check TAP Interface Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=32:21:21:11:11:11 - vpp_term: Check TAP interface State agent_vpp_1 vpp1_tap1 mac=32:21:21:11:11:11 ipv6=${TAP_IP_PREFIX} state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=32:21:21:11:11:11 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check TAP interface State agent_vpp_1 vpp1_tap1 mac=32:21:21:11:11:11 ipv6=${TAP_IP_PREFIX} state=up Check Stuff Show Interfaces And Other Objects @@ -107,8 +108,8 @@ Add ARPs Sleep ${SYNC_SLEEP} Check Memif ARP - vpp_term: Check ARP agent_vpp_1 vpp1_memif1 155.155.155.155 32:51:51:51:51:51 True - vpp_term: Check ARP agent_vpp_1 vpp1_memif1 155.155.155.156 32:51:51:51:51:52 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_memif1 155.155.155.155 32:51:51:51:51:51 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_memif1 155.155.155.156 32:51:51:51:51:52 True #Check Veth1 ARP # vpp_term: Check ARP agent_vpp_1 vpp1_veth1 155.155.155.155 32:51:51:51:51:51 True @@ -119,38 +120,37 @@ Check Memif ARP # vpp_term: Check ARP agent_vpp_1 vpp1_veth2 155.155.155.150 32:51:51:51:51:5 True Check VXLan ARP - vpp_term: Check ARP agent_vpp_1 vpp1_vxlan1 155.155.155.155 32:51:51:51:51:51 True - vpp_term: Check ARP agent_vpp_1 vpp1_vxlan1 155.155.155.154 32:51:51:51:51:53 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_vxlan1 155.155.155.155 32:51:51:51:51:51 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_vxlan1 155.155.155.154 32:51:51:51:51:53 True Check Loopback ARP - vpp_term: Check ARP agent_vpp_1 vpp1_loop1 155.155.155.155 32:51:51:51:51:51 True - vpp_term: Check ARP agent_vpp_1 vpp1_loop1 155.155.155.152 32:51:51:51:51:55 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_loop1 155.155.155.155 32:51:51:51:51:51 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_loop1 155.155.155.152 32:51:51:51:51:55 True Check TAP ARP - vpp_term: Check ARP agent_vpp_1 vpp1_tap1 155.155.155.155 32:51:51:51:51:51 True - vpp_term: Check ARP agent_vpp_1 vpp1_tap1 155.155.155.150 32:51:51:51:51:5 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_tap1 155.155.155.155 32:51:51:51:51:51 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_tap1 155.155.155.150 32:51:51:51:51:5 True ADD Afpacket Interface vpp_ctl: Put Afpacket Interface node=agent_vpp_1 name=vpp1_afpacket1 mac=a2:a1:a1:a1:a1:a1 host_int=vpp1_veth2 Check AFpacket Interface Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=a2:a1:a1:a1:a1:a1 - vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket1 enabled=1 mac=a2:a1:a1:a1:a1:a1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=a2:a1:a1:a1:a1:a1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket1 enabled=1 mac=a2:a1:a1:a1:a1:a1 Check Veth1 Veth2 Are Created After Afpacket is created - linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_MAC} - linux: Interface Is Created node=agent_vpp_1 mac=${VETH2_MAC} - linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv6=${VETH1_IP_PREFIX} mtu=1500 state=up - linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH2_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv6=${VETH1_IP_PREFIX} mtu=1500 state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up Add ARP for Afpacket vpp_ctl: Put ARP agent_vpp_1 host-vpp1_veth2 155.155.155.155 32:51:51:51:51:51 False vpp_ctl: Put ARP agent_vpp_1 host-vpp1_veth2 155.155.155.150 32:51:51:51:51:5 False - Sleep ${SYNC_SLEEP} Check Afpacket ARP - vpp_term: Check ARP agent_vpp_1 host-vpp1_veth2 155.155.155.155 32:51:51:51:51:51 True - vpp_term: Check ARP agent_vpp_1 host-vpp1_veth2 155.155.155.150 32:51:51:51:51:5 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 host-vpp1_veth2 155.155.155.155 32:51:51:51:51:51 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 host-vpp1_veth2 155.155.155.150 32:51:51:51:51:5 True Delete ARPs vpp_ctl: Delete ARP agent_vpp_1 vpp1_memif1 155.155.155.156 @@ -162,11 +162,11 @@ Delete ARPs vpp_ctl: Delete ARP agent_vpp_1 host-vpp1_veth2 155.155.155.150 vpp_term:Show ARP agent_vpp_1 Execute In Container agent_vpp_1 ip neigh - Sleep ${SYNC_SLEEP} + Check Memif ARP After Delete - vpp_term: Check ARP agent_vpp_1 vpp1_memif1 155.155.155.155 32:51:51:51:51:51 True - vpp_term: Check ARP agent_vpp_1 vpp1_memif1 155.155.155.156 32:51:51:51:51:52 False + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_memif1 155.155.155.155 32:51:51:51:51:51 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_memif1 155.155.155.156 32:51:51:51:51:52 False #Check Veth1 ARP After Delete # vpp_term: Check ARP agent_vpp_1 vpp1_veth1 155.155.155.155 32:51:51:51:51:51 True @@ -177,20 +177,20 @@ Check Memif ARP After Delete # vpp_term: Check ARP agent_vpp_1 vpp1_veth2 155.155.155.15 32:51:51:51:51:5 False Check VXLan ARP After Delete - vpp_term: Check ARP agent_vpp_1 vpp1_vxlan1 155.155.155.155 32:51:51:51:51:51 True - vpp_term: Check ARP agent_vpp_1 vpp1_vxlan1 155.155.155.154 32:51:51:51:51:53 False + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_vxlan1 155.155.155.155 32:51:51:51:51:51 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_vxlan1 155.155.155.154 32:51:51:51:51:53 False Check Loopback ARP After Delete - vpp_term: Check ARP agent_vpp_1 vpp1_loop1 155.155.155.155 32:51:51:51:51:51 True - vpp_term: Check ARP agent_vpp_1 vpp1_loop1 155.155.155.152 32:51:51:51:51:55 False + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_loop1 155.155.155.155 32:51:51:51:51:51 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_loop1 155.155.155.152 32:51:51:51:51:55 False Check TAP ARP After Delete - vpp_term: Check ARP agent_vpp_1 vpp1_tap1 155.155.155.155 32:51:51:51:51:51 True - vpp_term: Check ARP agent_vpp_1 vpp1_tap1 155.155.155.150 32:51:51:51:51:5 False + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_tap1 155.155.155.155 32:51:51:51:51:51 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_tap1 155.155.155.150 32:51:51:51:51:5 False Check Afpacket ARP After Delete - vpp_term: Check ARP agent_vpp_1 host-vpp1_veth2 155.155.155.155 32:51:51:51:51:51 True - vpp_term: Check ARP agent_vpp_1 host-vpp1_veth2 155.155.155.150 32:51:51:51:51:5 False + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 host-vpp1_veth2 155.155.155.155 32:51:51:51:51:51 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 host-vpp1_veth2 155.155.155.150 32:51:51:51:51:5 False Modify ARPs vpp_ctl: Put ARP agent_vpp_1 vpp1_memif1 155.155.155.155 32:51:51:51:51:58 false @@ -207,10 +207,9 @@ Modify ARPs vpp_term:Show ARP agent_vpp_1 vpp_ctl: Put ARP agent_vpp_1 host-vpp1_veth2 155.155.155.155 32:51:51:51:51:58 False vpp_term:Show ARP agent_vpp_1 - Sleep ${SYNC_SLEEP} Check Memif ARP After Modify - vpp_term: Check ARP agent_vpp_1 vpp1_memif1 155.155.155.155 32:51:51:51:51:58 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_memif1 155.155.155.155 32:51:51:51:51:58 True #Check Veth1 ARP After Modify # vpp_term: Check ARP agent_vpp_1 vpp1_veth1 155.155.155.155 32:51:51:51:51:5 True @@ -219,16 +218,16 @@ Check Memif ARP After Modify # vpp_term: Check ARP agent_vpp_1 vpp1_veth2 155.155.155.155 32:51:51:51:51:5 True Check VXLan ARP After Modify - vpp_term: Check ARP agent_vpp_1 vpp1_vxlan1 155.155.155.155 32:51:51:51:51:58 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_vxlan1 155.155.155.155 32:51:51:51:51:58 True Check Loopback ARP After Modify - vpp_term: Check ARP agent_vpp_1 vpp1_loop1 155.155.155.155 32:51:51:51:51:58 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_loop1 155.155.155.155 32:51:51:51:51:58 True Check TAP ARP After Modify - vpp_term: Check ARP agent_vpp_1 vpp1_tap1 155.155.155.155 32:51:51:51:51:58 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 vpp1_tap1 155.155.155.155 32:51:51:51:51:58 True Check Afpacket ARP After Modify - vpp_term: Check ARP agent_vpp_1 host-vpp1_veth2 155.155.155.155 32:51:51:51:51:58 True + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check ARP agent_vpp_1 host-vpp1_veth2 155.155.155.155 32:51:51:51:51:58 True *** Keywords *** diff --git a/tests/robot/suites/crudIPv6/bd_crudIPv6.robot b/tests/robot/suites/crudIPv6/bd_crudIPv6.robot index 4d38e0d0d0..c74f70220a 100644 --- a/tests/robot/suites/crudIPv6/bd_crudIPv6.robot +++ b/tests/robot/suites/crudIPv6/bd_crudIPv6.robot @@ -29,6 +29,8 @@ ${LOOPBACK_IP}= fd32::1:1:0:0:1 ${LOOPBACK_IP_PREFIX}= fd32::1:1:0:0:1/64 ${TAP_IP}= fd33::1:1:0:0:1 ${TAP_IP_PREFIX}= fd33::1:1:0:0:1/64 +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment @@ -57,8 +59,8 @@ Add BD1 Bridge Domain vpp_ctl: Put Bridge Domain node=agent_vpp_1 name=vpp1_bd1 ints=${ints} flood=true unicast=true forward=true learn=true arp_term=true Check BD1 Is Created - vat_term: BD Is Created agent_vpp_1 vpp1_memif1 vpp1_afpacket1 vpp1_vxlan1 - vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd1 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=vpp1_memif1 interface=vpp1_afpacket1 interface=vpp1_vxlan1 bvi_int=none + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: BD Is Created agent_vpp_1 vpp1_memif1 vpp1_afpacket1 vpp1_vxlan1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd1 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=vpp1_memif1 interface=vpp1_afpacket1 interface=vpp1_vxlan1 bvi_int=none Add BD2 Bridge Domain @{ints}= Create List vpp1_memif2 vpp1_vxlan2 bvi_vpp1_loop3 @@ -66,44 +68,44 @@ Add BD2 Bridge Domain vpp_ctl: Put Bridge Domain node=agent_vpp_1 name=vpp1_bd2 ints=${ints} flood=true unicast=true forward=true learn=true arp_term=true Check BD2 Is Created - vat_term: BD Is Created agent_vpp_1 vpp1_memif2 vpp1_vxlan2 bvi_vpp1_loop3 - vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd2 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=vpp1_memif2 interface=vpp1_vxlan2 interface=bvi_vpp1_loop3 bvi_int=bvi_vpp1_loop3 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: BD Is Created agent_vpp_1 vpp1_memif2 vpp1_vxlan2 bvi_vpp1_loop3 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd2 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=vpp1_memif2 interface=vpp1_vxlan2 interface=bvi_vpp1_loop3 bvi_int=bvi_vpp1_loop3 Check That BD1 Is Not Affected By Adding BD2 - vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd1 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=vpp1_memif1 interface=vpp1_afpacket1 interface=vpp1_vxlan1 bvi_int=none + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd1 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=vpp1_memif1 interface=vpp1_afpacket1 interface=vpp1_vxlan1 bvi_int=none Update BD1 @{ints}= Create List vpp1_memif1 vpp1_vxlan1 bvi_vpp1_loop2 vat_term: BD Not Exists agent_vpp_1 @{ints} vpp_ctl: Put Bridge Domain node=agent_vpp_1 name=vpp1_bd1 ints=${ints} flood=false unicast=false forward=false learn=false arp_term=false - vat_term: BD Is Deleted agent_vpp_1 vpp1_memif1 vpp1_afpacket1 vpp1_vxlan1 - vat_term: BD Is Created agent_vpp_1 vpp1_memif1 vpp1_vxlan1 bvi_vpp1_loop2 - vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd1 flood=0 unicast=0 forward=0 learn=0 arp_term=0 interface=vpp1_memif1 interface=vpp1_vxlan1 interface=bvi_vpp1_loop2 bvi_int=bvi_vpp1_loop2 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: BD Is Deleted agent_vpp_1 vpp1_memif1 vpp1_afpacket1 vpp1_vxlan1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: BD Is Created agent_vpp_1 vpp1_memif1 vpp1_vxlan1 bvi_vpp1_loop2 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd1 flood=0 unicast=0 forward=0 learn=0 arp_term=0 interface=vpp1_memif1 interface=vpp1_vxlan1 interface=bvi_vpp1_loop2 bvi_int=bvi_vpp1_loop2 Check That BD2 Is Not Affected By Updating BD1 - vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd2 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=vpp1_memif2 interface=vpp1_vxlan2 interface=bvi_vpp1_loop3 bvi_int=bvi_vpp1_loop3 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd2 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=vpp1_memif2 interface=vpp1_vxlan2 interface=bvi_vpp1_loop3 bvi_int=bvi_vpp1_loop3 Delete VXLan1 Interface vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=vpp1_vxlan1 - vxlan: Tunnel Is Deleted node=agent_vpp_1 src=192.168.1.1 dst=192.168.1.2 vni=5 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vxlan: Tunnel Is Deleted node=agent_vpp_1 src=192.168.1.1 dst=192.168.1.2 vni=5 Check That VXLan1 Interface Is Deleted From BD1 - vat_term: BD Is Deleted agent_vpp_1 vpp1_memif1 vpp1_vxlan1 bvi_vpp1_loop2 - vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd1 flood=0 unicast=0 forward=0 learn=0 arp_term=0 interface=vpp1_memif1 interface=bvi_vpp1_loop2 bvi_int=bvi_vpp1_loop2 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: BD Is Deleted agent_vpp_1 vpp1_memif1 vpp1_vxlan1 bvi_vpp1_loop2 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd1 flood=0 unicast=0 forward=0 learn=0 arp_term=0 interface=vpp1_memif1 interface=bvi_vpp1_loop2 bvi_int=bvi_vpp1_loop2 Read VXLan1 Interface vpp_ctl: Put VXLan Interface node=agent_vpp_1 name=vpp1_vxlan1 src=192.168.1.1 dst=192.168.1.2 vni=5 - vxlan: Tunnel Is Created node=agent_vpp_1 src=192.168.1.1 dst=192.168.1.2 vni=5 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vxlan: Tunnel Is Created node=agent_vpp_1 src=192.168.1.1 dst=192.168.1.2 vni=5 Check That VXLan1 Interface Is Added To BD1 - vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd1 flood=0 unicast=0 forward=0 learn=0 arp_term=0 interface=vpp1_memif1 interface=vpp1_vxlan1 interface=bvi_vpp1_loop2 bvi_int=bvi_vpp1_loop2 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd1 flood=0 unicast=0 forward=0 learn=0 arp_term=0 interface=vpp1_memif1 interface=vpp1_vxlan1 interface=bvi_vpp1_loop2 bvi_int=bvi_vpp1_loop2 Delete BD1 Bridge Domain vpp_ctl: Delete Bridge Domain agent_vpp_1 vpp1_bd1 - vat_term: BD Is Deleted agent_vpp_1 vpp1_memif1 vpp1_vxlan1 bvi_vpp1_loop2 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: BD Is Deleted agent_vpp_1 vpp1_memif1 vpp1_vxlan1 bvi_vpp1_loop2 Check That BD2 Is Not Affected By Deleting BD1 - vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd2 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=vpp1_memif2 interface=vpp1_vxlan2 interface=bvi_vpp1_loop3 bvi_int=bvi_vpp1_loop3 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_1 vpp1_bd2 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=vpp1_memif2 interface=vpp1_vxlan2 interface=bvi_vpp1_loop3 bvi_int=bvi_vpp1_loop3 Show Interfaces And Other Objects After Test vpp_term: Show Interfaces agent_vpp_1 diff --git a/tests/robot/suites/crudIPv6/inter_vrf_routing_crud_ipv6.robot b/tests/robot/suites/crudIPv6/inter_vrf_routing_crud_ipv6.robot new file mode 100644 index 0000000000..03a6c50279 --- /dev/null +++ b/tests/robot/suites/crudIPv6/inter_vrf_routing_crud_ipv6.robot @@ -0,0 +1,171 @@ +*** Settings *** + +Library OperatingSystem +Library String +#Library RequestsLibrary + +Resource ../../variables/${VARIABLES}_variables.robot +Resource ../../libraries/all_libs.robot +Resource ../../libraries/pretty_keywords.robot + +Force Tags trafficIPv4 +Suite Setup Run Keywords Discard old results Test Setup +Suite Teardown Test Teardown + +*** Variables *** +${VARIABLES}= common +${ENV}= common +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s +${FINAL_SLEEP}= 1s +${IP_1}= fd30::1:b:0:0:1 +${IP_2}= fd30::1:b:0:0:2 +${IP_3}= fd31::1:b:0:0:1 +${IP_4}= fd31::1:b:0:0:2 +${IP_5}= fd32::1:b:0:0:1 +${IP_6}= fd32::1:b:0:0:2 +${NET1}= fd30:0:0:1:: +${NET2}= fd31:0:0:1:: +${NET3}= fd32:0:0:1:: + +*** Test Cases *** +# Non default VRF table 2 used in Agent VPP Node agent_vpp_2 +Start Two Agents And Then Configure With Default And Non Default VRF + Add Agent VPP Node agent_vpp_1 + Add Agent VPP Node agent_vpp_2 + + Create Master memif0 on agent_vpp_1 with IP ${IP_1}, MAC 02:f1:be:90:00:00, key 1 and m0.sock socket + Create Slave memif0 on agent_vpp_2 with IP ${IP_2}, MAC 02:f1:be:90:00:02, key 1 and m0.sock socket + + Create Master memif1 on agent_vpp_1 with VRF 2, IP ${IP_3}, MAC 02:f1:be:90:02:00, key 1 and m1.sock socket + Create Slave memif1 on agent_vpp_2 with VRF 2, IP ${IP_4}, MAC 02:f1:be:90:02:02, key 1 and m1.sock socket + + Create Master memif2 on agent_vpp_1 with VRF 1, IP ${IP_5}, MAC 02:f1:be:90:04:00, key 1 and m2.sock socket + Create Slave memif2 on agent_vpp_2 with VRF 1, IP ${IP_6}, MAC 02:f1:be:90:04:02, key 1 and m2.sock socket + + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} List of interfaces On agent_vpp_1 Should Contain Interface memif1/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} List of interfaces On agent_vpp_2 Should Contain Interface memif1/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} List of interfaces On agent_vpp_1 Should Contain Interface memif2/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} List of interfaces On agent_vpp_2 Should Contain Interface memif2/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} List of interfaces On agent_vpp_1 Should Contain Interface memif3/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} List of interfaces On agent_vpp_2 Should Contain Interface memif3/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} IP6 Fib Table 0 On agent_vpp_1 Should Contain Route With IP ${IP_1}/128 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} IP6 Fib Table 2 On agent_vpp_1 Should Contain Route With IP ${IP_3}/128 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} IP6 Fib Table 0 On agent_vpp_2 Should Contain Route With IP ${IP_2}/128 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} IP6 Fib Table 2 On agent_vpp_2 Should Contain Route With IP ${IP_4}/128 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} IP6 Fib Table 1 On agent_vpp_1 Should Contain Route With IP ${IP_5}/128 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} IP6 Fib Table 1 On agent_vpp_2 Should Contain Route With IP ${IP_6}/128 + +Create Route For Inter Vrf Routing + Create Route On agent_vpp_1 With IP ${NET2}/64 With Next Hop ${IP_2} And Vrf Id 0 + Create Route On agent_vpp_1 With IP ${NET1}/64 With Next Hop ${IP_4} And Vrf Id 2 + Create Route On agent_vpp_2 With IP ${NET2}/64 With Next Hop VRF 2 From Vrf Id 0 And Type 1 + Create Route On agent_vpp_2 With IP ${NET1}/64 With Next Hop VRF 0 From Vrf Id 2 And Type 1 + +Config Done + No Operation + +Check Inter VRF Routing + Show IP Fib On agent_vpp_1 + IP6 Fib Table 0 On agent_vpp_1 Should Contain Route With IP ${NET2}/64 + IP6 Fib Table 0 On agent_vpp_1 Should Contain Vrf ipv6 via ${IP_2} memif1/1 + Show IP Fib On agent_vpp_2 + IP6 Fib Table 2 On agent_vpp_2 Should Contain Route With IP ${NET1}/64 + IP6 Fib Table 2 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv6-VRF: + IP6 Fib Table 0 On agent_vpp_2 Should Contain Route With IP ${NET2}/64 + IP6 Fib Table 0 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv6-VRF: + +Create Next Route For Inter Vrf Routing + Create Route On agent_vpp_2 With IP ${NET3}/64 With Next Hop VRF 1 From Vrf Id 0 And Type 1 + Create Route On agent_vpp_2 With IP ${NET3}/64 With Next Hop VRF 1 From Vrf Id 2 And Type 1 + Create Route On agent_vpp_2 With IP ${NET1}/64 With Next Hop VRF 0 From Vrf Id 1 And Type 1 + Create Route On agent_vpp_2 With IP ${NET2}/64 With Next Hop VRF 2 From Vrf Id 1 And Type 1 + +Check Inter VRF Routing Again + Show IP Fib On agent_vpp_1 + IP6 Fib Table 0 On agent_vpp_1 Should Contain Route With IP ${NET2}/64 + IP6 Fib Table 0 On agent_vpp_1 Should Contain Vrf ipv6 via ${IP_2} memif1/1 + Show IP Fib On agent_vpp_2 + IP6 Fib Table 2 On agent_vpp_2 Should Contain Route With IP ${NET1}/64 + IP6 Fib Table 2 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv6-VRF: + IP6 Fib Table 0 On agent_vpp_2 Should Contain Route With IP ${NET2}/64 + IP6 Fib Table 0 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv6-VRF: + + IP6 Fib Table 2 On agent_vpp_2 Should Contain Route With IP ${NET3}/64 + IP6 Fib Table 2 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv6-VRF: + IP6 Fib Table 0 On agent_vpp_2 Should Contain Route With IP ${NET3}/64 + IP6 Fib Table 0 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv6-VRF: + + IP6 Fib Table 1 On agent_vpp_2 Should Contain Route With IP ${NET1}/64 + IP6 Fib Table 1 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv6-VRF: + IP6 Fib Table 1 On agent_vpp_2 Should Contain Route With IP ${NET2}/64 + IP6 Fib Table 1 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv6-VRF: + +Delete Route VRF 1 + vpp_ctl: Delete Route agent_vpp_2 1 ${NET1} 64 + vpp_ctl: Delete Route agent_vpp_2 1 ${NET2} 64 + vpp_ctl: Delete Route agent_vpp_2 0 ${NET3} 64 + vpp_ctl: Delete Route agent_vpp_2 2 ${NET3} 64 + +Check State After Delete + Show IP Fib On agent_vpp_1 + IP6 Fib Table 0 On agent_vpp_1 Should Contain Route With IP ${NET2}/64 + IP6 Fib Table 0 On agent_vpp_1 Should Contain Vrf ipv6 via ${IP_2} memif1/1 + Show IP Fib On agent_vpp_2 + IP6 Fib Table 2 On agent_vpp_2 Should Contain Route With IP ${NET1}/64 + IP6 Fib Table 2 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv6-VRF: + IP6 Fib Table 0 On agent_vpp_2 Should Contain Route With IP ${NET2}/64 + IP6 Fib Table 0 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv6-VRF: + + ${status}= Run Keyword And Return Status IP6 Fib Table 2 On agent_vpp_2 Should Contain Route With IP ${NET3}/64 + Should Not Be True ${status} + + ${status}= Run Keyword And Return Status IP6 Fib Table 0 On agent_vpp_2 Should Contain Route With IP ${NET3}/64 + Should Not Be True ${status} + + ${status}= Run Keyword And Return Status IP6 Fib Table 1 On agent_vpp_2 Should Contain Route With IP ${NET1}/64 + Should Not Be True ${status} + + ${status}= Run Keyword And Return Status IP6 Fib Table 1 On agent_vpp_2 Should Contain Route With IP ${NET2}/64 + Should Not Be True ${status} + + ${status}= Run Keyword And Return Status IP6 Fib Table 1 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv6-VRF: + Should Not Be True ${status} + +Update Inter Vrf Route + Create Route On agent_vpp_2 With IP ${NET1}/64 With Next Hop VRF 0 From Vrf Id 1 And Type 1 + Create Route On agent_vpp_2 With IP ${NET1}/64 With Next Hop VRF 2 From Vrf Id 1 And Type 1 + +Check Route After Update + Show IP Fib On agent_vpp_2 + IP6 Fib Table 1 On agent_vpp_2 Should Contain Route With IP ${NET1}/64 + IP6 Fib Table 1 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv6-VRF:2 + +#can use in debug +#Check Route With Ping +# Ping On agent_vpp_1 With IP ${IP_4}, Source memif1/1 +# Ping On agent_vpp_1 With IP ${IP_4}, Source memif2/1 +# Ping On agent_vpp_1 With IP ${IP_3}, Source memif1/1 +# + +Final Sleep For Manual Checking + Sleep ${FINAL_SLEEP} + +*** Keywords *** +List of interfaces On ${node} Should Contain Interface ${int} + Log many ${node} ${int} + ${out}= vpp_term: Show Interfaces ${node} + log many ${out} + Should Match Regexp ${out} ${int} + +IP Fib Table ${table_id} On ${node} Should Contain Vrf ${inter_vrf_string} + Log many ${table_id} ${node} ${inter_vrf_string} + ${out}= vpp_term: Show IP Fib Table ${node} ${table_id} + log many ${out} + Should Contain ${out} ${inter_vrf_string} + +IP6 Fib Table ${table_id} On ${node} Should Contain Vrf ${inter_vrf_string} + Log many ${table_id} ${node} ${inter_vrf_string} + ${out}= vpp_term: Show IP6 Fib Table ${node} ${table_id} + log many ${out} + Should Contain ${out} ${inter_vrf_string} diff --git a/tests/robot/suites/crudIPv6/l2xconnect_crudIPv6.robot b/tests/robot/suites/crudIPv6/l2xconnect_crudIPv6.robot index 0f358010b0..a6b327ee69 100644 --- a/tests/robot/suites/crudIPv6/l2xconnect_crudIPv6.robot +++ b/tests/robot/suites/crudIPv6/l2xconnect_crudIPv6.robot @@ -17,9 +17,9 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${FINAL_SLEEP}= 5s -${SYNC_SLEEP}= 10s -${RESYNC_SLEEP}= 20s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s +${RESYNC_SLEEP}= 16s ${VETH1_MAC}= 1a:00:00:11:11:11 ${VETH2_MAC}= 2a:00:00:22:22:22 ${AFP1_MAC}= a2:01:01:01:01:01 @@ -34,7 +34,6 @@ ${TAP_IP}= fd33::1:1:0:0:1 Configure Environment [Tags] setup Configure Environment 5 - Sleep ${SYNC_SLEEP} Show Interfaces Before Setup vpp_term: Show Interfaces agent_vpp_1 @@ -48,46 +47,46 @@ Add Veth2 Interface vpp_ctl: Put Veth Interface node=agent_vpp_1 name=vpp1_veth2 mac=${VETH2_MAC} peer=vpp1_veth1 Check That Veth1 And Veth2 Interfaces Are Created - linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_MAC} - linux: Interface Is Created node=agent_vpp_1 mac=${VETH2_MAC} - linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv6=${VETH_IP}/${PREFIX} mtu=1500 state=up - linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH2_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv6=${VETH_IP}/${PREFIX} mtu=1500 state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up Add Memif Interface vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=true id=1 ip=${MEMIF_IP} prefix=${PREFIX} socket=default.sock Check Memif Interface Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=1 ipv6=${MEMIF_IP}/${PREFIX} connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=1 ipv6=${MEMIF_IP}/${PREFIX} connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock Add VXLan Interface vpp_ctl: Put VXLan Interface node=agent_vpp_1 name=vpp1_vxlan1 src=${MEMIF_IP} dst=${VXLAN_IP} vni=5 Check VXLan Interface Created - vxlan: Tunnel Is Created node=agent_vpp_1 src=${MEMIF_IP} dst=${VXLAN_IP} vni=5 - vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan1 enabled=1 src=${MEMIF_IP} dst=${VXLAN_IP} vni=5 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vxlan: Tunnel Is Created node=agent_vpp_1 src=${MEMIF_IP} dst=${VXLAN_IP} vni=5 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan1 enabled=1 src=${MEMIF_IP} dst=${VXLAN_IP} vni=5 Add Loopback1 Interface vpp_ctl: Put Loopback Interface With IP node=agent_vpp_1 name=vpp1_loop1 mac=12:21:21:11:11:11 ip=${LOOPB_IP} prefix=${PREFIX} mtu=1400 Check Loopback1 Interface Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=12:21:21:11:11:11 - vat_term: Check Loopback Interface State agent_vpp_1 vpp1_loop1 enabled=1 mac=12:21:21:11:11:11 mtu=1400 ipv6=${LOOPB_IP}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=12:21:21:11:11:11 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 vpp1_loop1 enabled=1 mac=12:21:21:11:11:11 mtu=1400 ipv6=${LOOPB_IP}/${PREFIX} Add Loopback2 Interface vpp_ctl: Put Loopback Interface With IP node=agent_vpp_1 name=vpp1_loop2 mac=22:21:21:11:11:11 ip=${LOOPB2_IP} prefix=${PREFIX} mtu=1400 Check Loopback2 Interface Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=22:21:21:11:11:11 - vat_term: Check Loopback Interface State agent_vpp_1 vpp1_loop2 enabled=1 mac=22:21:21:11:11:11 mtu=1400 ipv6=${LOOPB2_IP}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=22:21:21:11:11:11 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 vpp1_loop2 enabled=1 mac=22:21:21:11:11:11 mtu=1400 ipv6=${LOOPB2_IP}/${PREFIX} Add Tap Interface vpp_ctl: Put TAP Interface With IP node=agent_vpp_1 name=vpp1_tap1 mac=32:21:21:11:11:11 ip=${TAP_IP} prefix=${PREFIX} host_if_name=linux_vpp1_tap1 Check TAP Interface Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=32:21:21:11:11:11 - vpp_term: Check TAP IP6 interface State agent_vpp_1 vpp1_tap1 mac=32:21:21:11:11:11 ipv6=${TAP_IP}/${PREFIX} state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=32:21:21:11:11:11 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check TAP IP6 interface State agent_vpp_1 vpp1_tap1 mac=32:21:21:11:11:11 ipv6=${TAP_IP}/${PREFIX} state=up Check Stuff Show Interfaces And Other Objects @@ -98,8 +97,8 @@ Add L2XConnect1 for Memif and Loopback1 Check L2XConnect1 Memif and Loopback1 in XConnect mode ${out}= vpp_term: Show Interface Mode agent_vpp_1 - Should Contain ${out} l2 xconnect memif1/1 loop0 - Should Contain ${out} l2 xconnect loop0 memif1/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect memif1/1 loop0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect loop0 memif1/1 Add L2XConnect2 for Tap and Loopback2 vpp_ctl: Put L2XConnect agent_vpp_1 vpp1_tap1 vpp1_loop2 @@ -107,10 +106,10 @@ Add L2XConnect2 for Tap and Loopback2 Check L2XConnect2 and L2XConnect1 still configured ${out}= vpp_term: Show Interface Mode agent_vpp_1 - Should Contain ${out} l2 xconnect memif1/1 loop0 - Should Contain ${out} l2 xconnect loop0 memif1/1 - Should Contain ${out} l2 xconnect tapcli-0 loop1 - Should Contain ${out} l2 xconnect loop1 tapcli-0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect memif1/1 loop0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect loop0 memif1/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect tapcli-0 loop1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect loop1 tapcli-0 Modify L2XConnect1 vpp_ctl: Delete L2XConnect agent_vpp_1 vpp1_memif1 @@ -119,11 +118,11 @@ Modify L2XConnect1 Check L2XConnect1 Modified and L2XConnect2 still configured ${out}= vpp_term: Show Interface Mode agent_vpp_1 - Should Contain ${out} l2 xconnect vxlan_tunnel0 loop0 - Should Contain ${out} l2 xconnect loop0 vxlan_tunnel0 - Should Contain ${out} l2 xconnect tapcli-0 loop1 - Should Contain ${out} l2 xconnect loop1 tapcli-0 - Should Contain ${out} l3 memif1/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect vxlan_tunnel0 loop0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect loop0 vxlan_tunnel0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect tapcli-0 loop1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect loop1 tapcli-0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l3 memif1/1 Delete L2XConnect1 vpp_ctl: Delete L2XConnect agent_vpp_1 vpp1_vxlan1 @@ -131,11 +130,11 @@ Delete L2XConnect1 Check L2XConnect1 Deleted and L2XConnect2 still configured ${out}= vpp_term: Show Interface Mode agent_vpp_1 - Should Contain ${out} l3 memif1/1 - Should Contain ${out} l3 loop0 - Should Contain ${out} l3 vxlan_tunnel0 - Should Contain ${out} l2 xconnect tapcli-0 loop1 - Should Contain ${out} l2 xconnect loop1 tapcli-0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l3 memif1/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l3 loop0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l3 vxlan_tunnel0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect tapcli-0 loop1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l2 xconnect loop1 tapcli-0 Delete L2XConnect2 @@ -144,11 +143,11 @@ Delete L2XConnect2 Check L2XConnect1 and L2XConnect2 Deleted ${out}= vpp_term: Show Interface Mode agent_vpp_1 - Should Contain ${out} l3 memif1/1 - Should Contain ${out} l3 loop0 - Should Contain ${out} l3 vxlan_tunnel0 - Should Contain ${out} l3 tapcli-0 - Should Contain ${out} l3 loop1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l3 memif1/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l3 loop0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l3 vxlan_tunnel0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l3 tapcli-0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} l3 loop1 *** Keywords *** Show Interfaces And Other Objects diff --git a/tests/robot/suites/crudIPv6/linux_arp_crudIPv6.robot b/tests/robot/suites/crudIPv6/linux_arp_crudIPv6.robot index cf7cd80f57..d0dcea63d4 100644 --- a/tests/robot/suites/crudIPv6/linux_arp_crudIPv6.robot +++ b/tests/robot/suites/crudIPv6/linux_arp_crudIPv6.robot @@ -17,7 +17,8 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${SYNC_SLEEP}= 6s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s ${VETH1_MAC}= 1a:00:00:11:11:11 ${VETH2_MAC}= 2a:00:00:22:22:22 ${AFP1_MAC}= a2:01:01:01:01:01 @@ -49,49 +50,47 @@ Add Veth2 Interface Show Info Check That Veth1 And Veth2 Interfaces Are Created - linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_MAC} - linux: Interface Is Created node=agent_vpp_1 mac=${VETH2_MAC} - linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv6=${VETH1_IP_PREFIX} mtu=1500 state=up - linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH2_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv6=${VETH1_IP_PREFIX} mtu=1500 state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up ADD Afpacket Interface vpp_ctl: Put Afpacket Interface node=agent_vpp_1 name=vpp1_afpacket1 mac=a2:a1:a1:a1:a1:a1 host_int=vpp1_veth2 Check AFpacket Interface Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=a2:a1:a1:a1:a1:a1 - vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket1 enabled=1 mac=a2:a1:a1:a1:a1:a1 - Sleep ${SYNC_SLEEP} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=a2:a1:a1:a1:a1:a1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Afpacket Interface State agent_vpp_1 vpp1_afpacket1 enabled=1 mac=a2:a1:a1:a1:a1:a1 + Add ARPs vpp_ctl: Put Linux ARP agent_vpp_1 vpp1_veth1 veth1_arp ${ARP_IP1} 32:51:51:51:51:51 vpp_ctl: Put Linux ARP agent_vpp_1 vpp1_veth2 veth2_arp ${ARP_IP2} 32:51:51:51:51:52 vpp_ctl: Put Linux ARP agent_vpp_1 lo loopback_arp ${ARP_IP2} 32:51:51:51:51:52 #vpp_ctl: Put Linux ARP agent_vpp_1 eth0 eth_arp ${ARP_IP2} 32:51:51:51:51:52 - Sleep ${SYNC_SLEEP} Check ARPSs ${out}= Execute In Container agent_vpp_1 ip neigh Log ${out} - Should Contain ${out} ${ARP_IP2} dev vpp1_veth2 lladdr 32:51:51:51:51:52 PERMANENT - Should Contain ${out} ${ARP_IP1} dev vpp1_veth1 lladdr 32:51:51:51:51:51 PERMANENT + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} ${ARP_IP2} dev vpp1_veth2 lladdr 32:51:51:51:51:52 PERMANENT + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} ${ARP_IP1} dev vpp1_veth1 lladdr 32:51:51:51:51:51 PERMANENT #Should Contain ${out} ${ARP_IP2} dev eth0 lladdr 32:51:51:51:51:52 PERMANENT - Should Contain ${out} ${ARP_IP2} dev lo lladdr 32:51:51:51:51:52 PERMANENT + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} ${ARP_IP2} dev lo lladdr 32:51:51:51:51:52 PERMANENT Change ARPs vpp_ctl: Put Linux ARP agent_vpp_1 vpp1_veth1 veth1_arp ${ARP_IP3} 32:61:51:51:51:51 vpp_ctl: Put Linux ARP agent_vpp_1 vpp1_veth2 veth2_arp ${ARP_IP4} 32:61:51:51:51:52 vpp_ctl: Put Linux ARP agent_vpp_1 lo loopback_arp ${ARP_IP4} 32:61:51:51:51:52 #vpp_ctl: Put Linux ARP agent_vpp_1 eth0 eth_arp ${ARP_IP4} 32:61:51:51:51:52 - Sleep ${SYNC_SLEEP} Check ARPSs Again ${out}= Execute In Container agent_vpp_1 ip neigh Log ${out} - Should Contain ${out} ${ARP_IP4} dev vpp1_veth2 lladdr 32:61:51:51:51:52 PERMANENT - Should Contain ${out} ${ARP_IP3} dev vpp1_veth1 lladdr 32:61:51:51:51:51 PERMANENT + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} ${ARP_IP4} dev vpp1_veth2 lladdr 32:61:51:51:51:52 PERMANENT + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} ${ARP_IP3} dev vpp1_veth1 lladdr 32:61:51:51:51:51 PERMANENT #Should Contain ${out} ${ARP_IP4} dev eth0 lladdr 32:61:51:51:51:52 PERMANENT - Should Contain ${out} ${ARP_IP4} dev lo lladdr 32:61:51:51:51:52 PERMANENT + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Contain ${out} ${ARP_IP4} dev lo lladdr 32:61:51:51:51:52 PERMANENT Delete ARPs vpp_ctl: Delete Linux ARP agent_vpp_1 veth1_arp @@ -102,10 +101,10 @@ Delete ARPs Check ARPSs After Delete ${out}= Execute In Container agent_vpp_1 ip neigh Log ${out} - Should Not Contain ${out} ${ARP_IP4} dev vpp1_veth2 lladdr 32:61:51:51:51:52 PERMANENT - Should Not Contain ${out} ${ARP_IP3} dev vpp1_veth1 lladdr 32:61:51:51:51:51 PERMANENT + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Not Contain ${out} ${ARP_IP4} dev vpp1_veth2 lladdr 32:61:51:51:51:52 PERMANENT + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Not Contain ${out} ${ARP_IP3} dev vpp1_veth1 lladdr 32:61:51:51:51:51 PERMANENT #Should Not Contain ${out} ${ARP_IP4} dev eth0 lladdr 32:61:51:51:51:52 PERMANENT - Should Not Contain ${out} ${ARP_IP4} dev lo lladdr 32:61:51:51:51:52 PERMANENT + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Should Not Contain ${out} ${ARP_IP4} dev lo lladdr 32:61:51:51:51:52 PERMANENT *** Keywords *** diff --git a/tests/robot/suites/crudIPv6/linux_ip_route_crudIPv6.robot b/tests/robot/suites/crudIPv6/linux_ip_route_crudIPv6.robot index 4dd56507e6..4c9b82596b 100644 --- a/tests/robot/suites/crudIPv6/linux_ip_route_crudIPv6.robot +++ b/tests/robot/suites/crudIPv6/linux_ip_route_crudIPv6.robot @@ -17,7 +17,8 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${CONFIG_SLEEP}= 10s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s ${RESYNC_SLEEP}= 15s # wait for resync vpps after restart ${RESYNC_WAIT}= 30s @@ -40,11 +41,9 @@ Setup Interfaces vpp_ctl: Put Veth Interface Via Linux Plugin node=agent_vpp_1 namespace=ns1 name=ns1_veth1 host_if_name=ns1_veth1_linux mac=d2:74:8c:12:67:d2 peer=ns2_veth2 ip=${VETH_IP1} prefix=64 vpp_ctl: Put Veth Interface Via Linux Plugin node=agent_vpp_1 namespace=ns2 name=ns2_veth2 host_if_name=ns2_veth2_linux mac=92:c7:42:67:ab:cd peer=ns1_veth1 ip=${VETH_IP2} prefix=64 - Sleep ${CONFIG_SLEEP} - Chceck Interfaces - Check Linux Interfaces node=agent_vpp_1 namespace=ns1 interface=ns1_veth1 - Check Linux Interfaces node=agent_vpp_1 namespace=ns2 interface=ns2_veth2 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Interfaces node=agent_vpp_1 namespace=ns1 interface=ns1_veth1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Interfaces node=agent_vpp_1 namespace=ns2 interface=ns2_veth2 Ping # This should work by default after veth interface setup @@ -57,20 +56,18 @@ Create Linux Routes vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=ns1 interface=ns1_veth1 routename=pinginggoogl ip=${GOOGLE_IP} prefix=128 next_hop=${VETH_IP1} vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=ns2 interface=ns2_veth2 routename=pinging9 ip=${QUAD9_IP} prefix=128 next_hop=${VETH_IP2} - Sleep ${CONFIG_SLEEP} - Check Linux Routes - Check Linux Routes node=agent_vpp_1 namespace=ns1 ip=${VETH_IP2} - Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=${VETH_IP1} - Check Linux Routes node=agent_vpp_1 namespace=ns1 ip=${GOOGLE_IP} - Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=${QUAD9_IP} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns1 ip=${VETH_IP2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=${VETH_IP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns1 ip=${GOOGLE_IP} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=${QUAD9_IP} # created routes should not exist in other namespace - Check Removed Linux Route node=agent_vpp_1 namespace=ns2 ip=${VETH_IP2} - Check Removed Linux Route node=agent_vpp_1 namespace=ns1 ip=${VETH_IP1} - Check Removed Linux Route node=agent_vpp_1 namespace=ns2 ip=${GOOGLE_IP} - Check Removed Linux Route node=agent_vpp_1 namespace=ns1 ip=${QUAD9_IP} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Removed Linux Route node=agent_vpp_1 namespace=ns2 ip=${VETH_IP2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Removed Linux Route node=agent_vpp_1 namespace=ns1 ip=${VETH_IP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Removed Linux Route node=agent_vpp_1 namespace=ns2 ip=${GOOGLE_IP} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Removed Linux Route node=agent_vpp_1 namespace=ns1 ip=${QUAD9_IP} Read Route Information From Setup Database vpp_ctl: Get Linux Route As Json node=agent_vpp_1 routename=pingingveth2 @@ -81,57 +78,52 @@ Read Route Information From Setup Database Change Linux Routes Without Deleting Key (Changing Metric) # changing of gateway - this is incorrect/ the record would not be put in the database - Let us change metric vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=ns1 interface=ns1_veth1 routename=pinginggoogl ip=${GOOGLE_IP} prefix=128 next_hop=${VETH_IP1} metric=55 - Sleep ${CONFIG_SLEEP} + # testing if there is the new metric - Check Linux Routes Metric node=agent_vpp_1 namespace=ns1 ip=${GOOGLE_IP} metric=55 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes Metric node=agent_vpp_1 namespace=ns1 ip=${GOOGLE_IP} metric=55 Change Linux Routes At First Deleting Key And Putting The Same Secondly Deleting Key Then Putting It To Other Namespace vpp_ctl: Delete Linux Route node=agent_vpp_1 routename=pinging9 - Sleep ${CONFIG_SLEEP} - Check Removed Linux Route node=agent_vpp_1 namespace=ns2 ip=${QUAD9_IP} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Removed Linux Route node=agent_vpp_1 namespace=ns2 ip=${QUAD9_IP} # we create exactly the same as deleted route vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=ns2 interface=ns2_veth2 routename=pinging9 ip=${QUAD9_IP} prefix=128 next_hop=${VETH_IP2} - Sleep ${CONFIG_SLEEP} - Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=${QUAD9_IP} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=${QUAD9_IP} # delete again vpp_ctl: Delete Linux Route node=agent_vpp_1 routename=pinging9 - Sleep ${CONFIG_SLEEP} - Check Removed Linux Route node=agent_vpp_1 namespace=ns2 ip=${QUAD9_IP} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Removed Linux Route node=agent_vpp_1 namespace=ns2 ip=${QUAD9_IP} # we try to transfer route to other namespace - there is also need to change appropriately gateway vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=ns1 interface=ns1_veth1 routename=pinging9 ip=${QUAD9_IP} prefix=128 next_hop=${VETH_IP1} - Sleep ${CONFIG_SLEEP} - Check Removed Linux Route node=agent_vpp_1 namespace=ns2 ip=${QUAD9_IP} - Check Linux Routes Gateway node=agent_vpp_1 namespace=ns1 ip=${QUAD9_IP} next_hop=${VETH_IP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Removed Linux Route node=agent_vpp_1 namespace=ns2 ip=${QUAD9_IP} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes Gateway node=agent_vpp_1 namespace=ns1 ip=${QUAD9_IP} next_hop=${VETH_IP1} At first create route and after that create inteface in namespace 3 vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=ns3 interface=ns3_veth3 routename=pingingns2_veth3 ip=${VETH_IP4} prefix=128 next_hop=${VETH_IP3} vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=ns3 interface=ns3_veth3 routename=pingingns2_veth2 ip=${VETH_IP2} prefix=128 next_hop=${VETH_IP3} vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=ns3 interface=ns3_veth3 routename=pingingns1_veth1 ip=${VETH_IP1} prefix=128 next_hop=${VETH_IP3} vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=ns2 interface=ns2_veth3 routename=pingingns3_veth3 ip=${VETH_IP3} prefix=128 next_hop=${VETH_IP4} - Sleep ${CONFIG_SLEEP} vpp_ctl: Put Veth Interface Via Linux Plugin node=agent_vpp_1 namespace=ns3 name=ns3_veth3 host_if_name=ns3_veth3_linux mac=92:c7:42:67:ab:ce peer=ns2_veth3 ip=${VETH_IP3} vpp_ctl: Put Veth Interface Via Linux Plugin node=agent_vpp_1 namespace=ns2 name=ns2_veth3 host_if_name=ns2_veth3_linux mac=92:c7:42:67:ab:cf peer=ns3_veth3 ip=${VETH_IP4} - Sleep ${CONFIG_SLEEP} - Check Linux Interfaces node=agent_vpp_1 namespace=ns3 interface=ns3_veth3 - Check Linux Interfaces node=agent_vpp_1 namespace=ns2 interface=ns2_veth3 + + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Interfaces node=agent_vpp_1 namespace=ns3 interface=ns3_veth3 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Interfaces node=agent_vpp_1 namespace=ns2 interface=ns2_veth3 Ping6 in namespace node=agent_vpp_1 namespace=ns2 ip=${VETH_IP3} Ping6 in namespace node=agent_vpp_1 namespace=ns3 ip=${VETH_IP4} - Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=${VETH_IP1} - Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=${VETH_IP2} - Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=${VETH_IP4} - Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=${VETH_IP3} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=${VETH_IP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=${VETH_IP2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=${VETH_IP4} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=${VETH_IP3} # tested also above, but repeat after giving exact routes Ping6 in namespace node=agent_vpp_1 namespace=ns3 ip=${VETH_IP4} @@ -148,14 +140,14 @@ At first create route and after that create inteface in namespace 3 # Ping6 in namespace node=agent_vpp_1 namespace=ns1 ip=192.169.22.3 Check linux Routes On VPP1 - Check Linux Routes node=agent_vpp_1 namespace=ns1 ip=${VETH_IP2} - Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=${VETH_IP1} - Check Linux Routes Gateway node=agent_vpp_1 namespace=ns1 ip=${GOOGLE_IP} next_hop=${VETH_IP1} - Check Linux Routes Gateway node=agent_vpp_1 namespace=ns1 ip=${QUAD9_IP} next_hop=${VETH_IP1} - Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=${VETH_IP1} - Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=${VETH_IP2} - Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=${VETH_IP4} - Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=${VETH_IP3} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns1 ip=${VETH_IP2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=${VETH_IP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes Gateway node=agent_vpp_1 namespace=ns1 ip=${GOOGLE_IP} next_hop=${VETH_IP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes Gateway node=agent_vpp_1 namespace=ns1 ip=${QUAD9_IP} next_hop=${VETH_IP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=${VETH_IP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=${VETH_IP2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns3 ip=${VETH_IP4} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes node=agent_vpp_1 namespace=ns2 ip=${VETH_IP3} Remove VPP Nodes Remove All Nodes diff --git a/tests/robot/suites/crudIPv6/loopback_crudIPv6.robot b/tests/robot/suites/crudIPv6/loopback_crudIPv6.robot index 24341737e8..b834ea2f7f 100644 --- a/tests/robot/suites/crudIPv6/loopback_crudIPv6.robot +++ b/tests/robot/suites/crudIPv6/loopback_crudIPv6.robot @@ -27,6 +27,8 @@ ${IP_LOOP1_2}= fd30::1:e:0:0:2 ${IP_LOOP2}= fd31::1:e:0:0:1 ${PREFIX}= 64 ${MTU}= 4800 +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment @@ -41,35 +43,35 @@ Add Loopback1 Interface vpp_ctl: Put Loopback Interface With IP node=agent_vpp_1 name=${NAME_LOOP1} mac=${MAC_LOOP1} ip=${IP_LOOP1} prefix=${PREFIX} mtu=${MTU} enabled=true Check Loopback1 Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_LOOP1} - vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP1} enabled=1 mac=${MAC_LOOP1} mtu=${MTU} ipv6=${IP_LOOP1}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_LOOP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP1} enabled=1 mac=${MAC_LOOP1} mtu=${MTU} ipv6=${IP_LOOP1}/${PREFIX} Add Loopback2 Interface vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_LOOP2} vpp_ctl: Put Loopback Interface With IP node=agent_vpp_1 name=${NAME_LOOP2} mac=${MAC_LOOP2} ip=${IP_LOOP2} prefix=${PREFIX} mtu=${MTU} enabled=true Check Loopback2 Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_LOOP2} - vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP2} enabled=1 mac=${MAC_LOOP2} mtu=${MTU} ipv6=${IP_LOOP2}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_LOOP2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP2} enabled=1 mac=${MAC_LOOP2} mtu=${MTU} ipv6=${IP_LOOP2}/${PREFIX} Check Loopback1 Is Still Configured - vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP1} enabled=1 mac=${MAC_LOOP1} mtu=${MTU} ipv6=${IP_LOOP1}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP1} enabled=1 mac=${MAC_LOOP1} mtu=${MTU} ipv6=${IP_LOOP1}/${PREFIX} Update Loopback1 vpp_ctl: Put Loopback Interface With IP node=agent_vpp_1 name=${NAME_LOOP1} mac=${MAC_LOOP1_2} ip=${IP_LOOP1_2} prefix=${PREFIX} mtu=${MTU} enabled=true - vpp_term: Interface Is Deleted node=agent_vpp_1 mac=${MAC_LOOP1} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_LOOP1_2} - vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP1} enabled=1 mac=${MAC_LOOP1_2} mtu=${MTU} ipv6=${IP_LOOP1_2}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_1 mac=${MAC_LOOP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_LOOP1_2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP1} enabled=1 mac=${MAC_LOOP1_2} mtu=${MTU} ipv6=${IP_LOOP1_2}/${PREFIX} Check Loopback2 Is Not Changed - vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP2} enabled=1 mac=${MAC_LOOP2} mtu=${MTU} ipv6=${IP_LOOP2}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP2} enabled=1 mac=${MAC_LOOP2} mtu=${MTU} ipv6=${IP_LOOP2}/${PREFIX} Delete Loopback1_2 Interface vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=${NAME_LOOP1} - vpp_term: Interface Is Deleted node=agent_vpp_1 mac=${MAC_LOOP1_2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_1 mac=${MAC_LOOP1_2} Check Loopback2 Interface Is Still Configured - vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP2} enabled=1 mac=${MAC_LOOP2} mtu=${MTU} ipv6=${IP_LOOP2}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 ${NAME_LOOP2} enabled=1 mac=${MAC_LOOP2} mtu=${MTU} ipv6=${IP_LOOP2}/${PREFIX} Show Interfaces And Other Objects After Setup vpp_term: Show Interfaces agent_vpp_1 diff --git a/tests/robot/suites/crudIPv6/memif_crudIPv6.robot b/tests/robot/suites/crudIPv6/memif_crudIPv6.robot index 9de411989b..51f535a431 100644 --- a/tests/robot/suites/crudIPv6/memif_crudIPv6.robot +++ b/tests/robot/suites/crudIPv6/memif_crudIPv6.robot @@ -30,7 +30,8 @@ ${IP_4}= fd31::1:e:0:0:2 ${IP_5}= fd32::1:e:0:0:1 ${IP_6}= fd32::1:e:0:0:2 ${PREFIX}= 64 - +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment [Tags] setup @@ -44,83 +45,83 @@ Add VPP1_memif1 Interface vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=${MEMIF11_MAC} master=true id=1 ip=${IP_1} prefix=64 socket=default.sock Check That VPP1_memif1 Is Created But Not Connected - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MEMIF11_MAC} - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_MAC} role=master id=1 ipv6=${IP_1}/64 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MEMIF11_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_MAC} role=master id=1 ipv6=${IP_1}/64 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock Add VPP2_memif1 Interface vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MEMIF21_MAC} vpp_ctl: Put Memif Interface With IP node=agent_vpp_2 name=vpp2_memif1 mac=${MEMIF21_MAC} master=false id=1 ip=${IP_2} prefix=64 socket=default.sock Check That VPP2_memif1 Is Created And Connected With VPP1_memif1 - vpp_term: Interface Is Created node=agent_vpp_2 mac=${MEMIF21_MAC} - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_MAC} role=slave id=1 ipv6=${IP_2}/64 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_MAC} role=master id=1 ipv6=${IP_1}/64 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_2 mac=${MEMIF21_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_MAC} role=slave id=1 ipv6=${IP_2}/64 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_MAC} role=master id=1 ipv6=${IP_1}/64 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock Add VPP1_memif2 Interface vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MEMIF12_MAC} vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif2 mac=${MEMIF12_MAC} master=true id=2 ip=${IP_3} prefix=64 socket=default.sock Check That VPP1_memif2 Is Created But Not Connected - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MEMIF12_MAC} - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=${MEMIF12_MAC} role=master id=2 ipv6=${IP_3}/64 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MEMIF12_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=${MEMIF12_MAC} role=master id=2 ipv6=${IP_3}/64 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock Add VPP2_memif2 Interface vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MEMIF22_MAC} vpp_ctl: Put Memif Interface With IP node=agent_vpp_2 name=vpp2_memif2 mac=${MEMIF22_MAC} master=false id=2 ip=${IP_4} prefix=64 socket=default.sock Check That VPP2_memif2 Is Created And Connected With VPP1_memif2 - vpp_term: Interface Is Created node=agent_vpp_2 mac=${MEMIF22_MAC} - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif2 mac=${MEMIF22_MAC} role=slave id=2 ipv6=${IP_4}/64 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=${MEMIF12_MAC} role=master id=2 ipv6=${IP_3}/64 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_2 mac=${MEMIF22_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif2 mac=${MEMIF22_MAC} role=slave id=2 ipv6=${IP_4}/64 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=${MEMIF12_MAC} role=master id=2 ipv6=${IP_3}/64 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock Check That VPP1_memif1 And VPP2_memif1 Interfaces Are Not Affected By VPP1_memif2 And VPP2_memif2 Interfaces - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_MAC} role=master id=1 ipv6=${IP_1}/64 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_MAC} role=slave id=1 ipv6=${IP_2}/64 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_MAC} role=master id=1 ipv6=${IP_1}/64 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_MAC} role=slave id=1 ipv6=${IP_2}/64 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock Update VPP1_memif1 Interface vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=${MEMIF11_SEC_MAC} master=true id=1 ip=${IP_5} prefix=30 socket=default.sock - vpp_term: Interface Is Deleted node=agent_vpp_1 mac=${MEMIF11_MAC} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MEMIF11_SEC_MAC} - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_SEC_MAC} role=master id=1 ipv6=${IP_5}/30 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_1 mac=${MEMIF11_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MEMIF11_SEC_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_SEC_MAC} role=master id=1 ipv6=${IP_5}/30 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock Check That VPP2_memif1 Is Still Configured And Connected - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_MAC} role=slave id=1 ipv6=${IP_2}/64 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_MAC} role=slave id=1 ipv6=${IP_2}/64 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock Check That VPP1_memif2 And VPP2_memif2 Are Not Affected By VPP1_memif1 Update - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif2 mac=${MEMIF22_MAC} role=slave id=2 ipv6=${IP_4}/64 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=${MEMIF12_MAC} role=master id=2 ipv6=${IP_3}/64 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif2 mac=${MEMIF22_MAC} role=slave id=2 ipv6=${IP_4}/64 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=${MEMIF12_MAC} role=master id=2 ipv6=${IP_3}/64 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock Update VPP2_memif1 Interface vpp_ctl: Put Memif Interface With IP node=agent_vpp_2 name=vpp2_memif1 mac=${MEMIF21_SEC_MAC} master=false id=1 ip=${IP_6} prefix=64 socket=default.sock - vpp_term: Interface Is Deleted node=agent_vpp_2 mac=${MEMIF21_MAC} - vpp_term: Interface Is Created node=agent_vpp_2 mac=${MEMIF21_SEC_MAC} - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_SEC_MAC} role=slave id=1 ipv6=${IP_6}/64 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_2 mac=${MEMIF21_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_2 mac=${MEMIF21_SEC_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_SEC_MAC} role=slave id=1 ipv6=${IP_6}/64 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock Check That VPP1_memif1 Is Still Configured And Connected - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_SEC_MAC} role=master id=1 ipv6=${IP_5}/30 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_SEC_MAC} role=master id=1 ipv6=${IP_5}/30 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock Check That VPP1_memif2 And VPP2_memif2 Are Not Affected By VPP2_memif1 Update - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif2 mac=${MEMIF22_MAC} role=slave id=2 ipv6=${IP_4}/64 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=${MEMIF12_MAC} role=master id=2 ipv6=${IP_3}/64 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif2 mac=${MEMIF22_MAC} role=slave id=2 ipv6=${IP_4}/64 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=${MEMIF12_MAC} role=master id=2 ipv6=${IP_3}/64 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock Delete VPP1_memif2 Interface vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=vpp1_memif2 - vpp_term: Interface Is Deleted node=agent_vpp_1 mac=${MEMIF12_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_1 mac=${MEMIF12_MAC} Check That VPP2_memif2 Interface Is Disconnected - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif2 mac=${MEMIF22_MAC} role=slave id=2 ipv6=${IP_4}/64 connected=0 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif2 mac=${MEMIF22_MAC} role=slave id=2 ipv6=${IP_4}/64 connected=0 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock Check That VPP1_memif1 And VPP2_memif1 Are Not Affected By VPP1_memif2 Delete - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_SEC_MAC} role=master id=1 ipv6=${IP_5}/30 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_SEC_MAC} role=slave id=1 ipv6=${IP_6}/64 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_SEC_MAC} role=master id=1 ipv6=${IP_5}/30 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_SEC_MAC} role=slave id=1 ipv6=${IP_6}/64 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock Delete VPP2_memif2 Interface vpp_ctl: Delete VPP Interface node=agent_vpp_2 name=vpp2_memif2 - vpp_term: Interface Is Deleted node=agent_vpp_2 mac=${MEMIF22_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_2 mac=${MEMIF22_MAC} Check That VPP1_memif1 And VPP2_memif1 Are Not Affected By VPP2_memif2 Delete - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_SEC_MAC} role=master id=1 ipv6=${IP_5}/30 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_SEC_MAC} role=slave id=1 ipv6=${IP_6}/64 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=${MEMIF11_SEC_MAC} role=master id=1 ipv6=${IP_5}/30 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/default.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=${MEMIF21_SEC_MAC} role=slave id=1 ipv6=${IP_6}/64 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/default.sock Show Interfaces And Other Objects After Setup vpp_term: Show Interfaces agent_vpp_1 diff --git a/tests/robot/suites/crudIPv6/physical_crudIPv6.robot b/tests/robot/suites/crudIPv6/physical_crudIPv6.robot index 95788fdc65..e183bb4281 100644 --- a/tests/robot/suites/crudIPv6/physical_crudIPv6.robot +++ b/tests/robot/suites/crudIPv6/physical_crudIPv6.robot @@ -20,6 +20,8 @@ ${ENV}= common ${IP_1}= fd33::1:b:0:0:1 ${IP_2}= fd30::1:b:0:0:1 ${IP_3}= fd31::1:b:0:0:1 +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment [Tags] setup @@ -43,40 +45,40 @@ Add Physical1 Interface vpp_ctl: Put Physical Interface With IP node=agent_vpp_1 name=${DOCKER_PHYSICAL_INT_1_VPP_NAME} ip=${IP_1} prefix=64 mtu=1500 Check That Physical1 Interface Is Configured - vpp_term: Interface Is Enabled node=agent_vpp_1 interface=${DOCKER_PHYSICAL_INT_1_VPP_NAME} - vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_1_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_1_MAC} ipv6=${IP_1}/64 mtu=1500 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Enabled node=agent_vpp_1 interface=${DOCKER_PHYSICAL_INT_1_VPP_NAME} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_1_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_1_MAC} ipv6=${IP_1}/64 mtu=1500 Add Physical2 Interface vpp_ctl: Put Physical Interface With IP node=agent_vpp_1 name=${DOCKER_PHYSICAL_INT_2_VPP_NAME} ip=${IP_2} prefix=64 mtu=2500 Check That Physical2 Interface Is Configured - vpp_term: Interface Is Enabled node=agent_vpp_1 interface=${DOCKER_PHYSICAL_INT_2_VPP_NAME} - vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_2_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_2_MAC} ipv6=${IP_2}/64 mtu=2500 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Enabled node=agent_vpp_1 interface=${DOCKER_PHYSICAL_INT_2_VPP_NAME} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_2_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_2_MAC} ipv6=${IP_2}/64 mtu=2500 Check That Physical1 Interface Is Still Configured - vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_1_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_1_MAC} ipv6=${IP_1}/64 mtu=1500 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_1_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_1_MAC} ipv6=${IP_1}/64 mtu=1500 Update Physical1 Interface vpp_ctl: Put Physical Interface With IP node=agent_vpp_1 name=${DOCKER_PHYSICAL_INT_1_VPP_NAME} ip=${IP_3} prefix=64 mtu=1600 - vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_1_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_1_MAC} ipv6=${IP_3}/64 mtu=1600 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_1_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_1_MAC} ipv6=${IP_3}/64 mtu=1600 Check That Physical2 Interface Is Still Configured - vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_2_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_2_MAC} ipv6=${IP_2}/64 mtu=2500 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_2_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_2_MAC} ipv6=${IP_2}/64 mtu=2500 Delete Physical2 Interface vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=${DOCKER_PHYSICAL_INT_2_VPP_NAME} - vpp_term: Interface Is Disabled node=agent_vpp_1 interface=${DOCKER_PHYSICAL_INT_2_VPP_NAME} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Disabled node=agent_vpp_1 interface=${DOCKER_PHYSICAL_INT_2_VPP_NAME} Check That Physical2 Interface Is Unconfigured ${ipv4_list}= vpp_term: Get Interface IPs node=agent_vpp_1 interface=${DOCKER_PHYSICAL_INT_2_VPP_NAME} Lists Should Be Equal ${ipv4_list} ${EMPTY} Check That Physical1 Interface Is Not Affected By Delete Physical2 - vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_1_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_1_MAC} ipv6=${IP_3}/64 mtu=1600 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Physical Interface State agent_vpp_1 ${DOCKER_PHYSICAL_INT_1_VPP_NAME} enabled=1 mac=${DOCKER_PHYSICAL_INT_1_MAC} ipv6=${IP_3}/64 mtu=1600 Delete Physical1 interface vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=${DOCKER_PHYSICAL_INT_1_VPP_NAME} - vpp_term: Interface Is Disabled node=agent_vpp_1 interface=${DOCKER_PHYSICAL_INT_1_VPP_NAME} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Disabled node=agent_vpp_1 interface=${DOCKER_PHYSICAL_INT_1_VPP_NAME} Check That Physical1 Interface Is Unconfigured ${ipv4_list}= vpp_term: Get Interface IPs node=agent_vpp_1 interface=${DOCKER_PHYSICAL_INT_1_VPP_NAME} diff --git a/tests/robot/suites/crudIPv6/stn_rule_crudIPv6.robot b/tests/robot/suites/crudIPv6/stn_rule_crudIPv6.robot index 91095b3fcd..2eb22dc037 100644 --- a/tests/robot/suites/crudIPv6/stn_rule_crudIPv6.robot +++ b/tests/robot/suites/crudIPv6/stn_rule_crudIPv6.robot @@ -15,7 +15,7 @@ Test Setup TestSetup Test Teardown TestTeardown *** Variables *** -${SYNC_SLEEP}= 20s + ${RESYNC_SLEEP}= 45s ${VARIABLES}= common ${ENV}= common @@ -30,6 +30,8 @@ ${PREFIX}= 64 ${MTU}= 4800 ${UP_STATE}= up ${RULE_NAME} rule1 +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment @@ -46,14 +48,14 @@ Add TAP1 Interface Check TAP1 Interface Is Created ${interfaces}= vat_term: Interfaces Dump node=agent_vpp_1 Log ${interfaces} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1} ${actual_state}= vpp_term: Check TAP IP6 interface State agent_vpp_1 ${NAME_TAP1} mac=${MAC_TAP1} ipv6=${IP_TAP1}/${PREFIX} state=${UP_STATE} Add STN Rule vpp_ctl: Put STN Rule node=agent_vpp_1 interface=${NAME_TAP1} ip=${IP_STN_RULE} rule_name=${RULE_NAME} Check STN Rule Is Created - vpp_term: Check STN Rule State node=agent_vpp_1 interface=${NAME_TAP1} ip=${IP_STN_RULE} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check STN Rule State node=agent_vpp_1 interface=${NAME_TAP1} ip=${IP_STN_RULE} Check TAP1 Interface Is Still Configured ${actual_state}= vpp_term: Check TAP IP6 interface State agent_vpp_1 ${NAME_TAP1} mac=${MAC_TAP1} ipv6=${IP_TAP1}/${PREFIX} state=${UP_STATE} @@ -63,26 +65,26 @@ Add TAP2 Interface vpp_ctl: Put TAP Interface With IP node=agent_vpp_1 name=${NAME_TAP2} mac=${MAC_TAP2} ip=${IP_TAP2} prefix=${PREFIX} host_if_name=linux_${NAME_TAP2} Check TAP2 Interface Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP2} ${actual_state}= vpp_term: Check TAP IP6 interface State agent_vpp_1 ${NAME_TAP2} mac=${MAC_TAP2} ipv6=${IP_TAP2}/${PREFIX} state=${UP_STATE} Update STN Rule vpp_ctl: Put STN Rule node=agent_vpp_1 interface=${NAME_TAP2} ip=${IP_STN_RULE} rule_name=${RULE_NAME} Check STN Rule Is Updated - vpp_term: Check STN Rule State node=agent_vpp_1 interface=${NAME_TAP2} ip=${IP_STN_RULE} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check STN Rule State node=agent_vpp_1 interface=${NAME_TAP2} ip=${IP_STN_RULE} Delete STN Rule vpp_ctl: Delete STN Rule node=agent_vpp_1 rule_name=${RULE_NAME} Check Deleted STN Rule - vpp_term: Check STN Rule Deleted node=agent_vpp_1 interface=${NAME_TAP2} ip=${IP_STN_RULE} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check STN Rule Deleted node=agent_vpp_1 interface=${NAME_TAP2} ip=${IP_STN_RULE} Add STN Rule Again vpp_ctl: Put STN Rule node=agent_vpp_1 interface=${NAME_TAP1} ip=${IP_STN_RULE} rule_name=${RULE_NAME} Check STN Rule Is Created Again - vpp_term: Check STN Rule State node=agent_vpp_1 interface=${NAME_TAP1} ip=${IP_STN_RULE} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Check STN Rule State node=agent_vpp_1 interface=${NAME_TAP1} ip=${IP_STN_RULE} Remove VPP Node Remove Node agent_vpp_1 diff --git a/tests/robot/suites/crudIPv6/tap_crudIPv6.robot b/tests/robot/suites/crudIPv6/tap_crudIPv6.robot index 113a43056d..35f8f08d0c 100644 --- a/tests/robot/suites/crudIPv6/tap_crudIPv6.robot +++ b/tests/robot/suites/crudIPv6/tap_crudIPv6.robot @@ -28,6 +28,8 @@ ${IP_TAP2}= fd32::1:b:0:0:1 ${PREFIX}= 64 ${MTU}= 4800 ${UP_STATE}= up +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment @@ -44,7 +46,7 @@ Add TAP1 Interface Check TAP1 Interface Is Created ${interfaces}= vat_term: Interfaces Dump node=agent_vpp_1 Log ${interfaces} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1} ${actual_state}= vpp_term: Check TAP IP6 interface State agent_vpp_1 ${NAME_TAP1} mac=${MAC_TAP1} ipv6=${IP_TAP1}/${PREFIX} state=${UP_STATE} Add TAP2 Interface @@ -52,7 +54,7 @@ Add TAP2 Interface vpp_ctl: Put TAP Interface With IP node=agent_vpp_1 name=${NAME_TAP2} mac=${MAC_TAP2} ip=${IP_TAP2} prefix=${PREFIX} host_if_name=linux_${NAME_TAP2} Check TAP2 Interface Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP2} ${actual_state}= vpp_term: Check TAP IP6 interface State agent_vpp_1 ${NAME_TAP2} mac=${MAC_TAP2} ipv6=${IP_TAP2}/${PREFIX} state=${UP_STATE} Check TAP1 Interface Is Still Configured @@ -62,7 +64,7 @@ Update TAP1 Interface vpp_ctl: Put TAP Interface With IP node=agent_vpp_1 name=${NAME_TAP1} mac=${MAC_TAP1_2} ip=${IP_TAP1_2} prefix=${PREFIX} host_if_name=linux_${NAME_TAP1} Check TAP1_2 Interface Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1_2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1_2} ${actual_state}= vpp_term: Check TAP IP6 interface State agent_vpp_1 ${NAME_TAP1} mac=${MAC_TAP1_2} ipv6=${IP_TAP1_2}/${PREFIX} state=${UP_STATE} Check TAP2 Interface Has Not Changed @@ -72,7 +74,7 @@ Delete TAP1_2 Interface vpp_ctl: Delete VPP Interface agent_vpp_1 ${NAME_TAP1} Check TAP1_2 Interface Has Been Deleted - vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_TAP1_2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_TAP1_2} Check TAP2 Interface Is Still Configured ${actual_state}= vpp_term: Check TAP IP6 interface State agent_vpp_1 ${NAME_TAP2} mac=${MAC_TAP2} ipv6=${IP_TAP2}/${PREFIX} state=${UP_STATE} diff --git a/tests/robot/suites/crudIPv6/tap_unnumbered_crudIPv6.robot b/tests/robot/suites/crudIPv6/tap_unnumbered_crudIPv6.robot index f912481184..bd8612e43d 100644 --- a/tests/robot/suites/crudIPv6/tap_unnumbered_crudIPv6.robot +++ b/tests/robot/suites/crudIPv6/tap_unnumbered_crudIPv6.robot @@ -31,7 +31,8 @@ ${IP_TAP3}= fd30::1:b:0:0:1 ${PREFIX}= 64 ${MTU}= 4800 ${UP_STATE}= up - +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment [Tags] setup @@ -47,7 +48,7 @@ Add TAP1 Interface Check TAP1 Interface Is Created ${interfaces}= vat_term: Interfaces Dump node=agent_vpp_1 Log ${interfaces} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1} ${actual_state}= vpp_term: Check TAP IP6 interface State agent_vpp_1 ${NAME_TAP1} mac=${MAC_TAP1} ipv6=${IP_TAP1}/${PREFIX} state=${UP_STATE} Add TAP2 Unnumbered Interface @@ -55,7 +56,7 @@ Add TAP2 Unnumbered Interface vpp_ctl: Put TAP Unnumbered Interface node=agent_vpp_1 name=${NAME_TAP2} mac=${MAC_TAP2} unnumbered=true interface_with_ip_name=${NAME_TAP1} host_if_name=linux_${NAME_TAP2} Check TAP2 Unnumbered Interface Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP2} ${actual_state}= vpp_term: Check TAP IP6 interface State agent_vpp_1 ${NAME_TAP2} mac=${MAC_TAP2} ipv6=${IP_TAP1}/${PREFIX} state=${UP_STATE} Check TAP1 Interface Is Still Configured @@ -65,7 +66,7 @@ Update TAP1 Interface vpp_ctl: Put TAP Interface With IP node=agent_vpp_1 name=${NAME_TAP1} mac=${MAC_TAP1_2} ip=${IP_TAP1_2} prefix=${PREFIX} host_if_name=linux_${NAME_TAP1} Check TAP1_2 Interface Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1_2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1_2} ${actual_state}= vpp_term: Check TAP IP6 interface State agent_vpp_1 ${NAME_TAP1} mac=${MAC_TAP1_2} ipv6=${IP_TAP1_2}/${PREFIX} state=${UP_STATE} Check TAP2 Unnumbered Interface Is Changed @@ -78,7 +79,7 @@ Add TAP3 Interface Check TAP3 Interface Is Created ${interfaces}= vat_term: Interfaces Dump node=agent_vpp_1 Log ${interfaces} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP3} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP3} ${actual_state}= vpp_term: Check TAP IP6 interface State agent_vpp_1 ${NAME_TAP3} mac=${MAC_TAP3} ipv6=${IP_TAP3}/${PREFIX} state=${UP_STATE} Check TAP2 Unnumbered Interface IS Still Configuredl @@ -88,7 +89,7 @@ Update TAP2 Unnumbered Interface vpp_ctl: Put TAP Unnumbered Interface node=agent_vpp_1 name=${NAME_TAP2} mac=${MAC_TAP2} unnumbered=true interface_with_ip_name=${NAME_TAP3} host_if_name=linux_${NAME_TAP2} Check TAP2_2 Unnumbered Interface Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP2} ${actual_state}= vpp_term: Check TAP IP6 interface State agent_vpp_1 ${NAME_TAP2} mac=${MAC_TAP2} ipv6=${IP_TAP3}/${PREFIX} state=${UP_STATE} Check TAP1_2 Interface Is Still Configured @@ -101,7 +102,7 @@ Delete TAP1_2 Interface vpp_ctl: Delete VPP Interface agent_vpp_1 ${NAME_TAP1} Check TAP1_2 Interface Has Been Deleted - vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_TAP1_2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_TAP1_2} Check TAP2_2 Unnumbered Interface IS Still Configured ${actual_state}= vpp_term: Check TAP IP6 interface State agent_vpp_1 ${NAME_TAP2} mac=${MAC_TAP2} ipv6=${IP_TAP3}/${PREFIX} state=${UP_STATE} diff --git a/tests/robot/suites/crudIPv6/tapv2_crudIPv6.robot b/tests/robot/suites/crudIPv6/tapv2_crudIPv6.robot index c34b5d12a2..b9d412cfab 100644 --- a/tests/robot/suites/crudIPv6/tapv2_crudIPv6.robot +++ b/tests/robot/suites/crudIPv6/tapv2_crudIPv6.robot @@ -28,7 +28,8 @@ ${IP_TAP2}= fd33::1:b:0:0:2 ${PREFIX}= 64 ${MTU}= 4800 ${UP_STATE}= up - +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment [Tags] setup @@ -44,7 +45,7 @@ Add TAP1v2 Interface Check TAP1v2 Interface Is Created ${interfaces}= vat_term: Interfaces Dump node=agent_vpp_1 Log ${interfaces} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1} ${actual_state}= vpp_term: Check TAPv2 IP6 interface State agent_vpp_1 ${NAME_TAP1} mac=${MAC_TAP1} ipv6=${IP_TAP1}/${PREFIX} state=${UP_STATE} Add TAP2v2 Interface @@ -52,7 +53,7 @@ Add TAP2v2 Interface vpp_ctl: Put TAPv2 Interface With IP node=agent_vpp_1 name=${NAME_TAP2} mac=${MAC_TAP2} ip=${IP_TAP2} prefix=${PREFIX} host_if_name=linux_${NAME_TAP2} Check TAP2v2 Interface Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP2} ${actual_state}= vpp_term: Check TAPv2 IP6 interface State agent_vpp_1 ${NAME_TAP2} mac=${MAC_TAP2} ipv6=${IP_TAP2}/${PREFIX} state=${UP_STATE} Check TAP1v2 Interface Is Still Configured @@ -62,7 +63,7 @@ Update TAP1v2 Interface vpp_ctl: Put TAPv2 Interface With IP node=agent_vpp_1 name=${NAME_TAP1} mac=${MAC_TAP1_2} ip=${IP_TAP1_2} prefix=${PREFIX} host_if_name=linux_${NAME_TAP1} Check TAP1_2v2 Interface Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1_2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_TAP1_2} ${actual_state}= vpp_term: Check TAPv2 IP6 interface State agent_vpp_1 ${NAME_TAP1} mac=${MAC_TAP1_2} ipv6=${IP_TAP1_2}/${PREFIX} state=${UP_STATE} Check TAP2v2 Interface Has Not Changed @@ -72,7 +73,7 @@ Delete TAP1_2v2 Interface vpp_ctl: Delete VPP Interface agent_vpp_1 ${NAME_TAP1} Check TAP1_2v2 Interface Has Been Deleted - vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_TAP1_2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_TAP1_2} Check TAP2 Interface Is Still Configured ${actual_state}= vpp_term: Check TAPv2 IP6 interface State agent_vpp_1 ${NAME_TAP2} mac=${MAC_TAP2} ipv6=${IP_TAP2}/${PREFIX} state=${UP_STATE} diff --git a/tests/robot/suites/crudIPv6/veth_crudIPv6.robot b/tests/robot/suites/crudIPv6/veth_crudIPv6.robot index 1d80f7e4f5..54b84feb3a 100644 --- a/tests/robot/suites/crudIPv6/veth_crudIPv6.robot +++ b/tests/robot/suites/crudIPv6/veth_crudIPv6.robot @@ -43,10 +43,10 @@ Add Veth2 Interface vpp_ctl: Put Veth Interface node=agent_vpp_1 name=vpp1_veth2 mac=${VETH2_MAC} peer=vpp1_veth1 Check That Veth1 And Veth2 Interfaces Are Created - linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_MAC} - linux: Interface Is Created node=agent_vpp_1 mac=${VETH2_MAC} - linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv6=${VETHIP1}/64 mtu=1500 state=up - linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH2_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv6=${VETHIP1}/64 mtu=1500 state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up Add Veth3 Interface linux: Interface Not Exists node=agent_vpp_1 mac=${VETH3_MAC} @@ -58,30 +58,30 @@ Add Veth4 Interface vpp_ctl: Put Veth Interface node=agent_vpp_1 name=vpp1_veth4 mac=${VETH4_MAC} peer=vpp1_veth3 enabled=false Check That Veth3 And Veth4 Interfaces Are Created - linux: Interface Is Created node=agent_vpp_1 mac=${VETH3_MAC} - linux: Interface Is Created node=agent_vpp_1 mac=${VETH4_MAC} - linux: Check Veth Interface State agent_vpp_1 vpp1_veth3 mac=${VETH3_MAC} ipv6=${VETHIP2}/64 mtu=1500 state=lowerlayerdown - linux: Check Veth Interface State agent_vpp_1 vpp1_veth4 mac=${VETH4_MAC} state=down + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH3_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH4_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth3 mac=${VETH3_MAC} ipv6=${VETHIP2}/64 mtu=1500 state=lowerlayerdown + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth4 mac=${VETH4_MAC} state=down Check That Veth1 And Veth2 Interfaces Are Still Configured - linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv6=${VETHIP1}/64 mtu=1500 state=up - linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_MAC} ipv6=${VETHIP1}/64 mtu=1500 state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up Update Veth1 Interface vpp_ctl: Put Veth Interface With IP node=agent_vpp_1 name=vpp1_veth1 mac=${VETH1_SEC_MAC} peer=vpp1_veth2 ip=${VETHIP3} prefix=64 mtu=1600 - linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH1_MAC} - linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_SEC_MAC} - linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_SEC_MAC} ipv6=${VETHIP3}/64 mtu=1600 state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH1_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Created node=agent_vpp_1 mac=${VETH1_SEC_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth1 mac=${VETH1_SEC_MAC} ipv6=${VETHIP3}/64 mtu=1600 state=up Check That Veth2 And Veth3 And Veth4 interfaces Are Still Configured - linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up - linux: Check Veth Interface State agent_vpp_1 vpp1_veth3 mac=${VETH3_MAC} ipv6=${VETHIP2}/64 mtu=1500 state=lowerlayerdown - linux: Check Veth Interface State agent_vpp_1 vpp1_veth4 mac=${VETH4_MAC} state=down + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth2 mac=${VETH2_MAC} state=up + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth3 mac=${VETH3_MAC} ipv6=${VETHIP2}/64 mtu=1500 state=lowerlayerdown + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Check Veth Interface State agent_vpp_1 vpp1_veth4 mac=${VETH4_MAC} state=down Delete Veth2 Interface vpp_ctl: Delete Linux Interface node=agent_vpp_1 name=vpp1_veth2 - linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH1_SEC_MAC} - linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH2_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH1_SEC_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH2_MAC} Check That Veth3 And Veth4 Are Still Configured linux: Check Veth Interface State agent_vpp_1 vpp1_veth3 mac=${VETH3_MAC} ipv6=${VETHIP2}/64 mtu=1500 state=lowerlayerdown @@ -89,8 +89,8 @@ Check That Veth3 And Veth4 Are Still Configured Delete Veth3 Interface vpp_ctl: Delete Linux Interface node=agent_vpp_1 name=vpp1_veth3 - linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH3_MAC} - linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH4_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH3_MAC} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface Is Deleted node=agent_vpp_1 mac=${VETH4_MAC} Show Interfaces And Other Objects After Setup vpp_term: Show Interfaces agent_vpp_1 diff --git a/tests/robot/suites/crudIPv6/vxlan_crudIPv6.robot b/tests/robot/suites/crudIPv6/vxlan_crudIPv6.robot index b5996e1949..d67f9eca44 100644 --- a/tests/robot/suites/crudIPv6/vxlan_crudIPv6.robot +++ b/tests/robot/suites/crudIPv6/vxlan_crudIPv6.robot @@ -18,14 +18,14 @@ Test Teardown TestTeardown ${VARIABLES}= common ${ENV}= common -${SYNC_SLEEP}= 2s ${IP1}= fd30::1:b:0:0:1 ${IP2}= fd30::1:b:0:0:2 ${IP3}= fd31::1:b:0:0:1 ${IP4}= fd31::1:b:0:0:2 ${IP10}= fd32::1:b:0:0:1 ${IP20}= fd32::1:b:0:0:2 - +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment [Tags] setup @@ -37,37 +37,37 @@ Show Interfaces Before Setup Add First VXLan Interface vxlan: Tunnel Not Exists node=agent_vpp_1 src=${IP1} dst=${IP2} vni=15 vpp_ctl: Put VXLan Interface node=agent_vpp_1 name=vpp1_vxlan1 src=${IP1} dst=${IP2} vni=15 - Sleep ${SYNC_SLEEP} - vxlan: Tunnel Is Created node=agent_vpp_1 src=${IP1} dst=${IP2} vni=15 - vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan1 enabled=1 src=${IP1} dst=${IP2} vni=15 + + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vxlan: Tunnel Is Created node=agent_vpp_1 src=${IP1} dst=${IP2} vni=15 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan1 enabled=1 src=${IP1} dst=${IP2} vni=15 Add Second VXLan Interface vxlan: Tunnel Not Exists node=agent_vpp_1 src=${IP3} dst=${IP4} vni=25 vpp_ctl: Put VXLan Interface node=agent_vpp_1 name=vpp1_vxlan2 src=${IP3} dst=${IP4} vni=25 - Sleep ${SYNC_SLEEP} - vxlan: Tunnel Is Created node=agent_vpp_1 src=${IP3} dst=${IP4} vni=25 - vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan2 enabled=1 src=${IP3} dst=${IP4} vni=25 + + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vxlan: Tunnel Is Created node=agent_vpp_1 src=${IP3} dst=${IP4} vni=25 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan2 enabled=1 src=${IP3} dst=${IP4} vni=25 Check That First VXLan Interface Is Still Configured - vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan1 enabled=1 src=${IP1} dst=${IP2} vni=15 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan1 enabled=1 src=${IP1} dst=${IP2} vni=15 Update First VXLan Interface vpp_ctl: Put VXLan Interface node=agent_vpp_1 name=vpp1_vxlan1 src=${IP10} dst=${IP20} vni=150 - Sleep ${SYNC_SLEEP} - vxlan: Tunnel Is Deleted node=agent_vpp_1 src=${IP1} dst=${IP2} vni=15 - vxlan: Tunnel Is Created node=agent_vpp_1 src=${IP10} dst=${IP20} vni=150 - vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan1 enabled=1 src=${IP10} dst=${IP20} vni=150 + + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vxlan: Tunnel Is Deleted node=agent_vpp_1 src=${IP1} dst=${IP2} vni=15 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vxlan: Tunnel Is Created node=agent_vpp_1 src=${IP10} dst=${IP20} vni=150 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan1 enabled=1 src=${IP10} dst=${IP20} vni=150 Check That Second VXLan Interface Is Not Changed - vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan2 enabled=1 src=${IP3} dst=${IP4} vni=25 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan2 enabled=1 src=${IP3} dst=${IP4} vni=25 Delete First VXLan Interface vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=vpp1_vxlan1 - Sleep ${SYNC_SLEEP} - vxlan: Tunnel Is Deleted node=agent_vpp_1 src=${IP10} dst=${IP20} vni=150 + + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vxlan: Tunnel Is Deleted node=agent_vpp_1 src=${IP10} dst=${IP20} vni=150 Check That Second VXLan Interface Is Still Configured - vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan2 enabled=1 src=${IP3} dst=${IP4} vni=25 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check VXLan Interface State agent_vpp_1 vpp1_vxlan2 enabled=1 src=${IP3} dst=${IP4} vni=25 Show Interfaces And Other Objects After Setup vpp_term: Show Interfaces agent_vpp_1 diff --git a/tests/robot/suites/sfc/east-west/vswitch_1x_vpp_1x_novpp/vswitch_1x_vpp_1x_novpp.robot b/tests/robot/suites/sfc/east-west/vswitch_1x_vpp_1x_novpp/vswitch_1x_vpp_1x_novpp.robot index d5bf2a4970..2dd7b81c4a 100644 --- a/tests/robot/suites/sfc/east-west/vswitch_1x_vpp_1x_novpp/vswitch_1x_vpp_1x_novpp.robot +++ b/tests/robot/suites/sfc/east-west/vswitch_1x_vpp_1x_novpp/vswitch_1x_vpp_1x_novpp.robot @@ -17,8 +17,8 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${FINAL_SLEEP}= 3s -${SYNC_SLEEP}= 10s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment @@ -53,7 +53,6 @@ Start Agent Nodes Again Add Agent Node agent_1 Add Agent VPP Node agent_vpp_1 vswitch=${TRUE} #Sleep ${SYNC_SLEEP} - Sleep ${SYNC_SLEEP} Check Interfaces After Resync Check Stuff @@ -74,7 +73,6 @@ Remove Agent Nodes Again Start Agent Nodes Again2 Add Agent VPP Node agent_vpp_1 vswitch=${TRUE} Add Agent Node agent_1 - Sleep ${SYNC_SLEEP} Check Interfaces After Resync2 Check Stuff @@ -93,7 +91,6 @@ Start All Agent Nodes Add Agent VPP Node agent_vpp_1 vswitch=${TRUE} Add Agent VPP Node agent_vpp_2 Add Agent Node agent_1 - Sleep ${SYNC_SLEEP} Check Interfaces After Resync3 Check Stuff @@ -108,10 +105,10 @@ Check Ping Agent1 -> VPP2 After Resync3 *** Keywords *** Check Stuff + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 IF_MEMIF_VSWITCH_agent_vpp_2_vpp2_memif1 role=master connected=1 enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Afpacket Interface State agent_vpp_1 IF_AFPIF_VSWITCH_agent_1_agent1_afp1 enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=02:02:02:02:02:02 role=slave ipv4=10.0.0.1/24 connected=1 enabled=1 Show Interfaces And Other Objects - vat_term: Check Memif Interface State agent_vpp_1 IF_MEMIF_VSWITCH_agent_vpp_2_vpp2_memif1 role=master connected=1 enabled=1 - vat_term: Check Afpacket Interface State agent_vpp_1 IF_AFPIF_VSWITCH_agent_1_agent1_afp1 enabled=1 - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=02:02:02:02:02:02 role=slave ipv4=10.0.0.1/24 connected=1 enabled=1 Show Interfaces And Other Objects vpp_term: Show Interfaces agent_vpp_1 diff --git a/tests/robot/suites/sfc/east-west/vswitch_2x_vnf_vpp/vswitch_2x_vnf_vpp.robot b/tests/robot/suites/sfc/east-west/vswitch_2x_vnf_vpp/vswitch_2x_vnf_vpp.robot index 7431248a13..4945c6452a 100644 --- a/tests/robot/suites/sfc/east-west/vswitch_2x_vnf_vpp/vswitch_2x_vnf_vpp.robot +++ b/tests/robot/suites/sfc/east-west/vswitch_2x_vnf_vpp/vswitch_2x_vnf_vpp.robot @@ -11,12 +11,14 @@ Resource ../../../../libraries/all_libs.robot Force Tags sfcIPv4 Suite Setup Testsuite Setup Suite Teardown Suite Cleanup +Test Setup TestSetup +Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${FINAL_SLEEP}= 3s -${SYNC_SLEEP}= 10s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment @@ -27,17 +29,17 @@ Configure Environment ${DATA_FOLDER}= Catenate SEPARATOR=/ ${CURDIR} ${TEST_DATA_FOLDER} Set Suite Variable ${DATA_FOLDER} Start SFC Controller Container With Own Config basic.conf - Sleep ${SYNC_SLEEP} + Check Memifs On Vswitch - vat_term: Check Memif Interface State agent_vpp_1 IF_MEMIF_VSWITCH_agent_vpp_2_vpp2_memif1 role=master connected=1 enabled=1 - vat_term: Check Memif Interface State agent_vpp_1 IF_MEMIF_VSWITCH_agent_vpp_3_vpp3_memif1 role=master connected=1 enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 IF_MEMIF_VSWITCH_agent_vpp_2_vpp2_memif1 role=master connected=1 enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 IF_MEMIF_VSWITCH_agent_vpp_3_vpp3_memif1 role=master connected=1 enabled=1 Check Memif Interface On VPP2 - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=02:02:02:02:02:02 role=slave ipv4=10.0.0.1/24 connected=1 enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=02:02:02:02:02:02 role=slave ipv4=10.0.0.1/24 connected=1 enabled=1 Check Memif Interface On VPP3 - vat_term: Check Memif Interface State agent_vpp_3 vpp3_memif1 role=slave ipv4=10.0.0.10/24 connected=1 enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_3 vpp3_memif1 role=slave ipv4=10.0.0.10/24 connected=1 enabled=1 Show Interfaces And Other Objects vpp_term: Show Interfaces agent_vpp_1 @@ -83,17 +85,17 @@ Start Agent Nodes Again Add Agent VPP Node agent_vpp_1 vswitch=${TRUE} Add Agent VPP Node agent_vpp_2 Add Agent VPP Node agent_vpp_3 - Sleep ${SYNC_SLEEP} + Check Memifs On Vswitch After Resync - vat_term: Check Memif Interface State agent_vpp_1 IF_MEMIF_VSWITCH_agent_vpp_2_vpp2_memif1 role=master connected=1 enabled=1 - vat_term: Check Memif Interface State agent_vpp_1 IF_MEMIF_VSWITCH_agent_vpp_3_vpp3_memif1 role=master connected=1 enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 IF_MEMIF_VSWITCH_agent_vpp_2_vpp2_memif1 role=master connected=1 enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 IF_MEMIF_VSWITCH_agent_vpp_3_vpp3_memif1 role=master connected=1 enabled=1 Check Memif Interface On VPP2 After Resync - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=02:02:02:02:02:02 role=slave ipv4=10.0.0.1/24 connected=1 enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=02:02:02:02:02:02 role=slave ipv4=10.0.0.1/24 connected=1 enabled=1 Check Memif Interface On VPP3 After Resync - vat_term: Check Memif Interface State agent_vpp_3 vpp3_memif1 role=slave ipv4=10.0.0.10/24 connected=1 enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_3 vpp3_memif1 role=slave ipv4=10.0.0.10/24 connected=1 enabled=1 Show Interfaces And Other Objects After Resync vpp_term: Show Interfaces agent_vpp_1 @@ -135,11 +137,14 @@ Done [Tags] debug No Operation -Final Sleep For Manual Checking - [Tags] debug - Sleep ${FINAL_SLEEP} *** Keywords *** Suite Cleanup Stop SFC Controller Container Testsuite Teardown + +TestSetup + Make Datastore Snapshots ${TEST_NAME}_test_setup + +TestTeardown + Make Datastore Snapshots ${TEST_NAME}_test_teardown diff --git a/tests/robot/suites/sfc/test_controller_start/controller_start.robot b/tests/robot/suites/sfc/test_controller_start/controller_start.robot index 7ddad40ae1..b2e8cfee2f 100644 --- a/tests/robot/suites/sfc/test_controller_start/controller_start.robot +++ b/tests/robot/suites/sfc/test_controller_start/controller_start.robot @@ -17,7 +17,6 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${FINAL_SLEEP}= 3s *** Test Cases *** Configure Environment @@ -60,9 +59,6 @@ Done [Tags] debug No Operation -Final Sleep For Manual Checking - [Tags] debug - Sleep ${FINAL_SLEEP} *** Keywords *** Suite Cleanup diff --git a/tests/robot/suites/sfcIPv6/east-west/vswitch_1x_vpp_1x_novpp/vswitch_1x_vpp_1x_novppIPv6.robot b/tests/robot/suites/sfcIPv6/east-west/vswitch_1x_vpp_1x_novpp/vswitch_1x_vpp_1x_novppIPv6.robot index 791d95953e..26f2c7ac36 100644 --- a/tests/robot/suites/sfcIPv6/east-west/vswitch_1x_vpp_1x_novpp/vswitch_1x_vpp_1x_novppIPv6.robot +++ b/tests/robot/suites/sfcIPv6/east-west/vswitch_1x_vpp_1x_novpp/vswitch_1x_vpp_1x_novppIPv6.robot @@ -17,10 +17,11 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${FINAL_SLEEP}= 3s -${SYNC_SLEEP}= 12s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s ${IP_1}= fd30::1:b:0:0:1 ${IP_2}= fd30::1:b:0:0:10 + *** Test Cases *** Configure Environment [Tags] setup @@ -30,7 +31,6 @@ Configure Environment ${DATA_FOLDER}= Catenate SEPARATOR=/ ${CURDIR} ${TEST_DATA_FOLDER} Set Suite Variable ${DATA_FOLDER} Start SFC Controller Container With Own Config basicIPv6.conf - Sleep ${SYNC_SLEEP} Check Interfaces Created Check Stuff @@ -53,8 +53,6 @@ Start Agent Nodes Again #Add Agent VPP Node agent_vpp_2 Add Agent Node agent_1 Add Agent VPP Node agent_vpp_1 vswitch=${TRUE} - #Sleep ${SYNC_SLEEP} - Sleep ${SYNC_SLEEP} Check Interfaces After Resync Check Stuff @@ -75,7 +73,6 @@ Remove Agent Nodes Again Start Agent Nodes Again2 Add Agent VPP Node agent_vpp_1 vswitch=${TRUE} Add Agent Node agent_1 - Sleep ${SYNC_SLEEP} Check Interfaces After Resync2 Check Stuff @@ -94,7 +91,6 @@ Start All Agent Nodes Add Agent VPP Node agent_vpp_1 vswitch=${TRUE} Add Agent VPP Node agent_vpp_2 Add Agent Node agent_1 - Sleep ${SYNC_SLEEP} Check Interfaces After Resync3 Check Stuff @@ -109,10 +105,10 @@ Check Ping Agent1 -> VPP2 After Resync3 *** Keywords *** Check Stuff + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 IF_MEMIF_VSWITCH_agent_vpp_2_vpp2_memif1 role=master connected=1 enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Afpacket Interface State agent_vpp_1 IF_AFPIF_VSWITCH_agent_1_agent1_afp1 enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=02:02:02:02:02:02 role=slave ipv6=${IP_1}/64 connected=1 enabled=1 Show Interfaces And Other Objects - vat_term: Check Memif Interface State agent_vpp_1 IF_MEMIF_VSWITCH_agent_vpp_2_vpp2_memif1 role=master connected=1 enabled=1 - vat_term: Check Afpacket Interface State agent_vpp_1 IF_AFPIF_VSWITCH_agent_1_agent1_afp1 enabled=1 - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=02:02:02:02:02:02 role=slave ipv6=${IP_1}/64 connected=1 enabled=1 Show Interfaces And Other Objects vpp_term: Show Interfaces agent_vpp_1 diff --git a/tests/robot/suites/sfcIPv6/east-west/vswitch_2x_vnf_vpp/vswitch_2x_vnf_vppIPv6.robot b/tests/robot/suites/sfcIPv6/east-west/vswitch_2x_vnf_vpp/vswitch_2x_vnf_vppIPv6.robot index 57ad3153fa..8de363de2f 100644 --- a/tests/robot/suites/sfcIPv6/east-west/vswitch_2x_vnf_vpp/vswitch_2x_vnf_vppIPv6.robot +++ b/tests/robot/suites/sfcIPv6/east-west/vswitch_2x_vnf_vpp/vswitch_2x_vnf_vppIPv6.robot @@ -11,12 +11,14 @@ Resource ../../../../libraries/all_libs.robot Force Tags sfcIPv6 Suite Setup Testsuite Setup Suite Teardown Suite Cleanup +Test Setup TestSetup +Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${FINAL_SLEEP}= 3s -${SYNC_SLEEP}= 10s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s ${IP_1}= fd30::1:b:0:0:1 ${IP_2}= fd30::1:b:0:0:10 @@ -30,48 +32,20 @@ Configure Environment ${DATA_FOLDER}= Catenate SEPARATOR=/ ${CURDIR} ${TEST_DATA_FOLDER} Set Suite Variable ${DATA_FOLDER} Start SFC Controller Container With Own Config basicIPv6.conf - Sleep ${SYNC_SLEEP} + Check Memifs On Vswitch - vat_term: Check Memif Interface State agent_vpp_1 IF_MEMIF_VSWITCH_agent_vpp_2_vpp2_memif1 role=master connected=1 enabled=1 - vat_term: Check Memif Interface State agent_vpp_1 IF_MEMIF_VSWITCH_agent_vpp_3_vpp3_memif1 role=master connected=1 enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 IF_MEMIF_VSWITCH_agent_vpp_2_vpp2_memif1 role=master connected=1 enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 IF_MEMIF_VSWITCH_agent_vpp_3_vpp3_memif1 role=master connected=1 enabled=1 Check Memif Interface On VPP2 - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=02:02:02:02:02:02 role=slave ipv6=${IP_1}/64 connected=1 enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=02:02:02:02:02:02 role=slave ipv6=${IP_1}/64 connected=1 enabled=1 Check Memif Interface On VPP3 - vat_term: Check Memif Interface State agent_vpp_3 vpp3_memif1 role=slave ipv6=${IP_2}/64 connected=1 enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_3 vpp3_memif1 role=slave ipv6=${IP_2}/64 connected=1 enabled=1 Show Interfaces And Other Objects - vpp_term: Show Interfaces agent_vpp_1 - vpp_term: Show Interfaces agent_vpp_2 - vpp_term: Show Interfaces agent_vpp_3 - Write To Machine agent_vpp_1_term show int addr - Write To Machine agent_vpp_2_term show int addr - Write To Machine agent_vpp_3_term show int addr - Write To Machine agent_vpp_1_term show h - Write To Machine agent_vpp_2_term show h - Write To Machine agent_vpp_3_term show h - Write To Machine agent_vpp_1_term show br - Write To Machine agent_vpp_2_term show br - Write To Machine agent_vpp_3_term show br - Write To Machine agent_vpp_1_term show br 1 detail - Write To Machine agent_vpp_2_term show br 1 detail - Write To Machine agent_vpp_3_term show br 1 detail - Write To Machine agent_vpp_1_term show vxlan tunnel - Write To Machine agent_vpp_2_term show vxlan tunnel - Write To Machine agent_vpp_3_term show vxlan tunnel - Write To Machine agent_vpp_1_term show err - Write To Machine agent_vpp_2_term show err - Write To Machine agent_vpp_3_term show err - vat_term: Interfaces Dump agent_vpp_1 - vat_term: Interfaces Dump agent_vpp_2 - vat_term: Interfaces Dump agent_vpp_3 - Write To Machine vpp_agent_ctl vpp-agent-ctl ${AGENT_VPP_ETCD_CONF_PATH} -ps - Execute In Container agent_vpp_1 ip a - Execute In Container agent_vpp_2 ip a - Execute In Container agent_vpp_3 ip a - Make Datastore Snapshots before_resync + Check Stuff Check Ping Agent2 -> Agent3 vpp_term: Check Ping agent_vpp_2 ${IP_2} @@ -86,19 +60,29 @@ Start Agent Nodes Again Add Agent VPP Node agent_vpp_1 vswitch=${TRUE} Add Agent VPP Node agent_vpp_2 Add Agent VPP Node agent_vpp_3 - Sleep ${SYNC_SLEEP} + Check Memifs On Vswitch After Resync - vat_term: Check Memif Interface State agent_vpp_1 IF_MEMIF_VSWITCH_agent_vpp_2_vpp2_memif1 role=master connected=1 enabled=1 - vat_term: Check Memif Interface State agent_vpp_1 IF_MEMIF_VSWITCH_agent_vpp_3_vpp3_memif1 role=master connected=1 enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 IF_MEMIF_VSWITCH_agent_vpp_2_vpp2_memif1 role=master connected=1 enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 IF_MEMIF_VSWITCH_agent_vpp_3_vpp3_memif1 role=master connected=1 enabled=1 Check Memif Interface On VPP2 After Resync - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=02:02:02:02:02:02 role=slave ipv6=${IP_1}/64 connected=1 enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=02:02:02:02:02:02 role=slave ipv6=${IP_1}/64 connected=1 enabled=1 Check Memif Interface On VPP3 After Resync - vat_term: Check Memif Interface State agent_vpp_3 vpp3_memif1 role=slave ipv6=${IP_2}/64 connected=1 enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_3 vpp3_memif1 role=slave ipv6=${IP_2}/64 connected=1 enabled=1 Show Interfaces And Other Objects After Resync + Check Stuff + +Check Ping Agent2 -> Agent3 After Resync + vpp_term: Check Ping agent_vpp_2 ${IP_2} + +Check Ping Agent3 -> Agent2 After Resync + vpp_term: Check Ping agent_vpp_3 ${IP_1} + +*** Keywords *** +Check Stuff vpp_term: Show Interfaces agent_vpp_1 vpp_term: Show Interfaces agent_vpp_2 vpp_term: Show Interfaces agent_vpp_3 @@ -128,21 +112,12 @@ Show Interfaces And Other Objects After Resync Execute In Container agent_vpp_2 ip a Execute In Container agent_vpp_3 ip a -Check Ping Agent2 -> Agent3 After Resync - vpp_term: Check Ping agent_vpp_2 ${IP_2} - -Check Ping Agent3 -> Agent2 After Resync - vpp_term: Check Ping agent_vpp_3 ${IP_1} - -Done - [Tags] debug - No Operation - -Final Sleep For Manual Checking - [Tags] debug - Sleep ${FINAL_SLEEP} - -*** Keywords *** Suite Cleanup Stop SFC Controller Container Testsuite Teardown + +TestSetup + Make Datastore Snapshots ${TEST_NAME}_test_setup + +TestTeardown + Make Datastore Snapshots ${TEST_NAME}_test_teardown \ No newline at end of file diff --git a/tests/robot/suites/traffic/acl_traffic/acl_traffic.robot b/tests/robot/suites/traffic/acl_traffic/acl_traffic.robot index 15f9544adf..abf6ab6f15 100644 --- a/tests/robot/suites/traffic/acl_traffic/acl_traffic.robot +++ b/tests/robot/suites/traffic/acl_traffic/acl_traffic.robot @@ -18,8 +18,9 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${FINAL_SLEEP}= 5s -${SYNC_SLEEP}= 10s + +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s ${RESYNC_SLEEP}= 20s ${AGENT1_VETH_MAC}= 02:00:00:00:00:01 @@ -56,37 +57,36 @@ Configure Environment ${DATA_FOLDER}= Catenate SEPARATOR=/ ${CURDIR} ${TEST_DATA_FOLDER} Set Suite Variable ${DATA_FOLDER} Configure Environment 2 acl_basic.conf - Sleep ${SYNC_SLEEP} - Show Interfaces And Other Objects + #Show Interfaces And Other Objects Check AfPackets On Vswitch - vat_term: Check Afpacket Interface State agent_vpp_1 IF_AFPIF_VSWITCH_node_1_node1_veth enabled=1 - vat_term: Check Afpacket Interface State agent_vpp_1 IF_AFPIF_VSWITCH_node_2_node2_veth enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Afpacket Interface State agent_vpp_1 IF_AFPIF_VSWITCH_node_1_node1_veth enabled=1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Afpacket Interface State agent_vpp_1 IF_AFPIF_VSWITCH_node_2_node2_veth enabled=1 Create Loopbak Intfs Create loopback interface loop0 on agent_vpp_1 with ip 20.1.1.1/24 and mac 8a:f1:be:90:00:00 Create loopback interface loop1 on agent_vpp_1 with ip 30.1.1.1/24 and mac 8a:f1:be:90:20:00 Check Veth Interface On Agent1 - linux: Interface With IP Is Created node_1 mac=${AGENT1_VETH_MAC} ipv4=10.0.0.10/24 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface With IP Is Created node_1 mac=${AGENT1_VETH_MAC} ipv4=10.0.0.10/24 # status check not implemented in linux plugin #linux: Check Veth Interface State agent_vpp_1 agent1_veth mac=${AGENT1_VETH_MAC} ipv4=10.0.0.10/24 mtu=1500 state=up Check Veth Interface On Agent2 - linux: Interface With IP Is Created node_2 mac=${AGENT2_VETH_MAC} ipv4=10.0.0.11/24 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface With IP Is Created node_2 mac=${AGENT2_VETH_MAC} ipv4=10.0.0.11/24 # status check not implemented in linux plugin #linux: Check Veth Interface State agent_vpp_1 agent2_veth mac=${AGENT2_VETH_MAC} ipv4=10.0.0.11/24 mtu=1500 state=up Check Bridge Domain Is Created - vat_term: BD Is Created agent_vpp_1 IF_AFPIF_VSWITCH_node_1_node1_veth IF_AFPIF_VSWITCH_node_2_node2_veth + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: BD Is Created agent_vpp_1 IF_AFPIF_VSWITCH_node_1_node1_veth IF_AFPIF_VSWITCH_node_2_node2_veth Check loop0 Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=8a:f1:be:90:00:00 - vat_term: Check Loopback Interface State agent_vpp_1 loop0 enabled=1 mac=8a:f1:be:90:00:00 mtu=1500 ipv4=20.1.1.1/24 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=8a:f1:be:90:00:00 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 loop0 enabled=1 mac=8a:f1:be:90:00:00 mtu=1500 ipv4=20.1.1.1/24 Check loop1 Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=8a:f1:be:90:20:00 - vat_term: Check Loopback Interface State agent_vpp_1 loop0 enabled=1 mac=8a:f1:be:90:20:00 mtu=1500 ipv4=30.1.1.1/24 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=8a:f1:be:90:20:00 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 loop0 enabled=1 mac=8a:f1:be:90:20:00 mtu=1500 ipv4=30.1.1.1/24 Create BD fo Loopbacks Create Bridge Domain bd2 With Autolearn On agent_vpp_1 with interfaces loop0, loop1 diff --git a/tests/robot/suites/traffic/ip_route/test_inter_vrf_routes.robot b/tests/robot/suites/traffic/ip_route/test_inter_vrf_routes.robot new file mode 100644 index 0000000000..224e2e2b96 --- /dev/null +++ b/tests/robot/suites/traffic/ip_route/test_inter_vrf_routes.robot @@ -0,0 +1,110 @@ +*** Settings *** + +Library OperatingSystem +Library String +#Library RequestsLibrary + +Resource ../../../variables/${VARIABLES}_variables.robot +Resource ../../../libraries/all_libs.robot +Resource ../../../libraries/pretty_keywords.robot + +Force Tags trafficIPv4 +Suite Setup Run Keywords Discard old results Test Setup +Suite Teardown Test Teardown + +*** Variables *** +${VARIABLES}= common +${ENV}= common +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s +${FINAL_SLEEP}= 1s +${IP_1}= 10.1.1.1 +${IP_2}= 10.1.1.2 +${IP_3}= 10.1.2.1 +${IP_4}= 10.1.2.2 +${NET1}= 10.1.1.0 +${NET2}= 10.1.2.0 + +*** Test Cases *** +# Non default VRF table 2 used in Agent VPP Node agent_vpp_2 +Start Two Agents And Then Configure With Default And Non Default VRF + Add Agent VPP Node agent_vpp_1 + Add Agent VPP Node agent_vpp_2 + + Create Master memif0 on agent_vpp_1 with IP ${IP_1}, MAC 02:f1:be:90:00:00, key 1 and m0.sock socket + Create Slave memif0 on agent_vpp_2 with IP ${IP_2}, MAC 02:f1:be:90:00:02, key 1 and m0.sock socket + + Create Master memif1 on agent_vpp_1 with VRF 2, IP ${IP_3}, MAC 02:f1:be:90:02:00, key 1 and m1.sock socket + Create Slave memif1 on agent_vpp_2 with VRF 2, IP ${IP_4}, MAC 02:f1:be:90:02:02, key 1 and m1.sock socket + + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} List of interfaces On agent_vpp_1 Should Contain Interface memif1/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} List of interfaces On agent_vpp_2 Should Contain Interface memif1/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} List of interfaces On agent_vpp_1 Should Contain Interface memif2/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} List of interfaces On agent_vpp_2 Should Contain Interface memif2/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} IP Fib Table 0 On agent_vpp_1 Should Contain Route With IP ${IP_1}/32 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} IP Fib Table 2 On agent_vpp_1 Should Contain Route With IP ${IP_3}/32 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} IP Fib Table 0 On agent_vpp_2 Should Contain Route With IP ${IP_2}/32 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} IP Fib Table 2 On agent_vpp_2 Should Contain Route With IP ${IP_4}/32 + + +Check Normal Ping Inside VRF + # try ping + Ping From agent_vpp_1 To ${IP_2} + Ping From agent_vpp_2 To ${IP_1} + +Ping From Source Agent 1 + Ping On agent_vpp_1 With IP ${IP_2}, Source memif1/1 + Ping On agent_vpp_1 With IP ${IP_4}, Source memif2/1 + +Ping From Source Agent 2 +# ${int}= vpp_ctl: Get Interface Internal Name agent_vpp_2 memif0 +# Ping On agent_vpp_2 With IP 10.1.1.1, Source ${int} + Ping On agent_vpp_2 With IP ${IP_1}, Source memif1/1 + Ping On agent_vpp_2 With IP ${IP_3}, Source memif2/1 + +Ping Should Fail + #no route from vrf 0 to vrf 2, then shoul fail + Command: Ping On agent_vpp_1 With IP ${IP_4}, Source memif1/1 should fail + Command: Ping On agent_vpp_1 With IP ${IP_3}, Source memif1/1 should fail + Command: Ping On agent_vpp_2 With IP ${IP_4}, Source memif1/1 should fail + Command: Ping On agent_vpp_2 With IP ${IP_3}, Source memif1/1 should fail + +Create Route For Inter Vrf Routing + Create Route On agent_vpp_1 With IP ${NET2}/24 With Next Hop ${IP_2} And Vrf Id 0 + Create Route On agent_vpp_1 With IP ${NET1}/24 With Next Hop ${IP_4} And Vrf Id 2 + Create Route On agent_vpp_2 With IP ${NET2}/24 With Next Hop VRF 2 From Vrf Id 0 And Type 1 + Create Route On agent_vpp_2 With IP ${NET1}/24 With Next Hop VRF 0 From Vrf Id 2 And Type 1 + +Config Done + No Operation + +Check Inter VRF Routing + Show IP Fib On agent_vpp_1 + IP Fib Table 0 On agent_vpp_1 Should Contain Route With IP ${NET2}/24 + IP Fib Table 0 On agent_vpp_1 Should Contain Vrf ipv4 via ${IP_2} memif1/1 + Show IP Fib On agent_vpp_2 + IP Fib Table 2 On agent_vpp_2 Should Contain Route With IP ${NET1}/24 + IP Fib Table 2 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv4-VRF: + IP Fib Table 0 On agent_vpp_2 Should Contain Route With IP ${NET2}/24 + IP Fib Table 0 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv4-VRF: + +Check Route With Ping + Ping On agent_vpp_1 With IP ${IP_4}, Source memif1/1 + Ping On agent_vpp_1 With IP ${IP_4}, Source memif2/1 + Ping On agent_vpp_1 With IP ${IP_3}, Source memif1/1 + +Final Sleep For Manual Checking + Sleep ${FINAL_SLEEP} + +*** Keywords *** +List of interfaces On ${node} Should Contain Interface ${int} + Log many ${node} ${int} + ${out}= vpp_term: Show Interfaces ${node} + log many ${out} + Should Match Regexp ${out} ${int} + +IP Fib Table ${table_id} On ${node} Should Contain Vrf ${inter_vrf_string} + Log many ${table_id} ${node} ${inter_vrf_string} + ${out}= vpp_term: Show IP Fib Table ${node} ${table_id} + log many ${out} + Should Contain ${out} ${inter_vrf_string} diff --git a/tests/robot/suites/traffic/l2xconnect_traffic/l2xconnect_trafic.robot b/tests/robot/suites/traffic/l2xconnect_traffic/l2xconnect_trafic.robot index 213c7307d6..e4555344c5 100644 --- a/tests/robot/suites/traffic/l2xconnect_traffic/l2xconnect_trafic.robot +++ b/tests/robot/suites/traffic/l2xconnect_traffic/l2xconnect_trafic.robot @@ -17,7 +17,7 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${SYNC_SLEEP}= 15s +${SYNC_SLEEP}= 2s *** Test Cases *** Configure Environment 1 @@ -34,12 +34,12 @@ Create 2 Loopbacks And Memifs And BD On VPP1 vpp_ctl: Put Loopback Interface With IP node=agent_vpp_1 name=bvi_loop1 mac=8a:f1:be:90:01:00 ip=10.1.1.100 prefix=24 vrf=20 enabled=true vpp_ctl: Put Memif Interface node=agent_vpp_1 name=memif1 mac=02:f1:be:90:03:00 master=true id=3 socket=m2.sock vrf=20 Create Bridge Domain bd2 With Autolearn On agent_vpp_1 with interfaces bvi_loop1, memif1 - Sleep 2s + Create 2 Memifs On VPP3 Create Slave memif0 on agent_vpp_3 with MAC 02:f1:be:90:00:03, key 2 and m1.sock socket vpp_ctl: Put Memif Interface node=agent_vpp_3 name=memif1 mac=02:f1:be:90:03:03 master=false id=3 socket=m2.sock vrf=20 - Sleep 2s + Ping Loopback1 X Loopback2 vpp_term: Check No Ping Within Interface agent_vpp_1 10.1.1.100 loop0 15 diff --git a/tests/robot/suites/traffic/libmemif/libmemif_master_trafic1.robot b/tests/robot/suites/traffic/libmemif/libmemif_master_trafic1.robot index 73a0d3206f..4640031448 100644 --- a/tests/robot/suites/traffic/libmemif/libmemif_master_trafic1.robot +++ b/tests/robot/suites/traffic/libmemif/libmemif_master_trafic1.robot @@ -17,8 +17,9 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${SYNC_SLEEP}= 10s -${RESYNC_SLEEP}= 1s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s + ${LIBMEMIF_IP1}= 192.168.1.2 ${VPP2MEMIF_IP1}= 192.168.1.2 ${VPP1MEMIF_IP1}= 192.168.1.1 @@ -38,19 +39,19 @@ Show Interfaces Before Setup Add Memif1 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=false id=0 ip=${VPP1MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} + Check Memif1 Interface Created On VPP1 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:62 master=false id=0 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} + Check Memif1 Interface On VPP1 is Modified - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=slave id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=slave id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Create And Chek Memif1 On Agent Libmemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 conn 0 1 @@ -59,16 +60,15 @@ Create And Chek Memif1 On Agent Libmemif 1 Should Contain ${out} link: up Check Memif1 Interface On VPP1 Connected To LibMemif - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=slave id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=slave id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 On VPP1 back vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=false id=0 ip=${VPP1MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} + Check Memif1 on Vpp1 is connected - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock - Sleep ${SYNC_SLEEP} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Ping VPP1 -> Agent Libmemif 1 vpp_term: Check Ping agent_vpp_1 ${LIBMEMIF_IP1} @@ -93,35 +93,31 @@ Check Ping VPP1 -> Agent Libmemif 1 After Resync Delete Memif On Agent Libmemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 del 0 - Sleep ${SYNC_SLEEP} + Check Memif1 Interface On VPP1 Disconnected After Master Deleted - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Create Memif1 On Agent Libmemif 1 Again ${out}= lmterm: Issue Command agent_libmemif_1 conn 0 1 - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 Connected After Master Deleted and Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Ping VPP1 -> Agent Libmemif 1 After Delete and Create vpp_term: Check Ping agent_vpp_1 ${LIBMEMIF_IP1} - Sleep 850s ###### Here VPP crashes Modify Memif1 Interface On VPP1 While Connected vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:62 master=false id=0 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} + Check Memif1 Interface On VPP1 Modified - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=slave id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=slave id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock -Final Sleep - Sleep 250s ########################################################### diff --git a/tests/robot/suites/traffic/libmemif/libmemif_master_trafic2.robot b/tests/robot/suites/traffic/libmemif/libmemif_master_trafic2.robot index 18cf045bda..adfc2279c6 100644 --- a/tests/robot/suites/traffic/libmemif/libmemif_master_trafic2.robot +++ b/tests/robot/suites/traffic/libmemif/libmemif_master_trafic2.robot @@ -17,8 +17,8 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${SYNC_SLEEP}= 10s -${RESYNC_SLEEP}= 1s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s ${LIBMEMIF_IP1}= 192.168.1.2 ${VPP2MEMIF_IP1}= 192.168.1.2 ${VPP1MEMIF_IP1}= 192.168.1.1 @@ -38,19 +38,17 @@ Show Interfaces Before Setup Add Memif1 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=false id=0 ip=${VPP1MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface Created On VPP1 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:62 master=false id=0 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 is Modified - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=slave id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=slave id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Create And Chek Memif1 On Agent Libmemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 conn 0 1 @@ -59,16 +57,14 @@ Create And Chek Memif1 On Agent Libmemif 1 Should Contain ${out} link: up Check Memif1 Interface On VPP1 Connected To LibMemif - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=slave id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=slave id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 On VPP1 back vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=false id=0 ip=${VPP1MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 on Vpp1 is connected - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock - Sleep ${SYNC_SLEEP} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Ping VPP1 -> Agent Libmemif 1 vpp_term: Check Ping agent_vpp_1 ${LIBMEMIF_IP1} @@ -93,19 +89,17 @@ Check Ping VPP1 -> Agent Libmemif 1 After Resync Delete Memif On Agent Libmemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 del 0 - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 Disconnected After Master Deleted - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Create Memif1 On Agent Libmemif 1 Again ${out}= lmterm: Issue Command agent_libmemif_1 conn 0 1 - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 Connected After Master Deleted and Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Ping VPP1 -> Agent Libmemif 1 After Delete and Create vpp_term: Check Ping agent_vpp_1 ${LIBMEMIF_IP1} @@ -151,8 +145,8 @@ Create And Check Memif1 On Agent Libmemif 1 After node restart2 Should Contain ${out} link: up Check Memif1 Interface On VPP1 Connected After Node Restart2 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock ${out}= lmterm: Issue Command agent_libmemif_1 show Create Memif2 On Agent Libmemif 1 @@ -167,8 +161,8 @@ Check Memif 1 and Memif2 On Agent LibMemif 1 Should Contain ${out} link: down Check Memif1 Interface On VPP1 Connected After Second Libmemif Added - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock ${out}= lmterm: Issue Command agent_libmemif_1 show ############################################################################ @@ -205,13 +199,11 @@ Check LibMemif1 down and LibMemif2 down Add Memif2 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif2 mac=62:61:61:61:51:51 master=slave id=1 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} - Sleep ${SYNC_SLEEP} - Sleep ${SYNC_SLEEP} + Check Memif2 Interface Created On VPP1 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:51:51 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=62:61:61:61:51:51 role=slave id=1 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=62:61:61:61:51:51 role=slave id=1 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check LibMemif1 down and LibMemif2 up ${out}= lmterm: Issue Command agent_libmemif_1 show diff --git a/tests/robot/suites/traffic/libmemif/libmemif_slave_trafic1.robot b/tests/robot/suites/traffic/libmemif/libmemif_slave_trafic1.robot index ff3d99d42d..f2cb2e0801 100644 --- a/tests/robot/suites/traffic/libmemif/libmemif_slave_trafic1.robot +++ b/tests/robot/suites/traffic/libmemif/libmemif_slave_trafic1.robot @@ -17,8 +17,8 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${SYNC_SLEEP}= 10s -${RESYNC_SLEEP}= 1s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s ${LIBMEMIF_IP1}= 192.168.1.2 ${VPP2MEMIF_IP1}= 192.168.1.2 ${VPP1MEMIF_IP1}= 192.168.1.1 @@ -38,63 +38,59 @@ Show Interfaces Before Setup Add Memif1 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=true id=0 ip=${VPP1MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface Created On VPP1 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:62 master=true id=0 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 is Modified - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 Interface On VPP1 To Previous Values vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=true id=0 ip=${VPP1MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 Modified Back - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock ############################################################################## Add Memif1 Interface On VPP2 vpp_ctl: Put Memif Interface With IP node=agent_vpp_2 name=vpp2_memif1 mac=62:61:61:61:51:51 master=false id=0 ip=${VPP2MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} + Check Memif1 Interface Created And Connected On VPP2 - vpp_term: Interface Is Created node=agent_vpp_2 mac=62:61:61:61:51:51 - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=62:61:61:61:51:51 role=slave id=0 ipv4=${VPP2MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_2 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=62:61:61:61:51:51 role=slave id=0 ipv4=${VPP2MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Memif1 Interface On VPP1 Connected To VPP2 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 Interface On VPP1 While Connected To VPP2 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:62 master=true id=0 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} + Check Memif1 Interface On VPP1 Modified While Connected - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Delete Memif1 Interface On VPP2 - vpp_ctl: Delete VPP Interface node=agent_vpp_2 name=vpp2_memif1 - vpp_term: Interface Is Deleted node=agent_vpp_2 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_ctl: Delete VPP Interface node=agent_vpp_2 name=vpp2_memif1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_2 mac=62:61:61:61:51:51 Check VPP1_memif1 Interface Is Disconnected - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 Interface On VPP1 To Previous Values After Slave Delete vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=true id=0 ip=${VPP1MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 Modified Back After Slave Delete - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock ############################################################################# @@ -105,8 +101,8 @@ Create And Chek Memif1 On Agent Libmemif 1 Should Contain ${out} link: up Check Memif1 Interface On VPP1 Connected To LibMemif - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Ping VPP1 -> Agent Libmemif 1 vpp_term: Check Ping agent_vpp_1 ${LIBMEMIF_IP1} @@ -135,19 +131,19 @@ Delete Memif On Agent Libmemif 1 Check Memif1 Interface On VPP1 Disconnected After Slave Deleted vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock - Sleep ${SYNC_SLEEP} + Check Memif1 Interface On VPP1 Disconnected After Slave Deleted Again - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Create Memif1 On Agent Libmemif 1 Again ${out}= lmterm: Issue Command agent_libmemif_1 conn 0 0 - Sleep ${SYNC_SLEEP} + Check Memif1 Interface On VPP1 Connected After Slave Deleted and Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Ping VPP1 -> Agent Libmemif 1 After Delete and Create vpp_term: Check Ping agent_vpp_1 ${LIBMEMIF_IP1} @@ -209,19 +205,19 @@ Check Memif 1 and Memif2 On Agent LibMemif 1 Should Contain ${out} link: down Check Memif1 Interface On VPP1 Connected After Second Libmemif Added - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock ${out}= lmterm: Issue Command agent_libmemif_1 show ############################################################################ ##### Here VPP crashes Add Memif2 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif2 mac=62:61:61:61:51:51 master=true id=1 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} + Check Memif2 Interface Created On VPP1 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:51:51 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=62:61:61:61:51:51 role=master id=1 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=62:61:61:61:51:51 role=master id=1 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Memif 1 and Memif2 On Agent LibMemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 show @@ -232,11 +228,11 @@ Check Memif 1 and Memif2 On Agent LibMemif 1 Delete Memif2 Interface On VPP1 After Resync vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=vpp1_memif2 - vpp_term: Interface Is Deleted node=agent_vpp_1 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_1 mac=62:61:61:61:51:51 Delete Memif1 Interface On VPP1 vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=vpp1_memif1 - vpp_term: Interface Is Deleted node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_1 mac=62:61:61:61:61:61 Check Memif 1 and Memif2 On Agent LibMemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 show @@ -246,11 +242,11 @@ Check Memif 1 and Memif2 On Agent LibMemif 1 Add Memif2 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif2 mac=62:61:61:61:51:51 master=true id=1 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} + Check Memif2 Interface Created On VPP1 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:51:51 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=62:61:61:61:51:51 role=master id=1 ipv4=${VPP1MEMIF_IP2}/24 connecte + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=62:61:61:61:51:51 role=master id=1 ipv4=${VPP1MEMIF_IP2}/24 connecte Check Memif 1 and Memif2 On Agent LibMemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 show diff --git a/tests/robot/suites/traffic/libmemif/libmemif_slave_trafic2.robot b/tests/robot/suites/traffic/libmemif/libmemif_slave_trafic2.robot index ff3d99d42d..243663d311 100644 --- a/tests/robot/suites/traffic/libmemif/libmemif_slave_trafic2.robot +++ b/tests/robot/suites/traffic/libmemif/libmemif_slave_trafic2.robot @@ -17,8 +17,8 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${SYNC_SLEEP}= 10s -${RESYNC_SLEEP}= 1s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s ${LIBMEMIF_IP1}= 192.168.1.2 ${VPP2MEMIF_IP1}= 192.168.1.2 ${VPP1MEMIF_IP1}= 192.168.1.1 @@ -38,63 +38,58 @@ Show Interfaces Before Setup Add Memif1 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=true id=0 ip=${VPP1MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} + Check Memif1 Interface Created On VPP1 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:62 master=true id=0 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 is Modified - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 Interface On VPP1 To Previous Values vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=true id=0 ip=${VPP1MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 Modified Back - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock ############################################################################## Add Memif1 Interface On VPP2 vpp_ctl: Put Memif Interface With IP node=agent_vpp_2 name=vpp2_memif1 mac=62:61:61:61:51:51 master=false id=0 ip=${VPP2MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface Created And Connected On VPP2 - vpp_term: Interface Is Created node=agent_vpp_2 mac=62:61:61:61:51:51 - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=62:61:61:61:51:51 role=slave id=0 ipv4=${VPP2MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_2 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=62:61:61:61:51:51 role=slave id=0 ipv4=${VPP2MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Memif1 Interface On VPP1 Connected To VPP2 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 Interface On VPP1 While Connected To VPP2 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:62 master=true id=0 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 Modified While Connected - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Delete Memif1 Interface On VPP2 vpp_ctl: Delete VPP Interface node=agent_vpp_2 name=vpp2_memif1 - vpp_term: Interface Is Deleted node=agent_vpp_2 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_2 mac=62:61:61:61:51:51 Check VPP1_memif1 Interface Is Disconnected - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 Interface On VPP1 To Previous Values After Slave Delete vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=true id=0 ip=${VPP1MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 Modified Back After Slave Delete - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock ############################################################################# @@ -105,8 +100,8 @@ Create And Chek Memif1 On Agent Libmemif 1 Should Contain ${out} link: up Check Memif1 Interface On VPP1 Connected To LibMemif - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Ping VPP1 -> Agent Libmemif 1 vpp_term: Check Ping agent_vpp_1 ${LIBMEMIF_IP1} @@ -133,21 +128,21 @@ Delete Memif On Agent Libmemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 del 0 Check Memif1 Interface On VPP1 Disconnected After Slave Deleted - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock - Sleep ${SYNC_SLEEP} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Check Memif1 Interface On VPP1 Disconnected After Slave Deleted Again - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Create Memif1 On Agent Libmemif 1 Again ${out}= lmterm: Issue Command agent_libmemif_1 conn 0 0 - Sleep ${SYNC_SLEEP} + Check Memif1 Interface On VPP1 Connected After Slave Deleted and Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Ping VPP1 -> Agent Libmemif 1 After Delete and Create vpp_term: Check Ping agent_vpp_1 ${LIBMEMIF_IP1} @@ -217,11 +212,11 @@ Check Memif1 Interface On VPP1 Connected After Second Libmemif Added ##### Here VPP crashes Add Memif2 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif2 mac=62:61:61:61:51:51 master=true id=1 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} + Check Memif2 Interface Created On VPP1 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:51:51 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=62:61:61:61:51:51 role=master id=1 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=62:61:61:61:51:51 role=master id=1 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Memif 1 and Memif2 On Agent LibMemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 show @@ -232,11 +227,11 @@ Check Memif 1 and Memif2 On Agent LibMemif 1 Delete Memif2 Interface On VPP1 After Resync vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=vpp1_memif2 - vpp_term: Interface Is Deleted node=agent_vpp_1 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_1 mac=62:61:61:61:51:51 Delete Memif1 Interface On VPP1 vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=vpp1_memif1 - vpp_term: Interface Is Deleted node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_1 mac=62:61:61:61:61:61 Check Memif 1 and Memif2 On Agent LibMemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 show @@ -246,11 +241,10 @@ Check Memif 1 and Memif2 On Agent LibMemif 1 Add Memif2 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif2 mac=62:61:61:61:51:51 master=true id=1 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif2 Interface Created On VPP1 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:51:51 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=62:61:61:61:51:51 role=master id=1 ipv4=${VPP1MEMIF_IP2}/24 connecte + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=62:61:61:61:51:51 role=master id=1 ipv4=${VPP1MEMIF_IP2}/24 connecte Check Memif 1 and Memif2 On Agent LibMemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 show diff --git a/tests/robot/suites/traffic/linux_traffic/1x_vpp_3x_namespaces_traffic.robot b/tests/robot/suites/traffic/linux_traffic/1x_vpp_3x_namespaces_traffic.robot index 4bd580a8fe..ef84851054 100644 --- a/tests/robot/suites/traffic/linux_traffic/1x_vpp_3x_namespaces_traffic.robot +++ b/tests/robot/suites/traffic/linux_traffic/1x_vpp_3x_namespaces_traffic.robot @@ -16,7 +16,8 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${CONFIG_SLEEP}= 1s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s ${RESYNC_SLEEP}= 1s # wait for resync vpps after restart ${RESYNC_WAIT}= 30s @@ -37,13 +38,11 @@ Setup Interfaces vpp_ctl: Put Veth Interface Via Linux Plugin node=agent_vpp_1 namespace=ns2 name=ns2_veth3 host_if_name=ns2_veth3_linux mac=92:c7:42:67:ab:cf peer=ns3_veth3 ip=192.168.22.5 prefix=30 vpp_ctl: Put Veth Interface Via Linux Plugin node=agent_vpp_1 namespace=ns3 name=ns3_veth3 host_if_name=ns3_veth3_linux mac=92:c7:42:67:ab:ce peer=ns2_veth3 ip=192.168.22.6 prefix=30 - Sleep ${CONFIG_SLEEP} - Chcek Linux Interfaces - Check Linux Interfaces node=agent_vpp_1 namespace=ns1 interface=ns1_veth1 - Check Linux Interfaces node=agent_vpp_1 namespace=ns2 interface=ns2_veth2 - Check Linux Interfaces node=agent_vpp_1 namespace=ns2 interface=ns2_veth3 - Check Linux Interfaces node=agent_vpp_1 namespace=ns3 interface=ns3_veth3 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Interfaces node=agent_vpp_1 namespace=ns1 interface=ns1_veth1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Interfaces node=agent_vpp_1 namespace=ns2 interface=ns2_veth2 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Interfaces node=agent_vpp_1 namespace=ns2 interface=ns2_veth3 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Interfaces node=agent_vpp_1 namespace=ns3 interface=ns3_veth3 Ping In Namespaces # This should work by default after veth interface setup @@ -65,11 +64,10 @@ Create Linux Defalut Routes #vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=ns3 interface=ns3_veth3 routename=innercross2 ip=192.168.22.2 prefix=32 next_hop=192.168.22.6 vpp_ctl: Put Default Linux Route node=agent_vpp_1 namespace=ns1 interface=ns1_veth1 routename=innercross1 next_hop=192.168.22.1 vpp_ctl: Put Default Linux Route node=agent_vpp_1 namespace=ns3 interface=ns3_veth3 routename=innercross2 next_hop=192.168.22.6 - Sleep ${CONFIG_SLEEP} Check Linux Default Routes - Check Linux Default Routes node=agent_vpp_1 namespace=ns1 next_hop=192.168.22.1 - Check Linux Default Routes node=agent_vpp_1 namespace=ns3 next_hop=192.168.22.6 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Default Routes node=agent_vpp_1 namespace=ns1 next_hop=192.168.22.1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Default Routes node=agent_vpp_1 namespace=ns3 next_hop=192.168.22.6 Ping In Namespaces Again Ping in namespace node=agent_vpp_1 namespace=ns1 ip=192.168.22.5 @@ -83,7 +81,6 @@ Create Linux Routes2 #This needs to be fixed - https://jira.pantheon.sk/browse/ODPM-743 vpp_ctl: Put Linux Route Without Interface node=agent_vpp_1 namespace=ns1 routename=outercross1 ip=192.168.22.6 prefix=32 next_hop=192.168.22.2 vpp_ctl: Put Linux Route Without Interface node=agent_vpp_1 namespace=ns3 routename=outercross2 ip=192.168.22.1 prefix=32 next_hop=192.168.22.5 - Sleep ${CONFIG_SLEEP} #temporarily - because previous commands does not work ${out}= Execute In Container agent_vpp_1 ip netns exec ns1 ip route add 192.168.22.6/32 via 192.168.22.2 @@ -100,8 +97,8 @@ Create Linux Routes2 ${out}= Execute In Container agent_vpp_1 ip netns exec ns2 sysctl -w net.ipv4.ip_forward=1 Check Linux Routes2 - Check Linux Routes Gateway node=agent_vpp_1 namespace=ns1 ip=192.168.22.6 next_hop=192.168.22.2 - Check Linux Routes Gateway node=agent_vpp_1 namespace=ns3 ip=192.168.22.1 next_hop=192.168.22.5 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes Gateway node=agent_vpp_1 namespace=ns1 ip=192.168.22.6 next_hop=192.168.22.2 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes Gateway node=agent_vpp_1 namespace=ns3 ip=192.168.22.1 next_hop=192.168.22.5 Ping in namespace node=agent_vpp_1 namespace=ns1 ip=192.168.22.6 Ping in namespace node=agent_vpp_1 namespace=ns3 ip=192.168.22.1 diff --git a/tests/robot/suites/traffic/physical_int_traffic/physical_int_traffic.robot b/tests/robot/suites/traffic/physical_int_traffic/physical_int_traffic.robot index 3b567c6a75..862cff9113 100644 --- a/tests/robot/suites/traffic/physical_int_traffic/physical_int_traffic.robot +++ b/tests/robot/suites/traffic/physical_int_traffic/physical_int_traffic.robot @@ -15,7 +15,8 @@ Suite Teardown Testsuite Teardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${CONFIG_SLEEP}= 1s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s ${RESYNC_SLEEP}= 1s # wait for resync vpps after restart ${RESYNC_WAIT}= 30s diff --git a/tests/robot/suites/traffic/tap_int_traffic/tap_int_and_route_config_order_traffic.robot b/tests/robot/suites/traffic/tap_int_traffic/tap_int_and_route_config_order_traffic.robot index 07f7e30855..4e6962ba14 100644 --- a/tests/robot/suites/traffic/tap_int_traffic/tap_int_and_route_config_order_traffic.robot +++ b/tests/robot/suites/traffic/tap_int_traffic/tap_int_and_route_config_order_traffic.robot @@ -11,6 +11,8 @@ Resource ../../../libraries/pretty_keywords.robot Force Tags trafficIPv4 Suite Setup Testsuite Setup Suite Teardown Testsuite Teardown +Test Setup TestSetup +Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common @@ -35,9 +37,10 @@ ${IP_VPP1_MEMIF1}= 192.168.1.1 ${IP_VPP2_MEMIF1}= 192.168.1.2 ${PREFIX}= 24 ${UP_STATE}= up -${SYNC_SLEEP}= 10s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s # wait for resync vpps after restart -${RESYNC_WAIT}= 50s +${RESYNC_WAIT}= 20s *** Test Cases *** Configure Environment @@ -53,25 +56,25 @@ Add VPP1_TAP1 Interface And Check It Was Created vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_VPP1_TAP1} vpp_ctl: Put TAP Interface With IP node=agent_vpp_1 name=${NAME_VPP1_TAP1} mac=${MAC_VPP1_TAP1} ip=${IP_VPP1_TAP1} prefix=${PREFIX} host_if_name=linux_${NAME_VPP1_TAP1} linux: Set Host TAP Interface node=agent_vpp_1 host_if_name=linux_${NAME_VPP1_TAP1} ip=${IP_LINUX_VPP1_TAP1} prefix=${PREFIX} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_TAP1} ${actual_state}= vpp_term: Check TAP Interface State agent_vpp_1 ${NAME_VPP1_TAP1} mac=${MAC_VPP1_TAP1} ipv4=${IP_VPP1_TAP1}/${PREFIX} state=${UP_STATE} Add VPP1_memif1 Interface vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=${NAME_VPP1_MEMIF1} mac=${MAC_VPP1_MEMIF1} master=true id=1 ip=${IP_VPP1_MEMIF1} prefix=24 socket=memif.sock - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} Add VPP2_TAP1 Interface And Check It Was Created vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MAC_VPP2_TAP1} vpp_ctl: Put TAP Interface With IP node=agent_vpp_2 name=${NAME_VPP2_TAP1} mac=${MAC_VPP2_TAP1} ip=${IP_VPP2_TAP1} prefix=${PREFIX} host_if_name=linux_${NAME_VPP2_TAP1} linux: Set Host TAP Interface node=agent_vpp_2 host_if_name=linux_${NAME_VPP2_TAP1} ip=${IP_LINUX_VPP2_TAP1} prefix=${PREFIX} - vpp_term: Interface Is Created node=agent_vpp_2 mac=${MAC_VPP2_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_2 mac=${MAC_VPP2_TAP1} ${actual_state}= vpp_term: Check TAP Interface State agent_vpp_2 ${NAME_VPP2_TAP1} mac=${MAC_VPP2_TAP1} ipv4=${IP_VPP2_TAP1}/${PREFIX} state=${UP_STATE} Add VPP2_memif1 Interface vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MAC_VPP2_MEMIF1} vpp_ctl: Put Memif Interface With IP node=agent_vpp_2 name=${NAME_VPP2_MEMIF1} mac=${MAC_VPP2_MEMIF1} master=false id=1 ip=${IP_VPP2_MEMIF1} prefix=24 socket=memif.sock - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} Add Static Route From VPP1 Linux To VPP2 vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=${EMPTY} interface=${NAME_VPP1_TAP1} routename=${NAME_VPP1_LINUX_TO_VPP2} ip=${IP_VPP2_TAP1_NETWORK} next_hop=${EMPTY} @@ -217,3 +220,8 @@ Linux_VPP2_TAP1 Routes Are Configured Equally In Both Config Orders Should Be Equal ${linux_vpp2_tap1_route1} ${linux_vpp2_tap1_route2} *** Keywords *** +TestSetup + Make Datastore Snapshots ${TEST_NAME}_test_setup + +TestTeardown + Make Datastore Snapshots ${TEST_NAME}_test_teardown \ No newline at end of file diff --git a/tests/robot/suites/traffic/tap_int_traffic/tap_int_traffic.robot b/tests/robot/suites/traffic/tap_int_traffic/tap_int_traffic.robot index c9f47df67f..a7f881ed75 100644 --- a/tests/robot/suites/traffic/tap_int_traffic/tap_int_traffic.robot +++ b/tests/robot/suites/traffic/tap_int_traffic/tap_int_traffic.robot @@ -11,6 +11,8 @@ Resource ../../../libraries/pretty_keywords.robot Force Tags trafficIPv4 Suite Setup Testsuite Setup Suite Teardown Testsuite Teardown +Test Setup TestSetup +Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common @@ -33,7 +35,8 @@ ${IP_VPP1_MEMIF1}= 192.168.1.1 ${IP_VPP2_MEMIF1}= 192.168.1.2 ${PREFIX}= 24 ${UP_STATE}= up -${SYNC_SLEEP}= 10s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s # wait for resync vpps after restart ${RESYNC_WAIT}= 50s @@ -55,7 +58,7 @@ Add VPP1_TAP1 Interface Check VPP1_TAP1 Interface Is Created ${interfaces}= vat_term: Interfaces Dump node=agent_vpp_1 Log ${interfaces} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_TAP1} ${actual_state}= vpp_term: Check TAP interface State agent_vpp_1 ${NAME_VPP1_TAP1} mac=${MAC_VPP1_TAP1} ipv4=${IP_VPP1_TAP1}/${PREFIX} state=${UP_STATE} Check Ping Between VPP1 and linux_VPP1_TAP1 Interface @@ -65,7 +68,7 @@ Check Ping Between VPP1 and linux_VPP1_TAP1 Interface Add VPP1_memif1 Interface vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=${NAME_VPP1_MEMIF1} mac=${MAC_VPP1_MEMIF1} master=true id=1 ip=${IP_VPP1_MEMIF1} prefix=24 socket=memif.sock - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} Add VPP2_TAP1 Interface vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MAC_VPP2_TAP1} @@ -75,7 +78,7 @@ Add VPP2_TAP1 Interface Check VPP2_TAP1 Interface Is Created ${interfaces}= vat_term: Interfaces Dump node=agent_vpp_1 Log ${interfaces} - vpp_term: Interface Is Created node=agent_vpp_2 mac=${MAC_VPP2_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_2 mac=${MAC_VPP2_TAP1} ${actual_state}= vpp_term: Check TAP interface State agent_vpp_2 ${NAME_VPP2_TAP1} mac=${MAC_VPP2_TAP1} ipv4=${IP_VPP2_TAP1}/${PREFIX} state=${UP_STATE} Check Ping Between VPP2 And linux_VPP2_TAP1 Interface @@ -85,7 +88,7 @@ Check Ping Between VPP2 And linux_VPP2_TAP1 Interface Add VPP2_memif1 Interface vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MAC_VPP2_MEMIF1} vpp_ctl: Put Memif Interface With IP node=agent_vpp_2 name=${NAME_VPP2_MEMIF1} mac=${MAC_VPP2_MEMIF1} master=false id=1 ip=${IP_VPP2_MEMIF1} prefix=24 socket=memif.sock - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} Check Ping From VPP1 To VPP2_memif1 vpp_term: Check Ping node=agent_vpp_1 ip=${IP_VPP2_MEMIF1} @@ -151,7 +154,11 @@ Check Interfaces On VPP1 After Resync Should Contain ${out} ${int} ${int}= vpp_ctl: Get Interface Internal Name node=agent_vpp_1 interface=${NAME_VPP1_TAP1} Should Contain ${out} ${int} +TestSetup + Make Datastore Snapshots ${TEST_NAME}_test_setup +TestTeardown + Make Datastore Snapshots ${TEST_NAME}_test_teardown Check Linux Interfaces On VPP2 After Resync ${out}= Execute In Container agent_vpp_2 ip a Log ${out} @@ -180,4 +187,9 @@ Check Ping From VPP2 Linux To VPP1_TAP1 And LINUX_VPP1_TAP1 After Resync linux: Check Ping node=agent_vpp_2 ip=${IP_VPP1_TAP1} linux: Check Ping node=agent_vpp_2 ip=${IP_LINUX_VPP1_TAP1} -#*** Keywords *** +*** Keywords *** +TestSetup + Make Datastore Snapshots ${TEST_NAME}_test_setup + +TestTeardown + Make Datastore Snapshots ${TEST_NAME}_test_teardown \ No newline at end of file diff --git a/tests/robot/suites/traffic/tapv2_int_traffic/tapv2_int_and_route_config_order_traffic.robot b/tests/robot/suites/traffic/tapv2_int_traffic/tapv2_int_and_route_config_order_traffic.robot index 01263581a5..734ff8e0b4 100644 --- a/tests/robot/suites/traffic/tapv2_int_traffic/tapv2_int_and_route_config_order_traffic.robot +++ b/tests/robot/suites/traffic/tapv2_int_traffic/tapv2_int_and_route_config_order_traffic.robot @@ -11,6 +11,8 @@ Resource ../../../libraries/pretty_keywords.robot Force Tags trafficIPv4 Suite Setup Testsuite Setup Suite Teardown Testsuite Teardown +Test Setup TestSetup +Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common @@ -35,9 +37,10 @@ ${IP_VPP1_MEMIF1}= 192.168.1.1 ${IP_VPP2_MEMIF1}= 192.168.1.2 ${PREFIX}= 24 ${UP_STATE}= up -${SYNC_SLEEP}= 10s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s # wait for resync vpps after restart -${RESYNC_WAIT}= 50s +${RESYNC_WAIT}= 20s *** Test Cases *** Configure Environment @@ -53,25 +56,25 @@ Add VPP1_TAP1 Interface And Check It Was Created vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_VPP1_TAP1} vpp_ctl: Put TAPv2 Interface With IP node=agent_vpp_1 name=${NAME_VPP1_TAP1} mac=${MAC_VPP1_TAP1} ip=${IP_VPP1_TAP1} prefix=${PREFIX} host_if_name=linux_${NAME_VPP1_TAP1} linux: Set Host TAP Interface node=agent_vpp_1 host_if_name=linux_${NAME_VPP1_TAP1} ip=${IP_LINUX_VPP1_TAP1} prefix=${PREFIX} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_TAP1} ${actual_state}= vpp_term: Check TAPv2 Interface State agent_vpp_1 ${NAME_VPP1_TAP1} mac=${MAC_VPP1_TAP1} ipv4=${IP_VPP1_TAP1}/${PREFIX} state=${UP_STATE} Add VPP1_memif1 Interface vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=${NAME_VPP1_MEMIF1} mac=${MAC_VPP1_MEMIF1} master=true id=1 ip=${IP_VPP1_MEMIF1} prefix=24 socket=memif.sock - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} Add VPP2_TAP1 Interface And Check It Was Created vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MAC_VPP2_TAP1} vpp_ctl: Put TAPv2 Interface With IP node=agent_vpp_2 name=${NAME_VPP2_TAP1} mac=${MAC_VPP2_TAP1} ip=${IP_VPP2_TAP1} prefix=${PREFIX} host_if_name=linux_${NAME_VPP2_TAP1} linux: Set Host TAP Interface node=agent_vpp_2 host_if_name=linux_${NAME_VPP2_TAP1} ip=${IP_LINUX_VPP2_TAP1} prefix=${PREFIX} - vpp_term: Interface Is Created node=agent_vpp_2 mac=${MAC_VPP2_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_2 mac=${MAC_VPP2_TAP1} ${actual_state}= vpp_term: Check TAPv2 Interface State agent_vpp_2 ${NAME_VPP2_TAP1} mac=${MAC_VPP2_TAP1} ipv4=${IP_VPP2_TAP1}/${PREFIX} state=${UP_STATE} Add VPP2_memif1 Interface vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MAC_VPP2_MEMIF1} vpp_ctl: Put Memif Interface With IP node=agent_vpp_2 name=${NAME_VPP2_MEMIF1} mac=${MAC_VPP2_MEMIF1} master=false id=1 ip=${IP_VPP2_MEMIF1} prefix=24 socket=memif.sock - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} Add Static Route From VPP1 Linux To VPP2 vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=${EMPTY} interface=${NAME_VPP1_TAP1} routename=${NAME_VPP1_LINUX_TO_VPP2} ip=${IP_VPP2_TAP1_NETWORK} next_hop=${EMPTY} @@ -154,25 +157,25 @@ Add VPP1_TAP1 Interface And Check It Was Created 2 vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_VPP1_TAP1} vpp_ctl: Put TAPv2 Interface With IP node=agent_vpp_1 name=${NAME_VPP1_TAP1} mac=${MAC_VPP1_TAP1} ip=${IP_VPP1_TAP1} prefix=${PREFIX} host_if_name=linux_${NAME_VPP1_TAP1} linux: Set Host TAP Interface node=agent_vpp_1 host_if_name=linux_${NAME_VPP1_TAP1} ip=${IP_LINUX_VPP1_TAP1} prefix=${PREFIX} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_TAP1} ${actual_state}= vpp_term: Check TAPv2 Interface State agent_vpp_1 ${NAME_VPP1_TAP1} mac=${MAC_VPP1_TAP1} ipv4=${IP_VPP1_TAP1}/${PREFIX} state=${UP_STATE} Add VPP1_memif1 Interface 2 vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=${NAME_VPP1_MEMIF1} mac=${MAC_VPP1_MEMIF1} master=true id=1 ip=${IP_VPP1_MEMIF1} prefix=24 socket=memif.sock - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} Add VPP2_TAP1 Interface And Check It Was Created 2 vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MAC_VPP2_TAP1} vpp_ctl: Put TAPv2 Interface With IP node=agent_vpp_2 name=${NAME_VPP2_TAP1} mac=${MAC_VPP2_TAP1} ip=${IP_VPP2_TAP1} prefix=${PREFIX} host_if_name=linux_${NAME_VPP2_TAP1} linux: Set Host TAP Interface node=agent_vpp_2 host_if_name=linux_${NAME_VPP2_TAP1} ip=${IP_LINUX_VPP2_TAP1} prefix=${PREFIX} - vpp_term: Interface Is Created node=agent_vpp_2 mac=${MAC_VPP2_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_2 mac=${MAC_VPP2_TAP1} ${actual_state}= vpp_term: Check TAPv2 Interface State agent_vpp_2 ${NAME_VPP2_TAP1} mac=${MAC_VPP2_TAP1} ipv4=${IP_VPP2_TAP1}/${PREFIX} state=${UP_STATE} Add VPP2_memif1 Interface 2 vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MAC_VPP2_MEMIF1} vpp_ctl: Put Memif Interface With IP node=agent_vpp_2 name=${NAME_VPP2_MEMIF1} mac=${MAC_VPP2_MEMIF1} master=false id=1 ip=${IP_VPP2_MEMIF1} prefix=24 socket=memif.sock - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} Show Routes On VPP1 Linux 2 ${out}= Execute In Container agent_vpp_1 ip addr show linux_${NAME_VPP1_TAP1} @@ -217,3 +220,8 @@ Linux_VPP2_TAP1 Routes Are Configured Equally In Both Config Orders Should Be Equal ${linux_vpp2_tap1_route1} ${linux_vpp2_tap1_route2} *** Keywords *** +TestSetup + Make Datastore Snapshots ${TEST_NAME}_test_setup + +TestTeardown + Make Datastore Snapshots ${TEST_NAME}_test_teardown \ No newline at end of file diff --git a/tests/robot/suites/traffic/tapv2_int_traffic/tapv2_int_traffic.robot b/tests/robot/suites/traffic/tapv2_int_traffic/tapv2_int_traffic.robot index 134deb5258..c856aeaee8 100644 --- a/tests/robot/suites/traffic/tapv2_int_traffic/tapv2_int_traffic.robot +++ b/tests/robot/suites/traffic/tapv2_int_traffic/tapv2_int_traffic.robot @@ -11,6 +11,8 @@ Resource ../../../libraries/pretty_keywords.robot Force Tags trafficIPv4 Suite Setup Testsuite Setup Suite Teardown Testsuite Teardown +Test Setup TestSetup +Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common @@ -33,7 +35,8 @@ ${IP_VPP1_MEMIF1}= 192.168.1.1 ${IP_VPP2_MEMIF1}= 192.168.1.2 ${PREFIX}= 24 ${UP_STATE}= up -${SYNC_SLEEP}= 10s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s # wait for resync vpps after restart ${RESYNC_WAIT}= 50s @@ -55,7 +58,7 @@ Add VPP1_TAP1 Interface Check VPP1_TAP1 Interface Is Created ${interfaces}= vat_term: Interfaces Dump node=agent_vpp_1 Log ${interfaces} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_TAP1} ${actual_state}= vpp_term: Check TAPv2 interface State agent_vpp_1 ${NAME_VPP1_TAP1} mac=${MAC_VPP1_TAP1} ipv4=${IP_VPP1_TAP1}/${PREFIX} state=${UP_STATE} Check Ping Between VPP1 and linux_VPP1_TAP1 Interface @@ -65,7 +68,7 @@ Check Ping Between VPP1 and linux_VPP1_TAP1 Interface Add VPP1_memif1 Interface vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=${NAME_VPP1_MEMIF1} mac=${MAC_VPP1_MEMIF1} master=true id=1 ip=${IP_VPP1_MEMIF1} prefix=24 socket=memif.sock - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} Add VPP2_TAP1 Interface vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MAC_VPP2_TAP1} @@ -75,7 +78,7 @@ Add VPP2_TAP1 Interface Check VPP2_TAP1 Interface Is Created ${interfaces}= vat_term: Interfaces Dump node=agent_vpp_1 Log ${interfaces} - vpp_term: Interface Is Created node=agent_vpp_2 mac=${MAC_VPP2_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_2 mac=${MAC_VPP2_TAP1} ${actual_state}= vpp_term: Check TAPv2 interface State agent_vpp_2 ${NAME_VPP2_TAP1} mac=${MAC_VPP2_TAP1} ipv4=${IP_VPP2_TAP1}/${PREFIX} state=${UP_STATE} Check Ping Between VPP2 And linux_VPP2_TAP1 Interface @@ -85,7 +88,7 @@ Check Ping Between VPP2 And linux_VPP2_TAP1 Interface Add VPP2_memif1 Interface vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MAC_VPP2_MEMIF1} vpp_ctl: Put Memif Interface With IP node=agent_vpp_2 name=${NAME_VPP2_MEMIF1} mac=${MAC_VPP2_MEMIF1} master=false id=1 ip=${IP_VPP2_MEMIF1} prefix=24 socket=memif.sock - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} Check Ping From VPP1 To VPP2_memif1 vpp_term: Check Ping node=agent_vpp_1 ip=${IP_VPP2_MEMIF1} @@ -178,4 +181,9 @@ Check Ping From VPP2 Linux To VPP1_TAP1 And LINUX_VPP1_TAP1 After Resync linux: Check Ping node=agent_vpp_2 ip=${IP_VPP1_TAP1} linux: Check Ping node=agent_vpp_2 ip=${IP_LINUX_VPP1_TAP1} -#*** Keywords *** +*** Keywords *** +TestSetup + Make Datastore Snapshots ${TEST_NAME}_test_setup + +TestTeardown + Make Datastore Snapshots ${TEST_NAME}_test_teardown diff --git a/tests/robot/suites/traffic/veth_af_packet_traffic/veth_af_packet_traffic.robot b/tests/robot/suites/traffic/veth_af_packet_traffic/veth_af_packet_traffic.robot index 56a885c1bf..b400e8fdc6 100644 --- a/tests/robot/suites/traffic/veth_af_packet_traffic/veth_af_packet_traffic.robot +++ b/tests/robot/suites/traffic/veth_af_packet_traffic/veth_af_packet_traffic.robot @@ -17,9 +17,9 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${FINAL_SLEEP}= 5s -${SYNC_SLEEP}= 20s -${RESYNC_SLEEP}= 45s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s +${RESYNC_SLEEP}= 15s ${AGENT1_VETH_MAC}= 02:00:00:00:00:01 ${AGENT2_VETH_MAC}= 02:00:00:00:00:02 diff --git a/tests/robot/suites/traffic/veth_afpacket_memif_vxlan_traffic/veth_afpacket_memif_vxlan_traffic.robot b/tests/robot/suites/traffic/veth_afpacket_memif_vxlan_traffic/veth_afpacket_memif_vxlan_traffic.robot index 4a55f8bd78..fdb603b6e5 100644 --- a/tests/robot/suites/traffic/veth_afpacket_memif_vxlan_traffic/veth_afpacket_memif_vxlan_traffic.robot +++ b/tests/robot/suites/traffic/veth_afpacket_memif_vxlan_traffic/veth_afpacket_memif_vxlan_traffic.robot @@ -275,7 +275,6 @@ Final Sleep After Resync For Manual Checking Sleep ${RESYNC_SLEEP} -*** Keywords *** *** Keywords *** TestSetup Make Datastore Snapshots ${TEST_NAME}_test_setup diff --git a/tests/robot/suites/traffic/veth_afpacket_memif_vxlan_traffic/veth_afpacket_memif_vxlan_traffic_other_vrf.robot b/tests/robot/suites/traffic/veth_afpacket_memif_vxlan_traffic/veth_afpacket_memif_vxlan_traffic_other_vrf.robot index cf3d489b34..1e998aa7f5 100644 --- a/tests/robot/suites/traffic/veth_afpacket_memif_vxlan_traffic/veth_afpacket_memif_vxlan_traffic_other_vrf.robot +++ b/tests/robot/suites/traffic/veth_afpacket_memif_vxlan_traffic/veth_afpacket_memif_vxlan_traffic_other_vrf.robot @@ -10,7 +10,9 @@ Resource ../../../libraries/pretty_keywords.robot Force Tags trafficIPv4 Suite Setup Testsuite Setup -Suite Teardown Testsuite Teardown +Suite Teardown Suite Cleanup +Test Setup TestSetup +Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common @@ -47,7 +49,7 @@ Setup Interfaces vpp_ctl: Put Bridge Domain node=agent_vpp_1 name=vpp1_bd1 ints=${ints} vpp_ctl: Put Memif Interface With IP node=agent_vpp_2 name=vpp2_memif1 mac=62:62:62:62:62:62 master=false id=1 ip=192.168.1.2 - vpp_ctl: Put Veth Interface With IP node=agent_vpp_2 name=vpp2_veth1 mac=22:21:21:21:21:21 peer=vpp2_veth2 ip=10.10.1.2 + vpp_ctl: Put Veth Interface With IP node=agent_vpp_2 name=vpp2_veth1 mac=22:21:21:21:21:21 peer=k tomu ti staci jedno vpp ip=10.10.1.2 vpp_ctl: Put Veth Interface node=agent_vpp_2 name=vpp2_veth2 mac=22:22:22:22:22:22 peer=vpp2_veth1 vpp_ctl: Put Afpacket Interface node=agent_vpp_2 name=vpp2_afpacket1 mac=a2:a2:a2:a2:a2:a2 host_int=vpp2_veth2 vpp_ctl: Put VXLan Interface node=agent_vpp_2 name=vpp2_vxlan1 src=192.168.1.2 dst=192.168.1.1 vni=5 @@ -162,8 +164,11 @@ Check Ping After Resync From VPP2 to VPP1 Resync Done No Operation -Final Sleep After Resync For Manual Checking - Sleep ${RESYNC_SLEEP} *** Keywords *** +TestSetup + Make Datastore Snapshots ${TEST_NAME}_test_setup + +TestTeardown + Make Datastore Snapshots ${TEST_NAME}_test_teardown \ No newline at end of file diff --git a/tests/robot/suites/traffic/vpp_2novpp_memif_traffic/vpp_2novpp_memif_traffic.robot b/tests/robot/suites/traffic/vpp_2novpp_memif_traffic/vpp_2novpp_memif_traffic.robot index 6caa3f571e..1b5d3d5a80 100644 --- a/tests/robot/suites/traffic/vpp_2novpp_memif_traffic/vpp_2novpp_memif_traffic.robot +++ b/tests/robot/suites/traffic/vpp_2novpp_memif_traffic/vpp_2novpp_memif_traffic.robot @@ -10,12 +10,14 @@ Resource ../../../libraries/pretty_keywords.robot Force Tags trafficIPv4 Suite Setup Testsuite Setup -Suite Teardown Testsuite Teardown +Suite Teardown Suite Cleanup +Test Setup TestSetup +Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common - +${SYNC_SLEEP}= 10s *** Test Cases *** Configure Environment @@ -49,3 +51,9 @@ Create Memif on Agent1 Ping from agent_vpp_2 to 10.1.1.1 +*** Keywords *** +TestSetup + Make Datastore Snapshots ${TEST_NAME}_test_setup + +TestTeardown + Make Datastore Snapshots ${TEST_NAME}_test_teardown \ No newline at end of file diff --git a/tests/robot/suites/trafficIPv6/3x_vpp_traffic/3x_vpp_trafficIPv6.robot b/tests/robot/suites/trafficIPv6/3x_vpp_traffic/3x_vpp_trafficIPv6.robot index 06794f2d6f..cd537b8719 100644 --- a/tests/robot/suites/trafficIPv6/3x_vpp_traffic/3x_vpp_trafficIPv6.robot +++ b/tests/robot/suites/trafficIPv6/3x_vpp_traffic/3x_vpp_trafficIPv6.robot @@ -17,7 +17,7 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${SYNC_SLEEP}= 15s +${SYNC_SLEEP}= 12s ${IP_1}= fd30::1:b:0:0:1 ${IP_2}= fd30::1:b:0:0:10 ${IP_3}= fd31::1:b:0:0:10 @@ -27,8 +27,6 @@ Configure Environment 1 [Tags] setup Add Agent VPP Node agent_vpp_1 Add Agent VPP Node agent_vpp_3 - Sleep ${SYNC_SLEEP} - Create Infs And BD1 On VPP1 Create loopback interface bvi_loop0 on agent_vpp_1 with ip ${IP_1}/64 and mac 8a:f1:be:90:00:00 @@ -41,33 +39,29 @@ Add Intf And Update BD1 On VPP1 Create Intfs And BD1 On VPP3 Create loopback interface bvi_loop0 on agent_vpp_3 with ip ${IP_2}/64 and mac 8a:f1:be:90:00:03 - Sleep 2s Create Slave memif0 on agent_vpp_3 with MAC 02:f1:be:90:00:03, key 2 and m1.sock socket - Sleep 2s Create Bridge Domain bd1 With Autolearn On agent_vpp_3 with interfaces bvi_loop0, memif0 - Sleep 2s + Sleep ${SYNC_SLEEP} Ping VPP3 From VPP1 And VPP2 Ping6 from agent_vpp_1 to ${IP_2} Moving Memif1 From BD1 To BD2 on VPP1 Create Bridge Domain bd1 With Autolearn On agent_vpp_1 with interfaces bvi_loop0, memif0 - Sleep 2s Create Bridge Domain bd2 With Autolearn On agent_vpp_1 with interfaces bvi_loop1, memif1, memif2 - Sleep 2s + Modify Loopback IP on VPP3 Create loopback interface bvi_loop0 on agent_vpp_3 with ip ${IP_3}/64 and mac 8a:f1:be:90:00:03 - Sleep 2s vpp_term: Show Interfaces agent_vpp_3 Modify Loopback IP on VPP3 Back Create loopback interface bvi_loop0 on agent_vpp_3 with ip ${IP_2}/64 and mac 8a:f1:be:90:00:03 - Sleep 2s vpp_term: Show Interfaces agent_vpp_3 Moving Memif1 From BD2 To BD1 on VPP1 Create Bridge Domain bd1 With Autolearn On agent_vpp_1 with interfaces bvi_loop0, memif0, memif1 Create Bridge Domain bd2 With Autolearn On agent_vpp_1 with interfaces bvi_loop1, memif2 + Sleep ${SYNC_SLEEP} Ping VPP3 From VPP1 And VPP2 Again Ping6 from agent_vpp_1 to ${IP_2} diff --git a/tests/robot/suites/trafficIPv6/acl_traffic/acl_trafficIPv6.robot b/tests/robot/suites/trafficIPv6/acl_traffic/acl_trafficIPv6.robot index 78cfac65d9..0b8914628d 100644 --- a/tests/robot/suites/trafficIPv6/acl_traffic/acl_trafficIPv6.robot +++ b/tests/robot/suites/trafficIPv6/acl_traffic/acl_trafficIPv6.robot @@ -18,8 +18,8 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${FINAL_SLEEP}= 5s -${SYNC_SLEEP}= 10s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s ${RESYNC_SLEEP}= 20s ${AGENT1_VETH_MAC}= 02:00:00:00:00:01 @@ -75,25 +75,25 @@ Create Loopbak Intfs Create loopback interface loop1 on agent_vpp_1 with ip ${IP_2}/64 and mac 8a:f1:be:90:20:00 Check Veth Interface On Agent1 - linux: Interface With IP Is Created node_1 mac=${AGENT1_VETH_MAC} ipv4=${IP_3_PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface With IP Is Created node_1 mac=${AGENT1_VETH_MAC} ipv4=${IP_3_PREFIX} # status check not implemented in linux plugin #linux: Check Veth Interface State agent_vpp_1 agent1_veth mac=${AGENT1_VETH_MAC} ipv6=${IP_3}/64 mtu=1500 state=up Check Veth Interface On Agent2 - linux: Interface With IP Is Created node_2 mac=${AGENT2_VETH_MAC} ipv4=${IP_4_PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} linux: Interface With IP Is Created node_2 mac=${AGENT2_VETH_MAC} ipv4=${IP_4_PREFIX} # status check not implemented in linux plugin #linux: Check Veth Interface State agent_vpp_1 agent2_veth mac=${AGENT2_VETH_MAC} ipv6=${IP_4}/64 mtu=1500 state=up Check Bridge Domain Is Created - vat_term: BD Is Created agent_vpp_1 IF_AFPIF_VSWITCH_node_1_node1_veth IF_AFPIF_VSWITCH_node_2_node2_veth + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: BD Is Created agent_vpp_1 IF_AFPIF_VSWITCH_node_1_node1_veth IF_AFPIF_VSWITCH_node_2_node2_veth Check loop0 Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=8a:f1:be:90:00:00 - vat_term: Check Loopback Interface State agent_vpp_1 loop0 enabled=1 mac=8a:f1:be:90:00:00 mtu=1500 ipv6=${IP_1}/64 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=8a:f1:be:90:00:00 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 loop0 enabled=1 mac=8a:f1:be:90:00:00 mtu=1500 ipv6=${IP_1}/64 Check loop1 Is Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=8a:f1:be:90:20:00 - vat_term: Check Loopback Interface State agent_vpp_1 loop0 enabled=1 mac=8a:f1:be:90:20:00 mtu=1500 ipv6=${IP_2}/64 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=8a:f1:be:90:20:00 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 loop0 enabled=1 mac=8a:f1:be:90:20:00 mtu=1500 ipv6=${IP_2}/64 Create BD fo Loopbacks Create Bridge Domain bd2 With Autolearn On agent_vpp_1 with interfaces loop0, loop1 diff --git a/tests/robot/suites/trafficIPv6/bridge_domain/test1_bridge_domainIPv6.robot b/tests/robot/suites/trafficIPv6/bridge_domain/test1_bridge_domainIPv6.robot index 3ecda9e678..ce70b2363f 100644 --- a/tests/robot/suites/trafficIPv6/bridge_domain/test1_bridge_domainIPv6.robot +++ b/tests/robot/suites/trafficIPv6/bridge_domain/test1_bridge_domainIPv6.robot @@ -31,7 +31,8 @@ ${IP_4}= fd31::1:b:0:0:1 ${IP_5}= fd31::1:b:0:0:2 ${PREFIX}= 64 -${SYNC_SLEEP}= 15s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Start 2 Agents @@ -41,45 +42,31 @@ Start 2 Agents Create Loopback Interface on Agent1 Create Loopback Interface bvi_loop0 On agent_vpp_1 With Ip ${IP_1}/${PREFIX} And Mac ${MAC_LOOP1} - Sleep ${SYNC_SLEEP} - vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop0 enabled=1 mac=${MAC_LOOP1} ipv6=${IP_1}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop0 enabled=1 mac=${MAC_LOOP1} ipv6=${IP_1}/${PREFIX} Create Memif Interface on Agent1 Create Master memif0 On agent_vpp_1 With MAC ${MAC_MEMIF1}, Key 1 And m1.sock Socket - Sleep ${SYNC_SLEEP} - vat_term: Check Memif Interface State agent_vpp_1 memif0 mac=${MAC_MEMIF1} role=master id=1 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 memif0 mac=${MAC_MEMIF1} role=master id=1 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock Create Loopback Interface on Agent2 Create Loopback Interface bvi_loop0 On agent_vpp_2 With Ip ${IP_2}/${PREFIX} And Mac ${MAC_LOOP2} - Sleep ${SYNC_SLEEP} - vat_term: Check Loopback Interface State agent_vpp_2 bvi_loop0 enabled=1 mac=${MAC_LOOP2} ipv6=${IP_2}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_2 bvi_loop0 enabled=1 mac=${MAC_LOOP2} ipv6=${IP_2}/${PREFIX} Create Memif Interface on Agent2 Create Slave memif0 On agent_vpp_2 With MAC ${MAC_MEMIF2}, Key 1 And m1.sock Socket - Sleep ${SYNC_SLEEP} - vat_term: Check Memif Interface State agent_vpp_2 memif0 mac=${MAC_MEMIF2} role=slave id=1 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 memif0 mac=${MAC_MEMIF2} role=slave id=1 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock Create BD on Agent1 Create Bridge Domain bd1 With Autolearn On agent_vpp_1 With Interfaces bvi_loop0, memif0 - Sleep ${SYNC_SLEEP} - Sleep ${SYNC_SLEEP} - -Check Created Interfaces Again - vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop0 enabled=1 mac=${MAC_LOOP1} ipv6=${IP_1}/${PREFIX} - vat_term: Check Loopback Interface State agent_vpp_2 bvi_loop0 enabled=1 mac=${MAC_LOOP2} ipv6=${IP_2}/${PREFIX} - vat_term: Check Memif Interface State agent_vpp_1 memif0 mac=${MAC_MEMIF1} role=master id=1 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock - vat_term: Check Memif Interface State agent_vpp_2 memif0 mac=${MAC_MEMIF2} role=slave id=1 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock Create BD on Agent2 Create Bridge Domain bd1 With Autolearn On agent_vpp_2 With Interfaces bvi_loop0, memif0 - Sleep ${SYNC_SLEEP} - Sleep ${SYNC_SLEEP} Check Created Interfaces Again2 - vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop0 enabled=1 mac=${MAC_LOOP1} ipv6=${IP_1}/${PREFIX} - vat_term: Check Loopback Interface State agent_vpp_2 bvi_loop0 enabled=1 mac=${MAC_LOOP2} ipv6=${IP_2}/${PREFIX} - vat_term: Check Memif Interface State agent_vpp_1 memif0 mac=${MAC_MEMIF1} role=master id=1 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock - vat_term: Check Memif Interface State agent_vpp_2 memif0 mac=${MAC_MEMIF2} role=slave id=1 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop0 enabled=1 mac=${MAC_LOOP1} ipv6=${IP_1}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_2 bvi_loop0 enabled=1 mac=${MAC_LOOP2} ipv6=${IP_2}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 memif0 mac=${MAC_MEMIF1} role=master id=1 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 memif0 mac=${MAC_MEMIF2} role=slave id=1 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock Check Traffic VPP1-VPP2 Ping6 From agent_vpp_1 To ${IP_2} @@ -104,24 +91,20 @@ Check Traffic VPP1-VPP2 # Sleep ${SYNC_SLEEP} # vat_term: Check Memif Interface State agent_vpp_3 memif0 mac=${MAC_MEMIF4} role=slave id=2 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m2.sock - Sleep ${SYNC_SLEEP} - Sleep ${SYNC_SLEEP} - Sleep ${SYNC_SLEEP} - -Check Created Interfaces Again3 - vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop0 enabled=1 mac=${MAC_LOOP1} ipv6=${IP_1}/${PREFIX} - vat_term: Check Loopback Interface State agent_vpp_2 bvi_loop0 enabled=1 mac=${MAC_LOOP2} ipv6=${IP_2}/${PREFIX} - vat_term: Check Memif Interface State agent_vpp_1 memif0 mac=${MAC_MEMIF1} role=master id=1 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock - vat_term: Check Memif Interface State agent_vpp_2 memif0 mac=${MAC_MEMIF2} role=slave id=1 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock - Create BD on Agent1 Create Bridge Domain bd1 With Autolearn On agent_vpp_1 With Interfaces bvi_loop0, memif0, memif1 - Sleep ${SYNC_SLEEP} Create BD on Agent3 Create Bridge Domain bd1 With Autolearn On agent_vpp_3 With Interfaces bvi_loop0, memif0 +Check Created Interfaces Again3 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop0 enabled=1 mac=${MAC_LOOP1} ipv6=${IP_1}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_2 bvi_loop0 enabled=1 mac=${MAC_LOOP2} ipv6=${IP_2}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 memif0 mac=${MAC_MEMIF1} role=master id=1 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 memif0 mac=${MAC_MEMIF2} role=slave id=1 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock + + Check Traffic VPP2-VPP3 Ping6 From agent_vpp_2 To ${IP_3} Ping6 From agent_vpp_3 To ${IP_2} diff --git a/tests/robot/suites/trafficIPv6/bridge_domain/test2_bridge_domainIPv6.robot b/tests/robot/suites/trafficIPv6/bridge_domain/test2_bridge_domainIPv6.robot index b961c83be5..d9ca830e5c 100644 --- a/tests/robot/suites/trafficIPv6/bridge_domain/test2_bridge_domainIPv6.robot +++ b/tests/robot/suites/trafficIPv6/bridge_domain/test2_bridge_domainIPv6.robot @@ -32,7 +32,8 @@ ${IP_4}= fd31::1:b:0:0:1 ${IP_5}= fd31::1:b:0:0:2 ${PREFIX}= 64 -${SYNC_SLEEP}= 15s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** First configure Bridge Domain with Memif interfaces and VXLan then add two agents and try traffic @@ -48,14 +49,12 @@ First configure Bridge Domain with Memif interfaces and VXLan then add two agent Start Agents Add Agent VPP Node agent_vpp_1 Add Agent VPP Node agent_vpp_2 - Sleep ${SYNC_SLEEP} Check Created Interfaces - vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop0 enabled=1 mac=${MAC_LOOP1} ipv6=${IP_1}/${PREFIX} - vat_term: Check Loopback Interface State agent_vpp_2 bvi_loop0 enabled=1 mac=${MAC_LOOP2} ipv6=${IP_2}/${PREFIX} - vat_term: Check Memif Interface State agent_vpp_1 memif0 mac=${MAC_MEMIF1} role=master id=1 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock - vat_term: Check Memif Interface State agent_vpp_2 memif0 mac=${MAC_MEMIF2} role=slave id=1 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock - + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop0 enabled=1 mac=${MAC_LOOP1} ipv6=${IP_4}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_2 bvi_loop0 enabled=1 mac=${MAC_LOOP2} ipv6=${IP_5}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 memif0 mac=${MAC_MEMIF1} role=master id=1 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m0.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 memif0 mac=${MAC_MEMIF2} role=slave id=1 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m0.sock Pinging Ping6 From agent_vpp_1 To ${IP_2} diff --git a/tests/robot/suites/trafficIPv6/bridge_domain/test3_bridge_domainIPv6.robot b/tests/robot/suites/trafficIPv6/bridge_domain/test3_bridge_domainIPv6.robot index f77d08ee9d..216d04b2a3 100644 --- a/tests/robot/suites/trafficIPv6/bridge_domain/test3_bridge_domainIPv6.robot +++ b/tests/robot/suites/trafficIPv6/bridge_domain/test3_bridge_domainIPv6.robot @@ -32,7 +32,8 @@ ${IP_4}= fd31::1:b:0:0:1 ${IP_5}= fd31::1:b:0:0:2 ${PREFIX}= 64 -${SYNC_SLEEP}= 15s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** Start Agents @@ -53,13 +54,12 @@ Setup second agent Create Bridge Domain without autolearn on Agent2 Create Bridge Domain bd1 Without Autolearn On agent_vpp_2 With Interfaces bvi_loop0, memif0 - Sleep ${SYNC_SLEEP} Check Created Interfaces - vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop0 enabled=1 mac=${MAC_LOOP1} ipv6=${IP_1}/${PREFIX} - vat_term: Check Loopback Interface State agent_vpp_2 bvi_loop0 enabled=1 mac=${MAC_LOOP2} ipv6=${IP_2}/${PREFIX} - vat_term: Check Memif Interface State agent_vpp_1 memif0 mac=${MAC_MEMIF1} role=master id=1 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock - vat_term: Check Memif Interface State agent_vpp_2 memif0 mac=${MAC_MEMIF2} role=slave id=1 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop0 enabled=1 mac=${MAC_LOOP1} ipv6=${IP_1}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_2 bvi_loop0 enabled=1 mac=${MAC_LOOP2} ipv6=${IP_2}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 memif0 mac=${MAC_MEMIF1} role=master id=1 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 memif0 mac=${MAC_MEMIF2} role=slave id=1 connected=1 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock Ping should fail Command: Ping From agent_vpp_1 To ${IP_2} should fail diff --git a/tests/robot/suites/trafficIPv6/ip_route/test1_ip_routeIPv6.robot b/tests/robot/suites/trafficIPv6/ip_route/test1_ip_routeIPv6.robot index 0bdf4221d2..d70c463059 100644 --- a/tests/robot/suites/trafficIPv6/ip_route/test1_ip_routeIPv6.robot +++ b/tests/robot/suites/trafficIPv6/ip_route/test1_ip_routeIPv6.robot @@ -34,7 +34,8 @@ ${MAC2_MEMIF1}= 02:f1:be:90:00:02 ${MAC3_MEMIF1}= 02:f1:be:90:00:03 ${PREFIX}= 64 -${SYNC_WAIT}= 6s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** # Default VRF table ... Start Three Agents @@ -42,79 +43,72 @@ Start Three Agents Add Agent VPP Node agent_vpp_1 Add Agent VPP Node agent_vpp_2 Add Agent VPP Node agent_vpp_3 - Sleep ${SYNC_WAIT} Setup Agent1 for agent2 Create loopback interface bvi_loop0 on agent_vpp_1 with ip ${IP_1}/${PREFIX} and mac ${MAC_LOOP1} Create Master memif0 on agent_vpp_1 with MAC ${MAC_MEMIF1}, key 1 and m0.sock socket Create bridge domain bd1 With Autolearn on agent_vpp_1 with interfaces bvi_loop0, memif0 - Sleep ${SYNC_WAIT} + Check Interfaces on Agent1 for Agent2 - vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop0 enabled=1 mac=${MAC_LOOP1} ipv6=${IP_1}/${PREFIX} - vat_term: Check Memif Interface State agent_vpp_1 memif0 mac=${MAC_MEMIF1} role=master id=1 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m0.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop0 enabled=1 mac=${MAC_LOOP1} ipv6=${IP_1}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 memif0 mac=${MAC_MEMIF1} role=master id=1 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m0.sock Create BD on Agent1 Create bridge domain bd1 With Autolearn on agent_vpp_1 with interfaces bvi_loop0, memif0 - Sleep ${SYNC_WAIT} Check1 bd1 on Agent1 Is Created - vat_term: BD Is Created agent_vpp_1 bvi_loop0 memif0 - vat_term: Check Bridge Domain State agent_vpp_1 bd1 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=memif0 interface=bvi_loop0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: BD Is Created agent_vpp_1 bvi_loop0 memif0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_1 bd1 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=memif0 interface=bvi_loop0 Check2 Interfaces on Agent1 for Agent2 - vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop0 enabled=1 mac=${MAC_LOOP1} ipv6=${IP_1}/${PREFIX} - vat_term: Check Memif Interface State agent_vpp_1 memif0 mac=${MAC_MEMIF1} role=master id=1 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m0.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop0 enabled=1 mac=${MAC_LOOP1} ipv6=${IP_1}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 memif0 mac=${MAC_MEMIF1} role=master id=1 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m0.sock Setup Agent1 for Agent3 Create loopback interface bvi_loop1 on agent_vpp_1 with ip ${IP_3}/${PREFIX} and mac ${MAC_LOOP2} Create Master memif1 on agent_vpp_1 with MAC ${MAC_MEMIF2}, key 2 and m1.sock socket Create bridge domain bd2 With Autolearn on agent_vpp_1 with interfaces bvi_loop1, memif1 - Sleep ${SYNC_WAIT} Check Interfaces on Agent1 for Agent3 - vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop1 enabled=1 mac=${MAC_LOOP2} ipv6=${IP_3}/${PREFIX} - vat_term: Check Memif Interface State agent_vpp_1 memif1 mac=${MAC_MEMIF2} role=master id=2 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop1 enabled=1 mac=${MAC_LOOP2} ipv6=${IP_3}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 memif1 mac=${MAC_MEMIF2} role=master id=2 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock Check bd2 on Agent1 Is Created - vat_term: BD Is Created agent_vpp_1 bvi_loop1 memif1 - vat_term: Check Bridge Domain State agent_vpp_1 bd2 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=memif1 interface=bvi_loop1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: BD Is Created agent_vpp_1 bvi_loop1 memif1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_1 bd2 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=memif1 interface=bvi_loop1 Setup Agent2 Create loopback interface bvi_loop0 on agent_vpp_2 with ip ${IP_2}/${PREFIX} and mac ${MAC2_LOOP1} Create Slave memif0 on agent_vpp_2 with MAC ${MAC2_MEMIF1}, key 1 and m0.sock socket Create bridge domain bd1 With Autolearn on agent_vpp_2 with interfaces bvi_loop0, memif0 - Sleep ${SYNC_WAIT} Check Interfaces on Agent2 - vat_term: Check Loopback Interface State agent_vpp_2 bvi_loop0 enabled=1 mac=${MAC2_LOOP1} ipv6=${IP_2}/${PREFIX} - vat_term: Check Memif Interface State agent_vpp_2 memif0 mac=${MAC2_MEMIF1} role=slave id=1 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/m0.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_2 bvi_loop0 enabled=1 mac=${MAC2_LOOP1} ipv6=${IP_2}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 memif0 mac=${MAC2_MEMIF1} role=slave id=1 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/m0.sock Check bd1 on Agent2 Is Created - vat_term: BD Is Created agent_vpp_2 bvi_loop0 memif0 - vat_term: Check Bridge Domain State agent_vpp_2 bd1 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=memif0 interface=bvi_loop0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: BD Is Created agent_vpp_2 bvi_loop0 memif0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_2 bd1 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=memif0 interface=bvi_loop0 Setup Agent3 Create loopback interface bvi_loop0 on agent_vpp_3 with ip ${IP_4}/${PREFIX} and mac ${MAC3_LOOP1} Create Slave memif0 on agent_vpp_3 with MAC ${MAC3_MEMIF1}, key 2 and m1.sock socket Create bridge domain bd1 With Autolearn on agent_vpp_3 with interfaces bvi_loop0, memif0 - Sleep ${SYNC_WAIT} Check Interfaces on Agent3 - vat_term: Check Loopback Interface State agent_vpp_3 bvi_loop0 enabled=1 mac=${MAC3_LOOP1} ipv6=${IP_4}/${PREFIX} - vat_term: Check Memif Interface State agent_vpp_3 memif0 mac=${MAC3_MEMIF1} role=slave id=2 connected=1 enabled=1 socket=${AGENT_VPP_3_MEMIF_SOCKET_FOLDER}/m1.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_3 bvi_loop0 enabled=1 mac=${MAC3_LOOP1} ipv6=${IP_4}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_3 memif0 mac=${MAC3_MEMIF1} role=slave id=2 connected=1 enabled=1 socket=${AGENT_VPP_3_MEMIF_SOCKET_FOLDER}/m1.sock Check bd1 on Agent3 Is Created - vat_term: BD Is Created agent_vpp_3 bvi_loop0 memif0 - vat_term: Check Bridge Domain State agent_vpp_3 bd1 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=memif0 interface=bvi_loop0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: BD Is Created agent_vpp_3 bvi_loop0 memif0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_3 bd1 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=memif0 interface=bvi_loop0 Setup route on Agent2 Create Route On agent_vpp_2 With IP ${NET2}/${PREFIX} With Next Hop ${IP_1} And Vrf Id 0 - Sleep ${SYNC_WAIT} Setup route on Agent3 Create Route On agent_vpp_3 With IP ${NET1}/${PREFIX} With Next Hop ${IP_3} And Vrf Id 0 - Sleep ${SYNC_WAIT} Pinging diff --git a/tests/robot/suites/trafficIPv6/ip_route/test3_ip_routeIPv6.robot b/tests/robot/suites/trafficIPv6/ip_route/test3_ip_routeIPv6.robot index 9ab1014228..2060158f83 100644 --- a/tests/robot/suites/trafficIPv6/ip_route/test3_ip_routeIPv6.robot +++ b/tests/robot/suites/trafficIPv6/ip_route/test3_ip_routeIPv6.robot @@ -34,7 +34,8 @@ ${MAC2_MEMIF1}= 02:f1:be:90:00:02 ${MAC3_MEMIF1}= 02:f1:be:90:00:03 ${PREFIX}= 64 -${SYNC_WAIT}= 6s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s *** Test Cases *** # Default VRF table ... Start Three Agents @@ -48,65 +49,64 @@ Setup Agent1 for agent2 Create loopback interface bvi_loop0 on agent_vpp_1 with ip ${IP_1}/${PREFIX} and mac ${MAC_LOOP1} Create Master memif0 on agent_vpp_1 with MAC ${MAC_MEMIF1}, key 1 and m0.sock socket Create bridge domain bd1 With Autolearn on agent_vpp_1 with interfaces bvi_loop0, memif0 - Sleep ${SYNC_WAIT} + Check Interfaces on Agent1 for Agent2 - vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop0 enabled=1 mac=${MAC_LOOP1} ipv6=${IP_1}/${PREFIX} - vat_term: Check Memif Interface State agent_vpp_1 memif0 mac=${MAC_MEMIF1} role=master id=1 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m0.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop0 enabled=1 mac=${MAC_LOOP1} ipv6=${IP_1}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 memif0 mac=${MAC_MEMIF1} role=master id=1 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m0.sock Create BD on Agent1 Create bridge domain bd1 With Autolearn on agent_vpp_1 with interfaces bvi_loop0, memif0 - Sleep ${SYNC_WAIT} + Check1 bd1 on Agent1 Is Created - vat_term: BD Is Created agent_vpp_1 bvi_loop0 memif0 - vat_term: Check Bridge Domain State agent_vpp_1 bd1 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=memif0 interface=bvi_loop0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: BD Is Created agent_vpp_1 bvi_loop0 memif0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_1 bd1 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=memif0 interface=bvi_loop0 Check2 Interfaces on Agent1 for Agent2 - vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop0 enabled=1 mac=${MAC_LOOP1} ipv6=${IP_1}/${PREFIX} - vat_term: Check Memif Interface State agent_vpp_1 memif0 mac=${MAC_MEMIF1} role=master id=1 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m0.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop0 enabled=1 mac=${MAC_LOOP1} ipv6=${IP_1}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 memif0 mac=${MAC_MEMIF1} role=master id=1 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m0.sock Setup Agent1 for Agent3 Create loopback interface bvi_loop1 on agent_vpp_1 with ip ${IP_3}/${PREFIX} and mac ${MAC_LOOP2} Create Master memif1 on agent_vpp_1 with MAC ${MAC_MEMIF2}, key 2 and m1.sock socket Create bridge domain bd2 With Autolearn on agent_vpp_1 with interfaces bvi_loop1, memif1 - Sleep ${SYNC_WAIT} Check Interfaces on Agent1 for Agent3 - vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop1 enabled=1 mac=${MAC_LOOP2} ipv6=${IP_3}/${PREFIX} - vat_term: Check Memif Interface State agent_vpp_1 memif1 mac=${MAC_MEMIF2} role=master id=2 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_1 bvi_loop1 enabled=1 mac=${MAC_LOOP2} ipv6=${IP_3}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 memif1 mac=${MAC_MEMIF2} role=master id=2 connected=0 enabled=1 socket=${AGENT_VPP_1_MEMIF_SOCKET_FOLDER}/m1.sock Check bd2 on Agent1 Is Created - vat_term: BD Is Created agent_vpp_1 bvi_loop1 memif1 - vat_term: Check Bridge Domain State agent_vpp_1 bd2 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=memif1 interface=bvi_loop1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: BD Is Created agent_vpp_1 bvi_loop1 memif1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_1 bd2 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=memif1 interface=bvi_loop1 Setup Agent2 Create loopback interface bvi_loop0 on agent_vpp_2 with ip ${IP_2}/${PREFIX} and mac ${MAC2_LOOP1} Create Slave memif0 on agent_vpp_2 with MAC ${MAC2_MEMIF1}, key 1 and m0.sock socket Create bridge domain bd1 With Autolearn on agent_vpp_2 with interfaces bvi_loop0, memif0 - Sleep ${SYNC_WAIT} + Check Interfaces on Agent2 - vat_term: Check Loopback Interface State agent_vpp_2 bvi_loop0 enabled=1 mac=${MAC2_LOOP1} ipv6=${IP_2}/${PREFIX} - vat_term: Check Memif Interface State agent_vpp_2 memif0 mac=${MAC2_MEMIF1} role=slave id=1 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/m0.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_2 bvi_loop0 enabled=1 mac=${MAC2_LOOP1} ipv6=${IP_2}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 memif0 mac=${MAC2_MEMIF1} role=slave id=1 connected=1 enabled=1 socket=${AGENT_VPP_2_MEMIF_SOCKET_FOLDER}/m0.sock Check bd1 on Agent2 Is Created - vat_term: BD Is Created agent_vpp_2 bvi_loop0 memif0 - vat_term: Check Bridge Domain State agent_vpp_2 bd1 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=memif0 interface=bvi_loop0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: BD Is Created agent_vpp_2 bvi_loop0 memif0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_2 bd1 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=memif0 interface=bvi_loop0 Setup Agent3 Create loopback interface bvi_loop0 on agent_vpp_3 with ip ${IP_4}/${PREFIX} and mac ${MAC3_LOOP1} Create Slave memif0 on agent_vpp_3 with MAC ${MAC3_MEMIF1}, key 2 and m1.sock socket Create bridge domain bd1 With Autolearn on agent_vpp_3 with interfaces bvi_loop0, memif0 - Sleep ${SYNC_WAIT} + Check Interfaces on Agent3 - vat_term: Check Loopback Interface State agent_vpp_3 bvi_loop0 enabled=1 mac=${MAC3_LOOP1} ipv6=${IP_4}/${PREFIX} - vat_term: Check Memif Interface State agent_vpp_3 memif0 mac=${MAC3_MEMIF1} role=slave id=2 connected=1 enabled=1 socket=${AGENT_VPP_3_MEMIF_SOCKET_FOLDER}/m1.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Loopback Interface State agent_vpp_3 bvi_loop0 enabled=1 mac=${MAC3_LOOP1} ipv6=${IP_4}/${PREFIX} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_3 memif0 mac=${MAC3_MEMIF1} role=slave id=2 connected=1 enabled=1 socket=${AGENT_VPP_3_MEMIF_SOCKET_FOLDER}/m1.sock Check bd1 on Agent3 Is Created - vat_term: BD Is Created agent_vpp_3 bvi_loop0 memif0 - vat_term: Check Bridge Domain State agent_vpp_3 bd1 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=memif0 interface=bvi_loop0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: BD Is Created agent_vpp_3 bvi_loop0 memif0 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Bridge Domain State agent_vpp_3 bd1 flood=1 unicast=1 forward=1 learn=1 arp_term=1 interface=memif0 interface=bvi_loop0 # setup routes diff --git a/tests/robot/suites/trafficIPv6/ip_route/test_inter_vrf_routes_ipv6.robot b/tests/robot/suites/trafficIPv6/ip_route/test_inter_vrf_routes_ipv6.robot new file mode 100644 index 0000000000..ff8766572d --- /dev/null +++ b/tests/robot/suites/trafficIPv6/ip_route/test_inter_vrf_routes_ipv6.robot @@ -0,0 +1,111 @@ +*** Settings *** + +Library OperatingSystem +Library String +#Library RequestsLibrary + +Resource ../../../variables/${VARIABLES}_variables.robot +Resource ../../../libraries/all_libs.robot +Resource ../../../libraries/pretty_keywords.robot + +Force Tags trafficIPv4 +Suite Setup Run Keywords Discard old results Test Setup +Suite Teardown Test Teardown + +*** Variables *** +${VARIABLES}= common +${ENV}= common +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s +${FINAL_SLEEP}= 1s +${IP_1}= fd30::1:b:0:0:1 +${IP_2}= fd30::1:b:0:0:2 +${IP_3}= fd31::1:b:0:0:1 +${IP_4}= fd31::1:b:0:0:2 +#${NET1}= fd30::1:0:0:0:0 +#${NET2}= fd31::1:0:0:0:0 +${NET1}= fd30:0:0:1:: +${NET2}= fd31:0:0:1:: + +*** Test Cases *** +# Non default VRF table 2 used in Agent VPP Node agent_vpp_2 +Start Two Agents And Then Configure With Default And Non Default VRF + Add Agent VPP Node agent_vpp_1 + Add Agent VPP Node agent_vpp_2 + Create Master memif0 on agent_vpp_1 with IP ${IP_1}, MAC 02:f1:be:90:00:00, key 1 and m0.sock socket + Create Slave memif0 on agent_vpp_2 with IP ${IP_2}, MAC 02:f1:be:90:00:02, key 1 and m0.sock socket + + Create Master memif1 on agent_vpp_1 with VRF 2, IP ${IP_3}, MAC 02:f1:be:90:02:00, key 1 and m1.sock socket + Create Slave memif1 on agent_vpp_2 with VRF 2, IP ${IP_4}, MAC 02:f1:be:90:02:02, key 1 and m1.sock socket + + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} List of interfaces On agent_vpp_1 Should Contain Interface memif1/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} List of interfaces On agent_vpp_2 Should Contain Interface memif1/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} List of interfaces On agent_vpp_1 Should Contain Interface memif2/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} List of interfaces On agent_vpp_2 Should Contain Interface memif2/1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} IP6 Fib Table 0 On agent_vpp_1 Should Contain Route With IP ${IP_1}/128 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} IP6 Fib Table 2 On agent_vpp_1 Should Contain Route With IP ${IP_3}/128 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} IP6 Fib Table 0 On agent_vpp_2 Should Contain Route With IP ${IP_2}/128 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} IP6 Fib Table 2 On agent_vpp_2 Should Contain Route With IP ${IP_4}/128 + +Check Normal Ping Inside VRF + # try ping + Ping From agent_vpp_1 To ${IP_2} + Ping From agent_vpp_2 To ${IP_1} + +Ping From Source Agent 1 + Ping On agent_vpp_1 With IP ${IP_2}, Source memif1/1 + Ping On agent_vpp_1 With IP ${IP_4}, Source memif2/1 + +Ping From Source Agent 2 +# ${int}= vpp_ctl: Get Interface Internal Name agent_vpp_2 memif0 +# Ping On agent_vpp_2 With IP 10.1.1.1, Source ${int} + Ping On agent_vpp_2 With IP ${IP_1}, Source memif1/1 + Ping On agent_vpp_2 With IP ${IP_3}, Source memif2/1 + +Ping Should Fail + #no route from vrf 0 to vrf 2, then shoul fail + Command: Ping On agent_vpp_1 With IP ${IP_4}, Source memif1/1 should fail + Command: Ping On agent_vpp_1 With IP ${IP_3}, Source memif1/1 should fail + Command: Ping On agent_vpp_2 With IP ${IP_4}, Source memif1/1 should fail + Command: Ping On agent_vpp_2 With IP ${IP_3}, Source memif1/1 should fail + +Create Route For Inter Vrf Routing + Create Route On agent_vpp_1 With IP ${NET2}/64 With Next Hop ${IP_2} And Vrf Id 0 + Create Route On agent_vpp_1 With IP ${NET1}/64 With Next Hop ${IP_4} And Vrf Id 2 + Create Route On agent_vpp_2 With IP ${NET2}/64 With Next Hop VRF 2 From Vrf Id 0 And Type 1 + Create Route On agent_vpp_2 With IP ${NET1}/64 With Next Hop VRF 0 From Vrf Id 2 And Type 1 + +Config Done + No Operation + +Check Inter VRF Routing + Show IP Fib On agent_vpp_1 + IP6 Fib Table 0 On agent_vpp_1 Should Contain Route With IP ${NET2}/64 + IP6 Fib Table 0 On agent_vpp_1 Should Contain Vrf ipv6 via ${IP_2} memif1/1 + Show IP Fib On agent_vpp_2 + IP6 Fib Table 2 On agent_vpp_2 Should Contain Route With IP ${NET1}/64 + IP6 Fib Table 2 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv6-VRF: + IP6 Fib Table 0 On agent_vpp_2 Should Contain Route With IP ${NET2}/64 + IP6 Fib Table 0 On agent_vpp_2 Should Contain Vrf unicast lookup in ipv6-VRF: + +Check Route With Ping + Ping On agent_vpp_1 With IP ${IP_4}, Source memif1/1 + Ping On agent_vpp_1 With IP ${IP_4}, Source memif2/1 + Ping On agent_vpp_1 With IP ${IP_3}, Source memif1/1 + +Final Sleep For Manual Checking + Sleep ${FINAL_SLEEP} + + +*** Keywords *** +List of interfaces On ${node} Should Contain Interface ${int} + Log many ${node} ${int} + ${out}= vpp_term: Show Interfaces ${node} + log many ${out} + Should Match Regexp ${out} ${int} + +IP6 Fib Table ${table_id} On ${node} Should Contain Vrf ${inter_vrf_string} + Log many ${table_id} ${node} ${inter_vrf_string} + ${out}= vpp_term: Show IP6 Fib Table ${node} ${table_id} + log many ${out} + Should Contain ${out} ${inter_vrf_string} diff --git a/tests/robot/suites/trafficIPv6/libmemif/libmemif_master_trafic1IPv6.robot b/tests/robot/suites/trafficIPv6/libmemif/libmemif_master_trafic1IPv6.robot index 10085d94e2..13c9f4e9f2 100644 --- a/tests/robot/suites/trafficIPv6/libmemif/libmemif_master_trafic1IPv6.robot +++ b/tests/robot/suites/trafficIPv6/libmemif/libmemif_master_trafic1IPv6.robot @@ -17,7 +17,8 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${SYNC_SLEEP}= 10s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s ${RESYNC_SLEEP}= 1s ${LIBMEMIF_IP1}= 192.168.1.2 ${VPP2MEMIF_IP1}= 192.168.1.2 @@ -38,19 +39,18 @@ Show Interfaces Before Setup Add Memif1 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=false id=0 ip=${VPP1MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} + Check Memif1 Interface Created On VPP1 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:62 master=false id=0 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 is Modified - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=slave id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=slave id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Create And Chek Memif1 On Agent Libmemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 conn 0 1 @@ -59,16 +59,15 @@ Create And Chek Memif1 On Agent Libmemif 1 Should Contain ${out} link: up Check Memif1 Interface On VPP1 Connected To LibMemif - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=slave id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=slave id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 On VPP1 back vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=false id=0 ip=${VPP1MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} + Check Memif1 on Vpp1 is connected - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock - Sleep ${SYNC_SLEEP} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Ping VPP1 -> Agent Libmemif 1 vpp_term: Check Ping agent_vpp_1 ${LIBMEMIF_IP1} @@ -93,19 +92,17 @@ Check Ping VPP1 -> Agent Libmemif 1 After Resync Delete Memif On Agent Libmemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 del 0 - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 Disconnected After Master Deleted - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Create Memif1 On Agent Libmemif 1 Again ${out}= lmterm: Issue Command agent_libmemif_1 conn 0 1 - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 Connected After Master Deleted and Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Ping VPP1 -> Agent Libmemif 1 After Delete and Create vpp_term: Check Ping agent_vpp_1 ${LIBMEMIF_IP1} diff --git a/tests/robot/suites/trafficIPv6/libmemif/libmemif_master_trafic2IPv6.robot b/tests/robot/suites/trafficIPv6/libmemif/libmemif_master_trafic2IPv6.robot index e88486acdf..2fb01aab40 100644 --- a/tests/robot/suites/trafficIPv6/libmemif/libmemif_master_trafic2IPv6.robot +++ b/tests/robot/suites/trafficIPv6/libmemif/libmemif_master_trafic2IPv6.robot @@ -17,7 +17,8 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${SYNC_SLEEP}= 10s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s ${RESYNC_SLEEP}= 1s ${LIBMEMIF_IP1}= 192.168.1.2 ${VPP2MEMIF_IP1}= 192.168.1.2 @@ -38,37 +39,35 @@ Show Interfaces Before Setup Add Memif1 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=false id=0 ip=${VPP1MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface Created On VPP1 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:62 master=false id=0 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} + Check Memif1 Interface On VPP1 is Modified - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=slave id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=slave id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Create And Chek Memif1 On Agent Libmemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 conn 0 1 + Sleep ${SYNC_SLEEP} ${out}= lmterm: Issue Command agent_libmemif_1 show Should Contain ${out} interface ip: ${LIBMEMIF_IP1} Should Contain ${out} link: up Check Memif1 Interface On VPP1 Connected To LibMemif - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=slave id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=slave id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 On VPP1 back vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=false id=0 ip=${VPP1MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 on Vpp1 is connected - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock - Sleep ${SYNC_SLEEP} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Ping VPP1 -> Agent Libmemif 1 vpp_term: Check Ping agent_vpp_1 ${LIBMEMIF_IP1} @@ -93,19 +92,17 @@ Check Ping VPP1 -> Agent Libmemif 1 After Resync Delete Memif On Agent Libmemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 del 0 - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 Disconnected After Master Deleted - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Create Memif1 On Agent Libmemif 1 Again ${out}= lmterm: Issue Command agent_libmemif_1 conn 0 1 - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 Connected After Master Deleted and Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Ping VPP1 -> Agent Libmemif 1 After Delete and Create vpp_term: Check Ping agent_vpp_1 ${LIBMEMIF_IP1} @@ -145,19 +142,21 @@ Add Libmemif Node Again Create And Check Memif1 On Agent Libmemif 1 After node restart2 ${out_c}= lmterm: Issue Command agent_libmemif_1 conn 0 1 + Sleep ${SYNC_SLEEP} ${out}= lmterm: Issue Command agent_libmemif_1 show Log Many ${out_c} ${out} Should Contain ${out} interface ip: ${LIBMEMIF_IP1} Should Contain ${out} link: up Check Memif1 Interface On VPP1 Connected After Node Restart2 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} : Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock ${out}= lmterm: Issue Command agent_libmemif_1 show Create Memif2 On Agent Libmemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 conn 1 1 #Should Contain ${out} INFO: memif connected! + Sleep ${SYNC_SLEEP} Check Memif 1 and Memif2 On Agent LibMemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 show @@ -167,8 +166,8 @@ Check Memif 1 and Memif2 On Agent LibMemif 1 Should Contain ${out} link: down Check Memif1 Interface On VPP1 Connected After Second Libmemif Added - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=slave id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock ${out}= lmterm: Issue Command agent_libmemif_1 show ############################################################################ @@ -195,7 +194,7 @@ Check Memif1 Interface On VPP1 Connected After Second Libmemif Added Delete Memif1 Interface On VPP1 vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=vpp1_memif1 vpp_term: Show Interfaces agent_vpp_1 - vpp_term: Interface Is Deleted node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_1 mac=62:61:61:61:61:61 Check LibMemif1 down and LibMemif2 down ${out}= lmterm: Issue Command agent_libmemif_1 show @@ -205,13 +204,10 @@ Check LibMemif1 down and LibMemif2 down Add Memif2 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif2 mac=62:61:61:61:51:51 master=slave id=1 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} - Sleep ${SYNC_SLEEP} - Sleep ${SYNC_SLEEP} Check Memif2 Interface Created On VPP1 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:51:51 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=62:61:61:61:51:51 role=slave id=1 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=62:61:61:61:51:51 role=slave id=1 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check LibMemif1 down and LibMemif2 up ${out}= lmterm: Issue Command agent_libmemif_1 show diff --git a/tests/robot/suites/trafficIPv6/libmemif/libmemif_slave_trafic1IPv6.robot b/tests/robot/suites/trafficIPv6/libmemif/libmemif_slave_trafic1IPv6.robot index 60529ae77b..b32e12ddca 100644 --- a/tests/robot/suites/trafficIPv6/libmemif/libmemif_slave_trafic1IPv6.robot +++ b/tests/robot/suites/trafficIPv6/libmemif/libmemif_slave_trafic1IPv6.robot @@ -17,7 +17,8 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${SYNC_SLEEP}= 10s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s ${RESYNC_SLEEP}= 1s ${LIBMEMIF_IP1}= 192.168.1.2 ${VPP2MEMIF_IP1}= 192.168.1.2 @@ -38,75 +39,71 @@ Show Interfaces Before Setup Add Memif1 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=true id=0 ip=${VPP1MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface Created On VPP1 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:62 master=true id=0 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 is Modified - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 Interface On VPP1 To Previous Values vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=true id=0 ip=${VPP1MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 Modified Back - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock ############################################################################## Add Memif1 Interface On VPP2 vpp_ctl: Put Memif Interface With IP node=agent_vpp_2 name=vpp2_memif1 mac=62:61:61:61:51:51 master=false id=0 ip=${VPP2MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface Created And Connected On VPP2 - vpp_term: Interface Is Created node=agent_vpp_2 mac=62:61:61:61:51:51 - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=62:61:61:61:51:51 role=slave id=0 ipv4=${VPP2MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_2 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=62:61:61:61:51:51 role=slave id=0 ipv4=${VPP2MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Memif1 Interface On VPP1 Connected To VPP2 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 Interface On VPP1 While Connected To VPP2 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:62 master=true id=0 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} + Check Memif1 Interface On VPP1 Modified While Connected - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Delete Memif1 Interface On VPP2 vpp_ctl: Delete VPP Interface node=agent_vpp_2 name=vpp2_memif1 - vpp_term: Interface Is Deleted node=agent_vpp_2 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_2 mac=62:61:61:61:51:51 Check VPP1_memif1 Interface Is Disconnected - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 Interface On VPP1 To Previous Values After Slave Delete vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=true id=0 ip=${VPP1MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 Modified Back After Slave Delete - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock ############################################################################# Create And Chek Memif1 On Agent Libmemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 conn 0 0 + Sleep ${SYNC_SLEEP} ${out}= lmterm: Issue Command agent_libmemif_1 show Should Contain ${out} interface ip: ${LIBMEMIF_IP1} Should Contain ${out} link: up Check Memif1 Interface On VPP1 Connected To LibMemif - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Ping VPP1 -> Agent Libmemif 1 vpp_term: Check Ping agent_vpp_1 ${LIBMEMIF_IP1} @@ -120,7 +117,7 @@ Remove VPP Nodes Sleep ${RESYNC_WAIT} Check Memif1 Interface On VPP1 Connected To LibMemif After Resync - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Ping VPP1 -> Agent Libmemif 1 After Resync @@ -133,21 +130,19 @@ Delete Memif On Agent Libmemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 del 0 Check Memif1 Interface On VPP1 Disconnected After Slave Deleted - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock - Sleep ${SYNC_SLEEP} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Memif1 Interface On VPP1 Disconnected After Slave Deleted Again - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Create Memif1 On Agent Libmemif 1 Again ${out}= lmterm: Issue Command agent_libmemif_1 conn 0 0 - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 Connected After Slave Deleted and Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Ping VPP1 -> Agent Libmemif 1 After Delete and Create vpp_term: Check Ping agent_vpp_1 ${LIBMEMIF_IP1} @@ -187,18 +182,20 @@ Add Libmemif Node Again Create And Check Memif1 On Agent Libmemif 1 After node restart ${out_c}= lmterm: Issue Command agent_libmemif_1 conn 0 0 + Sleep ${SYNC_SLEEP} ${out}= lmterm: Issue Command agent_libmemif_1 show Log Many ${out_c} ${out} Should Contain ${out} interface ip: ${LIBMEMIF_IP1} Should Contain ${out} link: up Check Memif1 Interface On VPP1 Connected After Node Restart - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock ${out}= lmterm: Issue Command agent_libmemif_1 show Create Memif2 On Agent Libmemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 conn 1 0 + Sleep ${SYNC_SLEEP} #Should Contain ${out} INFO: memif connected! Check Memif 1 and Memif2 On Agent LibMemif 1 @@ -209,19 +206,18 @@ Check Memif 1 and Memif2 On Agent LibMemif 1 Should Contain ${out} link: down Check Memif1 Interface On VPP1 Connected After Second Libmemif Added - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Sleep ${SYNC_SLEEP}vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Sleep ${SYNC_SLEEP}vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock ${out}= lmterm: Issue Command agent_libmemif_1 show ############################################################################ ##### Here VPP crashes Add Memif2 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif2 mac=62:61:61:61:51:51 master=true id=1 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif2 Interface Created On VPP1 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:51:51 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=62:61:61:61:51:51 role=master id=1 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=62:61:61:61:51:51 role=master id=1 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Memif 1 and Memif2 On Agent LibMemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 show @@ -232,11 +228,11 @@ Check Memif 1 and Memif2 On Agent LibMemif 1 Delete Memif2 Interface On VPP1 After Resync vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=vpp1_memif2 - vpp_term: Interface Is Deleted node=agent_vpp_1 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_1 mac=62:61:61:61:51:51 Delete Memif1 Interface On VPP1 vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=vpp1_memif1 - vpp_term: Interface Is Deleted node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_1 mac=62:61:61:61:61:61 Check Memif 1 and Memif2 On Agent LibMemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 show @@ -246,11 +242,10 @@ Check Memif 1 and Memif2 On Agent LibMemif 1 Add Memif2 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif2 mac=62:61:61:61:51:51 master=true id=1 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif2 Interface Created On VPP1 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:51:51 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=62:61:61:61:51:51 role=master id=1 ipv4=${VPP1MEMIF_IP2}/24 connecte + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=62:61:61:61:51:51 role=master id=1 ipv4=${VPP1MEMIF_IP2}/24 connecte Check Memif 1 and Memif2 On Agent LibMemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 show diff --git a/tests/robot/suites/trafficIPv6/libmemif/libmemif_slave_trafic2IPv6.robot b/tests/robot/suites/trafficIPv6/libmemif/libmemif_slave_trafic2IPv6.robot index 60529ae77b..c5af860ad1 100644 --- a/tests/robot/suites/trafficIPv6/libmemif/libmemif_slave_trafic2IPv6.robot +++ b/tests/robot/suites/trafficIPv6/libmemif/libmemif_slave_trafic2IPv6.robot @@ -17,7 +17,8 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${SYNC_SLEEP}= 10s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s ${RESYNC_SLEEP}= 1s ${LIBMEMIF_IP1}= 192.168.1.2 ${VPP2MEMIF_IP1}= 192.168.1.2 @@ -38,75 +39,70 @@ Show Interfaces Before Setup Add Memif1 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=true id=0 ip=${VPP1MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface Created On VPP1 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:62 master=true id=0 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 is Modified - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 Interface On VPP1 To Previous Values vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=true id=0 ip=${VPP1MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 Modified Back - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock ############################################################################## Add Memif1 Interface On VPP2 vpp_ctl: Put Memif Interface With IP node=agent_vpp_2 name=vpp2_memif1 mac=62:61:61:61:51:51 master=false id=0 ip=${VPP2MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface Created And Connected On VPP2 - vpp_term: Interface Is Created node=agent_vpp_2 mac=62:61:61:61:51:51 - vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=62:61:61:61:51:51 role=slave id=0 ipv4=${VPP2MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_2 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_2 vpp2_memif1 mac=62:61:61:61:51:51 role=slave id=0 ipv4=${VPP2MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Memif1 Interface On VPP1 Connected To VPP2 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 Interface On VPP1 While Connected To VPP2 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:62 master=true id=0 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 Modified While Connected - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:62 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Delete Memif1 Interface On VPP2 vpp_ctl: Delete VPP Interface node=agent_vpp_2 name=vpp2_memif1 - vpp_term: Interface Is Deleted node=agent_vpp_2 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_2 mac=62:61:61:61:51:51 Check VPP1_memif1 Interface Is Disconnected - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:62 role=master id=0 ipv4=${VPP1MEMIF_IP2}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Modify Memif1 Interface On VPP1 To Previous Values After Slave Delete vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif1 mac=62:61:61:61:61:61 master=true id=0 ip=${VPP1MEMIF_IP1} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 Modified Back After Slave Delete - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock ############################################################################# Create And Chek Memif1 On Agent Libmemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 conn 0 0 + Sleep ${SYNC_SLEEP} ${out}= lmterm: Issue Command agent_libmemif_1 show Should Contain ${out} interface ip: ${LIBMEMIF_IP1} Should Contain ${out} link: up Check Memif1 Interface On VPP1 Connected To LibMemif - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Ping VPP1 -> Agent Libmemif 1 vpp_term: Check Ping agent_vpp_1 ${LIBMEMIF_IP1} @@ -133,21 +129,20 @@ Delete Memif On Agent Libmemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 del 0 Check Memif1 Interface On VPP1 Disconnected After Slave Deleted - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock - Sleep ${SYNC_SLEEP} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Check Memif1 Interface On VPP1 Disconnected After Slave Deleted Again - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=0 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Create Memif1 On Agent Libmemif 1 Again ${out}= lmterm: Issue Command agent_libmemif_1 conn 0 0 - Sleep ${SYNC_SLEEP} Check Memif1 Interface On VPP1 Connected After Slave Deleted and Created - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Ping VPP1 -> Agent Libmemif 1 After Delete and Create vpp_term: Check Ping agent_vpp_1 ${LIBMEMIF_IP1} @@ -187,18 +182,20 @@ Add Libmemif Node Again Create And Check Memif1 On Agent Libmemif 1 After node restart ${out_c}= lmterm: Issue Command agent_libmemif_1 conn 0 0 + Sleep ${SYNC_SLEEP} ${out}= lmterm: Issue Command agent_libmemif_1 show Log Many ${out_c} ${out} Should Contain ${out} interface ip: ${LIBMEMIF_IP1} Should Contain ${out} link: up Check Memif1 Interface On VPP1 Connected After Node Restart - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock ${out}= lmterm: Issue Command agent_libmemif_1 show Create Memif2 On Agent Libmemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 conn 1 0 + Sleep ${SYNC_SLEEP} #Should Contain ${out} INFO: memif connected! Check Memif 1 and Memif2 On Agent LibMemif 1 @@ -209,19 +206,19 @@ Check Memif 1 and Memif2 On Agent LibMemif 1 Should Contain ${out} link: down Check Memif1 Interface On VPP1 Connected After Second Libmemif Added - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif1 mac=62:61:61:61:61:61 role=master id=0 ipv4=${VPP1MEMIF_IP1}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock ${out}= lmterm: Issue Command agent_libmemif_1 show ############################################################################ ##### Here VPP crashes Add Memif2 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif2 mac=62:61:61:61:51:51 master=true id=1 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} + Check Memif2 Interface Created On VPP1 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:51:51 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=62:61:61:61:51:51 role=master id=1 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=62:61:61:61:51:51 role=master id=1 ipv4=${VPP1MEMIF_IP2}/24 connected=1 enabled=1 socket=${AGENT_LIBMEMIF_1_MEMIF_SOCKET_FOLDER}/memif.sock Check Memif 1 and Memif2 On Agent LibMemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 show @@ -232,11 +229,11 @@ Check Memif 1 and Memif2 On Agent LibMemif 1 Delete Memif2 Interface On VPP1 After Resync vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=vpp1_memif2 - vpp_term: Interface Is Deleted node=agent_vpp_1 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_1 mac=62:61:61:61:51:51 Delete Memif1 Interface On VPP1 vpp_ctl: Delete VPP Interface node=agent_vpp_1 name=vpp1_memif1 - vpp_term: Interface Is Deleted node=agent_vpp_1 mac=62:61:61:61:61:61 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Deleted node=agent_vpp_1 mac=62:61:61:61:61:61 Check Memif 1 and Memif2 On Agent LibMemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 show @@ -246,11 +243,10 @@ Check Memif 1 and Memif2 On Agent LibMemif 1 Add Memif2 Interface On VPP1 vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=vpp1_memif2 mac=62:61:61:61:51:51 master=true id=1 ip=${VPP1MEMIF_IP2} prefix=24 socket=memif.sock - Sleep ${SYNC_SLEEP} Check Memif2 Interface Created On VPP1 - vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:51:51 - vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=62:61:61:61:51:51 role=master id=1 ipv4=${VPP1MEMIF_IP2}/24 connecte + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=62:61:61:61:51:51 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vat_term: Check Memif Interface State agent_vpp_1 vpp1_memif2 mac=62:61:61:61:51:51 role=master id=1 ipv4=${VPP1MEMIF_IP2}/24 connecte Check Memif 1 and Memif2 On Agent LibMemif 1 ${out}= lmterm: Issue Command agent_libmemif_1 show diff --git a/tests/robot/suites/trafficIPv6/linux_traffic/1x_vpp_3x_namespaces_trafficIPv6.robot b/tests/robot/suites/trafficIPv6/linux_traffic/1x_vpp_3x_namespaces_trafficIPv6.robot index ebfaf3da47..ad11fa3c67 100644 --- a/tests/robot/suites/trafficIPv6/linux_traffic/1x_vpp_3x_namespaces_trafficIPv6.robot +++ b/tests/robot/suites/trafficIPv6/linux_traffic/1x_vpp_3x_namespaces_trafficIPv6.robot @@ -16,7 +16,8 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${CONFIG_SLEEP}= 1s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s ${RESYNC_SLEEP}= 1s # wait for resync vpps after restart ${RESYNC_WAIT}= 30s @@ -41,13 +42,13 @@ Setup Interfaces vpp_ctl: Put Veth Interface Via Linux Plugin node=agent_vpp_1 namespace=ns2 name=ns2_veth3 host_if_name=ns2_veth3_linux mac=92:c7:42:67:ab:cf peer=ns3_veth3 ip=${IP_3} prefix=30 vpp_ctl: Put Veth Interface Via Linux Plugin node=agent_vpp_1 namespace=ns3 name=ns3_veth3 host_if_name=ns3_veth3_linux mac=92:c7:42:67:ab:ce peer=ns2_veth3 ip=${IP_4} prefix=30 - Sleep ${CONFIG_SLEEP} + Chcek Linux Interfaces - Check Linux Interfaces node=agent_vpp_1 namespace=ns1 interface=ns1_veth1 - Check Linux Interfaces node=agent_vpp_1 namespace=ns2 interface=ns2_veth2 - Check Linux Interfaces node=agent_vpp_1 namespace=ns2 interface=ns2_veth3 - Check Linux Interfaces node=agent_vpp_1 namespace=ns3 interface=ns3_veth3 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Interfaces node=agent_vpp_1 namespace=ns1 interface=ns1_veth1 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Interfaces node=agent_vpp_1 namespace=ns2 interface=ns2_veth2 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Interfaces node=agent_vpp_1 namespace=ns2 interface=ns2_veth3 + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Interfaces node=agent_vpp_1 namespace=ns3 interface=ns3_veth3 Ping6 In Namespaces # This should work by default after veth interface setup @@ -72,8 +73,8 @@ Create Linux Defalut Routes Sleep ${CONFIG_SLEEP} Check Linux Default Routes - Check Linux Default Routes node=agent_vpp_1 namespace=ns1 next_hop=${IP_1} - Check Linux Default Routes node=agent_vpp_1 namespace=ns3 next_hop=${IP_4} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Default Routes node=agent_vpp_1 namespace=ns1 next_hop=${IP_1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Default Routes node=agent_vpp_1 namespace=ns3 next_hop=${IP_4} Ping6 In Namespaces Again Ping6 in namespace node=agent_vpp_1 namespace=ns1 ip=${IP_3} @@ -87,7 +88,7 @@ Create Linux Routes2 #This needs to be fixed - https://jira.pantheon.sk/browse/ODPM-743 vpp_ctl: Put Linux Route Without Interface node=agent_vpp_1 namespace=ns1 routename=outercross1 ip=${IP_4} prefix=32 next_hop=${IP_2} vpp_ctl: Put Linux Route Without Interface node=agent_vpp_1 namespace=ns3 routename=outercross2 ip=${IP_1} prefix=32 next_hop=${IP_3} - Sleep ${CONFIG_SLEEP} + #temporarily - because previous commands does not work ${out}= Execute In Container agent_vpp_1 ip netns exec ns1 ip route add ${IP_4}/32 via ${IP_2} @@ -104,8 +105,8 @@ Create Linux Routes2 ${out}= Execute In Container agent_vpp_1 ip netns exec ns2 sysctl -w net.ipv4.ip_forward=1 Check Linux Routes2 - Check Linux Routes Gateway node=agent_vpp_1 namespace=ns1 ip=${IP_4} next_hop=${IP_2} - Check Linux Routes Gateway node=agent_vpp_1 namespace=ns3 ip=${IP_1} next_hop=${IP_3} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes Gateway node=agent_vpp_1 namespace=ns1 ip=${IP_4} next_hop=${IP_2} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} Check Linux Routes Gateway node=agent_vpp_1 namespace=ns3 ip=${IP_1} next_hop=${IP_3} Ping6 in namespace node=agent_vpp_1 namespace=ns1 ip=${IP_4} Ping6 in namespace node=agent_vpp_1 namespace=ns3 ip=${IP_1} diff --git a/tests/robot/suites/trafficIPv6/tap_int_traffic/tap_int_and_route_config_order_trafficIPv6.robot b/tests/robot/suites/trafficIPv6/tap_int_traffic/tap_int_and_route_config_order_trafficIPv6.robot index 00e413f178..6d26ca3f83 100644 --- a/tests/robot/suites/trafficIPv6/tap_int_traffic/tap_int_and_route_config_order_trafficIPv6.robot +++ b/tests/robot/suites/trafficIPv6/tap_int_traffic/tap_int_and_route_config_order_trafficIPv6.robot @@ -37,7 +37,8 @@ ${IP_VPP1_MEMIF1}= fd33::1:a:0:0:1 ${IP_VPP2_MEMIF1}= fd33::1:a:0:0:2 ${PREFIX}= 64 ${UP_STATE}= up -${SYNC_SLEEP}= 10s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s # wait for resync vpps after restart ${RESYNC_WAIT}= 50s @@ -54,25 +55,25 @@ Add VPP1_TAP1 Interface And Check It Was Created vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_VPP1_TAP1} vpp_ctl: Put TAP Interface With IP node=agent_vpp_1 name=${NAME_VPP1_TAP1} mac=${MAC_VPP1_TAP1} ip=${IP_VPP1_TAP1} prefix=${PREFIX} host_if_name=linux_${NAME_VPP1_TAP1} linux: Set Host TAP Interface node=agent_vpp_1 host_if_name=linux_${NAME_VPP1_TAP1} ip=${IP_LINUX_VPP1_TAP1} prefix=${PREFIX} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_TAP1} ${actual_state}= vpp_term: Check TAP Interface State agent_vpp_1 ${NAME_VPP1_TAP1} mac=${MAC_VPP1_TAP1} ipv6=${IP_VPP1_TAP1}/${PREFIX} state=${UP_STATE} Add VPP1_memif1 Interface vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=${NAME_VPP1_MEMIF1} mac=${MAC_VPP1_MEMIF1} master=true id=1 ip=${IP_VPP1_MEMIF1} prefix=24 socket=memif.sock - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} Add VPP2_TAP1 Interface And Check It Was Created vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MAC_VPP2_TAP1} vpp_ctl: Put TAP Interface With IP node=agent_vpp_2 name=${NAME_VPP2_TAP1} mac=${MAC_VPP2_TAP1} ip=${IP_VPP2_TAP1} prefix=${PREFIX} host_if_name=linux_${NAME_VPP2_TAP1} linux: Set Host TAP Interface node=agent_vpp_2 host_if_name=linux_${NAME_VPP2_TAP1} ip=${IP_LINUX_VPP2_TAP1} prefix=${PREFIX} - vpp_term: Interface Is Created node=agent_vpp_2 mac=${MAC_VPP2_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_2 mac=${MAC_VPP2_TAP1} ${actual_state}= vpp_term: Check TAP Interface State agent_vpp_2 ${NAME_VPP2_TAP1} mac=${MAC_VPP2_TAP1} ipv6=${IP_VPP2_TAP1}/${PREFIX} state=${UP_STATE} Add VPP2_memif1 Interface vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MAC_VPP2_MEMIF1} vpp_ctl: Put Memif Interface With IP node=agent_vpp_2 name=${NAME_VPP2_MEMIF1} mac=${MAC_VPP2_MEMIF1} master=false id=1 ip=${IP_VPP2_MEMIF1} prefix=24 socket=memif.sock - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} Add Static Route From VPP1 Linux To VPP2 vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=${EMPTY} interface=${NAME_VPP1_TAP1} routename=${NAME_VPP1_LINUX_TO_VPP2} ip=${IP_VPP2_TAP1_NETWORK} next_hop=${EMPTY} @@ -155,25 +156,25 @@ Add VPP1_TAP1 Interface And Check It Was Created 2 vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_VPP1_TAP1} vpp_ctl: Put TAP Interface With IP node=agent_vpp_1 name=${NAME_VPP1_TAP1} mac=${MAC_VPP1_TAP1} ip=${IP_VPP1_TAP1} prefix=${PREFIX} host_if_name=linux_${NAME_VPP1_TAP1} linux: Set Host TAP Interface node=agent_vpp_1 host_if_name=linux_${NAME_VPP1_TAP1} ip=${IP_LINUX_VPP1_TAP1} prefix=${PREFIX} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_TAP1} ${actual_state}= vpp_term: Check TAP Interface State agent_vpp_1 ${NAME_VPP1_TAP1} mac=${MAC_VPP1_TAP1} ipv6=${IP_VPP1_TAP1}/${PREFIX} state=${UP_STATE} Add VPP1_memif1 Interface 2 vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=${NAME_VPP1_MEMIF1} mac=${MAC_VPP1_MEMIF1} master=true id=1 ip=${IP_VPP1_MEMIF1} prefix=24 socket=memif.sock - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} Add VPP2_TAP1 Interface And Check It Was Created 2 vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MAC_VPP2_TAP1} vpp_ctl: Put TAP Interface With IP node=agent_vpp_2 name=${NAME_VPP2_TAP1} mac=${MAC_VPP2_TAP1} ip=${IP_VPP2_TAP1} prefix=${PREFIX} host_if_name=linux_${NAME_VPP2_TAP1} linux: Set Host TAP Interface node=agent_vpp_2 host_if_name=linux_${NAME_VPP2_TAP1} ip=${IP_LINUX_VPP2_TAP1} prefix=${PREFIX} - vpp_term: Interface Is Created node=agent_vpp_2 mac=${MAC_VPP2_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_2 mac=${MAC_VPP2_TAP1} ${actual_state}= vpp_term: Check TAP Interface State agent_vpp_2 ${NAME_VPP2_TAP1} mac=${MAC_VPP2_TAP1} ipv6=${IP_VPP2_TAP1}/${PREFIX} state=${UP_STATE} Add VPP2_memif1 Interface 2 vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MAC_VPP2_MEMIF1} vpp_ctl: Put Memif Interface With IP node=agent_vpp_2 name=${NAME_VPP2_MEMIF1} mac=${MAC_VPP2_MEMIF1} master=false id=1 ip=${IP_VPP2_MEMIF1} prefix=24 socket=memif.sock - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} Show Routes On VPP1 Linux 2 ${out}= Execute In Container agent_vpp_1 ip addr show linux_${NAME_VPP1_TAP1} diff --git a/tests/robot/suites/trafficIPv6/tapv2_int_traffic/tapv2_int_and_route_config_order_trafficIPv6.robot b/tests/robot/suites/trafficIPv6/tapv2_int_traffic/tapv2_int_and_route_config_order_trafficIPv6.robot index 5752c956ec..5691c1e0f5 100644 --- a/tests/robot/suites/trafficIPv6/tapv2_int_traffic/tapv2_int_and_route_config_order_trafficIPv6.robot +++ b/tests/robot/suites/trafficIPv6/tapv2_int_traffic/tapv2_int_and_route_config_order_trafficIPv6.robot @@ -35,7 +35,8 @@ ${IP_VPP1_MEMIF1}= fd33::1:a:0:0:1 ${IP_VPP2_MEMIF1}= fd33::1:a:0:0:2 ${PREFIX}= 64 ${UP_STATE}= up -${SYNC_SLEEP}= 10s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s # wait for resync vpps after restart ${RESYNC_WAIT}= 50s @@ -53,25 +54,25 @@ Add VPP1_TAP1 Interface And Check It Was Created vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_VPP1_TAP1} vpp_ctl: Put TAPv2 Interface With IP node=agent_vpp_1 name=${NAME_VPP1_TAP1} mac=${MAC_VPP1_TAP1} ip=${IP_VPP1_TAP1} prefix=${PREFIX} host_if_name=linux_${NAME_VPP1_TAP1} linux: Set Host TAP Interface node=agent_vpp_1 host_if_name=linux_${NAME_VPP1_TAP1} ip=${IP_LINUX_VPP1_TAP1} prefix=${PREFIX} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_TAP1} ${actual_state}= vpp_term: Check TAPv2 Interface State agent_vpp_1 ${NAME_VPP1_TAP1} mac=${MAC_VPP1_TAP1} ipv6=${IP_VPP1_TAP1}/${PREFIX} state=${UP_STATE} Add VPP1_memif1 Interface vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=${NAME_VPP1_MEMIF1} mac=${MAC_VPP1_MEMIF1} master=true id=1 ip=${IP_VPP1_MEMIF1} prefix=24 socket=memif.sock - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} Add VPP2_TAP1 Interface And Check It Was Created vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MAC_VPP2_TAP1} vpp_ctl: Put TAPv2 Interface With IP node=agent_vpp_2 name=${NAME_VPP2_TAP1} mac=${MAC_VPP2_TAP1} ip=${IP_VPP2_TAP1} prefix=${PREFIX} host_if_name=linux_${NAME_VPP2_TAP1} linux: Set Host TAP Interface node=agent_vpp_2 host_if_name=linux_${NAME_VPP2_TAP1} ip=${IP_LINUX_VPP2_TAP1} prefix=${PREFIX} - vpp_term: Interface Is Created node=agent_vpp_2 mac=${MAC_VPP2_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_2 mac=${MAC_VPP2_TAP1} ${actual_state}= vpp_term: Check TAPv2 Interface State agent_vpp_2 ${NAME_VPP2_TAP1} mac=${MAC_VPP2_TAP1} ipv6=${IP_VPP2_TAP1}/${PREFIX} state=${UP_STATE} Add VPP2_memif1 Interface vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MAC_VPP2_MEMIF1} vpp_ctl: Put Memif Interface With IP node=agent_vpp_2 name=${NAME_VPP2_MEMIF1} mac=${MAC_VPP2_MEMIF1} master=false id=1 ip=${IP_VPP2_MEMIF1} prefix=24 socket=memif.sock - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} Add Static Route From VPP1 Linux To VPP2 vpp_ctl: Put Linux Route node=agent_vpp_1 namespace=${EMPTY} interface=${NAME_VPP1_TAP1} routename=${NAME_VPP1_LINUX_TO_VPP2} ip=${IP_VPP2_TAP1_NETWORK} next_hop=${EMPTY} @@ -154,25 +155,25 @@ Add VPP1_TAP1 Interface And Check It Was Created 2 vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_VPP1_TAP1} vpp_ctl: Put TAPv2 Interface With IP node=agent_vpp_1 name=${NAME_VPP1_TAP1} mac=${MAC_VPP1_TAP1} ip=${IP_VPP1_TAP1} prefix=${PREFIX} host_if_name=linux_${NAME_VPP1_TAP1} linux: Set Host TAP Interface node=agent_vpp_1 host_if_name=linux_${NAME_VPP1_TAP1} ip=${IP_LINUX_VPP1_TAP1} prefix=${PREFIX} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_TAP1} ${actual_state}= vpp_term: Check TAPv2 Interface State agent_vpp_1 ${NAME_VPP1_TAP1} mac=${MAC_VPP1_TAP1} ipv6=${IP_VPP1_TAP1}/${PREFIX} state=${UP_STATE} Add VPP1_memif1 Interface 2 vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=${NAME_VPP1_MEMIF1} mac=${MAC_VPP1_MEMIF1} master=true id=1 ip=${IP_VPP1_MEMIF1} prefix=24 socket=memif.sock - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} Add VPP2_TAP1 Interface And Check It Was Created 2 vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MAC_VPP2_TAP1} vpp_ctl: Put TAPv2 Interface With IP node=agent_vpp_2 name=${NAME_VPP2_TAP1} mac=${MAC_VPP2_TAP1} ip=${IP_VPP2_TAP1} prefix=${PREFIX} host_if_name=linux_${NAME_VPP2_TAP1} linux: Set Host TAP Interface node=agent_vpp_2 host_if_name=linux_${NAME_VPP2_TAP1} ip=${IP_LINUX_VPP2_TAP1} prefix=${PREFIX} - vpp_term: Interface Is Created node=agent_vpp_2 mac=${MAC_VPP2_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_2 mac=${MAC_VPP2_TAP1} ${actual_state}= vpp_term: Check TAPv2 Interface State agent_vpp_2 ${NAME_VPP2_TAP1} mac=${MAC_VPP2_TAP1} ipv6=${IP_VPP2_TAP1}/${PREFIX} state=${UP_STATE} Add VPP2_memif1 Interface 2 vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MAC_VPP2_MEMIF1} vpp_ctl: Put Memif Interface With IP node=agent_vpp_2 name=${NAME_VPP2_MEMIF1} mac=${MAC_VPP2_MEMIF1} master=false id=1 ip=${IP_VPP2_MEMIF1} prefix=24 socket=memif.sock - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} Show Routes On VPP1 Linux 2 ${out}= Execute In Container agent_vpp_1 ip addr show linux_${NAME_VPP1_TAP1} diff --git a/tests/robot/suites/trafficIPv6/tapv2_int_traffic/tapv2_int_trafficIPv6.robot b/tests/robot/suites/trafficIPv6/tapv2_int_traffic/tapv2_int_trafficIPv6.robot index c45b98d681..5ddcaa7a9d 100644 --- a/tests/robot/suites/trafficIPv6/tapv2_int_traffic/tapv2_int_trafficIPv6.robot +++ b/tests/robot/suites/trafficIPv6/tapv2_int_traffic/tapv2_int_trafficIPv6.robot @@ -33,7 +33,8 @@ ${IP_VPP1_MEMIF1}= fd33::1:a:0:0:1 ${IP_VPP2_MEMIF1}= fd33::1:a:0:0:2 ${PREFIX}= 64 ${UP_STATE}= up -${SYNC_SLEEP}= 10s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 2s # wait for resync vpps after restart ${RESYNC_WAIT}= 50s @@ -55,7 +56,7 @@ Add VPP1_TAP1 Interface Check VPP1_TAP1 Interface Is Created ${interfaces}= vat_term: Interfaces Dump node=agent_vpp_1 Log ${interfaces} - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_TAP1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_TAP1} ${actual_state}= vpp_term: Check TAPv2 interface State agent_vpp_1 ${NAME_VPP1_TAP1} mac=${MAC_VPP1_TAP1} ipv6=${IP_VPP1_TAP1}/${PREFIX} state=${UP_STATE} Check Ping Between VPP1 and linux_VPP1_TAP1 Interface @@ -65,7 +66,7 @@ Check Ping Between VPP1 and linux_VPP1_TAP1 Interface Add VPP1_memif1 Interface vpp_term: Interface Not Exists node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} vpp_ctl: Put Memif Interface With IP node=agent_vpp_1 name=${NAME_VPP1_MEMIF1} mac=${MAC_VPP1_MEMIF1} master=true id=1 ip=${IP_VPP1_MEMIF1} prefix=24 socket=memif.sock - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} Add VPP2_TAP1 Interface vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MAC_VPP2_TAP1} @@ -85,7 +86,7 @@ Check Ping Between VPP2 And linux_VPP2_TAP1 Interface Add VPP2_memif1 Interface vpp_term: Interface Not Exists node=agent_vpp_2 mac=${MAC_VPP2_MEMIF1} vpp_ctl: Put Memif Interface With IP node=agent_vpp_2 name=${NAME_VPP2_MEMIF1} mac=${MAC_VPP2_MEMIF1} master=false id=1 ip=${IP_VPP2_MEMIF1} prefix=24 socket=memif.sock - vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} + Wait Until Keyword Succeeds ${WAIT_TIMEOUT} ${SYNC_SLEEP} vpp_term: Interface Is Created node=agent_vpp_1 mac=${MAC_VPP1_MEMIF1} Check Ping From VPP1 To VPP2_memif1 vpp_term: Check Ping node=agent_vpp_1 ip=${IP_VPP2_MEMIF1} diff --git a/tests/robot/suites/trafficIPv6/veth_af_packet_traffic/veth_af_packet_trafficIPv6.robot b/tests/robot/suites/trafficIPv6/veth_af_packet_traffic/veth_af_packet_trafficIPv6.robot index 70e1fabb48..9190ec79ac 100644 --- a/tests/robot/suites/trafficIPv6/veth_af_packet_traffic/veth_af_packet_trafficIPv6.robot +++ b/tests/robot/suites/trafficIPv6/veth_af_packet_traffic/veth_af_packet_trafficIPv6.robot @@ -17,9 +17,9 @@ Test Teardown TestTeardown *** Variables *** ${VARIABLES}= common ${ENV}= common -${FINAL_SLEEP}= 5s -${SYNC_SLEEP}= 40s -${RESYNC_SLEEP}= 450s +${WAIT_TIMEOUT}= 20s +${SYNC_SLEEP}= 5s +${RESYNC_SLEEP}= 20s ${AGENT1_VETH_MAC}= 02:00:00:00:00:01 ${AGENT2_VETH_MAC}= 02:00:00:00:00:02 diff --git a/tests/vppcallmock/vpp_ctx_mock.go b/tests/vppcallmock/vpp_ctx_mock.go index 45f880fe8b..e6adbf6b8b 100644 --- a/tests/vppcallmock/vpp_ctx_mock.go +++ b/tests/vppcallmock/vpp_ctx_mock.go @@ -17,15 +17,32 @@ package vppcallmock import ( "testing" - "time" - "git.fd.io/govpp.git/adapter/mock" govppapi "git.fd.io/govpp.git/api" govpp "git.fd.io/govpp.git/core" + log "github.com/ligato/cn-infra/logging/logrus" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/acl" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/af_packet" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/bfd" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/interfaces" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/ip" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/memif" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/nat" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/stn" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/tap" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/tapv2" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/vpe" + "github.com/ligato/vpp-agent/plugins/vpp/binapi/vxlan" . "github.com/onsi/gomega" + "github.com/sirupsen/logrus" ) -// TestCtx is helping structure for unit testing. It wraps VppAdapter which is used instead of real VPP +func init() { + govpp.SetLogLevel(logrus.DebugLevel) +} + +// TestCtx is helping structure for unit testing. +// It wraps VppAdapter which is used instead of real VPP. type TestCtx struct { MockVpp *mock.VppAdapter conn *govpp.Connection @@ -48,7 +65,7 @@ func SetupTestCtx(t *testing.T) *TestCtx { ctx.channel, err = ctx.conn.NewAPIChannel() Expect(err).ShouldNot(HaveOccurred()) - ctx.MockChannel = &mockedChannel{channel: ctx.channel} + ctx.MockChannel = &mockedChannel{Channel: ctx.channel} return ctx } @@ -61,7 +78,7 @@ func (ctx *TestCtx) TeardownTestCtx() { // MockedChannel implements ChannelIntf for testing purposes type mockedChannel struct { - channel govppapi.Channel + govppapi.Channel // Last message which passed through method SendRequest Msg govppapi.Message @@ -74,68 +91,99 @@ type mockedChannel struct { func (m *mockedChannel) SendRequest(msg govppapi.Message) govppapi.RequestCtx { m.Msg = msg m.Msgs = append(m.Msgs, msg) - return m.channel.SendRequest(msg) + return m.Channel.SendRequest(msg) } // SendMultiRequest just save input argument to structure field for future check func (m *mockedChannel) SendMultiRequest(msg govppapi.Message) govppapi.MultiRequestCtx { m.Msg = msg m.Msgs = append(m.Msgs, msg) - return m.channel.SendMultiRequest(msg) -} - -// CheckMessageCompatibility checks whether provided messages are compatible with the version of VPP -// which the library is connected to -func (m *mockedChannel) CheckMessageCompatibility(msgs ...govppapi.Message) error { - return m.channel.CheckMessageCompatibility(msgs...) -} - -// SubscribeNotification subscribes for receiving of the specified notification messages via provided Go channel -func (m *mockedChannel) SubscribeNotification(notifChan chan govppapi.Message, msgFactory func() govppapi.Message) (*govppapi.NotifSubscription, error) { - return m.channel.SubscribeNotification(notifChan, msgFactory) -} - -// UnsubscribeNotification unsubscribes from receiving the notifications tied to the provided notification subscription -func (m *mockedChannel) UnsubscribeNotification(subscription *govppapi.NotifSubscription) error { - return m.channel.UnsubscribeNotification(subscription) -} - -// SetReplyTimeout sets the timeout for replies from VPP -func (m *mockedChannel) SetReplyTimeout(timeout time.Duration) { - m.channel.SetReplyTimeout(timeout) -} - -// GetNotificationChannel returns notification channel -func (m *mockedChannel) GetReplyChannel() <-chan *govppapi.VppReply { - return m.channel.GetReplyChannel() -} - -// GetRequestChannel returns notification channel -func (m *mockedChannel) GetRequestChannel() chan<- *govppapi.VppRequest { - return m.channel.GetRequestChannel() -} - -// GetNotificationChannel returns notification channel -func (m *mockedChannel) GetNotificationChannel() chan<- *govppapi.NotifSubscribeRequest { - return m.channel.GetNotificationChannel() -} - -// GetNotificationReplyChannel returns notification reply channel -func (m *mockedChannel) GetNotificationReplyChannel() <-chan error { - return m.channel.GetNotificationReplyChannel() -} - -// GetMessageDecoder returns message decoder -func (m *mockedChannel) GetMessageDecoder() govppapi.MessageDecoder { - return m.channel.GetMessageDecoder() -} - -// GetID returns channel's ID -func (m *mockedChannel) GetID() uint16 { - return m.channel.GetID() -} - -// Close closes channel -func (m *mockedChannel) Close() { - m.channel.Close() + return m.Channel.SendMultiRequest(msg) +} + +// HandleReplies represents spec for MockReplyHandler. +type HandleReplies struct { + Name string + Ping bool + Message govppapi.Message + Messages []govppapi.Message +} + +// MockReplies sets up reply handler for give HandleReplies. +func (ctx *TestCtx) MockReplies(dataList []*HandleReplies) { + var sendControlPing bool + + ctx.MockVpp.RegisterBinAPITypes(acl.Types) + ctx.MockVpp.RegisterBinAPITypes(af_packet.Types) + ctx.MockVpp.RegisterBinAPITypes(bfd.Types) + ctx.MockVpp.RegisterBinAPITypes(nat.Types) + ctx.MockVpp.RegisterBinAPITypes(stn.Types) + ctx.MockVpp.RegisterBinAPITypes(interfaces.Types) + ctx.MockVpp.RegisterBinAPITypes(ip.Types) + ctx.MockVpp.RegisterBinAPITypes(memif.Types) + ctx.MockVpp.RegisterBinAPITypes(tap.Types) + ctx.MockVpp.RegisterBinAPITypes(tapv2.Types) + ctx.MockVpp.RegisterBinAPITypes(vpe.Types) + ctx.MockVpp.RegisterBinAPITypes(vxlan.Types) + + ctx.MockVpp.MockReplyHandler(func(request mock.MessageDTO) (reply []byte, msgID uint16, prepared bool) { + // Following types are not automatically stored in mock adapter's map and will be sent with empty MsgName + // TODO: initialize mock adapter's map with these + switch request.MsgID { + case 100: + request.MsgName = "control_ping" + case 101: + request.MsgName = "control_ping_reply" + case 200: + request.MsgName = "sw_interface_dump" + case 201: + request.MsgName = "sw_interface_details" + } + + if request.MsgName == "" { + log.DefaultLogger().Fatalf("mockHandler received request (ID: %v) with empty MsgName, check if compatbility check is done before using this request", request.MsgID) + } + + if sendControlPing { + sendControlPing = false + data := &vpe.ControlPingReply{} + reply, err := ctx.MockVpp.ReplyBytes(request, data) + Expect(err).To(BeNil()) + msgID, err := ctx.MockVpp.GetMsgID(data.GetMessageName(), data.GetCrcString()) + Expect(err).To(BeNil()) + return reply, msgID, true + } + + for _, dataMock := range dataList { + if request.MsgName == dataMock.Name { + // Send control ping next iteration if set + sendControlPing = dataMock.Ping + if len(dataMock.Messages) > 0 { + log.DefaultLogger().Infof(" MOCK HANDLER: mocking %d messages", len(dataMock.Messages)) + for _, msg := range dataMock.Messages { + ctx.MockVpp.MockReply(msg) + } + return nil, 0, false + } + msgID, err := ctx.MockVpp.GetMsgID(dataMock.Message.GetMessageName(), dataMock.Message.GetCrcString()) + Expect(err).To(BeNil()) + reply, err := ctx.MockVpp.ReplyBytes(request, dataMock.Message) + Expect(err).To(BeNil()) + return reply, msgID, true + } + } + + var err error + replyMsg, id, ok := ctx.MockVpp.ReplyFor(request.MsgName) + if ok { + reply, err = ctx.MockVpp.ReplyBytes(request, replyMsg) + Expect(err).To(BeNil()) + msgID = id + prepared = true + } else { + log.DefaultLogger().Warnf("NO REPLY FOR %v FOUND", request.MsgName) + } + + return reply, msgID, prepared + }) } diff --git a/vendor/git.fd.io/govpp.git/adapter/adapter.go b/vendor/git.fd.io/govpp.git/adapter/adapter.go index bc3a573b44..7d3d1e429a 100644 --- a/vendor/git.fd.io/govpp.git/adapter/adapter.go +++ b/vendor/git.fd.io/govpp.git/adapter/adapter.go @@ -14,6 +14,16 @@ package adapter +import ( + "errors" +) + +// ErrNotImplemented is an error returned when missing implementation. +var ErrNotImplemented = errors.New("not implemented for this OS") + +// MsgCallback defines func signature for message callback. +type MsgCallback func(msgID uint16, context uint32, data []byte) + // VppAdapter provides connection to VPP. It is responsible for sending and receiving of binary-encoded messages to/from VPP. type VppAdapter interface { // Connect connects the process to VPP. @@ -29,7 +39,7 @@ type VppAdapter interface { SendMsg(context uint32, data []byte) error // SetMsgCallback sets a callback function that will be called by the adapter whenever a message comes from VPP. - SetMsgCallback(func(context uint32, msgId uint16, data []byte)) + SetMsgCallback(cb MsgCallback) // WaitReady waits until adapter is ready. WaitReady() error diff --git a/vendor/git.fd.io/govpp.git/adapter/mock/mock_adapter.go b/vendor/git.fd.io/govpp.git/adapter/mock/mock_adapter.go index a5cb62de06..3f5686f352 100644 --- a/vendor/git.fd.io/govpp.git/adapter/mock/mock_adapter.go +++ b/vendor/git.fd.io/govpp.git/adapter/mock/mock_adapter.go @@ -25,7 +25,6 @@ import ( "git.fd.io/govpp.git/adapter" "git.fd.io/govpp.git/adapter/mock/binapi" "git.fd.io/govpp.git/api" - "git.fd.io/govpp.git/codec" "github.com/lunixbochs/struc" ) @@ -33,24 +32,24 @@ import ( type replyMode int const ( - _ replyMode = 0 - useRepliesQueue = 1 // use replies in the queue - useReplyHandlers = 2 // use reply handler + _ replyMode = iota + useRepliesQueue // use replies in the queue + useReplyHandlers // use reply handler ) // VppAdapter represents a mock VPP adapter that can be used for unit/integration testing instead of the vppapiclient adapter. type VppAdapter struct { - callback func(context uint32, msgId uint16, data []byte) + callback adapter.MsgCallback + msgIDSeq uint16 + access sync.RWMutex msgNameToIds map[string]uint16 msgIDsToName map[uint16]string - msgIDSeq uint16 binAPITypes map[string]reflect.Type - access sync.RWMutex + repliesLock sync.Mutex // mutex for the queue replies []reply // FIFO queue of messages replyHandlers []ReplyHandler // callbacks that are able to calculate mock responses - repliesLock sync.Mutex // mutex for the queue mode replyMode // mode in which the mock operates } @@ -211,8 +210,6 @@ func (a *VppAdapter) GetMsgID(msgName string, msgCrc string) (uint16, error) { a.msgNameToIds[msgName] = msgID a.msgIDsToName[msgID] = msgName - log.Println("VPP GetMessageId ", msgID, " name:", msgName, " crc:", msgCrc) - return msgID, nil } @@ -252,11 +249,12 @@ func (a *VppAdapter) SendMsg(clientID uint32, data []byte) error { Data: data, }) if finished { - a.callback(clientID, msgID, reply) + a.callback(msgID, clientID, reply) return nil } } fallthrough + case useRepliesQueue: a.repliesLock.Lock() defer a.repliesLock.Unlock() @@ -274,15 +272,15 @@ func (a *VppAdapter) SendMsg(clientID uint32, data []byte) error { } if msg.Msg.GetMessageType() == api.ReplyMessage { struc.Pack(buf, &codec.VppReplyHeader{VlMsgID: msgID, Context: context}) - } else if msg.Msg.GetMessageType() == api.EventMessage { - struc.Pack(buf, &codec.VppEventHeader{VlMsgID: msgID, Context: context}) } else if msg.Msg.GetMessageType() == api.RequestMessage { struc.Pack(buf, &codec.VppRequestHeader{VlMsgID: msgID, Context: context}) + } else if msg.Msg.GetMessageType() == api.EventMessage { + struc.Pack(buf, &codec.VppEventHeader{VlMsgID: msgID}) } else { struc.Pack(buf, &codec.VppOtherHeader{VlMsgID: msgID}) } struc.Pack(buf, msg.Msg) - a.callback(context, msgID, buf.Bytes()) + a.callback(msgID, context, buf.Bytes()) } a.replies = a.replies[1:] @@ -301,13 +299,13 @@ func (a *VppAdapter) SendMsg(clientID uint32, data []byte) error { msgID := uint16(defaultReplyMsgID) struc.Pack(buf, &codec.VppReplyHeader{VlMsgID: msgID, Context: clientID}) struc.Pack(buf, &defaultReply{}) - a.callback(clientID, msgID, buf.Bytes()) + a.callback(msgID, clientID, buf.Bytes()) } return nil } // SetMsgCallback sets a callback function that will be called by the adapter whenever a message comes from the mock. -func (a *VppAdapter) SetMsgCallback(cb func(context uint32, msgID uint16, data []byte)) { +func (a *VppAdapter) SetMsgCallback(cb adapter.MsgCallback) { a.callback = cb } diff --git a/vendor/git.fd.io/govpp.git/adapter/vppapiclient/empty_adapter.go b/vendor/git.fd.io/govpp.git/adapter/vppapiclient/empty_adapter.go index c3010a0bfd..75140481f9 100644 --- a/vendor/git.fd.io/govpp.git/adapter/vppapiclient/empty_adapter.go +++ b/vendor/git.fd.io/govpp.git/adapter/vppapiclient/empty_adapter.go @@ -32,7 +32,7 @@ func NewVppAdapter(string) adapter.VppAdapter { } func (a *vppAPIClientAdapter) Connect() error { - return nil + return adapter.ErrNotImplemented } func (a *vppAPIClientAdapter) Disconnect() { @@ -47,7 +47,7 @@ func (a *vppAPIClientAdapter) SendMsg(clientID uint32, data []byte) error { return nil } -func (a *vppAPIClientAdapter) SetMsgCallback(cb func(context uint32, msgID uint16, data []byte)) { +func (a *vppAPIClientAdapter) SetMsgCallback(cb adapter.MsgCallback) { // no op } diff --git a/vendor/git.fd.io/govpp.git/adapter/vppapiclient/vppapiclient_adapter.go b/vendor/git.fd.io/govpp.git/adapter/vppapiclient/vppapiclient_adapter.go index c77d7f1017..7aafa5527b 100644 --- a/vendor/git.fd.io/govpp.git/adapter/vppapiclient/vppapiclient_adapter.go +++ b/vendor/git.fd.io/govpp.git/adapter/vppapiclient/vppapiclient_adapter.go @@ -28,7 +28,7 @@ package vppapiclient #include #include -extern void go_msg_callback(uint16_t, uint32_t, void*, size_t); +extern void go_msg_callback(uint16_t msg_id, uint32_t context, void* data, size_t size); typedef struct __attribute__((__packed__)) _req_header { uint16_t msg_id; @@ -38,7 +38,7 @@ typedef struct __attribute__((__packed__)) _req_header { typedef struct __attribute__((__packed__)) _reply_header { uint16_t msg_id; - uint32_t context; + uint32_t context; // currently not all reply messages contain context field } reply_header_t; static void @@ -49,23 +49,23 @@ govpp_msg_callback (unsigned char *data, int size) } static int -govpp_connect (char *shm) +govpp_send(uint32_t context, void *data, size_t size) { - return vac_connect("govpp", shm, govpp_msg_callback, 32); + req_header_t *header = ((req_header_t *)data); + header->context = htonl(context); + return vac_write(data, size); } static int -govvp_disconnect() +govpp_connect (char *shm) { - return vac_disconnect(); + return vac_connect("govpp", shm, govpp_msg_callback, 32); } static int -govpp_send(uint32_t context, void *data, size_t size) +govvp_disconnect() { - req_header_t *header = ((req_header_t *)data); - header->context = htonl(context); - return vac_write(data, size); + return vac_disconnect(); } static uint32_t @@ -79,6 +79,7 @@ import "C" import ( "fmt" "os" + "path/filepath" "reflect" "unsafe" @@ -98,7 +99,7 @@ const ( // vppAPIClientAdapter is the opaque context of the adapter. type vppAPIClientAdapter struct { shmPrefix string - callback func(context uint32, msgId uint16, data []byte) + callback adapter.MsgCallback } var vppClient *vppAPIClientAdapter // global vpp API client adapter context @@ -138,6 +139,7 @@ func (a *vppAPIClientAdapter) GetMsgID(msgName string, msgCrc string) (uint16, e msgID := uint16(C.govpp_get_msg_index(nameAndCrc)) if msgID == ^uint16(0) { + // VPP does not know this message return msgID, fmt.Errorf("unknown message: %v (crc: %v)", msgName, msgCrc) } @@ -154,40 +156,41 @@ func (a *vppAPIClientAdapter) SendMsg(context uint32, data []byte) error { } // SetMsgCallback sets a callback function that will be called by the adapter whenever a message comes from VPP. -func (a *vppAPIClientAdapter) SetMsgCallback(cb func(context uint32, msgID uint16, data []byte)) { +func (a *vppAPIClientAdapter) SetMsgCallback(cb adapter.MsgCallback) { a.callback = cb } // WaitReady blocks until shared memory for sending // binary api calls is present on the file system. func (a *vppAPIClientAdapter) WaitReady() error { - watcher, err := fsnotify.NewWatcher() - if err != nil { - return err - } - defer watcher.Close() - - err = watcher.Add(watchedFolder) - if err != nil { - return err - } - // Path to the shared memory segment with prefix, if set + // Path to the shared memory segment var path string if a.shmPrefix == "" { - path = watchedFolder + watchedFile + path = filepath.Join(watchedFolder, watchedFile) } else { - path = watchedFolder + a.shmPrefix + "-" + watchedFile - } - if fileExists(path) { - return nil + path = filepath.Join(watchedFolder, a.shmPrefix+"-"+watchedFile) } - for { - ev := <-watcher.Events - if ev.Name == path && (ev.Op&fsnotify.Create) == fsnotify.Create { - break + // Watch folder if file does not exist yet + if !fileExists(path) { + watcher, err := fsnotify.NewWatcher() + if err != nil { + return err + } + defer watcher.Close() + + if err := watcher.Add(watchedFolder); err != nil { + return err + } + + for { + ev := <-watcher.Events + if ev.Name == path && (ev.Op&fsnotify.Create) == fsnotify.Create { + break + } } } + return nil } @@ -206,5 +209,5 @@ func go_msg_callback(msgID C.uint16_t, context C.uint32_t, data unsafe.Pointer, slice := &reflect.SliceHeader{Data: uintptr(data), Len: int(size), Cap: int(size)} byteArr := *(*[]byte)(unsafe.Pointer(slice)) - vppClient.callback(uint32(context), uint16(msgID), byteArr) -} \ No newline at end of file + vppClient.callback(uint16(msgID), uint32(context), byteArr) +} diff --git a/vendor/git.fd.io/govpp.git/api/api.go b/vendor/git.fd.io/govpp.git/api/api.go index 9c68ab96ee..39fe60f0c3 100644 --- a/vendor/git.fd.io/govpp.git/api/api.go +++ b/vendor/git.fd.io/govpp.git/api/api.go @@ -15,10 +15,15 @@ package api import ( + "fmt" "time" ) // MessageType represents the type of a VPP message. +// Note: this is currently derived from the message header (fields), +// and in many cases it does not represent the actual type of VPP message. +// This means that some replies can be identified as requests, etc. +// TODO: use services to identify type of message type MessageType int const ( @@ -26,9 +31,9 @@ const ( RequestMessage MessageType = iota // ReplyMessage represents a VPP reply message ReplyMessage - // EventMessage represents a VPP notification event message + // EventMessage represents a VPP event message EventMessage - // OtherMessage represents other VPP message (e.g. counters) + // OtherMessage represents other VPP message OtherMessage ) @@ -37,11 +42,11 @@ type Message interface { // GetMessageName returns the original VPP name of the message, as defined in the VPP API. GetMessageName() string - // GetMessageType returns the type of the VPP message. - GetMessageType() MessageType - // GetCrcString returns the string with CRC checksum of the message definition (the string represents a hexadecimal number). GetCrcString() string + + // GetMessageType returns the type of the VPP message. + GetMessageType() MessageType } // DataType is an interface that is implemented by all VPP Binary API data types by the binapi_generator. @@ -53,17 +58,6 @@ type DataType interface { GetCrcString() string } -// ChannelProvider provides the communication channel with govpp core. -type ChannelProvider interface { - // NewAPIChannel returns a new channel for communication with VPP via govpp core. - // It uses default buffer sizes for the request and reply Go channels. - NewAPIChannel() (Channel, error) - - // NewAPIChannelBuffered returns a new channel for communication with VPP via govpp core. - // It allows to specify custom buffer sizes for the request and reply Go channels. - NewAPIChannelBuffered(reqChanBufSize, replyChanBufSize int) (Channel, error) -} - // MessageDecoder provides functionality for decoding binary data to generated API messages. type MessageDecoder interface { // DecodeMsg decodes binary-encoded data of a message into provided Message structure. @@ -74,43 +68,48 @@ type MessageDecoder interface { type MessageIdentifier interface { // GetMessageID returns message identifier of given API message. GetMessageID(msg Message) (uint16, error) + // LookupByID looks up message name and crc by ID - LookupByID(ID uint16) (string, error) + LookupByID(msgID uint16) (Message, error) +} + +// ChannelProvider provides the communication channel with govpp core. +type ChannelProvider interface { + // NewAPIChannel returns a new channel for communication with VPP via govpp core. + // It uses default buffer sizes for the request and reply Go channels. + NewAPIChannel() (Channel, error) + + // NewAPIChannelBuffered returns a new channel for communication with VPP via govpp core. + // It allows to specify custom buffer sizes for the request and reply Go channels. + NewAPIChannelBuffered(reqChanBufSize, replyChanBufSize int) (Channel, error) } // Channel provides methods for direct communication with VPP channel. type Channel interface { + // GetID returns channel's ID + GetID() uint16 + // SendRequest asynchronously sends a request to VPP. Returns a request context, that can be used to call ReceiveReply. // In case of any errors by sending, the error will be delivered to ReplyChan (and returned by ReceiveReply). SendRequest(msg Message) RequestCtx + // SendMultiRequest asynchronously sends a multipart request (request to which multiple responses are expected) to VPP. // Returns a multipart request context, that can be used to call ReceiveReply. // In case of any errors by sending, the error will be delivered to ReplyChan (and returned by ReceiveReply). SendMultiRequest(msg Message) MultiRequestCtx + // SubscribeNotification subscribes for receiving of the specified notification messages via provided Go channel. // Note that the caller is responsible for creating the Go channel with preferred buffer size. If the channel's // buffer is full, the notifications will not be delivered into it. SubscribeNotification(notifChan chan Message, msgFactory func() Message) (*NotifSubscription, error) + // UnsubscribeNotification unsubscribes from receiving the notifications tied to the provided notification subscription. UnsubscribeNotification(subscription *NotifSubscription) error - // CheckMessageCompatibility checks whether provided messages are compatible with the version of VPP - // which the library is connected to. - CheckMessageCompatibility(messages ...Message) error + // SetReplyTimeout sets the timeout for replies from VPP. It represents the maximum time the API waits for a reply // from VPP before returning an error. SetReplyTimeout(timeout time.Duration) - // GetRequestChannel returns request go channel of the VPP channel - GetRequestChannel() chan<- *VppRequest - // GetReplyChannel returns reply go channel of the VPP channel - GetReplyChannel() <-chan *VppReply - // GetNotificationChannel returns notification go channel of the VPP channel - GetNotificationChannel() chan<- *NotifSubscribeRequest - // GetNotificationReplyChannel returns notification reply go channel of the VPP channel - GetNotificationReplyChannel() <-chan error - // GetMessageDecoder returns message decoder instance - GetMessageDecoder() MessageDecoder - // GetID returns channel's ID - GetID() uint16 + // Close closes the API channel and releases all API channel-related resources in the ChannelProvider. Close() } @@ -131,30 +130,24 @@ type MultiRequestCtx interface { ReceiveReply(msg Message) (lastReplyReceived bool, err error) } -// VppRequest is a request that will be sent to VPP. -type VppRequest struct { - SeqNum uint16 // sequence number - Message Message // binary API message to be send to VPP - Multipart bool // true if multipart response is expected, false otherwise +// NotifSubscription represents a subscription for delivery of specific notification messages. +type NotifSubscription struct { + NotifChan chan Message // channel where notification messages will be delivered to + MsgFactory func() Message // function that returns a new instance of the specific message that is expected as a notification + // TODO: use Message directly here, not a factory, eliminating need to allocation } -// VppReply is a reply received from VPP. -type VppReply struct { - MessageID uint16 // ID of the message - SeqNum uint16 // sequence number - Data []byte // encoded data with the message - MessageDecoder can be used for decoding - LastReplyReceived bool // in case of multipart replies, true if the last reply has been already received and this one should be ignored - Error error // in case of error, data is nil and this member contains error description -} +var registeredMessages = make(map[string]Message) -// NotifSubscribeRequest is a request to subscribe for delivery of specific notification messages. -type NotifSubscribeRequest struct { - Subscription *NotifSubscription // subscription details - Subscribe bool // true if this is a request to subscribe, false if unsubscribe +// RegisterMessage is called from generated code to register message. +func RegisterMessage(x Message, name string) { + if _, ok := registeredMessages[name]; ok { + panic(fmt.Errorf("govpp: duplicate message registered: %s (%s)", name, x.GetCrcString())) + } + registeredMessages[name] = x } -// NotifSubscription represents a subscription for delivery of specific notification messages. -type NotifSubscription struct { - NotifChan chan Message // channel where notification messages will be delivered to - MsgFactory func() Message // function that returns a new instance of the specific message that is expected as a notification +// GetAllMessages returns list of all registered messages. +func GetAllMessages() map[string]Message { + return registeredMessages } diff --git a/vendor/git.fd.io/govpp.git/api/vppapi_errors.go b/vendor/git.fd.io/govpp.git/api/vppapi_errors.go new file mode 100644 index 0000000000..c921e14f8b --- /dev/null +++ b/vendor/git.fd.io/govpp.git/api/vppapi_errors.go @@ -0,0 +1,274 @@ +package api + +import ( + "fmt" + "strconv" +) + +// VPPApiError represents VPP's vnet API error that is usually +// returned as Retval field in replies from VPP binary API. +type VPPApiError int32 + +func (e VPPApiError) Error() string { + var errstr string + if s, ok := vppApiErrors[e]; ok { + errstr = s + } else { + errstr = strconv.Itoa(int(e)) + } + return fmt.Sprintf("VPPApiError: %s", errstr) +} + +// definitions from: vpp/src/vnet/api_errno.h +const ( + _ VPPApiError = 0 + UNSPECIFIED = -1 + INVALID_SW_IF_INDEX = -2 + NO_SUCH_FIB = -3 + NO_SUCH_INNER_FIB = -4 + NO_SUCH_LABEL = -5 + NO_SUCH_ENTRY = -6 + INVALID_VALUE = -7 + INVALID_VALUE_2 = -8 + UNIMPLEMENTED = -9 + INVALID_SW_IF_INDEX_2 = -10 + SYSCALL_ERROR_1 = -11 + SYSCALL_ERROR_2 = -12 + SYSCALL_ERROR_3 = -13 + SYSCALL_ERROR_4 = -14 + SYSCALL_ERROR_5 = -15 + SYSCALL_ERROR_6 = -16 + SYSCALL_ERROR_7 = -17 + SYSCALL_ERROR_8 = -18 + SYSCALL_ERROR_9 = -19 + SYSCALL_ERROR_10 = -20 + FEATURE_DISABLED = -30 + INVALID_REGISTRATION = -31 + NEXT_HOP_NOT_IN_FIB = -50 + UNKNOWN_DESTINATION = -51 + PREFIX_MATCHES_NEXT_HOP = -52 + NEXT_HOP_NOT_FOUND_MP = -53 + NO_MATCHING_INTERFACE = -54 + INVALID_VLAN = -55 + VLAN_ALREADY_EXISTS = -56 + INVALID_SRC_ADDRESS = -57 + INVALID_DST_ADDRESS = -58 + ADDRESS_LENGTH_MISMATCH = -59 + ADDRESS_NOT_FOUND_FOR_INTERFACE = -60 + ADDRESS_NOT_LINK_LOCAL = -61 + IP6_NOT_ENABLED = -62 + IN_PROGRESS = 10 + NO_SUCH_NODE = -63 + NO_SUCH_NODE2 = -64 + NO_SUCH_TABLE = -65 + NO_SUCH_TABLE2 = -66 + NO_SUCH_TABLE3 = -67 + SUBIF_ALREADY_EXISTS = -68 + SUBIF_CREATE_FAILED = -69 + INVALID_MEMORY_SIZE = -70 + INVALID_INTERFACE = -71 + INVALID_VLAN_TAG_COUNT = -72 + INVALID_ARGUMENT = -73 + UNEXPECTED_INTF_STATE = -74 + TUNNEL_EXIST = -75 + INVALID_DECAP_NEXT = -76 + RESPONSE_NOT_READY = -77 + NOT_CONNECTED = -78 + IF_ALREADY_EXISTS = -79 + BOND_SLAVE_NOT_ALLOWED = -80 + VALUE_EXIST = -81 + SAME_SRC_DST = -82 + IP6_MULTICAST_ADDRESS_NOT_PRESENT = -83 + SR_POLICY_NAME_NOT_PRESENT = -84 + NOT_RUNNING_AS_ROOT = -85 + ALREADY_CONNECTED = -86 + UNSUPPORTED_JNI_VERSION = -87 + FAILED_TO_ATTACH_TO_JAVA_THREAD = -88 + INVALID_WORKER = -89 + LISP_DISABLED = -90 + CLASSIFY_TABLE_NOT_FOUND = -91 + INVALID_EID_TYPE = -92 + CANNOT_CREATE_PCAP_FILE = -93 + INCORRECT_ADJACENCY_TYPE = -94 + EXCEEDED_NUMBER_OF_RANGES_CAPACITY = -95 + EXCEEDED_NUMBER_OF_PORTS_CAPACITY = -96 + INVALID_ADDRESS_FAMILY = -97 + INVALID_SUB_SW_IF_INDEX = -98 + TABLE_TOO_BIG = -99 + CANNOT_ENABLE_DISABLE_FEATURE = -100 + BFD_EEXIST = -101 + BFD_ENOENT = -102 + BFD_EINUSE = -103 + BFD_NOTSUPP = -104 + ADDRESS_IN_USE = -105 + ADDRESS_NOT_IN_USE = -106 + QUEUE_FULL = -107 + APP_UNSUPPORTED_CFG = -108 + URI_FIFO_CREATE_FAILED = -109 + LISP_RLOC_LOCAL = -110 + BFD_EAGAIN = -111 + INVALID_GPE_MODE = -112 + LISP_GPE_ENTRIES_PRESENT = -113 + ADDRESS_FOUND_FOR_INTERFACE = -114 + SESSION_CONNECT = -115 + ENTRY_ALREADY_EXISTS = -116 + SVM_SEGMENT_CREATE_FAIL = -117 + APPLICATION_NOT_ATTACHED = -118 + BD_ALREADY_EXISTS = -119 + BD_IN_USE = -120 + BD_NOT_MODIFIABLE = -121 + BD_ID_EXCEED_MAX = -122 + SUBIF_DOESNT_EXIST = -123 + L2_MACS_EVENT_CLINET_PRESENT = -124 + INVALID_QUEUE = -125 + UNSUPPORTED = -126 + DUPLICATE_IF_ADDRESS = -127 + APP_INVALID_NS = -128 + APP_WRONG_NS_SECRET = -129 + APP_CONNECT_SCOPE = -130 + APP_ALREADY_ATTACHED = -131 + SESSION_REDIRECT = -132 + ILLEGAL_NAME = -133 + NO_NAME_SERVERS = -134 + NAME_SERVER_NOT_FOUND = -135 + NAME_RESOLUTION_NOT_ENABLED = -136 + NAME_SERVER_FORMAT_ERROR = -137 + NAME_SERVER_NO_SUCH_NAME = -138 + NAME_SERVER_NO_ADDRESSES = -139 + NAME_SERVER_NEXT_SERVER = -140 + APP_CONNECT_FILTERED = -141 + ACL_IN_USE_INBOUND = -142 + ACL_IN_USE_OUTBOUND = -143 + INIT_FAILED = -144 + NETLINK_ERROR = -145 + BIER_BSL_UNSUP = -146 + INSTANCE_IN_USE = -147 + INVALID_SESSION_ID = -148 + ACL_IN_USE_BY_LOOKUP_CONTEXT = -149 +) + +var vppApiErrors = map[VPPApiError]string{ + UNSPECIFIED: "Unspecified Error", + INVALID_SW_IF_INDEX: "Invalid sw_if_index", + NO_SUCH_FIB: "No such FIB / VRF", + NO_SUCH_INNER_FIB: "No such inner FIB / VRF", + NO_SUCH_LABEL: "No such label", + NO_SUCH_ENTRY: "No such entry", + INVALID_VALUE: "Invalid value", + INVALID_VALUE_2: "Invalid value #2", + UNIMPLEMENTED: "Unimplemented", + INVALID_SW_IF_INDEX_2: "Invalid sw_if_index #2", + SYSCALL_ERROR_1: "System call error #1", + SYSCALL_ERROR_2: "System call error #2", + SYSCALL_ERROR_3: "System call error #3", + SYSCALL_ERROR_4: "System call error #4", + SYSCALL_ERROR_5: "System call error #5", + SYSCALL_ERROR_6: "System call error #6", + SYSCALL_ERROR_7: "System call error #7", + SYSCALL_ERROR_8: "System call error #8", + SYSCALL_ERROR_9: "System call error #9", + SYSCALL_ERROR_10: "System call error #10", + FEATURE_DISABLED: "Feature disabled by configuration", + INVALID_REGISTRATION: "Invalid registration", + NEXT_HOP_NOT_IN_FIB: "Next hop not in FIB", + UNKNOWN_DESTINATION: "Unknown destination", + PREFIX_MATCHES_NEXT_HOP: "Prefix matches next hop", + NEXT_HOP_NOT_FOUND_MP: "Next hop not found (multipath)", + NO_MATCHING_INTERFACE: "No matching interface for probe", + INVALID_VLAN: "Invalid VLAN", + VLAN_ALREADY_EXISTS: "VLAN subif already exists", + INVALID_SRC_ADDRESS: "Invalid src address", + INVALID_DST_ADDRESS: "Invalid dst address", + ADDRESS_LENGTH_MISMATCH: "Address length mismatch", + ADDRESS_NOT_FOUND_FOR_INTERFACE: "Address not found for interface", + ADDRESS_NOT_LINK_LOCAL: "Address not link-local", + IP6_NOT_ENABLED: "ip6 not enabled", + IN_PROGRESS: "Operation in progress", + NO_SUCH_NODE: "No such graph node", + NO_SUCH_NODE2: "No such graph node #2", + NO_SUCH_TABLE: "No such table", + NO_SUCH_TABLE2: "No such table #2", + NO_SUCH_TABLE3: "No such table #3", + SUBIF_ALREADY_EXISTS: "Subinterface already exists", + SUBIF_CREATE_FAILED: "Subinterface creation failed", + INVALID_MEMORY_SIZE: "Invalid memory size requested", + INVALID_INTERFACE: "Invalid interface", + INVALID_VLAN_TAG_COUNT: "Invalid number of tags for requested operation", + INVALID_ARGUMENT: "Invalid argument", + UNEXPECTED_INTF_STATE: "Unexpected interface state", + TUNNEL_EXIST: "Tunnel already exists", + INVALID_DECAP_NEXT: "Invalid decap-next", + RESPONSE_NOT_READY: "Response not ready", + NOT_CONNECTED: "Not connected to the data plane", + IF_ALREADY_EXISTS: "Interface already exists", + BOND_SLAVE_NOT_ALLOWED: "Operation not allowed on slave of BondEthernet", + VALUE_EXIST: "Value already exists", + SAME_SRC_DST: "Source and destination are the same", + IP6_MULTICAST_ADDRESS_NOT_PRESENT: "IP6 multicast address required", + SR_POLICY_NAME_NOT_PRESENT: "Segement routing policy name required", + NOT_RUNNING_AS_ROOT: "Not running as root", + ALREADY_CONNECTED: "Connection to the data plane already exists", + UNSUPPORTED_JNI_VERSION: "Unsupported JNI version", + FAILED_TO_ATTACH_TO_JAVA_THREAD: "Failed to attach to Java thread", + INVALID_WORKER: "Invalid worker thread", + LISP_DISABLED: "LISP is disabled", + CLASSIFY_TABLE_NOT_FOUND: "Classify table not found", + INVALID_EID_TYPE: "Unsupported LSIP EID type", + CANNOT_CREATE_PCAP_FILE: "Cannot create pcap file", + INCORRECT_ADJACENCY_TYPE: "Invalid adjacency type for this operation", + EXCEEDED_NUMBER_OF_RANGES_CAPACITY: "Operation would exceed configured capacity of ranges", + EXCEEDED_NUMBER_OF_PORTS_CAPACITY: "Operation would exceed capacity of number of ports", + INVALID_ADDRESS_FAMILY: "Invalid address family", + INVALID_SUB_SW_IF_INDEX: "Invalid sub-interface sw_if_index", + TABLE_TOO_BIG: "Table too big", + CANNOT_ENABLE_DISABLE_FEATURE: "Cannot enable/disable feature", + BFD_EEXIST: "Duplicate BFD object", + BFD_ENOENT: "No such BFD object", + BFD_EINUSE: "BFD object in use", + BFD_NOTSUPP: "BFD feature not supported", + ADDRESS_IN_USE: "Address in use", + ADDRESS_NOT_IN_USE: "Address not in use", + QUEUE_FULL: "Queue full", + APP_UNSUPPORTED_CFG: "Unsupported application config", + URI_FIFO_CREATE_FAILED: "URI FIFO segment create failed", + LISP_RLOC_LOCAL: "RLOC address is local", + BFD_EAGAIN: "BFD object cannot be manipulated at this time", + INVALID_GPE_MODE: "Invalid GPE mode", + LISP_GPE_ENTRIES_PRESENT: "LISP GPE entries are present", + ADDRESS_FOUND_FOR_INTERFACE: "Address found for interface", + SESSION_CONNECT: "Session failed to connect", + ENTRY_ALREADY_EXISTS: "Entry already exists", + SVM_SEGMENT_CREATE_FAIL: "svm segment create fail", + APPLICATION_NOT_ATTACHED: "application not attached", + BD_ALREADY_EXISTS: "Bridge domain already exists", + BD_IN_USE: "Bridge domain has member interfaces", + BD_NOT_MODIFIABLE: "Bridge domain 0 can't be deleted/modified", + BD_ID_EXCEED_MAX: "Bridge domain ID exceed 16M limit", + SUBIF_DOESNT_EXIST: "Subinterface doesn't exist", + L2_MACS_EVENT_CLINET_PRESENT: "Client already exist for L2 MACs events", + INVALID_QUEUE: "Invalid queue", + UNSUPPORTED: "Unsupported", + DUPLICATE_IF_ADDRESS: "Address already present on another interface", + APP_INVALID_NS: "Invalid application namespace", + APP_WRONG_NS_SECRET: "Wrong app namespace secret", + APP_CONNECT_SCOPE: "Connect scope", + APP_ALREADY_ATTACHED: "App already attached", + SESSION_REDIRECT: "Redirect failed", + ILLEGAL_NAME: "Illegal name", + NO_NAME_SERVERS: "No name servers configured", + NAME_SERVER_NOT_FOUND: "Name server not found", + NAME_RESOLUTION_NOT_ENABLED: "Name resolution not enabled", + NAME_SERVER_FORMAT_ERROR: "Server format error (bug!)", + NAME_SERVER_NO_SUCH_NAME: "No such name", + NAME_SERVER_NO_ADDRESSES: "No addresses available", + NAME_SERVER_NEXT_SERVER: "Retry with new server", + APP_CONNECT_FILTERED: "Connect was filtered", + ACL_IN_USE_INBOUND: "Inbound ACL in use", + ACL_IN_USE_OUTBOUND: "Outbound ACL in use", + INIT_FAILED: "Initialization Failed", + NETLINK_ERROR: "netlink error", + BIER_BSL_UNSUP: "BIER bit-string-length unsupported", + INSTANCE_IN_USE: "Instance in use", + INVALID_SESSION_ID: "session ID out of range", + ACL_IN_USE_BY_LOOKUP_CONTEXT: "ACL in use by a lookup context", +} diff --git a/vendor/git.fd.io/govpp.git/cmd/binapi-generator/definitions.go b/vendor/git.fd.io/govpp.git/cmd/binapi-generator/definitions.go new file mode 100644 index 0000000000..3ad782f7ff --- /dev/null +++ b/vendor/git.fd.io/govpp.git/cmd/binapi-generator/definitions.go @@ -0,0 +1,176 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "strconv" + "strings" + "unicode" +) + +func getBinapiTypeSize(binapiType string) int { + if _, ok := binapiTypes[binapiType]; ok { + b, err := strconv.Atoi(strings.TrimLeft(binapiType, "uif")) + if err == nil { + return b / 8 + } + } + return -1 +} + +// binapiTypes is a set of types used VPP binary API for translation to Go types +var binapiTypes = map[string]string{ + "u8": "uint8", + "i8": "int8", + "u16": "uint16", + "i16": "int16", + "u32": "uint32", + "i32": "int32", + "u64": "uint64", + "i64": "int64", + "f64": "float64", +} + +func usesInitialism(s string) string { + if u := strings.ToUpper(s); commonInitialisms[u] { + return u + } else if su, ok := specialInitialisms[u]; ok { + return su + } + return "" +} + +// commonInitialisms is a set of common initialisms that need to stay in upper case. +var commonInitialisms = map[string]bool{ + "ACL": true, + "API": true, + //"ASCII": true, // there are only two use cases for ASCII which already have initialism before and after + "CPU": true, + "CSS": true, + "DNS": true, + "DHCP": true, + "EOF": true, + "GUID": true, + "HTML": true, + "HTTP": true, + "HTTPS": true, + "ID": true, + "IP": true, + "ICMP": true, + "JSON": true, + "LHS": true, + "QPS": true, + "PID": true, + "RAM": true, + "RHS": true, + "RPC": true, + "SLA": true, + "SMTP": true, + "SQL": true, + "SSH": true, + "TCP": true, + "TLS": true, + "TTL": true, + "UDP": true, + "UI": true, + "UID": true, + "UUID": true, + "URI": true, + "URL": true, + "UTF8": true, + "VM": true, + "VPN": true, + "XML": true, + "XMPP": true, + "XSRF": true, + "XSS": true, +} + +// specialInitialisms is a set of special initialisms that need part to stay in upper case. +var specialInitialisms = map[string]string{ + "IPV": "IPv", + //"IPV4": "IPv4", + //"IPV6": "IPv6", +} + +// camelCaseName returns correct name identifier (camelCase). +func camelCaseName(name string) (should string) { + name = strings.Title(name) + + // Fast path for simple cases: "_" and all lowercase. + if name == "_" { + return name + } + allLower := true + for _, r := range name { + if !unicode.IsLower(r) { + allLower = false + break + } + } + if allLower { + return name + } + + // Split camelCase at any lower->upper transition, and split on underscores. + // Check each word for common initialisms. + runes := []rune(name) + w, i := 0, 0 // index of start of word, scan + for i+1 <= len(runes) { + eow := false // whether we hit the end of a word + if i+1 == len(runes) { + eow = true + } else if runes[i+1] == '_' { + // underscore; shift the remainder forward over any run of underscores + eow = true + n := 1 + for i+n+1 < len(runes) && runes[i+n+1] == '_' { + n++ + } + + // Leave at most one underscore if the underscore is between two digits + if i+n+1 < len(runes) && unicode.IsDigit(runes[i]) && unicode.IsDigit(runes[i+n+1]) { + n-- + } + + copy(runes[i+1:], runes[i+n+1:]) + runes = runes[:len(runes)-n] + } else if unicode.IsLower(runes[i]) && !unicode.IsLower(runes[i+1]) { + // lower->non-lower + eow = true + } + i++ + if !eow { + continue + } + + // [w,i) is a word. + word := string(runes[w:i]) + if u := usesInitialism(word); u != "" { + // Keep consistent case, which is lowercase only at the start. + if w == 0 && unicode.IsLower(runes[w]) { + u = strings.ToLower(u) + } + // All the common initialisms are ASCII, + // so we can replace the bytes exactly. + copy(runes[w:], []rune(u)) + } else if w > 0 && strings.ToLower(word) == word { + // already all lowercase, and not the first word, so uppercase the first character. + runes[w] = unicode.ToUpper(runes[w]) + } + w = i + } + return string(runes) +} diff --git a/vendor/git.fd.io/govpp.git/cmd/binapi-generator/generate.go b/vendor/git.fd.io/govpp.git/cmd/binapi-generator/generate.go new file mode 100644 index 0000000000..251d39decd --- /dev/null +++ b/vendor/git.fd.io/govpp.git/cmd/binapi-generator/generate.go @@ -0,0 +1,565 @@ +// Copyright (c) 2017 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "bufio" + "bytes" + "fmt" + "io" + "path/filepath" + "strings" + "unicode" +) + +const ( + govppApiImportPath = "git.fd.io/govpp.git/api" // import path of the govpp API package + inputFileExt = ".api.json" // file extension of the VPP binary API files + outputFileExt = ".ba.go" // file extension of the Go generated files +) + +// context is a structure storing data for code generation +type context struct { + inputFile string // input file with VPP API in JSON + outputFile string // output file with generated Go package + + inputData []byte // contents of the input file + inputBuff *bytes.Buffer // contents of the input file currently being read + inputLine int // currently processed line in the input file + + moduleName string // name of the source VPP module + packageName string // name of the Go package being generated + + packageData *Package // parsed package data +} + +// getContext returns context details of the code generation task +func getContext(inputFile, outputDir string) (*context, error) { + if !strings.HasSuffix(inputFile, inputFileExt) { + return nil, fmt.Errorf("invalid input file name: %q", inputFile) + } + + ctx := &context{ + inputFile: inputFile, + } + + // package name + inputFileName := filepath.Base(inputFile) + ctx.moduleName = inputFileName[:strings.Index(inputFileName, ".")] + + // alter package names for modules that are reserved keywords in Go + switch ctx.moduleName { + case "interface": + ctx.packageName = "interfaces" + case "map": + ctx.packageName = "maps" + default: + ctx.packageName = ctx.moduleName + } + + // output file + packageDir := filepath.Join(outputDir, ctx.packageName) + outputFileName := ctx.packageName + outputFileExt + ctx.outputFile = filepath.Join(packageDir, outputFileName) + + return ctx, nil +} + +// generatePackage generates code for the parsed package data and writes it into w +func generatePackage(ctx *context, w *bufio.Writer) error { + logf("generating package %q", ctx.packageName) + + // generate file header + generateHeader(ctx, w) + generateImports(ctx, w) + + if *includeAPIVer { + const APIVerConstName = "VlAPIVersion" + fmt.Fprintf(w, "// %s represents version of the API.\n", APIVerConstName) + fmt.Fprintf(w, "const %s = %v\n", APIVerConstName, ctx.packageData.APIVersion) + fmt.Fprintln(w) + } + + // generate enums + if len(ctx.packageData.Enums) > 0 { + fmt.Fprintf(w, "/* Enums */\n\n") + + ctx.inputBuff = bytes.NewBuffer(ctx.inputData) + ctx.inputLine = 0 + for _, enum := range ctx.packageData.Enums { + generateEnum(ctx, w, &enum) + } + } + + // generate types + if len(ctx.packageData.Types) > 0 { + fmt.Fprintf(w, "/* Types */\n\n") + + ctx.inputBuff = bytes.NewBuffer(ctx.inputData) + ctx.inputLine = 0 + for _, typ := range ctx.packageData.Types { + generateType(ctx, w, &typ) + } + } + + // generate unions + if len(ctx.packageData.Unions) > 0 { + fmt.Fprintf(w, "/* Unions */\n\n") + + ctx.inputBuff = bytes.NewBuffer(ctx.inputData) + ctx.inputLine = 0 + for _, union := range ctx.packageData.Unions { + generateUnion(ctx, w, &union) + } + } + + // generate messages + if len(ctx.packageData.Messages) > 0 { + fmt.Fprintf(w, "/* Messages */\n\n") + + ctx.inputBuff = bytes.NewBuffer(ctx.inputData) + ctx.inputLine = 0 + for _, msg := range ctx.packageData.Messages { + generateMessage(ctx, w, &msg) + } + } + + // generate services + if len(ctx.packageData.Services) > 0 { + fmt.Fprintf(w, "/* Services */\n\n") + + fmt.Fprintf(w, "type %s interface {\n", "Services") + ctx.inputBuff = bytes.NewBuffer(ctx.inputData) + ctx.inputLine = 0 + for _, svc := range ctx.packageData.Services { + generateService(ctx, w, &svc) + } + fmt.Fprintln(w, "}") + } + + // TODO: generate implementation for Services interface + + // generate message registrations + fmt.Fprintln(w) + fmt.Fprintln(w, "func init() {") + for _, msg := range ctx.packageData.Messages { + name := camelCaseName(msg.Name) + fmt.Fprintf(w, "\tapi.RegisterMessage((*%s)(nil), \"%s\")\n", name, ctx.moduleName+"."+name) + } + fmt.Fprintln(w, "}") + + // flush the data: + if err := w.Flush(); err != nil { + return fmt.Errorf("flushing data to %s failed: %v", ctx.outputFile, err) + } + + return nil +} + +// generateHeader writes generated package header into w +func generateHeader(ctx *context, w io.Writer) { + fmt.Fprintln(w, "// Code generated by GoVPP binapi-generator. DO NOT EDIT.") + fmt.Fprintf(w, "// source: %s\n", ctx.inputFile) + fmt.Fprintln(w) + + fmt.Fprintln(w, "/*") + fmt.Fprintf(w, "Package %s is a generated VPP binary API of the '%s' VPP module.\n", ctx.packageName, ctx.moduleName) + fmt.Fprintln(w) + fmt.Fprintln(w, "It is generated from this file:") + fmt.Fprintf(w, "\t%s\n", filepath.Base(ctx.inputFile)) + fmt.Fprintln(w) + fmt.Fprintln(w, "It contains these VPP binary API objects:") + var printObjNum = func(obj string, num int) { + if num > 0 { + if num > 1 { + obj += "s" + } + fmt.Fprintf(w, "\t%d %s\n", num, obj) + } + } + printObjNum("message", len(ctx.packageData.Messages)) + printObjNum("type", len(ctx.packageData.Types)) + printObjNum("enum", len(ctx.packageData.Enums)) + printObjNum("union", len(ctx.packageData.Unions)) + printObjNum("service", len(ctx.packageData.Services)) + fmt.Fprintln(w, "*/") + fmt.Fprintf(w, "package %s\n", ctx.packageName) + fmt.Fprintln(w) +} + +// generateImports writes generated package imports into w +func generateImports(ctx *context, w io.Writer) { + fmt.Fprintf(w, "import \"%s\"\n", govppApiImportPath) + fmt.Fprintf(w, "import \"%s\"\n", "github.com/lunixbochs/struc") + fmt.Fprintf(w, "import \"%s\"\n", "bytes") + fmt.Fprintln(w) + + fmt.Fprintf(w, "// Reference imports to suppress errors if they are not otherwise used.\n") + fmt.Fprintf(w, "var _ = struc.Pack\n") + fmt.Fprintf(w, "var _ = bytes.NewBuffer\n") + fmt.Fprintln(w) +} + +// generateComment writes generated comment for the object into w +func generateComment(ctx *context, w io.Writer, goName string, vppName string, objKind string) { + fmt.Fprintf(w, "// %s represents the VPP binary API %s '%s'.\n", goName, objKind, vppName) + + var isNotSpace = func(r rune) bool { + return !unicode.IsSpace(r) + } + + // print out the source of the generated object + objFound := false + objTitle := fmt.Sprintf(`"%s",`, vppName) + var indent int + for { + line, err := ctx.inputBuff.ReadString('\n') + if err != nil { + break + } + ctx.inputLine++ + + if !objFound { + indent = strings.Index(line, objTitle) + if indent == -1 { + continue + } + // If no other non-whitespace character then we are at the message header. + if trimmed := strings.TrimSpace(line); trimmed == objTitle { + objFound = true + fmt.Fprintf(w, "// Generated from '%s', line %d:\n", filepath.Base(ctx.inputFile), ctx.inputLine) + fmt.Fprintln(w, "//") + } + } else { + if strings.IndexFunc(line, isNotSpace) < indent { + break // end of the object definition in JSON + } + } + fmt.Fprint(w, "//", line) + } + + fmt.Fprintln(w, "//") +} + +// generateEnum writes generated code for the enum into w +func generateEnum(ctx *context, w io.Writer, enum *Enum) { + name := camelCaseName(enum.Name) + typ := binapiTypes[enum.Type] + + logf(" writing enum %q (%s) with %d entries", enum.Name, name, len(enum.Entries)) + + // generate enum comment + generateComment(ctx, w, name, enum.Name, "enum") + + // generate enum definition + fmt.Fprintf(w, "type %s %s\n", name, typ) + fmt.Fprintln(w) + + fmt.Fprintln(w, "const (") + + // generate enum entries + for _, entry := range enum.Entries { + fmt.Fprintf(w, "\t%s %s = %v\n", entry.Name, name, entry.Value) + } + + fmt.Fprintln(w, ")") + + fmt.Fprintln(w) +} + +// generateType writes generated code for the type into w +func generateType(ctx *context, w io.Writer, typ *Type) { + name := camelCaseName(typ.Name) + + logf(" writing type %q (%s) with %d fields", typ.Name, name, len(typ.Fields)) + + // generate struct comment + generateComment(ctx, w, name, typ.Name, "type") + + // generate struct definition + fmt.Fprintf(w, "type %s struct {\n", name) + + // generate struct fields + for i, field := range typ.Fields { + // skip internal fields + switch strings.ToLower(field.Name) { + case "crc", "_vl_msg_id": + continue + } + + generateField(ctx, w, typ.Fields, i) + } + + // generate end of the struct + fmt.Fprintln(w, "}") + + // generate name getter + generateTypeNameGetter(w, name, typ.Name) + + // generate CRC getter + generateCrcGetter(w, name, typ.CRC) + + fmt.Fprintln(w) +} + +// generateUnion writes generated code for the union into w +func generateUnion(ctx *context, w io.Writer, union *Union) { + name := camelCaseName(union.Name) + + logf(" writing union %q (%s) with %d fields", union.Name, name, len(union.Fields)) + + // generate struct comment + generateComment(ctx, w, name, union.Name, "union") + + // generate struct definition + fmt.Fprintln(w, "type", name, "struct {") + + // maximum size for union + maxSize := getUnionSize(ctx, union) + + // generate data field + fieldName := "Union_data" + fmt.Fprintf(w, "\t%s [%d]byte\n", fieldName, maxSize) + + // generate end of the struct + fmt.Fprintln(w, "}") + + // generate name getter + generateTypeNameGetter(w, name, union.Name) + + // generate CRC getter + generateCrcGetter(w, name, union.CRC) + + // generate getters for fields + for _, field := range union.Fields { + fieldName := camelCaseName(field.Name) + fieldType := convertToGoType(ctx, field.Type) + generateUnionGetterSetter(w, name, fieldName, fieldType) + } + + // generate union methods + //generateUnionMethods(w, name) + + fmt.Fprintln(w) +} + +// generateUnionMethods generates methods that implement struc.Custom +// interface to allow having Union_data field unexported +// TODO: do more testing when unions are actually used in some messages +func generateUnionMethods(w io.Writer, structName string) { + // generate struc.Custom implementation for union + fmt.Fprintf(w, ` +func (u *%[1]s) Pack(p []byte, opt *struc.Options) (int, error) { + var b = new(bytes.Buffer) + if err := struc.PackWithOptions(b, u.union_data, opt); err != nil { + return 0, err + } + copy(p, b.Bytes()) + return b.Len(), nil +} +func (u *%[1]s) Unpack(r io.Reader, length int, opt *struc.Options) error { + return struc.UnpackWithOptions(r, u.union_data[:], opt) +} +func (u *%[1]s) Size(opt *struc.Options) int { + return len(u.union_data) +} +func (u *%[1]s) String() string { + return string(u.union_data[:]) +} +`, structName) +} + +func generateUnionGetterSetter(w io.Writer, structName string, getterField, getterStruct string) { + fmt.Fprintf(w, ` +func (u *%[1]s) Set%[2]s(a %[3]s) { + var b = new(bytes.Buffer) + if err := struc.Pack(b, &a); err != nil { + return + } + copy(u.Union_data[:], b.Bytes()) +} +func (u *%[1]s) Get%[2]s() (a %[3]s) { + var b = bytes.NewReader(u.Union_data[:]) + struc.Unpack(b, &a) + return +} +`, structName, getterField, getterStruct) +} + +// generateMessage writes generated code for the message into w +func generateMessage(ctx *context, w io.Writer, msg *Message) { + name := camelCaseName(msg.Name) + + logf(" writing message %q (%s) with %d fields", msg.Name, name, len(msg.Fields)) + + // generate struct comment + generateComment(ctx, w, name, msg.Name, "message") + + // generate struct definition + fmt.Fprintf(w, "type %s struct {", name) + + msgType := otherMessage + wasClientIndex := false + + // generate struct fields + n := 0 + for i, field := range msg.Fields { + if i == 1 { + if field.Name == "client_index" { + // "client_index" as the second member, this might be an event message or a request + msgType = eventMessage + wasClientIndex = true + } else if field.Name == "context" { + // reply needs "context" as the second member + msgType = replyMessage + } + } else if i == 2 { + if wasClientIndex && field.Name == "context" { + // request needs "client_index" as the second member and "context" as the third member + msgType = requestMessage + } + } + + // skip internal fields + switch strings.ToLower(field.Name) { + case "crc", "_vl_msg_id": + continue + case "client_index", "context": + if n == 0 { + continue + } + } + n++ + if n == 1 { + fmt.Fprintln(w) + } + + generateField(ctx, w, msg.Fields, i) + } + + // generate end of the struct + fmt.Fprintln(w, "}") + + // generate name getter + generateMessageNameGetter(w, name, msg.Name) + + // generate CRC getter + generateCrcGetter(w, name, msg.CRC) + + // generate message type getter method + generateMessageTypeGetter(w, name, msgType) + + // generate message factory + generateMessageFactory(w, name) +} + +// generateField writes generated code for the field into w +func generateField(ctx *context, w io.Writer, fields []Field, i int) { + field := fields[i] + + fieldName := strings.TrimPrefix(field.Name, "_") + fieldName = camelCaseName(fieldName) + + dataType := convertToGoType(ctx, field.Type) + + fieldType := dataType + if field.IsArray() { + if dataType == "uint8" { + dataType = "byte" + } + fieldType = "[]" + dataType + } + fmt.Fprintf(w, "\t%s %s", fieldName, fieldType) + + if field.Length > 0 { + // fixed size array + fmt.Fprintf(w, "\t`struc:\"[%d]%s\"`", field.Length, dataType) + } else { + for _, f := range fields { + if f.SizeFrom == field.Name { + // variable sized array + sizeOfName := camelCaseName(f.Name) + fmt.Fprintf(w, "\t`struc:\"sizeof=%s\"`", sizeOfName) + } + } + } + + fmt.Fprintln(w) +} + +// generateService writes generated code for the service into w +func generateService(ctx *context, w io.Writer, svc *Service) { + reqTyp := camelCaseName(svc.RequestType) + + // method name is same as parameter type name by default + method := reqTyp + if svc.Stream { + // use Dump as prefix instead of suffix for stream services + if m := strings.TrimSuffix(method, "Dump"); method != m { + method = "Dump" + m + } + } + params := fmt.Sprintf("*%s", reqTyp) + returns := "error" + if replyTyp := camelCaseName(svc.ReplyType); replyTyp != "" { + returns = fmt.Sprintf("(*%s, error)", replyTyp) + } + + fmt.Fprintf(w, "\t%s(%s) %s\n", method, params, returns) +} + +// generateMessageNameGetter generates getter for original VPP message name into the provider writer +func generateMessageNameGetter(w io.Writer, structName string, msgName string) { + fmt.Fprintln(w, "func (*"+structName+") GetMessageName() string {") + fmt.Fprintln(w, "\treturn \""+msgName+"\"") + fmt.Fprintln(w, "}") +} + +// generateTypeNameGetter generates getter for original VPP type name into the provider writer +func generateTypeNameGetter(w io.Writer, structName string, msgName string) { + fmt.Fprintln(w, "func (*"+structName+") GetTypeName() string {") + fmt.Fprintln(w, "\treturn \""+msgName+"\"") + fmt.Fprintln(w, "}") +} + +// generateCrcGetter generates getter for CRC checksum of the message definition into the provider writer +func generateCrcGetter(w io.Writer, structName string, crc string) { + crc = strings.TrimPrefix(crc, "0x") + fmt.Fprintln(w, "func (*"+structName+") GetCrcString() string {") + fmt.Fprintln(w, "\treturn \""+crc+"\"") + fmt.Fprintln(w, "}") +} + +// generateMessageTypeGetter generates message factory for the generated message into the provider writer +func generateMessageTypeGetter(w io.Writer, structName string, msgType MessageType) { + fmt.Fprintln(w, "func (*"+structName+") GetMessageType() api.MessageType {") + if msgType == requestMessage { + fmt.Fprintln(w, "\treturn api.RequestMessage") + } else if msgType == replyMessage { + fmt.Fprintln(w, "\treturn api.ReplyMessage") + } else if msgType == eventMessage { + fmt.Fprintln(w, "\treturn api.EventMessage") + } else { + fmt.Fprintln(w, "\treturn api.OtherMessage") + } + fmt.Fprintln(w, "}") +} + +// generateMessageFactory generates message factory for the generated message into the provider writer +func generateMessageFactory(w io.Writer, structName string) { + fmt.Fprintln(w, "func New"+structName+"() api.Message {") + fmt.Fprintln(w, "\treturn &"+structName+"{}") + fmt.Fprintln(w, "}") +} diff --git a/vendor/git.fd.io/govpp.git/cmd/binapi-generator/generator.go b/vendor/git.fd.io/govpp.git/cmd/binapi-generator/generator.go deleted file mode 100644 index 15f6164413..0000000000 --- a/vendor/git.fd.io/govpp.git/cmd/binapi-generator/generator.go +++ /dev/null @@ -1,660 +0,0 @@ -// Copyright (c) 2017 Cisco and/or its affiliates. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at: -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "bufio" - "bytes" - "encoding/json" - "errors" - "flag" - "fmt" - "io" - "io/ioutil" - "os" - "os/exec" - "path/filepath" - "strings" - "unicode" - - "github.com/bennyscetbun/jsongo" -) - -var ( - inputFile = flag.String("input-file", "", "Input JSON file.") - inputDir = flag.String("input-dir", ".", "Input directory with JSON files.") - outputDir = flag.String("output-dir", ".", "Output directory where package folders will be generated.") - includeAPIVer = flag.Bool("include-apiver", false, "Wether to include VlAPIVersion in generated file.") -) - -// MessageType represents the type of a VPP message. -type messageType int - -const ( - requestMessage messageType = iota // VPP request message - replyMessage // VPP reply message - eventMessage // VPP event message - otherMessage // other VPP message -) - -const ( - apiImportPath = "git.fd.io/govpp.git/api" // import path of the govpp API - inputFileExt = ".json" // filename extension of files that should be processed as the input -) - -// context is a structure storing details of a particular code generation task -type context struct { - inputFile string // file with input JSON data - inputData []byte // contents of the input file - inputBuff *bytes.Buffer // contents of the input file currently being read - inputLine int // currently processed line in the input file - outputFile string // file with output data - packageName string // name of the Go package being generated - packageDir string // directory where the package source files are located - types map[string]string // map of the VPP typedef names to generated Go typedef names -} - -func main() { - flag.Parse() - - if *inputFile == "" && *inputDir == "" { - fmt.Fprintln(os.Stderr, "ERROR: input-file or input-dir must be specified") - os.Exit(1) - } - - var err, tmpErr error - if *inputFile != "" { - // process one input file - err = generateFromFile(*inputFile, *outputDir) - if err != nil { - fmt.Fprintf(os.Stderr, "ERROR: code generation from %s failed: %v\n", *inputFile, err) - } - } else { - // process all files in specified directory - files, err := getInputFiles(*inputDir) - if err != nil { - fmt.Fprintf(os.Stderr, "ERROR: code generation failed: %v\n", err) - } - for _, file := range files { - tmpErr = generateFromFile(file, *outputDir) - if tmpErr != nil { - fmt.Fprintf(os.Stderr, "ERROR: code generation from %s failed: %v\n", file, err) - err = tmpErr // remember that the error occurred - } - } - } - if err != nil { - os.Exit(1) - } -} - -// getInputFiles returns all input files located in specified directory -func getInputFiles(inputDir string) ([]string, error) { - files, err := ioutil.ReadDir(inputDir) - if err != nil { - return nil, fmt.Errorf("reading directory %s failed: %v", inputDir, err) - } - res := make([]string, 0) - for _, f := range files { - if strings.HasSuffix(f.Name(), inputFileExt) { - res = append(res, inputDir+"/"+f.Name()) - } - } - return res, nil -} - -// generateFromFile generates Go bindings from one input JSON file -func generateFromFile(inputFile, outputDir string) error { - ctx, err := getContext(inputFile, outputDir) - if err != nil { - return err - } - // read the file - ctx.inputData, err = readFile(inputFile) - if err != nil { - return err - } - - // parse JSON - jsonRoot, err := parseJSON(ctx.inputData) - if err != nil { - return err - } - - // create output directory - err = os.MkdirAll(ctx.packageDir, 0777) - if err != nil { - return fmt.Errorf("creating output directory %s failed: %v", ctx.packageDir, err) - } - - // open output file - f, err := os.Create(ctx.outputFile) - defer f.Close() - if err != nil { - return fmt.Errorf("creating output file %s failed: %v", ctx.outputFile, err) - } - w := bufio.NewWriter(f) - - // generate Go package code - err = generatePackage(ctx, w, jsonRoot) - if err != nil { - return err - } - - // go format the output file (non-fatal if fails) - exec.Command("gofmt", "-w", ctx.outputFile).Run() - - return nil -} - -// getContext returns context details of the code generation task -func getContext(inputFile, outputDir string) (*context, error) { - if !strings.HasSuffix(inputFile, inputFileExt) { - return nil, fmt.Errorf("invalid input file name %s", inputFile) - } - - ctx := &context{inputFile: inputFile} - inputFileName := filepath.Base(inputFile) - - ctx.packageName = inputFileName[0:strings.Index(inputFileName, ".")] - if ctx.packageName == "interface" { - // 'interface' cannot be a package name, it is a go keyword - ctx.packageName = "interfaces" - } - - ctx.packageDir = outputDir + "/" + ctx.packageName + "/" - ctx.outputFile = ctx.packageDir + ctx.packageName + ".go" - - return ctx, nil -} - -// readFile reads content of a file into memory -func readFile(inputFile string) ([]byte, error) { - - inputData, err := ioutil.ReadFile(inputFile) - - if err != nil { - return nil, fmt.Errorf("reading data from file failed: %v", err) - } - - return inputData, nil -} - -// parseJSON parses a JSON data into an in-memory tree -func parseJSON(inputData []byte) (*jsongo.JSONNode, error) { - root := jsongo.JSONNode{} - - err := json.Unmarshal(inputData, &root) - if err != nil { - return nil, fmt.Errorf("JSON unmarshall failed: %v", err) - } - - return &root, nil - -} - -// generatePackage generates Go code of a package from provided JSON -func generatePackage(ctx *context, w *bufio.Writer, jsonRoot *jsongo.JSONNode) error { - // generate file header - generatePackageHeader(ctx, w, jsonRoot) - - // generate data types - ctx.inputBuff = bytes.NewBuffer(ctx.inputData) - ctx.inputLine = 0 - ctx.types = make(map[string]string) - types := jsonRoot.Map("types") - for i := 0; i < types.Len(); i++ { - typ := types.At(i) - err := generateMessage(ctx, w, typ, true) - if err != nil { - return err - } - } - - // generate messages - ctx.inputBuff = bytes.NewBuffer(ctx.inputData) - ctx.inputLine = 0 - messages := jsonRoot.Map("messages") - for i := 0; i < messages.Len(); i++ { - msg := messages.At(i) - err := generateMessage(ctx, w, msg, false) - if err != nil { - return err - } - } - - // flush the data: - err := w.Flush() - if err != nil { - return fmt.Errorf("flushing data to %s failed: %v", ctx.outputFile, err) - } - - return nil -} - -// generateMessage generates Go code of one VPP message encoded in JSON into provided writer -func generateMessage(ctx *context, w io.Writer, msg *jsongo.JSONNode, isType bool) error { - if msg.Len() == 0 || msg.At(0).GetType() != jsongo.TypeValue { - return errors.New("invalid JSON for message specified") - } - - msgName, ok := msg.At(0).Get().(string) - if !ok { - return fmt.Errorf("invalid JSON for message specified, message name is %T, not a string", msg.At(0).Get()) - } - structName := camelCaseName(strings.Title(msgName)) - - // generate struct fields into the slice & determine message type - fields := make([]string, 0) - msgType := otherMessage - wasClientIndex := false - for j := 0; j < msg.Len(); j++ { - if jsongo.TypeArray == msg.At(j).GetType() { - fld := msg.At(j) - if !isType { - // determine whether ths is a request / reply / other message - fieldName, ok := fld.At(1).Get().(string) - if ok { - if j == 2 { - if fieldName == "client_index" { - // "client_index" as the second member, this might be an event message or a request - msgType = eventMessage - wasClientIndex = true - } else if fieldName == "context" { - // reply needs "context" as the second member - msgType = replyMessage - } - } else if j == 3 { - if wasClientIndex && fieldName == "context" { - // request needs "client_index" as the second member and "context" as the third member - msgType = requestMessage - } - } - } - } - err := processMessageField(ctx, &fields, fld, isType) - if err != nil { - return err - } - } - } - - // generate struct comment - generateMessageComment(ctx, w, structName, msgName, isType) - - // generate struct header - fmt.Fprintln(w, "type", structName, "struct {") - - // print out the fields - for _, field := range fields { - fmt.Fprintln(w, field) - } - - // generate end of the struct - fmt.Fprintln(w, "}") - - // generate name getter - if isType { - generateTypeNameGetter(w, structName, msgName) - } else { - generateMessageNameGetter(w, structName, msgName) - } - - // generate message type getter method - if !isType { - generateMessageTypeGetter(w, structName, msgType) - } - - // generate CRC getter - crcIf := msg.At(msg.Len() - 1).At("crc").Get() - if crc, ok := crcIf.(string); ok { - generateCrcGetter(w, structName, crc) - } - - // generate message factory - if !isType { - generateMessageFactory(w, structName) - } - - // if this is a type, save it in the map for later use - if isType { - ctx.types[fmt.Sprintf("vl_api_%s_t", msgName)] = structName - } - - return nil -} - -// processMessageField process JSON describing one message field into Go code emitted into provided slice of message fields -func processMessageField(ctx *context, fields *[]string, fld *jsongo.JSONNode, isType bool) error { - if fld.Len() < 2 || fld.At(0).GetType() != jsongo.TypeValue || fld.At(1).GetType() != jsongo.TypeValue { - return errors.New("invalid JSON for message field specified") - } - fieldVppType, ok := fld.At(0).Get().(string) - if !ok { - return fmt.Errorf("invalid JSON for message specified, field type is %T, not a string", fld.At(0).Get()) - } - fieldName, ok := fld.At(1).Get().(string) - if !ok { - return fmt.Errorf("invalid JSON for message specified, field name is %T, not a string", fld.At(1).Get()) - } - - // skip internal fields - fieldNameLower := strings.ToLower(fieldName) - if fieldNameLower == "crc" || fieldNameLower == "_vl_msg_id" { - return nil - } - if !isType && len(*fields) == 0 && (fieldNameLower == "client_index" || fieldNameLower == "context") { - return nil - } - - fieldName = strings.TrimPrefix(fieldName, "_") - fieldName = camelCaseName(strings.Title(fieldName)) - - fieldStr := "" - isArray := false - arraySize := 0 - - fieldStr += "\t" + fieldName + " " - if fld.Len() > 2 { - isArray = true - arraySize = int(fld.At(2).Get().(float64)) - fieldStr += "[]" - } - - dataType := translateVppType(ctx, fieldVppType, isArray) - fieldStr += dataType - - if isArray { - if arraySize == 0 { - // variable sized array - if fld.Len() > 3 { - // array size is specified by another field - arraySizeField := string(fld.At(3).Get().(string)) - arraySizeField = camelCaseName(strings.Title(arraySizeField)) - // find & update the field that specifies the array size - for i, f := range *fields { - if strings.Contains(f, fmt.Sprintf("\t%s ", arraySizeField)) { - (*fields)[i] += fmt.Sprintf("\t`struc:\"sizeof=%s\"`", fieldName) - } - } - } - } else { - // fixed size array - fieldStr += fmt.Sprintf("\t`struc:\"[%d]%s\"`", arraySize, dataType) - } - } - - *fields = append(*fields, fieldStr) - return nil -} - -// generatePackageHeader generates package header into provider writer -func generatePackageHeader(ctx *context, w io.Writer, rootNode *jsongo.JSONNode) { - fmt.Fprintln(w, "// Code generated by govpp binapi-generator DO NOT EDIT.") - fmt.Fprintln(w, "// Package "+ctx.packageName+" represents the VPP binary API of the '"+ctx.packageName+"' VPP module.") - fmt.Fprintln(w, "// Generated from '"+ctx.inputFile+"'") - - fmt.Fprintln(w, "package "+ctx.packageName) - - fmt.Fprintln(w, "import \""+apiImportPath+"\"") - fmt.Fprintln(w) - - vlAPIVersion := rootNode.Map("vl_api_version").Get() - if *includeAPIVer { - fmt.Fprintln(w, "// VlApiVersion contains version of the API.") - fmt.Fprintln(w, "const VlAPIVersion = ", vlAPIVersion) - fmt.Fprintln(w) - } -} - -// generateMessageComment generates comment for a message into provider writer -func generateMessageComment(ctx *context, w io.Writer, structName string, msgName string, isType bool) { - fmt.Fprintln(w) - if isType { - fmt.Fprintln(w, "// "+structName+" represents the VPP binary API data type '"+msgName+"'.") - } else { - fmt.Fprintln(w, "// "+structName+" represents the VPP binary API message '"+msgName+"'.") - } - - // print out the source of the generated message - the JSON - msgFound := false - msgTitle := "\"" + msgName + "\"," - var msgIndent int - for { - lineBuff, err := ctx.inputBuff.ReadBytes('\n') - if err != nil { - break - } - ctx.inputLine++ - line := string(lineBuff) - - if !msgFound { - msgIndent = strings.Index(line, msgTitle) - if msgIndent > -1 { - prefix := line[:msgIndent] - suffix := line[msgIndent+len(msgTitle):] - // If no other non-whitespace character then we are at the message header. - if strings.IndexFunc(prefix, isNotSpace) == -1 && strings.IndexFunc(suffix, isNotSpace) == -1 { - fmt.Fprintf(w, "// Generated from '%s', line %d:\n", ctx.inputFile, ctx.inputLine) - fmt.Fprintln(w, "//") - fmt.Fprint(w, "//", line) - msgFound = true - } - } - } else { - if strings.IndexFunc(line, isNotSpace) < msgIndent { - break // end of the message in JSON - } - fmt.Fprint(w, "//", line) - } - } - fmt.Fprintln(w, "//") -} - -// generateMessageNameGetter generates getter for original VPP message name into the provider writer -func generateMessageNameGetter(w io.Writer, structName string, msgName string) { - fmt.Fprintln(w, "func (*"+structName+") GetMessageName() string {") - fmt.Fprintln(w, "\treturn \""+msgName+"\"") - fmt.Fprintln(w, "}") -} - -// generateTypeNameGetter generates getter for original VPP type name into the provider writer -func generateTypeNameGetter(w io.Writer, structName string, msgName string) { - fmt.Fprintln(w, "func (*"+structName+") GetTypeName() string {") - fmt.Fprintln(w, "\treturn \""+msgName+"\"") - fmt.Fprintln(w, "}") -} - -// generateMessageTypeGetter generates message factory for the generated message into the provider writer -func generateMessageTypeGetter(w io.Writer, structName string, msgType messageType) { - fmt.Fprintln(w, "func (*"+structName+") GetMessageType() api.MessageType {") - if msgType == requestMessage { - fmt.Fprintln(w, "\treturn api.RequestMessage") - } else if msgType == replyMessage { - fmt.Fprintln(w, "\treturn api.ReplyMessage") - } else if msgType == eventMessage { - fmt.Fprintln(w, "\treturn api.EventMessage") - } else { - fmt.Fprintln(w, "\treturn api.OtherMessage") - } - fmt.Fprintln(w, "}") -} - -// generateCrcGetter generates getter for CRC checksum of the message definition into the provider writer -func generateCrcGetter(w io.Writer, structName string, crc string) { - crc = strings.TrimPrefix(crc, "0x") - fmt.Fprintln(w, "func (*"+structName+") GetCrcString() string {") - fmt.Fprintln(w, "\treturn \""+crc+"\"") - fmt.Fprintln(w, "}") -} - -// generateMessageFactory generates message factory for the generated message into the provider writer -func generateMessageFactory(w io.Writer, structName string) { - fmt.Fprintln(w, "func New"+structName+"() api.Message {") - fmt.Fprintln(w, "\treturn &"+structName+"{}") - fmt.Fprintln(w, "}") -} - -// translateVppType translates the VPP data type into Go data type -func translateVppType(ctx *context, vppType string, isArray bool) string { - // basic types - switch vppType { - case "u8": - if isArray { - return "byte" - } - return "uint8" - case "i8": - return "int8" - case "u16": - return "uint16" - case "i16": - return "int16" - case "u32": - return "uint32" - case "i32": - return "int32" - case "u64": - return "uint64" - case "i64": - return "int64" - case "f64": - return "float64" - } - - // typedefs - typ, ok := ctx.types[vppType] - if ok { - return typ - } - - panic(fmt.Sprintf("Unknown VPP type %s", vppType)) -} - -// camelCaseName returns correct name identifier (camelCase). -func camelCaseName(name string) (should string) { - // Fast path for simple cases: "_" and all lowercase. - if name == "_" { - return name - } - allLower := true - for _, r := range name { - if !unicode.IsLower(r) { - allLower = false - break - } - } - if allLower { - return name - } - - // Split camelCase at any lower->upper transition, and split on underscores. - // Check each word for common initialisms. - runes := []rune(name) - w, i := 0, 0 // index of start of word, scan - for i+1 <= len(runes) { - eow := false // whether we hit the end of a word - if i+1 == len(runes) { - eow = true - } else if runes[i+1] == '_' { - // underscore; shift the remainder forward over any run of underscores - eow = true - n := 1 - for i+n+1 < len(runes) && runes[i+n+1] == '_' { - n++ - } - - // Leave at most one underscore if the underscore is between two digits - if i+n+1 < len(runes) && unicode.IsDigit(runes[i]) && unicode.IsDigit(runes[i+n+1]) { - n-- - } - - copy(runes[i+1:], runes[i+n+1:]) - runes = runes[:len(runes)-n] - } else if unicode.IsLower(runes[i]) && !unicode.IsLower(runes[i+1]) { - // lower->non-lower - eow = true - } - i++ - if !eow { - continue - } - - // [w,i) is a word. - word := string(runes[w:i]) - if u := strings.ToUpper(word); commonInitialisms[u] { - // Keep consistent case, which is lowercase only at the start. - if w == 0 && unicode.IsLower(runes[w]) { - u = strings.ToLower(u) - } - // All the common initialisms are ASCII, - // so we can replace the bytes exactly. - copy(runes[w:], []rune(u)) - } else if w > 0 && strings.ToLower(word) == word { - // already all lowercase, and not the first word, so uppercase the first character. - runes[w] = unicode.ToUpper(runes[w]) - } - w = i - } - return string(runes) -} - -// isNotSpace returns true if the rune is NOT a whitespace character. -func isNotSpace(r rune) bool { - return !unicode.IsSpace(r) -} - -// commonInitialisms is a set of common initialisms that need to stay in upper case. -var commonInitialisms = map[string]bool{ - "ACL": true, - "API": true, - "ASCII": true, - "CPU": true, - "CSS": true, - "DNS": true, - "EOF": true, - "GUID": true, - "HTML": true, - "HTTP": true, - "HTTPS": true, - "ID": true, - "IP": true, - "ICMP": true, - "JSON": true, - "LHS": true, - "QPS": true, - "RAM": true, - "RHS": true, - "RPC": true, - "SLA": true, - "SMTP": true, - "SQL": true, - "SSH": true, - "TCP": true, - "TLS": true, - "TTL": true, - "UDP": true, - "UI": true, - "UID": true, - "UUID": true, - "URI": true, - "URL": true, - "UTF8": true, - "VM": true, - "XML": true, - "XMPP": true, - "XSRF": true, - "XSS": true, -} diff --git a/vendor/git.fd.io/govpp.git/cmd/binapi-generator/main.go b/vendor/git.fd.io/govpp.git/cmd/binapi-generator/main.go new file mode 100644 index 0000000000..804521287f --- /dev/null +++ b/vendor/git.fd.io/govpp.git/cmd/binapi-generator/main.go @@ -0,0 +1,173 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "bufio" + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "os/exec" + "path/filepath" + "strings" + + "github.com/bennyscetbun/jsongo" +) + +var ( + inputFile = flag.String("input-file", "", "Input JSON file.") + inputDir = flag.String("input-dir", ".", "Input directory with JSON files.") + outputDir = flag.String("output-dir", ".", "Output directory where package folders will be generated.") + includeAPIVer = flag.Bool("include-apiver", false, "Whether to include VlAPIVersion in generated file.") + debug = flag.Bool("debug", false, "Turn on debug mode.") + continueOnError = flag.Bool("continue-onerror", false, "Wheter to continue with next file on error.") +) + +func logf(f string, v ...interface{}) { + if *debug { + log.Printf(f, v...) + } +} + +func main() { + flag.Parse() + + if *inputFile == "" && *inputDir == "" { + fmt.Fprintln(os.Stderr, "ERROR: input-file or input-dir must be specified") + os.Exit(1) + } + + if *inputFile != "" { + // process one input file + if err := generateFromFile(*inputFile, *outputDir); err != nil { + fmt.Fprintf(os.Stderr, "ERROR: code generation from %s failed: %v\n", *inputFile, err) + os.Exit(1) + } + } else { + // process all files in specified directory + files, err := getInputFiles(*inputDir) + if err != nil { + fmt.Fprintf(os.Stderr, "ERROR: code generation failed: %v\n", err) + os.Exit(1) + } + for _, file := range files { + if err := generateFromFile(file, *outputDir); err != nil { + fmt.Fprintf(os.Stderr, "ERROR: code generation from %s failed: %v\n", file, err) + if *continueOnError { + continue + } + os.Exit(1) + } + } + } +} + +// getInputFiles returns all input files located in specified directory +func getInputFiles(inputDir string) (res []string, err error) { + files, err := ioutil.ReadDir(inputDir) + if err != nil { + return nil, fmt.Errorf("reading directory %s failed: %v", inputDir, err) + } + for _, f := range files { + if strings.HasSuffix(f.Name(), inputFileExt) { + res = append(res, filepath.Join(inputDir, f.Name())) + } + } + return res, nil +} + +// generateFromFile generates Go package from one input JSON file +func generateFromFile(inputFile, outputDir string) error { + logf("generating from file: %q", inputFile) + defer logf("--------------------------------------") + + ctx, err := getContext(inputFile, outputDir) + if err != nil { + return err + } + + // read input file contents + ctx.inputData, err = readFile(inputFile) + if err != nil { + return err + } + // parse JSON data into objects + jsonRoot, err := parseJSON(ctx.inputData) + if err != nil { + return err + } + ctx.packageData, err = parsePackage(ctx, jsonRoot) + if err != nil { + return err + } + + // create output directory + packageDir := filepath.Dir(ctx.outputFile) + if err := os.MkdirAll(packageDir, 0777); err != nil { + return fmt.Errorf("creating output directory %q failed: %v", packageDir, err) + } + // open output file + f, err := os.Create(ctx.outputFile) + if err != nil { + return fmt.Errorf("creating output file %q failed: %v", ctx.outputFile, err) + } + defer f.Close() + + // generate Go package code + w := bufio.NewWriter(f) + if err := generatePackage(ctx, w); err != nil { + return err + } + + // go format the output file (fail probably means the output is not compilable) + cmd := exec.Command("gofmt", "-w", ctx.outputFile) + if output, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("gofmt failed: %v\n%s", err, string(output)) + } + + // count number of lines in generated output file + cmd = exec.Command("wc", "-l", ctx.outputFile) + if output, err := cmd.CombinedOutput(); err != nil { + log.Printf("wc command failed: %v\n%s", err, string(output)) + } else { + logf("generated lines: %s", output) + } + + return nil +} + +// readFile reads content of a file into memory +func readFile(inputFile string) ([]byte, error) { + inputData, err := ioutil.ReadFile(inputFile) + if err != nil { + return nil, fmt.Errorf("reading data from file failed: %v", err) + } + + return inputData, nil +} + +// parseJSON parses a JSON data into an in-memory tree +func parseJSON(inputData []byte) (*jsongo.JSONNode, error) { + root := jsongo.JSONNode{} + + if err := json.Unmarshal(inputData, &root); err != nil { + return nil, fmt.Errorf("unmarshalling JSON failed: %v", err) + } + + return &root, nil +} diff --git a/vendor/git.fd.io/govpp.git/cmd/binapi-generator/parse.go b/vendor/git.fd.io/govpp.git/cmd/binapi-generator/parse.go new file mode 100644 index 0000000000..7f7880b5e2 --- /dev/null +++ b/vendor/git.fd.io/govpp.git/cmd/binapi-generator/parse.go @@ -0,0 +1,547 @@ +// Copyright (c) 2018 Cisco and/or its affiliates. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "errors" + "fmt" + "log" + "sort" + "strings" + + "github.com/bennyscetbun/jsongo" +) + +// Package represents collection of objects parsed from VPP binary API JSON data +type Package struct { + APIVersion string + Enums []Enum + Unions []Union + Types []Type + Messages []Message + Services []Service + RefMap map[string]string +} + +// MessageType represents the type of a VPP message +type MessageType int + +const ( + requestMessage MessageType = iota // VPP request message + replyMessage // VPP reply message + eventMessage // VPP event message + otherMessage // other VPP message +) + +// Message represents VPP binary API message +type Message struct { + Name string + CRC string + Fields []Field +} + +// Type represents VPP binary API type +type Type struct { + Name string + CRC string + Fields []Field +} + +// Union represents VPP binary API union +type Union struct { + Name string + CRC string + Fields []Field +} + +// Field represents VPP binary API object field +type Field struct { + Name string + Type string + Length int + SizeFrom string +} + +func (f *Field) IsArray() bool { + return f.Length > 0 || f.SizeFrom != "" +} + +// Enum represents VPP binary API enum +type Enum struct { + Name string + Type string + Entries []EnumEntry +} + +// EnumEntry represents VPP binary API enum entry +type EnumEntry struct { + Name string + Value interface{} +} + +// Service represents VPP binary API service +type Service struct { + RequestType string + ReplyType string + Stream bool + Events []string +} + +func getSizeOfType(typ *Type) (size int) { + for _, field := range typ.Fields { + if n := getBinapiTypeSize(field.Type); n > 0 { + if field.Length > 0 { + size += n * field.Length + } else { + size += n + } + } + } + return size +} + +func getTypeByRef(ctx *context, ref string) *Type { + for _, typ := range ctx.packageData.Types { + if ref == toApiType(typ.Name) { + return &typ + } + } + return nil +} + +func getUnionSize(ctx *context, union *Union) (maxSize int) { + for _, field := range union.Fields { + if typ := getTypeByRef(ctx, field.Type); typ != nil { + if size := getSizeOfType(typ); size > maxSize { + maxSize = size + } + } + } + return +} + +// toApiType returns name that is used as type reference in VPP binary API +func toApiType(name string) string { + return fmt.Sprintf("vl_api_%s_t", name) +} + +// parsePackage parses provided JSON data into objects prepared for code generation +func parsePackage(ctx *context, jsonRoot *jsongo.JSONNode) (*Package, error) { + logf(" %s contains: %d services, %d messages, %d types, %d enums, %d unions (version: %s)", + ctx.packageName, + jsonRoot.Map("services").Len(), + jsonRoot.Map("messages").Len(), + jsonRoot.Map("types").Len(), + jsonRoot.Map("enums").Len(), + jsonRoot.Map("unions").Len(), + jsonRoot.Map("vl_api_version").Get(), + ) + + pkg := Package{ + APIVersion: jsonRoot.Map("vl_api_version").Get().(string), + RefMap: make(map[string]string), + } + + // parse enums + enums := jsonRoot.Map("enums") + pkg.Enums = make([]Enum, enums.Len()) + for i := 0; i < enums.Len(); i++ { + enumNode := enums.At(i) + + enum, err := parseEnum(ctx, enumNode) + if err != nil { + return nil, err + } + pkg.Enums[i] = *enum + pkg.RefMap[toApiType(enum.Name)] = enum.Name + } + + // parse types + types := jsonRoot.Map("types") + pkg.Types = make([]Type, types.Len()) + for i := 0; i < types.Len(); i++ { + typNode := types.At(i) + + typ, err := parseType(ctx, typNode) + if err != nil { + return nil, err + } + pkg.Types[i] = *typ + pkg.RefMap[toApiType(typ.Name)] = typ.Name + } + + // parse unions + unions := jsonRoot.Map("unions") + pkg.Unions = make([]Union, unions.Len()) + for i := 0; i < unions.Len(); i++ { + unionNode := unions.At(i) + + union, err := parseUnion(ctx, unionNode) + if err != nil { + return nil, err + } + pkg.Unions[i] = *union + pkg.RefMap[toApiType(union.Name)] = union.Name + } + + // parse messages + messages := jsonRoot.Map("messages") + pkg.Messages = make([]Message, messages.Len()) + for i := 0; i < messages.Len(); i++ { + msgNode := messages.At(i) + + msg, err := parseMessage(ctx, msgNode) + if err != nil { + return nil, err + } + pkg.Messages[i] = *msg + } + + // parse services + services := jsonRoot.Map("services") + if services.GetType() == jsongo.TypeMap { + pkg.Services = make([]Service, services.Len()) + for i, key := range services.GetKeys() { + svcNode := services.At(key) + + svc, err := parseService(ctx, key.(string), svcNode) + if err != nil { + return nil, err + } + pkg.Services[i] = *svc + } + + // sort services + sort.Slice(pkg.Services, func(i, j int) bool { + // dumps first + if pkg.Services[i].Stream != pkg.Services[j].Stream { + return pkg.Services[i].Stream + } + return pkg.Services[i].RequestType < pkg.Services[j].RequestType + }) + } + + printPackage(&pkg) + + return &pkg, nil +} + +// printPackage prints all loaded objects for package +func printPackage(pkg *Package) { + if len(pkg.Enums) > 0 { + logf("loaded %d enums:", len(pkg.Enums)) + for k, enum := range pkg.Enums { + logf(" - enum #%d\t%+v", k, enum) + } + } + if len(pkg.Unions) > 0 { + logf("loaded %d unions:", len(pkg.Unions)) + for k, union := range pkg.Unions { + logf(" - union #%d\t%+v", k, union) + } + } + if len(pkg.Types) > 0 { + logf("loaded %d types:", len(pkg.Types)) + for _, typ := range pkg.Types { + logf(" - type: %q (%d fields)", typ.Name, len(typ.Fields)) + } + } + if len(pkg.Messages) > 0 { + logf("loaded %d messages:", len(pkg.Messages)) + for _, msg := range pkg.Messages { + logf(" - message: %q (%d fields)", msg.Name, len(msg.Fields)) + } + } + if len(pkg.Services) > 0 { + logf("loaded %d services:", len(pkg.Services)) + for _, svc := range pkg.Services { + var info string + if svc.Stream { + info = "(STREAM)" + } else if len(svc.Events) > 0 { + info = fmt.Sprintf("(EVENTS: %v)", svc.Events) + } + logf(" - service: %q -> %q %s", svc.RequestType, svc.ReplyType, info) + } + } +} + +// parseEnum parses VPP binary API enum object from JSON node +func parseEnum(ctx *context, enumNode *jsongo.JSONNode) (*Enum, error) { + if enumNode.Len() == 0 || enumNode.At(0).GetType() != jsongo.TypeValue { + return nil, errors.New("invalid JSON for enum specified") + } + + enumName, ok := enumNode.At(0).Get().(string) + if !ok { + return nil, fmt.Errorf("enum name is %T, not a string", enumNode.At(0).Get()) + } + enumType, ok := enumNode.At(enumNode.Len() - 1).At("enumtype").Get().(string) + if !ok { + return nil, fmt.Errorf("enum type invalid or missing") + } + + enum := Enum{ + Name: enumName, + Type: enumType, + } + + // loop through enum entries, skip first (name) and last (enumtype) + for j := 1; j < enumNode.Len()-1; j++ { + if enumNode.At(j).GetType() == jsongo.TypeArray { + entry := enumNode.At(j) + + if entry.Len() < 2 || entry.At(0).GetType() != jsongo.TypeValue || entry.At(1).GetType() != jsongo.TypeValue { + return nil, errors.New("invalid JSON for enum entry specified") + } + + entryName, ok := entry.At(0).Get().(string) + if !ok { + return nil, fmt.Errorf("enum entry name is %T, not a string", entry.At(0).Get()) + } + entryVal := entry.At(1).Get() + + enum.Entries = append(enum.Entries, EnumEntry{ + Name: entryName, + Value: entryVal, + }) + } + } + + return &enum, nil +} + +// parseUnion parses VPP binary API union object from JSON node +func parseUnion(ctx *context, unionNode *jsongo.JSONNode) (*Union, error) { + if unionNode.Len() == 0 || unionNode.At(0).GetType() != jsongo.TypeValue { + return nil, errors.New("invalid JSON for union specified") + } + + unionName, ok := unionNode.At(0).Get().(string) + if !ok { + return nil, fmt.Errorf("union name is %T, not a string", unionNode.At(0).Get()) + } + unionCRC, ok := unionNode.At(unionNode.Len() - 1).At("crc").Get().(string) + if !ok { + return nil, fmt.Errorf("union crc invalid or missing") + } + + union := Union{ + Name: unionName, + CRC: unionCRC, + } + + // loop through union fields, skip first (name) and last (crc) + for j := 1; j < unionNode.Len()-1; j++ { + if unionNode.At(j).GetType() == jsongo.TypeArray { + fieldNode := unionNode.At(j) + + field, err := parseField(ctx, fieldNode) + if err != nil { + return nil, err + } + + union.Fields = append(union.Fields, *field) + } + } + + return &union, nil +} + +// parseType parses VPP binary API type object from JSON node +func parseType(ctx *context, typeNode *jsongo.JSONNode) (*Type, error) { + if typeNode.Len() == 0 || typeNode.At(0).GetType() != jsongo.TypeValue { + return nil, errors.New("invalid JSON for type specified") + } + + typeName, ok := typeNode.At(0).Get().(string) + if !ok { + return nil, fmt.Errorf("type name is %T, not a string", typeNode.At(0).Get()) + } + typeCRC, ok := typeNode.At(typeNode.Len() - 1).At("crc").Get().(string) + if !ok { + return nil, fmt.Errorf("type crc invalid or missing") + } + + typ := Type{ + Name: typeName, + CRC: typeCRC, + } + + // loop through type fields, skip first (name) and last (crc) + for j := 1; j < typeNode.Len()-1; j++ { + if typeNode.At(j).GetType() == jsongo.TypeArray { + fieldNode := typeNode.At(j) + + field, err := parseField(ctx, fieldNode) + if err != nil { + return nil, err + } + + typ.Fields = append(typ.Fields, *field) + } + } + + return &typ, nil +} + +// parseMessage parses VPP binary API message object from JSON node +func parseMessage(ctx *context, msgNode *jsongo.JSONNode) (*Message, error) { + if msgNode.Len() == 0 || msgNode.At(0).GetType() != jsongo.TypeValue { + return nil, errors.New("invalid JSON for message specified") + } + + msgName, ok := msgNode.At(0).Get().(string) + if !ok { + return nil, fmt.Errorf("message name is %T, not a string", msgNode.At(0).Get()) + } + msgCRC, ok := msgNode.At(msgNode.Len() - 1).At("crc").Get().(string) + if !ok { + return nil, fmt.Errorf("message crc invalid or missing") + } + + msg := Message{ + Name: msgName, + CRC: msgCRC, + } + + // loop through message fields, skip first (name) and last (crc) + for j := 1; j < msgNode.Len()-1; j++ { + if msgNode.At(j).GetType() == jsongo.TypeArray { + fieldNode := msgNode.At(j) + + field, err := parseField(ctx, fieldNode) + if err != nil { + return nil, err + } + + msg.Fields = append(msg.Fields, *field) + } + } + + return &msg, nil +} + +// parseField parses VPP binary API object field from JSON node +func parseField(ctx *context, field *jsongo.JSONNode) (*Field, error) { + if field.Len() < 2 || field.At(0).GetType() != jsongo.TypeValue || field.At(1).GetType() != jsongo.TypeValue { + return nil, errors.New("invalid JSON for field specified") + } + + fieldType, ok := field.At(0).Get().(string) + if !ok { + return nil, fmt.Errorf("field type is %T, not a string", field.At(0).Get()) + } + fieldName, ok := field.At(1).Get().(string) + if !ok { + return nil, fmt.Errorf("field name is %T, not a string", field.At(1).Get()) + } + var fieldLength float64 + if field.Len() >= 3 { + fieldLength, ok = field.At(2).Get().(float64) + if !ok { + return nil, fmt.Errorf("field length is %T, not an int", field.At(2).Get()) + } + } + var fieldLengthFrom string + if field.Len() >= 4 { + fieldLengthFrom, ok = field.At(3).Get().(string) + if !ok { + return nil, fmt.Errorf("field length from is %T, not a string", field.At(3).Get()) + } + } + + return &Field{ + Name: fieldName, + Type: fieldType, + Length: int(fieldLength), + SizeFrom: fieldLengthFrom, + }, nil +} + +// parseService parses VPP binary API service object from JSON node +func parseService(ctx *context, svcName string, svcNode *jsongo.JSONNode) (*Service, error) { + if svcNode.Len() == 0 || svcNode.At("reply").GetType() != jsongo.TypeValue { + return nil, errors.New("invalid JSON for service specified") + } + + svc := Service{ + RequestType: svcName, + } + + if replyNode := svcNode.At("reply"); replyNode.GetType() == jsongo.TypeValue { + reply, ok := replyNode.Get().(string) + if !ok { + return nil, fmt.Errorf("service reply is %T, not a string", replyNode.Get()) + } + // some binapi messages might have `null` reply (for example: memclnt) + if reply != "null" { + svc.ReplyType = reply + } + } + + // stream service (dumps) + if streamNode := svcNode.At("stream"); streamNode.GetType() == jsongo.TypeValue { + var ok bool + svc.Stream, ok = streamNode.Get().(bool) + if !ok { + return nil, fmt.Errorf("service stream is %T, not a string", streamNode.Get()) + } + } + + // events service (event subscription) + if eventsNode := svcNode.At("events"); eventsNode.GetType() == jsongo.TypeArray { + for j := 0; j < eventsNode.Len(); j++ { + event := eventsNode.At(j).Get().(string) + svc.Events = append(svc.Events, event) + } + } + + // validate service + if svc.Stream { + if !strings.HasSuffix(svc.RequestType, "_dump") || + !strings.HasSuffix(svc.ReplyType, "_details") { + fmt.Printf("Invalid STREAM SERVICE: %+v\n", svc) + } + } else if len(svc.Events) > 0 { + if (!strings.HasSuffix(svc.RequestType, "_events") && + !strings.HasSuffix(svc.RequestType, "_stats")) || + !strings.HasSuffix(svc.ReplyType, "_reply") { + fmt.Printf("Invalid EVENTS SERVICE: %+v\n", svc) + } + } else if svc.ReplyType != "" { + if !strings.HasSuffix(svc.ReplyType, "_reply") { + fmt.Printf("Invalid SERVICE: %+v\n", svc) + } + } + + return &svc, nil +} + +// convertToGoType translates the VPP binary API type into Go type +func convertToGoType(ctx *context, binapiType string) (typ string) { + if t, ok := binapiTypes[binapiType]; ok { + // basic types + typ = t + } else if r, ok := ctx.packageData.RefMap[binapiType]; ok { + // specific types (enums/types/unions) + typ = camelCaseName(r) + } else { + // fallback type + log.Printf("found unknown VPP binary API type %q, using byte", binapiType) + typ = "byte" + } + return typ +} diff --git a/vendor/git.fd.io/govpp.git/codec/msg_codec.go b/vendor/git.fd.io/govpp.git/codec/msg_codec.go index 7ba87711b2..572e672c63 100644 --- a/vendor/git.fd.io/govpp.git/codec/msg_codec.go +++ b/vendor/git.fd.io/govpp.git/codec/msg_codec.go @@ -43,8 +43,8 @@ type VppReplyHeader struct { // VppEventHeader struct contains header fields implemented by all VPP events. type VppEventHeader struct { - VlMsgID uint16 - Context uint32 + VlMsgID uint16 + ClientIndex uint32 } // VppOtherHeader struct contains header fields implemented by other VPP messages (not requests nor replies). @@ -52,42 +52,36 @@ type VppOtherHeader struct { VlMsgID uint16 } -const ( - vppRequestHeaderSize = 10 // size of a VPP request header - vppReplyHeaderSize = 6 // size of a VPP reply header - vppEventHeaderSize = 6 // size of a VPP event header - vppOtherHeaderSize = 2 // size of the header of other VPP messages -) - // EncodeMsg encodes provided `Message` structure into its binary-encoded data representation. func (*MsgCodec) EncodeMsg(msg api.Message, msgID uint16) ([]byte, error) { if msg == nil { return nil, errors.New("nil message passed in") } - buf := new(bytes.Buffer) - // encode message header var header interface{} - if msg.GetMessageType() == api.RequestMessage { + switch msg.GetMessageType() { + case api.RequestMessage: header = &VppRequestHeader{VlMsgID: msgID} - } else if msg.GetMessageType() == api.ReplyMessage { + case api.ReplyMessage: header = &VppReplyHeader{VlMsgID: msgID} - } else if msg.GetMessageType() == api.EventMessage { + case api.EventMessage: header = &VppEventHeader{VlMsgID: msgID} - } else { + default: header = &VppOtherHeader{VlMsgID: msgID} } - err := struc.Pack(buf, header) - if err != nil { - return nil, fmt.Errorf("unable to encode message: header: %v, error %v", header, err) + + buf := new(bytes.Buffer) + + // encode message header + if err := struc.Pack(buf, header); err != nil { + return nil, fmt.Errorf("unable to encode message header: %v, error %v", header, err) } // encode message content - if reflect.Indirect(reflect.ValueOf(msg)).NumField() > 0 { - err := struc.Pack(buf, msg) - if err != nil { - return nil, fmt.Errorf("unable to encode message: header %v, error %v", header, err) + if reflect.TypeOf(msg).Elem().NumField() > 0 { + if err := struc.Pack(buf, msg); err != nil { + return nil, fmt.Errorf("unable to encode message data: %v, error %v", header, err) } } @@ -100,42 +94,60 @@ func (*MsgCodec) DecodeMsg(data []byte, msg api.Message) error { return errors.New("nil message passed in") } - buf := bytes.NewReader(data) - // check which header is expected var header interface{} - if msg.GetMessageType() == api.RequestMessage { - header = &VppRequestHeader{} - } else if msg.GetMessageType() == api.ReplyMessage { - header = &VppReplyHeader{} - } else if msg.GetMessageType() == api.EventMessage { - header = &VppEventHeader{} - } else { - header = &VppOtherHeader{} + switch msg.GetMessageType() { + case api.RequestMessage: + header = new(VppRequestHeader) + case api.ReplyMessage: + header = new(VppReplyHeader) + case api.EventMessage: + header = new(VppEventHeader) + default: + header = new(VppOtherHeader) } - // decode message header - err := struc.Unpack(buf, header) - if err != nil { - return fmt.Errorf("unable to decode message: data %v, error %v", data, err) - } + buf := bytes.NewReader(data) - // get rid of the message header - if msg.GetMessageType() == api.RequestMessage { - buf = bytes.NewReader(data[vppRequestHeaderSize:]) - } else if msg.GetMessageType() == api.ReplyMessage { - buf = bytes.NewReader(data[vppReplyHeaderSize:]) - } else if msg.GetMessageType() == api.EventMessage { - buf = bytes.NewReader(data[vppEventHeaderSize:]) - } else { - buf = bytes.NewReader(data[vppOtherHeaderSize:]) + // decode message header + if err := struc.Unpack(buf, header); err != nil { + return fmt.Errorf("unable to decode message header: %+v, error %v", data, err) } // decode message content - err = struc.Unpack(buf, msg) - if err != nil { - return fmt.Errorf("unable to decode message: data %v, error %v", data, err) + if err := struc.Unpack(buf, msg); err != nil { + return fmt.Errorf("unable to decode message data: %+v, error %v", data, err) } return nil } + +func (*MsgCodec) DecodeMsgContext(data []byte, msg api.Message) (uint32, error) { + if msg == nil { + return 0, errors.New("nil message passed in") + } + + var getContext func() uint32 + + // check which header is expected + var header interface{} + switch msg.GetMessageType() { + case api.RequestMessage: + header = new(VppRequestHeader) + getContext = func() uint32 { return header.(*VppRequestHeader).Context } + case api.ReplyMessage: + header = new(VppReplyHeader) + getContext = func() uint32 { return header.(*VppReplyHeader).Context } + default: + return 0, nil + } + + buf := bytes.NewReader(data) + + // decode message header + if err := struc.Unpack(buf, header); err != nil { + return 0, fmt.Errorf("decoding message header failed: %v", err) + } + + return getContext(), nil +} diff --git a/vendor/git.fd.io/govpp.git/core/channel.go b/vendor/git.fd.io/govpp.git/core/channel.go index 87b3e29a1f..5f7763ec65 100644 --- a/vendor/git.fd.io/govpp.git/core/channel.go +++ b/vendor/git.fd.io/govpp.git/core/channel.go @@ -15,50 +15,78 @@ package core import ( + "errors" "fmt" + "reflect" + "strings" "time" - "errors" - "git.fd.io/govpp.git/api" "github.com/sirupsen/logrus" ) -const defaultReplyTimeout = time.Second * 1 // default timeout for replies from VPP, can be changed with SetReplyTimeout +var ( + ErrInvalidRequestCtx = errors.New("invalid request context") +) -// requestCtxData is a context of a ongoing request (simple one - only one response is expected). -type requestCtxData struct { +// requestCtx is a context for request with single reply +type requestCtx struct { ch *channel seqNum uint16 } -// multiRequestCtxData is a context of a ongoing multipart request (multiple responses are expected). -type multiRequestCtxData struct { +// multiRequestCtx is a context for request with multiple responses +type multiRequestCtx struct { ch *channel seqNum uint16 } -func (req *requestCtxData) ReceiveReply(msg api.Message) error { +func (req *requestCtx) ReceiveReply(msg api.Message) error { if req == nil || req.ch == nil { - return errors.New("invalid request context") + return ErrInvalidRequestCtx } lastReplyReceived, err := req.ch.receiveReplyInternal(msg, req.seqNum) - + if err != nil { + return err + } if lastReplyReceived { - err = errors.New("multipart reply recieved while a simple reply expected") + return errors.New("multipart reply recieved while a single reply expected") } - return err + + return nil } -func (req *multiRequestCtxData) ReceiveReply(msg api.Message) (lastReplyReceived bool, err error) { +func (req *multiRequestCtx) ReceiveReply(msg api.Message) (lastReplyReceived bool, err error) { if req == nil || req.ch == nil { - return false, errors.New("invalid request context") + return false, ErrInvalidRequestCtx } return req.ch.receiveReplyInternal(msg, req.seqNum) } +// vppRequest is a request that will be sent to VPP. +type vppRequest struct { + seqNum uint16 // sequence number + msg api.Message // binary API message to be send to VPP + multi bool // true if multipart response is expected +} + +// vppReply is a reply received from VPP. +type vppReply struct { + seqNum uint16 // sequence number + msgID uint16 // ID of the message + data []byte // encoded data with the message + lastReceived bool // for multi request, true if the last reply has been already received + err error // in case of error, data is nil and this member contains error +} + +// NotifSubscribeRequest is a request to subscribe for delivery of specific notification messages. +type subscriptionRequest struct { + sub *api.NotifSubscription // subscription details + subscribe bool // true if this is a request to subscribe +} + // channel is the main communication interface with govpp core. It contains four Go channels, one for sending the requests // to VPP, one for receiving the replies from it and the same set for notifications. The user can access the Go channels // via methods provided by Channel interface in this package. Do not use the same channel from multiple goroutines @@ -66,99 +94,75 @@ func (req *multiRequestCtxData) ReceiveReply(msg api.Message) (lastReplyReceived type channel struct { id uint16 // channel ID - reqChan chan *api.VppRequest // channel for sending the requests to VPP, closing this channel releases all resources in the ChannelProvider - replyChan chan *api.VppReply // channel where VPP replies are delivered to + reqChan chan *vppRequest // channel for sending the requests to VPP + replyChan chan *vppReply // channel where VPP replies are delivered to - notifSubsChan chan *api.NotifSubscribeRequest // channel for sending notification subscribe requests - notifSubsReplyChan chan error // channel where replies to notification subscribe requests are delivered to + notifSubsChan chan *subscriptionRequest // channel for sending notification subscribe requests + notifSubsReplyChan chan error // channel where replies to notification subscribe requests are delivered to msgDecoder api.MessageDecoder // used to decode binary data to generated API messages msgIdentifier api.MessageIdentifier // used to retrieve message ID of a message lastSeqNum uint16 // sequence number of the last sent request - delayedReply *api.VppReply // reply already taken from ReplyChan, buffered for later delivery + delayedReply *vppReply // reply already taken from ReplyChan, buffered for later delivery replyTimeout time.Duration // maximum time that the API waits for a reply from VPP before returning an error, can be set with SetReplyTimeout } -func (ch *channel) SendRequest(msg api.Message) api.RequestCtx { +func (ch *channel) GetID() uint16 { + return ch.id +} + +func (ch *channel) nextSeqNum() uint16 { ch.lastSeqNum++ - ch.reqChan <- &api.VppRequest{ - Message: msg, - SeqNum: ch.lastSeqNum, + return ch.lastSeqNum +} + +func (ch *channel) SendRequest(msg api.Message) api.RequestCtx { + req := &vppRequest{ + msg: msg, + seqNum: ch.nextSeqNum(), } - return &requestCtxData{ch: ch, seqNum: ch.lastSeqNum} + ch.reqChan <- req + return &requestCtx{ch: ch, seqNum: req.seqNum} } func (ch *channel) SendMultiRequest(msg api.Message) api.MultiRequestCtx { - ch.lastSeqNum++ - ch.reqChan <- &api.VppRequest{ - Message: msg, - Multipart: true, - SeqNum: ch.lastSeqNum, + req := &vppRequest{ + msg: msg, + seqNum: ch.nextSeqNum(), + multi: true, } - return &multiRequestCtxData{ch: ch, seqNum: ch.lastSeqNum} + ch.reqChan <- req + return &multiRequestCtx{ch: ch, seqNum: req.seqNum} } func (ch *channel) SubscribeNotification(notifChan chan api.Message, msgFactory func() api.Message) (*api.NotifSubscription, error) { - subscription := &api.NotifSubscription{ + sub := &api.NotifSubscription{ NotifChan: notifChan, MsgFactory: msgFactory, } - ch.notifSubsChan <- &api.NotifSubscribeRequest{ - Subscription: subscription, - Subscribe: true, + // TODO: get rid of notifSubsChan and notfSubsReplyChan, + // it's no longer need because we know all message IDs and can store subscription right here + ch.notifSubsChan <- &subscriptionRequest{ + sub: sub, + subscribe: true, } - return subscription, <-ch.notifSubsReplyChan + return sub, <-ch.notifSubsReplyChan } func (ch *channel) UnsubscribeNotification(subscription *api.NotifSubscription) error { - ch.notifSubsChan <- &api.NotifSubscribeRequest{ - Subscription: subscription, - Subscribe: false, + ch.notifSubsChan <- &subscriptionRequest{ + sub: subscription, + subscribe: false, } return <-ch.notifSubsReplyChan } -func (ch *channel) CheckMessageCompatibility(messages ...api.Message) error { - for _, msg := range messages { - _, err := ch.msgIdentifier.GetMessageID(msg) - if err != nil { - return fmt.Errorf("message %s with CRC %s is not compatible with the VPP we are connected to", - msg.GetMessageName(), msg.GetCrcString()) - } - } - return nil -} - func (ch *channel) SetReplyTimeout(timeout time.Duration) { ch.replyTimeout = timeout } -func (ch *channel) GetRequestChannel() chan<- *api.VppRequest { - return ch.reqChan -} - -func (ch *channel) GetReplyChannel() <-chan *api.VppReply { - return ch.replyChan -} - -func (ch *channel) GetNotificationChannel() chan<- *api.NotifSubscribeRequest { - return ch.notifSubsChan -} - -func (ch *channel) GetNotificationReplyChannel() <-chan error { - return ch.notifSubsReplyChan -} - -func (ch *channel) GetMessageDecoder() api.MessageDecoder { - return ch.msgDecoder -} - -func (ch *channel) GetID() uint16 { - return ch.id -} - func (ch *channel) Close() { if ch.reqChan != nil { close(ch.reqChan) @@ -172,9 +176,8 @@ func (ch *channel) receiveReplyInternal(msg api.Message, expSeqNum uint16) (last return false, errors.New("nil message passed in") } - if ch.delayedReply != nil { + if vppReply := ch.delayedReply; vppReply != nil { // try the delayed reply - vppReply := ch.delayedReply ch.delayedReply = nil ignore, lastReplyReceived, err = ch.processReply(vppReply, expSeqNum, msg) if !ignore { @@ -201,12 +204,12 @@ func (ch *channel) receiveReplyInternal(msg api.Message, expSeqNum uint16) (last return } -func (ch *channel) processReply(reply *api.VppReply, expSeqNum uint16, msg api.Message) (ignore bool, lastReplyReceived bool, err error) { +func (ch *channel) processReply(reply *vppReply, expSeqNum uint16, msg api.Message) (ignore bool, lastReplyReceived bool, err error) { // check the sequence number - cmpSeqNums := compareSeqNumbers(reply.SeqNum, expSeqNum) + cmpSeqNums := compareSeqNumbers(reply.seqNum, expSeqNum) if cmpSeqNums == -1 { // reply received too late, ignore the message - logrus.WithField("sequence-number", reply.SeqNum).Warn( + logrus.WithField("sequence-number", reply.seqNum).Warn( "Received reply to an already closed binary API request") ignore = true return @@ -217,11 +220,11 @@ func (ch *channel) processReply(reply *api.VppReply, expSeqNum uint16, msg api.M return } - if reply.Error != nil { - err = reply.Error + if reply.err != nil { + err = reply.err return } - if reply.LastReplyReceived { + if reply.lastReceived { lastReplyReceived = true return } @@ -235,42 +238,34 @@ func (ch *channel) processReply(reply *api.VppReply, expSeqNum uint16, msg api.M return } - if reply.MessageID != expMsgID { + if reply.msgID != expMsgID { var msgNameCrc string - if nameCrc, err := ch.msgIdentifier.LookupByID(reply.MessageID); err != nil { + if replyMsg, err := ch.msgIdentifier.LookupByID(reply.msgID); err != nil { msgNameCrc = err.Error() } else { - msgNameCrc = nameCrc + msgNameCrc = getMsgNameWithCrc(replyMsg) } - err = fmt.Errorf("received invalid message ID (seq-num=%d), expected %d (%s), but got %d (%s) "+ + err = fmt.Errorf("received invalid message ID (seqNum=%d), expected %d (%s), but got %d (%s) "+ "(check if multiple goroutines are not sharing single GoVPP channel)", - reply.SeqNum, expMsgID, msg.GetMessageName(), reply.MessageID, msgNameCrc) + reply.seqNum, expMsgID, msg.GetMessageName(), reply.msgID, msgNameCrc) return } // decode the message - err = ch.msgDecoder.DecodeMsg(reply.Data, msg) - return -} - -// compareSeqNumbers returns -1, 0, 1 if sequence number precedes, equals to, -// or succeeds seq. number . -// Since sequence numbers cycle in the finite set of size 2^16, the function -// must assume that the distance between compared sequence numbers is less than -// (2^16)/2 to determine the order. -func compareSeqNumbers(seqNum1, seqNum2 uint16) int { - // calculate distance from seqNum1 to seqNum2 - var dist uint16 - if seqNum1 <= seqNum2 { - dist = seqNum2 - seqNum1 - } else { - dist = 0xffff - (seqNum1 - seqNum2 - 1) + if err = ch.msgDecoder.DecodeMsg(reply.data, msg); err != nil { + return } - if dist == 0 { - return 0 - } else if dist <= 0x8000 { - return -1 + + // check Retval and convert it into VnetAPIError error + if strings.HasSuffix(msg.GetMessageName(), "_reply") { + // TODO: use categories for messages to avoid checking message name + if f := reflect.Indirect(reflect.ValueOf(msg)).FieldByName("Retval"); f.IsValid() { + if retval := f.Int(); retval != 0 { + err = api.VPPApiError(retval) + } + } } - return 1 + + return } diff --git a/vendor/git.fd.io/govpp.git/core/connection.go b/vendor/git.fd.io/govpp.git/core/connection.go index a44d0c4d80..c77358f76c 100644 --- a/vendor/git.fd.io/govpp.git/core/connection.go +++ b/vendor/git.fd.io/govpp.git/core/connection.go @@ -12,13 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:generate binapi-generator --input-dir=bin_api --output-dir=bin_api - package core import ( "errors" - "os" + "fmt" + "reflect" "sync" "sync/atomic" "time" @@ -28,115 +27,95 @@ import ( "git.fd.io/govpp.git/adapter" "git.fd.io/govpp.git/api" "git.fd.io/govpp.git/codec" - "git.fd.io/govpp.git/core/bin_api/vpe" -) - -var ( - msgControlPing api.Message = &vpe.ControlPing{} - msgControlPingReply api.Message = &vpe.ControlPingReply{} ) const ( - requestChannelBufSize = 100 // default size of the request channel buffers - replyChannelBufSize = 100 // default size of the reply channel buffers - notificationChannelBufSize = 100 // default size of the notification channel buffers + requestChannelBufSize = 100 // default size of the request channel buffer + replyChannelBufSize = 100 // default size of the reply channel buffer + notificationChannelBufSize = 100 // default size of the notification channel buffer + + defaultReplyTimeout = time.Second * 1 // default timeout for replies from VPP, can be changed with SetReplyTimeout ) var ( - healthCheckProbeInterval = time.Second * 1 // default health check probe interval - healthCheckReplyTimeout = time.Millisecond * 100 // timeout for reply to a health check probe - healthCheckThreshold = 1 // number of failed healthProbe until the error is reported + healthCheckInterval = time.Second * 1 // default health check interval + healthCheckReplyTimeout = time.Millisecond * 100 // timeout for reply to a health check + healthCheckThreshold = 1 // number of failed health checks until the error is reported ) -// ConnectionState holds the current state of the connection to VPP. +// SetHealthCheckProbeInterval sets health check probe interval. +// Beware: Function is not thread-safe. It is recommended to setup this parameter +// before connecting to vpp. +func SetHealthCheckProbeInterval(interval time.Duration) { + healthCheckInterval = interval +} + +// SetHealthCheckReplyTimeout sets timeout for reply to a health check probe. +// If reply arrives after the timeout, check is considered as failed. +// Beware: Function is not thread-safe. It is recommended to setup this parameter +// before connecting to vpp. +func SetHealthCheckReplyTimeout(timeout time.Duration) { + healthCheckReplyTimeout = timeout +} + +// SetHealthCheckThreshold sets the number of failed healthProbe checks until the error is reported. +// Beware: Function is not thread-safe. It is recommended to setup this parameter +// before connecting to vpp. +func SetHealthCheckThreshold(threshold int) { + healthCheckThreshold = threshold +} + +// ConnectionState represents the current state of the connection to VPP. type ConnectionState int const ( - // Connected connection state means that the connection to VPP has been successfully established. + // Connected represents state in which the connection has been successfully established. Connected ConnectionState = iota - // Disconnected connection state means that the connection to VPP has been lost. + // Disconnected represents state in which the connection has been dropped. Disconnected ) // ConnectionEvent is a notification about change in the VPP connection state. type ConnectionEvent struct { - // Timestamp holds the time when the event has been generated. + // Timestamp holds the time when the event has been created. Timestamp time.Time - // State holds the new state of the connection to VPP at the time when the event has been generated. + // State holds the new state of the connection at the time when the event has been created. State ConnectionState + + // Error holds error if any encountered. + Error error } +var ( + connLock sync.RWMutex // lock for the global connection + conn *Connection // global handle to the Connection (used in the message receive callback) +) + // Connection represents a shared memory connection to VPP via vppAdapter. type Connection struct { vpp adapter.VppAdapter // VPP adapter connected uint32 // non-zero if the adapter is connected to VPP - codec *codec.MsgCodec // message codec - msgIDsLock sync.RWMutex // lock for the message IDs map - msgIDs map[string]uint16 // map of message IDs indexed by message name + CRC + codec *codec.MsgCodec // message codec + msgIDs map[string]uint16 // map of message IDs indexed by message name + CRC + msgMap map[uint16]api.Message // map of messages indexed by message ID + maxChannelID uint32 // maximum used channel ID (the real limit is 2^15, 32-bit is used for atomic operations) channelsLock sync.RWMutex // lock for the channels map channels map[uint16]*channel // map of all API channels indexed by the channel ID notifSubscriptionsLock sync.RWMutex // lock for the subscriptions map notifSubscriptions map[uint16][]*api.NotifSubscription // map od all notification subscriptions indexed by message ID - maxChannelID uint32 // maximum used channel ID (the real limit is 2^15, 32-bit is used for atomic operations) - pingReqID uint16 // ID if the ControlPing message - pingReplyID uint16 // ID of the ControlPingReply message + pingReqID uint16 // ID if the ControlPing message + pingReplyID uint16 // ID of the ControlPingReply message lastReplyLock sync.Mutex // lock for the last reply lastReply time.Time // time of the last received reply from VPP } -var ( - log *logger.Logger // global logger - conn *Connection // global handle to the Connection (used in the message receive callback) - connLock sync.RWMutex // lock for the global connection -) - -// init initializes global logger, which logs debug level messages to stdout. -func init() { - log = logger.New() - log.Out = os.Stdout - log.Level = logger.DebugLevel -} - -// SetLogger sets global logger to provided one. -func SetLogger(l *logger.Logger) { - log = l -} - -// SetHealthCheckProbeInterval sets health check probe interval. -// Beware: Function is not thread-safe. It is recommended to setup this parameter -// before connecting to vpp. -func SetHealthCheckProbeInterval(interval time.Duration) { - healthCheckProbeInterval = interval -} - -// SetHealthCheckReplyTimeout sets timeout for reply to a health check probe. -// If reply arrives after the timeout, check is considered as failed. -// Beware: Function is not thread-safe. It is recommended to setup this parameter -// before connecting to vpp. -func SetHealthCheckReplyTimeout(timeout time.Duration) { - healthCheckReplyTimeout = timeout -} - -// SetHealthCheckThreshold sets the number of failed healthProbe checks until the error is reported. -// Beware: Function is not thread-safe. It is recommended to setup this parameter -// before connecting to vpp. -func SetHealthCheckThreshold(threshold int) { - healthCheckThreshold = threshold -} - -// SetControlPingMessages sets the messages for ControlPing and ControlPingReply -func SetControlPingMessages(controPing, controlPingReply api.Message) { - msgControlPing = controPing - msgControlPingReply = controlPingReply -} - // Connect connects to VPP using specified VPP adapter and returns the connection handle. // This call blocks until VPP is connected, or an error occurs. Only one connection attempt will be performed. func Connect(vppAdapter adapter.VppAdapter) (*Connection, error) { @@ -152,7 +131,7 @@ func Connect(vppAdapter adapter.VppAdapter) (*Connection, error) { return nil, err } - return conn, nil + return c, nil } // AsyncConnect asynchronously connects to VPP using specified VPP adapter and returns the connection handle @@ -170,7 +149,7 @@ func AsyncConnect(vppAdapter adapter.VppAdapter) (*Connection, chan ConnectionEv connChan := make(chan ConnectionEvent, notificationChannelBufSize) go c.connectLoop(connChan) - return conn, connChan, nil + return c, connChan, nil } // Disconnect disconnects from VPP and releases all connection-related resources. @@ -178,10 +157,11 @@ func (c *Connection) Disconnect() { if c == nil { return } + connLock.Lock() defer connLock.Unlock() - if c != nil && c.vpp != nil { + if c.vpp != nil { c.disconnectVPP() } conn = nil @@ -201,41 +181,119 @@ func newConnection(vppAdapter adapter.VppAdapter) (*Connection, error) { codec: &codec.MsgCodec{}, channels: make(map[uint16]*channel), msgIDs: make(map[string]uint16), + msgMap: make(map[uint16]api.Message), notifSubscriptions: make(map[uint16][]*api.NotifSubscription), } + conn.vpp.SetMsgCallback(conn.msgCallback) - conn.vpp.SetMsgCallback(msgCallback) return conn, nil } -// connectVPP performs one blocking attempt to connect to VPP. +// connectVPP performs blocking attempt to connect to VPP. func (c *Connection) connectVPP() error { - log.Debug("Connecting to VPP...") + log.Debug("Connecting to VPP..") // blocking connect - err := c.vpp.Connect() - if err != nil { - log.Warn(err) + if err := c.vpp.Connect(); err != nil { return err } - // store control ping IDs - if c.pingReqID, err = c.GetMessageID(msgControlPing); err != nil { - c.vpp.Disconnect() - return err - } - if c.pingReplyID, err = c.GetMessageID(msgControlPingReply); err != nil { + log.Debugf("Connected to VPP.") + + if err := c.retrieveMessageIDs(); err != nil { c.vpp.Disconnect() - return err + return fmt.Errorf("VPP is incompatible: %v", err) } // store connected state atomic.StoreUint32(&c.connected, 1) - log.Info("Connected to VPP.") return nil } +func getMsgNameWithCrc(x api.Message) string { + return x.GetMessageName() + "_" + x.GetCrcString() +} + +// retrieveMessageIDs retrieves IDs for all registered messages and stores them in map +func (c *Connection) retrieveMessageIDs() (err error) { + t := time.Now() + + var addMsg = func(msgID uint16, msg api.Message) { + c.msgIDs[getMsgNameWithCrc(msg)] = msgID + c.msgMap[msgID] = msg + } + + msgs := api.GetAllMessages() + + for name, msg := range msgs { + msgID, err := c.vpp.GetMsgID(msg.GetMessageName(), msg.GetCrcString()) + if err != nil { + return err + } + + addMsg(msgID, msg) + + if msg.GetMessageName() == msgControlPing.GetMessageName() { + c.pingReqID = msgID + msgControlPing = reflect.New(reflect.TypeOf(msg).Elem()).Interface().(api.Message) + } else if msg.GetMessageName() == msgControlPingReply.GetMessageName() { + c.pingReplyID = msgID + msgControlPingReply = reflect.New(reflect.TypeOf(msg).Elem()).Interface().(api.Message) + } + + if debugMsgIDs { + log.Debugf("message %q (%s) has ID: %d", name, getMsgNameWithCrc(msg), msgID) + } + } + + log.Debugf("retrieving %d message IDs took %s", len(msgs), time.Since(t)) + + // fallback for control ping when vpe package is not imported + if c.pingReqID == 0 { + c.pingReqID, err = c.vpp.GetMsgID(msgControlPing.GetMessageName(), msgControlPing.GetCrcString()) + if err != nil { + return err + } + addMsg(c.pingReqID, msgControlPing) + } + if c.pingReplyID == 0 { + c.pingReplyID, err = c.vpp.GetMsgID(msgControlPingReply.GetMessageName(), msgControlPingReply.GetCrcString()) + if err != nil { + return err + } + addMsg(c.pingReplyID, msgControlPingReply) + } + + return nil +} + +// GetMessageID returns message identifier of given API message. +func (c *Connection) GetMessageID(msg api.Message) (uint16, error) { + if c == nil { + return 0, errors.New("nil connection passed in") + } + + if msgID, ok := c.msgIDs[getMsgNameWithCrc(msg)]; ok { + return msgID, nil + } + + return 0, fmt.Errorf("unknown message: %s (%s)", msg.GetMessageName(), msg.GetCrcString()) +} + +// LookupByID looks up message name and crc by ID. +func (c *Connection) LookupByID(msgID uint16) (api.Message, error) { + if c == nil { + return nil, errors.New("nil connection passed in") + } + + if msg, ok := c.msgMap[msgID]; ok { + return msg, nil + } + + return nil, fmt.Errorf("unknown message ID: %d", msgID) +} + // disconnectVPP disconnects from VPP in case it is connected. func (c *Connection) disconnectVPP() { if atomic.CompareAndSwapUint32(&c.connected, 1, 0) { @@ -269,19 +327,21 @@ func (c *Connection) connectLoop(connChan chan ConnectionEvent) { // it continues with connectLoop and tries to reconnect. func (c *Connection) healthCheckLoop(connChan chan ConnectionEvent) { // create a separate API channel for health check probes - ch, err := conn.newAPIChannelBuffered(1, 1) + ch, err := c.newAPIChannel(1, 1) if err != nil { log.Error("Failed to create health check API channel, health check will be disabled:", err) return } - var sinceLastReply time.Duration - var failedChecks int + var ( + sinceLastReply time.Duration + failedChecks int + ) // send health check probes until an error or timeout occurs for { // sleep until next health check probe period - time.Sleep(healthCheckProbeInterval) + time.Sleep(healthCheckInterval) if atomic.LoadUint32(&c.connected) == 0 { // Disconnect has been called in the meantime, return the healthcheck - reconnect loop @@ -297,22 +357,22 @@ func (c *Connection) healthCheckLoop(connChan chan ConnectionEvent) { } // send the control ping request - ch.reqChan <- &api.VppRequest{Message: msgControlPing} + ch.reqChan <- &vppRequest{msg: msgControlPing} for { // expect response within timeout period select { case vppReply := <-ch.replyChan: - err = vppReply.Error + err = vppReply.err case <-time.After(healthCheckReplyTimeout): err = ErrProbeTimeout // check if time since last reply from any other // channel is less than health check reply timeout - conn.lastReplyLock.Lock() + c.lastReplyLock.Lock() sinceLastReply = time.Since(c.lastReply) - conn.lastReplyLock.Unlock() + c.lastReplyLock.Unlock() if sinceLastReply < healthCheckReplyTimeout { log.Warnf("VPP health check probe timing out, but some request on other channel was received %v ago, continue waiting!", sinceLastReply) @@ -326,17 +386,18 @@ func (c *Connection) healthCheckLoop(connChan chan ConnectionEvent) { failedChecks++ log.Warnf("VPP health check probe timed out after %v (%d. timeout)", healthCheckReplyTimeout, failedChecks) if failedChecks > healthCheckThreshold { - // in case of exceeded treshold disconnect + // in case of exceeded failed check treshold, assume VPP disconnected log.Errorf("VPP health check exceeded treshold for timeouts (>%d), assuming disconnect", healthCheckThreshold) connChan <- ConnectionEvent{Timestamp: time.Now(), State: Disconnected} break } } else if err != nil { - // in case of error disconnect + // in case of error, assume VPP disconnected log.Errorf("VPP health check probe failed: %v", err) - connChan <- ConnectionEvent{Timestamp: time.Now(), State: Disconnected} + connChan <- ConnectionEvent{Timestamp: time.Now(), State: Disconnected, Error: err} break } else if failedChecks > 0 { + // in case of success after failed checks, clear failed check counter failedChecks = 0 log.Infof("VPP health check probe OK") } @@ -351,33 +412,31 @@ func (c *Connection) healthCheckLoop(connChan chan ConnectionEvent) { } func (c *Connection) NewAPIChannel() (api.Channel, error) { - return c.newAPIChannelBuffered(requestChannelBufSize, replyChannelBufSize) + return c.newAPIChannel(requestChannelBufSize, replyChannelBufSize) } func (c *Connection) NewAPIChannelBuffered(reqChanBufSize, replyChanBufSize int) (api.Channel, error) { - return c.newAPIChannelBuffered(reqChanBufSize, replyChanBufSize) + return c.newAPIChannel(reqChanBufSize, replyChanBufSize) } // NewAPIChannelBuffered returns a new API channel for communication with VPP via govpp core. // It allows to specify custom buffer sizes for the request and reply Go channels. -func (c *Connection) newAPIChannelBuffered(reqChanBufSize, replyChanBufSize int) (*channel, error) { +func (c *Connection) newAPIChannel(reqChanBufSize, replyChanBufSize int) (*channel, error) { if c == nil { return nil, errors.New("nil connection passed in") } chID := uint16(atomic.AddUint32(&c.maxChannelID, 1) & 0x7fff) ch := &channel{ - id: chID, - replyTimeout: defaultReplyTimeout, + id: chID, + replyTimeout: defaultReplyTimeout, + msgDecoder: c.codec, + msgIdentifier: c, + reqChan: make(chan *vppRequest, reqChanBufSize), + replyChan: make(chan *vppReply, replyChanBufSize), + notifSubsChan: make(chan *subscriptionRequest, reqChanBufSize), + notifSubsReplyChan: make(chan error, replyChanBufSize), } - ch.msgDecoder = c.codec - ch.msgIdentifier = c - - // create the communication channels - ch.reqChan = make(chan *api.VppRequest, reqChanBufSize) - ch.replyChan = make(chan *api.VppReply, replyChanBufSize) - ch.notifSubsChan = make(chan *api.NotifSubscribeRequest, reqChanBufSize) - ch.notifSubsReplyChan = make(chan error, replyChanBufSize) // store API channel within the client c.channelsLock.Lock() @@ -393,8 +452,8 @@ func (c *Connection) newAPIChannelBuffered(reqChanBufSize, replyChanBufSize int) // releaseAPIChannel releases API channel that needs to be closed. func (c *Connection) releaseAPIChannel(ch *channel) { log.WithFields(logger.Fields{ - "ID": ch.id, - }).Debug("API channel closed.") + "channel": ch.id, + }).Debug("API channel released") // delete the channel from channels map c.channelsLock.Lock() diff --git a/vendor/git.fd.io/govpp.git/core/control_ping.go b/vendor/git.fd.io/govpp.git/core/control_ping.go new file mode 100644 index 0000000000..904068a890 --- /dev/null +++ b/vendor/git.fd.io/govpp.git/core/control_ping.go @@ -0,0 +1,36 @@ +package core + +import "git.fd.io/govpp.git/api" + +var ( + msgControlPing api.Message = new(ControlPing) + msgControlPingReply api.Message = new(ControlPingReply) +) + +type ControlPing struct{} + +func (*ControlPing) GetMessageName() string { + return "control_ping" +} +func (*ControlPing) GetCrcString() string { + return "51077d14" +} +func (*ControlPing) GetMessageType() api.MessageType { + return api.RequestMessage +} + +type ControlPingReply struct { + Retval int32 + ClientIndex uint32 + VpePID uint32 +} + +func (*ControlPingReply) GetMessageName() string { + return "control_ping_reply" +} +func (*ControlPingReply) GetCrcString() string { + return "f6b0b8ca" +} +func (*ControlPingReply) GetMessageType() api.MessageType { + return api.ReplyMessage +} diff --git a/vendor/git.fd.io/govpp.git/core/log.go b/vendor/git.fd.io/govpp.git/core/log.go new file mode 100644 index 0000000000..aaef4cc517 --- /dev/null +++ b/vendor/git.fd.io/govpp.git/core/log.go @@ -0,0 +1,32 @@ +package core + +import ( + "os" + + logger "github.com/sirupsen/logrus" +) + +var ( + debug = os.Getenv("DEBUG_GOVPP") != "" + debugMsgIDs = os.Getenv("DEBUG_GOVPP_MSGIDS") != "" + + log = logger.New() // global logger +) + +// init initializes global logger, which logs debug level messages to stdout. +func init() { + log.Out = os.Stdout + if debug { + log.Level = logger.DebugLevel + } +} + +// SetLogger sets global logger to l. +func SetLogger(l *logger.Logger) { + log = l +} + +// SetLogLevel sets global logger level to lvl. +func SetLogLevel(lvl logger.Level) { + log.Level = lvl +} diff --git a/vendor/git.fd.io/govpp.git/core/notification_handler.go b/vendor/git.fd.io/govpp.git/core/notification_handler.go index c0e8687bd7..7b889e37ab 100644 --- a/vendor/git.fd.io/govpp.git/core/notification_handler.go +++ b/vendor/git.fd.io/govpp.git/core/notification_handler.go @@ -16,21 +16,20 @@ package core import ( "fmt" - "reflect" "git.fd.io/govpp.git/api" logger "github.com/sirupsen/logrus" ) -// processNotifSubscribeRequest processes a notification subscribe request. -func (c *Connection) processNotifSubscribeRequest(ch *channel, req *api.NotifSubscribeRequest) error { +// processSubscriptionRequest processes a notification subscribe request. +func (c *Connection) processSubscriptionRequest(ch *channel, req *subscriptionRequest) error { var err error // subscribe / unsubscribe - if req.Subscribe { - err = c.addNotifSubscription(req.Subscription) + if req.subscribe { + err = c.addNotifSubscription(req.sub) } else { - err = c.removeNotifSubscription(req.Subscription) + err = c.removeNotifSubscription(req.sub) } // send the reply into the go channel @@ -40,7 +39,7 @@ func (c *Connection) processNotifSubscribeRequest(ch *channel, req *api.NotifSub default: // unable to write into the channel without blocking log.WithFields(logger.Fields{ - "channel": ch, + "channel": ch.id, }).Warn("Unable to deliver the subscribe reply, reciever end not ready.") } @@ -50,14 +49,14 @@ func (c *Connection) processNotifSubscribeRequest(ch *channel, req *api.NotifSub // addNotifSubscription adds the notification subscription into the subscriptions map of the connection. func (c *Connection) addNotifSubscription(subs *api.NotifSubscription) error { // get message ID of the notification message - msgID, err := c.getSubscriptionMessageID(subs) + msgID, msgName, err := c.getSubscriptionMessageID(subs) if err != nil { return err } log.WithFields(logger.Fields{ - "msg_id": msgID, - "subscription": subs, + "msg_name": msgName, + "msg_id": msgID, }).Debug("Adding new notification subscription.") // add the subscription into map @@ -72,14 +71,14 @@ func (c *Connection) addNotifSubscription(subs *api.NotifSubscription) error { // removeNotifSubscription removes the notification subscription from the subscriptions map of the connection. func (c *Connection) removeNotifSubscription(subs *api.NotifSubscription) error { // get message ID of the notification message - msgID, err := c.getSubscriptionMessageID(subs) + msgID, msgName, err := c.getSubscriptionMessageID(subs) if err != nil { return err } log.WithFields(logger.Fields{ - "msg_id": msgID, - "subscription": subs, + "msg_name": msgName, + "msg_id": msgID, }).Debug("Removing notification subscription.") // remove the subscription from the map @@ -115,31 +114,22 @@ func (c *Connection) sendNotifications(msgID uint16, data []byte) { // send to notification to each subscriber for _, subs := range c.notifSubscriptions[msgID] { + msg := subs.MsgFactory() log.WithFields(logger.Fields{ - "msg_id": msgID, - "msg_size": len(data), - "subscription": subs, + "msg_name": msg.GetMessageName(), + "msg_id": msgID, + "msg_size": len(data), }).Debug("Sending a notification to the subscription channel.") - msg := subs.MsgFactory() - err := c.codec.DecodeMsg(data, msg) - if err != nil { + if err := c.codec.DecodeMsg(data, msg); err != nil { log.WithFields(logger.Fields{ - "msg_id": msgID, - "msg_size": len(data), - "subscription": subs, - }).Error("Unable to decode the notification message.") + "msg_name": msg.GetMessageName(), + "msg_id": msgID, + "msg_size": len(data), + }).Errorf("Unable to decode the notification message: %v", err) continue } - // special case for the strange interface counters message - if msg.GetMessageName() == "vnet_interface_counters" { - v := reflect.ValueOf(msg).Elem().FieldByName("Data") - if v.IsValid() { - v.SetBytes(data[8:]) // include the Count and Data fields in the data - } - } - // send the message into the go channel of the subscription select { case subs.NotifChan <- msg: @@ -147,9 +137,9 @@ func (c *Connection) sendNotifications(msgID uint16, data []byte) { default: // unable to write into the channel without blocking log.WithFields(logger.Fields{ - "msg_id": msgID, - "msg_size": len(data), - "subscription": subs, + "msg_name": msg.GetMessageName(), + "msg_id": msgID, + "msg_size": len(data), }).Warn("Unable to deliver the notification, reciever end not ready.") } @@ -160,22 +150,21 @@ func (c *Connection) sendNotifications(msgID uint16, data []byte) { log.WithFields(logger.Fields{ "msg_id": msgID, "msg_size": len(data), - }).Debug("No subscription found for the notification message.") + }).Info("No subscription found for the notification message.") } } // getSubscriptionMessageID returns ID of the message the subscription is tied to. -func (c *Connection) getSubscriptionMessageID(subs *api.NotifSubscription) (uint16, error) { +func (c *Connection) getSubscriptionMessageID(subs *api.NotifSubscription) (uint16, string, error) { msg := subs.MsgFactory() msgID, err := c.GetMessageID(msg) - if err != nil { log.WithFields(logger.Fields{ "msg_name": msg.GetMessageName(), "msg_crc": msg.GetCrcString(), }).Errorf("unable to retrieve message ID: %v", err) - return 0, fmt.Errorf("unable to retrieve message ID: %v", err) + return 0, "", fmt.Errorf("unable to retrieve message ID: %v", err) } - return msgID, nil + return msgID, msg.GetMessageName(), nil } diff --git a/vendor/git.fd.io/govpp.git/core/request_handler.go b/vendor/git.fd.io/govpp.git/core/request_handler.go index 8681963d6d..fd6d10027e 100644 --- a/vendor/git.fd.io/govpp.git/core/request_handler.go +++ b/vendor/git.fd.io/govpp.git/core/request_handler.go @@ -21,8 +21,6 @@ import ( "time" logger "github.com/sirupsen/logrus" - - "git.fd.io/govpp.git/api" ) var ( @@ -45,151 +43,182 @@ func (c *Connection) watchRequests(ch *channel) { case req := <-ch.notifSubsChan: // new request on the notification subscribe channel - c.processNotifSubscribeRequest(ch, req) + c.processSubscriptionRequest(ch, req) } } } // processRequest processes a single request received on the request channel. -func (c *Connection) processRequest(ch *channel, req *api.VppRequest) error { +func (c *Connection) processRequest(ch *channel, req *vppRequest) error { // check whether we are connected to VPP if atomic.LoadUint32(&c.connected) == 0 { err := ErrNotConnected - log.Error(err) - sendReply(ch, &api.VppReply{SeqNum: req.SeqNum, Error: err}) + log.Errorf("processing request failed: %v", err) + sendReplyError(ch, req, err) return err } // retrieve message ID - msgID, err := c.GetMessageID(req.Message) + msgID, err := c.GetMessageID(req.msg) if err != nil { err = fmt.Errorf("unable to retrieve message ID: %v", err) log.WithFields(logger.Fields{ - "msg_name": req.Message.GetMessageName(), - "msg_crc": req.Message.GetCrcString(), - "seq_num": req.SeqNum, + "msg_name": req.msg.GetMessageName(), + "msg_crc": req.msg.GetCrcString(), + "seq_num": req.seqNum, }).Error(err) - sendReply(ch, &api.VppReply{SeqNum: req.SeqNum, Error: err}) + sendReplyError(ch, req, err) return err } // encode the message into binary - data, err := c.codec.EncodeMsg(req.Message, msgID) + data, err := c.codec.EncodeMsg(req.msg, msgID) if err != nil { err = fmt.Errorf("unable to encode the messge: %v", err) log.WithFields(logger.Fields{ - "channel": ch.id, - "msg_id": msgID, - "seq_num": req.SeqNum, + "channel": ch.id, + "msg_id": msgID, + "msg_name": req.msg.GetMessageName(), + "seq_num": req.seqNum, }).Error(err) - sendReply(ch, &api.VppReply{SeqNum: req.SeqNum, Error: err}) + sendReplyError(ch, req, err) return err } + // get context + context := packRequestContext(ch.id, req.multi, req.seqNum) if log.Level == logger.DebugLevel { // for performance reasons - logrus does some processing even if debugs are disabled log.WithFields(logger.Fields{ "channel": ch.id, + "context": context, + "is_multi": req.multi, "msg_id": msgID, + "msg_name": req.msg.GetMessageName(), "msg_size": len(data), - "msg_name": req.Message.GetMessageName(), - "seq_num": req.SeqNum, - }).Debug("Sending a message to VPP.") + "seq_num": req.seqNum, + }).Debug(" -> Sending a message to VPP.") } // send the request to VPP - context := packRequestContext(ch.id, req.Multipart, req.SeqNum) err = c.vpp.SendMsg(context, data) if err != nil { err = fmt.Errorf("unable to send the message: %v", err) log.WithFields(logger.Fields{ "context": context, "msg_id": msgID, - "seq_num": req.SeqNum, + "seq_num": req.seqNum, }).Error(err) - sendReply(ch, &api.VppReply{SeqNum: req.SeqNum, Error: err}) + sendReplyError(ch, req, err) return err } - if req.Multipart { + if req.multi { // send a control ping to determine end of the multipart response pingData, _ := c.codec.EncodeMsg(msgControlPing, c.pingReqID) log.WithFields(logger.Fields{ + "channel": ch.id, "context": context, "msg_id": c.pingReqID, "msg_size": len(pingData), - "seq_num": req.SeqNum, - }).Debug("Sending a control ping to VPP.") - - c.vpp.SendMsg(context, pingData) + "seq_num": req.seqNum, + }).Debug(" -> Sending a control ping to VPP.") + + if err := c.vpp.SendMsg(context, pingData); err != nil { + log.WithFields(logger.Fields{ + "context": context, + "msg_id": msgID, + "seq_num": req.seqNum, + }).Warnf("unable to send control ping: %v", err) + } } return nil } // msgCallback is called whenever any binary API message comes from VPP. -func msgCallback(context uint32, msgID uint16, data []byte) { +func (c *Connection) msgCallback(msgID uint16, context uint32, data []byte) { connLock.RLock() defer connLock.RUnlock() - if conn == nil { + if c == nil { log.Warn("Already disconnected, ignoring the message.") return } - chanID, isMultipart, seqNum := unpackRequestContext(context) + msg, ok := c.msgMap[msgID] + if !ok { + log.Warnf("Unknown message received, ID: %d", msgID) + return + } + + // decode message context to fix for special cases of messages, + // for example: + // - replies that don't have context as first field (comes as zero) + // - events that don't have context at all (comes as non zero) + // + msgContext, err := c.codec.DecodeMsgContext(data, msg) + if err == nil { + if context != msgContext { + log.Debugf("different context was decoded from message (%d -> %d)", context, msgContext) + context = msgContext + } + } else { + log.Errorf("decoding context failed: %v", err) + } + + chanID, isMulti, seqNum := unpackRequestContext(context) if log.Level == logger.DebugLevel { // for performance reasons - logrus does some processing even if debugs are disabled log.WithFields(logger.Fields{ - "msg_id": msgID, - "msg_size": len(data), - "channel_id": chanID, - "is_multipart": isMultipart, - "seq_num": seqNum, - }).Debug("Received a message from VPP.") + "context": context, + "msg_id": msgID, + "msg_name": msg.GetMessageName(), + "msg_size": len(data), + "channel": chanID, + "is_multi": isMulti, + "seq_num": seqNum, + }).Debug(" <- Received a message from VPP.") } - if context == 0 || conn.isNotificationMessage(msgID) { + if context == 0 || c.isNotificationMessage(msgID) { // process the message as a notification - conn.sendNotifications(msgID, data) + c.sendNotifications(msgID, data) return } // match ch according to the context - conn.channelsLock.RLock() - ch, ok := conn.channels[chanID] - conn.channelsLock.RUnlock() - + c.channelsLock.RLock() + ch, ok := c.channels[chanID] + c.channelsLock.RUnlock() if !ok { log.WithFields(logger.Fields{ - "channel_id": chanID, - "msg_id": msgID, + "channel": chanID, + "msg_id": msgID, }).Error("Channel ID not known, ignoring the message.") return } - lastReplyReceived := false - // if this is a control ping reply to a multipart request, treat this as a last part of the reply - if msgID == conn.pingReplyID && isMultipart { - lastReplyReceived = true - } + // if this is a control ping reply to a multipart request, + // treat this as a last part of the reply + lastReplyReceived := isMulti && msgID == c.pingReplyID // send the data to the channel - sendReply(ch, &api.VppReply{ - MessageID: msgID, - SeqNum: seqNum, - Data: data, - LastReplyReceived: lastReplyReceived, + sendReply(ch, &vppReply{ + msgID: msgID, + seqNum: seqNum, + data: data, + lastReceived: lastReplyReceived, }) // store actual time of this reply - conn.lastReplyLock.Lock() - conn.lastReply = time.Now() - conn.lastReplyLock.Unlock() + c.lastReplyLock.Lock() + c.lastReply = time.Now() + c.lastReplyLock.Unlock() } // sendReply sends the reply into the go channel, if it cannot be completed without blocking, otherwise // it logs the error and do not send the message. -func sendReply(ch *channel, reply *api.VppReply) { +func sendReply(ch *channel, reply *vppReply) { select { case ch.replyChan <- reply: // reply sent successfully @@ -197,66 +226,14 @@ func sendReply(ch *channel, reply *api.VppReply) { // receiver still not ready log.WithFields(logger.Fields{ "channel": ch, - "msg_id": reply.MessageID, - "seq_num": reply.SeqNum, + "msg_id": reply.msgID, + "seq_num": reply.seqNum, }).Warn("Unable to send the reply, reciever end not ready.") } } -// GetMessageID returns message identifier of given API message. -func (c *Connection) GetMessageID(msg api.Message) (uint16, error) { - if c == nil { - return 0, errors.New("nil connection passed in") - } - return c.messageNameToID(msg.GetMessageName(), msg.GetCrcString()) -} - -// messageNameToID returns message ID of a message identified by its name and CRC. -func (c *Connection) messageNameToID(msgName string, msgCrc string) (uint16, error) { - msgKey := msgName + "_" + msgCrc - - // try to get the ID from the map - c.msgIDsLock.RLock() - id, ok := c.msgIDs[msgKey] - c.msgIDsLock.RUnlock() - if ok { - return id, nil - } - - // get the ID using VPP API - id, err := c.vpp.GetMsgID(msgName, msgCrc) - if err != nil { - err = fmt.Errorf("unable to retrieve message ID: %v", err) - log.WithFields(logger.Fields{ - "msg_name": msgName, - "msg_crc": msgCrc, - }).Error(err) - return id, err - } - - c.msgIDsLock.Lock() - c.msgIDs[msgKey] = id - c.msgIDsLock.Unlock() - - return id, nil -} - -// LookupByID looks up message name and crc by ID. -func (c *Connection) LookupByID(ID uint16) (string, error) { - if c == nil { - return "", errors.New("nil connection passed in") - } - - c.msgIDsLock.Lock() - defer c.msgIDsLock.Unlock() - - for key, id := range c.msgIDs { - if id == ID { - return key, nil - } - } - - return "", fmt.Errorf("unknown message ID: %d", ID) +func sendReplyError(ch *channel, req *vppRequest, err error) { + sendReply(ch, &vppReply{seqNum: req.seqNum, err: err}) } // +------------------+-------------------+-----------------------+ @@ -279,3 +256,24 @@ func unpackRequestContext(context uint32) (chanID uint16, isMulipart bool, seqNu seqNum = uint16(context & 0xffff) return } + +// compareSeqNumbers returns -1, 0, 1 if sequence number precedes, equals to, +// or succeeds seq. number . +// Since sequence numbers cycle in the finite set of size 2^16, the function +// must assume that the distance between compared sequence numbers is less than +// (2^16)/2 to determine the order. +func compareSeqNumbers(seqNum1, seqNum2 uint16) int { + // calculate distance from seqNum1 to seqNum2 + var dist uint16 + if seqNum1 <= seqNum2 { + dist = seqNum2 - seqNum1 + } else { + dist = 0xffff - (seqNum1 - seqNum2 - 1) + } + if dist == 0 { + return 0 + } else if dist <= 0x8000 { + return -1 + } + return 1 +} diff --git a/vendor/github.com/bshuster-repo/logrus-logstash-hook/.gitignore b/vendor/github.com/bshuster-repo/logrus-logstash-hook/.gitignore new file mode 100644 index 0000000000..4206723292 --- /dev/null +++ b/vendor/github.com/bshuster-repo/logrus-logstash-hook/.gitignore @@ -0,0 +1,26 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test +.idea + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof +*.iml diff --git a/vendor/github.com/bshuster-repo/logrus-logstash-hook/.travis.yml b/vendor/github.com/bshuster-repo/logrus-logstash-hook/.travis.yml new file mode 100644 index 0000000000..60c00ef662 --- /dev/null +++ b/vendor/github.com/bshuster-repo/logrus-logstash-hook/.travis.yml @@ -0,0 +1,19 @@ +language: go +sudo: false + +matrix: + include: + - go: 1.3 + - go: 1.4 + - go: 1.5 + - go: 1.6 + - go: tip + +install: + - # Skip + +script: + - go get -t -v ./... + - diff -u <(echo -n) <(gofmt -d .) + - go tool vet . + - go test -v -race ./... diff --git a/vendor/github.com/bshuster-repo/logrus-logstash-hook/CHANGELOG.md b/vendor/github.com/bshuster-repo/logrus-logstash-hook/CHANGELOG.md new file mode 100644 index 0000000000..31c8b5f347 --- /dev/null +++ b/vendor/github.com/bshuster-repo/logrus-logstash-hook/CHANGELOG.md @@ -0,0 +1,18 @@ +# Changelog + +## 0.4 + + * Update the name of the package from `logrus_logstash` to `logrustash` + * Add TimeFormat to Hook + * Replace the old logrus package path: `github.com/Sirupsen/logrus` with `github.com/sirupsen/logrus` + +## 0.3 + + * Fix the Logstash format to set `@version` to `"1"` + * Add unit-tests to logstash.go + * Remove the assert package + * Add prefix filtering + +## Before that (major changes) + + * Update LICENSE to MIT from GPL diff --git a/vendor/github.com/kr/text/License b/vendor/github.com/bshuster-repo/logrus-logstash-hook/LICENSE similarity index 93% rename from vendor/github.com/kr/text/License rename to vendor/github.com/bshuster-repo/logrus-logstash-hook/LICENSE index 480a328059..3fb4442f84 100644 --- a/vendor/github.com/kr/text/License +++ b/vendor/github.com/bshuster-repo/logrus-logstash-hook/LICENSE @@ -1,4 +1,6 @@ -Copyright 2012 Keith Rarick +The MIT License (MIT) + +Copyright (c) 2016 Boaz Shuster Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -16,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +THE SOFTWARE. \ No newline at end of file diff --git a/vendor/github.com/bshuster-repo/logrus-logstash-hook/README.md b/vendor/github.com/bshuster-repo/logrus-logstash-hook/README.md new file mode 100644 index 0000000000..9cc4378c50 --- /dev/null +++ b/vendor/github.com/bshuster-repo/logrus-logstash-hook/README.md @@ -0,0 +1,106 @@ +# Logstash hook for logrus :walrus: [![Build Status](https://travis-ci.org/bshuster-repo/logrus-logstash-hook.svg?branch=master)](https://travis-ci.org/bshuster-repo/logrus-logstash-hook) +Use this hook to send the logs to [Logstash](https://www.elastic.co/products/logstash) over both UDP and TCP. + +## Usage + +```go +package main + +import ( + "github.com/sirupsen/logrus" + "github.com/bshuster-repo/logrus-logstash-hook" +) + +func main() { + log := logrus.New() + hook, err := logrustash.NewHook("tcp", "172.17.0.2:9999", "myappName") + + if err != nil { + log.Fatal(err) + } + log.Hooks.Add(hook) + ctx := log.WithFields(logrus.Fields{ + "method": "main", + }) + ... + ctx.Info("Hello World!") +} +``` + +This is how it will look like: + +```ruby +{ + "@timestamp" => "2016-02-29T16:57:23.000Z", + "@version" => "1", + "level" => "info", + "message" => "Hello World!", + "method" => "main", + "host" => "172.17.0.1", + "port" => 45199, + "type" => "myappName" +} +``` +## Hook Fields +Fields can be added to the hook, which will always be in the log context. +This can be done when creating the hook: + +```go + +hook, err := logrustash.NewHookWithFields("tcp", "172.17.0.2:9999", "myappName", logrus.Fields{ + "hostname": os.Hostname(), + "serviceName": "myServiceName", +}) +``` + +Or afterwards: + +```go + +hook.WithFields(logrus.Fields{ + "hostname": os.Hostname(), + "serviceName": "myServiceName", +}) +``` +This allows you to set up the hook so logging is available immediately, and add important fields as they become available. + +Single fields can be added/updated using 'WithField': + +```go + +hook.WithField("status", "running") +``` + + + +## Field prefix + +The hook allows you to send logging to logstash and also retain the default std output in text format. +However to keep this console output readable some fields might need to be omitted from the default non-hooked log output. +Each hook can be configured with a prefix used to identify fields which are only to be logged to the logstash connection. +For example if you don't want to see the hostname and serviceName on each log line in the console output you can add a prefix: + +```go + + +hook, err := logrustash.NewHookWithFields("tcp", "172.17.0.2:9999", "myappName", logrus.Fields{ + "_hostname": os.Hostname(), + "_serviceName": "myServiceName", +}) +... +hook.WithPrefix("_") +``` + +There are also constructors available which allow you to specify the prefix from the start. +The std-out will not have the '\_hostname' and '\_servicename' fields, and the logstash output will, but the prefix will be dropped from the name. + + +# Authors + +Name | Github | Twitter | +------------ | --------- | ---------- | +Boaz Shuster | ripcurld0 | @ripcurld0 | + +# License + +MIT. diff --git a/vendor/github.com/bshuster-repo/logrus-logstash-hook/logstash.go b/vendor/github.com/bshuster-repo/logrus-logstash-hook/logstash.go new file mode 100644 index 0000000000..1f2e5a0cb9 --- /dev/null +++ b/vendor/github.com/bshuster-repo/logrus-logstash-hook/logstash.go @@ -0,0 +1,133 @@ +package logrustash + +import ( + "net" + "strings" + + "github.com/sirupsen/logrus" +) + +// Hook represents a connection to a Logstash instance +type Hook struct { + conn net.Conn + appName string + alwaysSentFields logrus.Fields + hookOnlyPrefix string + TimeFormat string +} + +// NewHook creates a new hook to a Logstash instance, which listens on +// `protocol`://`address`. +func NewHook(protocol, address, appName string) (*Hook, error) { + return NewHookWithFields(protocol, address, appName, make(logrus.Fields)) +} + +// NewHookWithConn creates a new hook to a Logstash instance, using the supplied connection +func NewHookWithConn(conn net.Conn, appName string) (*Hook, error) { + return NewHookWithFieldsAndConn(conn, appName, make(logrus.Fields)) +} + +// NewHookWithFields creates a new hook to a Logstash instance, which listens on +// `protocol`://`address`. alwaysSentFields will be sent with every log entry. +func NewHookWithFields(protocol, address, appName string, alwaysSentFields logrus.Fields) (*Hook, error) { + return NewHookWithFieldsAndPrefix(protocol, address, appName, alwaysSentFields, "") +} + +// NewHookWithFieldsAndPrefix creates a new hook to a Logstash instance, which listens on +// `protocol`://`address`. alwaysSentFields will be sent with every log entry. prefix is used to select fields to filter +func NewHookWithFieldsAndPrefix(protocol, address, appName string, alwaysSentFields logrus.Fields, prefix string) (*Hook, error) { + conn, err := net.Dial(protocol, address) + if err != nil { + return nil, err + } + return NewHookWithFieldsAndConnAndPrefix(conn, appName, alwaysSentFields, prefix) +} + +// NewHookWithFieldsAndConn creates a new hook to a Logstash instance using the supplied connection +func NewHookWithFieldsAndConn(conn net.Conn, appName string, alwaysSentFields logrus.Fields) (*Hook, error) { + return NewHookWithFieldsAndConnAndPrefix(conn, appName, alwaysSentFields, "") +} + +//NewHookWithFieldsAndConnAndPrefix creates a new hook to a Logstash instance using the suppolied connection and prefix +func NewHookWithFieldsAndConnAndPrefix(conn net.Conn, appName string, alwaysSentFields logrus.Fields, prefix string) (*Hook, error) { + return &Hook{conn: conn, appName: appName, alwaysSentFields: alwaysSentFields, hookOnlyPrefix: prefix}, nil +} + +//NewFilterHook makes a new hook which does not forward to logstash, but simply enforces the prefix rules +func NewFilterHook() *Hook { + return NewFilterHookWithPrefix("") +} + +//NewFilterHookWithPrefix make a new hook which does not forward to logstash, but simply enforces the specified prefix +func NewFilterHookWithPrefix(prefix string) *Hook { + return &Hook{conn: nil, appName: "", alwaysSentFields: make(logrus.Fields), hookOnlyPrefix: prefix} +} + +func (h *Hook) filterHookOnly(entry *logrus.Entry) { + if h.hookOnlyPrefix != "" { + for key := range entry.Data { + if strings.HasPrefix(key, h.hookOnlyPrefix) { + delete(entry.Data, key) + } + } + } + +} + +//WithPrefix sets a prefix filter to use in all subsequent logging +func (h *Hook) WithPrefix(prefix string) { + h.hookOnlyPrefix = prefix +} + +func (h *Hook) WithField(key string, value interface{}) { + h.alwaysSentFields[key] = value +} + +func (h *Hook) WithFields(fields logrus.Fields) { + //Add all the new fields to the 'alwaysSentFields', possibly overwriting exising fields + for key, value := range fields { + h.alwaysSentFields[key] = value + } +} + +func (h *Hook) Fire(entry *logrus.Entry) error { + //make sure we always clear the hookonly fields from the entry + defer h.filterHookOnly(entry) + + // Add in the alwaysSentFields. We don't override fields that are already set. + for k, v := range h.alwaysSentFields { + if _, inMap := entry.Data[k]; !inMap { + entry.Data[k] = v + } + } + + //For a filteringHook, stop here + if h.conn == nil { + return nil + } + + formatter := LogstashFormatter{Type: h.appName} + if h.TimeFormat != "" { + formatter.TimestampFormat = h.TimeFormat + } + + dataBytes, err := formatter.FormatWithPrefix(entry, h.hookOnlyPrefix) + if err != nil { + return err + } + if _, err = h.conn.Write(dataBytes); err != nil { + return err + } + return nil +} + +func (h *Hook) Levels() []logrus.Level { + return []logrus.Level{ + logrus.PanicLevel, + logrus.FatalLevel, + logrus.ErrorLevel, + logrus.WarnLevel, + logrus.InfoLevel, + logrus.DebugLevel, + } +} diff --git a/vendor/github.com/bshuster-repo/logrus-logstash-hook/logstash_formatter.go b/vendor/github.com/bshuster-repo/logrus-logstash-hook/logstash_formatter.go new file mode 100644 index 0000000000..64bc5c3899 --- /dev/null +++ b/vendor/github.com/bshuster-repo/logrus-logstash-hook/logstash_formatter.go @@ -0,0 +1,81 @@ +package logrustash + +import ( + "encoding/json" + "fmt" + "strings" + "time" + + "github.com/sirupsen/logrus" +) + +// Formatter generates json in logstash format. +// Logstash site: http://logstash.net/ +type LogstashFormatter struct { + Type string // if not empty use for logstash type field. + + // TimestampFormat sets the format used for timestamps. + TimestampFormat string +} + +func (f *LogstashFormatter) Format(entry *logrus.Entry) ([]byte, error) { + return f.FormatWithPrefix(entry, "") +} + +func (f *LogstashFormatter) FormatWithPrefix(entry *logrus.Entry, prefix string) ([]byte, error) { + fields := make(logrus.Fields) + for k, v := range entry.Data { + //remvove the prefix when sending the fields to logstash + if prefix != "" && strings.HasPrefix(k, prefix) { + k = strings.TrimPrefix(k, prefix) + } + + switch v := v.(type) { + case error: + // Otherwise errors are ignored by `encoding/json` + // https://github.com/Sirupsen/logrus/issues/377 + fields[k] = v.Error() + default: + fields[k] = v + } + } + + fields["@version"] = "1" + + timeStampFormat := f.TimestampFormat + + if timeStampFormat == "" { + timeStampFormat = time.RFC3339 + } + + fields["@timestamp"] = entry.Time.Format(timeStampFormat) + + // set message field + v, ok := entry.Data["message"] + if ok { + fields["fields.message"] = v + } + fields["message"] = entry.Message + + // set level field + v, ok = entry.Data["level"] + if ok { + fields["fields.level"] = v + } + fields["level"] = entry.Level.String() + + // set type field + if f.Type != "" { + v, ok = entry.Data["type"] + if ok { + fields["fields.type"] = v + } + fields["type"] = f.Type + } + + serialized, err := json.Marshal(fields) + if err != nil { + return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) + } + return append(serialized, '\n'), nil +} diff --git a/vendor/github.com/bsm/sarama-cluster/Gopkg.lock b/vendor/github.com/bsm/sarama-cluster/Gopkg.lock index b7c59b1c03..3ab8b6ab2c 100644 --- a/vendor/github.com/bsm/sarama-cluster/Gopkg.lock +++ b/vendor/github.com/bsm/sarama-cluster/Gopkg.lock @@ -4,8 +4,8 @@ [[projects]] name = "github.com/Shopify/sarama" packages = ["."] - revision = "240fd146ce68bcafb034cc5dc977229ffbafa8ea" - version = "v1.14.0" + revision = "3b1b38866a79f06deddf0487d5c27ba0697ccd65" + version = "v1.15.0" [[projects]] name = "github.com/davecgh/go-spew" @@ -28,8 +28,8 @@ [[projects]] name = "github.com/eapache/queue" packages = ["."] - revision = "ded5959c0d4e360646dc9e9908cff48666781367" - version = "v1.0.2" + revision = "44cc805cf13205b55f69e14bcb69867d1ae92f98" + version = "v1.1.0" [[projects]] branch = "master" @@ -39,21 +39,54 @@ [[projects]] name = "github.com/onsi/ginkgo" - packages = [".","config","extensions/table","internal/codelocation","internal/containernode","internal/failer","internal/leafnodes","internal/remote","internal/spec","internal/spec_iterator","internal/specrunner","internal/suite","internal/testingtproxy","internal/writer","reporters","reporters/stenographer","reporters/stenographer/support/go-colorable","reporters/stenographer/support/go-isatty","types"] + packages = [ + ".", + "config", + "extensions/table", + "internal/codelocation", + "internal/containernode", + "internal/failer", + "internal/leafnodes", + "internal/remote", + "internal/spec", + "internal/spec_iterator", + "internal/specrunner", + "internal/suite", + "internal/testingtproxy", + "internal/writer", + "reporters", + "reporters/stenographer", + "reporters/stenographer/support/go-colorable", + "reporters/stenographer/support/go-isatty", + "types" + ] revision = "9eda700730cba42af70d53180f9dcce9266bc2bc" version = "v1.4.0" [[projects]] name = "github.com/onsi/gomega" - packages = [".","format","internal/assertion","internal/asyncassertion","internal/oraclematcher","internal/testingtsupport","matchers","matchers/support/goraph/bipartitegraph","matchers/support/goraph/edge","matchers/support/goraph/node","matchers/support/goraph/util","types"] - revision = "c893efa28eb45626cdaa76c9f653b62488858837" - version = "v1.2.0" + packages = [ + ".", + "format", + "internal/assertion", + "internal/asyncassertion", + "internal/oraclematcher", + "internal/testingtsupport", + "matchers", + "matchers/support/goraph/bipartitegraph", + "matchers/support/goraph/edge", + "matchers/support/goraph/node", + "matchers/support/goraph/util", + "types" + ] + revision = "003f63b7f4cff3fc95357005358af2de0f5fe152" + version = "v1.3.0" [[projects]] name = "github.com/pierrec/lz4" packages = ["."] - revision = "08c27939df1bd95e881e2c2367a749964ad1fceb" - version = "v1.0.1" + revision = "2fcda4cb7018ce05a25959d2fe08c83e3329f169" + version = "v1.1" [[projects]] name = "github.com/pierrec/xxHash" @@ -65,31 +98,53 @@ branch = "master" name = "github.com/rcrowley/go-metrics" packages = ["."] - revision = "1f30fe9094a513ce4c700b9a54458bbb0c96996c" + revision = "8732c616f52954686704c8645fe1a9d59e9df7c1" [[projects]] branch = "master" name = "golang.org/x/net" - packages = ["html","html/atom","html/charset"] - revision = "a337091b0525af65de94df2eb7e98bd9962dcbe2" + packages = [ + "html", + "html/atom", + "html/charset" + ] + revision = "0ed95abb35c445290478a5348a7b38bb154135fd" [[projects]] branch = "master" name = "golang.org/x/sys" packages = ["unix"] - revision = "665f6529cca930e27b831a0d1dafffbe1c172924" + revision = "3dbebcf8efb6a5011a60c2b4591c1022a759af8a" [[projects]] branch = "master" name = "golang.org/x/text" - packages = ["encoding","encoding/charmap","encoding/htmlindex","encoding/internal","encoding/internal/identifier","encoding/japanese","encoding/korean","encoding/simplifiedchinese","encoding/traditionalchinese","encoding/unicode","internal/gen","internal/tag","internal/utf8internal","language","runes","transform","unicode/cldr"] - revision = "88f656faf3f37f690df1a32515b479415e1a6769" + packages = [ + "encoding", + "encoding/charmap", + "encoding/htmlindex", + "encoding/internal", + "encoding/internal/identifier", + "encoding/japanese", + "encoding/korean", + "encoding/simplifiedchinese", + "encoding/traditionalchinese", + "encoding/unicode", + "internal/gen", + "internal/tag", + "internal/utf8internal", + "language", + "runes", + "transform", + "unicode/cldr" + ] + revision = "e19ae1496984b1c655b8044a65c0300a3c878dd3" [[projects]] branch = "v2" name = "gopkg.in/yaml.v2" packages = ["."] - revision = "eb3733d160e74a9c7e442f435eb3bea458e1d19f" + revision = "d670f9405373e636a5a2765eea47fac0c9bc91a4" [solve-meta] analyzer-name = "dep" diff --git a/vendor/github.com/bsm/sarama-cluster/consumer.go b/vendor/github.com/bsm/sarama-cluster/consumer.go index 761596d1a5..13500cc8e7 100644 --- a/vendor/github.com/bsm/sarama-cluster/consumer.go +++ b/vendor/github.com/bsm/sarama-cluster/consumer.go @@ -140,13 +140,19 @@ func (c *Consumer) HighWaterMarks() map[string]map[int32]int64 { return c.consum // your application crashes. This means that you may end up processing the same // message twice, and your processing should ideally be idempotent. func (c *Consumer) MarkOffset(msg *sarama.ConsumerMessage, metadata string) { - c.subs.Fetch(msg.Topic, msg.Partition).MarkOffset(msg.Offset+1, metadata) + sub := c.subs.Fetch(msg.Topic, msg.Partition) + if sub != nil { + sub.MarkOffset(msg.Offset+1, metadata) + } } // MarkPartitionOffset marks an offset of the provided topic/partition as processed. // See MarkOffset for additional explanation. func (c *Consumer) MarkPartitionOffset(topic string, partition int32, offset int64, metadata string) { - c.subs.Fetch(topic, partition).MarkOffset(offset+1, metadata) + sub := c.subs.Fetch(topic, partition) + if sub != nil { + sub.MarkOffset(offset+1, metadata) + } } // MarkOffsets marks stashed offsets as processed. @@ -156,7 +162,47 @@ func (c *Consumer) MarkOffsets(s *OffsetStash) { defer s.mu.Unlock() for tp, info := range s.offsets { - c.subs.Fetch(tp.Topic, tp.Partition).MarkOffset(info.Offset+1, info.Metadata) + sub := c.subs.Fetch(tp.Topic, tp.Partition) + if sub != nil { + sub.MarkOffset(info.Offset+1, info.Metadata) + } + delete(s.offsets, tp) + } +} + +// ResetOffsets marks the provided message as processed, alongside a metadata string +// that represents the state of the partition consumer at that point in time. The +// metadata string can be used by another consumer to restore that state, so it +// can resume consumption. +// +// Difference between ResetOffset and MarkOffset is that it allows to rewind to an earlier offset +func (c *Consumer) ResetOffset(msg *sarama.ConsumerMessage, metadata string) { + sub := c.subs.Fetch(msg.Topic, msg.Partition) + if sub != nil { + sub.ResetOffset(msg.Offset+1, metadata) + } +} + +// ResetPartitionOffset marks an offset of the provided topic/partition as processed. +// See ResetOffset for additional explanation. +func (c *Consumer) ResetPartitionOffset(topic string, partition int32, offset int64, metadata string) { + sub := c.subs.Fetch(topic, partition) + if sub != nil { + sub.ResetOffset(offset+1, metadata) + } +} + +// ResetOffsets marks stashed offsets as processed. +// See ResetOffset for additional explanation. +func (c *Consumer) ResetOffsets(s *OffsetStash) { + s.mu.Lock() + defer s.mu.Unlock() + + for tp, info := range s.offsets { + sub := c.subs.Fetch(tp.Topic, tp.Partition) + if sub != nil { + sub.ResetOffset(info.Offset+1, info.Metadata) + } delete(s.offsets, tp) } } @@ -218,7 +264,10 @@ func (c *Consumer) CommitOffsets() error { if kerr != sarama.ErrNoError { err = kerr } else if state, ok := snap[topicPartition{topic, partition}]; ok { - c.subs.Fetch(topic, partition).MarkCommitted(state.Info.Offset) + sub := c.subs.Fetch(topic, partition) + if sub != nil { + sub.MarkCommitted(state.Info.Offset) + } } } } diff --git a/vendor/github.com/bsm/sarama-cluster/offsets.go b/vendor/github.com/bsm/sarama-cluster/offsets.go index b2abe355f2..4223ac5e01 100644 --- a/vendor/github.com/bsm/sarama-cluster/offsets.go +++ b/vendor/github.com/bsm/sarama-cluster/offsets.go @@ -36,6 +36,26 @@ func (s *OffsetStash) MarkPartitionOffset(topic string, partition int32, offset } } +// ResetPartitionOffset stashes the offset for the provided topic/partition combination. +// Difference between ResetPartitionOffset and MarkPartitionOffset is that, ResetPartitionOffset supports earlier offsets +func (s *OffsetStash) ResetPartitionOffset(topic string, partition int32, offset int64, metadata string) { + s.mu.Lock() + defer s.mu.Unlock() + + key := topicPartition{Topic: topic, Partition: partition} + if info := s.offsets[key]; offset <= info.Offset { + info.Offset = offset + info.Metadata = metadata + s.offsets[key] = info + } +} + +// ResetOffset stashes the provided message offset +// See ResetPartitionOffset for explanation +func (s *OffsetStash) ResetOffset(msg *sarama.ConsumerMessage, metadata string) { + s.ResetPartitionOffset(msg.Topic, msg.Partition, msg.Offset, metadata) +} + // Offsets returns the latest stashed offsets by topic-partition func (s *OffsetStash) Offsets() map[string]int64 { s.mu.Lock() diff --git a/vendor/github.com/bsm/sarama-cluster/partitions.go b/vendor/github.com/bsm/sarama-cluster/partitions.go index d5f59af4ea..987780bde1 100644 --- a/vendor/github.com/bsm/sarama-cluster/partitions.go +++ b/vendor/github.com/bsm/sarama-cluster/partitions.go @@ -12,19 +12,7 @@ import ( // // See docs for Consumer.Partitions() for more on how to implement this. type PartitionConsumer interface { - - // Close stops the PartitionConsumer from fetching messages. It will initiate a shutdown, drain - // the Messages channel, harvest any errors & return them to the caller and trigger a rebalance. - Close() error - - // Messages returns the read channel for the messages that are returned by - // the broker. - Messages() <-chan *sarama.ConsumerMessage - - // HighWaterMarkOffset returns the high water mark offset of the partition, - // i.e. the offset that will be used for the next message that will be produced. - // You can use this to determine how far behind the processing is. - HighWaterMarkOffset() int64 + sarama.PartitionConsumer // Topic returns the consumed topic name Topic() string @@ -42,7 +30,9 @@ type partitionConsumer struct { topic string partition int32 - once sync.Once + closeOnce sync.Once + closeErr error + dying, dead chan none } @@ -76,6 +66,21 @@ func (c *partitionConsumer) Topic() string { return c.topic } // Partition implements PartitionConsumer func (c *partitionConsumer) Partition() int32 { return c.partition } +// AsyncClose implements PartitionConsumer +func (c *partitionConsumer) AsyncClose() { + c.closeOnce.Do(func() { + c.closeErr = c.PartitionConsumer.Close() + close(c.dying) + }) +} + +// Close implements PartitionConsumer +func (c *partitionConsumer) Close() error { + c.AsyncClose() + <-c.dead + return c.closeErr +} + func (c *partitionConsumer) WaitFor(stopper <-chan none, errors chan<- error) { defer close(c.dead) @@ -135,15 +140,6 @@ func (c *partitionConsumer) Multiplex(stopper <-chan none, messages chan<- *sara } } -func (c *partitionConsumer) Close() (err error) { - c.once.Do(func() { - err = c.PartitionConsumer.Close() - close(c.dying) - }) - <-c.dead - return err -} - func (c *partitionConsumer) State() partitionState { if c == nil { return partitionState{} @@ -182,6 +178,20 @@ func (c *partitionConsumer) MarkOffset(offset int64, metadata string) { c.mu.Unlock() } +func (c *partitionConsumer) ResetOffset(offset int64, metadata string) { + if c == nil { + return + } + + c.mu.Lock() + if offset <= c.state.Info.Offset { + c.state.Info.Offset = offset + c.state.Info.Metadata = metadata + c.state.Dirty = true + } + c.mu.Unlock() +} + // -------------------------------------------------------------------- type partitionState struct { diff --git a/vendor/github.com/docker/docker/AUTHORS b/vendor/github.com/docker/docker/AUTHORS index f465a87903..46102d7402 100644 --- a/vendor/github.com/docker/docker/AUTHORS +++ b/vendor/github.com/docker/docker/AUTHORS @@ -21,11 +21,13 @@ Adam Eijdenberg Adam Kunk Adam Miller Adam Mills +Adam Pointer Adam Singer Adam Walz Addam Hardy Aditi Rajagopal Aditya +Adnan Khan Adolfo Ochagavía Adria Casas Adrian Moisey @@ -37,12 +39,13 @@ Ahmed Kamal Ahmet Alp Balkan Aidan Feldman Aidan Hobson Sayers -AJ Bowen +AJ Bowen Ajey Charantimath ajneu Akash Gupta Akihiro Matsushima Akihiro Suda +Akim Demaille Akira Koyasu Akshay Karle Al Tobey @@ -51,6 +54,7 @@ Alan Scherger Alan Thompson Albert Callarisa Albert Zhang +Alejandro González Hevia Aleksa Sarai Aleksandrs Fadins Alena Prokharchyk @@ -62,6 +66,7 @@ Alex Coventry Alex Crawford Alex Ellis Alex Gaynor +Alex Goodman Alex Olshansky Alex Samorukov Alex Warhawk @@ -74,6 +79,7 @@ Alexander Shopov Alexandre Beslic Alexandre Garnier Alexandre González +Alexandre Jomin Alexandru Sfirlogea Alexey Guskov Alexey Kotlyarov @@ -95,16 +101,19 @@ Amir Goldstein Amit Bakshi Amit Krishnan Amit Shukla +Amr Gawish Amy Lindburg Anand Patil AnandkumarPatel Anatoly Borodin Anchal Agrawal +Anda Xu Anders Janmyr Andre Dublin <81dublin@gmail.com> Andre Granovsky Andrea Luzzardi Andrea Turli +Andreas Elvers Andreas Köhler Andreas Savvides Andreas Tiefenthaler @@ -123,8 +132,9 @@ Andrew Macpherson Andrew Martin Andrew McDonnell Andrew Munsell +Andrew Pennebaker Andrew Po -Andrew Weiss +Andrew Weiss Andrew Williams Andrews Medina Andrey Petrov @@ -144,6 +154,7 @@ Anil Madhavapeddy Ankush Agarwal Anonmily Anran Qiao +Anshul Pundir Anthon van der Neut Anthony Baire Anthony Bishopric @@ -167,6 +178,7 @@ Arthur Barr Arthur Gautier Artur Meyster Arun Gupta +Asad Saeeduddin Asbjørn Enge averagehuman Avi Das @@ -190,6 +202,7 @@ Ben Toews Ben Wiklund Benjamin Atkin Benjamin Boudreau +Benjamin Yolken Benoit Chesneau Bernerd Schaefer Bernhard M. Wiedemann @@ -198,27 +211,27 @@ Bharath Thiruveedula Bhiraj Butala Bhumika Bayani Bilal Amarni -Bill W -bin liu +Bill Wang +Bin Liu Bingshen Wang Blake Geno Boaz Shuster bobby abbott Boris Pruessmann Boshi Lian -boucher Bouke Haarsma Boyd Hemphill boynux Bradley Cicenas Bradley Wright Brandon Liu -Brandon Philips +Brandon Philips Brandon Rhodes Brendan Dixon Brent Salisbury Brett Higgins Brett Kochendorfer +Brett Randall Brian (bex) Exelbierd Brian Bland Brian DeHamer @@ -242,7 +255,6 @@ Bryan Bess Bryan Boreham Bryan Matsuo Bryan Murphy -buddhamagnet Burke Libbey Byung Kang Caleb Spare @@ -261,12 +273,15 @@ Carlos Sanchez Carol Fager-Higgins Cary Casey Bisson +Catalin Pirvu Ce Gao Cedric Davies Cezar Sa Espinola Chad Swenson Chance Zibolski -Chander G +Chander Govindarajan +Chanhun Jeong +Chao Wang Charles Chan Charles Hooper Charles Law @@ -284,6 +299,10 @@ Chen Hanxiao Chen Min Chen Mingjie Chen Qiu +Cheng-mean Liu +Chengguang Xu +chenyuzhu +Chetan Birajdar Chewey Chia-liang Kao chli @@ -303,9 +322,11 @@ Chris Snow Chris St. Pierre Chris Stivers Chris Swan +Chris Telfer Chris Wahl Chris Weyl Christian Berendt +Christian Brauner Christian Böhme Christian Persson Christian Rotzoll @@ -325,6 +346,7 @@ Chun Chen Ciro S. Costa Clayton Coleman Clinton Kitson +Cody Roseborough Coenraad Loubser Colin Dunklau Colin Hebert @@ -333,6 +355,7 @@ Colin Walters Collin Guarino Colm Hally companycy +Corbin Coleman Corey Farrell Cory Forsyth cressie176 @@ -362,7 +385,9 @@ Dan Levy Dan McPherson Dan Stine Dan Williams +Dani Louca Daniel Antlinger +Daniel Dao Daniel Exner Daniel Farrell Daniel Garcia @@ -378,23 +403,26 @@ Daniel Nordberg Daniel Robinson Daniel S Daniel Von Fange +Daniel Watkins Daniel X Moore Daniel YC Lin Daniel Zhang -Daniel, Dao Quang Minh Danny Berger Danny Yates +Danyal Khaliq Darren Coxall Darren Shepherd Darren Stahl Dattatraya Kumbhar Davanum Srinivas Dave Barboza +Dave Goodchild Dave Henderson Dave MacDonald Dave Tucker David Anderson David Calavera +David Chung David Corking David Cramer David Currie @@ -416,7 +444,7 @@ David Röthlisberger David Sheets David Sissitka David Trott -David Williamson +David Williamson David Xia David Young Davide Ceretti @@ -431,6 +459,7 @@ Denis Defreyne Denis Gladkikh Denis Ollier Dennis Chen +Dennis Chen Dennis Docter Derek Derek @@ -484,6 +513,7 @@ Dr Nic Williams dragon788 Dražen Lučanin Drew Erny +Drew Hubl Dustin Sallings Ed Costello Edmund Wagner @@ -492,6 +522,7 @@ Eike Herzbach Eivin Giske Skaaren Eivind Uggedal Elan Ruusamäe +Elango Sivanandam Elena Morozova Eli Uriegas Elias Faxö @@ -499,6 +530,7 @@ Elias Probst Elijah Zupancic eluck Elvir Kuric +Emil Davtyan Emil Hernvall Emily Maier Emily Rose @@ -514,8 +546,9 @@ Eric Lee Eric Myhre Eric Paris Eric Rafaloff -Eric Rosenberg +Eric Rosenberg Eric Sage +Eric Soderstrom Eric Yang Eric-Olivier Lamey Erica Windisch @@ -528,12 +561,12 @@ Erik St. Martin Erik Weathers Erno Hopearuoho Erwin van der Koogh +Ethan Bell Euan Kemp Eugen Krizo Eugene Yakubovich Evan Allrich Evan Carmi -Evan Hazlett Evan Hazlett Evan Krall Evan Phoenix @@ -556,6 +589,7 @@ Fabrizio Regini Fabrizio Soppelsa Faiz Khan falmp +Fangming Fang Fangyuan Gao <21551127@zju.edu.cn> Fareed Dudhia Fathi Boudra @@ -563,10 +597,11 @@ Federico Gimenez Felipe Oliveira Felix Abecassis Felix Geisendörfer -Felix Hupfeld +Felix Hupfeld Felix Rabe Felix Ruess Felix Schindler +Feng Yan Fengtu Wang Ferenc Szabo Fernando @@ -574,10 +609,8 @@ Fero Volar Ferran Rodenas Filipe Brandenburger Filipe Oliveira -fl0yd Flavio Castelli Flavio Crisciani -FLGMwt Florian Florian Klein Florian Maier @@ -586,7 +619,6 @@ Florian Weingarten Florin Asavoaie Florin Patan fonglh -fortinux Foysal Iqbal Francesc Campoy Francis Chuang @@ -601,8 +633,7 @@ Frederick F. Kautz IV Frederik Loeffert Frederik Nordahl Jul Sabroe Freek Kalter -frosforever -fy2462 +Frieder Bluemle Félix Baylac-Jacqué Félix Cantournet Gabe Rosenhouse @@ -629,7 +660,8 @@ Georgi Hristozov Gereon Frey German DZ Gert van Valkenhoef -Gerwim +Gerwim Feiken +Ghislain Bourgeois Giampaolo Mancini Gianluca Borello Gildas Cuisinier @@ -656,6 +688,7 @@ Guilherme Salgado Guillaume Dufour Guillaume J. Charmes guoxiuyan +Guri Gurjeet Singh Guruprasad Gustav Sinder @@ -673,11 +706,13 @@ Harry Zhang Harshal Patil Harshal Patil He Simei +He Xiaoxi He Xin heartlock <21521209@zju.edu.cn> Hector Castro Helen Xie Henning Sprang +Hiroshi Hatake Hobofan Hollie Teal Hong Xu @@ -708,11 +743,12 @@ Iavael Icaro Seara Ignacio Capurro Igor Dolzhikov +Igor Karpovich Iliana Weller Ilkka Laukkanen Ilya Dmitrichenko Ilya Gusev -ILYA Khlopotov +Ilya Khlopotov imre Fitos inglesp Ingo Gottwald @@ -722,14 +758,17 @@ Isao Jonas Ivan Babrou Ivan Fraixedes Ivan Grcic -Ivan Markin +Ivan Markin J Bruni J. Nunn Jack Danger Canty +Jack Laxson Jacob Atzen Jacob Edelman Jacob Tomlinson +Jacob Vallejo Jacob Wen +Jaivish Kothari Jake Champlin Jake Moshenko Jake Sanders @@ -746,7 +785,7 @@ James Mills James Nesbitt James Nugent James Turnbull -Jamie Hannaford +Jamie Hannaford Jamshid Afshar Jan Keromnes Jan Koprowski @@ -756,7 +795,6 @@ Jan-Gerd Tenberge Jan-Jaap Driessen Jana Radhakrishnan Jannick Fahlbusch -Janonymous Januar Wayong Jared Biel Jared Hocutt @@ -785,7 +823,9 @@ Jean-Christophe Berthon Jean-Paul Calderone Jean-Pierre Huynh Jean-Tiare Le Bigot +Jeeva S. Chelladhurai Jeff Anderson +Jeff Hajewski Jeff Johnston Jeff Lindsay Jeff Mickey @@ -803,17 +843,17 @@ Jeremy Price Jeremy Qian Jeremy Unruh Jeremy Yallop +Jeroen Franse Jeroen Jacobs Jesse Dearing Jesse Dubay Jessica Frazelle Jezeniel Zapanta -jgeiger Jhon Honce Ji.Zhilong Jian Zhang -jianbosun Jie Luo +Jihyun Hwang Jilles Oldenbeuving Jim Alateras Jim Galasyn @@ -840,6 +880,7 @@ Joel Friedly Joel Handwell Joel Hansson Joel Wurtz +Joey Geiger Joey Geiger Joey Gibson Joffrey F @@ -864,11 +905,13 @@ John V. Martinez John Warwick John Willis Jon Johnson +Jon Surrell Jon Wedaman Jonas Pfenniger Jonathan A. Sternberg Jonathan Boulle Jonathan Camp +Jonathan Choy Jonathan Dowland Jonathan Lebon Jonathan Lomas @@ -880,10 +923,11 @@ Jonathan Stoppani Jonh Wendell Joni Sar Joost Cassee -Jordan Jordan Arentsen +Jordan Jennings Jordan Sissel Jorge Marin +Jorit Kleine-Möllhoff Jose Diaz-Gonzalez Joseph Anthony Pasquale Holsten Joseph Hager @@ -891,6 +935,7 @@ Joseph Kern Joseph Rothrock Josh Josh Bodah +Josh Bonczkowski Josh Chorlton Josh Eveleth Josh Hawn @@ -900,9 +945,8 @@ Josh Soref Josh Wilson Josiah Kiehl José Tomás Albornoz +Joyce Jang JP -jrabbit -jroenf Julian Taylor Julien Barbier Julien Bisconti @@ -927,9 +971,9 @@ Jérôme Petazzoni Jörg Thalheim K. Heller Kai Blin -Kai Qiang Wu(Kennan) +Kai Qiang Wu (Kennan) Kamil Domański -kamjar gerami +Kamjar Gerami Kanstantsin Shautsou Kara Alexandra Karan Lyons @@ -937,7 +981,9 @@ Kareem Khazem kargakis Karl Grzeszczak Karol Duleba +Karthik Karanth Karthik Nayak +Kate Heddleston Katie McLaughlin Kato Kazuyoshi Katrina Owen @@ -963,12 +1009,12 @@ Kevin J. Lynagh Kevin Jing Qiu Kevin Kern Kevin Menard +Kevin Meredith Kevin P. Kucharczyk Kevin Richardson Kevin Shi Kevin Wallace Kevin Yap -kevinmeredith Keyvan Fatehi kies Kim BKC Carlbacker @@ -976,7 +1022,6 @@ Kim Eik Kimbro Staken Kir Kolyshkin Kiran Gangadharan -Kirill Kolyshkin Kirill SIbirev knappe Kohei Tsuruta @@ -1025,6 +1070,7 @@ Levi Gross Lewis Daly Lewis Marshall Lewis Peckover +Li Yi Liam Macgillavry Liana Lo Liang Mingqiang @@ -1050,12 +1096,13 @@ longliqiang88 <394564827@qq.com> Lorenz Leutgeb Lorenzo Fontana Louis Opter -Luca Favatella +Luca Favatella Luca Marturana Luca Orlandi Luca-Bogdan Grigorescu Lucas Chan Lucas Chi +Lucas Molas Luciano Mores Luis Martínez de Bartolomé Izquierdo Luiz Svoboda @@ -1081,17 +1128,20 @@ Manfred Zabarauskas Manjunath A Kumatagi Mansi Nahar Manuel Meurer +Manuel Rüger Manuel Woelker mapk0y Marc Abramowitz Marc Kuo Marc Tamsky Marcel Edmund Franke +Marcelo Horacio Fortino Marcelo Salazar Marco Hennings Marcus Cobden Marcus Farkas Marcus Linke +Marcus Martins Marcus Ramberg Marek Goldmann Marian Marinov @@ -1104,6 +1154,7 @@ Mark Allen Mark McGranaghan Mark McKinstry Mark Milstein +Mark Oates Mark Parker Mark West Markan Patel @@ -1119,10 +1170,12 @@ Martin Mosegaard Amdisen Martin Redmond Mary Anthony Masahito Zembutsu +Masato Ohba Masayuki Morita Mason Malone Mateusz Sulima Mathias Monnerville +Mathieu Champlon Mathieu Le Marec - Pasquet Mathieu Parent Matt Apperson @@ -1133,6 +1186,7 @@ Matt Hoyle Matt McCormick Matt Moore Matt Richardson +Matt Rickard Matt Robenolt Matt Schurenko Matt Williams @@ -1178,6 +1232,7 @@ Michael Huettermann Michael Irwin Michael Käufl Michael Neale +Michael Nussbaum Michael Prokop Michael Scharf Michael Spetsiotis @@ -1192,6 +1247,7 @@ Michal Minář Michal Wieczorek Michaël Pailloncy Michał Czeraszkiewicz +Michał Gryko Michiel@unhosted Mickaël FORTUNATO Miguel Angel Fernández @@ -1204,9 +1260,11 @@ Mike Chelen Mike Danese Mike Dillon Mike Dougherty +Mike Estes Mike Gaffney Mike Goelzer Mike Leone +Mike Lundy Mike MacCana Mike Naberezny Mike Snitzer @@ -1219,6 +1277,7 @@ mingqing Mingzhen Feng Misty Stanley-Jones Mitch Capper +Mizuki Urushida mlarcher Mohammad Banikazemi Mohammed Aaqib Ansari @@ -1262,20 +1321,22 @@ Neyazul Haque Nghia Tran Niall O'Higgins Nicholas E. Rabenau -nick Nick DeCoursin Nick Irvine +Nick Neisen Nick Parker Nick Payne +Nick Russo Nick Stenning Nick Stinemates NickrenREN Nicola Kabar -Nicolas Borboën -Nicolas De loof +Nicolas Borboën +Nicolas De Loof Nicolas Dudebout Nicolas Goy Nicolas Kaiser +Nicolas Sterchele Nicolás Hock Isaza Nigel Poulton Nik Nyby @@ -1286,7 +1347,9 @@ Nikolay Milovanov Nirmal Mehta Nishant Totla NIWA Hideyuki +Noah Meyerhans Noah Treuhaft +NobodyOnSE noducks Nolan Darilek nponeccop @@ -1294,8 +1357,6 @@ Nuutti Kotivuori nzwsch O.S. Tezer objectified -OddBloke -odk- Oguz Bilgic Oh Jinkyun Ohad Schneider @@ -1318,6 +1379,7 @@ Patrick Böänziger Patrick Devine Patrick Hemmer Patrick Stapleton +Patrik Cyvoct pattichen Paul paul @@ -1335,6 +1397,7 @@ Paul Nasrat Paul Weaver Paulo Ribeiro Pavel Lobashov +Pavel Pletenev Pavel Pospisil Pavel Sutyrin Pavel Tikhomirov @@ -1388,10 +1451,10 @@ Pradip Dhara Prasanna Gautam Pratik Karki Prayag Verma +Priya Wadhwa Przemek Hejman Pure White pysqz -qhuang Qiang Huang Qinglan Peng qudongfang @@ -1412,7 +1475,7 @@ Ralph Bean Ramkumar Ramachandra Ramon Brooker Ramon van Alteren -Ray Tsang +Ray Tsang ReadmeCritic Recursive Madman Reficul @@ -1422,6 +1485,7 @@ Remy Suen Renato Riccieri Santos Zannon Renaud Gaubert Rhys Hiltner +Ri Xu Ricardo N Feliciano Rich Moyse Rich Seymour @@ -1470,7 +1534,6 @@ Roman Strashkin Ron Smits Ron Williams root -root root root root @@ -1493,6 +1556,8 @@ Ryan Liu Ryan McLaughlin Ryan O'Donnell Ryan Seto +Ryan Simmen +Ryan Stelly Ryan Thomas Ryan Trauntvein Ryan Wallner @@ -1506,7 +1571,7 @@ Sabin Basyal Sachin Joshi Sagar Hani Sainath Grandhi -sakeven +Sakeven Jiang Sally O'Malley Sam Abed Sam Alba @@ -1526,6 +1591,7 @@ Sankar சங்கர் Sanket Saurav Santhosh Manohar sapphiredev +Sargun Dhillon Sascha Andres Satnam Singh Satoshi Amemiya @@ -1569,6 +1635,7 @@ Shengbo Song Shev Yan Shih-Yuan Lee Shijiang Wei +Shijun Qin Shishir Mahajan Shoubhik Bose Shourya Sarcar @@ -1576,6 +1643,7 @@ shuai-z Shukui Yang Shuwei Hao Sian Lerk Lau +Sidhartha Mani sidharthamani Silas Sewell Silvan Jegen @@ -1608,6 +1676,7 @@ Stefan S. Stefan Scherer Stefan Staudenmeyer Stefan Weil +Stephan Spindler Stephen Crosby Stephen Day Stephen Drake @@ -1627,6 +1696,7 @@ Steven Taylor Subhajit Ghosh Sujith Haridasan Sun Gengze <690388648@qq.com> +Sun Jianbo Sunny Gogoi Suryakumar Sudar Sven Dowideit @@ -1641,7 +1711,7 @@ Tabakhase Tadej Janež TAGOMORI Satoshi tang0th -Tangi COLIN +Tangi Colin Tatsuki Sugiura Tatsushi Inagaki Taylor Jones @@ -1662,7 +1732,7 @@ Thomas Gazagnaire Thomas Grainger Thomas Hansen Thomas Leonard -Thomas LEVEIL +Thomas Léveil Thomas Orozco Thomas Riccardi Thomas Schroeter @@ -1744,6 +1814,7 @@ Tyler Brock Tzu-Jung Lee uhayate Ulysse Carion +Umesh Yadav Utz Bacher vagrant Vaidas Jablonskis @@ -1763,7 +1834,6 @@ Viktor Stanchev Viktor Vojnovski VinayRaghavanKS Vincent Batts -Vincent Bernat Vincent Bernat Vincent Demeester Vincent Giersch @@ -1783,11 +1853,12 @@ Vladimir Pouzanov Vladimir Rutsky Vladimir Varankin VladimirAus +Vlastimil Zeman Vojtech Vitek (V-Teq) waitingkuo Walter Leibbrandt Walter Stanish -WANG Chao +Wang Chao Wang Guoliang Wang Jie Wang Long @@ -1796,10 +1867,13 @@ Wang Xing Wang Yuexiao Ward Vandewege WarheadsSE +Wassim Dhif Wayne Chang Wayne Song +Weerasak Chongnguluam Wei Wu Wei-Ting Kuo +weipeng weiyan Weiyang Zhu Wen Cheng Ma @@ -1823,9 +1897,7 @@ William Martin William Riancho William Thurston WiseTrem -wlan0 Wolfgang Powisch -wonderflow Wonjun Kim xamyzhao Xianglin Gao @@ -1837,7 +1909,6 @@ xiekeyang Xinbo Weng Xinzi Zhou Xiuming Chen -xlgao-zju Xuecong Liao xuzhaokui Yahya @@ -1851,6 +1922,7 @@ Yanqiang Miao Yao Zaiyong Yassine Tijani Yasunori Mahata +Yazhong Liu Yestin Sun Yi EungJun Yibai Zhang @@ -1859,7 +1931,7 @@ Ying Li Yohei Ueda Yong Tang Yongzhi Pan -yorkie +Yosef Fertel You-Sheng Yang (楊有勝) Youcef YEKHLEF Yu Changchun @@ -1871,10 +1943,10 @@ Yuanhong Peng Yuhao Fang Yunxiang Huang Yurii Rashkovskii -yuzou +Yves Junqueira Zac Dover Zach Borboa -Zachary Jaffee +Zachary Jaffee Zain Memon Zaiste! Zane DeGraffenried @@ -1888,7 +1960,7 @@ zhangxianwei Zhenan Ye <21551168@zju.edu.cn> zhenghenghuo Zhenkun Bi -zhouhao +Zhou Hao Zhu Guihua Zhu Kunjia Zhuoyun Wei @@ -1898,6 +1970,7 @@ Ziming Dong ZJUshuaizhou <21551191@zju.edu.cn> zmarouf Zoltan Tombol +Zou Yu zqh Zuhayr Elahi Zunayed Ali @@ -1906,4 +1979,6 @@ Zunayed Ali Átila Camurça Alves 尹吉峰 徐俊杰 +慕陶 搏通 +黄艳红00139573 diff --git a/vendor/github.com/docker/docker/api/types/auth.go b/vendor/github.com/docker/docker/api/types/auth.go index 056af6b842..ddf15bb182 100644 --- a/vendor/github.com/docker/docker/api/types/auth.go +++ b/vendor/github.com/docker/docker/api/types/auth.go @@ -1,4 +1,4 @@ -package types +package types // import "github.com/docker/docker/api/types" // AuthConfig contains authorization information for connecting to a Registry type AuthConfig struct { diff --git a/vendor/github.com/docker/docker/api/types/blkiodev/blkio.go b/vendor/github.com/docker/docker/api/types/blkiodev/blkio.go index 931ae10ab1..bf3463b90e 100644 --- a/vendor/github.com/docker/docker/api/types/blkiodev/blkio.go +++ b/vendor/github.com/docker/docker/api/types/blkiodev/blkio.go @@ -1,4 +1,4 @@ -package blkiodev +package blkiodev // import "github.com/docker/docker/api/types/blkiodev" import "fmt" diff --git a/vendor/github.com/docker/docker/api/types/client.go b/vendor/github.com/docker/docker/api/types/client.go index 93ca428540..3df8d23368 100644 --- a/vendor/github.com/docker/docker/api/types/client.go +++ b/vendor/github.com/docker/docker/api/types/client.go @@ -1,4 +1,4 @@ -package types +package types // import "github.com/docker/docker/api/types" import ( "bufio" @@ -7,7 +7,7 @@ import ( "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" - units "github.com/docker/go-units" + "github.com/docker/go-units" ) // CheckpointCreateOptions holds parameters to create a checkpoint from a container @@ -181,8 +181,24 @@ type ImageBuildOptions struct { Target string SessionID string Platform string + // Version specifies the version of the unerlying builder to use + Version BuilderVersion + // BuildID is an optional identifier that can be passed together with the + // build request. The same identifier can be used to gracefully cancel the + // build with the cancel request. + BuildID string } +// BuilderVersion sets the version of underlying builder to use +type BuilderVersion string + +const ( + // BuilderV1 is the first generation builder in docker daemon + BuilderV1 BuilderVersion = "1" + // BuilderBuildKit is builder based on moby/buildkit project + BuilderBuildKit = "2" +) + // ImageBuildResponse holds information // returned by a server after building // an image. diff --git a/vendor/github.com/docker/docker/api/types/configs.go b/vendor/github.com/docker/docker/api/types/configs.go index 20c19f2132..f6537a27f2 100644 --- a/vendor/github.com/docker/docker/api/types/configs.go +++ b/vendor/github.com/docker/docker/api/types/configs.go @@ -1,4 +1,4 @@ -package types +package types // import "github.com/docker/docker/api/types" import ( "github.com/docker/docker/api/types/container" @@ -25,19 +25,6 @@ type ContainerRmConfig struct { ForceRemove, RemoveVolume, RemoveLink bool } -// ContainerCommitConfig contains build configs for commit operation, -// and is used when making a commit with the current state of the container. -type ContainerCommitConfig struct { - Pause bool - Repo string - Tag string - Author string - Comment string - // merge container config into commit config before commit - MergeConfigs bool - Config *container.Config -} - // ExecConfig is a small subset of the Config struct that holds the configuration // for the exec feature of docker. type ExecConfig struct { @@ -50,6 +37,7 @@ type ExecConfig struct { Detach bool // Execute in detach mode DetachKeys string // Escape keys for detach Env []string // Environment variables + WorkingDir string // Working directory Cmd []string // Execution commands and args } diff --git a/vendor/github.com/docker/docker/api/types/container/config.go b/vendor/github.com/docker/docker/api/types/container/config.go index 55a03fc981..89ad08c234 100644 --- a/vendor/github.com/docker/docker/api/types/container/config.go +++ b/vendor/github.com/docker/docker/api/types/container/config.go @@ -1,4 +1,4 @@ -package container +package container // import "github.com/docker/docker/api/types/container" import ( "time" diff --git a/vendor/github.com/docker/docker/api/types/container/container_changes.go b/vendor/github.com/docker/docker/api/types/container/container_changes.go index 767945a532..c909d6ca3e 100644 --- a/vendor/github.com/docker/docker/api/types/container/container_changes.go +++ b/vendor/github.com/docker/docker/api/types/container/container_changes.go @@ -7,7 +7,7 @@ package container // See hack/generate-swagger-api.sh // ---------------------------------------------------------------------------- -// ContainerChangeResponseItem container change response item +// ContainerChangeResponseItem change item in response to ContainerChanges operation // swagger:model ContainerChangeResponseItem type ContainerChangeResponseItem struct { diff --git a/vendor/github.com/docker/docker/api/types/container/container_create.go b/vendor/github.com/docker/docker/api/types/container/container_create.go index c95023b814..49efa0f2c0 100644 --- a/vendor/github.com/docker/docker/api/types/container/container_create.go +++ b/vendor/github.com/docker/docker/api/types/container/container_create.go @@ -7,7 +7,7 @@ package container // See hack/generate-swagger-api.sh // ---------------------------------------------------------------------------- -// ContainerCreateCreatedBody container create created body +// ContainerCreateCreatedBody OK response to ContainerCreate operation // swagger:model ContainerCreateCreatedBody type ContainerCreateCreatedBody struct { diff --git a/vendor/github.com/docker/docker/api/types/container/container_top.go b/vendor/github.com/docker/docker/api/types/container/container_top.go index 78bc37ee5e..ba41edcf3f 100644 --- a/vendor/github.com/docker/docker/api/types/container/container_top.go +++ b/vendor/github.com/docker/docker/api/types/container/container_top.go @@ -7,7 +7,7 @@ package container // See hack/generate-swagger-api.sh // ---------------------------------------------------------------------------- -// ContainerTopOKBody container top o k body +// ContainerTopOKBody OK response to ContainerTop operation // swagger:model ContainerTopOKBody type ContainerTopOKBody struct { diff --git a/vendor/github.com/docker/docker/api/types/container/container_update.go b/vendor/github.com/docker/docker/api/types/container/container_update.go index 2339366fbd..7630ae54cd 100644 --- a/vendor/github.com/docker/docker/api/types/container/container_update.go +++ b/vendor/github.com/docker/docker/api/types/container/container_update.go @@ -7,7 +7,7 @@ package container // See hack/generate-swagger-api.sh // ---------------------------------------------------------------------------- -// ContainerUpdateOKBody container update o k body +// ContainerUpdateOKBody OK response to ContainerUpdate operation // swagger:model ContainerUpdateOKBody type ContainerUpdateOKBody struct { diff --git a/vendor/github.com/docker/docker/api/types/container/container_wait.go b/vendor/github.com/docker/docker/api/types/container/container_wait.go index 47fb17578a..9e3910a6b4 100644 --- a/vendor/github.com/docker/docker/api/types/container/container_wait.go +++ b/vendor/github.com/docker/docker/api/types/container/container_wait.go @@ -15,7 +15,7 @@ type ContainerWaitOKBodyError struct { Message string `json:"Message,omitempty"` } -// ContainerWaitOKBody container wait o k body +// ContainerWaitOKBody OK response to ContainerWait operation // swagger:model ContainerWaitOKBody type ContainerWaitOKBody struct { diff --git a/vendor/github.com/docker/docker/api/types/container/host_config.go b/vendor/github.com/docker/docker/api/types/container/host_config.go index 568cdcca93..4ef26fa6c8 100644 --- a/vendor/github.com/docker/docker/api/types/container/host_config.go +++ b/vendor/github.com/docker/docker/api/types/container/host_config.go @@ -1,4 +1,4 @@ -package container +package container // import "github.com/docker/docker/api/types/container" import ( "strings" @@ -401,6 +401,12 @@ type HostConfig struct { // Mounts specs used by the container Mounts []mount.Mount `json:",omitempty"` + // MaskedPaths is the list of paths to be masked inside the container (this overrides the default set of paths) + MaskedPaths []string + + // ReadonlyPaths is the list of paths to be set as read-only inside the container (this overrides the default set of paths) + ReadonlyPaths []string + // Run a custom init inside the container, if null, use the daemon's configured settings Init *bool `json:",omitempty"` } diff --git a/vendor/github.com/docker/docker/api/types/container/hostconfig_unix.go b/vendor/github.com/docker/docker/api/types/container/hostconfig_unix.go index 2d664d1c96..cf6fdf4402 100644 --- a/vendor/github.com/docker/docker/api/types/container/hostconfig_unix.go +++ b/vendor/github.com/docker/docker/api/types/container/hostconfig_unix.go @@ -1,6 +1,6 @@ // +build !windows -package container +package container // import "github.com/docker/docker/api/types/container" // IsValid indicates if an isolation technology is valid func (i Isolation) IsValid() bool { diff --git a/vendor/github.com/docker/docker/api/types/container/hostconfig_windows.go b/vendor/github.com/docker/docker/api/types/container/hostconfig_windows.go index 3374d737f1..99f803a5bb 100644 --- a/vendor/github.com/docker/docker/api/types/container/hostconfig_windows.go +++ b/vendor/github.com/docker/docker/api/types/container/hostconfig_windows.go @@ -1,4 +1,4 @@ -package container +package container // import "github.com/docker/docker/api/types/container" // IsBridge indicates whether container uses the bridge network stack // in windows it is given the name NAT diff --git a/vendor/github.com/docker/docker/api/types/container/waitcondition.go b/vendor/github.com/docker/docker/api/types/container/waitcondition.go index 64820fe358..cd8311f99c 100644 --- a/vendor/github.com/docker/docker/api/types/container/waitcondition.go +++ b/vendor/github.com/docker/docker/api/types/container/waitcondition.go @@ -1,4 +1,4 @@ -package container +package container // import "github.com/docker/docker/api/types/container" // WaitCondition is a type used to specify a container state for which // to wait. diff --git a/vendor/github.com/docker/docker/api/types/filters/parse.go b/vendor/github.com/docker/docker/api/types/filters/parse.go index d45d0528fb..a41e3d8d96 100644 --- a/vendor/github.com/docker/docker/api/types/filters/parse.go +++ b/vendor/github.com/docker/docker/api/types/filters/parse.go @@ -1,7 +1,7 @@ /*Package filters provides tools for encoding a mapping of keys to a set of multiple values. */ -package filters +package filters // import "github.com/docker/docker/api/types/filters" import ( "encoding/json" diff --git a/vendor/github.com/docker/docker/api/types/mount/mount.go b/vendor/github.com/docker/docker/api/types/mount/mount.go index b7d133cd84..3fef974df8 100644 --- a/vendor/github.com/docker/docker/api/types/mount/mount.go +++ b/vendor/github.com/docker/docker/api/types/mount/mount.go @@ -1,4 +1,4 @@ -package mount +package mount // import "github.com/docker/docker/api/types/mount" import ( "os" diff --git a/vendor/github.com/docker/docker/api/types/network/network.go b/vendor/github.com/docker/docker/api/types/network/network.go index 7c7dbacc85..761d0b34f2 100644 --- a/vendor/github.com/docker/docker/api/types/network/network.go +++ b/vendor/github.com/docker/docker/api/types/network/network.go @@ -1,4 +1,4 @@ -package network +package network // import "github.com/docker/docker/api/types/network" // Address represents an IP address type Address struct { diff --git a/vendor/github.com/docker/docker/api/types/plugin.go b/vendor/github.com/docker/docker/api/types/plugin.go index cab333e01a..abae48b9ab 100644 --- a/vendor/github.com/docker/docker/api/types/plugin.go +++ b/vendor/github.com/docker/docker/api/types/plugin.go @@ -121,6 +121,9 @@ type PluginConfigArgs struct { // swagger:model PluginConfigInterface type PluginConfigInterface struct { + // Protocol to use for clients connecting to the plugin. + ProtocolScheme string `json:"ProtocolScheme,omitempty"` + // socket // Required: true Socket string `json:"Socket"` diff --git a/vendor/github.com/docker/docker/api/types/plugin_responses.go b/vendor/github.com/docker/docker/api/types/plugin_responses.go index 18f743fcde..60d1fb5ad8 100644 --- a/vendor/github.com/docker/docker/api/types/plugin_responses.go +++ b/vendor/github.com/docker/docker/api/types/plugin_responses.go @@ -1,4 +1,4 @@ -package types +package types // import "github.com/docker/docker/api/types" import ( "encoding/json" diff --git a/vendor/github.com/docker/docker/api/types/port.go b/vendor/github.com/docker/docker/api/types/port.go index ad52d46d56..d91234744c 100644 --- a/vendor/github.com/docker/docker/api/types/port.go +++ b/vendor/github.com/docker/docker/api/types/port.go @@ -7,7 +7,7 @@ package types // swagger:model Port type Port struct { - // IP + // Host IP address that the container's port is mapped to IP string `json:"IP,omitempty"` // Port on the container diff --git a/vendor/github.com/docker/docker/api/types/registry/authenticate.go b/vendor/github.com/docker/docker/api/types/registry/authenticate.go index 42cac4430a..f0a2113e40 100644 --- a/vendor/github.com/docker/docker/api/types/registry/authenticate.go +++ b/vendor/github.com/docker/docker/api/types/registry/authenticate.go @@ -1,4 +1,4 @@ -package registry +package registry // import "github.com/docker/docker/api/types/registry" // ---------------------------------------------------------------------------- // DO NOT EDIT THIS FILE diff --git a/vendor/github.com/docker/docker/api/types/registry/registry.go b/vendor/github.com/docker/docker/api/types/registry/registry.go index b98a943a13..8789ad3b32 100644 --- a/vendor/github.com/docker/docker/api/types/registry/registry.go +++ b/vendor/github.com/docker/docker/api/types/registry/registry.go @@ -1,4 +1,4 @@ -package registry +package registry // import "github.com/docker/docker/api/types/registry" import ( "encoding/json" diff --git a/vendor/github.com/docker/docker/api/types/seccomp.go b/vendor/github.com/docker/docker/api/types/seccomp.go index 7d62c9a43f..67a41e1a89 100644 --- a/vendor/github.com/docker/docker/api/types/seccomp.go +++ b/vendor/github.com/docker/docker/api/types/seccomp.go @@ -1,4 +1,4 @@ -package types +package types // import "github.com/docker/docker/api/types" // Seccomp represents the config for a seccomp profile for syscall restriction. type Seccomp struct { diff --git a/vendor/github.com/docker/docker/api/types/stats.go b/vendor/github.com/docker/docker/api/types/stats.go index 7ca76a5b63..60175c0613 100644 --- a/vendor/github.com/docker/docker/api/types/stats.go +++ b/vendor/github.com/docker/docker/api/types/stats.go @@ -1,6 +1,6 @@ // Package types is used for API stability in the types and response to the // consumers of the API stats endpoint. -package types +package types // import "github.com/docker/docker/api/types" import "time" diff --git a/vendor/github.com/docker/docker/api/types/strslice/strslice.go b/vendor/github.com/docker/docker/api/types/strslice/strslice.go index bad493fb89..82921cebc1 100644 --- a/vendor/github.com/docker/docker/api/types/strslice/strslice.go +++ b/vendor/github.com/docker/docker/api/types/strslice/strslice.go @@ -1,4 +1,4 @@ -package strslice +package strslice // import "github.com/docker/docker/api/types/strslice" import "encoding/json" diff --git a/vendor/github.com/docker/docker/api/types/swarm/common.go b/vendor/github.com/docker/docker/api/types/swarm/common.go index 2834cf2022..ef020f458b 100644 --- a/vendor/github.com/docker/docker/api/types/swarm/common.go +++ b/vendor/github.com/docker/docker/api/types/swarm/common.go @@ -1,4 +1,4 @@ -package swarm +package swarm // import "github.com/docker/docker/api/types/swarm" import "time" diff --git a/vendor/github.com/docker/docker/api/types/swarm/config.go b/vendor/github.com/docker/docker/api/types/swarm/config.go index 0fb021ce92..a1555cf43e 100644 --- a/vendor/github.com/docker/docker/api/types/swarm/config.go +++ b/vendor/github.com/docker/docker/api/types/swarm/config.go @@ -1,4 +1,4 @@ -package swarm +package swarm // import "github.com/docker/docker/api/types/swarm" import "os" @@ -13,6 +13,10 @@ type Config struct { type ConfigSpec struct { Annotations Data []byte `json:",omitempty"` + + // Templating controls whether and how to evaluate the config payload as + // a template. If it is not set, no templating is used. + Templating *Driver `json:",omitempty"` } // ConfigReferenceFileTarget is a file target in a config reference diff --git a/vendor/github.com/docker/docker/api/types/swarm/container.go b/vendor/github.com/docker/docker/api/types/swarm/container.go index 734236c4b0..151211ff5a 100644 --- a/vendor/github.com/docker/docker/api/types/swarm/container.go +++ b/vendor/github.com/docker/docker/api/types/swarm/container.go @@ -1,4 +1,4 @@ -package swarm +package swarm // import "github.com/docker/docker/api/types/swarm" import ( "time" @@ -55,6 +55,7 @@ type ContainerSpec struct { User string `json:",omitempty"` Groups []string `json:",omitempty"` Privileges *Privileges `json:",omitempty"` + Init *bool `json:",omitempty"` StopSignal string `json:",omitempty"` TTY bool `json:",omitempty"` OpenStdin bool `json:",omitempty"` diff --git a/vendor/github.com/docker/docker/api/types/swarm/network.go b/vendor/github.com/docker/docker/api/types/swarm/network.go index 97c484e14c..98ef3284d1 100644 --- a/vendor/github.com/docker/docker/api/types/swarm/network.go +++ b/vendor/github.com/docker/docker/api/types/swarm/network.go @@ -1,4 +1,4 @@ -package swarm +package swarm // import "github.com/docker/docker/api/types/swarm" import ( "github.com/docker/docker/api/types/network" @@ -62,6 +62,8 @@ const ( PortConfigProtocolTCP PortConfigProtocol = "tcp" // PortConfigProtocolUDP UDP PortConfigProtocolUDP PortConfigProtocol = "udp" + // PortConfigProtocolSCTP SCTP + PortConfigProtocolSCTP PortConfigProtocol = "sctp" ) // EndpointVirtualIP represents the virtual ip of a port. diff --git a/vendor/github.com/docker/docker/api/types/swarm/node.go b/vendor/github.com/docker/docker/api/types/swarm/node.go index 28c6851e9c..1e30f5fa10 100644 --- a/vendor/github.com/docker/docker/api/types/swarm/node.go +++ b/vendor/github.com/docker/docker/api/types/swarm/node.go @@ -1,4 +1,4 @@ -package swarm +package swarm // import "github.com/docker/docker/api/types/swarm" // Node represents a node. type Node struct { diff --git a/vendor/github.com/docker/docker/api/types/swarm/runtime.go b/vendor/github.com/docker/docker/api/types/swarm/runtime.go index c4c731dc82..0c77403ccf 100644 --- a/vendor/github.com/docker/docker/api/types/swarm/runtime.go +++ b/vendor/github.com/docker/docker/api/types/swarm/runtime.go @@ -1,4 +1,4 @@ -package swarm +package swarm // import "github.com/docker/docker/api/types/swarm" // RuntimeType is the type of runtime used for the TaskSpec type RuntimeType string @@ -11,9 +11,17 @@ const ( RuntimeContainer RuntimeType = "container" // RuntimePlugin is the plugin based runtime RuntimePlugin RuntimeType = "plugin" + // RuntimeNetworkAttachment is the network attachment runtime + RuntimeNetworkAttachment RuntimeType = "attachment" // RuntimeURLContainer is the proto url for the container type RuntimeURLContainer RuntimeURL = "types.docker.com/RuntimeContainer" // RuntimeURLPlugin is the proto url for the plugin type RuntimeURLPlugin RuntimeURL = "types.docker.com/RuntimePlugin" ) + +// NetworkAttachmentSpec represents the runtime spec type for network +// attachment tasks +type NetworkAttachmentSpec struct { + ContainerID string +} diff --git a/vendor/github.com/docker/docker/api/types/swarm/runtime/gen.go b/vendor/github.com/docker/docker/api/types/swarm/runtime/gen.go index 47ae234ef3..98c2806c31 100644 --- a/vendor/github.com/docker/docker/api/types/swarm/runtime/gen.go +++ b/vendor/github.com/docker/docker/api/types/swarm/runtime/gen.go @@ -1,3 +1,3 @@ //go:generate protoc -I . --gogofast_out=import_path=github.com/docker/docker/api/types/swarm/runtime:. plugin.proto -package runtime +package runtime // import "github.com/docker/docker/api/types/swarm/runtime" diff --git a/vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.proto b/vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.proto index 06eb7ba650..6d63b7783f 100644 --- a/vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.proto +++ b/vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.proto @@ -1,5 +1,7 @@ syntax = "proto3"; +option go_package = "github.com/docker/docker/api/types/swarm/runtime;runtime"; + // PluginSpec defines the base payload which clients can specify for creating // a service with the plugin runtime. message PluginSpec { diff --git a/vendor/github.com/docker/docker/api/types/swarm/secret.go b/vendor/github.com/docker/docker/api/types/swarm/secret.go index f9b1e92669..d5213ec981 100644 --- a/vendor/github.com/docker/docker/api/types/swarm/secret.go +++ b/vendor/github.com/docker/docker/api/types/swarm/secret.go @@ -1,4 +1,4 @@ -package swarm +package swarm // import "github.com/docker/docker/api/types/swarm" import "os" @@ -14,6 +14,10 @@ type SecretSpec struct { Annotations Data []byte `json:",omitempty"` Driver *Driver `json:",omitempty"` // name of the secrets driver used to fetch the secret's value from an external secret store + + // Templating controls whether and how to evaluate the secret payload as + // a template. If it is not set, no templating is used. + Templating *Driver `json:",omitempty"` } // SecretReferenceFileTarget is a file target in a secret reference diff --git a/vendor/github.com/docker/docker/api/types/swarm/service.go b/vendor/github.com/docker/docker/api/types/swarm/service.go index fa31a7ec86..abf192e759 100644 --- a/vendor/github.com/docker/docker/api/types/swarm/service.go +++ b/vendor/github.com/docker/docker/api/types/swarm/service.go @@ -1,4 +1,4 @@ -package swarm +package swarm // import "github.com/docker/docker/api/types/swarm" import "time" diff --git a/vendor/github.com/docker/docker/api/types/swarm/swarm.go b/vendor/github.com/docker/docker/api/types/swarm/swarm.go index b65fa86dac..1b111d725b 100644 --- a/vendor/github.com/docker/docker/api/types/swarm/swarm.go +++ b/vendor/github.com/docker/docker/api/types/swarm/swarm.go @@ -1,4 +1,4 @@ -package swarm +package swarm // import "github.com/docker/docker/api/types/swarm" import "time" diff --git a/vendor/github.com/docker/docker/api/types/swarm/task.go b/vendor/github.com/docker/docker/api/types/swarm/task.go index ff11b07e74..b35605d12f 100644 --- a/vendor/github.com/docker/docker/api/types/swarm/task.go +++ b/vendor/github.com/docker/docker/api/types/swarm/task.go @@ -1,4 +1,4 @@ -package swarm +package swarm // import "github.com/docker/docker/api/types/swarm" import ( "time" @@ -36,6 +36,10 @@ const ( TaskStateFailed TaskState = "failed" // TaskStateRejected REJECTED TaskStateRejected TaskState = "rejected" + // TaskStateRemove REMOVE + TaskStateRemove TaskState = "remove" + // TaskStateOrphaned ORPHANED + TaskStateOrphaned TaskState = "orphaned" ) // Task represents a task. @@ -56,10 +60,13 @@ type Task struct { // TaskSpec represents the spec of a task. type TaskSpec struct { - // ContainerSpec and PluginSpec are mutually exclusive. - // PluginSpec will only be used when the `Runtime` field is set to `plugin` - ContainerSpec *ContainerSpec `json:",omitempty"` - PluginSpec *runtime.PluginSpec `json:",omitempty"` + // ContainerSpec, NetworkAttachmentSpec, and PluginSpec are mutually exclusive. + // PluginSpec is only used when the `Runtime` field is set to `plugin` + // NetworkAttachmentSpec is used if the `Runtime` field is set to + // `attachment`. + ContainerSpec *ContainerSpec `json:",omitempty"` + PluginSpec *runtime.PluginSpec `json:",omitempty"` + NetworkAttachmentSpec *NetworkAttachmentSpec `json:",omitempty"` Resources *ResourceRequirements `json:",omitempty"` RestartPolicy *RestartPolicy `json:",omitempty"` @@ -162,19 +169,19 @@ const ( // TaskStatus represents the status of a task. type TaskStatus struct { - Timestamp time.Time `json:",omitempty"` - State TaskState `json:",omitempty"` - Message string `json:",omitempty"` - Err string `json:",omitempty"` - ContainerStatus ContainerStatus `json:",omitempty"` - PortStatus PortStatus `json:",omitempty"` + Timestamp time.Time `json:",omitempty"` + State TaskState `json:",omitempty"` + Message string `json:",omitempty"` + Err string `json:",omitempty"` + ContainerStatus *ContainerStatus `json:",omitempty"` + PortStatus PortStatus `json:",omitempty"` } // ContainerStatus represents the status of a container. type ContainerStatus struct { - ContainerID string `json:",omitempty"` - PID int `json:",omitempty"` - ExitCode int `json:",omitempty"` + ContainerID string + PID int + ExitCode int } // PortStatus represents the port status of a task's host ports whose diff --git a/vendor/github.com/docker/docker/api/types/types.go b/vendor/github.com/docker/docker/api/types/types.go index f7ac772971..06c0ca3a69 100644 --- a/vendor/github.com/docker/docker/api/types/types.go +++ b/vendor/github.com/docker/docker/api/types/types.go @@ -1,4 +1,4 @@ -package types +package types // import "github.com/docker/docker/api/types" import ( "errors" @@ -107,9 +107,21 @@ type Ping struct { Experimental bool } +// ComponentVersion describes the version information for a specific component. +type ComponentVersion struct { + Name string + Version string + Details map[string]string `json:",omitempty"` +} + // Version contains response of Engine API: // GET "/version" type Version struct { + Platform struct{ Name string } `json:",omitempty"` + Components []ComponentVersion `json:",omitempty"` + + // The following fields are deprecated, they relate to the Engine component and are kept for backwards compatibility + Version string APIVersion string `json:"ApiVersion"` MinAPIVersion string `json:"MinAPIVersion,omitempty"` @@ -500,7 +512,8 @@ type DiskUsage struct { Images []*ImageSummary Containers []*Container Volumes []*Volume - BuilderSize int64 + BuildCache []*BuildCache + BuilderSize int64 // deprecated } // ContainersPruneReport contains the response for Engine API: @@ -573,3 +586,17 @@ type PushResult struct { type BuildResult struct { ID string } + +// BuildCache contains information about a build cache record +type BuildCache struct { + ID string + Mutable bool + InUse bool + Size int64 + + CreatedAt time.Time + LastUsedAt *time.Time + UsageCount int + Parent string + Description string +} diff --git a/vendor/github.com/docker/docker/api/types/versions/compare.go b/vendor/github.com/docker/docker/api/types/versions/compare.go index 611d4fed66..8ccb0aa92e 100644 --- a/vendor/github.com/docker/docker/api/types/versions/compare.go +++ b/vendor/github.com/docker/docker/api/types/versions/compare.go @@ -1,4 +1,4 @@ -package versions +package versions // import "github.com/docker/docker/api/types/versions" import ( "strconv" diff --git a/vendor/github.com/docker/docker/contrib/selinux-fedora-24/docker-engine-selinux/LICENSE b/vendor/github.com/docker/docker/contrib/selinux-fedora-24/docker-engine-selinux/LICENSE deleted file mode 100644 index d511905c16..0000000000 --- a/vendor/github.com/docker/docker/contrib/selinux-fedora-24/docker-engine-selinux/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/vendor/github.com/docker/docker/contrib/selinux-oraclelinux-7/docker-engine-selinux/LICENSE b/vendor/github.com/docker/docker/contrib/selinux-oraclelinux-7/docker-engine-selinux/LICENSE deleted file mode 100644 index 5b6e7c66c2..0000000000 --- a/vendor/github.com/docker/docker/contrib/selinux-oraclelinux-7/docker-engine-selinux/LICENSE +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/vendor/github.com/docker/docker/opts/address_pools.go b/vendor/github.com/docker/docker/opts/address_pools.go new file mode 100644 index 0000000000..9b27a62853 --- /dev/null +++ b/vendor/github.com/docker/docker/opts/address_pools.go @@ -0,0 +1,84 @@ +package opts + +import ( + "encoding/csv" + "encoding/json" + "fmt" + "strconv" + "strings" + + types "github.com/docker/libnetwork/ipamutils" +) + +// PoolsOpt is a Value type for parsing the default address pools definitions +type PoolsOpt struct { + values []*types.NetworkToSplit +} + +// UnmarshalJSON fills values structure info from JSON input +func (p *PoolsOpt) UnmarshalJSON(raw []byte) error { + return json.Unmarshal(raw, &(p.values)) +} + +// Set predefined pools +func (p *PoolsOpt) Set(value string) error { + csvReader := csv.NewReader(strings.NewReader(value)) + fields, err := csvReader.Read() + if err != nil { + return err + } + + poolsDef := types.NetworkToSplit{} + + for _, field := range fields { + parts := strings.SplitN(field, "=", 2) + if len(parts) != 2 { + return fmt.Errorf("invalid field '%s' must be a key=value pair", field) + } + + key := strings.ToLower(parts[0]) + value := strings.ToLower(parts[1]) + + switch key { + case "base": + poolsDef.Base = value + case "size": + size, err := strconv.Atoi(value) + if err != nil { + return fmt.Errorf("invalid size value: %q (must be integer): %v", value, err) + } + poolsDef.Size = size + default: + return fmt.Errorf("unexpected key '%s' in '%s'", key, field) + } + } + + p.values = append(p.values, &poolsDef) + + return nil +} + +// Type returns the type of this option +func (p *PoolsOpt) Type() string { + return "pool-options" +} + +// String returns a string repr of this option +func (p *PoolsOpt) String() string { + var pools []string + for _, pool := range p.values { + repr := fmt.Sprintf("%s %d", pool.Base, pool.Size) + pools = append(pools, repr) + } + return strings.Join(pools, ", ") +} + +// Value returns the mounts +func (p *PoolsOpt) Value() []*types.NetworkToSplit { + return p.values +} + +// Name returns the flag name of this option +func (p *PoolsOpt) Name() string { + return "default-address-pools" +} diff --git a/vendor/github.com/docker/docker/opts/env.go b/vendor/github.com/docker/docker/opts/env.go index 4fbd470bcf..f6e5e9074d 100644 --- a/vendor/github.com/docker/docker/opts/env.go +++ b/vendor/github.com/docker/docker/opts/env.go @@ -1,4 +1,4 @@ -package opts +package opts // import "github.com/docker/docker/opts" import ( "fmt" diff --git a/vendor/github.com/docker/docker/opts/hosts.go b/vendor/github.com/docker/docker/opts/hosts.go index f46b8ee711..2adf4211d5 100644 --- a/vendor/github.com/docker/docker/opts/hosts.go +++ b/vendor/github.com/docker/docker/opts/hosts.go @@ -1,4 +1,4 @@ -package opts +package opts // import "github.com/docker/docker/opts" import ( "fmt" diff --git a/vendor/github.com/docker/docker/opts/hosts_unix.go b/vendor/github.com/docker/docker/opts/hosts_unix.go index 611407a9d9..9d5bb64565 100644 --- a/vendor/github.com/docker/docker/opts/hosts_unix.go +++ b/vendor/github.com/docker/docker/opts/hosts_unix.go @@ -1,6 +1,6 @@ // +build !windows -package opts +package opts // import "github.com/docker/docker/opts" import "fmt" diff --git a/vendor/github.com/docker/docker/opts/hosts_windows.go b/vendor/github.com/docker/docker/opts/hosts_windows.go index 7c239e00f1..906eba53ee 100644 --- a/vendor/github.com/docker/docker/opts/hosts_windows.go +++ b/vendor/github.com/docker/docker/opts/hosts_windows.go @@ -1,6 +1,4 @@ -// +build windows - -package opts +package opts // import "github.com/docker/docker/opts" // DefaultHost constant defines the default host string used by docker on Windows var DefaultHost = "npipe://" + DefaultNamedPipe diff --git a/vendor/github.com/docker/docker/opts/ip.go b/vendor/github.com/docker/docker/opts/ip.go index 1095063977..cfbff3a9fd 100644 --- a/vendor/github.com/docker/docker/opts/ip.go +++ b/vendor/github.com/docker/docker/opts/ip.go @@ -1,4 +1,4 @@ -package opts +package opts // import "github.com/docker/docker/opts" import ( "fmt" diff --git a/vendor/github.com/docker/docker/opts/opts.go b/vendor/github.com/docker/docker/opts/opts.go index a2cc5e33b1..de8aacb806 100644 --- a/vendor/github.com/docker/docker/opts/opts.go +++ b/vendor/github.com/docker/docker/opts/opts.go @@ -1,4 +1,4 @@ -package opts +package opts // import "github.com/docker/docker/opts" import ( "fmt" @@ -7,7 +7,7 @@ import ( "regexp" "strings" - units "github.com/docker/go-units" + "github.com/docker/go-units" ) var ( @@ -52,7 +52,7 @@ func (opts *ListOpts) Set(value string) error { } value = v } - (*opts.values) = append((*opts.values), value) + *opts.values = append(*opts.values, value) return nil } @@ -60,7 +60,7 @@ func (opts *ListOpts) Set(value string) error { func (opts *ListOpts) Delete(key string) { for i, k := range *opts.values { if k == key { - (*opts.values) = append((*opts.values)[:i], (*opts.values)[i+1:]...) + *opts.values = append((*opts.values)[:i], (*opts.values)[i+1:]...) return } } @@ -78,7 +78,7 @@ func (opts *ListOpts) GetMap() map[string]struct{} { // GetAll returns the values of slice. func (opts *ListOpts) GetAll() []string { - return (*opts.values) + return *opts.values } // GetAllOrEmpty returns the values of the slice @@ -103,7 +103,7 @@ func (opts *ListOpts) Get(key string) bool { // Len returns the amount of element in the slice. func (opts *ListOpts) Len() int { - return len((*opts.values)) + return len(*opts.values) } // Type returns a string name for this Option type diff --git a/vendor/github.com/docker/docker/opts/opts_unix.go b/vendor/github.com/docker/docker/opts/opts_unix.go index 2766a43a08..0c32367cb2 100644 --- a/vendor/github.com/docker/docker/opts/opts_unix.go +++ b/vendor/github.com/docker/docker/opts/opts_unix.go @@ -1,6 +1,6 @@ // +build !windows -package opts +package opts // import "github.com/docker/docker/opts" // DefaultHTTPHost Default HTTP Host used if only port is provided to -H flag e.g. dockerd -H tcp://:8080 const DefaultHTTPHost = "localhost" diff --git a/vendor/github.com/docker/docker/opts/opts_windows.go b/vendor/github.com/docker/docker/opts/opts_windows.go index 98b7251a9e..0e1b6c6d18 100644 --- a/vendor/github.com/docker/docker/opts/opts_windows.go +++ b/vendor/github.com/docker/docker/opts/opts_windows.go @@ -1,4 +1,4 @@ -package opts +package opts // import "github.com/docker/docker/opts" // TODO Windows. Identify bug in GOLang 1.5.1+ and/or Windows Server 2016 TP5. // @jhowardmsft, @swernli. diff --git a/vendor/github.com/docker/docker/opts/quotedstring.go b/vendor/github.com/docker/docker/opts/quotedstring.go index 09c68a5261..6c889070e8 100644 --- a/vendor/github.com/docker/docker/opts/quotedstring.go +++ b/vendor/github.com/docker/docker/opts/quotedstring.go @@ -1,4 +1,4 @@ -package opts +package opts // import "github.com/docker/docker/opts" // QuotedString is a string that may have extra quotes around the value. The // quotes are stripped from the value. diff --git a/vendor/github.com/docker/docker/opts/runtime.go b/vendor/github.com/docker/docker/opts/runtime.go index 4361b3ce09..4b9babf0a5 100644 --- a/vendor/github.com/docker/docker/opts/runtime.go +++ b/vendor/github.com/docker/docker/opts/runtime.go @@ -1,4 +1,4 @@ -package opts +package opts // import "github.com/docker/docker/opts" import ( "fmt" diff --git a/vendor/github.com/docker/docker/opts/ulimit.go b/vendor/github.com/docker/docker/opts/ulimit.go index a2a65fcd21..0e2a36236c 100644 --- a/vendor/github.com/docker/docker/opts/ulimit.go +++ b/vendor/github.com/docker/docker/opts/ulimit.go @@ -1,4 +1,4 @@ -package opts +package opts // import "github.com/docker/docker/opts" import ( "fmt" diff --git a/vendor/github.com/docker/docker/pkg/archive/README.md b/vendor/github.com/docker/docker/pkg/archive/README.md deleted file mode 100644 index 7307d9694f..0000000000 --- a/vendor/github.com/docker/docker/pkg/archive/README.md +++ /dev/null @@ -1 +0,0 @@ -This code provides helper functions for dealing with archive files. diff --git a/vendor/github.com/docker/docker/pkg/archive/archive.go b/vendor/github.com/docker/docker/pkg/archive/archive.go deleted file mode 100644 index aa55637565..0000000000 --- a/vendor/github.com/docker/docker/pkg/archive/archive.go +++ /dev/null @@ -1,1237 +0,0 @@ -package archive - -import ( - "archive/tar" - "bufio" - "bytes" - "compress/bzip2" - "compress/gzip" - "fmt" - "io" - "io/ioutil" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" - "syscall" - - "github.com/docker/docker/pkg/fileutils" - "github.com/docker/docker/pkg/idtools" - "github.com/docker/docker/pkg/ioutils" - "github.com/docker/docker/pkg/pools" - "github.com/docker/docker/pkg/system" - "github.com/sirupsen/logrus" -) - -type ( - // Compression is the state represents if compressed or not. - Compression int - // WhiteoutFormat is the format of whiteouts unpacked - WhiteoutFormat int - - // TarOptions wraps the tar options. - TarOptions struct { - IncludeFiles []string - ExcludePatterns []string - Compression Compression - NoLchown bool - UIDMaps []idtools.IDMap - GIDMaps []idtools.IDMap - ChownOpts *idtools.IDPair - IncludeSourceDir bool - // WhiteoutFormat is the expected on disk format for whiteout files. - // This format will be converted to the standard format on pack - // and from the standard format on unpack. - WhiteoutFormat WhiteoutFormat - // When unpacking, specifies whether overwriting a directory with a - // non-directory is allowed and vice versa. - NoOverwriteDirNonDir bool - // For each include when creating an archive, the included name will be - // replaced with the matching name from this map. - RebaseNames map[string]string - InUserNS bool - } -) - -// Archiver implements the Archiver interface and allows the reuse of most utility functions of -// this package with a pluggable Untar function. Also, to facilitate the passing of specific id -// mappings for untar, an Archiver can be created with maps which will then be passed to Untar operations. -type Archiver struct { - Untar func(io.Reader, string, *TarOptions) error - IDMappingsVar *idtools.IDMappings -} - -// NewDefaultArchiver returns a new Archiver without any IDMappings -func NewDefaultArchiver() *Archiver { - return &Archiver{Untar: Untar, IDMappingsVar: &idtools.IDMappings{}} -} - -// breakoutError is used to differentiate errors related to breaking out -// When testing archive breakout in the unit tests, this error is expected -// in order for the test to pass. -type breakoutError error - -const ( - // Uncompressed represents the uncompressed. - Uncompressed Compression = iota - // Bzip2 is bzip2 compression algorithm. - Bzip2 - // Gzip is gzip compression algorithm. - Gzip - // Xz is xz compression algorithm. - Xz -) - -const ( - // AUFSWhiteoutFormat is the default format for whiteouts - AUFSWhiteoutFormat WhiteoutFormat = iota - // OverlayWhiteoutFormat formats whiteout according to the overlay - // standard. - OverlayWhiteoutFormat -) - -const ( - modeISDIR = 040000 // Directory - modeISFIFO = 010000 // FIFO - modeISREG = 0100000 // Regular file - modeISLNK = 0120000 // Symbolic link - modeISBLK = 060000 // Block special file - modeISCHR = 020000 // Character special file - modeISSOCK = 0140000 // Socket -) - -// IsArchivePath checks if the (possibly compressed) file at the given path -// starts with a tar file header. -func IsArchivePath(path string) bool { - file, err := os.Open(path) - if err != nil { - return false - } - defer file.Close() - rdr, err := DecompressStream(file) - if err != nil { - return false - } - r := tar.NewReader(rdr) - _, err = r.Next() - return err == nil -} - -// DetectCompression detects the compression algorithm of the source. -func DetectCompression(source []byte) Compression { - for compression, m := range map[Compression][]byte{ - Bzip2: {0x42, 0x5A, 0x68}, - Gzip: {0x1F, 0x8B, 0x08}, - Xz: {0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00}, - } { - if len(source) < len(m) { - logrus.Debug("Len too short") - continue - } - if bytes.Equal(m, source[:len(m)]) { - return compression - } - } - return Uncompressed -} - -func xzDecompress(archive io.Reader) (io.ReadCloser, <-chan struct{}, error) { - args := []string{"xz", "-d", "-c", "-q"} - - return cmdStream(exec.Command(args[0], args[1:]...), archive) -} - -// DecompressStream decompresses the archive and returns a ReaderCloser with the decompressed archive. -func DecompressStream(archive io.Reader) (io.ReadCloser, error) { - p := pools.BufioReader32KPool - buf := p.Get(archive) - bs, err := buf.Peek(10) - if err != nil && err != io.EOF { - // Note: we'll ignore any io.EOF error because there are some odd - // cases where the layer.tar file will be empty (zero bytes) and - // that results in an io.EOF from the Peek() call. So, in those - // cases we'll just treat it as a non-compressed stream and - // that means just create an empty layer. - // See Issue 18170 - return nil, err - } - - compression := DetectCompression(bs) - switch compression { - case Uncompressed: - readBufWrapper := p.NewReadCloserWrapper(buf, buf) - return readBufWrapper, nil - case Gzip: - gzReader, err := gzip.NewReader(buf) - if err != nil { - return nil, err - } - readBufWrapper := p.NewReadCloserWrapper(buf, gzReader) - return readBufWrapper, nil - case Bzip2: - bz2Reader := bzip2.NewReader(buf) - readBufWrapper := p.NewReadCloserWrapper(buf, bz2Reader) - return readBufWrapper, nil - case Xz: - xzReader, chdone, err := xzDecompress(buf) - if err != nil { - return nil, err - } - readBufWrapper := p.NewReadCloserWrapper(buf, xzReader) - return ioutils.NewReadCloserWrapper(readBufWrapper, func() error { - <-chdone - return readBufWrapper.Close() - }), nil - default: - return nil, fmt.Errorf("Unsupported compression format %s", (&compression).Extension()) - } -} - -// CompressStream compresses the dest with specified compression algorithm. -func CompressStream(dest io.Writer, compression Compression) (io.WriteCloser, error) { - p := pools.BufioWriter32KPool - buf := p.Get(dest) - switch compression { - case Uncompressed: - writeBufWrapper := p.NewWriteCloserWrapper(buf, buf) - return writeBufWrapper, nil - case Gzip: - gzWriter := gzip.NewWriter(dest) - writeBufWrapper := p.NewWriteCloserWrapper(buf, gzWriter) - return writeBufWrapper, nil - case Bzip2, Xz: - // archive/bzip2 does not support writing, and there is no xz support at all - // However, this is not a problem as docker only currently generates gzipped tars - return nil, fmt.Errorf("Unsupported compression format %s", (&compression).Extension()) - default: - return nil, fmt.Errorf("Unsupported compression format %s", (&compression).Extension()) - } -} - -// TarModifierFunc is a function that can be passed to ReplaceFileTarWrapper to -// modify the contents or header of an entry in the archive. If the file already -// exists in the archive the TarModifierFunc will be called with the Header and -// a reader which will return the files content. If the file does not exist both -// header and content will be nil. -type TarModifierFunc func(path string, header *tar.Header, content io.Reader) (*tar.Header, []byte, error) - -// ReplaceFileTarWrapper converts inputTarStream to a new tar stream. Files in the -// tar stream are modified if they match any of the keys in mods. -func ReplaceFileTarWrapper(inputTarStream io.ReadCloser, mods map[string]TarModifierFunc) io.ReadCloser { - pipeReader, pipeWriter := io.Pipe() - - go func() { - tarReader := tar.NewReader(inputTarStream) - tarWriter := tar.NewWriter(pipeWriter) - defer inputTarStream.Close() - defer tarWriter.Close() - - modify := func(name string, original *tar.Header, modifier TarModifierFunc, tarReader io.Reader) error { - header, data, err := modifier(name, original, tarReader) - switch { - case err != nil: - return err - case header == nil: - return nil - } - - header.Name = name - header.Size = int64(len(data)) - if err := tarWriter.WriteHeader(header); err != nil { - return err - } - if len(data) != 0 { - if _, err := tarWriter.Write(data); err != nil { - return err - } - } - return nil - } - - var err error - var originalHeader *tar.Header - for { - originalHeader, err = tarReader.Next() - if err == io.EOF { - break - } - if err != nil { - pipeWriter.CloseWithError(err) - return - } - - modifier, ok := mods[originalHeader.Name] - if !ok { - // No modifiers for this file, copy the header and data - if err := tarWriter.WriteHeader(originalHeader); err != nil { - pipeWriter.CloseWithError(err) - return - } - if _, err := pools.Copy(tarWriter, tarReader); err != nil { - pipeWriter.CloseWithError(err) - return - } - continue - } - delete(mods, originalHeader.Name) - - if err := modify(originalHeader.Name, originalHeader, modifier, tarReader); err != nil { - pipeWriter.CloseWithError(err) - return - } - } - - // Apply the modifiers that haven't matched any files in the archive - for name, modifier := range mods { - if err := modify(name, nil, modifier, nil); err != nil { - pipeWriter.CloseWithError(err) - return - } - } - - pipeWriter.Close() - - }() - return pipeReader -} - -// Extension returns the extension of a file that uses the specified compression algorithm. -func (compression *Compression) Extension() string { - switch *compression { - case Uncompressed: - return "tar" - case Bzip2: - return "tar.bz2" - case Gzip: - return "tar.gz" - case Xz: - return "tar.xz" - } - return "" -} - -// FileInfoHeader creates a populated Header from fi. -// Compared to archive pkg this function fills in more information. -// Also, regardless of Go version, this function fills file type bits (e.g. hdr.Mode |= modeISDIR), -// which have been deleted since Go 1.9 archive/tar. -func FileInfoHeader(name string, fi os.FileInfo, link string) (*tar.Header, error) { - hdr, err := tar.FileInfoHeader(fi, link) - if err != nil { - return nil, err - } - hdr.Mode = fillGo18FileTypeBits(int64(chmodTarEntry(os.FileMode(hdr.Mode))), fi) - name, err = canonicalTarName(name, fi.IsDir()) - if err != nil { - return nil, fmt.Errorf("tar: cannot canonicalize path: %v", err) - } - hdr.Name = name - if err := setHeaderForSpecialDevice(hdr, name, fi.Sys()); err != nil { - return nil, err - } - return hdr, nil -} - -// fillGo18FileTypeBits fills type bits which have been removed on Go 1.9 archive/tar -// https://github.com/golang/go/commit/66b5a2f -func fillGo18FileTypeBits(mode int64, fi os.FileInfo) int64 { - fm := fi.Mode() - switch { - case fm.IsRegular(): - mode |= modeISREG - case fi.IsDir(): - mode |= modeISDIR - case fm&os.ModeSymlink != 0: - mode |= modeISLNK - case fm&os.ModeDevice != 0: - if fm&os.ModeCharDevice != 0 { - mode |= modeISCHR - } else { - mode |= modeISBLK - } - case fm&os.ModeNamedPipe != 0: - mode |= modeISFIFO - case fm&os.ModeSocket != 0: - mode |= modeISSOCK - } - return mode -} - -// ReadSecurityXattrToTarHeader reads security.capability xattr from filesystem -// to a tar header -func ReadSecurityXattrToTarHeader(path string, hdr *tar.Header) error { - capability, _ := system.Lgetxattr(path, "security.capability") - if capability != nil { - hdr.Xattrs = make(map[string]string) - hdr.Xattrs["security.capability"] = string(capability) - } - return nil -} - -type tarWhiteoutConverter interface { - ConvertWrite(*tar.Header, string, os.FileInfo) (*tar.Header, error) - ConvertRead(*tar.Header, string) (bool, error) -} - -type tarAppender struct { - TarWriter *tar.Writer - Buffer *bufio.Writer - - // for hardlink mapping - SeenFiles map[uint64]string - IDMappings *idtools.IDMappings - ChownOpts *idtools.IDPair - - // For packing and unpacking whiteout files in the - // non standard format. The whiteout files defined - // by the AUFS standard are used as the tar whiteout - // standard. - WhiteoutConverter tarWhiteoutConverter -} - -func newTarAppender(idMapping *idtools.IDMappings, writer io.Writer, chownOpts *idtools.IDPair) *tarAppender { - return &tarAppender{ - SeenFiles: make(map[uint64]string), - TarWriter: tar.NewWriter(writer), - Buffer: pools.BufioWriter32KPool.Get(nil), - IDMappings: idMapping, - ChownOpts: chownOpts, - } -} - -// canonicalTarName provides a platform-independent and consistent posix-style -//path for files and directories to be archived regardless of the platform. -func canonicalTarName(name string, isDir bool) (string, error) { - name, err := CanonicalTarNameForPath(name) - if err != nil { - return "", err - } - - // suffix with '/' for directories - if isDir && !strings.HasSuffix(name, "/") { - name += "/" - } - return name, nil -} - -// addTarFile adds to the tar archive a file from `path` as `name` -func (ta *tarAppender) addTarFile(path, name string) error { - fi, err := os.Lstat(path) - if err != nil { - return err - } - - var link string - if fi.Mode()&os.ModeSymlink != 0 { - var err error - link, err = os.Readlink(path) - if err != nil { - return err - } - } - - hdr, err := FileInfoHeader(name, fi, link) - if err != nil { - return err - } - if err := ReadSecurityXattrToTarHeader(path, hdr); err != nil { - return err - } - - // if it's not a directory and has more than 1 link, - // it's hard linked, so set the type flag accordingly - if !fi.IsDir() && hasHardlinks(fi) { - inode, err := getInodeFromStat(fi.Sys()) - if err != nil { - return err - } - // a link should have a name that it links too - // and that linked name should be first in the tar archive - if oldpath, ok := ta.SeenFiles[inode]; ok { - hdr.Typeflag = tar.TypeLink - hdr.Linkname = oldpath - hdr.Size = 0 // This Must be here for the writer math to add up! - } else { - ta.SeenFiles[inode] = name - } - } - - //handle re-mapping container ID mappings back to host ID mappings before - //writing tar headers/files. We skip whiteout files because they were written - //by the kernel and already have proper ownership relative to the host - if !strings.HasPrefix(filepath.Base(hdr.Name), WhiteoutPrefix) && !ta.IDMappings.Empty() { - fileIDPair, err := getFileUIDGID(fi.Sys()) - if err != nil { - return err - } - hdr.Uid, hdr.Gid, err = ta.IDMappings.ToContainer(fileIDPair) - if err != nil { - return err - } - } - - // explicitly override with ChownOpts - if ta.ChownOpts != nil { - hdr.Uid = ta.ChownOpts.UID - hdr.Gid = ta.ChownOpts.GID - } - - if ta.WhiteoutConverter != nil { - wo, err := ta.WhiteoutConverter.ConvertWrite(hdr, path, fi) - if err != nil { - return err - } - - // If a new whiteout file exists, write original hdr, then - // replace hdr with wo to be written after. Whiteouts should - // always be written after the original. Note the original - // hdr may have been updated to be a whiteout with returning - // a whiteout header - if wo != nil { - if err := ta.TarWriter.WriteHeader(hdr); err != nil { - return err - } - if hdr.Typeflag == tar.TypeReg && hdr.Size > 0 { - return fmt.Errorf("tar: cannot use whiteout for non-empty file") - } - hdr = wo - } - } - - if err := ta.TarWriter.WriteHeader(hdr); err != nil { - return err - } - - if hdr.Typeflag == tar.TypeReg && hdr.Size > 0 { - // We use system.OpenSequential to ensure we use sequential file - // access on Windows to avoid depleting the standby list. - // On Linux, this equates to a regular os.Open. - file, err := system.OpenSequential(path) - if err != nil { - return err - } - - ta.Buffer.Reset(ta.TarWriter) - defer ta.Buffer.Reset(nil) - _, err = io.Copy(ta.Buffer, file) - file.Close() - if err != nil { - return err - } - err = ta.Buffer.Flush() - if err != nil { - return err - } - } - - return nil -} - -func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, Lchown bool, chownOpts *idtools.IDPair, inUserns bool) error { - // hdr.Mode is in linux format, which we can use for sycalls, - // but for os.Foo() calls we need the mode converted to os.FileMode, - // so use hdrInfo.Mode() (they differ for e.g. setuid bits) - hdrInfo := hdr.FileInfo() - - switch hdr.Typeflag { - case tar.TypeDir: - // Create directory unless it exists as a directory already. - // In that case we just want to merge the two - if fi, err := os.Lstat(path); !(err == nil && fi.IsDir()) { - if err := os.Mkdir(path, hdrInfo.Mode()); err != nil { - return err - } - } - - case tar.TypeReg, tar.TypeRegA: - // Source is regular file. We use system.OpenFileSequential to use sequential - // file access to avoid depleting the standby list on Windows. - // On Linux, this equates to a regular os.OpenFile - file, err := system.OpenFileSequential(path, os.O_CREATE|os.O_WRONLY, hdrInfo.Mode()) - if err != nil { - return err - } - if _, err := io.Copy(file, reader); err != nil { - file.Close() - return err - } - file.Close() - - case tar.TypeBlock, tar.TypeChar: - if inUserns { // cannot create devices in a userns - return nil - } - // Handle this is an OS-specific way - if err := handleTarTypeBlockCharFifo(hdr, path); err != nil { - return err - } - - case tar.TypeFifo: - // Handle this is an OS-specific way - if err := handleTarTypeBlockCharFifo(hdr, path); err != nil { - return err - } - - case tar.TypeLink: - targetPath := filepath.Join(extractDir, hdr.Linkname) - // check for hardlink breakout - if !strings.HasPrefix(targetPath, extractDir) { - return breakoutError(fmt.Errorf("invalid hardlink %q -> %q", targetPath, hdr.Linkname)) - } - if err := os.Link(targetPath, path); err != nil { - return err - } - - case tar.TypeSymlink: - // path -> hdr.Linkname = targetPath - // e.g. /extractDir/path/to/symlink -> ../2/file = /extractDir/path/2/file - targetPath := filepath.Join(filepath.Dir(path), hdr.Linkname) - - // the reason we don't need to check symlinks in the path (with FollowSymlinkInScope) is because - // that symlink would first have to be created, which would be caught earlier, at this very check: - if !strings.HasPrefix(targetPath, extractDir) { - return breakoutError(fmt.Errorf("invalid symlink %q -> %q", path, hdr.Linkname)) - } - if err := os.Symlink(hdr.Linkname, path); err != nil { - return err - } - - case tar.TypeXGlobalHeader: - logrus.Debug("PAX Global Extended Headers found and ignored") - return nil - - default: - return fmt.Errorf("unhandled tar header type %d", hdr.Typeflag) - } - - // Lchown is not supported on Windows. - if Lchown && runtime.GOOS != "windows" { - if chownOpts == nil { - chownOpts = &idtools.IDPair{UID: hdr.Uid, GID: hdr.Gid} - } - if err := os.Lchown(path, chownOpts.UID, chownOpts.GID); err != nil { - return err - } - } - - var errors []string - for key, value := range hdr.Xattrs { - if err := system.Lsetxattr(path, key, []byte(value), 0); err != nil { - if err == syscall.ENOTSUP { - // We ignore errors here because not all graphdrivers support - // xattrs *cough* old versions of AUFS *cough*. However only - // ENOTSUP should be emitted in that case, otherwise we still - // bail. - errors = append(errors, err.Error()) - continue - } - return err - } - - } - - if len(errors) > 0 { - logrus.WithFields(logrus.Fields{ - "errors": errors, - }).Warn("ignored xattrs in archive: underlying filesystem doesn't support them") - } - - // There is no LChmod, so ignore mode for symlink. Also, this - // must happen after chown, as that can modify the file mode - if err := handleLChmod(hdr, path, hdrInfo); err != nil { - return err - } - - aTime := hdr.AccessTime - if aTime.Before(hdr.ModTime) { - // Last access time should never be before last modified time. - aTime = hdr.ModTime - } - - // system.Chtimes doesn't support a NOFOLLOW flag atm - if hdr.Typeflag == tar.TypeLink { - if fi, err := os.Lstat(hdr.Linkname); err == nil && (fi.Mode()&os.ModeSymlink == 0) { - if err := system.Chtimes(path, aTime, hdr.ModTime); err != nil { - return err - } - } - } else if hdr.Typeflag != tar.TypeSymlink { - if err := system.Chtimes(path, aTime, hdr.ModTime); err != nil { - return err - } - } else { - ts := []syscall.Timespec{timeToTimespec(aTime), timeToTimespec(hdr.ModTime)} - if err := system.LUtimesNano(path, ts); err != nil && err != system.ErrNotSupportedPlatform { - return err - } - } - return nil -} - -// Tar creates an archive from the directory at `path`, and returns it as a -// stream of bytes. -func Tar(path string, compression Compression) (io.ReadCloser, error) { - return TarWithOptions(path, &TarOptions{Compression: compression}) -} - -// TarWithOptions creates an archive from the directory at `path`, only including files whose relative -// paths are included in `options.IncludeFiles` (if non-nil) or not in `options.ExcludePatterns`. -func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error) { - - // Fix the source path to work with long path names. This is a no-op - // on platforms other than Windows. - srcPath = fixVolumePathPrefix(srcPath) - - pm, err := fileutils.NewPatternMatcher(options.ExcludePatterns) - if err != nil { - return nil, err - } - - pipeReader, pipeWriter := io.Pipe() - - compressWriter, err := CompressStream(pipeWriter, options.Compression) - if err != nil { - return nil, err - } - - go func() { - ta := newTarAppender( - idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps), - compressWriter, - options.ChownOpts, - ) - ta.WhiteoutConverter = getWhiteoutConverter(options.WhiteoutFormat) - - defer func() { - // Make sure to check the error on Close. - if err := ta.TarWriter.Close(); err != nil { - logrus.Errorf("Can't close tar writer: %s", err) - } - if err := compressWriter.Close(); err != nil { - logrus.Errorf("Can't close compress writer: %s", err) - } - if err := pipeWriter.Close(); err != nil { - logrus.Errorf("Can't close pipe writer: %s", err) - } - }() - - // this buffer is needed for the duration of this piped stream - defer pools.BufioWriter32KPool.Put(ta.Buffer) - - // In general we log errors here but ignore them because - // during e.g. a diff operation the container can continue - // mutating the filesystem and we can see transient errors - // from this - - stat, err := os.Lstat(srcPath) - if err != nil { - return - } - - if !stat.IsDir() { - // We can't later join a non-dir with any includes because the - // 'walk' will error if "file/." is stat-ed and "file" is not a - // directory. So, we must split the source path and use the - // basename as the include. - if len(options.IncludeFiles) > 0 { - logrus.Warn("Tar: Can't archive a file with includes") - } - - dir, base := SplitPathDirEntry(srcPath) - srcPath = dir - options.IncludeFiles = []string{base} - } - - if len(options.IncludeFiles) == 0 { - options.IncludeFiles = []string{"."} - } - - seen := make(map[string]bool) - - for _, include := range options.IncludeFiles { - rebaseName := options.RebaseNames[include] - - walkRoot := getWalkRoot(srcPath, include) - filepath.Walk(walkRoot, func(filePath string, f os.FileInfo, err error) error { - if err != nil { - logrus.Errorf("Tar: Can't stat file %s to tar: %s", srcPath, err) - return nil - } - - relFilePath, err := filepath.Rel(srcPath, filePath) - if err != nil || (!options.IncludeSourceDir && relFilePath == "." && f.IsDir()) { - // Error getting relative path OR we are looking - // at the source directory path. Skip in both situations. - return nil - } - - if options.IncludeSourceDir && include == "." && relFilePath != "." { - relFilePath = strings.Join([]string{".", relFilePath}, string(filepath.Separator)) - } - - skip := false - - // If "include" is an exact match for the current file - // then even if there's an "excludePatterns" pattern that - // matches it, don't skip it. IOW, assume an explicit 'include' - // is asking for that file no matter what - which is true - // for some files, like .dockerignore and Dockerfile (sometimes) - if include != relFilePath { - skip, err = pm.Matches(relFilePath) - if err != nil { - logrus.Errorf("Error matching %s: %v", relFilePath, err) - return err - } - } - - if skip { - // If we want to skip this file and its a directory - // then we should first check to see if there's an - // excludes pattern (e.g. !dir/file) that starts with this - // dir. If so then we can't skip this dir. - - // Its not a dir then so we can just return/skip. - if !f.IsDir() { - return nil - } - - // No exceptions (!...) in patterns so just skip dir - if !pm.Exclusions() { - return filepath.SkipDir - } - - dirSlash := relFilePath + string(filepath.Separator) - - for _, pat := range pm.Patterns() { - if !pat.Exclusion() { - continue - } - if strings.HasPrefix(pat.String()+string(filepath.Separator), dirSlash) { - // found a match - so can't skip this dir - return nil - } - } - - // No matching exclusion dir so just skip dir - return filepath.SkipDir - } - - if seen[relFilePath] { - return nil - } - seen[relFilePath] = true - - // Rename the base resource. - if rebaseName != "" { - var replacement string - if rebaseName != string(filepath.Separator) { - // Special case the root directory to replace with an - // empty string instead so that we don't end up with - // double slashes in the paths. - replacement = rebaseName - } - - relFilePath = strings.Replace(relFilePath, include, replacement, 1) - } - - if err := ta.addTarFile(filePath, relFilePath); err != nil { - logrus.Errorf("Can't add file %s to tar: %s", filePath, err) - // if pipe is broken, stop writing tar stream to it - if err == io.ErrClosedPipe { - return err - } - } - return nil - }) - } - }() - - return pipeReader, nil -} - -// Unpack unpacks the decompressedArchive to dest with options. -func Unpack(decompressedArchive io.Reader, dest string, options *TarOptions) error { - tr := tar.NewReader(decompressedArchive) - trBuf := pools.BufioReader32KPool.Get(nil) - defer pools.BufioReader32KPool.Put(trBuf) - - var dirs []*tar.Header - idMappings := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps) - rootIDs := idMappings.RootPair() - whiteoutConverter := getWhiteoutConverter(options.WhiteoutFormat) - - // Iterate through the files in the archive. -loop: - for { - hdr, err := tr.Next() - if err == io.EOF { - // end of tar archive - break - } - if err != nil { - return err - } - - // Normalize name, for safety and for a simple is-root check - // This keeps "../" as-is, but normalizes "/../" to "/". Or Windows: - // This keeps "..\" as-is, but normalizes "\..\" to "\". - hdr.Name = filepath.Clean(hdr.Name) - - for _, exclude := range options.ExcludePatterns { - if strings.HasPrefix(hdr.Name, exclude) { - continue loop - } - } - - // After calling filepath.Clean(hdr.Name) above, hdr.Name will now be in - // the filepath format for the OS on which the daemon is running. Hence - // the check for a slash-suffix MUST be done in an OS-agnostic way. - if !strings.HasSuffix(hdr.Name, string(os.PathSeparator)) { - // Not the root directory, ensure that the parent directory exists - parent := filepath.Dir(hdr.Name) - parentPath := filepath.Join(dest, parent) - if _, err := os.Lstat(parentPath); err != nil && os.IsNotExist(err) { - err = idtools.MkdirAllAndChownNew(parentPath, 0777, rootIDs) - if err != nil { - return err - } - } - } - - path := filepath.Join(dest, hdr.Name) - rel, err := filepath.Rel(dest, path) - if err != nil { - return err - } - if strings.HasPrefix(rel, ".."+string(os.PathSeparator)) { - return breakoutError(fmt.Errorf("%q is outside of %q", hdr.Name, dest)) - } - - // If path exits we almost always just want to remove and replace it - // The only exception is when it is a directory *and* the file from - // the layer is also a directory. Then we want to merge them (i.e. - // just apply the metadata from the layer). - if fi, err := os.Lstat(path); err == nil { - if options.NoOverwriteDirNonDir && fi.IsDir() && hdr.Typeflag != tar.TypeDir { - // If NoOverwriteDirNonDir is true then we cannot replace - // an existing directory with a non-directory from the archive. - return fmt.Errorf("cannot overwrite directory %q with non-directory %q", path, dest) - } - - if options.NoOverwriteDirNonDir && !fi.IsDir() && hdr.Typeflag == tar.TypeDir { - // If NoOverwriteDirNonDir is true then we cannot replace - // an existing non-directory with a directory from the archive. - return fmt.Errorf("cannot overwrite non-directory %q with directory %q", path, dest) - } - - if fi.IsDir() && hdr.Name == "." { - continue - } - - if !(fi.IsDir() && hdr.Typeflag == tar.TypeDir) { - if err := os.RemoveAll(path); err != nil { - return err - } - } - } - trBuf.Reset(tr) - - if err := remapIDs(idMappings, hdr); err != nil { - return err - } - - if whiteoutConverter != nil { - writeFile, err := whiteoutConverter.ConvertRead(hdr, path) - if err != nil { - return err - } - if !writeFile { - continue - } - } - - if err := createTarFile(path, dest, hdr, trBuf, !options.NoLchown, options.ChownOpts, options.InUserNS); err != nil { - return err - } - - // Directory mtimes must be handled at the end to avoid further - // file creation in them to modify the directory mtime - if hdr.Typeflag == tar.TypeDir { - dirs = append(dirs, hdr) - } - } - - for _, hdr := range dirs { - path := filepath.Join(dest, hdr.Name) - - if err := system.Chtimes(path, hdr.AccessTime, hdr.ModTime); err != nil { - return err - } - } - return nil -} - -// Untar reads a stream of bytes from `archive`, parses it as a tar archive, -// and unpacks it into the directory at `dest`. -// The archive may be compressed with one of the following algorithms: -// identity (uncompressed), gzip, bzip2, xz. -// FIXME: specify behavior when target path exists vs. doesn't exist. -func Untar(tarArchive io.Reader, dest string, options *TarOptions) error { - return untarHandler(tarArchive, dest, options, true) -} - -// UntarUncompressed reads a stream of bytes from `archive`, parses it as a tar archive, -// and unpacks it into the directory at `dest`. -// The archive must be an uncompressed stream. -func UntarUncompressed(tarArchive io.Reader, dest string, options *TarOptions) error { - return untarHandler(tarArchive, dest, options, false) -} - -// Handler for teasing out the automatic decompression -func untarHandler(tarArchive io.Reader, dest string, options *TarOptions, decompress bool) error { - if tarArchive == nil { - return fmt.Errorf("Empty archive") - } - dest = filepath.Clean(dest) - if options == nil { - options = &TarOptions{} - } - if options.ExcludePatterns == nil { - options.ExcludePatterns = []string{} - } - - r := tarArchive - if decompress { - decompressedArchive, err := DecompressStream(tarArchive) - if err != nil { - return err - } - defer decompressedArchive.Close() - r = decompressedArchive - } - - return Unpack(r, dest, options) -} - -// TarUntar is a convenience function which calls Tar and Untar, with the output of one piped into the other. -// If either Tar or Untar fails, TarUntar aborts and returns the error. -func (archiver *Archiver) TarUntar(src, dst string) error { - logrus.Debugf("TarUntar(%s %s)", src, dst) - archive, err := TarWithOptions(src, &TarOptions{Compression: Uncompressed}) - if err != nil { - return err - } - defer archive.Close() - options := &TarOptions{ - UIDMaps: archiver.IDMappingsVar.UIDs(), - GIDMaps: archiver.IDMappingsVar.GIDs(), - } - return archiver.Untar(archive, dst, options) -} - -// UntarPath untar a file from path to a destination, src is the source tar file path. -func (archiver *Archiver) UntarPath(src, dst string) error { - archive, err := os.Open(src) - if err != nil { - return err - } - defer archive.Close() - options := &TarOptions{ - UIDMaps: archiver.IDMappingsVar.UIDs(), - GIDMaps: archiver.IDMappingsVar.GIDs(), - } - return archiver.Untar(archive, dst, options) -} - -// CopyWithTar creates a tar archive of filesystem path `src`, and -// unpacks it at filesystem path `dst`. -// The archive is streamed directly with fixed buffering and no -// intermediary disk IO. -func (archiver *Archiver) CopyWithTar(src, dst string) error { - srcSt, err := os.Stat(src) - if err != nil { - return err - } - if !srcSt.IsDir() { - return archiver.CopyFileWithTar(src, dst) - } - - // if this Archiver is set up with ID mapping we need to create - // the new destination directory with the remapped root UID/GID pair - // as owner - rootIDs := archiver.IDMappingsVar.RootPair() - // Create dst, copy src's content into it - logrus.Debugf("Creating dest directory: %s", dst) - if err := idtools.MkdirAllAndChownNew(dst, 0755, rootIDs); err != nil { - return err - } - logrus.Debugf("Calling TarUntar(%s, %s)", src, dst) - return archiver.TarUntar(src, dst) -} - -// CopyFileWithTar emulates the behavior of the 'cp' command-line -// for a single file. It copies a regular file from path `src` to -// path `dst`, and preserves all its metadata. -func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) { - logrus.Debugf("CopyFileWithTar(%s, %s)", src, dst) - srcSt, err := os.Stat(src) - if err != nil { - return err - } - - if srcSt.IsDir() { - return fmt.Errorf("Can't copy a directory") - } - - // Clean up the trailing slash. This must be done in an operating - // system specific manner. - if dst[len(dst)-1] == os.PathSeparator { - dst = filepath.Join(dst, filepath.Base(src)) - } - // Create the holding directory if necessary - if err := system.MkdirAll(filepath.Dir(dst), 0700, ""); err != nil { - return err - } - - r, w := io.Pipe() - errC := make(chan error, 1) - - go func() { - defer close(errC) - - errC <- func() error { - defer w.Close() - - srcF, err := os.Open(src) - if err != nil { - return err - } - defer srcF.Close() - - hdr, err := tar.FileInfoHeader(srcSt, "") - if err != nil { - return err - } - hdr.Name = filepath.Base(dst) - hdr.Mode = int64(chmodTarEntry(os.FileMode(hdr.Mode))) - - if err := remapIDs(archiver.IDMappingsVar, hdr); err != nil { - return err - } - - tw := tar.NewWriter(w) - defer tw.Close() - if err := tw.WriteHeader(hdr); err != nil { - return err - } - if _, err := io.Copy(tw, srcF); err != nil { - return err - } - return nil - }() - }() - defer func() { - if er := <-errC; err == nil && er != nil { - err = er - } - }() - - err = archiver.Untar(r, filepath.Dir(dst), nil) - if err != nil { - r.CloseWithError(err) - } - return err -} - -// IDMappings returns the IDMappings of the archiver. -func (archiver *Archiver) IDMappings() *idtools.IDMappings { - return archiver.IDMappingsVar -} - -func remapIDs(idMappings *idtools.IDMappings, hdr *tar.Header) error { - ids, err := idMappings.ToHost(idtools.IDPair{UID: hdr.Uid, GID: hdr.Gid}) - hdr.Uid, hdr.Gid = ids.UID, ids.GID - return err -} - -// cmdStream executes a command, and returns its stdout as a stream. -// If the command fails to run or doesn't complete successfully, an error -// will be returned, including anything written on stderr. -func cmdStream(cmd *exec.Cmd, input io.Reader) (io.ReadCloser, <-chan struct{}, error) { - chdone := make(chan struct{}) - cmd.Stdin = input - pipeR, pipeW := io.Pipe() - cmd.Stdout = pipeW - var errBuf bytes.Buffer - cmd.Stderr = &errBuf - - // Run the command and return the pipe - if err := cmd.Start(); err != nil { - return nil, nil, err - } - - // Copy stdout to the returned pipe - go func() { - if err := cmd.Wait(); err != nil { - pipeW.CloseWithError(fmt.Errorf("%s: %s", err, errBuf.String())) - } else { - pipeW.Close() - } - close(chdone) - }() - - return pipeR, chdone, nil -} - -// NewTempArchive reads the content of src into a temporary file, and returns the contents -// of that file as an archive. The archive can only be read once - as soon as reading completes, -// the file will be deleted. -func NewTempArchive(src io.Reader, dir string) (*TempArchive, error) { - f, err := ioutil.TempFile(dir, "") - if err != nil { - return nil, err - } - if _, err := io.Copy(f, src); err != nil { - return nil, err - } - if _, err := f.Seek(0, 0); err != nil { - return nil, err - } - st, err := f.Stat() - if err != nil { - return nil, err - } - size := st.Size() - return &TempArchive{File: f, Size: size}, nil -} - -// TempArchive is a temporary archive. The archive can only be read once - as soon as reading completes, -// the file will be deleted. -type TempArchive struct { - *os.File - Size int64 // Pre-computed from Stat().Size() as a convenience - read int64 - closed bool -} - -// Close closes the underlying file if it's still open, or does a no-op -// to allow callers to try to close the TempArchive multiple times safely. -func (archive *TempArchive) Close() error { - if archive.closed { - return nil - } - - archive.closed = true - - return archive.File.Close() -} - -func (archive *TempArchive) Read(data []byte) (int, error) { - n, err := archive.File.Read(data) - archive.read += int64(n) - if err != nil || archive.read == archive.Size { - archive.Close() - os.Remove(archive.File.Name()) - } - return n, err -} diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_other.go b/vendor/github.com/docker/docker/pkg/archive/archive_other.go deleted file mode 100644 index 54acbf2856..0000000000 --- a/vendor/github.com/docker/docker/pkg/archive/archive_other.go +++ /dev/null @@ -1,7 +0,0 @@ -// +build !linux - -package archive - -func getWhiteoutConverter(format WhiteoutFormat) tarWhiteoutConverter { - return nil -} diff --git a/vendor/github.com/docker/docker/pkg/archive/changes.go b/vendor/github.com/docker/docker/pkg/archive/changes.go deleted file mode 100644 index d78fe6ac65..0000000000 --- a/vendor/github.com/docker/docker/pkg/archive/changes.go +++ /dev/null @@ -1,441 +0,0 @@ -package archive - -import ( - "archive/tar" - "bytes" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "sort" - "strings" - "syscall" - "time" - - "github.com/docker/docker/pkg/idtools" - "github.com/docker/docker/pkg/pools" - "github.com/docker/docker/pkg/system" - "github.com/sirupsen/logrus" -) - -// ChangeType represents the change type. -type ChangeType int - -const ( - // ChangeModify represents the modify operation. - ChangeModify = iota - // ChangeAdd represents the add operation. - ChangeAdd - // ChangeDelete represents the delete operation. - ChangeDelete -) - -func (c ChangeType) String() string { - switch c { - case ChangeModify: - return "C" - case ChangeAdd: - return "A" - case ChangeDelete: - return "D" - } - return "" -} - -// Change represents a change, it wraps the change type and path. -// It describes changes of the files in the path respect to the -// parent layers. The change could be modify, add, delete. -// This is used for layer diff. -type Change struct { - Path string - Kind ChangeType -} - -func (change *Change) String() string { - return fmt.Sprintf("%s %s", change.Kind, change.Path) -} - -// for sort.Sort -type changesByPath []Change - -func (c changesByPath) Less(i, j int) bool { return c[i].Path < c[j].Path } -func (c changesByPath) Len() int { return len(c) } -func (c changesByPath) Swap(i, j int) { c[j], c[i] = c[i], c[j] } - -// Gnu tar and the go tar writer don't have sub-second mtime -// precision, which is problematic when we apply changes via tar -// files, we handle this by comparing for exact times, *or* same -// second count and either a or b having exactly 0 nanoseconds -func sameFsTime(a, b time.Time) bool { - return a == b || - (a.Unix() == b.Unix() && - (a.Nanosecond() == 0 || b.Nanosecond() == 0)) -} - -func sameFsTimeSpec(a, b syscall.Timespec) bool { - return a.Sec == b.Sec && - (a.Nsec == b.Nsec || a.Nsec == 0 || b.Nsec == 0) -} - -// Changes walks the path rw and determines changes for the files in the path, -// with respect to the parent layers -func Changes(layers []string, rw string) ([]Change, error) { - return changes(layers, rw, aufsDeletedFile, aufsMetadataSkip) -} - -func aufsMetadataSkip(path string) (skip bool, err error) { - skip, err = filepath.Match(string(os.PathSeparator)+WhiteoutMetaPrefix+"*", path) - if err != nil { - skip = true - } - return -} - -func aufsDeletedFile(root, path string, fi os.FileInfo) (string, error) { - f := filepath.Base(path) - - // If there is a whiteout, then the file was removed - if strings.HasPrefix(f, WhiteoutPrefix) { - originalFile := f[len(WhiteoutPrefix):] - return filepath.Join(filepath.Dir(path), originalFile), nil - } - - return "", nil -} - -type skipChange func(string) (bool, error) -type deleteChange func(string, string, os.FileInfo) (string, error) - -func changes(layers []string, rw string, dc deleteChange, sc skipChange) ([]Change, error) { - var ( - changes []Change - changedDirs = make(map[string]struct{}) - ) - - err := filepath.Walk(rw, func(path string, f os.FileInfo, err error) error { - if err != nil { - return err - } - - // Rebase path - path, err = filepath.Rel(rw, path) - if err != nil { - return err - } - - // As this runs on the daemon side, file paths are OS specific. - path = filepath.Join(string(os.PathSeparator), path) - - // Skip root - if path == string(os.PathSeparator) { - return nil - } - - if sc != nil { - if skip, err := sc(path); skip { - return err - } - } - - change := Change{ - Path: path, - } - - deletedFile, err := dc(rw, path, f) - if err != nil { - return err - } - - // Find out what kind of modification happened - if deletedFile != "" { - change.Path = deletedFile - change.Kind = ChangeDelete - } else { - // Otherwise, the file was added - change.Kind = ChangeAdd - - // ...Unless it already existed in a top layer, in which case, it's a modification - for _, layer := range layers { - stat, err := os.Stat(filepath.Join(layer, path)) - if err != nil && !os.IsNotExist(err) { - return err - } - if err == nil { - // The file existed in the top layer, so that's a modification - - // However, if it's a directory, maybe it wasn't actually modified. - // If you modify /foo/bar/baz, then /foo will be part of the changed files only because it's the parent of bar - if stat.IsDir() && f.IsDir() { - if f.Size() == stat.Size() && f.Mode() == stat.Mode() && sameFsTime(f.ModTime(), stat.ModTime()) { - // Both directories are the same, don't record the change - return nil - } - } - change.Kind = ChangeModify - break - } - } - } - - // If /foo/bar/file.txt is modified, then /foo/bar must be part of the changed files. - // This block is here to ensure the change is recorded even if the - // modify time, mode and size of the parent directory in the rw and ro layers are all equal. - // Check https://github.com/docker/docker/pull/13590 for details. - if f.IsDir() { - changedDirs[path] = struct{}{} - } - if change.Kind == ChangeAdd || change.Kind == ChangeDelete { - parent := filepath.Dir(path) - if _, ok := changedDirs[parent]; !ok && parent != "/" { - changes = append(changes, Change{Path: parent, Kind: ChangeModify}) - changedDirs[parent] = struct{}{} - } - } - - // Record change - changes = append(changes, change) - return nil - }) - if err != nil && !os.IsNotExist(err) { - return nil, err - } - return changes, nil -} - -// FileInfo describes the information of a file. -type FileInfo struct { - parent *FileInfo - name string - stat *system.StatT - children map[string]*FileInfo - capability []byte - added bool -} - -// LookUp looks up the file information of a file. -func (info *FileInfo) LookUp(path string) *FileInfo { - // As this runs on the daemon side, file paths are OS specific. - parent := info - if path == string(os.PathSeparator) { - return info - } - - pathElements := strings.Split(path, string(os.PathSeparator)) - for _, elem := range pathElements { - if elem != "" { - child := parent.children[elem] - if child == nil { - return nil - } - parent = child - } - } - return parent -} - -func (info *FileInfo) path() string { - if info.parent == nil { - // As this runs on the daemon side, file paths are OS specific. - return string(os.PathSeparator) - } - return filepath.Join(info.parent.path(), info.name) -} - -func (info *FileInfo) addChanges(oldInfo *FileInfo, changes *[]Change) { - - sizeAtEntry := len(*changes) - - if oldInfo == nil { - // add - change := Change{ - Path: info.path(), - Kind: ChangeAdd, - } - *changes = append(*changes, change) - info.added = true - } - - // We make a copy so we can modify it to detect additions - // also, we only recurse on the old dir if the new info is a directory - // otherwise any previous delete/change is considered recursive - oldChildren := make(map[string]*FileInfo) - if oldInfo != nil && info.isDir() { - for k, v := range oldInfo.children { - oldChildren[k] = v - } - } - - for name, newChild := range info.children { - oldChild := oldChildren[name] - if oldChild != nil { - // change? - oldStat := oldChild.stat - newStat := newChild.stat - // Note: We can't compare inode or ctime or blocksize here, because these change - // when copying a file into a container. However, that is not generally a problem - // because any content change will change mtime, and any status change should - // be visible when actually comparing the stat fields. The only time this - // breaks down is if some code intentionally hides a change by setting - // back mtime - if statDifferent(oldStat, newStat) || - !bytes.Equal(oldChild.capability, newChild.capability) { - change := Change{ - Path: newChild.path(), - Kind: ChangeModify, - } - *changes = append(*changes, change) - newChild.added = true - } - - // Remove from copy so we can detect deletions - delete(oldChildren, name) - } - - newChild.addChanges(oldChild, changes) - } - for _, oldChild := range oldChildren { - // delete - change := Change{ - Path: oldChild.path(), - Kind: ChangeDelete, - } - *changes = append(*changes, change) - } - - // If there were changes inside this directory, we need to add it, even if the directory - // itself wasn't changed. This is needed to properly save and restore filesystem permissions. - // As this runs on the daemon side, file paths are OS specific. - if len(*changes) > sizeAtEntry && info.isDir() && !info.added && info.path() != string(os.PathSeparator) { - change := Change{ - Path: info.path(), - Kind: ChangeModify, - } - // Let's insert the directory entry before the recently added entries located inside this dir - *changes = append(*changes, change) // just to resize the slice, will be overwritten - copy((*changes)[sizeAtEntry+1:], (*changes)[sizeAtEntry:]) - (*changes)[sizeAtEntry] = change - } - -} - -// Changes add changes to file information. -func (info *FileInfo) Changes(oldInfo *FileInfo) []Change { - var changes []Change - - info.addChanges(oldInfo, &changes) - - return changes -} - -func newRootFileInfo() *FileInfo { - // As this runs on the daemon side, file paths are OS specific. - root := &FileInfo{ - name: string(os.PathSeparator), - children: make(map[string]*FileInfo), - } - return root -} - -// ChangesDirs compares two directories and generates an array of Change objects describing the changes. -// If oldDir is "", then all files in newDir will be Add-Changes. -func ChangesDirs(newDir, oldDir string) ([]Change, error) { - var ( - oldRoot, newRoot *FileInfo - ) - if oldDir == "" { - emptyDir, err := ioutil.TempDir("", "empty") - if err != nil { - return nil, err - } - defer os.Remove(emptyDir) - oldDir = emptyDir - } - oldRoot, newRoot, err := collectFileInfoForChanges(oldDir, newDir) - if err != nil { - return nil, err - } - - return newRoot.Changes(oldRoot), nil -} - -// ChangesSize calculates the size in bytes of the provided changes, based on newDir. -func ChangesSize(newDir string, changes []Change) int64 { - var ( - size int64 - sf = make(map[uint64]struct{}) - ) - for _, change := range changes { - if change.Kind == ChangeModify || change.Kind == ChangeAdd { - file := filepath.Join(newDir, change.Path) - fileInfo, err := os.Lstat(file) - if err != nil { - logrus.Errorf("Can not stat %q: %s", file, err) - continue - } - - if fileInfo != nil && !fileInfo.IsDir() { - if hasHardlinks(fileInfo) { - inode := getIno(fileInfo) - if _, ok := sf[inode]; !ok { - size += fileInfo.Size() - sf[inode] = struct{}{} - } - } else { - size += fileInfo.Size() - } - } - } - } - return size -} - -// ExportChanges produces an Archive from the provided changes, relative to dir. -func ExportChanges(dir string, changes []Change, uidMaps, gidMaps []idtools.IDMap) (io.ReadCloser, error) { - reader, writer := io.Pipe() - go func() { - ta := newTarAppender(idtools.NewIDMappingsFromMaps(uidMaps, gidMaps), writer, nil) - - // this buffer is needed for the duration of this piped stream - defer pools.BufioWriter32KPool.Put(ta.Buffer) - - sort.Sort(changesByPath(changes)) - - // In general we log errors here but ignore them because - // during e.g. a diff operation the container can continue - // mutating the filesystem and we can see transient errors - // from this - for _, change := range changes { - if change.Kind == ChangeDelete { - whiteOutDir := filepath.Dir(change.Path) - whiteOutBase := filepath.Base(change.Path) - whiteOut := filepath.Join(whiteOutDir, WhiteoutPrefix+whiteOutBase) - timestamp := time.Now() - hdr := &tar.Header{ - Name: whiteOut[1:], - Size: 0, - ModTime: timestamp, - AccessTime: timestamp, - ChangeTime: timestamp, - } - if err := ta.TarWriter.WriteHeader(hdr); err != nil { - logrus.Debugf("Can't write whiteout header: %s", err) - } - } else { - path := filepath.Join(dir, change.Path) - if err := ta.addTarFile(path, change.Path[1:]); err != nil { - logrus.Debugf("Can't add file %s to tar: %s", path, err) - } - } - } - - // Make sure to check the error on Close. - if err := ta.TarWriter.Close(); err != nil { - logrus.Debugf("Can't close layer: %s", err) - } - if err := writer.Close(); err != nil { - logrus.Debugf("failed close Changes writer: %s", err) - } - }() - return reader, nil -} diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_linux.go b/vendor/github.com/docker/docker/pkg/archive/changes_linux.go deleted file mode 100644 index e9eb478fe3..0000000000 --- a/vendor/github.com/docker/docker/pkg/archive/changes_linux.go +++ /dev/null @@ -1,313 +0,0 @@ -package archive - -import ( - "bytes" - "fmt" - "os" - "path/filepath" - "sort" - "syscall" - "unsafe" - - "github.com/docker/docker/pkg/system" - "golang.org/x/sys/unix" -) - -// walker is used to implement collectFileInfoForChanges on linux. Where this -// method in general returns the entire contents of two directory trees, we -// optimize some FS calls out on linux. In particular, we take advantage of the -// fact that getdents(2) returns the inode of each file in the directory being -// walked, which, when walking two trees in parallel to generate a list of -// changes, can be used to prune subtrees without ever having to lstat(2) them -// directly. Eliminating stat calls in this way can save up to seconds on large -// images. -type walker struct { - dir1 string - dir2 string - root1 *FileInfo - root2 *FileInfo -} - -// collectFileInfoForChanges returns a complete representation of the trees -// rooted at dir1 and dir2, with one important exception: any subtree or -// leaf where the inode and device numbers are an exact match between dir1 -// and dir2 will be pruned from the results. This method is *only* to be used -// to generating a list of changes between the two directories, as it does not -// reflect the full contents. -func collectFileInfoForChanges(dir1, dir2 string) (*FileInfo, *FileInfo, error) { - w := &walker{ - dir1: dir1, - dir2: dir2, - root1: newRootFileInfo(), - root2: newRootFileInfo(), - } - - i1, err := os.Lstat(w.dir1) - if err != nil { - return nil, nil, err - } - i2, err := os.Lstat(w.dir2) - if err != nil { - return nil, nil, err - } - - if err := w.walk("/", i1, i2); err != nil { - return nil, nil, err - } - - return w.root1, w.root2, nil -} - -// Given a FileInfo, its path info, and a reference to the root of the tree -// being constructed, register this file with the tree. -func walkchunk(path string, fi os.FileInfo, dir string, root *FileInfo) error { - if fi == nil { - return nil - } - parent := root.LookUp(filepath.Dir(path)) - if parent == nil { - return fmt.Errorf("walkchunk: Unexpectedly no parent for %s", path) - } - info := &FileInfo{ - name: filepath.Base(path), - children: make(map[string]*FileInfo), - parent: parent, - } - cpath := filepath.Join(dir, path) - stat, err := system.FromStatT(fi.Sys().(*syscall.Stat_t)) - if err != nil { - return err - } - info.stat = stat - info.capability, _ = system.Lgetxattr(cpath, "security.capability") // lgetxattr(2): fs access - parent.children[info.name] = info - return nil -} - -// Walk a subtree rooted at the same path in both trees being iterated. For -// example, /docker/overlay/1234/a/b/c/d and /docker/overlay/8888/a/b/c/d -func (w *walker) walk(path string, i1, i2 os.FileInfo) (err error) { - // Register these nodes with the return trees, unless we're still at the - // (already-created) roots: - if path != "/" { - if err := walkchunk(path, i1, w.dir1, w.root1); err != nil { - return err - } - if err := walkchunk(path, i2, w.dir2, w.root2); err != nil { - return err - } - } - - is1Dir := i1 != nil && i1.IsDir() - is2Dir := i2 != nil && i2.IsDir() - - sameDevice := false - if i1 != nil && i2 != nil { - si1 := i1.Sys().(*syscall.Stat_t) - si2 := i2.Sys().(*syscall.Stat_t) - if si1.Dev == si2.Dev { - sameDevice = true - } - } - - // If these files are both non-existent, or leaves (non-dirs), we are done. - if !is1Dir && !is2Dir { - return nil - } - - // Fetch the names of all the files contained in both directories being walked: - var names1, names2 []nameIno - if is1Dir { - names1, err = readdirnames(filepath.Join(w.dir1, path)) // getdents(2): fs access - if err != nil { - return err - } - } - if is2Dir { - names2, err = readdirnames(filepath.Join(w.dir2, path)) // getdents(2): fs access - if err != nil { - return err - } - } - - // We have lists of the files contained in both parallel directories, sorted - // in the same order. Walk them in parallel, generating a unique merged list - // of all items present in either or both directories. - var names []string - ix1 := 0 - ix2 := 0 - - for { - if ix1 >= len(names1) { - break - } - if ix2 >= len(names2) { - break - } - - ni1 := names1[ix1] - ni2 := names2[ix2] - - switch bytes.Compare([]byte(ni1.name), []byte(ni2.name)) { - case -1: // ni1 < ni2 -- advance ni1 - // we will not encounter ni1 in names2 - names = append(names, ni1.name) - ix1++ - case 0: // ni1 == ni2 - if ni1.ino != ni2.ino || !sameDevice { - names = append(names, ni1.name) - } - ix1++ - ix2++ - case 1: // ni1 > ni2 -- advance ni2 - // we will not encounter ni2 in names1 - names = append(names, ni2.name) - ix2++ - } - } - for ix1 < len(names1) { - names = append(names, names1[ix1].name) - ix1++ - } - for ix2 < len(names2) { - names = append(names, names2[ix2].name) - ix2++ - } - - // For each of the names present in either or both of the directories being - // iterated, stat the name under each root, and recurse the pair of them: - for _, name := range names { - fname := filepath.Join(path, name) - var cInfo1, cInfo2 os.FileInfo - if is1Dir { - cInfo1, err = os.Lstat(filepath.Join(w.dir1, fname)) // lstat(2): fs access - if err != nil && !os.IsNotExist(err) { - return err - } - } - if is2Dir { - cInfo2, err = os.Lstat(filepath.Join(w.dir2, fname)) // lstat(2): fs access - if err != nil && !os.IsNotExist(err) { - return err - } - } - if err = w.walk(fname, cInfo1, cInfo2); err != nil { - return err - } - } - return nil -} - -// {name,inode} pairs used to support the early-pruning logic of the walker type -type nameIno struct { - name string - ino uint64 -} - -type nameInoSlice []nameIno - -func (s nameInoSlice) Len() int { return len(s) } -func (s nameInoSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } -func (s nameInoSlice) Less(i, j int) bool { return s[i].name < s[j].name } - -// readdirnames is a hacked-apart version of the Go stdlib code, exposing inode -// numbers further up the stack when reading directory contents. Unlike -// os.Readdirnames, which returns a list of filenames, this function returns a -// list of {filename,inode} pairs. -func readdirnames(dirname string) (names []nameIno, err error) { - var ( - size = 100 - buf = make([]byte, 4096) - nbuf int - bufp int - nb int - ) - - f, err := os.Open(dirname) - if err != nil { - return nil, err - } - defer f.Close() - - names = make([]nameIno, 0, size) // Empty with room to grow. - for { - // Refill the buffer if necessary - if bufp >= nbuf { - bufp = 0 - nbuf, err = unix.ReadDirent(int(f.Fd()), buf) // getdents on linux - if nbuf < 0 { - nbuf = 0 - } - if err != nil { - return nil, os.NewSyscallError("readdirent", err) - } - if nbuf <= 0 { - break // EOF - } - } - - // Drain the buffer - nb, names = parseDirent(buf[bufp:nbuf], names) - bufp += nb - } - - sl := nameInoSlice(names) - sort.Sort(sl) - return sl, nil -} - -// parseDirent is a minor modification of unix.ParseDirent (linux version) -// which returns {name,inode} pairs instead of just names. -func parseDirent(buf []byte, names []nameIno) (consumed int, newnames []nameIno) { - origlen := len(buf) - for len(buf) > 0 { - dirent := (*unix.Dirent)(unsafe.Pointer(&buf[0])) - buf = buf[dirent.Reclen:] - if dirent.Ino == 0 { // File absent in directory. - continue - } - bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0])) - var name = string(bytes[0:clen(bytes[:])]) - if name == "." || name == ".." { // Useless names - continue - } - names = append(names, nameIno{name, dirent.Ino}) - } - return origlen - len(buf), names -} - -func clen(n []byte) int { - for i := 0; i < len(n); i++ { - if n[i] == 0 { - return i - } - } - return len(n) -} - -// OverlayChanges walks the path rw and determines changes for the files in the path, -// with respect to the parent layers -func OverlayChanges(layers []string, rw string) ([]Change, error) { - return changes(layers, rw, overlayDeletedFile, nil) -} - -func overlayDeletedFile(root, path string, fi os.FileInfo) (string, error) { - if fi.Mode()&os.ModeCharDevice != 0 { - s := fi.Sys().(*syscall.Stat_t) - if unix.Major(uint64(s.Rdev)) == 0 && unix.Minor(uint64(s.Rdev)) == 0 { // nolint: unconvert - return path, nil - } - } - if fi.Mode()&os.ModeDir != 0 { - opaque, err := system.Lgetxattr(filepath.Join(root, path), "trusted.overlay.opaque") - if err != nil { - return "", err - } - if len(opaque) == 1 && opaque[0] == 'y' { - return path, nil - } - } - - return "", nil - -} diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_other.go b/vendor/github.com/docker/docker/pkg/archive/changes_other.go deleted file mode 100644 index da70ed37c4..0000000000 --- a/vendor/github.com/docker/docker/pkg/archive/changes_other.go +++ /dev/null @@ -1,97 +0,0 @@ -// +build !linux - -package archive - -import ( - "fmt" - "os" - "path/filepath" - "runtime" - "strings" - - "github.com/docker/docker/pkg/system" -) - -func collectFileInfoForChanges(oldDir, newDir string) (*FileInfo, *FileInfo, error) { - var ( - oldRoot, newRoot *FileInfo - err1, err2 error - errs = make(chan error, 2) - ) - go func() { - oldRoot, err1 = collectFileInfo(oldDir) - errs <- err1 - }() - go func() { - newRoot, err2 = collectFileInfo(newDir) - errs <- err2 - }() - - // block until both routines have returned - for i := 0; i < 2; i++ { - if err := <-errs; err != nil { - return nil, nil, err - } - } - - return oldRoot, newRoot, nil -} - -func collectFileInfo(sourceDir string) (*FileInfo, error) { - root := newRootFileInfo() - - err := filepath.Walk(sourceDir, func(path string, f os.FileInfo, err error) error { - if err != nil { - return err - } - - // Rebase path - relPath, err := filepath.Rel(sourceDir, path) - if err != nil { - return err - } - - // As this runs on the daemon side, file paths are OS specific. - relPath = filepath.Join(string(os.PathSeparator), relPath) - - // See https://github.com/golang/go/issues/9168 - bug in filepath.Join. - // Temporary workaround. If the returned path starts with two backslashes, - // trim it down to a single backslash. Only relevant on Windows. - if runtime.GOOS == "windows" { - if strings.HasPrefix(relPath, `\\`) { - relPath = relPath[1:] - } - } - - if relPath == string(os.PathSeparator) { - return nil - } - - parent := root.LookUp(filepath.Dir(relPath)) - if parent == nil { - return fmt.Errorf("collectFileInfo: Unexpectedly no parent for %s", relPath) - } - - info := &FileInfo{ - name: filepath.Base(relPath), - children: make(map[string]*FileInfo), - parent: parent, - } - - s, err := system.Lstat(path) - if err != nil { - return err - } - info.stat = s - - info.capability, _ = system.Lgetxattr(path, "security.capability") - - parent.children[info.name] = info - - return nil - }) - if err != nil { - return nil, err - } - return root, nil -} diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_unix.go b/vendor/github.com/docker/docker/pkg/archive/changes_unix.go deleted file mode 100644 index 7aa1226d7f..0000000000 --- a/vendor/github.com/docker/docker/pkg/archive/changes_unix.go +++ /dev/null @@ -1,37 +0,0 @@ -// +build !windows - -package archive - -import ( - "os" - "syscall" - - "github.com/docker/docker/pkg/system" - "golang.org/x/sys/unix" -) - -func statDifferent(oldStat *system.StatT, newStat *system.StatT) bool { - // Don't look at size for dirs, its not a good measure of change - if oldStat.Mode() != newStat.Mode() || - oldStat.UID() != newStat.UID() || - oldStat.GID() != newStat.GID() || - oldStat.Rdev() != newStat.Rdev() || - // Don't look at size for dirs, its not a good measure of change - (oldStat.Mode()&unix.S_IFDIR != unix.S_IFDIR && - (!sameFsTimeSpec(oldStat.Mtim(), newStat.Mtim()) || (oldStat.Size() != newStat.Size()))) { - return true - } - return false -} - -func (info *FileInfo) isDir() bool { - return info.parent == nil || info.stat.Mode()&unix.S_IFDIR != 0 -} - -func getIno(fi os.FileInfo) uint64 { - return fi.Sys().(*syscall.Stat_t).Ino -} - -func hasHardlinks(fi os.FileInfo) bool { - return fi.Sys().(*syscall.Stat_t).Nlink > 1 -} diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_windows.go b/vendor/github.com/docker/docker/pkg/archive/changes_windows.go deleted file mode 100644 index 6fd353269b..0000000000 --- a/vendor/github.com/docker/docker/pkg/archive/changes_windows.go +++ /dev/null @@ -1,30 +0,0 @@ -package archive - -import ( - "os" - - "github.com/docker/docker/pkg/system" -) - -func statDifferent(oldStat *system.StatT, newStat *system.StatT) bool { - - // Don't look at size for dirs, its not a good measure of change - if oldStat.Mtim() != newStat.Mtim() || - oldStat.Mode() != newStat.Mode() || - oldStat.Size() != newStat.Size() && !oldStat.Mode().IsDir() { - return true - } - return false -} - -func (info *FileInfo) isDir() bool { - return info.parent == nil || info.stat.Mode().IsDir() -} - -func getIno(fi os.FileInfo) (inode uint64) { - return -} - -func hasHardlinks(fi os.FileInfo) bool { - return false -} diff --git a/vendor/github.com/docker/docker/pkg/archive/copy.go b/vendor/github.com/docker/docker/pkg/archive/copy.go deleted file mode 100644 index d1e036d5c6..0000000000 --- a/vendor/github.com/docker/docker/pkg/archive/copy.go +++ /dev/null @@ -1,472 +0,0 @@ -package archive - -import ( - "archive/tar" - "errors" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - - "github.com/docker/docker/pkg/system" - "github.com/sirupsen/logrus" -) - -// Errors used or returned by this file. -var ( - ErrNotDirectory = errors.New("not a directory") - ErrDirNotExists = errors.New("no such directory") - ErrCannotCopyDir = errors.New("cannot copy directory") - ErrInvalidCopySource = errors.New("invalid copy source content") -) - -// PreserveTrailingDotOrSeparator returns the given cleaned path (after -// processing using any utility functions from the path or filepath stdlib -// packages) and appends a trailing `/.` or `/` if its corresponding original -// path (from before being processed by utility functions from the path or -// filepath stdlib packages) ends with a trailing `/.` or `/`. If the cleaned -// path already ends in a `.` path segment, then another is not added. If the -// clean path already ends in the separator, then another is not added. -func PreserveTrailingDotOrSeparator(cleanedPath string, originalPath string, sep byte) string { - // Ensure paths are in platform semantics - cleanedPath = strings.Replace(cleanedPath, "/", string(sep), -1) - originalPath = strings.Replace(originalPath, "/", string(sep), -1) - - if !specifiesCurrentDir(cleanedPath) && specifiesCurrentDir(originalPath) { - if !hasTrailingPathSeparator(cleanedPath, sep) { - // Add a separator if it doesn't already end with one (a cleaned - // path would only end in a separator if it is the root). - cleanedPath += string(sep) - } - cleanedPath += "." - } - - if !hasTrailingPathSeparator(cleanedPath, sep) && hasTrailingPathSeparator(originalPath, sep) { - cleanedPath += string(sep) - } - - return cleanedPath -} - -// assertsDirectory returns whether the given path is -// asserted to be a directory, i.e., the path ends with -// a trailing '/' or `/.`, assuming a path separator of `/`. -func assertsDirectory(path string, sep byte) bool { - return hasTrailingPathSeparator(path, sep) || specifiesCurrentDir(path) -} - -// hasTrailingPathSeparator returns whether the given -// path ends with the system's path separator character. -func hasTrailingPathSeparator(path string, sep byte) bool { - return len(path) > 0 && path[len(path)-1] == sep -} - -// specifiesCurrentDir returns whether the given path specifies -// a "current directory", i.e., the last path segment is `.`. -func specifiesCurrentDir(path string) bool { - return filepath.Base(path) == "." -} - -// SplitPathDirEntry splits the given path between its directory name and its -// basename by first cleaning the path but preserves a trailing "." if the -// original path specified the current directory. -func SplitPathDirEntry(path string) (dir, base string) { - cleanedPath := filepath.Clean(filepath.FromSlash(path)) - - if specifiesCurrentDir(path) { - cleanedPath += string(os.PathSeparator) + "." - } - - return filepath.Dir(cleanedPath), filepath.Base(cleanedPath) -} - -// TarResource archives the resource described by the given CopyInfo to a Tar -// archive. A non-nil error is returned if sourcePath does not exist or is -// asserted to be a directory but exists as another type of file. -// -// This function acts as a convenient wrapper around TarWithOptions, which -// requires a directory as the source path. TarResource accepts either a -// directory or a file path and correctly sets the Tar options. -func TarResource(sourceInfo CopyInfo) (content io.ReadCloser, err error) { - return TarResourceRebase(sourceInfo.Path, sourceInfo.RebaseName) -} - -// TarResourceRebase is like TarResource but renames the first path element of -// items in the resulting tar archive to match the given rebaseName if not "". -func TarResourceRebase(sourcePath, rebaseName string) (content io.ReadCloser, err error) { - sourcePath = normalizePath(sourcePath) - if _, err = os.Lstat(sourcePath); err != nil { - // Catches the case where the source does not exist or is not a - // directory if asserted to be a directory, as this also causes an - // error. - return - } - - // Separate the source path between its directory and - // the entry in that directory which we are archiving. - sourceDir, sourceBase := SplitPathDirEntry(sourcePath) - opts := TarResourceRebaseOpts(sourceBase, rebaseName) - - logrus.Debugf("copying %q from %q", sourceBase, sourceDir) - return TarWithOptions(sourceDir, opts) -} - -// TarResourceRebaseOpts does not preform the Tar, but instead just creates the rebase -// parameters to be sent to TarWithOptions (the TarOptions struct) -func TarResourceRebaseOpts(sourceBase string, rebaseName string) *TarOptions { - filter := []string{sourceBase} - return &TarOptions{ - Compression: Uncompressed, - IncludeFiles: filter, - IncludeSourceDir: true, - RebaseNames: map[string]string{ - sourceBase: rebaseName, - }, - } -} - -// CopyInfo holds basic info about the source -// or destination path of a copy operation. -type CopyInfo struct { - Path string - Exists bool - IsDir bool - RebaseName string -} - -// CopyInfoSourcePath stats the given path to create a CopyInfo -// struct representing that resource for the source of an archive copy -// operation. The given path should be an absolute local path. A source path -// has all symlinks evaluated that appear before the last path separator ("/" -// on Unix). As it is to be a copy source, the path must exist. -func CopyInfoSourcePath(path string, followLink bool) (CopyInfo, error) { - // normalize the file path and then evaluate the symbol link - // we will use the target file instead of the symbol link if - // followLink is set - path = normalizePath(path) - - resolvedPath, rebaseName, err := ResolveHostSourcePath(path, followLink) - if err != nil { - return CopyInfo{}, err - } - - stat, err := os.Lstat(resolvedPath) - if err != nil { - return CopyInfo{}, err - } - - return CopyInfo{ - Path: resolvedPath, - Exists: true, - IsDir: stat.IsDir(), - RebaseName: rebaseName, - }, nil -} - -// CopyInfoDestinationPath stats the given path to create a CopyInfo -// struct representing that resource for the destination of an archive copy -// operation. The given path should be an absolute local path. -func CopyInfoDestinationPath(path string) (info CopyInfo, err error) { - maxSymlinkIter := 10 // filepath.EvalSymlinks uses 255, but 10 already seems like a lot. - path = normalizePath(path) - originalPath := path - - stat, err := os.Lstat(path) - - if err == nil && stat.Mode()&os.ModeSymlink == 0 { - // The path exists and is not a symlink. - return CopyInfo{ - Path: path, - Exists: true, - IsDir: stat.IsDir(), - }, nil - } - - // While the path is a symlink. - for n := 0; err == nil && stat.Mode()&os.ModeSymlink != 0; n++ { - if n > maxSymlinkIter { - // Don't follow symlinks more than this arbitrary number of times. - return CopyInfo{}, errors.New("too many symlinks in " + originalPath) - } - - // The path is a symbolic link. We need to evaluate it so that the - // destination of the copy operation is the link target and not the - // link itself. This is notably different than CopyInfoSourcePath which - // only evaluates symlinks before the last appearing path separator. - // Also note that it is okay if the last path element is a broken - // symlink as the copy operation should create the target. - var linkTarget string - - linkTarget, err = os.Readlink(path) - if err != nil { - return CopyInfo{}, err - } - - if !system.IsAbs(linkTarget) { - // Join with the parent directory. - dstParent, _ := SplitPathDirEntry(path) - linkTarget = filepath.Join(dstParent, linkTarget) - } - - path = linkTarget - stat, err = os.Lstat(path) - } - - if err != nil { - // It's okay if the destination path doesn't exist. We can still - // continue the copy operation if the parent directory exists. - if !os.IsNotExist(err) { - return CopyInfo{}, err - } - - // Ensure destination parent dir exists. - dstParent, _ := SplitPathDirEntry(path) - - parentDirStat, err := os.Stat(dstParent) - if err != nil { - return CopyInfo{}, err - } - if !parentDirStat.IsDir() { - return CopyInfo{}, ErrNotDirectory - } - - return CopyInfo{Path: path}, nil - } - - // The path exists after resolving symlinks. - return CopyInfo{ - Path: path, - Exists: true, - IsDir: stat.IsDir(), - }, nil -} - -// PrepareArchiveCopy prepares the given srcContent archive, which should -// contain the archived resource described by srcInfo, to the destination -// described by dstInfo. Returns the possibly modified content archive along -// with the path to the destination directory which it should be extracted to. -func PrepareArchiveCopy(srcContent io.Reader, srcInfo, dstInfo CopyInfo) (dstDir string, content io.ReadCloser, err error) { - // Ensure in platform semantics - srcInfo.Path = normalizePath(srcInfo.Path) - dstInfo.Path = normalizePath(dstInfo.Path) - - // Separate the destination path between its directory and base - // components in case the source archive contents need to be rebased. - dstDir, dstBase := SplitPathDirEntry(dstInfo.Path) - _, srcBase := SplitPathDirEntry(srcInfo.Path) - - switch { - case dstInfo.Exists && dstInfo.IsDir: - // The destination exists as a directory. No alteration - // to srcContent is needed as its contents can be - // simply extracted to the destination directory. - return dstInfo.Path, ioutil.NopCloser(srcContent), nil - case dstInfo.Exists && srcInfo.IsDir: - // The destination exists as some type of file and the source - // content is a directory. This is an error condition since - // you cannot copy a directory to an existing file location. - return "", nil, ErrCannotCopyDir - case dstInfo.Exists: - // The destination exists as some type of file and the source content - // is also a file. The source content entry will have to be renamed to - // have a basename which matches the destination path's basename. - if len(srcInfo.RebaseName) != 0 { - srcBase = srcInfo.RebaseName - } - return dstDir, RebaseArchiveEntries(srcContent, srcBase, dstBase), nil - case srcInfo.IsDir: - // The destination does not exist and the source content is an archive - // of a directory. The archive should be extracted to the parent of - // the destination path instead, and when it is, the directory that is - // created as a result should take the name of the destination path. - // The source content entries will have to be renamed to have a - // basename which matches the destination path's basename. - if len(srcInfo.RebaseName) != 0 { - srcBase = srcInfo.RebaseName - } - return dstDir, RebaseArchiveEntries(srcContent, srcBase, dstBase), nil - case assertsDirectory(dstInfo.Path, os.PathSeparator): - // The destination does not exist and is asserted to be created as a - // directory, but the source content is not a directory. This is an - // error condition since you cannot create a directory from a file - // source. - return "", nil, ErrDirNotExists - default: - // The last remaining case is when the destination does not exist, is - // not asserted to be a directory, and the source content is not an - // archive of a directory. It this case, the destination file will need - // to be created when the archive is extracted and the source content - // entry will have to be renamed to have a basename which matches the - // destination path's basename. - if len(srcInfo.RebaseName) != 0 { - srcBase = srcInfo.RebaseName - } - return dstDir, RebaseArchiveEntries(srcContent, srcBase, dstBase), nil - } - -} - -// RebaseArchiveEntries rewrites the given srcContent archive replacing -// an occurrence of oldBase with newBase at the beginning of entry names. -func RebaseArchiveEntries(srcContent io.Reader, oldBase, newBase string) io.ReadCloser { - if oldBase == string(os.PathSeparator) { - // If oldBase specifies the root directory, use an empty string as - // oldBase instead so that newBase doesn't replace the path separator - // that all paths will start with. - oldBase = "" - } - - rebased, w := io.Pipe() - - go func() { - srcTar := tar.NewReader(srcContent) - rebasedTar := tar.NewWriter(w) - - for { - hdr, err := srcTar.Next() - if err == io.EOF { - // Signals end of archive. - rebasedTar.Close() - w.Close() - return - } - if err != nil { - w.CloseWithError(err) - return - } - - hdr.Name = strings.Replace(hdr.Name, oldBase, newBase, 1) - if hdr.Typeflag == tar.TypeLink { - hdr.Linkname = strings.Replace(hdr.Linkname, oldBase, newBase, 1) - } - - if err = rebasedTar.WriteHeader(hdr); err != nil { - w.CloseWithError(err) - return - } - - if _, err = io.Copy(rebasedTar, srcTar); err != nil { - w.CloseWithError(err) - return - } - } - }() - - return rebased -} - -// TODO @gupta-ak. These might have to be changed in the future to be -// continuity driver aware as well to support LCOW. - -// CopyResource performs an archive copy from the given source path to the -// given destination path. The source path MUST exist and the destination -// path's parent directory must exist. -func CopyResource(srcPath, dstPath string, followLink bool) error { - var ( - srcInfo CopyInfo - err error - ) - - // Ensure in platform semantics - srcPath = normalizePath(srcPath) - dstPath = normalizePath(dstPath) - - // Clean the source and destination paths. - srcPath = PreserveTrailingDotOrSeparator(filepath.Clean(srcPath), srcPath, os.PathSeparator) - dstPath = PreserveTrailingDotOrSeparator(filepath.Clean(dstPath), dstPath, os.PathSeparator) - - if srcInfo, err = CopyInfoSourcePath(srcPath, followLink); err != nil { - return err - } - - content, err := TarResource(srcInfo) - if err != nil { - return err - } - defer content.Close() - - return CopyTo(content, srcInfo, dstPath) -} - -// CopyTo handles extracting the given content whose -// entries should be sourced from srcInfo to dstPath. -func CopyTo(content io.Reader, srcInfo CopyInfo, dstPath string) error { - // The destination path need not exist, but CopyInfoDestinationPath will - // ensure that at least the parent directory exists. - dstInfo, err := CopyInfoDestinationPath(normalizePath(dstPath)) - if err != nil { - return err - } - - dstDir, copyArchive, err := PrepareArchiveCopy(content, srcInfo, dstInfo) - if err != nil { - return err - } - defer copyArchive.Close() - - options := &TarOptions{ - NoLchown: true, - NoOverwriteDirNonDir: true, - } - - return Untar(copyArchive, dstDir, options) -} - -// ResolveHostSourcePath decides real path need to be copied with parameters such as -// whether to follow symbol link or not, if followLink is true, resolvedPath will return -// link target of any symbol link file, else it will only resolve symlink of directory -// but return symbol link file itself without resolving. -func ResolveHostSourcePath(path string, followLink bool) (resolvedPath, rebaseName string, err error) { - if followLink { - resolvedPath, err = filepath.EvalSymlinks(path) - if err != nil { - return - } - - resolvedPath, rebaseName = GetRebaseName(path, resolvedPath) - } else { - dirPath, basePath := filepath.Split(path) - - // if not follow symbol link, then resolve symbol link of parent dir - var resolvedDirPath string - resolvedDirPath, err = filepath.EvalSymlinks(dirPath) - if err != nil { - return - } - // resolvedDirPath will have been cleaned (no trailing path separators) so - // we can manually join it with the base path element. - resolvedPath = resolvedDirPath + string(filepath.Separator) + basePath - if hasTrailingPathSeparator(path, os.PathSeparator) && - filepath.Base(path) != filepath.Base(resolvedPath) { - rebaseName = filepath.Base(path) - } - } - return resolvedPath, rebaseName, nil -} - -// GetRebaseName normalizes and compares path and resolvedPath, -// return completed resolved path and rebased file name -func GetRebaseName(path, resolvedPath string) (string, string) { - // linkTarget will have been cleaned (no trailing path separators and dot) so - // we can manually join it with them - var rebaseName string - if specifiesCurrentDir(path) && - !specifiesCurrentDir(resolvedPath) { - resolvedPath += string(filepath.Separator) + "." - } - - if hasTrailingPathSeparator(path, os.PathSeparator) && - !hasTrailingPathSeparator(resolvedPath, os.PathSeparator) { - resolvedPath += string(filepath.Separator) - } - - if filepath.Base(path) != filepath.Base(resolvedPath) { - // In the case where the path had a trailing separator and a symlink - // evaluation has changed the last path component, we will need to - // rebase the name in the archive that is being copied to match the - // originally requested name. - rebaseName = filepath.Base(path) - } - return resolvedPath, rebaseName -} diff --git a/vendor/github.com/docker/docker/pkg/archive/copy_unix.go b/vendor/github.com/docker/docker/pkg/archive/copy_unix.go deleted file mode 100644 index e305b5e4af..0000000000 --- a/vendor/github.com/docker/docker/pkg/archive/copy_unix.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build !windows - -package archive - -import ( - "path/filepath" -) - -func normalizePath(path string) string { - return filepath.ToSlash(path) -} diff --git a/vendor/github.com/docker/docker/pkg/archive/copy_windows.go b/vendor/github.com/docker/docker/pkg/archive/copy_windows.go deleted file mode 100644 index 2b775b45c4..0000000000 --- a/vendor/github.com/docker/docker/pkg/archive/copy_windows.go +++ /dev/null @@ -1,9 +0,0 @@ -package archive - -import ( - "path/filepath" -) - -func normalizePath(path string) string { - return filepath.FromSlash(path) -} diff --git a/vendor/github.com/docker/docker/pkg/archive/diff.go b/vendor/github.com/docker/docker/pkg/archive/diff.go deleted file mode 100644 index 019facd383..0000000000 --- a/vendor/github.com/docker/docker/pkg/archive/diff.go +++ /dev/null @@ -1,256 +0,0 @@ -package archive - -import ( - "archive/tar" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "runtime" - "strings" - - "github.com/docker/docker/pkg/idtools" - "github.com/docker/docker/pkg/pools" - "github.com/docker/docker/pkg/system" - "github.com/sirupsen/logrus" -) - -// UnpackLayer unpack `layer` to a `dest`. The stream `layer` can be -// compressed or uncompressed. -// Returns the size in bytes of the contents of the layer. -func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64, err error) { - tr := tar.NewReader(layer) - trBuf := pools.BufioReader32KPool.Get(tr) - defer pools.BufioReader32KPool.Put(trBuf) - - var dirs []*tar.Header - unpackedPaths := make(map[string]struct{}) - - if options == nil { - options = &TarOptions{} - } - if options.ExcludePatterns == nil { - options.ExcludePatterns = []string{} - } - idMappings := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps) - - aufsTempdir := "" - aufsHardlinks := make(map[string]*tar.Header) - - // Iterate through the files in the archive. - for { - hdr, err := tr.Next() - if err == io.EOF { - // end of tar archive - break - } - if err != nil { - return 0, err - } - - size += hdr.Size - - // Normalize name, for safety and for a simple is-root check - hdr.Name = filepath.Clean(hdr.Name) - - // Windows does not support filenames with colons in them. Ignore - // these files. This is not a problem though (although it might - // appear that it is). Let's suppose a client is running docker pull. - // The daemon it points to is Windows. Would it make sense for the - // client to be doing a docker pull Ubuntu for example (which has files - // with colons in the name under /usr/share/man/man3)? No, absolutely - // not as it would really only make sense that they were pulling a - // Windows image. However, for development, it is necessary to be able - // to pull Linux images which are in the repository. - // - // TODO Windows. Once the registry is aware of what images are Windows- - // specific or Linux-specific, this warning should be changed to an error - // to cater for the situation where someone does manage to upload a Linux - // image but have it tagged as Windows inadvertently. - if runtime.GOOS == "windows" { - if strings.Contains(hdr.Name, ":") { - logrus.Warnf("Windows: Ignoring %s (is this a Linux image?)", hdr.Name) - continue - } - } - - // Note as these operations are platform specific, so must the slash be. - if !strings.HasSuffix(hdr.Name, string(os.PathSeparator)) { - // Not the root directory, ensure that the parent directory exists. - // This happened in some tests where an image had a tarfile without any - // parent directories. - parent := filepath.Dir(hdr.Name) - parentPath := filepath.Join(dest, parent) - - if _, err := os.Lstat(parentPath); err != nil && os.IsNotExist(err) { - err = system.MkdirAll(parentPath, 0600, "") - if err != nil { - return 0, err - } - } - } - - // Skip AUFS metadata dirs - if strings.HasPrefix(hdr.Name, WhiteoutMetaPrefix) { - // Regular files inside /.wh..wh.plnk can be used as hardlink targets - // We don't want this directory, but we need the files in them so that - // such hardlinks can be resolved. - if strings.HasPrefix(hdr.Name, WhiteoutLinkDir) && hdr.Typeflag == tar.TypeReg { - basename := filepath.Base(hdr.Name) - aufsHardlinks[basename] = hdr - if aufsTempdir == "" { - if aufsTempdir, err = ioutil.TempDir("", "dockerplnk"); err != nil { - return 0, err - } - defer os.RemoveAll(aufsTempdir) - } - if err := createTarFile(filepath.Join(aufsTempdir, basename), dest, hdr, tr, true, nil, options.InUserNS); err != nil { - return 0, err - } - } - - if hdr.Name != WhiteoutOpaqueDir { - continue - } - } - path := filepath.Join(dest, hdr.Name) - rel, err := filepath.Rel(dest, path) - if err != nil { - return 0, err - } - - // Note as these operations are platform specific, so must the slash be. - if strings.HasPrefix(rel, ".."+string(os.PathSeparator)) { - return 0, breakoutError(fmt.Errorf("%q is outside of %q", hdr.Name, dest)) - } - base := filepath.Base(path) - - if strings.HasPrefix(base, WhiteoutPrefix) { - dir := filepath.Dir(path) - if base == WhiteoutOpaqueDir { - _, err := os.Lstat(dir) - if err != nil { - return 0, err - } - err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { - if err != nil { - if os.IsNotExist(err) { - err = nil // parent was deleted - } - return err - } - if path == dir { - return nil - } - if _, exists := unpackedPaths[path]; !exists { - err := os.RemoveAll(path) - return err - } - return nil - }) - if err != nil { - return 0, err - } - } else { - originalBase := base[len(WhiteoutPrefix):] - originalPath := filepath.Join(dir, originalBase) - if err := os.RemoveAll(originalPath); err != nil { - return 0, err - } - } - } else { - // If path exits we almost always just want to remove and replace it. - // The only exception is when it is a directory *and* the file from - // the layer is also a directory. Then we want to merge them (i.e. - // just apply the metadata from the layer). - if fi, err := os.Lstat(path); err == nil { - if !(fi.IsDir() && hdr.Typeflag == tar.TypeDir) { - if err := os.RemoveAll(path); err != nil { - return 0, err - } - } - } - - trBuf.Reset(tr) - srcData := io.Reader(trBuf) - srcHdr := hdr - - // Hard links into /.wh..wh.plnk don't work, as we don't extract that directory, so - // we manually retarget these into the temporary files we extracted them into - if hdr.Typeflag == tar.TypeLink && strings.HasPrefix(filepath.Clean(hdr.Linkname), WhiteoutLinkDir) { - linkBasename := filepath.Base(hdr.Linkname) - srcHdr = aufsHardlinks[linkBasename] - if srcHdr == nil { - return 0, fmt.Errorf("Invalid aufs hardlink") - } - tmpFile, err := os.Open(filepath.Join(aufsTempdir, linkBasename)) - if err != nil { - return 0, err - } - defer tmpFile.Close() - srcData = tmpFile - } - - if err := remapIDs(idMappings, srcHdr); err != nil { - return 0, err - } - - if err := createTarFile(path, dest, srcHdr, srcData, true, nil, options.InUserNS); err != nil { - return 0, err - } - - // Directory mtimes must be handled at the end to avoid further - // file creation in them to modify the directory mtime - if hdr.Typeflag == tar.TypeDir { - dirs = append(dirs, hdr) - } - unpackedPaths[path] = struct{}{} - } - } - - for _, hdr := range dirs { - path := filepath.Join(dest, hdr.Name) - if err := system.Chtimes(path, hdr.AccessTime, hdr.ModTime); err != nil { - return 0, err - } - } - - return size, nil -} - -// ApplyLayer parses a diff in the standard layer format from `layer`, -// and applies it to the directory `dest`. The stream `layer` can be -// compressed or uncompressed. -// Returns the size in bytes of the contents of the layer. -func ApplyLayer(dest string, layer io.Reader) (int64, error) { - return applyLayerHandler(dest, layer, &TarOptions{}, true) -} - -// ApplyUncompressedLayer parses a diff in the standard layer format from -// `layer`, and applies it to the directory `dest`. The stream `layer` -// can only be uncompressed. -// Returns the size in bytes of the contents of the layer. -func ApplyUncompressedLayer(dest string, layer io.Reader, options *TarOptions) (int64, error) { - return applyLayerHandler(dest, layer, options, false) -} - -// do the bulk load of ApplyLayer, but allow for not calling DecompressStream -func applyLayerHandler(dest string, layer io.Reader, options *TarOptions, decompress bool) (int64, error) { - dest = filepath.Clean(dest) - - // We need to be able to set any perms - oldmask, err := system.Umask(0) - if err != nil { - return 0, err - } - defer system.Umask(oldmask) // ignore err, ErrNotSupportedPlatform - - if decompress { - layer, err = DecompressStream(layer) - if err != nil { - return 0, err - } - } - return UnpackLayer(dest, layer, options) -} diff --git a/vendor/github.com/docker/docker/pkg/archive/example_changes.go b/vendor/github.com/docker/docker/pkg/archive/example_changes.go deleted file mode 100644 index 495db809e9..0000000000 --- a/vendor/github.com/docker/docker/pkg/archive/example_changes.go +++ /dev/null @@ -1,97 +0,0 @@ -// +build ignore - -// Simple tool to create an archive stream from an old and new directory -// -// By default it will stream the comparison of two temporary directories with junk files -package main - -import ( - "flag" - "fmt" - "io" - "io/ioutil" - "os" - "path" - - "github.com/docker/docker/pkg/archive" - "github.com/sirupsen/logrus" -) - -var ( - flDebug = flag.Bool("D", false, "debugging output") - flNewDir = flag.String("newdir", "", "") - flOldDir = flag.String("olddir", "", "") - log = logrus.New() -) - -func main() { - flag.Usage = func() { - fmt.Println("Produce a tar from comparing two directory paths. By default a demo tar is created of around 200 files (including hardlinks)") - fmt.Printf("%s [OPTIONS]\n", os.Args[0]) - flag.PrintDefaults() - } - flag.Parse() - log.Out = os.Stderr - if (len(os.Getenv("DEBUG")) > 0) || *flDebug { - logrus.SetLevel(logrus.DebugLevel) - } - var newDir, oldDir string - - if len(*flNewDir) == 0 { - var err error - newDir, err = ioutil.TempDir("", "docker-test-newDir") - if err != nil { - log.Fatal(err) - } - defer os.RemoveAll(newDir) - if _, err := prepareUntarSourceDirectory(100, newDir, true); err != nil { - log.Fatal(err) - } - } else { - newDir = *flNewDir - } - - if len(*flOldDir) == 0 { - oldDir, err := ioutil.TempDir("", "docker-test-oldDir") - if err != nil { - log.Fatal(err) - } - defer os.RemoveAll(oldDir) - } else { - oldDir = *flOldDir - } - - changes, err := archive.ChangesDirs(newDir, oldDir) - if err != nil { - log.Fatal(err) - } - - a, err := archive.ExportChanges(newDir, changes) - if err != nil { - log.Fatal(err) - } - defer a.Close() - - i, err := io.Copy(os.Stdout, a) - if err != nil && err != io.EOF { - log.Fatal(err) - } - fmt.Fprintf(os.Stderr, "wrote archive of %d bytes", i) -} - -func prepareUntarSourceDirectory(numberOfFiles int, targetPath string, makeLinks bool) (int, error) { - fileData := []byte("fooo") - for n := 0; n < numberOfFiles; n++ { - fileName := fmt.Sprintf("file-%d", n) - if err := ioutil.WriteFile(path.Join(targetPath, fileName), fileData, 0700); err != nil { - return 0, err - } - if makeLinks { - if err := os.Link(path.Join(targetPath, fileName), path.Join(targetPath, fileName+"-link")); err != nil { - return 0, err - } - } - } - totalSize := numberOfFiles * len(fileData) - return totalSize, nil -} diff --git a/vendor/github.com/docker/docker/pkg/archive/time_linux.go b/vendor/github.com/docker/docker/pkg/archive/time_linux.go deleted file mode 100644 index 3448569b1e..0000000000 --- a/vendor/github.com/docker/docker/pkg/archive/time_linux.go +++ /dev/null @@ -1,16 +0,0 @@ -package archive - -import ( - "syscall" - "time" -) - -func timeToTimespec(time time.Time) (ts syscall.Timespec) { - if time.IsZero() { - // Return UTIME_OMIT special value - ts.Sec = 0 - ts.Nsec = ((1 << 30) - 2) - return - } - return syscall.NsecToTimespec(time.UnixNano()) -} diff --git a/vendor/github.com/docker/docker/pkg/archive/time_unsupported.go b/vendor/github.com/docker/docker/pkg/archive/time_unsupported.go deleted file mode 100644 index e85aac0540..0000000000 --- a/vendor/github.com/docker/docker/pkg/archive/time_unsupported.go +++ /dev/null @@ -1,16 +0,0 @@ -// +build !linux - -package archive - -import ( - "syscall" - "time" -) - -func timeToTimespec(time time.Time) (ts syscall.Timespec) { - nsec := int64(0) - if !time.IsZero() { - nsec = time.UnixNano() - } - return syscall.NsecToTimespec(nsec) -} diff --git a/vendor/github.com/docker/docker/pkg/archive/wrap.go b/vendor/github.com/docker/docker/pkg/archive/wrap.go deleted file mode 100644 index b39d12c878..0000000000 --- a/vendor/github.com/docker/docker/pkg/archive/wrap.go +++ /dev/null @@ -1,59 +0,0 @@ -package archive - -import ( - "archive/tar" - "bytes" - "io" -) - -// Generate generates a new archive from the content provided -// as input. -// -// `files` is a sequence of path/content pairs. A new file is -// added to the archive for each pair. -// If the last pair is incomplete, the file is created with an -// empty content. For example: -// -// Generate("foo.txt", "hello world", "emptyfile") -// -// The above call will return an archive with 2 files: -// * ./foo.txt with content "hello world" -// * ./empty with empty content -// -// FIXME: stream content instead of buffering -// FIXME: specify permissions and other archive metadata -func Generate(input ...string) (io.Reader, error) { - files := parseStringPairs(input...) - buf := new(bytes.Buffer) - tw := tar.NewWriter(buf) - for _, file := range files { - name, content := file[0], file[1] - hdr := &tar.Header{ - Name: name, - Size: int64(len(content)), - } - if err := tw.WriteHeader(hdr); err != nil { - return nil, err - } - if _, err := tw.Write([]byte(content)); err != nil { - return nil, err - } - } - if err := tw.Close(); err != nil { - return nil, err - } - return buf, nil -} - -func parseStringPairs(input ...string) (output [][2]string) { - output = make([][2]string, 0, len(input)/2+1) - for i := 0; i < len(input); i += 2 { - var pair [2]string - pair[0] = input[i] - if i+1 < len(input) { - pair[1] = input[i+1] - } - output = append(output, pair) - } - return -} diff --git a/vendor/github.com/docker/docker/pkg/fileutils/fileutils.go b/vendor/github.com/docker/docker/pkg/fileutils/fileutils.go index a129e654ea..28cad499aa 100644 --- a/vendor/github.com/docker/docker/pkg/fileutils/fileutils.go +++ b/vendor/github.com/docker/docker/pkg/fileutils/fileutils.go @@ -1,4 +1,4 @@ -package fileutils +package fileutils // import "github.com/docker/docker/pkg/fileutils" import ( "errors" @@ -13,7 +13,7 @@ import ( "github.com/sirupsen/logrus" ) -// PatternMatcher allows checking paths agaist a list of patterns +// PatternMatcher allows checking paths against a list of patterns type PatternMatcher struct { patterns []*Pattern exclusions bool diff --git a/vendor/github.com/docker/docker/pkg/fileutils/fileutils_darwin.go b/vendor/github.com/docker/docker/pkg/fileutils/fileutils_darwin.go index ccd648fac3..e40cc271b3 100644 --- a/vendor/github.com/docker/docker/pkg/fileutils/fileutils_darwin.go +++ b/vendor/github.com/docker/docker/pkg/fileutils/fileutils_darwin.go @@ -1,4 +1,4 @@ -package fileutils +package fileutils // import "github.com/docker/docker/pkg/fileutils" import ( "os" diff --git a/vendor/github.com/docker/docker/pkg/fileutils/fileutils_unix.go b/vendor/github.com/docker/docker/pkg/fileutils/fileutils_unix.go index 9e0e97bd64..565396f1c7 100644 --- a/vendor/github.com/docker/docker/pkg/fileutils/fileutils_unix.go +++ b/vendor/github.com/docker/docker/pkg/fileutils/fileutils_unix.go @@ -1,6 +1,6 @@ // +build linux freebsd -package fileutils +package fileutils // import "github.com/docker/docker/pkg/fileutils" import ( "fmt" diff --git a/vendor/github.com/docker/docker/pkg/fileutils/fileutils_windows.go b/vendor/github.com/docker/docker/pkg/fileutils/fileutils_windows.go index 5ec21cace5..3f1ebb6567 100644 --- a/vendor/github.com/docker/docker/pkg/fileutils/fileutils_windows.go +++ b/vendor/github.com/docker/docker/pkg/fileutils/fileutils_windows.go @@ -1,4 +1,4 @@ -package fileutils +package fileutils // import "github.com/docker/docker/pkg/fileutils" // GetTotalUsedFds Returns the number of used File Descriptors. Not supported // on Windows. diff --git a/vendor/github.com/docker/docker/pkg/homedir/homedir_linux.go b/vendor/github.com/docker/docker/pkg/homedir/homedir_linux.go index 012fe52a28..ee15ed52b1 100644 --- a/vendor/github.com/docker/docker/pkg/homedir/homedir_linux.go +++ b/vendor/github.com/docker/docker/pkg/homedir/homedir_linux.go @@ -1,6 +1,4 @@ -// +build linux - -package homedir +package homedir // import "github.com/docker/docker/pkg/homedir" import ( "os" diff --git a/vendor/github.com/docker/docker/pkg/homedir/homedir_others.go b/vendor/github.com/docker/docker/pkg/homedir/homedir_others.go index 6b96b856f6..75ada2fe54 100644 --- a/vendor/github.com/docker/docker/pkg/homedir/homedir_others.go +++ b/vendor/github.com/docker/docker/pkg/homedir/homedir_others.go @@ -1,6 +1,6 @@ // +build !linux -package homedir +package homedir // import "github.com/docker/docker/pkg/homedir" import ( "errors" diff --git a/vendor/github.com/docker/docker/pkg/homedir/homedir_unix.go b/vendor/github.com/docker/docker/pkg/homedir/homedir_unix.go index f2a20ea8f8..d85e124488 100644 --- a/vendor/github.com/docker/docker/pkg/homedir/homedir_unix.go +++ b/vendor/github.com/docker/docker/pkg/homedir/homedir_unix.go @@ -1,6 +1,6 @@ // +build !windows -package homedir +package homedir // import "github.com/docker/docker/pkg/homedir" import ( "os" diff --git a/vendor/github.com/docker/docker/pkg/homedir/homedir_windows.go b/vendor/github.com/docker/docker/pkg/homedir/homedir_windows.go index fafdb2bbf9..2f81813b28 100644 --- a/vendor/github.com/docker/docker/pkg/homedir/homedir_windows.go +++ b/vendor/github.com/docker/docker/pkg/homedir/homedir_windows.go @@ -1,4 +1,4 @@ -package homedir +package homedir // import "github.com/docker/docker/pkg/homedir" import ( "os" diff --git a/vendor/github.com/docker/docker/pkg/idtools/idtools.go b/vendor/github.com/docker/docker/pkg/idtools/idtools.go index 49cc97c3d6..d1f173a311 100644 --- a/vendor/github.com/docker/docker/pkg/idtools/idtools.go +++ b/vendor/github.com/docker/docker/pkg/idtools/idtools.go @@ -1,4 +1,4 @@ -package idtools +package idtools // import "github.com/docker/docker/pkg/idtools" import ( "bufio" @@ -30,8 +30,8 @@ func (e ranges) Swap(i, j int) { e[i], e[j] = e[j], e[i] } func (e ranges) Less(i, j int) bool { return e[i].Start < e[j].Start } const ( - subuidFileName string = "/etc/subuid" - subgidFileName string = "/etc/subgid" + subuidFileName = "/etc/subuid" + subgidFileName = "/etc/subgid" ) // MkdirAllAndChown creates a directory (include any along the path) and then modifies @@ -42,7 +42,9 @@ func MkdirAllAndChown(path string, mode os.FileMode, owner IDPair) error { } // MkdirAndChown creates a directory and then modifies ownership to the requested uid/gid. -// If the directory already exists, this function still changes ownership +// If the directory already exists, this function still changes ownership. +// Note that unlike os.Mkdir(), this function does not return IsExist error +// in case path already exists. func MkdirAndChown(path string, mode os.FileMode, owner IDPair) error { return mkdirAs(path, mode, owner.UID, owner.GID, false, true) } diff --git a/vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go b/vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go index ff7968f854..1d87ea3bcb 100644 --- a/vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go +++ b/vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go @@ -1,6 +1,6 @@ // +build !windows -package idtools +package idtools // import "github.com/docker/docker/pkg/idtools" import ( "bytes" @@ -10,6 +10,7 @@ import ( "path/filepath" "strings" "sync" + "syscall" "github.com/docker/docker/pkg/system" "github.com/opencontainers/runc/libcontainer/user" @@ -29,6 +30,9 @@ func mkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int, mkAll, chown stat, err := system.Stat(path) if err == nil { + if !stat.IsDir() { + return &os.PathError{Op: "mkdir", Path: path, Err: syscall.ENOTDIR} + } if !chownExisting { return nil } @@ -54,7 +58,7 @@ func mkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int, mkAll, chown paths = append(paths, dirPath) } } - if err := system.MkdirAll(path, mode, ""); err != nil && !os.IsExist(err) { + if err := system.MkdirAll(path, mode, ""); err != nil { return err } } else { diff --git a/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go b/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go index 45d2878e38..d72cc28929 100644 --- a/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go +++ b/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go @@ -1,6 +1,4 @@ -// +build windows - -package idtools +package idtools // import "github.com/docker/docker/pkg/idtools" import ( "os" @@ -11,7 +9,7 @@ import ( // Platforms such as Windows do not support the UID/GID concept. So make this // just a wrapper around system.MkdirAll. func mkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int, mkAll, chownExisting bool) error { - if err := system.MkdirAll(path, mode, ""); err != nil && !os.IsExist(err) { + if err := system.MkdirAll(path, mode, ""); err != nil { return err } return nil diff --git a/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_linux.go b/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_linux.go index 9da7975e2c..6272c5a404 100644 --- a/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_linux.go +++ b/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_linux.go @@ -1,4 +1,4 @@ -package idtools +package idtools // import "github.com/docker/docker/pkg/idtools" import ( "fmt" diff --git a/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_unsupported.go b/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_unsupported.go index d98b354cbd..e7c4d63118 100644 --- a/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_unsupported.go +++ b/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_unsupported.go @@ -1,6 +1,6 @@ // +build !linux -package idtools +package idtools // import "github.com/docker/docker/pkg/idtools" import "fmt" diff --git a/vendor/github.com/docker/docker/pkg/idtools/utils_unix.go b/vendor/github.com/docker/docker/pkg/idtools/utils_unix.go index 9703ecbd9d..903ac4501b 100644 --- a/vendor/github.com/docker/docker/pkg/idtools/utils_unix.go +++ b/vendor/github.com/docker/docker/pkg/idtools/utils_unix.go @@ -1,6 +1,6 @@ // +build !windows -package idtools +package idtools // import "github.com/docker/docker/pkg/idtools" import ( "fmt" diff --git a/vendor/github.com/docker/docker/pkg/ioutils/buffer.go b/vendor/github.com/docker/docker/pkg/ioutils/buffer.go index 3d737b3e19..466f79294b 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/buffer.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/buffer.go @@ -1,4 +1,4 @@ -package ioutils +package ioutils // import "github.com/docker/docker/pkg/ioutils" import ( "errors" diff --git a/vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go b/vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go index 72a04f3491..d4bbf3c9dc 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go @@ -1,4 +1,4 @@ -package ioutils +package ioutils // import "github.com/docker/docker/pkg/ioutils" import ( "errors" diff --git a/vendor/github.com/docker/docker/pkg/ioutils/fswriters.go b/vendor/github.com/docker/docker/pkg/ioutils/fswriters.go index a56c462651..534d66ac26 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/fswriters.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/fswriters.go @@ -1,4 +1,4 @@ -package ioutils +package ioutils // import "github.com/docker/docker/pkg/ioutils" import ( "io" diff --git a/vendor/github.com/docker/docker/pkg/ioutils/readers.go b/vendor/github.com/docker/docker/pkg/ioutils/readers.go index 63f3c07f46..1f657bd3dc 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/readers.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/readers.go @@ -1,25 +1,28 @@ -package ioutils +package ioutils // import "github.com/docker/docker/pkg/ioutils" import ( + "context" "crypto/sha256" "encoding/hex" "io" - - "golang.org/x/net/context" ) -type readCloserWrapper struct { +// ReadCloserWrapper wraps an io.Reader, and implements an io.ReadCloser +// It calls the given callback function when closed. It should be constructed +// with NewReadCloserWrapper +type ReadCloserWrapper struct { io.Reader closer func() error } -func (r *readCloserWrapper) Close() error { +// Close calls back the passed closer function +func (r *ReadCloserWrapper) Close() error { return r.closer() } // NewReadCloserWrapper returns a new io.ReadCloser. func NewReadCloserWrapper(r io.Reader, closer func() error) io.ReadCloser { - return &readCloserWrapper{ + return &ReadCloserWrapper{ Reader: r, closer: closer, } diff --git a/vendor/github.com/docker/docker/pkg/ioutils/temp_unix.go b/vendor/github.com/docker/docker/pkg/ioutils/temp_unix.go index 1539ad21b5..dc894f9131 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/temp_unix.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/temp_unix.go @@ -1,6 +1,6 @@ // +build !windows -package ioutils +package ioutils // import "github.com/docker/docker/pkg/ioutils" import "io/ioutil" diff --git a/vendor/github.com/docker/docker/pkg/ioutils/temp_windows.go b/vendor/github.com/docker/docker/pkg/ioutils/temp_windows.go index c258e5fdd8..ecaba2e36d 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/temp_windows.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/temp_windows.go @@ -1,6 +1,4 @@ -// +build windows - -package ioutils +package ioutils // import "github.com/docker/docker/pkg/ioutils" import ( "io/ioutil" diff --git a/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go b/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go index 52a4901ade..91b8d18266 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go @@ -1,4 +1,4 @@ -package ioutils +package ioutils // import "github.com/docker/docker/pkg/ioutils" import ( "io" diff --git a/vendor/github.com/docker/docker/pkg/ioutils/writers.go b/vendor/github.com/docker/docker/pkg/ioutils/writers.go index ccc7f9c23e..61c679497d 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/writers.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/writers.go @@ -1,4 +1,4 @@ -package ioutils +package ioutils // import "github.com/docker/docker/pkg/ioutils" import "io" diff --git a/vendor/github.com/docker/docker/pkg/longpath/longpath.go b/vendor/github.com/docker/docker/pkg/longpath/longpath.go index 9b15bfff4c..4177affba2 100644 --- a/vendor/github.com/docker/docker/pkg/longpath/longpath.go +++ b/vendor/github.com/docker/docker/pkg/longpath/longpath.go @@ -2,7 +2,7 @@ // in Windows, which are expected to be prepended with `\\?\` and followed by either // a drive letter, a UNC server\share, or a volume identifier. -package longpath +package longpath // import "github.com/docker/docker/pkg/longpath" import ( "strings" diff --git a/vendor/github.com/docker/docker/pkg/mount/flags.go b/vendor/github.com/docker/docker/pkg/mount/flags.go index 607dbed43a..272363b685 100644 --- a/vendor/github.com/docker/docker/pkg/mount/flags.go +++ b/vendor/github.com/docker/docker/pkg/mount/flags.go @@ -1,4 +1,4 @@ -package mount +package mount // import "github.com/docker/docker/pkg/mount" import ( "fmt" diff --git a/vendor/github.com/docker/docker/pkg/mount/flags_freebsd.go b/vendor/github.com/docker/docker/pkg/mount/flags_freebsd.go index 5f76f331b6..ef35ef9059 100644 --- a/vendor/github.com/docker/docker/pkg/mount/flags_freebsd.go +++ b/vendor/github.com/docker/docker/pkg/mount/flags_freebsd.go @@ -1,6 +1,6 @@ // +build freebsd,cgo -package mount +package mount // import "github.com/docker/docker/pkg/mount" /* #include diff --git a/vendor/github.com/docker/docker/pkg/mount/flags_linux.go b/vendor/github.com/docker/docker/pkg/mount/flags_linux.go index 0425d0dd63..a1b199a31a 100644 --- a/vendor/github.com/docker/docker/pkg/mount/flags_linux.go +++ b/vendor/github.com/docker/docker/pkg/mount/flags_linux.go @@ -1,4 +1,4 @@ -package mount +package mount // import "github.com/docker/docker/pkg/mount" import ( "golang.org/x/sys/unix" diff --git a/vendor/github.com/docker/docker/pkg/mount/flags_unsupported.go b/vendor/github.com/docker/docker/pkg/mount/flags_unsupported.go index 43d5e339f0..cc6c475908 100644 --- a/vendor/github.com/docker/docker/pkg/mount/flags_unsupported.go +++ b/vendor/github.com/docker/docker/pkg/mount/flags_unsupported.go @@ -1,6 +1,6 @@ // +build !linux,!freebsd freebsd,!cgo -package mount +package mount // import "github.com/docker/docker/pkg/mount" // These flags are unsupported. const ( diff --git a/vendor/github.com/docker/docker/pkg/mount/mount.go b/vendor/github.com/docker/docker/pkg/mount/mount.go index ee5833c49d..874aff6545 100644 --- a/vendor/github.com/docker/docker/pkg/mount/mount.go +++ b/vendor/github.com/docker/docker/pkg/mount/mount.go @@ -1,32 +1,66 @@ -package mount +package mount // import "github.com/docker/docker/pkg/mount" import ( "sort" "strings" + "syscall" "github.com/sirupsen/logrus" ) -// GetMounts retrieves a list of mounts for the current running process. -func GetMounts() ([]*Info, error) { - return parseMountTable() +// FilterFunc is a type defining a callback function +// to filter out unwanted entries. It takes a pointer +// to an Info struct (not fully populated, currently +// only Mountpoint is filled in), and returns two booleans: +// - skip: true if the entry should be skipped +// - stop: true if parsing should be stopped after the entry +type FilterFunc func(*Info) (skip, stop bool) + +// PrefixFilter discards all entries whose mount points +// do not start with a prefix specified +func PrefixFilter(prefix string) FilterFunc { + return func(m *Info) (bool, bool) { + skip := !strings.HasPrefix(m.Mountpoint, prefix) + return skip, false + } +} + +// SingleEntryFilter looks for a specific entry +func SingleEntryFilter(mp string) FilterFunc { + return func(m *Info) (bool, bool) { + if m.Mountpoint == mp { + return false, true // don't skip, stop now + } + return true, false // skip, keep going + } +} + +// ParentsFilter returns all entries whose mount points +// can be parents of a path specified, discarding others. +// For example, given `/var/lib/docker/something`, entries +// like `/var/lib/docker`, `/var` and `/` are returned. +func ParentsFilter(path string) FilterFunc { + return func(m *Info) (bool, bool) { + skip := !strings.HasPrefix(path, m.Mountpoint) + return skip, false + } +} + +// GetMounts retrieves a list of mounts for the current running process, +// with an optional filter applied (use nil for no filter). +func GetMounts(f FilterFunc) ([]*Info, error) { + return parseMountTable(f) } // Mounted determines if a specified mountpoint has been mounted. // On Linux it looks at /proc/self/mountinfo. func Mounted(mountpoint string) (bool, error) { - entries, err := parseMountTable() + entries, err := GetMounts(SingleEntryFilter(mountpoint)) if err != nil { return false, err } - // Search the table for the mountpoint - for _, e := range entries { - if e.Mountpoint == mountpoint { - return true, nil - } - } - return false, nil + return len(entries) > 0, nil } // Mount will mount filesystem according to the specified configuration, on the @@ -55,40 +89,53 @@ func ForceMount(device, target, mType, options string) error { // Unmount lazily unmounts a filesystem on supported platforms, otherwise // does a normal unmount. func Unmount(target string) error { - if mounted, err := Mounted(target); err != nil || !mounted { - return err + err := unmount(target, mntDetach) + if err == syscall.EINVAL { + // ignore "not mounted" error + err = nil } - return unmount(target, mntDetach) + return err } // RecursiveUnmount unmounts the target and all mounts underneath, starting with // the deepsest mount first. func RecursiveUnmount(target string) error { - mounts, err := GetMounts() + mounts, err := parseMountTable(PrefixFilter(target)) if err != nil { return err } // Make the deepest mount be first - sort.Sort(sort.Reverse(byMountpoint(mounts))) + sort.Slice(mounts, func(i, j int) bool { + return len(mounts[i].Mountpoint) > len(mounts[j].Mountpoint) + }) for i, m := range mounts { - if !strings.HasPrefix(m.Mountpoint, target) { - continue - } logrus.Debugf("Trying to unmount %s", m.Mountpoint) - err = Unmount(m.Mountpoint) - if err != nil && i == len(mounts)-1 { - if mounted, err := Mounted(m.Mountpoint); err != nil || mounted { - return err + err = unmount(m.Mountpoint, mntDetach) + if err != nil { + // If the error is EINVAL either this whole package is wrong (invalid flags passed to unmount(2)) or this is + // not a mountpoint (which is ok in this case). + // Meanwhile calling `Mounted()` is very expensive. + // + // We've purposefully used `syscall.EINVAL` here instead of `unix.EINVAL` to avoid platform branching + // Since `EINVAL` is defined for both Windows and Linux in the `syscall` package (and other platforms), + // this is nicer than defining a custom value that we can refer to in each platform file. + if err == syscall.EINVAL { + continue + } + if i == len(mounts)-1 { + if mounted, e := Mounted(m.Mountpoint); e != nil || mounted { + return err + } + continue } - // Ignore errors for submounts and continue trying to unmount others - // The final unmount should fail if there ane any submounts remaining - } else if err != nil { - logrus.Errorf("Failed to unmount %s: %v", m.Mountpoint, err) - } else if err == nil { - logrus.Debugf("Unmounted %s", m.Mountpoint) + // This is some submount, we can ignore this error for now, the final unmount will fail if this is a real problem + logrus.WithError(err).Warnf("Failed to unmount submount %s", m.Mountpoint) + continue } + + logrus.Debugf("Unmounted %s", m.Mountpoint) } return nil } diff --git a/vendor/github.com/docker/docker/pkg/mount/mounter_freebsd.go b/vendor/github.com/docker/docker/pkg/mount/mounter_freebsd.go index 814896cc9e..b6ab83a230 100644 --- a/vendor/github.com/docker/docker/pkg/mount/mounter_freebsd.go +++ b/vendor/github.com/docker/docker/pkg/mount/mounter_freebsd.go @@ -1,4 +1,4 @@ -package mount +package mount // import "github.com/docker/docker/pkg/mount" /* #include diff --git a/vendor/github.com/docker/docker/pkg/mount/mounter_linux.go b/vendor/github.com/docker/docker/pkg/mount/mounter_linux.go index 39c36d472a..631daf10a5 100644 --- a/vendor/github.com/docker/docker/pkg/mount/mounter_linux.go +++ b/vendor/github.com/docker/docker/pkg/mount/mounter_linux.go @@ -1,4 +1,4 @@ -package mount +package mount // import "github.com/docker/docker/pkg/mount" import ( "golang.org/x/sys/unix" diff --git a/vendor/github.com/docker/docker/pkg/mount/mounter_unsupported.go b/vendor/github.com/docker/docker/pkg/mount/mounter_unsupported.go index eb93365eb7..1428dffa52 100644 --- a/vendor/github.com/docker/docker/pkg/mount/mounter_unsupported.go +++ b/vendor/github.com/docker/docker/pkg/mount/mounter_unsupported.go @@ -1,6 +1,6 @@ // +build !linux,!freebsd freebsd,!cgo -package mount +package mount // import "github.com/docker/docker/pkg/mount" func mount(device, target, mType string, flag uintptr, data string) error { panic("Not implemented") diff --git a/vendor/github.com/docker/docker/pkg/mount/mountinfo.go b/vendor/github.com/docker/docker/pkg/mount/mountinfo.go index ff4cc1d86b..ecd03fc022 100644 --- a/vendor/github.com/docker/docker/pkg/mount/mountinfo.go +++ b/vendor/github.com/docker/docker/pkg/mount/mountinfo.go @@ -1,4 +1,4 @@ -package mount +package mount // import "github.com/docker/docker/pkg/mount" // Info reveals information about a particular mounted filesystem. This // struct is populated from the content in the /proc//mountinfo file. @@ -38,17 +38,3 @@ type Info struct { // VfsOpts represents per super block options. VfsOpts string } - -type byMountpoint []*Info - -func (by byMountpoint) Len() int { - return len(by) -} - -func (by byMountpoint) Less(i, j int) bool { - return by[i].Mountpoint < by[j].Mountpoint -} - -func (by byMountpoint) Swap(i, j int) { - by[i], by[j] = by[j], by[i] -} diff --git a/vendor/github.com/docker/docker/pkg/mount/mountinfo_freebsd.go b/vendor/github.com/docker/docker/pkg/mount/mountinfo_freebsd.go index 4f32edcd90..36c89dc1a2 100644 --- a/vendor/github.com/docker/docker/pkg/mount/mountinfo_freebsd.go +++ b/vendor/github.com/docker/docker/pkg/mount/mountinfo_freebsd.go @@ -1,4 +1,4 @@ -package mount +package mount // import "github.com/docker/docker/pkg/mount" /* #include @@ -15,7 +15,7 @@ import ( // Parse /proc/self/mountinfo because comparing Dev and ino does not work from // bind mounts. -func parseMountTable() ([]*Info, error) { +func parseMountTable(filter FilterFunc) ([]*Info, error) { var rawEntries *C.struct_statfs count := int(C.getmntinfo(&rawEntries, C.MNT_WAIT)) @@ -32,10 +32,24 @@ func parseMountTable() ([]*Info, error) { var out []*Info for _, entry := range entries { var mountinfo Info + var skip, stop bool mountinfo.Mountpoint = C.GoString(&entry.f_mntonname[0]) + + if filter != nil { + // filter out entries we're not interested in + skip, stop = filter(p) + if skip { + continue + } + } + mountinfo.Source = C.GoString(&entry.f_mntfromname[0]) mountinfo.Fstype = C.GoString(&entry.f_fstypename[0]) + out = append(out, &mountinfo) + if stop { + break + } } return out, nil } diff --git a/vendor/github.com/docker/docker/pkg/mount/mountinfo_linux.go b/vendor/github.com/docker/docker/pkg/mount/mountinfo_linux.go index be69fee1d7..c1dba01fc3 100644 --- a/vendor/github.com/docker/docker/pkg/mount/mountinfo_linux.go +++ b/vendor/github.com/docker/docker/pkg/mount/mountinfo_linux.go @@ -1,86 +1,123 @@ -// +build linux - -package mount +package mount // import "github.com/docker/docker/pkg/mount" import ( "bufio" "fmt" "io" "os" + "strconv" "strings" ) -const ( - /* 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue - (1)(2)(3) (4) (5) (6) (7) (8) (9) (10) (11) +func parseInfoFile(r io.Reader, filter FilterFunc) ([]*Info, error) { + s := bufio.NewScanner(r) + out := []*Info{} + for s.Scan() { + if err := s.Err(); err != nil { + return nil, err + } + /* + 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue + (1)(2)(3) (4) (5) (6) (7) (8) (9) (10) (11) - (1) mount ID: unique identifier of the mount (may be reused after umount) - (2) parent ID: ID of parent (or of self for the top of the mount tree) - (3) major:minor: value of st_dev for files on filesystem - (4) root: root of the mount within the filesystem - (5) mount point: mount point relative to the process's root - (6) mount options: per mount options - (7) optional fields: zero or more fields of the form "tag[:value]" - (8) separator: marks the end of the optional fields - (9) filesystem type: name of filesystem of the form "type[.subtype]" - (10) mount source: filesystem specific information or "none" - (11) super options: per super block options*/ - mountinfoFormat = "%d %d %d:%d %s %s %s %s" -) + (1) mount ID: unique identifier of the mount (may be reused after umount) + (2) parent ID: ID of parent (or of self for the top of the mount tree) + (3) major:minor: value of st_dev for files on filesystem + (4) root: root of the mount within the filesystem + (5) mount point: mount point relative to the process's root + (6) mount options: per mount options + (7) optional fields: zero or more fields of the form "tag[:value]" + (8) separator: marks the end of the optional fields + (9) filesystem type: name of filesystem of the form "type[.subtype]" + (10) mount source: filesystem specific information or "none" + (11) super options: per super block options + */ -// Parse /proc/self/mountinfo because comparing Dev and ino does not work from -// bind mounts -func parseMountTable() ([]*Info, error) { - f, err := os.Open("/proc/self/mountinfo") - if err != nil { - return nil, err - } - defer f.Close() + text := s.Text() + fields := strings.Split(text, " ") + numFields := len(fields) + if numFields < 10 { + // should be at least 10 fields + return nil, fmt.Errorf("Parsing '%s' failed: not enough fields (%d)", text, numFields) + } - return parseInfoFile(f) -} + p := &Info{} + // ignore any numbers parsing errors, as there should not be any + p.ID, _ = strconv.Atoi(fields[0]) + p.Parent, _ = strconv.Atoi(fields[1]) + mm := strings.Split(fields[2], ":") + if len(mm) != 2 { + return nil, fmt.Errorf("Parsing '%s' failed: unexpected minor:major pair %s", text, mm) + } + p.Major, _ = strconv.Atoi(mm[0]) + p.Minor, _ = strconv.Atoi(mm[1]) -func parseInfoFile(r io.Reader) ([]*Info, error) { - var ( - s = bufio.NewScanner(r) - out = []*Info{} - ) + p.Root = fields[3] + p.Mountpoint = fields[4] + p.Opts = fields[5] - for s.Scan() { - if err := s.Err(); err != nil { - return nil, err + var skip, stop bool + if filter != nil { + // filter out entries we're not interested in + skip, stop = filter(p) + if skip { + continue + } } - var ( - p = &Info{} - text = s.Text() - optionalFields string - ) - - if _, err := fmt.Sscanf(text, mountinfoFormat, - &p.ID, &p.Parent, &p.Major, &p.Minor, - &p.Root, &p.Mountpoint, &p.Opts, &optionalFields); err != nil { - return nil, fmt.Errorf("Scanning '%s' failed: %s", text, err) + // one or more optional fields, when a separator (-) + i := 6 + for ; i < numFields && fields[i] != "-"; i++ { + switch i { + case 6: + p.Optional = fields[6] + default: + /* NOTE there might be more optional fields before the such as + fields[7]...fields[N] (where N < sepIndex), although + as of Linux kernel 4.15 the only known ones are + mount propagation flags in fields[6]. The correct + behavior is to ignore any unknown optional fields. + */ + break + } } - // Safe as mountinfo encodes mountpoints with spaces as \040. - index := strings.Index(text, " - ") - postSeparatorFields := strings.Fields(text[index+3:]) - if len(postSeparatorFields) < 3 { - return nil, fmt.Errorf("Error found less than 3 fields post '-' in %q", text) + if i == numFields { + return nil, fmt.Errorf("Parsing '%s' failed: missing separator ('-')", text) } - if optionalFields != "-" { - p.Optional = optionalFields + // There should be 3 fields after the separator... + if i+4 > numFields { + return nil, fmt.Errorf("Parsing '%s' failed: not enough fields after a separator", text) } + // ... but in Linux <= 3.9 mounting a cifs with spaces in a share name + // (like "//serv/My Documents") _may_ end up having a space in the last field + // of mountinfo (like "unc=//serv/My Documents"). Since kernel 3.10-rc1, cifs + // option unc= is ignored, so a space should not appear. In here we ignore + // those "extra" fields caused by extra spaces. + p.Fstype = fields[i+1] + p.Source = fields[i+2] + p.VfsOpts = fields[i+3] - p.Fstype = postSeparatorFields[0] - p.Source = postSeparatorFields[1] - p.VfsOpts = strings.Join(postSeparatorFields[2:], " ") out = append(out, p) + if stop { + break + } } return out, nil } +// Parse /proc/self/mountinfo because comparing Dev and ino does not work from +// bind mounts +func parseMountTable(filter FilterFunc) ([]*Info, error) { + f, err := os.Open("/proc/self/mountinfo") + if err != nil { + return nil, err + } + defer f.Close() + + return parseInfoFile(f, filter) +} + // PidMountInfo collects the mounts for a specific process ID. If the process // ID is unknown, it is better to use `GetMounts` which will inspect // "/proc/self/mountinfo" instead. @@ -91,5 +128,5 @@ func PidMountInfo(pid int) ([]*Info, error) { } defer f.Close() - return parseInfoFile(f) + return parseInfoFile(f, nil) } diff --git a/vendor/github.com/docker/docker/pkg/mount/mountinfo_unsupported.go b/vendor/github.com/docker/docker/pkg/mount/mountinfo_unsupported.go index b8d9aa5c73..fd16d3ed69 100644 --- a/vendor/github.com/docker/docker/pkg/mount/mountinfo_unsupported.go +++ b/vendor/github.com/docker/docker/pkg/mount/mountinfo_unsupported.go @@ -1,12 +1,12 @@ // +build !windows,!linux,!freebsd freebsd,!cgo -package mount +package mount // import "github.com/docker/docker/pkg/mount" import ( "fmt" "runtime" ) -func parseMountTable() ([]*Info, error) { +func parseMountTable(f FilterFunc) ([]*Info, error) { return nil, fmt.Errorf("mount.parseMountTable is not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) } diff --git a/vendor/github.com/docker/docker/pkg/mount/mountinfo_windows.go b/vendor/github.com/docker/docker/pkg/mount/mountinfo_windows.go index dab8a37ed0..27e0f6976e 100644 --- a/vendor/github.com/docker/docker/pkg/mount/mountinfo_windows.go +++ b/vendor/github.com/docker/docker/pkg/mount/mountinfo_windows.go @@ -1,6 +1,6 @@ -package mount +package mount // import "github.com/docker/docker/pkg/mount" -func parseMountTable() ([]*Info, error) { +func parseMountTable(f FilterFunc) ([]*Info, error) { // Do NOT return an error! return nil, nil } diff --git a/vendor/github.com/docker/docker/pkg/mount/sharedsubtree_linux.go b/vendor/github.com/docker/docker/pkg/mount/sharedsubtree_linux.go index 8ceec84bc6..538f6637a0 100644 --- a/vendor/github.com/docker/docker/pkg/mount/sharedsubtree_linux.go +++ b/vendor/github.com/docker/docker/pkg/mount/sharedsubtree_linux.go @@ -1,6 +1,4 @@ -// +build linux - -package mount +package mount // import "github.com/docker/docker/pkg/mount" // MakeShared ensures a mounted filesystem has the SHARED mount option enabled. // See the supported options in flags.go for further reference. diff --git a/vendor/github.com/docker/docker/pkg/pools/pools.go b/vendor/github.com/docker/docker/pkg/pools/pools.go index 6a111a3ba7..46339c282f 100644 --- a/vendor/github.com/docker/docker/pkg/pools/pools.go +++ b/vendor/github.com/docker/docker/pkg/pools/pools.go @@ -7,7 +7,7 @@ // // Utility functions which operate on pools should be added to this // package to allow them to be reused. -package pools +package pools // import "github.com/docker/docker/pkg/pools" import ( "bufio" diff --git a/vendor/github.com/docker/docker/pkg/stdcopy/stdcopy.go b/vendor/github.com/docker/docker/pkg/stdcopy/stdcopy.go index a018a203f3..8f6e0a737a 100644 --- a/vendor/github.com/docker/docker/pkg/stdcopy/stdcopy.go +++ b/vendor/github.com/docker/docker/pkg/stdcopy/stdcopy.go @@ -1,4 +1,4 @@ -package stdcopy +package stdcopy // import "github.com/docker/docker/pkg/stdcopy" import ( "bytes" @@ -21,7 +21,7 @@ const ( // Stderr represents standard error steam type. Stderr // Systemerr represents errors originating from the system that make it - // into the the multiplexed stream. + // into the multiplexed stream. Systemerr stdWriterPrefixLen = 8 diff --git a/vendor/github.com/docker/docker/pkg/system/chtimes.go b/vendor/github.com/docker/docker/pkg/system/chtimes.go index 056d19954d..c26a4e24b6 100644 --- a/vendor/github.com/docker/docker/pkg/system/chtimes.go +++ b/vendor/github.com/docker/docker/pkg/system/chtimes.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" import ( "os" @@ -27,9 +27,5 @@ func Chtimes(name string, atime time.Time, mtime time.Time) error { } // Take platform specific action for setting create time. - if err := setCTime(name, mtime); err != nil { - return err - } - - return nil + return setCTime(name, mtime) } diff --git a/vendor/github.com/docker/docker/pkg/system/chtimes_unix.go b/vendor/github.com/docker/docker/pkg/system/chtimes_unix.go index 09d58bcbfd..259138a45b 100644 --- a/vendor/github.com/docker/docker/pkg/system/chtimes_unix.go +++ b/vendor/github.com/docker/docker/pkg/system/chtimes_unix.go @@ -1,6 +1,6 @@ // +build !windows -package system +package system // import "github.com/docker/docker/pkg/system" import ( "time" diff --git a/vendor/github.com/docker/docker/pkg/system/chtimes_windows.go b/vendor/github.com/docker/docker/pkg/system/chtimes_windows.go index 45428c141c..d3a115ff42 100644 --- a/vendor/github.com/docker/docker/pkg/system/chtimes_windows.go +++ b/vendor/github.com/docker/docker/pkg/system/chtimes_windows.go @@ -1,6 +1,4 @@ -// +build windows - -package system +package system // import "github.com/docker/docker/pkg/system" import ( "time" diff --git a/vendor/github.com/docker/docker/pkg/system/errors.go b/vendor/github.com/docker/docker/pkg/system/errors.go index 288318985e..2573d71622 100644 --- a/vendor/github.com/docker/docker/pkg/system/errors.go +++ b/vendor/github.com/docker/docker/pkg/system/errors.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" import ( "errors" @@ -7,4 +7,7 @@ import ( var ( // ErrNotSupportedPlatform means the platform is not supported. ErrNotSupportedPlatform = errors.New("platform and architecture is not supported") + + // ErrNotSupportedOperatingSystem means the operating system is not supported. + ErrNotSupportedOperatingSystem = errors.New("operating system is not supported") ) diff --git a/vendor/github.com/docker/docker/pkg/system/exitcode.go b/vendor/github.com/docker/docker/pkg/system/exitcode.go index a5e5616c4f..4ba8fe35bf 100644 --- a/vendor/github.com/docker/docker/pkg/system/exitcode.go +++ b/vendor/github.com/docker/docker/pkg/system/exitcode.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" import ( "fmt" diff --git a/vendor/github.com/docker/docker/pkg/system/filesys.go b/vendor/github.com/docker/docker/pkg/system/filesys.go index 102565f760..adeb163052 100644 --- a/vendor/github.com/docker/docker/pkg/system/filesys.go +++ b/vendor/github.com/docker/docker/pkg/system/filesys.go @@ -1,6 +1,6 @@ // +build !windows -package system +package system // import "github.com/docker/docker/pkg/system" import ( "io/ioutil" diff --git a/vendor/github.com/docker/docker/pkg/system/filesys_windows.go b/vendor/github.com/docker/docker/pkg/system/filesys_windows.go index a61b53d0ba..a1f6013f13 100644 --- a/vendor/github.com/docker/docker/pkg/system/filesys_windows.go +++ b/vendor/github.com/docker/docker/pkg/system/filesys_windows.go @@ -1,6 +1,4 @@ -// +build windows - -package system +package system // import "github.com/docker/docker/pkg/system" import ( "os" diff --git a/vendor/github.com/docker/docker/pkg/system/init.go b/vendor/github.com/docker/docker/pkg/system/init.go index 17935088de..a17597aaba 100644 --- a/vendor/github.com/docker/docker/pkg/system/init.go +++ b/vendor/github.com/docker/docker/pkg/system/init.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" import ( "syscall" diff --git a/vendor/github.com/docker/docker/pkg/system/init_unix.go b/vendor/github.com/docker/docker/pkg/system/init_unix.go index a219895e6d..4996a67c12 100644 --- a/vendor/github.com/docker/docker/pkg/system/init_unix.go +++ b/vendor/github.com/docker/docker/pkg/system/init_unix.go @@ -1,6 +1,6 @@ // +build !windows -package system +package system // import "github.com/docker/docker/pkg/system" // InitLCOW does nothing since LCOW is a windows only feature func InitLCOW(experimental bool) { diff --git a/vendor/github.com/docker/docker/pkg/system/init_windows.go b/vendor/github.com/docker/docker/pkg/system/init_windows.go index 75f8f2c061..4910ff69d6 100644 --- a/vendor/github.com/docker/docker/pkg/system/init_windows.go +++ b/vendor/github.com/docker/docker/pkg/system/init_windows.go @@ -1,17 +1,12 @@ -package system - -import "os" +package system // import "github.com/docker/docker/pkg/system" // lcowSupported determines if Linux Containers on Windows are supported. var lcowSupported = false // InitLCOW sets whether LCOW is supported or not -// TODO @jhowardmsft. -// 1. Replace with RS3 RTM build number. -// 2. Remove the getenv check when image-store is coalesced as shouldn't be needed anymore. func InitLCOW(experimental bool) { v := GetOSVersion() - if experimental && v.Build > 16270 && os.Getenv("LCOW_SUPPORTED") != "" { + if experimental && v.Build >= 16299 { lcowSupported = true } } diff --git a/vendor/github.com/docker/docker/pkg/system/lcow.go b/vendor/github.com/docker/docker/pkg/system/lcow.go index b88c11e316..5c3fbfe6f4 100644 --- a/vendor/github.com/docker/docker/pkg/system/lcow.go +++ b/vendor/github.com/docker/docker/pkg/system/lcow.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" import ( "fmt" @@ -56,3 +56,14 @@ func ParsePlatform(in string) *specs.Platform { } return p } + +// IsOSSupported determines if an operating system is supported by the host +func IsOSSupported(os string) bool { + if runtime.GOOS == os { + return true + } + if LCOWSupported() && os == "linux" { + return true + } + return false +} diff --git a/vendor/github.com/docker/docker/pkg/system/lcow_unix.go b/vendor/github.com/docker/docker/pkg/system/lcow_unix.go index cff33bb408..26397fb8a1 100644 --- a/vendor/github.com/docker/docker/pkg/system/lcow_unix.go +++ b/vendor/github.com/docker/docker/pkg/system/lcow_unix.go @@ -1,6 +1,6 @@ // +build !windows -package system +package system // import "github.com/docker/docker/pkg/system" // LCOWSupported returns true if Linux containers on Windows are supported. func LCOWSupported() bool { diff --git a/vendor/github.com/docker/docker/pkg/system/lcow_windows.go b/vendor/github.com/docker/docker/pkg/system/lcow_windows.go index e54d01e696..f0139df8f7 100644 --- a/vendor/github.com/docker/docker/pkg/system/lcow_windows.go +++ b/vendor/github.com/docker/docker/pkg/system/lcow_windows.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" // LCOWSupported returns true if Linux containers on Windows are supported. func LCOWSupported() bool { diff --git a/vendor/github.com/docker/docker/pkg/system/lstat_unix.go b/vendor/github.com/docker/docker/pkg/system/lstat_unix.go index bd23c4d50b..7477995f1b 100644 --- a/vendor/github.com/docker/docker/pkg/system/lstat_unix.go +++ b/vendor/github.com/docker/docker/pkg/system/lstat_unix.go @@ -1,6 +1,6 @@ // +build !windows -package system +package system // import "github.com/docker/docker/pkg/system" import ( "syscall" diff --git a/vendor/github.com/docker/docker/pkg/system/lstat_windows.go b/vendor/github.com/docker/docker/pkg/system/lstat_windows.go index e51df0dafe..359c791d9b 100644 --- a/vendor/github.com/docker/docker/pkg/system/lstat_windows.go +++ b/vendor/github.com/docker/docker/pkg/system/lstat_windows.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" import "os" diff --git a/vendor/github.com/docker/docker/pkg/system/meminfo.go b/vendor/github.com/docker/docker/pkg/system/meminfo.go index 3b6e947e67..6667eb84dc 100644 --- a/vendor/github.com/docker/docker/pkg/system/meminfo.go +++ b/vendor/github.com/docker/docker/pkg/system/meminfo.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" // MemInfo contains memory statistics of the host system. type MemInfo struct { diff --git a/vendor/github.com/docker/docker/pkg/system/meminfo_linux.go b/vendor/github.com/docker/docker/pkg/system/meminfo_linux.go index 385f1d5e73..d79e8b0765 100644 --- a/vendor/github.com/docker/docker/pkg/system/meminfo_linux.go +++ b/vendor/github.com/docker/docker/pkg/system/meminfo_linux.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" import ( "bufio" diff --git a/vendor/github.com/docker/docker/pkg/system/meminfo_unsupported.go b/vendor/github.com/docker/docker/pkg/system/meminfo_unsupported.go index 82ddd30c1b..56f4494268 100644 --- a/vendor/github.com/docker/docker/pkg/system/meminfo_unsupported.go +++ b/vendor/github.com/docker/docker/pkg/system/meminfo_unsupported.go @@ -1,6 +1,6 @@ // +build !linux,!windows -package system +package system // import "github.com/docker/docker/pkg/system" // ReadMemInfo is not supported on platforms other than linux and windows. func ReadMemInfo() (*MemInfo, error) { diff --git a/vendor/github.com/docker/docker/pkg/system/meminfo_windows.go b/vendor/github.com/docker/docker/pkg/system/meminfo_windows.go index 883944a4c5..6ed93f2fe2 100644 --- a/vendor/github.com/docker/docker/pkg/system/meminfo_windows.go +++ b/vendor/github.com/docker/docker/pkg/system/meminfo_windows.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" import ( "unsafe" diff --git a/vendor/github.com/docker/docker/pkg/system/mknod.go b/vendor/github.com/docker/docker/pkg/system/mknod.go index 2200ec42da..b132482e03 100644 --- a/vendor/github.com/docker/docker/pkg/system/mknod.go +++ b/vendor/github.com/docker/docker/pkg/system/mknod.go @@ -1,6 +1,6 @@ // +build !windows -package system +package system // import "github.com/docker/docker/pkg/system" import ( "golang.org/x/sys/unix" diff --git a/vendor/github.com/docker/docker/pkg/system/mknod_windows.go b/vendor/github.com/docker/docker/pkg/system/mknod_windows.go index 2e863c0215..ec89d7a15e 100644 --- a/vendor/github.com/docker/docker/pkg/system/mknod_windows.go +++ b/vendor/github.com/docker/docker/pkg/system/mknod_windows.go @@ -1,6 +1,4 @@ -// +build windows - -package system +package system // import "github.com/docker/docker/pkg/system" // Mknod is not implemented on Windows. func Mknod(path string, mode uint32, dev int) error { diff --git a/vendor/github.com/docker/docker/pkg/system/path.go b/vendor/github.com/docker/docker/pkg/system/path.go index 034c33c877..a3d957afab 100644 --- a/vendor/github.com/docker/docker/pkg/system/path.go +++ b/vendor/github.com/docker/docker/pkg/system/path.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" import ( "fmt" @@ -35,7 +35,7 @@ func DefaultPathEnv(os string) string { // This is used, for example, when validating a user provided path in docker cp. // If a drive letter is supplied, it must be the system drive. The drive letter // is always removed. Also, it translates it to OS semantics (IOW / to \). We -// need the path in this syntax so that it can ultimately be contatenated with +// need the path in this syntax so that it can ultimately be concatenated with // a Windows long-path which doesn't support drive-letters. Examples: // C: --> Fail // C:\ --> \ diff --git a/vendor/github.com/docker/docker/pkg/system/process_unix.go b/vendor/github.com/docker/docker/pkg/system/process_unix.go index 02c138235a..0195a891b2 100644 --- a/vendor/github.com/docker/docker/pkg/system/process_unix.go +++ b/vendor/github.com/docker/docker/pkg/system/process_unix.go @@ -1,6 +1,6 @@ // +build linux freebsd darwin -package system +package system // import "github.com/docker/docker/pkg/system" import ( "syscall" diff --git a/vendor/github.com/docker/docker/pkg/system/process_windows.go b/vendor/github.com/docker/docker/pkg/system/process_windows.go index 5973c46de9..4e70c97b18 100644 --- a/vendor/github.com/docker/docker/pkg/system/process_windows.go +++ b/vendor/github.com/docker/docker/pkg/system/process_windows.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" import "os" diff --git a/vendor/github.com/docker/docker/pkg/system/rm.go b/vendor/github.com/docker/docker/pkg/system/rm.go index c453adcdb9..02e4d26221 100644 --- a/vendor/github.com/docker/docker/pkg/system/rm.go +++ b/vendor/github.com/docker/docker/pkg/system/rm.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" import ( "os" diff --git a/vendor/github.com/docker/docker/pkg/system/stat_darwin.go b/vendor/github.com/docker/docker/pkg/system/stat_darwin.go index 715f05b938..c1c0ee9f38 100644 --- a/vendor/github.com/docker/docker/pkg/system/stat_darwin.go +++ b/vendor/github.com/docker/docker/pkg/system/stat_darwin.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" import "syscall" diff --git a/vendor/github.com/docker/docker/pkg/system/stat_freebsd.go b/vendor/github.com/docker/docker/pkg/system/stat_freebsd.go index 715f05b938..c1c0ee9f38 100644 --- a/vendor/github.com/docker/docker/pkg/system/stat_freebsd.go +++ b/vendor/github.com/docker/docker/pkg/system/stat_freebsd.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" import "syscall" diff --git a/vendor/github.com/docker/docker/pkg/system/stat_linux.go b/vendor/github.com/docker/docker/pkg/system/stat_linux.go index 1939f95181..98c9eb18d1 100644 --- a/vendor/github.com/docker/docker/pkg/system/stat_linux.go +++ b/vendor/github.com/docker/docker/pkg/system/stat_linux.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" import "syscall" diff --git a/vendor/github.com/docker/docker/pkg/system/stat_openbsd.go b/vendor/github.com/docker/docker/pkg/system/stat_openbsd.go index b607dea946..756b92d1e6 100644 --- a/vendor/github.com/docker/docker/pkg/system/stat_openbsd.go +++ b/vendor/github.com/docker/docker/pkg/system/stat_openbsd.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" import "syscall" diff --git a/vendor/github.com/docker/docker/pkg/system/stat_solaris.go b/vendor/github.com/docker/docker/pkg/system/stat_solaris.go index b607dea946..756b92d1e6 100644 --- a/vendor/github.com/docker/docker/pkg/system/stat_solaris.go +++ b/vendor/github.com/docker/docker/pkg/system/stat_solaris.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" import "syscall" diff --git a/vendor/github.com/docker/docker/pkg/system/stat_unix.go b/vendor/github.com/docker/docker/pkg/system/stat_unix.go index 91c7d121cc..3d7e2ebbef 100644 --- a/vendor/github.com/docker/docker/pkg/system/stat_unix.go +++ b/vendor/github.com/docker/docker/pkg/system/stat_unix.go @@ -1,6 +1,6 @@ // +build !windows -package system +package system // import "github.com/docker/docker/pkg/system" import ( "syscall" @@ -47,6 +47,11 @@ func (s StatT) Mtim() syscall.Timespec { return s.mtim } +// IsDir reports whether s describes a directory. +func (s StatT) IsDir() bool { + return s.mode&syscall.S_IFDIR != 0 +} + // Stat takes a path to a file and returns // a system.StatT type pertaining to that file. // diff --git a/vendor/github.com/docker/docker/pkg/system/stat_windows.go b/vendor/github.com/docker/docker/pkg/system/stat_windows.go index 6c63972682..b2456cb887 100644 --- a/vendor/github.com/docker/docker/pkg/system/stat_windows.go +++ b/vendor/github.com/docker/docker/pkg/system/stat_windows.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" import ( "os" diff --git a/vendor/github.com/docker/docker/pkg/system/syscall_unix.go b/vendor/github.com/docker/docker/pkg/system/syscall_unix.go index 49dbdd3781..919a412a7b 100644 --- a/vendor/github.com/docker/docker/pkg/system/syscall_unix.go +++ b/vendor/github.com/docker/docker/pkg/system/syscall_unix.go @@ -1,6 +1,6 @@ // +build linux freebsd -package system +package system // import "github.com/docker/docker/pkg/system" import "golang.org/x/sys/unix" diff --git a/vendor/github.com/docker/docker/pkg/system/syscall_windows.go b/vendor/github.com/docker/docker/pkg/system/syscall_windows.go index 23e9b207c7..ee7e0256f3 100644 --- a/vendor/github.com/docker/docker/pkg/system/syscall_windows.go +++ b/vendor/github.com/docker/docker/pkg/system/syscall_windows.go @@ -1,6 +1,7 @@ -package system +package system // import "github.com/docker/docker/pkg/system" import ( + "fmt" "unsafe" "github.com/sirupsen/logrus" @@ -53,6 +54,10 @@ func GetOSVersion() OSVersion { return osv } +func (osv OSVersion) ToString() string { + return fmt.Sprintf("%d.%d.%d", osv.MajorVersion, osv.MinorVersion, osv.Build) +} + // IsWindowsClient returns true if the SKU is client // @engine maintainers - this function should not be removed or modified as it // is used to enforce licensing restrictions on Windows. diff --git a/vendor/github.com/docker/docker/pkg/system/umask.go b/vendor/github.com/docker/docker/pkg/system/umask.go index 5a10eda5af..9912a2babb 100644 --- a/vendor/github.com/docker/docker/pkg/system/umask.go +++ b/vendor/github.com/docker/docker/pkg/system/umask.go @@ -1,6 +1,6 @@ // +build !windows -package system +package system // import "github.com/docker/docker/pkg/system" import ( "golang.org/x/sys/unix" diff --git a/vendor/github.com/docker/docker/pkg/system/umask_windows.go b/vendor/github.com/docker/docker/pkg/system/umask_windows.go index 13f1de1769..fc62388c38 100644 --- a/vendor/github.com/docker/docker/pkg/system/umask_windows.go +++ b/vendor/github.com/docker/docker/pkg/system/umask_windows.go @@ -1,6 +1,4 @@ -// +build windows - -package system +package system // import "github.com/docker/docker/pkg/system" // Umask is not supported on the windows platform. func Umask(newmask int) (oldmask int, err error) { diff --git a/vendor/github.com/docker/docker/pkg/system/utimes_freebsd.go b/vendor/github.com/docker/docker/pkg/system/utimes_freebsd.go index 6a77524376..ed1b9fad59 100644 --- a/vendor/github.com/docker/docker/pkg/system/utimes_freebsd.go +++ b/vendor/github.com/docker/docker/pkg/system/utimes_freebsd.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" import ( "syscall" diff --git a/vendor/github.com/docker/docker/pkg/system/utimes_linux.go b/vendor/github.com/docker/docker/pkg/system/utimes_linux.go index edc588a63f..0afe854589 100644 --- a/vendor/github.com/docker/docker/pkg/system/utimes_linux.go +++ b/vendor/github.com/docker/docker/pkg/system/utimes_linux.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" import ( "syscall" diff --git a/vendor/github.com/docker/docker/pkg/system/utimes_unsupported.go b/vendor/github.com/docker/docker/pkg/system/utimes_unsupported.go index 139714544d..095e072e1d 100644 --- a/vendor/github.com/docker/docker/pkg/system/utimes_unsupported.go +++ b/vendor/github.com/docker/docker/pkg/system/utimes_unsupported.go @@ -1,6 +1,6 @@ // +build !linux,!freebsd -package system +package system // import "github.com/docker/docker/pkg/system" import "syscall" diff --git a/vendor/github.com/docker/docker/pkg/system/xattrs_linux.go b/vendor/github.com/docker/docker/pkg/system/xattrs_linux.go index 98b111be42..66d4895b27 100644 --- a/vendor/github.com/docker/docker/pkg/system/xattrs_linux.go +++ b/vendor/github.com/docker/docker/pkg/system/xattrs_linux.go @@ -1,4 +1,4 @@ -package system +package system // import "github.com/docker/docker/pkg/system" import "golang.org/x/sys/unix" diff --git a/vendor/github.com/docker/docker/pkg/system/xattrs_unsupported.go b/vendor/github.com/docker/docker/pkg/system/xattrs_unsupported.go index 0114f2227c..d780a90cd3 100644 --- a/vendor/github.com/docker/docker/pkg/system/xattrs_unsupported.go +++ b/vendor/github.com/docker/docker/pkg/system/xattrs_unsupported.go @@ -1,6 +1,6 @@ // +build !linux -package system +package system // import "github.com/docker/docker/pkg/system" // Lgetxattr is not supported on platforms other than linux. func Lgetxattr(path string, attr string) ([]byte, error) { diff --git a/vendor/github.com/docker/docker/pkg/term/ascii.go b/vendor/github.com/docker/docker/pkg/term/ascii.go deleted file mode 100644 index 55873c0556..0000000000 --- a/vendor/github.com/docker/docker/pkg/term/ascii.go +++ /dev/null @@ -1,66 +0,0 @@ -package term - -import ( - "fmt" - "strings" -) - -// ASCII list the possible supported ASCII key sequence -var ASCII = []string{ - "ctrl-@", - "ctrl-a", - "ctrl-b", - "ctrl-c", - "ctrl-d", - "ctrl-e", - "ctrl-f", - "ctrl-g", - "ctrl-h", - "ctrl-i", - "ctrl-j", - "ctrl-k", - "ctrl-l", - "ctrl-m", - "ctrl-n", - "ctrl-o", - "ctrl-p", - "ctrl-q", - "ctrl-r", - "ctrl-s", - "ctrl-t", - "ctrl-u", - "ctrl-v", - "ctrl-w", - "ctrl-x", - "ctrl-y", - "ctrl-z", - "ctrl-[", - "ctrl-\\", - "ctrl-]", - "ctrl-^", - "ctrl-_", -} - -// ToBytes converts a string representing a suite of key-sequence to the corresponding ASCII code. -func ToBytes(keys string) ([]byte, error) { - codes := []byte{} -next: - for _, key := range strings.Split(keys, ",") { - if len(key) != 1 { - for code, ctrl := range ASCII { - if ctrl == key { - codes = append(codes, byte(code)) - continue next - } - } - if key == "DEL" { - codes = append(codes, 127) - } else { - return nil, fmt.Errorf("Unknown character: '%s'", key) - } - } else { - codes = append(codes, key[0]) - } - } - return codes, nil -} diff --git a/vendor/github.com/docker/docker/pkg/term/proxy.go b/vendor/github.com/docker/docker/pkg/term/proxy.go deleted file mode 100644 index e648eb8120..0000000000 --- a/vendor/github.com/docker/docker/pkg/term/proxy.go +++ /dev/null @@ -1,74 +0,0 @@ -package term - -import ( - "io" -) - -// EscapeError is special error which returned by a TTY proxy reader's Read() -// method in case its detach escape sequence is read. -type EscapeError struct{} - -func (EscapeError) Error() string { - return "read escape sequence" -} - -// escapeProxy is used only for attaches with a TTY. It is used to proxy -// stdin keypresses from the underlying reader and look for the passed in -// escape key sequence to signal a detach. -type escapeProxy struct { - escapeKeys []byte - escapeKeyPos int - r io.Reader -} - -// NewEscapeProxy returns a new TTY proxy reader which wraps the given reader -// and detects when the specified escape keys are read, in which case the Read -// method will return an error of type EscapeError. -func NewEscapeProxy(r io.Reader, escapeKeys []byte) io.Reader { - return &escapeProxy{ - escapeKeys: escapeKeys, - r: r, - } -} - -func (r *escapeProxy) Read(buf []byte) (int, error) { - nr, err := r.r.Read(buf) - - preserve := func() { - // this preserves the original key presses in the passed in buffer - nr += r.escapeKeyPos - preserve := make([]byte, 0, r.escapeKeyPos+len(buf)) - preserve = append(preserve, r.escapeKeys[:r.escapeKeyPos]...) - preserve = append(preserve, buf...) - r.escapeKeyPos = 0 - copy(buf[0:nr], preserve) - } - - if nr != 1 || err != nil { - if r.escapeKeyPos > 0 { - preserve() - } - return nr, err - } - - if buf[0] != r.escapeKeys[r.escapeKeyPos] { - if r.escapeKeyPos > 0 { - preserve() - } - return nr, nil - } - - if r.escapeKeyPos == len(r.escapeKeys)-1 { - return 0, EscapeError{} - } - - // Looks like we've got an escape key, but we need to match again on the next - // read. - // Store the current escape key we found so we can look for the next one on - // the next read. - // Since this is an escape key, make sure we don't let the caller read it - // If later on we find that this is not the escape sequence, we'll add the - // keys back - r.escapeKeyPos++ - return nr - r.escapeKeyPos, nil -} diff --git a/vendor/github.com/docker/docker/pkg/term/tc.go b/vendor/github.com/docker/docker/pkg/term/tc.go deleted file mode 100644 index 19dbb1cb11..0000000000 --- a/vendor/github.com/docker/docker/pkg/term/tc.go +++ /dev/null @@ -1,20 +0,0 @@ -// +build !windows - -package term - -import ( - "syscall" - "unsafe" - - "golang.org/x/sys/unix" -) - -func tcget(fd uintptr, p *Termios) syscall.Errno { - _, _, err := unix.Syscall(unix.SYS_IOCTL, fd, uintptr(getTermios), uintptr(unsafe.Pointer(p))) - return err -} - -func tcset(fd uintptr, p *Termios) syscall.Errno { - _, _, err := unix.Syscall(unix.SYS_IOCTL, fd, setTermios, uintptr(unsafe.Pointer(p))) - return err -} diff --git a/vendor/github.com/docker/docker/pkg/term/term.go b/vendor/github.com/docker/docker/pkg/term/term.go deleted file mode 100644 index 4f59d8d938..0000000000 --- a/vendor/github.com/docker/docker/pkg/term/term.go +++ /dev/null @@ -1,124 +0,0 @@ -// +build !windows - -// Package term provides structures and helper functions to work with -// terminal (state, sizes). -package term - -import ( - "errors" - "fmt" - "io" - "os" - "os/signal" - - "golang.org/x/sys/unix" -) - -var ( - // ErrInvalidState is returned if the state of the terminal is invalid. - ErrInvalidState = errors.New("Invalid terminal state") -) - -// State represents the state of the terminal. -type State struct { - termios Termios -} - -// Winsize represents the size of the terminal window. -type Winsize struct { - Height uint16 - Width uint16 - x uint16 - y uint16 -} - -// StdStreams returns the standard streams (stdin, stdout, stderr). -func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { - return os.Stdin, os.Stdout, os.Stderr -} - -// GetFdInfo returns the file descriptor for an os.File and indicates whether the file represents a terminal. -func GetFdInfo(in interface{}) (uintptr, bool) { - var inFd uintptr - var isTerminalIn bool - if file, ok := in.(*os.File); ok { - inFd = file.Fd() - isTerminalIn = IsTerminal(inFd) - } - return inFd, isTerminalIn -} - -// IsTerminal returns true if the given file descriptor is a terminal. -func IsTerminal(fd uintptr) bool { - var termios Termios - return tcget(fd, &termios) == 0 -} - -// RestoreTerminal restores the terminal connected to the given file descriptor -// to a previous state. -func RestoreTerminal(fd uintptr, state *State) error { - if state == nil { - return ErrInvalidState - } - if err := tcset(fd, &state.termios); err != 0 { - return err - } - return nil -} - -// SaveState saves the state of the terminal connected to the given file descriptor. -func SaveState(fd uintptr) (*State, error) { - var oldState State - if err := tcget(fd, &oldState.termios); err != 0 { - return nil, err - } - - return &oldState, nil -} - -// DisableEcho applies the specified state to the terminal connected to the file -// descriptor, with echo disabled. -func DisableEcho(fd uintptr, state *State) error { - newState := state.termios - newState.Lflag &^= unix.ECHO - - if err := tcset(fd, &newState); err != 0 { - return err - } - handleInterrupt(fd, state) - return nil -} - -// SetRawTerminal puts the terminal connected to the given file descriptor into -// raw mode and returns the previous state. On UNIX, this puts both the input -// and output into raw mode. On Windows, it only puts the input into raw mode. -func SetRawTerminal(fd uintptr) (*State, error) { - oldState, err := MakeRaw(fd) - if err != nil { - return nil, err - } - handleInterrupt(fd, oldState) - return oldState, err -} - -// SetRawTerminalOutput puts the output of terminal connected to the given file -// descriptor into raw mode. On UNIX, this does nothing and returns nil for the -// state. On Windows, it disables LF -> CRLF translation. -func SetRawTerminalOutput(fd uintptr) (*State, error) { - return nil, nil -} - -func handleInterrupt(fd uintptr, state *State) { - sigchan := make(chan os.Signal, 1) - signal.Notify(sigchan, os.Interrupt) - go func() { - for range sigchan { - // quit cleanly and the new terminal item is on a new line - fmt.Println() - signal.Stop(sigchan) - close(sigchan) - RestoreTerminal(fd, state) - os.Exit(1) - } - }() -} diff --git a/vendor/github.com/docker/docker/pkg/term/term_windows.go b/vendor/github.com/docker/docker/pkg/term/term_windows.go deleted file mode 100644 index b6819b3426..0000000000 --- a/vendor/github.com/docker/docker/pkg/term/term_windows.go +++ /dev/null @@ -1,230 +0,0 @@ -// +build windows - -package term - -import ( - "io" - "os" - "os/signal" - "syscall" // used for STD_INPUT_HANDLE, STD_OUTPUT_HANDLE and STD_ERROR_HANDLE - - "github.com/Azure/go-ansiterm/winterm" - "github.com/docker/docker/pkg/term/windows" -) - -// State holds the console mode for the terminal. -type State struct { - mode uint32 -} - -// Winsize is used for window size. -type Winsize struct { - Height uint16 - Width uint16 -} - -// vtInputSupported is true if winterm.ENABLE_VIRTUAL_TERMINAL_INPUT is supported by the console -var vtInputSupported bool - -// StdStreams returns the standard streams (stdin, stdout, stderr). -func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { - // Turn on VT handling on all std handles, if possible. This might - // fail, in which case we will fall back to terminal emulation. - var emulateStdin, emulateStdout, emulateStderr bool - fd := os.Stdin.Fd() - if mode, err := winterm.GetConsoleMode(fd); err == nil { - // Validate that winterm.ENABLE_VIRTUAL_TERMINAL_INPUT is supported, but do not set it. - if err = winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_INPUT); err != nil { - emulateStdin = true - } else { - vtInputSupported = true - } - // Unconditionally set the console mode back even on failure because SetConsoleMode - // remembers invalid bits on input handles. - winterm.SetConsoleMode(fd, mode) - } - - fd = os.Stdout.Fd() - if mode, err := winterm.GetConsoleMode(fd); err == nil { - // Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it. - if err = winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING|winterm.DISABLE_NEWLINE_AUTO_RETURN); err != nil { - emulateStdout = true - } else { - winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING) - } - } - - fd = os.Stderr.Fd() - if mode, err := winterm.GetConsoleMode(fd); err == nil { - // Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it. - if err = winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING|winterm.DISABLE_NEWLINE_AUTO_RETURN); err != nil { - emulateStderr = true - } else { - winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING) - } - } - - if os.Getenv("ConEmuANSI") == "ON" || os.Getenv("ConsoleZVersion") != "" { - // The ConEmu and ConsoleZ terminals emulate ANSI on output streams well. - emulateStdin = true - emulateStdout = false - emulateStderr = false - } - - // Temporarily use STD_INPUT_HANDLE, STD_OUTPUT_HANDLE and - // STD_ERROR_HANDLE from syscall rather than x/sys/windows as long as - // go-ansiterm hasn't switch to x/sys/windows. - // TODO: switch back to x/sys/windows once go-ansiterm has switched - if emulateStdin { - stdIn = windowsconsole.NewAnsiReader(syscall.STD_INPUT_HANDLE) - } else { - stdIn = os.Stdin - } - - if emulateStdout { - stdOut = windowsconsole.NewAnsiWriter(syscall.STD_OUTPUT_HANDLE) - } else { - stdOut = os.Stdout - } - - if emulateStderr { - stdErr = windowsconsole.NewAnsiWriter(syscall.STD_ERROR_HANDLE) - } else { - stdErr = os.Stderr - } - - return -} - -// GetFdInfo returns the file descriptor for an os.File and indicates whether the file represents a terminal. -func GetFdInfo(in interface{}) (uintptr, bool) { - return windowsconsole.GetHandleInfo(in) -} - -// GetWinsize returns the window size based on the specified file descriptor. -func GetWinsize(fd uintptr) (*Winsize, error) { - info, err := winterm.GetConsoleScreenBufferInfo(fd) - if err != nil { - return nil, err - } - - winsize := &Winsize{ - Width: uint16(info.Window.Right - info.Window.Left + 1), - Height: uint16(info.Window.Bottom - info.Window.Top + 1), - } - - return winsize, nil -} - -// IsTerminal returns true if the given file descriptor is a terminal. -func IsTerminal(fd uintptr) bool { - return windowsconsole.IsConsole(fd) -} - -// RestoreTerminal restores the terminal connected to the given file descriptor -// to a previous state. -func RestoreTerminal(fd uintptr, state *State) error { - return winterm.SetConsoleMode(fd, state.mode) -} - -// SaveState saves the state of the terminal connected to the given file descriptor. -func SaveState(fd uintptr) (*State, error) { - mode, e := winterm.GetConsoleMode(fd) - if e != nil { - return nil, e - } - - return &State{mode: mode}, nil -} - -// DisableEcho disables echo for the terminal connected to the given file descriptor. -// -- See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx -func DisableEcho(fd uintptr, state *State) error { - mode := state.mode - mode &^= winterm.ENABLE_ECHO_INPUT - mode |= winterm.ENABLE_PROCESSED_INPUT | winterm.ENABLE_LINE_INPUT - err := winterm.SetConsoleMode(fd, mode) - if err != nil { - return err - } - - // Register an interrupt handler to catch and restore prior state - restoreAtInterrupt(fd, state) - return nil -} - -// SetRawTerminal puts the terminal connected to the given file descriptor into -// raw mode and returns the previous state. On UNIX, this puts both the input -// and output into raw mode. On Windows, it only puts the input into raw mode. -func SetRawTerminal(fd uintptr) (*State, error) { - state, err := MakeRaw(fd) - if err != nil { - return nil, err - } - - // Register an interrupt handler to catch and restore prior state - restoreAtInterrupt(fd, state) - return state, err -} - -// SetRawTerminalOutput puts the output of terminal connected to the given file -// descriptor into raw mode. On UNIX, this does nothing and returns nil for the -// state. On Windows, it disables LF -> CRLF translation. -func SetRawTerminalOutput(fd uintptr) (*State, error) { - state, err := SaveState(fd) - if err != nil { - return nil, err - } - - // Ignore failures, since winterm.DISABLE_NEWLINE_AUTO_RETURN might not be supported on this - // version of Windows. - winterm.SetConsoleMode(fd, state.mode|winterm.DISABLE_NEWLINE_AUTO_RETURN) - return state, err -} - -// MakeRaw puts the terminal (Windows Console) connected to the given file descriptor into raw -// mode and returns the previous state of the terminal so that it can be restored. -func MakeRaw(fd uintptr) (*State, error) { - state, err := SaveState(fd) - if err != nil { - return nil, err - } - - mode := state.mode - - // See - // -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx - // -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx - - // Disable these modes - mode &^= winterm.ENABLE_ECHO_INPUT - mode &^= winterm.ENABLE_LINE_INPUT - mode &^= winterm.ENABLE_MOUSE_INPUT - mode &^= winterm.ENABLE_WINDOW_INPUT - mode &^= winterm.ENABLE_PROCESSED_INPUT - - // Enable these modes - mode |= winterm.ENABLE_EXTENDED_FLAGS - mode |= winterm.ENABLE_INSERT_MODE - mode |= winterm.ENABLE_QUICK_EDIT_MODE - if vtInputSupported { - mode |= winterm.ENABLE_VIRTUAL_TERMINAL_INPUT - } - - err = winterm.SetConsoleMode(fd, mode) - if err != nil { - return nil, err - } - return state, nil -} - -func restoreAtInterrupt(fd uintptr, state *State) { - sigchan := make(chan os.Signal, 1) - signal.Notify(sigchan, os.Interrupt) - - go func() { - _ = <-sigchan - RestoreTerminal(fd, state) - os.Exit(0) - }() -} diff --git a/vendor/github.com/docker/docker/pkg/term/termios_bsd.go b/vendor/github.com/docker/docker/pkg/term/termios_bsd.go deleted file mode 100644 index c47341e873..0000000000 --- a/vendor/github.com/docker/docker/pkg/term/termios_bsd.go +++ /dev/null @@ -1,42 +0,0 @@ -// +build darwin freebsd openbsd - -package term - -import ( - "unsafe" - - "golang.org/x/sys/unix" -) - -const ( - getTermios = unix.TIOCGETA - setTermios = unix.TIOCSETA -) - -// Termios is the Unix API for terminal I/O. -type Termios unix.Termios - -// MakeRaw put the terminal connected to the given file descriptor into raw -// mode and returns the previous state of the terminal so that it can be -// restored. -func MakeRaw(fd uintptr) (*State, error) { - var oldState State - if _, _, err := unix.Syscall(unix.SYS_IOCTL, fd, getTermios, uintptr(unsafe.Pointer(&oldState.termios))); err != 0 { - return nil, err - } - - newState := oldState.termios - newState.Iflag &^= (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON) - newState.Oflag &^= unix.OPOST - newState.Lflag &^= (unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN) - newState.Cflag &^= (unix.CSIZE | unix.PARENB) - newState.Cflag |= unix.CS8 - newState.Cc[unix.VMIN] = 1 - newState.Cc[unix.VTIME] = 0 - - if _, _, err := unix.Syscall(unix.SYS_IOCTL, fd, setTermios, uintptr(unsafe.Pointer(&newState))); err != 0 { - return nil, err - } - - return &oldState, nil -} diff --git a/vendor/github.com/docker/docker/pkg/term/termios_linux.go b/vendor/github.com/docker/docker/pkg/term/termios_linux.go deleted file mode 100644 index 0f21abcc2f..0000000000 --- a/vendor/github.com/docker/docker/pkg/term/termios_linux.go +++ /dev/null @@ -1,39 +0,0 @@ -package term - -import ( - "golang.org/x/sys/unix" -) - -const ( - getTermios = unix.TCGETS - setTermios = unix.TCSETS -) - -// Termios is the Unix API for terminal I/O. -type Termios unix.Termios - -// MakeRaw put the terminal connected to the given file descriptor into raw -// mode and returns the previous state of the terminal so that it can be -// restored. -func MakeRaw(fd uintptr) (*State, error) { - termios, err := unix.IoctlGetTermios(int(fd), getTermios) - if err != nil { - return nil, err - } - - var oldState State - oldState.termios = Termios(*termios) - - termios.Iflag &^= (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON) - termios.Oflag &^= unix.OPOST - termios.Lflag &^= (unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN) - termios.Cflag &^= (unix.CSIZE | unix.PARENB) - termios.Cflag |= unix.CS8 - termios.Cc[unix.VMIN] = 1 - termios.Cc[unix.VTIME] = 0 - - if err := unix.IoctlSetTermios(int(fd), setTermios, termios); err != nil { - return nil, err - } - return &oldState, nil -} diff --git a/vendor/github.com/docker/docker/pkg/term/windows/ansi_reader.go b/vendor/github.com/docker/docker/pkg/term/windows/ansi_reader.go deleted file mode 100644 index 29d3963187..0000000000 --- a/vendor/github.com/docker/docker/pkg/term/windows/ansi_reader.go +++ /dev/null @@ -1,263 +0,0 @@ -// +build windows - -package windowsconsole - -import ( - "bytes" - "errors" - "fmt" - "io" - "os" - "strings" - "unsafe" - - ansiterm "github.com/Azure/go-ansiterm" - "github.com/Azure/go-ansiterm/winterm" -) - -const ( - escapeSequence = ansiterm.KEY_ESC_CSI -) - -// ansiReader wraps a standard input file (e.g., os.Stdin) providing ANSI sequence translation. -type ansiReader struct { - file *os.File - fd uintptr - buffer []byte - cbBuffer int - command []byte -} - -// NewAnsiReader returns an io.ReadCloser that provides VT100 terminal emulation on top of a -// Windows console input handle. -func NewAnsiReader(nFile int) io.ReadCloser { - initLogger() - file, fd := winterm.GetStdFile(nFile) - return &ansiReader{ - file: file, - fd: fd, - command: make([]byte, 0, ansiterm.ANSI_MAX_CMD_LENGTH), - buffer: make([]byte, 0), - } -} - -// Close closes the wrapped file. -func (ar *ansiReader) Close() (err error) { - return ar.file.Close() -} - -// Fd returns the file descriptor of the wrapped file. -func (ar *ansiReader) Fd() uintptr { - return ar.fd -} - -// Read reads up to len(p) bytes of translated input events into p. -func (ar *ansiReader) Read(p []byte) (int, error) { - if len(p) == 0 { - return 0, nil - } - - // Previously read bytes exist, read as much as we can and return - if len(ar.buffer) > 0 { - logger.Debugf("Reading previously cached bytes") - - originalLength := len(ar.buffer) - copiedLength := copy(p, ar.buffer) - - if copiedLength == originalLength { - ar.buffer = make([]byte, 0, len(p)) - } else { - ar.buffer = ar.buffer[copiedLength:] - } - - logger.Debugf("Read from cache p[%d]: % x", copiedLength, p) - return copiedLength, nil - } - - // Read and translate key events - events, err := readInputEvents(ar.fd, len(p)) - if err != nil { - return 0, err - } else if len(events) == 0 { - logger.Debug("No input events detected") - return 0, nil - } - - keyBytes := translateKeyEvents(events, []byte(escapeSequence)) - - // Save excess bytes and right-size keyBytes - if len(keyBytes) > len(p) { - logger.Debugf("Received %d keyBytes, only room for %d bytes", len(keyBytes), len(p)) - ar.buffer = keyBytes[len(p):] - keyBytes = keyBytes[:len(p)] - } else if len(keyBytes) == 0 { - logger.Debug("No key bytes returned from the translator") - return 0, nil - } - - copiedLength := copy(p, keyBytes) - if copiedLength != len(keyBytes) { - return 0, errors.New("unexpected copy length encountered") - } - - logger.Debugf("Read p[%d]: % x", copiedLength, p) - logger.Debugf("Read keyBytes[%d]: % x", copiedLength, keyBytes) - return copiedLength, nil -} - -// readInputEvents polls until at least one event is available. -func readInputEvents(fd uintptr, maxBytes int) ([]winterm.INPUT_RECORD, error) { - // Determine the maximum number of records to retrieve - // -- Cast around the type system to obtain the size of a single INPUT_RECORD. - // unsafe.Sizeof requires an expression vs. a type-reference; the casting - // tricks the type system into believing it has such an expression. - recordSize := int(unsafe.Sizeof(*((*winterm.INPUT_RECORD)(unsafe.Pointer(&maxBytes))))) - countRecords := maxBytes / recordSize - if countRecords > ansiterm.MAX_INPUT_EVENTS { - countRecords = ansiterm.MAX_INPUT_EVENTS - } else if countRecords == 0 { - countRecords = 1 - } - logger.Debugf("[windows] readInputEvents: Reading %v records (buffer size %v, record size %v)", countRecords, maxBytes, recordSize) - - // Wait for and read input events - events := make([]winterm.INPUT_RECORD, countRecords) - nEvents := uint32(0) - eventsExist, err := winterm.WaitForSingleObject(fd, winterm.WAIT_INFINITE) - if err != nil { - return nil, err - } - - if eventsExist { - err = winterm.ReadConsoleInput(fd, events, &nEvents) - if err != nil { - return nil, err - } - } - - // Return a slice restricted to the number of returned records - logger.Debugf("[windows] readInputEvents: Read %v events", nEvents) - return events[:nEvents], nil -} - -// KeyEvent Translation Helpers - -var arrowKeyMapPrefix = map[uint16]string{ - winterm.VK_UP: "%s%sA", - winterm.VK_DOWN: "%s%sB", - winterm.VK_RIGHT: "%s%sC", - winterm.VK_LEFT: "%s%sD", -} - -var keyMapPrefix = map[uint16]string{ - winterm.VK_UP: "\x1B[%sA", - winterm.VK_DOWN: "\x1B[%sB", - winterm.VK_RIGHT: "\x1B[%sC", - winterm.VK_LEFT: "\x1B[%sD", - winterm.VK_HOME: "\x1B[1%s~", // showkey shows ^[[1 - winterm.VK_END: "\x1B[4%s~", // showkey shows ^[[4 - winterm.VK_INSERT: "\x1B[2%s~", - winterm.VK_DELETE: "\x1B[3%s~", - winterm.VK_PRIOR: "\x1B[5%s~", - winterm.VK_NEXT: "\x1B[6%s~", - winterm.VK_F1: "", - winterm.VK_F2: "", - winterm.VK_F3: "\x1B[13%s~", - winterm.VK_F4: "\x1B[14%s~", - winterm.VK_F5: "\x1B[15%s~", - winterm.VK_F6: "\x1B[17%s~", - winterm.VK_F7: "\x1B[18%s~", - winterm.VK_F8: "\x1B[19%s~", - winterm.VK_F9: "\x1B[20%s~", - winterm.VK_F10: "\x1B[21%s~", - winterm.VK_F11: "\x1B[23%s~", - winterm.VK_F12: "\x1B[24%s~", -} - -// translateKeyEvents converts the input events into the appropriate ANSI string. -func translateKeyEvents(events []winterm.INPUT_RECORD, escapeSequence []byte) []byte { - var buffer bytes.Buffer - for _, event := range events { - if event.EventType == winterm.KEY_EVENT && event.KeyEvent.KeyDown != 0 { - buffer.WriteString(keyToString(&event.KeyEvent, escapeSequence)) - } - } - - return buffer.Bytes() -} - -// keyToString maps the given input event record to the corresponding string. -func keyToString(keyEvent *winterm.KEY_EVENT_RECORD, escapeSequence []byte) string { - if keyEvent.UnicodeChar == 0 { - return formatVirtualKey(keyEvent.VirtualKeyCode, keyEvent.ControlKeyState, escapeSequence) - } - - _, alt, control := getControlKeys(keyEvent.ControlKeyState) - if control { - // TODO(azlinux): Implement following control sequences - // -D Signals the end of input from the keyboard; also exits current shell. - // -H Deletes the first character to the left of the cursor. Also called the ERASE key. - // -Q Restarts printing after it has been stopped with -s. - // -S Suspends printing on the screen (does not stop the program). - // -U Deletes all characters on the current line. Also called the KILL key. - // -E Quits current command and creates a core - - } - - // +Key generates ESC N Key - if !control && alt { - return ansiterm.KEY_ESC_N + strings.ToLower(string(keyEvent.UnicodeChar)) - } - - return string(keyEvent.UnicodeChar) -} - -// formatVirtualKey converts a virtual key (e.g., up arrow) into the appropriate ANSI string. -func formatVirtualKey(key uint16, controlState uint32, escapeSequence []byte) string { - shift, alt, control := getControlKeys(controlState) - modifier := getControlKeysModifier(shift, alt, control) - - if format, ok := arrowKeyMapPrefix[key]; ok { - return fmt.Sprintf(format, escapeSequence, modifier) - } - - if format, ok := keyMapPrefix[key]; ok { - return fmt.Sprintf(format, modifier) - } - - return "" -} - -// getControlKeys extracts the shift, alt, and ctrl key states. -func getControlKeys(controlState uint32) (shift, alt, control bool) { - shift = 0 != (controlState & winterm.SHIFT_PRESSED) - alt = 0 != (controlState & (winterm.LEFT_ALT_PRESSED | winterm.RIGHT_ALT_PRESSED)) - control = 0 != (controlState & (winterm.LEFT_CTRL_PRESSED | winterm.RIGHT_CTRL_PRESSED)) - return shift, alt, control -} - -// getControlKeysModifier returns the ANSI modifier for the given combination of control keys. -func getControlKeysModifier(shift, alt, control bool) string { - if shift && alt && control { - return ansiterm.KEY_CONTROL_PARAM_8 - } - if alt && control { - return ansiterm.KEY_CONTROL_PARAM_7 - } - if shift && control { - return ansiterm.KEY_CONTROL_PARAM_6 - } - if control { - return ansiterm.KEY_CONTROL_PARAM_5 - } - if shift && alt { - return ansiterm.KEY_CONTROL_PARAM_4 - } - if alt { - return ansiterm.KEY_CONTROL_PARAM_3 - } - if shift { - return ansiterm.KEY_CONTROL_PARAM_2 - } - return "" -} diff --git a/vendor/github.com/docker/docker/pkg/term/windows/ansi_writer.go b/vendor/github.com/docker/docker/pkg/term/windows/ansi_writer.go deleted file mode 100644 index 256577e1f2..0000000000 --- a/vendor/github.com/docker/docker/pkg/term/windows/ansi_writer.go +++ /dev/null @@ -1,64 +0,0 @@ -// +build windows - -package windowsconsole - -import ( - "io" - "os" - - ansiterm "github.com/Azure/go-ansiterm" - "github.com/Azure/go-ansiterm/winterm" -) - -// ansiWriter wraps a standard output file (e.g., os.Stdout) providing ANSI sequence translation. -type ansiWriter struct { - file *os.File - fd uintptr - infoReset *winterm.CONSOLE_SCREEN_BUFFER_INFO - command []byte - escapeSequence []byte - inAnsiSequence bool - parser *ansiterm.AnsiParser -} - -// NewAnsiWriter returns an io.Writer that provides VT100 terminal emulation on top of a -// Windows console output handle. -func NewAnsiWriter(nFile int) io.Writer { - initLogger() - file, fd := winterm.GetStdFile(nFile) - info, err := winterm.GetConsoleScreenBufferInfo(fd) - if err != nil { - return nil - } - - parser := ansiterm.CreateParser("Ground", winterm.CreateWinEventHandler(fd, file)) - logger.Infof("newAnsiWriter: parser %p", parser) - - aw := &ansiWriter{ - file: file, - fd: fd, - infoReset: info, - command: make([]byte, 0, ansiterm.ANSI_MAX_CMD_LENGTH), - escapeSequence: []byte(ansiterm.KEY_ESC_CSI), - parser: parser, - } - - logger.Infof("newAnsiWriter: aw.parser %p", aw.parser) - logger.Infof("newAnsiWriter: %v", aw) - return aw -} - -func (aw *ansiWriter) Fd() uintptr { - return aw.fd -} - -// Write writes len(p) bytes from p to the underlying data stream. -func (aw *ansiWriter) Write(p []byte) (total int, err error) { - if len(p) == 0 { - return 0, nil - } - - logger.Infof("Write: % x", p) - logger.Infof("Write: %s", string(p)) - return aw.parser.Parse(p) -} diff --git a/vendor/github.com/docker/docker/pkg/term/windows/console.go b/vendor/github.com/docker/docker/pkg/term/windows/console.go deleted file mode 100644 index 4bad32ea78..0000000000 --- a/vendor/github.com/docker/docker/pkg/term/windows/console.go +++ /dev/null @@ -1,35 +0,0 @@ -// +build windows - -package windowsconsole - -import ( - "os" - - "github.com/Azure/go-ansiterm/winterm" -) - -// GetHandleInfo returns file descriptor and bool indicating whether the file is a console. -func GetHandleInfo(in interface{}) (uintptr, bool) { - switch t := in.(type) { - case *ansiReader: - return t.Fd(), true - case *ansiWriter: - return t.Fd(), true - } - - var inFd uintptr - var isTerminal bool - - if file, ok := in.(*os.File); ok { - inFd = file.Fd() - isTerminal = IsConsole(inFd) - } - return inFd, isTerminal -} - -// IsConsole returns true if the given file descriptor is a Windows Console. -// The code assumes that GetConsoleMode will return an error for file descriptors that are not a console. -func IsConsole(fd uintptr) bool { - _, e := winterm.GetConsoleMode(fd) - return e == nil -} diff --git a/vendor/github.com/docker/docker/pkg/term/windows/windows.go b/vendor/github.com/docker/docker/pkg/term/windows/windows.go deleted file mode 100644 index c02a93a03f..0000000000 --- a/vendor/github.com/docker/docker/pkg/term/windows/windows.go +++ /dev/null @@ -1,33 +0,0 @@ -// These files implement ANSI-aware input and output streams for use by the Docker Windows client. -// When asked for the set of standard streams (e.g., stdin, stdout, stderr), the code will create -// and return pseudo-streams that convert ANSI sequences to / from Windows Console API calls. - -package windowsconsole - -import ( - "io/ioutil" - "os" - "sync" - - ansiterm "github.com/Azure/go-ansiterm" - "github.com/sirupsen/logrus" -) - -var logger *logrus.Logger -var initOnce sync.Once - -func initLogger() { - initOnce.Do(func() { - logFile := ioutil.Discard - - if isDebugEnv := os.Getenv(ansiterm.LogEnv); isDebugEnv == "1" { - logFile, _ = os.Create("ansiReaderWriter.log") - } - - logger = &logrus.Logger{ - Out: logFile, - Formatter: new(logrus.TextFormatter), - Level: logrus.DebugLevel, - } - }) -} diff --git a/vendor/github.com/docker/libnetwork/LICENSE b/vendor/github.com/docker/libnetwork/LICENSE new file mode 100644 index 0000000000..e06d208186 --- /dev/null +++ b/vendor/github.com/docker/libnetwork/LICENSE @@ -0,0 +1,202 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/vendor/gopkg.in/inf.v0/LICENSE b/vendor/github.com/docker/libnetwork/client/mflag/LICENSE similarity index 93% rename from vendor/gopkg.in/inf.v0/LICENSE rename to vendor/github.com/docker/libnetwork/client/mflag/LICENSE index 87a5cede33..9b4f4a294e 100644 --- a/vendor/gopkg.in/inf.v0/LICENSE +++ b/vendor/github.com/docker/libnetwork/client/mflag/LICENSE @@ -1,5 +1,4 @@ -Copyright (c) 2012 Péter Surányi. Portions Copyright (c) 2009 The Go -Authors. All rights reserved. +Copyright (c) 2014-2016 The Docker & Go Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/vendor/github.com/docker/libnetwork/ipamutils/utils.go b/vendor/github.com/docker/libnetwork/ipamutils/utils.go new file mode 100644 index 0000000000..f8eca58e8c --- /dev/null +++ b/vendor/github.com/docker/libnetwork/ipamutils/utils.go @@ -0,0 +1,96 @@ +// Package ipamutils provides utility functions for ipam management +package ipamutils + +import ( + "fmt" + "net" + "sync" + + "github.com/sirupsen/logrus" +) + +var ( + // PredefinedBroadNetworks contains a list of 31 IPv4 private networks with host size 16 and 12 + // (172.17-31.x.x/16, 192.168.x.x/20) which do not overlap with the networks in `PredefinedGranularNetworks` + PredefinedBroadNetworks []*net.IPNet + // PredefinedGranularNetworks contains a list of 64K IPv4 private networks with host size 8 + // (10.x.x.x/24) which do not overlap with the networks in `PredefinedBroadNetworks` + PredefinedGranularNetworks []*net.IPNet + initNetworksOnce sync.Once + + defaultBroadNetwork = []*NetworkToSplit{{"172.17.0.0/16", 16}, {"172.18.0.0/16", 16}, {"172.19.0.0/16", 16}, + {"172.20.0.0/14", 16}, {"172.24.0.0/14", 16}, {"172.28.0.0/14", 16}, + {"192.168.0.0/16", 20}} + defaultGranularNetwork = []*NetworkToSplit{{"10.0.0.0/8", 24}} +) + +// NetworkToSplit represent a network that has to be split in chunks with mask length Size. +// Each subnet in the set is derived from the Base pool. Base is to be passed +// in CIDR format. +// Example: a Base "10.10.0.0/16 with Size 24 will define the set of 256 +// 10.10.[0-255].0/24 address pools +type NetworkToSplit struct { + Base string `json:"base"` + Size int `json:"size"` +} + +// InitNetworks initializes the broad network pool and the granular network pool +func InitNetworks(defaultAddressPool []*NetworkToSplit) { + initNetworksOnce.Do(func() { + // error ingnored should never fail + PredefinedGranularNetworks, _ = splitNetworks(defaultGranularNetwork) + if defaultAddressPool == nil { + defaultAddressPool = defaultBroadNetwork + } + var err error + if PredefinedBroadNetworks, err = splitNetworks(defaultAddressPool); err != nil { + logrus.WithError(err).Error("InitAddressPools failed to initialize the default address pool") + } + }) +} + +// splitNetworks takes a slice of networks, split them accordingly and returns them +func splitNetworks(list []*NetworkToSplit) ([]*net.IPNet, error) { + localPools := make([]*net.IPNet, 0, len(list)) + + for _, p := range list { + _, b, err := net.ParseCIDR(p.Base) + if err != nil { + return nil, fmt.Errorf("invalid base pool %q: %v", p.Base, err) + } + ones, _ := b.Mask.Size() + if p.Size <= 0 || p.Size < ones { + return nil, fmt.Errorf("invalid pools size: %d", p.Size) + } + localPools = append(localPools, splitNetwork(p.Size, b)...) + } + return localPools, nil +} + +func splitNetwork(size int, base *net.IPNet) []*net.IPNet { + one, bits := base.Mask.Size() + mask := net.CIDRMask(size, bits) + n := 1 << uint(size-one) + s := uint(bits - size) + list := make([]*net.IPNet, 0, n) + + for i := 0; i < n; i++ { + ip := copyIP(base.IP) + addIntToIP(ip, uint(i<= 0; i-- { + array[i] |= (byte)(ordinal & 0xff) + ordinal >>= 8 + } +} diff --git a/vendor/github.com/eapache/go-resiliency/breaker/README.md b/vendor/github.com/eapache/go-resiliency/breaker/README.md index 7262bfc282..2d1b3d9322 100644 --- a/vendor/github.com/eapache/go-resiliency/breaker/README.md +++ b/vendor/github.com/eapache/go-resiliency/breaker/README.md @@ -3,6 +3,7 @@ circuit-breaker [![Build Status](https://travis-ci.org/eapache/go-resiliency.svg?branch=master)](https://travis-ci.org/eapache/go-resiliency) [![GoDoc](https://godoc.org/github.com/eapache/go-resiliency/breaker?status.svg)](https://godoc.org/github.com/eapache/go-resiliency/breaker) +[![Code of Conduct](https://img.shields.io/badge/code%20of%20conduct-active-blue.svg)](https://eapache.github.io/conduct.html) The circuit-breaker resiliency pattern for golang. diff --git a/vendor/github.com/eapache/go-xerial-snappy/fuzz.go b/vendor/github.com/eapache/go-xerial-snappy/fuzz.go new file mode 100644 index 0000000000..6a46f4784e --- /dev/null +++ b/vendor/github.com/eapache/go-xerial-snappy/fuzz.go @@ -0,0 +1,16 @@ +// +build gofuzz + +package snappy + +func Fuzz(data []byte) int { + decode, err := Decode(data) + if decode == nil && err == nil { + panic("nil error with nil result") + } + + if err != nil { + return 0 + } + + return 1 +} diff --git a/vendor/github.com/eapache/go-xerial-snappy/snappy.go b/vendor/github.com/eapache/go-xerial-snappy/snappy.go index b8f8b51fce..de69eacbb3 100644 --- a/vendor/github.com/eapache/go-xerial-snappy/snappy.go +++ b/vendor/github.com/eapache/go-xerial-snappy/snappy.go @@ -3,11 +3,22 @@ package snappy import ( "bytes" "encoding/binary" + "errors" master "github.com/golang/snappy" ) -var xerialHeader = []byte{130, 83, 78, 65, 80, 80, 89, 0} +const ( + sizeOffset = 16 + sizeBytes = 4 +) + +var ( + xerialHeader = []byte{130, 83, 78, 65, 80, 80, 89, 0} + // ErrMalformed is returned by the decoder when the xerial framing + // is malformed + ErrMalformed = errors.New("malformed xerial framing") +) // Encode encodes data as snappy with no framing header. func Encode(src []byte) []byte { @@ -17,26 +28,43 @@ func Encode(src []byte) []byte { // Decode decodes snappy data whether it is traditional unframed // or includes the xerial framing format. func Decode(src []byte) ([]byte, error) { + var max = len(src) + if max < len(xerialHeader) { + return nil, ErrMalformed + } + if !bytes.Equal(src[:8], xerialHeader) { return master.Decode(nil, src) } + if max < sizeOffset+sizeBytes { + return nil, ErrMalformed + } + var ( - pos = uint32(16) - max = uint32(len(src)) + pos = sizeOffset dst = make([]byte, 0, len(src)) chunk []byte err error ) - for pos < max { - size := binary.BigEndian.Uint32(src[pos : pos+4]) - pos += 4 - chunk, err = master.Decode(chunk, src[pos:pos+size]) + for pos+sizeBytes <= max { + size := int(binary.BigEndian.Uint32(src[pos : pos+sizeBytes])) + pos += sizeBytes + + nextPos := pos + size + // On architectures where int is 32-bytes wide size + pos could + // overflow so we need to check the low bound as well as the + // high + if nextPos < pos || nextPos > max { + return nil, ErrMalformed + } + + chunk, err = master.Decode(chunk, src[pos:nextPos]) if err != nil { return nil, err } - pos += size + pos = nextPos dst = append(dst, chunk...) } return dst, nil diff --git a/vendor/github.com/hailocab/go-hostpool/.gitignore b/vendor/github.com/evalphobia/logrus_fluent/.gitignore similarity index 94% rename from vendor/github.com/hailocab/go-hostpool/.gitignore rename to vendor/github.com/evalphobia/logrus_fluent/.gitignore index 00268614f0..daf913b1b3 100644 --- a/vendor/github.com/hailocab/go-hostpool/.gitignore +++ b/vendor/github.com/evalphobia/logrus_fluent/.gitignore @@ -20,3 +20,5 @@ _cgo_export.* _testmain.go *.exe +*.test +*.prof diff --git a/vendor/github.com/evalphobia/logrus_fluent/.travis.yml b/vendor/github.com/evalphobia/logrus_fluent/.travis.yml new file mode 100644 index 0000000000..86a6ce4aaf --- /dev/null +++ b/vendor/github.com/evalphobia/logrus_fluent/.travis.yml @@ -0,0 +1,17 @@ +sudo: false +language: go +go: + - 1.7 + - 1.8 + - tip +matrix: + allow_failures: + - go: tip +before_install: + - go get github.com/axw/gocov/gocov + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cmd/cover + - test -z "$(gofmt -s -l . | tee /dev/stderr)" + - go tool vet -all -structtags -shadow . +script: + - $HOME/gopath/bin/goveralls -service=travis-ci diff --git a/vendor/github.com/evalphobia/logrus_fluent/LICENSE b/vendor/github.com/evalphobia/logrus_fluent/LICENSE new file mode 100644 index 0000000000..8f71f43fee --- /dev/null +++ b/vendor/github.com/evalphobia/logrus_fluent/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/vendor/github.com/evalphobia/logrus_fluent/README.md b/vendor/github.com/evalphobia/logrus_fluent/README.md new file mode 100644 index 0000000000..145f6eab8d --- /dev/null +++ b/vendor/github.com/evalphobia/logrus_fluent/README.md @@ -0,0 +1,77 @@ +Fluentd Hook for Logrus :walrus: +---- + +[![GoDoc][1]][2] [![License: Apache 2.0][3]][4] [![Release][5]][6] [![Travis Status][7]][8] [![wercker Status][19]][20] [![Coveralls Coverage][9]][10] [![Go Report Card][13]][14] [![Downloads][15]][16] + +[1]: https://godoc.org/github.com/evalphobia/logrus_fluent?status.svg +[2]: https://godoc.org/github.com/evalphobia/logrus_fluent +[3]: https://img.shields.io/badge/License-Apache%202.0-blue.svg +[4]: LICENSE.md +[5]: https://img.shields.io/github/release/evalphobia/logrus_fluent.svg +[6]: https://github.com/evalphobia/logrus_fluent/releases/latest +[7]: https://travis-ci.org/evalphobia/logrus_fluent.svg?branch=master +[8]: https://travis-ci.org/evalphobia/logrus_fluent +[9]: https://coveralls.io/repos/evalphobia/logrus_fluent/badge.svg?branch=master&service=github +[10]: https://coveralls.io/github/evalphobia/logrus_fluent?branch=master +[11]: https://codecov.io/github/evalphobia/logrus_fluent/coverage.svg?branch=master +[12]: https://codecov.io/github/evalphobia/logrus_fluent?branch=master +[13]: https://goreportcard.com/badge/github.com/evalphobia/logrus_fluent +[14]: https://goreportcard.com/report/github.com/evalphobia/logrus_fluent +[15]: https://img.shields.io/github/downloads/evalphobia/logrus_fluent/total.svg?maxAge=1800 +[16]: https://github.com/evalphobia/logrus_fluent/releases +[17]: https://img.shields.io/github/stars/evalphobia/logrus_fluent.svg +[18]: https://github.com/evalphobia/logrus_fluent/stargazers +[19]: https://app.wercker.com/status/04fb4bde79d8c54bb681af664394d2e4/s/master +[20]: https://app.wercker.com/project/byKey/04fb4bde79d8c54bb681af664394d2e4 + + +## Usage + +```go +import ( + "github.com/sirupsen/logrus" + "github.com/evalphobia/logrus_fluent" +) + +func main() { + hook, err := logrus_fluent.NewWithConfig(logrus_fluent.Config{ + Host: "localhost", + Port: 24224, + }) + if err != nil { + panic(err) + } + + // set custom fire level + hook.SetLevels([]logrus.Level{ + logrus.PanicLevel, + logrus.ErrorLevel, + }) + + // set static tag + hook.SetTag("original.tag") + + // ignore field + hook.AddIgnore("context") + + // filter func + hook.AddFilter("error", logrus_fluent.FilterError) + + logrus.AddHook(hook) +} + +func logging(ctx context.Context) { + logrus.WithFields(logrus.Fields{ + "value": "some content...", + "error": errors.New("unknown error"), // this field will be applied filter function in the hook. + "context": ctx, // this field will be ignored in the hook. + }).Error("error message") +} +``` + + +## Special fields + +Some logrus fields have a special meaning in this hook. + +- `tag` is used as a fluentd tag. (if `tag` is omitted, Entry.Message is used as a fluentd tag, unless a static tag is set for the hook with `hook.SetTag`) diff --git a/vendor/github.com/evalphobia/logrus_fluent/config.go b/vendor/github.com/evalphobia/logrus_fluent/config.go new file mode 100644 index 0000000000..0b632cee14 --- /dev/null +++ b/vendor/github.com/evalphobia/logrus_fluent/config.go @@ -0,0 +1,53 @@ +package logrus_fluent + +import ( + "time" + + "github.com/fluent/fluent-logger-golang/fluent" + "github.com/sirupsen/logrus" +) + +// Config is settings for FluentHook. +type Config struct { + Port int + Host string + LogLevels []logrus.Level + DisableConnectionPool bool // Fluent client will be created every logging if true. + DefaultTag string + DefaultMessageField string + DefaultIgnoreFields map[string]struct{} + DefaultFilters map[string]func(interface{}) interface{} + + // from fluent.Config + // see https://github.com/fluent/fluent-logger-golang/blob/master/fluent/fluent.go + FluentNetwork string + FluentSocketPath string + Timeout time.Duration + WriteTimeout time.Duration + BufferLimit int + RetryWait int + MaxRetry int + TagPrefix string + AsyncConnect bool + MarshalAsJSON bool + SubSecondPrecision bool +} + +// FluentConfig converts data to fluent.Config. +func (c Config) FluentConfig() fluent.Config { + return fluent.Config{ + FluentPort: c.Port, + FluentHost: c.Host, + FluentNetwork: c.FluentNetwork, + FluentSocketPath: c.FluentSocketPath, + Timeout: c.Timeout, + WriteTimeout: c.WriteTimeout, + BufferLimit: c.BufferLimit, + RetryWait: c.RetryWait, + MaxRetry: c.MaxRetry, + TagPrefix: c.TagPrefix, + AsyncConnect: c.AsyncConnect, + MarshalAsJSON: c.MarshalAsJSON, + SubSecondPrecision: c.SubSecondPrecision, + } +} diff --git a/vendor/github.com/evalphobia/logrus_fluent/filter.go b/vendor/github.com/evalphobia/logrus_fluent/filter.go new file mode 100644 index 0000000000..bcd398703a --- /dev/null +++ b/vendor/github.com/evalphobia/logrus_fluent/filter.go @@ -0,0 +1,9 @@ +package logrus_fluent + +// FilterError is a filter function to convert error type to string type. +func FilterError(v interface{}) interface{} { + if err, ok := v.(error); ok { + return err.Error() + } + return v +} diff --git a/vendor/github.com/evalphobia/logrus_fluent/fluent.go b/vendor/github.com/evalphobia/logrus_fluent/fluent.go new file mode 100644 index 0000000000..a1a54ec059 --- /dev/null +++ b/vendor/github.com/evalphobia/logrus_fluent/fluent.go @@ -0,0 +1,223 @@ +package logrus_fluent + +import ( + "github.com/fluent/fluent-logger-golang/fluent" + "github.com/sirupsen/logrus" +) + +const ( + // TagName is struct field tag name. + // Some basic option is allowed in the field tag, + // + // type myStruct { + // Value1: `fluent:"value_1"` // change field name. + // Value2: `fluent:"-"` // always omit this field. + // Value3: `fluent:",omitempty"` // omit this field when zero-value. + // } + TagName = "fluent" + // TagField is logrus field name used as fluentd tag + TagField = "tag" + // MessageField is logrus field name used as message. + // If missing in the log fields, entry.Message is set to this field. + MessageField = "message" +) + +var defaultLevels = []logrus.Level{ + logrus.PanicLevel, + logrus.FatalLevel, + logrus.ErrorLevel, + logrus.WarnLevel, + logrus.InfoLevel, +} + +// FluentHook is logrus hook for fluentd. +type FluentHook struct { + // Fluent is actual fluentd logger. + // If set, this logger is used for logging. + // otherwise new logger is created every time. + Fluent *fluent.Fluent + conf Config + + levels []logrus.Level + tag *string + + messageField string + ignoreFields map[string]struct{} + filters map[string]func(interface{}) interface{} +} + +// New returns initialized logrus hook for fluentd with persistent fluentd logger. +func New(host string, port int) (*FluentHook, error) { + return NewWithConfig(Config{ + Host: host, + Port: port, + DefaultMessageField: MessageField, + }) +} + +// NewWithConfig returns initialized logrus hook by config setting. +func NewWithConfig(conf Config) (*FluentHook, error) { + var fd *fluent.Fluent + if !conf.DisableConnectionPool { + var err error + fd, err = fluent.New(conf.FluentConfig()) + if err != nil { + return nil, err + } + } + + hook := &FluentHook{ + Fluent: fd, + conf: conf, + levels: conf.LogLevels, + } + // set default values + if len(hook.levels) == 0 { + hook.levels = defaultLevels + } + if conf.DefaultTag != "" { + tag := conf.DefaultTag + hook.tag = &tag + } + if conf.DefaultMessageField != "" { + hook.messageField = conf.DefaultMessageField + } + if hook.ignoreFields == nil { + hook.ignoreFields = make(map[string]struct{}) + } + if hook.filters == nil { + hook.filters = make(map[string]func(interface{}) interface{}) + } + return hook, nil +} + +// NewHook returns initialized logrus hook for fluentd. +// (** deperecated: use New() or NewWithConfig() **) +func NewHook(host string, port int) *FluentHook { + hook, _ := NewWithConfig(Config{ + Host: host, + Port: port, + DefaultMessageField: MessageField, + DisableConnectionPool: true, + }) + return hook +} + +// Levels returns logging level to fire this hook. +func (hook *FluentHook) Levels() []logrus.Level { + return hook.levels +} + +// SetLevels sets logging level to fire this hook. +func (hook *FluentHook) SetLevels(levels []logrus.Level) { + hook.levels = levels +} + +// Tag returns custom static tag. +func (hook *FluentHook) Tag() string { + if hook.tag == nil { + return "" + } + + return *hook.tag +} + +// SetTag sets custom static tag to override tag in the message fields. +func (hook *FluentHook) SetTag(tag string) { + hook.tag = &tag +} + +// SetMessageField sets custom message field. +func (hook *FluentHook) SetMessageField(messageField string) { + hook.messageField = messageField +} + +// AddIgnore adds field name to ignore. +func (hook *FluentHook) AddIgnore(name string) { + hook.ignoreFields[name] = struct{}{} +} + +// AddFilter adds a custom filter function. +func (hook *FluentHook) AddFilter(name string, fn func(interface{}) interface{}) { + hook.filters[name] = fn +} + +// Fire is invoked by logrus and sends log to fluentd logger. +func (hook *FluentHook) Fire(entry *logrus.Entry) error { + var logger *fluent.Fluent + var err error + + switch { + case hook.Fluent != nil: + logger = hook.Fluent + default: + logger, err = fluent.New(hook.conf.FluentConfig()) + if err != nil { + return err + } + defer logger.Close() + } + + // Create a map for passing to FluentD + data := make(logrus.Fields) + for k, v := range entry.Data { + if _, ok := hook.ignoreFields[k]; ok { + continue + } + if fn, ok := hook.filters[k]; ok { + v = fn(v) + } + data[k] = v + } + + setLevelString(entry, data) + tag := hook.getTagAndDel(entry, data) + if tag != entry.Message { + hook.setMessage(entry, data) + } + + fluentData := ConvertToValue(data, TagName) + err = logger.PostWithTime(tag, entry.Time, fluentData) + return err +} + +// getTagAndDel extracts tag data from log entry and custom log fields. +// 1. if tag is set in the hook, use it. +// 2. if tag is set in custom fields, use it. +// 3. if cannot find tag data, use entry.Message as tag. +func (hook *FluentHook) getTagAndDel(entry *logrus.Entry, data logrus.Fields) string { + // use static tag from + if hook.tag != nil { + return *hook.tag + } + + tagField, ok := data[TagField] + if !ok { + return entry.Message + } + + tag, ok := tagField.(string) + if !ok { + return entry.Message + } + + // remove tag from data fields + delete(data, TagField) + return tag +} + +func (hook *FluentHook) setMessage(entry *logrus.Entry, data logrus.Fields) { + if _, ok := data[hook.messageField]; ok { + return + } + var v interface{} + v = entry.Message + if fn, ok := hook.filters[hook.messageField]; ok { + v = fn(v) + } + data[hook.messageField] = v +} + +func setLevelString(entry *logrus.Entry, data logrus.Fields) { + data["level"] = entry.Level.String() +} diff --git a/vendor/github.com/evalphobia/logrus_fluent/reflect.go b/vendor/github.com/evalphobia/logrus_fluent/reflect.go new file mode 100644 index 0000000000..addce5d286 --- /dev/null +++ b/vendor/github.com/evalphobia/logrus_fluent/reflect.go @@ -0,0 +1,157 @@ +package logrus_fluent + +import ( + "fmt" + "reflect" + "strings" +) + +// ConvertToValue make map data from struct and tags +func ConvertToValue(p interface{}, tagName string) interface{} { + rv := toValue(p) + switch rv.Kind() { + case reflect.Struct: + return convertFromStruct(rv.Interface(), tagName) + case reflect.Map: + return convertFromMap(rv, tagName) + case reflect.Slice: + return convertFromSlice(rv, tagName) + case reflect.Chan: + return nil + case reflect.Invalid: + return nil + default: + return rv.Interface() + } +} + +func convertFromMap(rv reflect.Value, tagName string) interface{} { + result := make(map[string]interface{}) + for _, key := range rv.MapKeys() { + kv := rv.MapIndex(key) + result[fmt.Sprint(key.Interface())] = ConvertToValue(kv.Interface(), tagName) + } + return result +} + +func convertFromSlice(rv reflect.Value, tagName string) interface{} { + var result []interface{} + for i, max := 0, rv.Len(); i < max; i++ { + result = append(result, ConvertToValue(rv.Index(i).Interface(), tagName)) + } + return result +} + +// convertFromStruct converts struct to value +// see: https://github.com/fatih/structs/ +func convertFromStruct(p interface{}, tagName string) interface{} { + result := make(map[string]interface{}) + return convertFromStructDeep(result, tagName, toType(p), toValue(p)) +} + +func convertFromStructDeep(result map[string]interface{}, tagName string, t reflect.Type, values reflect.Value) interface{} { + for i, max := 0, t.NumField(); i < max; i++ { + f := t.Field(i) + if f.PkgPath != "" && !f.Anonymous { + continue + } + + if f.Anonymous { + tt := f.Type + if tt.Kind() == reflect.Ptr { + tt = tt.Elem() + } + vv := values.Field(i) + if !vv.IsValid() { + continue + } + if vv.Kind() == reflect.Ptr { + vv = vv.Elem() + } + + if vv.Kind() == reflect.Struct { + convertFromStructDeep(result, tagName, tt, vv) + } + continue + } + + tag, opts := parseTag(f, tagName) + if tag == "-" { + continue // skip `-` tag + } + + if !values.IsValid() { + continue + } + v := values.Field(i) + if opts.Has("omitempty") && isZero(v) { + continue // skip zero-value when omitempty option exists in tag + } + name := getNameFromTag(f, tagName) + result[name] = ConvertToValue(v.Interface(), TagName) + } + return result +} + +// toValue converts any value to reflect.Value +func toValue(p interface{}) reflect.Value { + v := reflect.ValueOf(p) + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + return v +} + +// toType converts any value to reflect.Type +func toType(p interface{}) reflect.Type { + t := reflect.ValueOf(p).Type() + if t.Kind() == reflect.Ptr { + t = t.Elem() + } + return t +} + +// isZero checks the value is zero-value or not +func isZero(v reflect.Value) bool { + zero := reflect.Zero(v.Type()).Interface() + value := v.Interface() + return reflect.DeepEqual(value, zero) +} + +// getNameFromTag return the value in tag or field name in the struct field +func getNameFromTag(f reflect.StructField, tagName string) string { + tag, _ := parseTag(f, tagName) + if tag != "" { + return tag + } + return f.Name +} + +// getTagValues returns tag value of the struct field +func getTagValues(f reflect.StructField, tag string) string { + return f.Tag.Get(tag) +} + +// parseTag returns the first tag value of the struct field +func parseTag(f reflect.StructField, tag string) (string, options) { + return splitTags(getTagValues(f, tag)) +} + +// splitTags returns the first tag value and rest slice +func splitTags(tags string) (string, options) { + res := strings.Split(tags, ",") + return res[0], res[1:] +} + +// TagOptions is wrapper struct for rest tag values +type options []string + +// Has checks the value exists in the rest values or not +func (t options) Has(tag string) bool { + for _, opt := range t { + if opt == tag { + return true + } + } + return false +} diff --git a/vendor/github.com/evalphobia/logrus_fluent/wercker.yml b/vendor/github.com/evalphobia/logrus_fluent/wercker.yml new file mode 100644 index 0000000000..1f1a056727 --- /dev/null +++ b/vendor/github.com/evalphobia/logrus_fluent/wercker.yml @@ -0,0 +1,21 @@ +box: golang:1.8.1-stretch +dev: +build: + steps: + - setup-go-workspace + - script: + name: gofmt + code: | + test -z "$(gofmt -s -l . | tee /dev/stderr)" + - script: + name: go vet + code: | + go tool vet -all -structtags -shadow . + - script: + name: go get + code: | + go get -t -v ./... + - script: + name: go test + code: | + go test ./... diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/license_apache_2.go b/vendor/github.com/fluent/fluent-logger-golang/LICENSE similarity index 88% rename from vendor/github.com/spf13/cobra/cobra/cmd/license_apache_2.go rename to vendor/github.com/fluent/fluent-logger-golang/LICENSE index 38393d5417..d645695673 100644 --- a/vendor/github.com/spf13/cobra/cobra/cmd/license_apache_2.go +++ b/vendor/github.com/fluent/fluent-logger-golang/LICENSE @@ -1,37 +1,4 @@ -// Copyright © 2015 Steve Francia . -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Parts inspired by https://github.com/ryanuber/go-license - -package cmd - -func initApache2() { - Licenses["apache"] = License{ - Name: "Apache 2.0", - PossibleMatches: []string{"apache", "apache20", "apache 2.0", "apache2.0", "apache-2.0"}, - Header: ` -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License.`, - Text: ` + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -233,6 +200,3 @@ limitations under the License.`, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -`, - } -} diff --git a/vendor/github.com/fluent/fluent-logger-golang/fluent/fluent.go b/vendor/github.com/fluent/fluent-logger-golang/fluent/fluent.go new file mode 100644 index 0000000000..4693c5c3b5 --- /dev/null +++ b/vendor/github.com/fluent/fluent-logger-golang/fluent/fluent.go @@ -0,0 +1,332 @@ +package fluent + +import ( + "encoding/json" + "errors" + "fmt" + "math" + "net" + "reflect" + "strconv" + "sync" + "time" + + "github.com/tinylib/msgp/msgp" +) + +const ( + defaultHost = "127.0.0.1" + defaultNetwork = "tcp" + defaultSocketPath = "" + defaultPort = 24224 + defaultTimeout = 3 * time.Second + defaultWriteTimeout = time.Duration(0) // Write() will not time out + defaultBufferLimit = 8 * 1024 * 1024 + defaultRetryWait = 500 + defaultMaxRetry = 13 + defaultReconnectWaitIncreRate = 1.5 + // Default sub-second precision value to false since it is only compatible + // with fluentd versions v0.14 and above. + defaultSubSecondPrecision = false +) + +type Config struct { + FluentPort int `json:"fluent_port"` + FluentHost string `json:"fluent_host"` + FluentNetwork string `json:"fluent_network"` + FluentSocketPath string `json:"fluent_socket_path"` + Timeout time.Duration `json:"timeout"` + WriteTimeout time.Duration `json:"write_timeout"` + BufferLimit int `json:"buffer_limit"` + RetryWait int `json:"retry_wait"` + MaxRetry int `json:"max_retry"` + TagPrefix string `json:"tag_prefix"` + AsyncConnect bool `json:"async_connect"` + MarshalAsJSON bool `json:"marshal_as_json"` + + // Sub-second precision timestamps are only possible for those using fluentd + // v0.14+ and serializing their messages with msgpack. + SubSecondPrecision bool `json:"sub_second_precision"` +} + +type Fluent struct { + Config + + mubuff sync.Mutex + pending []byte + + muconn sync.Mutex + conn net.Conn + reconnecting bool +} + +// New creates a new Logger. +func New(config Config) (f *Fluent, err error) { + if config.FluentNetwork == "" { + config.FluentNetwork = defaultNetwork + } + if config.FluentHost == "" { + config.FluentHost = defaultHost + } + if config.FluentPort == 0 { + config.FluentPort = defaultPort + } + if config.FluentSocketPath == "" { + config.FluentSocketPath = defaultSocketPath + } + if config.Timeout == 0 { + config.Timeout = defaultTimeout + } + if config.WriteTimeout == 0 { + config.WriteTimeout = defaultWriteTimeout + } + if config.BufferLimit == 0 { + config.BufferLimit = defaultBufferLimit + } + if config.RetryWait == 0 { + config.RetryWait = defaultRetryWait + } + if config.MaxRetry == 0 { + config.MaxRetry = defaultMaxRetry + } + if config.AsyncConnect { + f = &Fluent{Config: config, reconnecting: true} + go f.reconnect() + } else { + f = &Fluent{Config: config, reconnecting: false} + err = f.connect() + } + return +} + +// Post writes the output for a logging event. +// +// Examples: +// +// // send map[string] +// mapStringData := map[string]string{ +// "foo": "bar", +// } +// f.Post("tag_name", mapStringData) +// +// // send message with specified time +// mapStringData := map[string]string{ +// "foo": "bar", +// } +// tm := time.Now() +// f.PostWithTime("tag_name", tm, mapStringData) +// +// // send struct +// structData := struct { +// Name string `msg:"name"` +// } { +// "john smith", +// } +// f.Post("tag_name", structData) +// +func (f *Fluent) Post(tag string, message interface{}) error { + timeNow := time.Now() + return f.PostWithTime(tag, timeNow, message) +} + +func (f *Fluent) PostWithTime(tag string, tm time.Time, message interface{}) error { + if len(f.TagPrefix) > 0 { + tag = f.TagPrefix + "." + tag + } + + if m, ok := message.(msgp.Marshaler); ok { + return f.EncodeAndPostData(tag, tm, m) + } + + msg := reflect.ValueOf(message) + msgtype := msg.Type() + + if msgtype.Kind() == reflect.Struct { + // message should be tagged by "codec" or "msg" + kv := make(map[string]interface{}) + fields := msgtype.NumField() + for i := 0; i < fields; i++ { + field := msgtype.Field(i) + name := field.Name + if n1 := field.Tag.Get("msg"); n1 != "" { + name = n1 + } else if n2 := field.Tag.Get("codec"); n2 != "" { + name = n2 + } + kv[name] = msg.FieldByIndex(field.Index).Interface() + } + return f.EncodeAndPostData(tag, tm, kv) + } + + if msgtype.Kind() != reflect.Map { + return errors.New("fluent#PostWithTime: message must be a map") + } else if msgtype.Key().Kind() != reflect.String { + return errors.New("fluent#PostWithTime: map keys must be strings") + } + + kv := make(map[string]interface{}) + for _, k := range msg.MapKeys() { + kv[k.String()] = msg.MapIndex(k).Interface() + } + + return f.EncodeAndPostData(tag, tm, kv) +} + +func (f *Fluent) EncodeAndPostData(tag string, tm time.Time, message interface{}) error { + var data []byte + var err error + if data, err = f.EncodeData(tag, tm, message); err != nil { + return fmt.Errorf("fluent#EncodeAndPostData: can't convert '%#v' to msgpack:%v", message, err) + } + return f.postRawData(data) +} + +// Deprecated: Use EncodeAndPostData instead +func (f *Fluent) PostRawData(data []byte) { + f.postRawData(data) +} + +func (f *Fluent) postRawData(data []byte) error { + if err := f.appendBuffer(data); err != nil { + return err + } + if err := f.send(); err != nil { + f.close() + return err + } + return nil +} + +// For sending forward protocol adopted JSON +type MessageChunk struct { + message Message +} + +// Golang default marshaler does not support +// ["value", "value2", {"key":"value"}] style marshaling. +// So, it should write JSON marshaler by hand. +func (chunk *MessageChunk) MarshalJSON() ([]byte, error) { + data, err := json.Marshal(chunk.message.Record) + return []byte(fmt.Sprintf("[\"%s\",%d,%s,null]", chunk.message.Tag, + chunk.message.Time, data)), err +} + +func (f *Fluent) EncodeData(tag string, tm time.Time, message interface{}) (data []byte, err error) { + timeUnix := tm.Unix() + if f.Config.MarshalAsJSON { + msg := Message{Tag: tag, Time: timeUnix, Record: message} + chunk := &MessageChunk{message: msg} + data, err = json.Marshal(chunk) + } else if f.Config.SubSecondPrecision { + msg := &MessageExt{Tag: tag, Time: EventTime(tm), Record: message} + data, err = msg.MarshalMsg(nil) + } else { + msg := &Message{Tag: tag, Time: timeUnix, Record: message} + data, err = msg.MarshalMsg(nil) + } + return +} + +// Close closes the connection. +func (f *Fluent) Close() (err error) { + if len(f.pending) > 0 { + err = f.send() + } + f.close() + return +} + +// appendBuffer appends data to buffer with lock. +func (f *Fluent) appendBuffer(data []byte) error { + f.mubuff.Lock() + defer f.mubuff.Unlock() + if len(f.pending)+len(data) > f.Config.BufferLimit { + return errors.New(fmt.Sprintf("fluent#appendBuffer: Buffer full, limit %v", f.Config.BufferLimit)) + } + f.pending = append(f.pending, data...) + return nil +} + +// close closes the connection. +func (f *Fluent) close() { + f.muconn.Lock() + if f.conn != nil { + f.conn.Close() + f.conn = nil + } + f.muconn.Unlock() +} + +// connect establishes a new connection using the specified transport. +func (f *Fluent) connect() (err error) { + f.muconn.Lock() + defer f.muconn.Unlock() + + switch f.Config.FluentNetwork { + case "tcp": + f.conn, err = net.DialTimeout(f.Config.FluentNetwork, f.Config.FluentHost+":"+strconv.Itoa(f.Config.FluentPort), f.Config.Timeout) + case "unix": + f.conn, err = net.DialTimeout(f.Config.FluentNetwork, f.Config.FluentSocketPath, f.Config.Timeout) + default: + err = net.UnknownNetworkError(f.Config.FluentNetwork) + } + + if err == nil { + f.reconnecting = false + } + return +} + +func e(x, y float64) int { + return int(math.Pow(x, y)) +} + +func (f *Fluent) reconnect() { + for i := 0; ; i++ { + err := f.connect() + if err == nil { + f.send() + return + } + if i == f.Config.MaxRetry { + // TODO: What we can do when connection failed MaxRetry times? + panic("fluent#reconnect: failed to reconnect!") + } + waitTime := f.Config.RetryWait * e(defaultReconnectWaitIncreRate, float64(i-1)) + time.Sleep(time.Duration(waitTime) * time.Millisecond) + } +} + +func (f *Fluent) send() error { + f.muconn.Lock() + defer f.muconn.Unlock() + + if f.conn == nil { + if f.reconnecting == false { + f.reconnecting = true + go f.reconnect() + } + return errors.New("fluent#send: can't send logs, client is reconnecting") + } + + f.mubuff.Lock() + defer f.mubuff.Unlock() + + var err error + if len(f.pending) > 0 { + t := f.Config.WriteTimeout + if time.Duration(0) < t { + f.conn.SetWriteDeadline(time.Now().Add(t)) + } else { + f.conn.SetWriteDeadline(time.Time{}) + } + _, err = f.conn.Write(f.pending) + if err != nil { + f.conn.Close() + f.conn = nil + } else { + f.pending = f.pending[:0] + } + } + return err +} diff --git a/vendor/github.com/fluent/fluent-logger-golang/fluent/proto.go b/vendor/github.com/fluent/fluent-logger-golang/fluent/proto.go new file mode 100644 index 0000000000..158e22da71 --- /dev/null +++ b/vendor/github.com/fluent/fluent-logger-golang/fluent/proto.go @@ -0,0 +1,96 @@ +//go:generate msgp + +package fluent + +import ( + "time" + + "github.com/tinylib/msgp/msgp" +) + +//msgp:tuple Entry +type Entry struct { + Time int64 `msg:"time"` + Record interface{} `msg:"record"` +} + +//msgp:tuple Forward +type Forward struct { + Tag string `msg:"tag"` + Entries []Entry `msg:"entries"` + Option interface{} `msg:"option"` +} + +//msgp:tuple Message +type Message struct { + Tag string `msg:"tag"` + Time int64 `msg:"time"` + Record interface{} `msg:"record"` + Option interface{} `msg:"option"` +} + +//msgp:tuple MessageExt +type MessageExt struct { + Tag string `msg:"tag"` + Time EventTime `msg:"time,extension"` + Record interface{} `msg:"record"` + Option interface{} `msg:"option"` +} + +// EventTime is an extension to the serialized time value. It builds in support +// for sub-second (nanosecond) precision in serialized timestamps. +// +// You can find the full specification for the msgpack message payload here: +// https://github.com/fluent/fluentd/wiki/Forward-Protocol-Specification-v1. +// +// You can find more information on msgpack extension types here: +// https://github.com/tinylib/msgp/wiki/Using-Extensions. +type EventTime time.Time + +const ( + extensionType = 0 + length = 8 +) + +func init() { + msgp.RegisterExtension(extensionType, func() msgp.Extension { return new(EventTime) }) +} + +func (t *EventTime) ExtensionType() int8 { return extensionType } + +func (t *EventTime) Len() int { return length } + +func (t *EventTime) MarshalBinaryTo(b []byte) error { + // Unwrap to Golang time + goTime := time.Time(*t) + + // There's no support for timezones in fluentd's protocol for EventTime. + // Convert to UTC. + utc := goTime.UTC() + + // Warning! Converting seconds to an int32 is a lossy operation. This code + // will hit the "Year 2038" problem. + sec := int32(utc.Unix()) + nsec := utc.Nanosecond() + + // Fill the buffer with 4 bytes for the second component of the timestamp. + b[0] = byte(sec >> 24) + b[1] = byte(sec >> 16) + b[2] = byte(sec >> 8) + b[3] = byte(sec) + + // Fill the buffer with 4 bytes for the nanosecond component of the + // timestamp. + b[4] = byte(nsec >> 24) + b[5] = byte(nsec >> 16) + b[6] = byte(nsec >> 8) + b[7] = byte(nsec) + + return nil +} + +// UnmarshalBinary is not implemented since decoding messages is not supported +// by this library. +func (t *EventTime) UnmarshalBinary(b []byte) error { + return nil +} diff --git a/vendor/github.com/fluent/fluent-logger-golang/fluent/proto_gen.go b/vendor/github.com/fluent/fluent-logger-golang/fluent/proto_gen.go new file mode 100644 index 0000000000..5b88a688f8 --- /dev/null +++ b/vendor/github.com/fluent/fluent-logger-golang/fluent/proto_gen.go @@ -0,0 +1,489 @@ +package fluent + +// NOTE: THIS FILE WAS PRODUCED BY THE +// MSGP CODE GENERATION TOOL (github.com/tinylib/msgp) +// DO NOT EDIT + +import ( + "github.com/tinylib/msgp/msgp" +) + +// DecodeMsg implements msgp.Decodable +func (z *Entry) DecodeMsg(dc *msgp.Reader) (err error) { + var zxvk uint32 + zxvk, err = dc.ReadArrayHeader() + if err != nil { + return + } + if zxvk != 2 { + err = msgp.ArrayError{Wanted: 2, Got: zxvk} + return + } + z.Time, err = dc.ReadInt64() + if err != nil { + return + } + z.Record, err = dc.ReadIntf() + if err != nil { + return + } + return +} + +// EncodeMsg implements msgp.Encodable +func (z Entry) EncodeMsg(en *msgp.Writer) (err error) { + // array header, size 2 + err = en.Append(0x92) + if err != nil { + return err + } + err = en.WriteInt64(z.Time) + if err != nil { + return + } + err = en.WriteIntf(z.Record) + if err != nil { + return + } + return +} + +// MarshalMsg implements msgp.Marshaler +func (z Entry) MarshalMsg(b []byte) (o []byte, err error) { + o = msgp.Require(b, z.Msgsize()) + // array header, size 2 + o = append(o, 0x92) + o = msgp.AppendInt64(o, z.Time) + o, err = msgp.AppendIntf(o, z.Record) + if err != nil { + return + } + return +} + +// UnmarshalMsg implements msgp.Unmarshaler +func (z *Entry) UnmarshalMsg(bts []byte) (o []byte, err error) { + var zbzg uint32 + zbzg, bts, err = msgp.ReadArrayHeaderBytes(bts) + if err != nil { + return + } + if zbzg != 2 { + err = msgp.ArrayError{Wanted: 2, Got: zbzg} + return + } + z.Time, bts, err = msgp.ReadInt64Bytes(bts) + if err != nil { + return + } + z.Record, bts, err = msgp.ReadIntfBytes(bts) + if err != nil { + return + } + o = bts + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z Entry) Msgsize() (s int) { + s = 1 + msgp.Int64Size + msgp.GuessSize(z.Record) + return +} + +// DecodeMsg implements msgp.Decodable +func (z *Forward) DecodeMsg(dc *msgp.Reader) (err error) { + var zcmr uint32 + zcmr, err = dc.ReadArrayHeader() + if err != nil { + return + } + if zcmr != 3 { + err = msgp.ArrayError{Wanted: 3, Got: zcmr} + return + } + z.Tag, err = dc.ReadString() + if err != nil { + return + } + var zajw uint32 + zajw, err = dc.ReadArrayHeader() + if err != nil { + return + } + if cap(z.Entries) >= int(zajw) { + z.Entries = (z.Entries)[:zajw] + } else { + z.Entries = make([]Entry, zajw) + } + for zbai := range z.Entries { + var zwht uint32 + zwht, err = dc.ReadArrayHeader() + if err != nil { + return + } + if zwht != 2 { + err = msgp.ArrayError{Wanted: 2, Got: zwht} + return + } + z.Entries[zbai].Time, err = dc.ReadInt64() + if err != nil { + return + } + z.Entries[zbai].Record, err = dc.ReadIntf() + if err != nil { + return + } + } + z.Option, err = dc.ReadIntf() + if err != nil { + return + } + return +} + +// EncodeMsg implements msgp.Encodable +func (z *Forward) EncodeMsg(en *msgp.Writer) (err error) { + // array header, size 3 + err = en.Append(0x93) + if err != nil { + return err + } + err = en.WriteString(z.Tag) + if err != nil { + return + } + err = en.WriteArrayHeader(uint32(len(z.Entries))) + if err != nil { + return + } + for zbai := range z.Entries { + // array header, size 2 + err = en.Append(0x92) + if err != nil { + return err + } + err = en.WriteInt64(z.Entries[zbai].Time) + if err != nil { + return + } + err = en.WriteIntf(z.Entries[zbai].Record) + if err != nil { + return + } + } + err = en.WriteIntf(z.Option) + if err != nil { + return + } + return +} + +// MarshalMsg implements msgp.Marshaler +func (z *Forward) MarshalMsg(b []byte) (o []byte, err error) { + o = msgp.Require(b, z.Msgsize()) + // array header, size 3 + o = append(o, 0x93) + o = msgp.AppendString(o, z.Tag) + o = msgp.AppendArrayHeader(o, uint32(len(z.Entries))) + for zbai := range z.Entries { + // array header, size 2 + o = append(o, 0x92) + o = msgp.AppendInt64(o, z.Entries[zbai].Time) + o, err = msgp.AppendIntf(o, z.Entries[zbai].Record) + if err != nil { + return + } + } + o, err = msgp.AppendIntf(o, z.Option) + if err != nil { + return + } + return +} + +// UnmarshalMsg implements msgp.Unmarshaler +func (z *Forward) UnmarshalMsg(bts []byte) (o []byte, err error) { + var zhct uint32 + zhct, bts, err = msgp.ReadArrayHeaderBytes(bts) + if err != nil { + return + } + if zhct != 3 { + err = msgp.ArrayError{Wanted: 3, Got: zhct} + return + } + z.Tag, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + return + } + var zcua uint32 + zcua, bts, err = msgp.ReadArrayHeaderBytes(bts) + if err != nil { + return + } + if cap(z.Entries) >= int(zcua) { + z.Entries = (z.Entries)[:zcua] + } else { + z.Entries = make([]Entry, zcua) + } + for zbai := range z.Entries { + var zxhx uint32 + zxhx, bts, err = msgp.ReadArrayHeaderBytes(bts) + if err != nil { + return + } + if zxhx != 2 { + err = msgp.ArrayError{Wanted: 2, Got: zxhx} + return + } + z.Entries[zbai].Time, bts, err = msgp.ReadInt64Bytes(bts) + if err != nil { + return + } + z.Entries[zbai].Record, bts, err = msgp.ReadIntfBytes(bts) + if err != nil { + return + } + } + z.Option, bts, err = msgp.ReadIntfBytes(bts) + if err != nil { + return + } + o = bts + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z *Forward) Msgsize() (s int) { + s = 1 + msgp.StringPrefixSize + len(z.Tag) + msgp.ArrayHeaderSize + for zbai := range z.Entries { + s += 1 + msgp.Int64Size + msgp.GuessSize(z.Entries[zbai].Record) + } + s += msgp.GuessSize(z.Option) + return +} + +// DecodeMsg implements msgp.Decodable +func (z *Message) DecodeMsg(dc *msgp.Reader) (err error) { + var zlqf uint32 + zlqf, err = dc.ReadArrayHeader() + if err != nil { + return + } + if zlqf != 4 { + err = msgp.ArrayError{Wanted: 4, Got: zlqf} + return + } + z.Tag, err = dc.ReadString() + if err != nil { + return + } + z.Time, err = dc.ReadInt64() + if err != nil { + return + } + z.Record, err = dc.ReadIntf() + if err != nil { + return + } + z.Option, err = dc.ReadIntf() + if err != nil { + return + } + return +} + +// EncodeMsg implements msgp.Encodable +func (z *Message) EncodeMsg(en *msgp.Writer) (err error) { + // array header, size 4 + err = en.Append(0x94) + if err != nil { + return err + } + err = en.WriteString(z.Tag) + if err != nil { + return + } + err = en.WriteInt64(z.Time) + if err != nil { + return + } + err = en.WriteIntf(z.Record) + if err != nil { + return + } + err = en.WriteIntf(z.Option) + if err != nil { + return + } + return +} + +// MarshalMsg implements msgp.Marshaler +func (z *Message) MarshalMsg(b []byte) (o []byte, err error) { + o = msgp.Require(b, z.Msgsize()) + // array header, size 4 + o = append(o, 0x94) + o = msgp.AppendString(o, z.Tag) + o = msgp.AppendInt64(o, z.Time) + o, err = msgp.AppendIntf(o, z.Record) + if err != nil { + return + } + o, err = msgp.AppendIntf(o, z.Option) + if err != nil { + return + } + return +} + +// UnmarshalMsg implements msgp.Unmarshaler +func (z *Message) UnmarshalMsg(bts []byte) (o []byte, err error) { + var zdaf uint32 + zdaf, bts, err = msgp.ReadArrayHeaderBytes(bts) + if err != nil { + return + } + if zdaf != 4 { + err = msgp.ArrayError{Wanted: 4, Got: zdaf} + return + } + z.Tag, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + return + } + z.Time, bts, err = msgp.ReadInt64Bytes(bts) + if err != nil { + return + } + z.Record, bts, err = msgp.ReadIntfBytes(bts) + if err != nil { + return + } + z.Option, bts, err = msgp.ReadIntfBytes(bts) + if err != nil { + return + } + o = bts + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z *Message) Msgsize() (s int) { + s = 1 + msgp.StringPrefixSize + len(z.Tag) + msgp.Int64Size + msgp.GuessSize(z.Record) + msgp.GuessSize(z.Option) + return +} + +// DecodeMsg implements msgp.Decodable +func (z *MessageExt) DecodeMsg(dc *msgp.Reader) (err error) { + var zpks uint32 + zpks, err = dc.ReadArrayHeader() + if err != nil { + return + } + if zpks != 4 { + err = msgp.ArrayError{Wanted: 4, Got: zpks} + return + } + z.Tag, err = dc.ReadString() + if err != nil { + return + } + err = dc.ReadExtension(&z.Time) + if err != nil { + return + } + z.Record, err = dc.ReadIntf() + if err != nil { + return + } + z.Option, err = dc.ReadIntf() + if err != nil { + return + } + return +} + +// EncodeMsg implements msgp.Encodable +func (z *MessageExt) EncodeMsg(en *msgp.Writer) (err error) { + // array header, size 4 + err = en.Append(0x94) + if err != nil { + return err + } + err = en.WriteString(z.Tag) + if err != nil { + return + } + err = en.WriteExtension(&z.Time) + if err != nil { + return + } + err = en.WriteIntf(z.Record) + if err != nil { + return + } + err = en.WriteIntf(z.Option) + if err != nil { + return + } + return +} + +// MarshalMsg implements msgp.Marshaler +func (z *MessageExt) MarshalMsg(b []byte) (o []byte, err error) { + o = msgp.Require(b, z.Msgsize()) + // array header, size 4 + o = append(o, 0x94) + o = msgp.AppendString(o, z.Tag) + o, err = msgp.AppendExtension(o, &z.Time) + if err != nil { + return + } + o, err = msgp.AppendIntf(o, z.Record) + if err != nil { + return + } + o, err = msgp.AppendIntf(o, z.Option) + if err != nil { + return + } + return +} + +// UnmarshalMsg implements msgp.Unmarshaler +func (z *MessageExt) UnmarshalMsg(bts []byte) (o []byte, err error) { + var zjfb uint32 + zjfb, bts, err = msgp.ReadArrayHeaderBytes(bts) + if err != nil { + return + } + if zjfb != 4 { + err = msgp.ArrayError{Wanted: 4, Got: zjfb} + return + } + z.Tag, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + return + } + bts, err = msgp.ReadExtensionBytes(bts, &z.Time) + if err != nil { + return + } + z.Record, bts, err = msgp.ReadIntfBytes(bts) + if err != nil { + return + } + z.Option, bts, err = msgp.ReadIntfBytes(bts) + if err != nil { + return + } + o = bts + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z *MessageExt) Msgsize() (s int) { + s = 1 + msgp.StringPrefixSize + len(z.Tag) + msgp.ExtensionPrefixSize + z.Time.Len() + msgp.GuessSize(z.Record) + msgp.GuessSize(z.Option) + return +} diff --git a/vendor/github.com/fluent/fluent-logger-golang/fluent/test_message.go b/vendor/github.com/fluent/fluent-logger-golang/fluent/test_message.go new file mode 100644 index 0000000000..dcf5baae2e --- /dev/null +++ b/vendor/github.com/fluent/fluent-logger-golang/fluent/test_message.go @@ -0,0 +1,7 @@ +package fluent + +//go:generate msgp +type TestMessage struct { + Foo string `msg:"foo" json:"foo,omitempty"` + Hoge string `msg:"hoge" json:"hoge,omitempty"` +} diff --git a/vendor/github.com/fluent/fluent-logger-golang/fluent/test_message_gen.go b/vendor/github.com/fluent/fluent-logger-golang/fluent/test_message_gen.go new file mode 100644 index 0000000000..17a45e22a3 --- /dev/null +++ b/vendor/github.com/fluent/fluent-logger-golang/fluent/test_message_gen.go @@ -0,0 +1,125 @@ +package fluent + +// NOTE: THIS FILE WAS PRODUCED BY THE +// MSGP CODE GENERATION TOOL (github.com/tinylib/msgp) +// DO NOT EDIT + +import ( + "github.com/tinylib/msgp/msgp" +) + +// DecodeMsg implements msgp.Decodable +func (z *TestMessage) DecodeMsg(dc *msgp.Reader) (err error) { + var field []byte + _ = field + var zxvk uint32 + zxvk, err = dc.ReadMapHeader() + if err != nil { + return + } + for zxvk > 0 { + zxvk-- + field, err = dc.ReadMapKeyPtr() + if err != nil { + return + } + switch msgp.UnsafeString(field) { + case "foo": + z.Foo, err = dc.ReadString() + if err != nil { + return + } + case "hoge": + z.Hoge, err = dc.ReadString() + if err != nil { + return + } + default: + err = dc.Skip() + if err != nil { + return + } + } + } + return +} + +// EncodeMsg implements msgp.Encodable +func (z TestMessage) EncodeMsg(en *msgp.Writer) (err error) { + // map header, size 2 + // write "foo" + err = en.Append(0x82, 0xa3, 0x66, 0x6f, 0x6f) + if err != nil { + return err + } + err = en.WriteString(z.Foo) + if err != nil { + return + } + // write "hoge" + err = en.Append(0xa4, 0x68, 0x6f, 0x67, 0x65) + if err != nil { + return err + } + err = en.WriteString(z.Hoge) + if err != nil { + return + } + return +} + +// MarshalMsg implements msgp.Marshaler +func (z TestMessage) MarshalMsg(b []byte) (o []byte, err error) { + o = msgp.Require(b, z.Msgsize()) + // map header, size 2 + // string "foo" + o = append(o, 0x82, 0xa3, 0x66, 0x6f, 0x6f) + o = msgp.AppendString(o, z.Foo) + // string "hoge" + o = append(o, 0xa4, 0x68, 0x6f, 0x67, 0x65) + o = msgp.AppendString(o, z.Hoge) + return +} + +// UnmarshalMsg implements msgp.Unmarshaler +func (z *TestMessage) UnmarshalMsg(bts []byte) (o []byte, err error) { + var field []byte + _ = field + var zbzg uint32 + zbzg, bts, err = msgp.ReadMapHeaderBytes(bts) + if err != nil { + return + } + for zbzg > 0 { + zbzg-- + field, bts, err = msgp.ReadMapKeyZC(bts) + if err != nil { + return + } + switch msgp.UnsafeString(field) { + case "foo": + z.Foo, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + return + } + case "hoge": + z.Hoge, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + return + } + default: + bts, err = msgp.Skip(bts) + if err != nil { + return + } + } + } + o = bts + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z TestMessage) Msgsize() (s int) { + s = 1 + 4 + msgp.StringPrefixSize + len(z.Foo) + 5 + msgp.StringPrefixSize + len(z.Hoge) + return +} diff --git a/vendor/github.com/fluent/fluent-logger-golang/fluent/version.go b/vendor/github.com/fluent/fluent-logger-golang/fluent/version.go new file mode 100644 index 0000000000..c6ec7e41e2 --- /dev/null +++ b/vendor/github.com/fluent/fluent-logger-golang/fluent/version.go @@ -0,0 +1,3 @@ +package fluent + +const Version = "1.3.0" diff --git a/vendor/github.com/fsouza/go-dockerclient/.gitignore b/vendor/github.com/fsouza/go-dockerclient/.gitignore index 5f6b48eae0..ef22245eae 100644 --- a/vendor/github.com/fsouza/go-dockerclient/.gitignore +++ b/vendor/github.com/fsouza/go-dockerclient/.gitignore @@ -1,2 +1,4 @@ # temporary symlink for testing testing/data/symlink +Gopkg.lock +vendor/ diff --git a/vendor/github.com/fsouza/go-dockerclient/.travis.yml b/vendor/github.com/fsouza/go-dockerclient/.travis.yml index fb371c52f1..7da0371a0d 100644 --- a/vendor/github.com/fsouza/go-dockerclient/.travis.yml +++ b/vendor/github.com/fsouza/go-dockerclient/.travis.yml @@ -1,20 +1,18 @@ language: go sudo: required go: - - 1.7.x - - 1.8.x - - tip + - 1.9.x + - 1.10.x os: - linux - osx env: matrix: - - GOARCH=amd64 DOCKER_VERSION=1.12.6 - - GOARCH=386 DOCKER_VERSION=1.12.6 - - GOARCH=amd64 DOCKER_VERSION=1.13.1 - - GOARCH=386 DOCKER_VERSION=1.13.1 + - GOARCH=amd64 DOCKER_PKG_VERSION=18.03.0~ce-0~ubuntu + - GOARCH=386 DOCKER_PKG_VERSION=18.03.0~ce-0~ubuntu + - GOARCH=amd64 DOCKER_PKG_VERSION=18.02.0~ce-0~ubuntu + - GOARCH=386 DOCKER_PKG_VERSION=18.02.0~ce-0~ubuntu global: - - GO_TEST_FLAGS=-race - DOCKER_HOST=tcp://127.0.0.1:2375 install: - make testdeps @@ -27,6 +25,6 @@ matrix: fast_finish: true exclude: - os: osx - env: GOARCH=amd64 DOCKER_VERSION=1.12.6 + env: GOARCH=amd64 DOCKER_PKG_VERSION=18.02.0~ce-0~ubuntu - os: osx - env: GOARCH=386 DOCKER_VERSION=1.12.6 + env: GOARCH=386 DOCKER_PKG_VERSION=18.02.0~ce-0~ubuntu diff --git a/vendor/github.com/fsouza/go-dockerclient/AUTHORS b/vendor/github.com/fsouza/go-dockerclient/AUTHORS index b1ba43b86f..f944f3950b 100644 --- a/vendor/github.com/fsouza/go-dockerclient/AUTHORS +++ b/vendor/github.com/fsouza/go-dockerclient/AUTHORS @@ -2,7 +2,9 @@ Abhishek Chanda Adam Bell-Hanssen +Adnan Khan Adrien Kohlbecker +Aithal Aldrin Leal Alex Dadgar Alfonso Acosta @@ -36,19 +38,27 @@ Changping Chen Cheah Chu Yeow cheneydeng Chris Bednarski +Chris Stavropoulos Christian Stewart +Christophe Mourette +Clayton Coleman +Clint Armstrong CMGS Colin Hebert Craig Jellick +Damien Lespiau Damon Wang Dan Williams Daniel, Dao Quang Minh Daniel Garcia Daniel Hiltgen +Daniel Nephin +Daniel Tsui Darren Shepherd Dave Choi David Huie Dawn Chen +Denis Makogon Derek Petersen Dinesh Subhraveti Drew Wells @@ -56,12 +66,14 @@ Ed Elias G. Schneevoigt Erez Horev Eric Anderson +Eric J. Holmes Eric Mountain Erwin van Eyk Ethan Mosbaugh Ewout Prangsma Fabio Rehm Fatih Arslan +Faye Salwin Felipe Oliveira Flavia Missi Florent Aide @@ -73,9 +85,11 @@ Guilherme Rezende Guillermo Álvarez Fernández Harry Zhang He Simei +Isaac Schnitzer Ivan Mikushin James Bardin James Nugent +Jamie Snell Januar Wayong Jari Kolehmainen Jason Wilder @@ -87,6 +101,7 @@ Jen Andre Jérôme Laurens Jim Minter Johan Euphrosine +Johannes Scheuermann John Hughes Jorge Marey Julian Einwag @@ -98,6 +113,7 @@ Kevin Xu Kim, Hirokuni Kostas Lekkas Kyle Allan +Yunhee Lee Liron Levin Lior Yankovich Liu Peng @@ -106,6 +122,7 @@ Lucas Clemente Lucas Weiblen Lyon Hill Mantas Matelis +Manuel Vogel Marguerite des Trois Maisons Mariusz Borsa Martin Sweeney @@ -126,6 +143,7 @@ Paul Morie Paul Weil Peter Edge Peter Jihoon Kim +Peter Teich Phil Lu Philippe Lafoucrière Radek Simko @@ -143,6 +161,7 @@ Sam Rijs Sami Wagiaalla Samuel Archambault Samuel Karp +Sebastian Borza Seth Jennings Shane Xie Silas Sewell @@ -151,8 +170,10 @@ Simon Menke Skolos Soulou Sridhar Ratnakumar +Steven Jack Summer Mousa Sunjin Lee +Sunny Swaroop Ramachandra Tarsis Azevedo Tim Schindler @@ -168,5 +189,6 @@ Vlad Alexandru Ionescu Weitao Zhou Wiliam Souza Ye Yin +Yosuke Otosu Yu, Zou Yuriy Bogdanov diff --git a/vendor/github.com/fsouza/go-dockerclient/Gopkg.toml b/vendor/github.com/fsouza/go-dockerclient/Gopkg.toml new file mode 100644 index 0000000000..47971edaea --- /dev/null +++ b/vendor/github.com/fsouza/go-dockerclient/Gopkg.toml @@ -0,0 +1,28 @@ +[[constraint]] + name = "github.com/Microsoft/go-winio" + version = "v0.4.5" + +[[constraint]] + name = "github.com/docker/docker" + revision = "3dfb26ab3cbf961298f8ce3f94659b5fe4146ceb" + +[[constraint]] + name = "github.com/docker/go-units" + version = "v0.3.2" + +[[constraint]] + name = "github.com/google/go-cmp" + version = "v0.2.0" + +[[constraint]] + name = "github.com/gorilla/mux" + version = "v1.5.0" + +[[override]] + name = "github.com/Nvveen/Gotty" + source = "https://github.com/ijc25/Gotty.git" + revision = "a8b993ba6abdb0e0c12b0125c603323a71c7790c" + +[[override]] + name = "github.com/docker/libnetwork" + revision = "19279f0492417475b6bfbd0aa529f73e8f178fb5" diff --git a/vendor/github.com/fsouza/go-dockerclient/LICENSE b/vendor/github.com/fsouza/go-dockerclient/LICENSE index 545174c18f..fc7e73f8f6 100644 --- a/vendor/github.com/fsouza/go-dockerclient/LICENSE +++ b/vendor/github.com/fsouza/go-dockerclient/LICENSE @@ -1,18 +1,19 @@ -Copyright (c) 2013-2017, go-dockerclient authors +Copyright (c) 2013-2018, go-dockerclient authors All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR diff --git a/vendor/github.com/fsouza/go-dockerclient/Makefile b/vendor/github.com/fsouza/go-dockerclient/Makefile index 483aa1bb4a..479b07b0c5 100644 --- a/vendor/github.com/fsouza/go-dockerclient/Makefile +++ b/vendor/github.com/fsouza/go-dockerclient/Makefile @@ -2,40 +2,33 @@ all \ lint \ vet \ - fmt \ fmtcheck \ pretest \ test \ - integration \ - clean + integration all: test lint: - @ go get -v github.com/golang/lint/golint + @ go get -v golang.org/x/lint/golint [ -z "$$(golint . | grep -v 'type name will be used as docker.DockerInfo' | grep -v 'context.Context should be the first' | tee /dev/stderr)" ] vet: go vet ./... -fmt: - gofmt -s -w . - fmtcheck: - [ -z "$$(gofmt -s -d . | tee /dev/stderr)" ] + [ -z "$$(gofmt -s -d *.go ./testing | tee /dev/stderr)" ] testdeps: - go get -d -t ./... + go get -u github.com/golang/dep/cmd/dep + dep ensure -v pretest: testdeps lint vet fmtcheck gotest: - go test $(GO_TEST_FLAGS) ./... + go test -race ./... test: pretest gotest integration: go test -tags docker_integration -run TestIntegration -v - -clean: - go clean ./... diff --git a/vendor/github.com/fsouza/go-dockerclient/README.markdown b/vendor/github.com/fsouza/go-dockerclient/README.markdown index 68434a03ce..86824d6c5f 100644 --- a/vendor/github.com/fsouza/go-dockerclient/README.markdown +++ b/vendor/github.com/fsouza/go-dockerclient/README.markdown @@ -6,7 +6,6 @@ This package presents a client for the Docker remote API. It also provides support for the extensions in the [Swarm API](https://docs.docker.com/swarm/swarm-api/). -It currently supports the Docker API up to version 1.23. This package also provides support for docker's network API, which is a simple passthrough to the libnetwork remote API. Note that docker's network API is @@ -110,3 +109,25 @@ Commited code must pass: Running `make test` will check all of these. If your editor does not automatically call ``gofmt -s``, `make fmt` will format all go files in this repository. + +## Vendoring + +go-dockerclient uses [dep](https://github.com/golang/dep/) for vendoring. If +you're using dep, you should be able to pick go-dockerclient releases and get +the proper dependencies. + +With other vendoring tools, users might need to specify go-dockerclient's +dependencies manually. + +## Using with Docker 1.9 and Go 1.4 + +There's a tag for using go-dockerclient with Docker 1.9 (which requires +compiling go-dockerclient with Go 1.4), the tag name is ``docker-1.9/go-1.4``. + +The instructions below can be used to get a version of go-dockerclient that compiles with Go 1.4: + +``` +% git clone -b docker-1.9/go-1.4 https://github.com/fsouza/go-dockerclient.git $GOPATH/src/github.com/fsouza/go-dockerclient +% git clone -b v1.9.1 https://github.com/docker/docker.git $GOPATH/src/github.com/docker/docker +% go get github.com/fsouza/go-dockerclient +``` diff --git a/vendor/github.com/fsouza/go-dockerclient/appveyor.yml b/vendor/github.com/fsouza/go-dockerclient/appveyor.yml index 85a2c94e10..ee1297ad0d 100644 --- a/vendor/github.com/fsouza/go-dockerclient/appveyor.yml +++ b/vendor/github.com/fsouza/go-dockerclient/appveyor.yml @@ -5,16 +5,17 @@ clone_folder: c:\gopath\src\github.com\fsouza\go-dockerclient environment: GOPATH: c:\gopath matrix: - - GOVERSION: 1.7.5 - - GOVERSION: 1.8.1 + - GOVERSION: 1.9.7 + - GOVERSION: 1.10.3 install: - set PATH=%GOPATH%\bin;c:\go\bin;%PATH% - rmdir c:\go /s /q - appveyor DownloadFile https://storage.googleapis.com/golang/go%GOVERSION%.windows-amd64.zip - 7z x go%GOVERSION%.windows-amd64.zip -y -oC:\ > NUL build_script: - - go get -d -t ./... + - go get -u github.com/golang/dep/cmd/dep + - dep ensure -v test_script: - - go test -v ./... + - for /f "" %%G in ('go list ./... ^| find /i /v "/vendor/"') do ( go test %%G & IF ERRORLEVEL == 1 EXIT 1) matrix: fast_finish: true diff --git a/vendor/github.com/fsouza/go-dockerclient/auth.go b/vendor/github.com/fsouza/go-dockerclient/auth.go index 03d192b792..c58de86710 100644 --- a/vendor/github.com/fsouza/go-dockerclient/auth.go +++ b/vendor/github.com/fsouza/go-dockerclient/auth.go @@ -129,6 +129,9 @@ func authConfigs(confs map[string]dockerConfig) (*AuthConfigurations, error) { Configs: make(map[string]AuthConfiguration), } for reg, conf := range confs { + if conf.Auth == "" { + continue + } data, err := base64.StdEncoding.DecodeString(conf.Auth) if err != nil { return nil, err diff --git a/vendor/github.com/fsouza/go-dockerclient/client.go b/vendor/github.com/fsouza/go-dockerclient/client.go index 3527adf769..581e314172 100644 --- a/vendor/github.com/fsouza/go-dockerclient/client.go +++ b/vendor/github.com/fsouza/go-dockerclient/client.go @@ -10,6 +10,7 @@ package docker import ( "bufio" "bytes" + "context" "crypto/tls" "crypto/x509" "encoding/json" @@ -24,6 +25,7 @@ import ( "os" "path/filepath" "reflect" + "runtime" "strconv" "strings" "sync/atomic" @@ -31,11 +33,8 @@ import ( "github.com/docker/docker/opts" "github.com/docker/docker/pkg/homedir" - "github.com/docker/docker/pkg/jsonmessage" "github.com/docker/docker/pkg/stdcopy" - "github.com/hashicorp/go-cleanhttp" - "golang.org/x/net/context" - "golang.org/x/net/context/ctxhttp" + "github.com/fsouza/go-dockerclient/internal/jsonmessage" ) const ( @@ -59,6 +58,7 @@ var ( apiVersion119, _ = NewAPIVersion("1.19") apiVersion124, _ = NewAPIVersion("1.24") apiVersion125, _ = NewAPIVersion("1.25") + apiVersion135, _ = NewAPIVersion("1.35") ) // APIVersion is an internal representation of a version of the Remote API. @@ -151,7 +151,6 @@ type Client struct { requestedAPIVersion APIVersion serverAPIVersion APIVersion expectedAPIVersion APIVersion - nativeHTTPClient *http.Client } // Dialer is an interface that allows network connections to be dialed @@ -212,18 +211,26 @@ func NewVersionedClient(endpoint string, apiVersionString string) (*Client, erro } } c := &Client{ - HTTPClient: cleanhttp.DefaultClient(), + HTTPClient: defaultClient(), Dialer: &net.Dialer{}, endpoint: endpoint, endpointURL: u, eventMonitor: new(eventMonitoringState), requestedAPIVersion: requestedAPIVersion, } - c.initializeNativeClient() + c.initializeNativeClient(defaultTransport) return c, nil } -// NewVersionnedTLSClient has been DEPRECATED, please use NewVersionedTLSClient. +// WithTransport replaces underlying HTTP client of Docker Client by accepting +// a function that returns pointer to a transport object. +func (c *Client) WithTransport(trFunc func() *http.Transport) { + c.initializeNativeClient(trFunc) +} + +// NewVersionnedTLSClient is like NewVersionedClient, but with ann extra n. +// +// Deprecated: Use NewVersionedTLSClient instead. func NewVersionnedTLSClient(endpoint string, cert, key, ca, apiVersionString string) (*Client, error) { return NewVersionedTLSClient(endpoint, cert, key, ca, apiVersionString) } @@ -326,7 +333,7 @@ func NewVersionedTLSClientFromBytes(endpoint string, certPEMBlock, keyPEMBlock, } tlsConfig.RootCAs = caPool } - tr := cleanhttp.DefaultTransport() + tr := defaultTransport() tr.TLSClientConfig = tlsConfig if err != nil { return nil, err @@ -340,20 +347,16 @@ func NewVersionedTLSClientFromBytes(endpoint string, certPEMBlock, keyPEMBlock, eventMonitor: new(eventMonitoringState), requestedAPIVersion: requestedAPIVersion, } - c.initializeNativeClient() + c.initializeNativeClient(defaultTransport) return c, nil } -// SetTimeout takes a timeout and applies it to both the HTTPClient and -// nativeHTTPClient. It should not be called concurrently with any other Client -// methods. +// SetTimeout takes a timeout and applies it to the HTTPClient. It should not +// be called concurrently with any other Client methods. func (c *Client) SetTimeout(t time.Duration) { if c.HTTPClient != nil { c.HTTPClient.Timeout = t } - if c.nativeHTTPClient != nil { - c.nativeHTTPClient.Timeout = t - } } func (c *Client) checkAPIVersion() error { @@ -445,12 +448,10 @@ func (c *Client) do(method, path string, doOptions doOptions) (*http.Response, e return nil, err } } - httpClient := c.HTTPClient protocol := c.endpointURL.Scheme var u string switch protocol { case unixProtocol, namedPipeProtocol: - httpClient = c.nativeHTTPClient u = c.getFakeNativeURL(path) default: u = c.getURL(path) @@ -476,7 +477,7 @@ func (c *Client) do(method, path string, doOptions doOptions) (*http.Response, e ctx = context.Background() } - resp, err := ctxhttp.Do(ctx, httpClient, req) + resp, err := c.HTTPClient.Do(req.WithContext(ctx)) if err != nil { if strings.Contains(err.Error(), "connection refused") { return nil, ErrConnectionRefused @@ -498,6 +499,7 @@ type streamOptions struct { in io.Reader stdout io.Writer stderr io.Writer + reqSent chan struct{} // timeout is the initial connection timeout timeout time.Duration // Timeout with no data is received, it's reset every time new data @@ -576,6 +578,9 @@ func (c *Client) stream(method, path string, streamOptions streamOptions) error dial.SetDeadline(time.Now().Add(streamOptions.timeout)) } + if streamOptions.reqSent != nil { + close(streamOptions.reqSent) + } if resp, err = http.ReadResponse(breader, req); err != nil { // Cancel timeout for future I/O operations if streamOptions.timeout > 0 { @@ -588,12 +593,15 @@ func (c *Client) stream(method, path string, streamOptions streamOptions) error return chooseError(subCtx, err) } } else { - if resp, err = ctxhttp.Do(subCtx, c.HTTPClient, req); err != nil { + if resp, err = c.HTTPClient.Do(req.WithContext(subCtx)); err != nil { if strings.Contains(err.Error(), "connection refused") { return ErrConnectionRefused } return chooseError(subCtx, err) } + if streamOptions.reqSent != nil { + close(streamOptions.reqSent) + } } defer resp.Body.Close() if resp.StatusCode < 200 || resp.StatusCode >= 400 { @@ -909,6 +917,10 @@ func addQueryStringValue(items url.Values, key string, v reflect.Value) { if v.Int() > 0 { items.Add(key, strconv.FormatInt(v.Int(), 10)) } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + if v.Uint() > 0 { + items.Add(key, strconv.FormatUint(v.Uint(), 10)) + } case reflect.Float32, reflect.Float64: if v.Float() > 0 { items.Add(key, strconv.FormatFloat(v.Float(), 'f', -1, 64)) @@ -946,12 +958,20 @@ type Error struct { } func newError(resp *http.Response) *Error { + type ErrMsg struct { + Message string `json:"message"` + } defer resp.Body.Close() data, err := ioutil.ReadAll(resp.Body) if err != nil { return &Error{Status: resp.StatusCode, Message: fmt.Sprintf("cannot read body, err: %v", err)} } - return &Error{Status: resp.StatusCode, Message: string(data)} + var emsg ErrMsg + err = json.Unmarshal(data, &emsg) + if err != nil { + return &Error{Status: resp.StatusCode, Message: string(data)} + } + return &Error{Status: resp.StatusCode, Message: emsg.Message} } func (e *Error) Error() string { @@ -1033,3 +1053,41 @@ func getDockerEnv() (*dockerEnv, error) { dockerCertPath: dockerCertPath, }, nil } + +// defaultTransport returns a new http.Transport with similar default values to +// http.DefaultTransport, but with idle connections and keepalives disabled. +func defaultTransport() *http.Transport { + transport := defaultPooledTransport() + transport.DisableKeepAlives = true + transport.MaxIdleConnsPerHost = -1 + return transport +} + +// defaultPooledTransport returns a new http.Transport with similar default +// values to http.DefaultTransport. Do not use this for transient transports as +// it can leak file descriptors over time. Only use this for transports that +// will be re-used for the same host(s). +func defaultPooledTransport() *http.Transport { + transport := &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + }).DialContext, + MaxIdleConns: 100, + IdleConnTimeout: 90 * time.Second, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, + MaxIdleConnsPerHost: runtime.GOMAXPROCS(0) + 1, + } + return transport +} + +// defaultClient returns a new http.Client with similar default values to +// http.Client, but with a non-shared Transport, idle connections disabled, and +// keepalives disabled. +func defaultClient() *http.Client { + return &http.Client{ + Transport: defaultTransport(), + } +} diff --git a/vendor/github.com/fsouza/go-dockerclient/client_unix.go b/vendor/github.com/fsouza/go-dockerclient/client_unix.go index dd153348cb..57d7904ea2 100644 --- a/vendor/github.com/fsouza/go-dockerclient/client_unix.go +++ b/vendor/github.com/fsouza/go-dockerclient/client_unix.go @@ -10,23 +10,23 @@ import ( "context" "net" "net/http" - - "github.com/hashicorp/go-cleanhttp" ) // initializeNativeClient initializes the native Unix domain socket client on // Unix-style operating systems -func (c *Client) initializeNativeClient() { +func (c *Client) initializeNativeClient(trFunc func() *http.Transport) { if c.endpointURL.Scheme != unixProtocol { return } - socketPath := c.endpointURL.Path - tr := cleanhttp.DefaultTransport() + sockPath := c.endpointURL.Path + + tr := trFunc() + tr.Dial = func(network, addr string) (net.Conn, error) { - return c.Dialer.Dial(network, addr) + return c.Dialer.Dial(unixProtocol, sockPath) } tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) { - return c.Dialer.Dial(unixProtocol, socketPath) + return c.Dialer.Dial(unixProtocol, sockPath) } - c.nativeHTTPClient = &http.Client{Transport: tr} + c.HTTPClient.Transport = tr } diff --git a/vendor/github.com/fsouza/go-dockerclient/client_windows.go b/vendor/github.com/fsouza/go-dockerclient/client_windows.go index 95ef56b4c3..8e7b457d7f 100644 --- a/vendor/github.com/fsouza/go-dockerclient/client_windows.go +++ b/vendor/github.com/fsouza/go-dockerclient/client_windows.go @@ -1,9 +1,9 @@ -// +build windows - // Copyright 2016 go-dockerclient authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// +build windows + package docker import ( @@ -13,7 +13,6 @@ import ( "time" "github.com/Microsoft/go-winio" - "github.com/hashicorp/go-cleanhttp" ) const namedPipeConnectTimeout = 2 * time.Second @@ -27,7 +26,7 @@ func (p pipeDialer) Dial(network, address string) (net.Conn, error) { } // initializeNativeClient initializes the native Named Pipe client for Windows -func (c *Client) initializeNativeClient() { +func (c *Client) initializeNativeClient(trFunc func() *http.Transport) { if c.endpointURL.Scheme != namedPipeProtocol { return } @@ -36,11 +35,11 @@ func (c *Client) initializeNativeClient() { timeout := namedPipeConnectTimeout return winio.DialPipe(namedPipePath, &timeout) } - tr := cleanhttp.DefaultTransport() + tr := trFunc() tr.Dial = dialFunc tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) { return dialFunc(network, addr) } c.Dialer = &pipeDialer{dialFunc} - c.nativeHTTPClient = &http.Client{Transport: tr} + c.HTTPClient.Transport = tr } diff --git a/vendor/github.com/fsouza/go-dockerclient/container.go b/vendor/github.com/fsouza/go-dockerclient/container.go index af1cd41ca6..e24c9fb2e9 100644 --- a/vendor/github.com/fsouza/go-dockerclient/container.go +++ b/vendor/github.com/fsouza/go-dockerclient/container.go @@ -5,6 +5,7 @@ package docker import ( + "context" "encoding/json" "errors" "fmt" @@ -16,7 +17,6 @@ import ( "time" "github.com/docker/go-units" - "golang.org/x/net/context" ) // ErrContainerAlreadyExists is the error returned by CreateContainer when the @@ -204,7 +204,7 @@ func (s *State) StateString() string { // PortBinding represents the host/container port mapping as returned in the // `docker inspect` json type PortBinding struct { - HostIP string `json:"HostIP,omitempty" yaml:"HostIP,omitempty" toml:"HostIP,omitempty"` + HostIP string `json:"HostIp,omitempty" yaml:"HostIp,omitempty" toml:"HostIp,omitempty"` HostPort string `json:"HostPort,omitempty" yaml:"HostPort,omitempty" toml:"HostPort,omitempty"` } @@ -300,8 +300,10 @@ type Config struct { ExposedPorts map[Port]struct{} `json:"ExposedPorts,omitempty" yaml:"ExposedPorts,omitempty" toml:"ExposedPorts,omitempty"` PublishService string `json:"PublishService,omitempty" yaml:"PublishService,omitempty" toml:"PublishService,omitempty"` StopSignal string `json:"StopSignal,omitempty" yaml:"StopSignal,omitempty" toml:"StopSignal,omitempty"` + StopTimeout int `json:"StopTimeout,omitempty" yaml:"StopTimeout,omitempty" toml:"StopTimeout,omitempty"` Env []string `json:"Env,omitempty" yaml:"Env,omitempty" toml:"Env,omitempty"` Cmd []string `json:"Cmd" yaml:"Cmd" toml:"Cmd"` + Shell []string `json:"Shell,omitempty" yaml:"Shell,omitempty" toml:"Shell,omitempty"` Healthcheck *HealthConfig `json:"Healthcheck,omitempty" yaml:"Healthcheck,omitempty" toml:"Healthcheck,omitempty"` DNS []string `json:"Dns,omitempty" yaml:"Dns,omitempty" toml:"Dns,omitempty"` // For Docker API v1.9 and below only Image string `json:"Image,omitempty" yaml:"Image,omitempty" toml:"Image,omitempty"` @@ -328,6 +330,43 @@ type Config struct { VolumesFrom string `json:"VolumesFrom,omitempty" yaml:"VolumesFrom,omitempty" toml:"VolumesFrom,omitempty"` } +// HostMount represents a mount point in the container in HostConfig. +// +// It has been added in the version 1.25 of the Docker API +type HostMount struct { + Target string `json:"Target,omitempty" yaml:"Target,omitempty" toml:"Target,omitempty"` + Source string `json:"Source,omitempty" yaml:"Source,omitempty" toml:"Source,omitempty"` + Type string `json:"Type,omitempty" yaml:"Type,omitempty" toml:"Type,omitempty"` + ReadOnly bool `json:"ReadOnly,omitempty" yaml:"ReadOnly,omitempty" toml:"ReadOnly,omitempty"` + BindOptions *BindOptions `json:"BindOptions,omitempty" yaml:"BindOptions,omitempty" toml:"BindOptions,omitempty"` + VolumeOptions *VolumeOptions `json:"VolumeOptions,omitempty" yaml:"VolumeOptions,omitempty" toml:"VolumeOptions,omitempty"` + TempfsOptions *TempfsOptions `json:"TempfsOptions,omitempty" yaml:"TempfsOptions,omitempty" toml:"TempfsOptions,omitempty"` +} + +// BindOptions contains optional configuration for the bind type +type BindOptions struct { + Propagation string `json:"Propagation,omitempty" yaml:"Propagation,omitempty" toml:"Propagation,omitempty"` +} + +// VolumeOptions contains optional configuration for the volume type +type VolumeOptions struct { + NoCopy bool `json:"NoCopy,omitempty" yaml:"NoCopy,omitempty" toml:"NoCopy,omitempty"` + Labels map[string]string `json:"Labels,omitempty" yaml:"Labels,omitempty" toml:"Labels,omitempty"` + DriverConfig VolumeDriverConfig `json:"DriverConfig,omitempty" yaml:"DriverConfig,omitempty" toml:"DriverConfig,omitempty"` +} + +// TempfsOptions contains optional configuration for the tempfs type +type TempfsOptions struct { + SizeBytes int64 `json:"SizeBytes,omitempty" yaml:"SizeBytes,omitempty" toml:"SizeBytes,omitempty"` + Mode int `json:"Mode,omitempty" yaml:"Mode,omitempty" toml:"Mode,omitempty"` +} + +// VolumeDriverConfig holds a map of volume driver specific options +type VolumeDriverConfig struct { + Name string `json:"Name,omitempty" yaml:"Name,omitempty" toml:"Name,omitempty"` + Options map[string]string `json:"Options,omitempty" yaml:"Options,omitempty" toml:"Options,omitempty"` +} + // Mount represents a mount point in the container. // // It has been added in the version 1.20 of the Docker API, available since @@ -389,8 +428,9 @@ type HealthConfig struct { Test []string `json:"Test,omitempty" yaml:"Test,omitempty" toml:"Test,omitempty"` // Zero means to inherit. Durations are expressed as integer nanoseconds. - Interval time.Duration `json:"Interval,omitempty" yaml:"Interval,omitempty" toml:"Interval,omitempty"` // Interval is the time to wait between checks. - Timeout time.Duration `json:"Timeout,omitempty" yaml:"Timeout,omitempty" toml:"Timeout,omitempty"` // Timeout is the time to wait before considering the check to have hung. + Interval time.Duration `json:"Interval,omitempty" yaml:"Interval,omitempty" toml:"Interval,omitempty"` // Interval is the time to wait between checks. + Timeout time.Duration `json:"Timeout,omitempty" yaml:"Timeout,omitempty" toml:"Timeout,omitempty"` // Timeout is the time to wait before considering the check to have hung. + StartPeriod time.Duration `json:"StartPeriod,omitempty" yaml:"StartPeriod,omitempty" toml:"StartPeriod,omitempty"` // The start period for the container to initialize before the retries starts to count down. // Retries is the number of consecutive failures needed to consider a container as unhealthy. // Zero means inherit. @@ -593,6 +633,11 @@ func (c *Client) CreateContainer(opts CreateContainerOptions) (*Container, error if e.Status == http.StatusConflict { return nil, ErrContainerAlreadyExists } + // Workaround for 17.09 bug returning 400 instead of 409. + // See https://github.com/moby/moby/issues/35021 + if e.Status == http.StatusBadRequest && strings.Contains(e.Message, "Conflict.") { + return nil, ErrContainerAlreadyExists + } } if err != nil { @@ -700,6 +745,7 @@ type HostConfig struct { UTSMode string `json:"UTSMode,omitempty" yaml:"UTSMode,omitempty" toml:"UTSMode,omitempty"` RestartPolicy RestartPolicy `json:"RestartPolicy,omitempty" yaml:"RestartPolicy,omitempty" toml:"RestartPolicy,omitempty"` Devices []Device `json:"Devices,omitempty" yaml:"Devices,omitempty" toml:"Devices,omitempty"` + DeviceCgroupRules []string `json:"DeviceCgroupRules,omitempty" yaml:"DeviceCgroupRules,omitempty" toml:"DeviceCgroupRules,omitempty"` LogConfig LogConfig `json:"LogConfig,omitempty" yaml:"LogConfig,omitempty" toml:"LogConfig,omitempty"` SecurityOpt []string `json:"SecurityOpt,omitempty" yaml:"SecurityOpt,omitempty" toml:"SecurityOpt,omitempty"` Cgroup string `json:"Cgroup,omitempty" yaml:"Cgroup,omitempty" toml:"Cgroup,omitempty"` @@ -708,7 +754,7 @@ type HostConfig struct { MemoryReservation int64 `json:"MemoryReservation,omitempty" yaml:"MemoryReservation,omitempty" toml:"MemoryReservation,omitempty"` KernelMemory int64 `json:"KernelMemory,omitempty" yaml:"KernelMemory,omitempty" toml:"KernelMemory,omitempty"` MemorySwap int64 `json:"MemorySwap,omitempty" yaml:"MemorySwap,omitempty" toml:"MemorySwap,omitempty"` - MemorySwappiness int64 `json:"MemorySwappiness" yaml:"MemorySwappiness" toml:"MemorySwappiness"` + MemorySwappiness int64 `json:"MemorySwappiness,omitempty" yaml:"MemorySwappiness,omitempty" toml:"MemorySwappiness,omitempty"` CPUShares int64 `json:"CpuShares,omitempty" yaml:"CpuShares,omitempty" toml:"CpuShares,omitempty"` CPUSet string `json:"Cpuset,omitempty" yaml:"Cpuset,omitempty" toml:"Cpuset,omitempty"` CPUSetCPUs string `json:"CpusetCpus,omitempty" yaml:"CpusetCpus,omitempty" toml:"CpusetCpus,omitempty"` @@ -740,6 +786,8 @@ type HostConfig struct { CPUPercent int64 `json:"CpuPercent,omitempty" yaml:"CpuPercent,omitempty"` IOMaximumBandwidth int64 `json:"IOMaximumBandwidth,omitempty" yaml:"IOMaximumBandwidth,omitempty"` IOMaximumIOps int64 `json:"IOMaximumIOps,omitempty" yaml:"IOMaximumIOps,omitempty"` + Mounts []HostMount `json:"Mounts,omitempty" yaml:"Mounts,omitempty" toml:"Mounts,omitempty"` + Init bool `json:",omitempty" yaml:",omitempty"` } // NetworkingConfig represents the container's networking configuration for each of its interfaces @@ -915,6 +963,8 @@ func (c *Client) TopContainer(id string, psArgs string) (TopResult, error) { // See https://goo.gl/Dk3Xio for more details. type Stats struct { Read time.Time `json:"read,omitempty" yaml:"read,omitempty" toml:"read,omitempty"` + PreRead time.Time `json:"preread,omitempty" yaml:"preread,omitempty" toml:"preread,omitempty"` + NumProcs uint32 `json:"num_procs" yaml:"num_procs" toml:"num_procs"` PidsStats struct { Current uint64 `json:"current,omitempty" yaml:"current,omitempty"` } `json:"pids_stats,omitempty" yaml:"pids_stats,omitempty" toml:"pids_stats,omitempty"` @@ -954,10 +1004,13 @@ type Stats struct { HierarchicalMemswLimit uint64 `json:"hierarchical_memsw_limit,omitempty" yaml:"hierarchical_memsw_limit,omitempty" toml:"hierarchical_memsw_limit,omitempty"` Swap uint64 `json:"swap,omitempty" yaml:"swap,omitempty" toml:"swap,omitempty"` } `json:"stats,omitempty" yaml:"stats,omitempty" toml:"stats,omitempty"` - MaxUsage uint64 `json:"max_usage,omitempty" yaml:"max_usage,omitempty" toml:"max_usage,omitempty"` - Usage uint64 `json:"usage,omitempty" yaml:"usage,omitempty" toml:"usage,omitempty"` - Failcnt uint64 `json:"failcnt,omitempty" yaml:"failcnt,omitempty" toml:"failcnt,omitempty"` - Limit uint64 `json:"limit,omitempty" yaml:"limit,omitempty" toml:"limit,omitempty"` + MaxUsage uint64 `json:"max_usage,omitempty" yaml:"max_usage,omitempty" toml:"max_usage,omitempty"` + Usage uint64 `json:"usage,omitempty" yaml:"usage,omitempty" toml:"usage,omitempty"` + Failcnt uint64 `json:"failcnt,omitempty" yaml:"failcnt,omitempty" toml:"failcnt,omitempty"` + Limit uint64 `json:"limit,omitempty" yaml:"limit,omitempty" toml:"limit,omitempty"` + Commit uint64 `json:"commitbytes,omitempty" yaml:"commitbytes,omitempty" toml:"privateworkingset,omitempty"` + CommitPeak uint64 `json:"commitpeakbytes,omitempty" yaml:"commitpeakbytes,omitempty" toml:"commitpeakbytes,omitempty"` + PrivateWorkingSet uint64 `json:"privateworkingset,omitempty" yaml:"privateworkingset,omitempty" toml:"privateworkingset,omitempty"` } `json:"memory_stats,omitempty" yaml:"memory_stats,omitempty" toml:"memory_stats,omitempty"` BlkioStats struct { IOServiceBytesRecursive []BlkioStatsEntry `json:"io_service_bytes_recursive,omitempty" yaml:"io_service_bytes_recursive,omitempty" toml:"io_service_bytes_recursive,omitempty"` @@ -969,8 +1022,14 @@ type Stats struct { IOTimeRecursive []BlkioStatsEntry `json:"io_time_recursive,omitempty" yaml:"io_time_recursive,omitempty" toml:"io_time_recursive,omitempty"` SectorsRecursive []BlkioStatsEntry `json:"sectors_recursive,omitempty" yaml:"sectors_recursive,omitempty" toml:"sectors_recursive,omitempty"` } `json:"blkio_stats,omitempty" yaml:"blkio_stats,omitempty" toml:"blkio_stats,omitempty"` - CPUStats CPUStats `json:"cpu_stats,omitempty" yaml:"cpu_stats,omitempty" toml:"cpu_stats,omitempty"` - PreCPUStats CPUStats `json:"precpu_stats,omitempty"` + CPUStats CPUStats `json:"cpu_stats,omitempty" yaml:"cpu_stats,omitempty" toml:"cpu_stats,omitempty"` + PreCPUStats CPUStats `json:"precpu_stats,omitempty"` + StorageStats struct { + ReadCountNormalized uint64 `json:"read_count_normalized,omitempty" yaml:"read_count_normalized,omitempty" toml:"read_count_normalized,omitempty"` + ReadSizeBytes uint64 `json:"read_size_bytes,omitempty" yaml:"read_size_bytes,omitempty" toml:"read_size_bytes,omitempty"` + WriteCountNormalized uint64 `json:"write_count_normalized,omitempty" yaml:"write_count_normalized,omitempty" toml:"write_count_normalized,omitempty"` + WriteSizeBytes uint64 `json:"write_size_bytes,omitempty" yaml:"write_size_bytes,omitempty" toml:"write_size_bytes,omitempty"` + } `json:"storage_stats,omitempty" yaml:"storage_stats,omitempty" toml:"storage_stats,omitempty"` } // NetworkStats is a stats entry for network stats @@ -994,6 +1053,7 @@ type CPUStats struct { UsageInKernelmode uint64 `json:"usage_in_kernelmode,omitempty" yaml:"usage_in_kernelmode,omitempty" toml:"usage_in_kernelmode,omitempty"` } `json:"cpu_usage,omitempty" yaml:"cpu_usage,omitempty" toml:"cpu_usage,omitempty"` SystemCPUUsage uint64 `json:"system_cpu_usage,omitempty" yaml:"system_cpu_usage,omitempty" toml:"system_cpu_usage,omitempty"` + OnlineCPUs uint64 `json:"online_cpus,omitempty" yaml:"online_cpus,omitempty" toml:"online_cpus,omitempty"` ThrottlingData struct { Periods uint64 `json:"periods,omitempty"` ThrottledPeriods uint64 `json:"throttled_periods,omitempty"` @@ -1056,6 +1116,7 @@ func (c *Client) Stats(opts StatsOptions) (retErr error) { } }() + reqSent := make(chan struct{}) go func() { err := c.stream("GET", fmt.Sprintf("/containers/%s/stats?stream=%v", opts.ID, opts.Stream), streamOptions{ rawJSONStream: true, @@ -1064,6 +1125,7 @@ func (c *Client) Stats(opts StatsOptions) (retErr error) { timeout: opts.Timeout, inactivityTimeout: opts.InactivityTimeout, context: opts.Context, + reqSent: reqSent, }) if err != nil { dockerError, ok := err.(*Error) @@ -1094,6 +1156,7 @@ func (c *Client) Stats(opts StatsOptions) (retErr error) { decoder := json.NewDecoder(readCloser) stats := new(Stats) + <-reqSent for err := decoder.Decode(stats); err != io.EOF; err = decoder.Decode(stats) { if err != nil { return err @@ -1126,10 +1189,18 @@ func (c *Client) KillContainer(opts KillContainerOptions) error { path := "/containers/" + opts.ID + "/kill" + "?" + queryString(opts) resp, err := c.do("POST", path, doOptions{context: opts.Context}) if err != nil { - if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { + e, ok := err.(*Error) + if !ok { + return err + } + switch e.Status { + case http.StatusNotFound: return &NoSuchContainer{ID: opts.ID} + case http.StatusConflict: + return &ContainerNotRunning{ID: opts.ID} + default: + return err } - return err } resp.Body.Close() return nil @@ -1217,9 +1288,10 @@ func (c *Client) DownloadFromContainer(id string, opts DownloadFromContainerOpti }) } -// CopyFromContainerOptions has been DEPRECATED, please use DownloadFromContainerOptions along with DownloadFromContainer. +// CopyFromContainerOptions contains the set of options used for copying +// files from a container. // -// See https://goo.gl/nWk2YQ for more details. +// Deprecated: Use DownloadFromContainerOptions and DownloadFromContainer instead. type CopyFromContainerOptions struct { OutputStream io.Writer `json:"-"` Container string `json:"-"` @@ -1227,9 +1299,9 @@ type CopyFromContainerOptions struct { Context context.Context `json:"-"` } -// CopyFromContainer has been DEPRECATED, please use DownloadFromContainerOptions along with DownloadFromContainer. +// CopyFromContainer copies files from a container. // -// See https://goo.gl/nWk2YQ for more details. +// Deprecated: Use DownloadFromContainer and DownloadFromContainer instead. func (c *Client) CopyFromContainer(opts CopyFromContainerOptions) error { if opts.Container == "" { return &NoSuchContainer{ID: opts.Container} @@ -1420,7 +1492,7 @@ type LogsOptions struct { // stderr to LogsOptions.ErrorStream. // // When LogsOptions.RawTerminal is true, callers will get the raw stream on -// LogOptions.OutputStream. The caller can use libraries such as dlog +// LogsOptions.OutputStream. The caller can use libraries such as dlog // (github.com/ahmetalpbalkan/dlog). // // See https://goo.gl/krK0ZH for more details. diff --git a/vendor/github.com/fsouza/go-dockerclient/distribution.go b/vendor/github.com/fsouza/go-dockerclient/distribution.go new file mode 100644 index 0000000000..d0f8ce74cc --- /dev/null +++ b/vendor/github.com/fsouza/go-dockerclient/distribution.go @@ -0,0 +1,26 @@ +// Copyright 2017 go-dockerclient authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package docker + +import ( + "encoding/json" + + "github.com/docker/docker/api/types/registry" +) + +// InspectDistribution returns image digest and platform information by contacting the registry +func (c *Client) InspectDistribution(name string) (*registry.DistributionInspect, error) { + path := "/distribution/" + name + "/json" + resp, err := c.do("GET", path, doOptions{}) + if err != nil { + return nil, err + } + defer resp.Body.Close() + var distributionInspect registry.DistributionInspect + if err := json.NewDecoder(resp.Body).Decode(&distributionInspect); err != nil { + return nil, err + } + return &distributionInspect, nil +} diff --git a/vendor/github.com/fsouza/go-dockerclient/env.go b/vendor/github.com/fsouza/go-dockerclient/env.go index c54b0b0e80..13fedfb17e 100644 --- a/vendor/github.com/fsouza/go-dockerclient/env.go +++ b/vendor/github.com/fsouza/go-dockerclient/env.go @@ -162,7 +162,11 @@ func (env *Env) Map() map[string]string { m := make(map[string]string) for _, kv := range *env { parts := strings.SplitN(kv, "=", 2) - m[parts[0]] = parts[1] + if len(parts) == 1 { + m[parts[0]] = "" + } else { + m[parts[0]] = parts[1] + } } return m } diff --git a/vendor/github.com/fsouza/go-dockerclient/event.go b/vendor/github.com/fsouza/go-dockerclient/event.go index 007d2b22bc..18ae5d5a64 100644 --- a/vendor/github.com/fsouza/go-dockerclient/event.go +++ b/vendor/github.com/fsouza/go-dockerclient/event.go @@ -195,10 +195,25 @@ func (eventState *eventMonitoringState) disableEventMonitoring() error { } func (eventState *eventMonitoringState) monitorEvents(c *Client) { + const ( + noListenersTimeout = 5 * time.Second + noListenersInterval = 10 * time.Millisecond + noListenersMaxTries = noListenersTimeout / noListenersInterval + ) + var err error - for eventState.noListeners() { + for i := time.Duration(0); i < noListenersMaxTries && eventState.noListeners(); i++ { time.Sleep(10 * time.Millisecond) } + + if eventState.noListeners() { + // terminate if no listener is available after 5 seconds. + // Prevents goroutine leak when RemoveEventListener is called + // right after AddEventListener. + eventState.disableEventMonitoring() + return + } + if err = eventState.connectWithRetry(c); err != nil { // terminate if connect failed eventState.disableEventMonitoring() @@ -216,7 +231,7 @@ func (eventState *eventMonitoringState) monitorEvents(c *Client) { return } eventState.updateLastSeen(ev) - go eventState.sendEvent(ev) + eventState.sendEvent(ev) case err = <-eventState.errC: if err == ErrNoListeners { eventState.disableEventMonitoring() @@ -274,7 +289,10 @@ func (eventState *eventMonitoringState) sendEvent(event *APIEvents) { } for _, listener := range eventState.listeners { - listener <- event + select { + case listener <- event: + default: + } } } } @@ -342,11 +360,12 @@ func (c *Client) eventHijack(startTime int64, eventChan chan *APIEvents, errChan if event.Time == 0 { continue } - if !c.eventMonitor.isEnabled() || c.eventMonitor.C != eventChan { - return - } transformEvent(&event) - eventChan <- &event + c.eventMonitor.RLock() + if c.eventMonitor.enabled && c.eventMonitor.C == eventChan { + eventChan <- &event + } + c.eventMonitor.RUnlock() } }(res, conn) return nil diff --git a/vendor/github.com/fsouza/go-dockerclient/exec.go b/vendor/github.com/fsouza/go-dockerclient/exec.go index b935c6893a..5e7ea87f6e 100644 --- a/vendor/github.com/fsouza/go-dockerclient/exec.go +++ b/vendor/github.com/fsouza/go-dockerclient/exec.go @@ -5,14 +5,14 @@ package docker import ( + "context" "encoding/json" + "errors" "fmt" "io" "net/http" "net/url" "strconv" - - "golang.org/x/net/context" ) // Exec is the type representing a `docker exec` instance and containing the @@ -29,9 +29,11 @@ type CreateExecOptions struct { AttachStdout bool `json:"AttachStdout,omitempty" yaml:"AttachStdout,omitempty" toml:"AttachStdout,omitempty"` AttachStderr bool `json:"AttachStderr,omitempty" yaml:"AttachStderr,omitempty" toml:"AttachStderr,omitempty"` Tty bool `json:"Tty,omitempty" yaml:"Tty,omitempty" toml:"Tty,omitempty"` + Env []string `json:"Env,omitempty" yaml:"Env,omitempty" toml:"Env,omitempty"` Cmd []string `json:"Cmd,omitempty" yaml:"Cmd,omitempty" toml:"Cmd,omitempty"` Container string `json:"Container,omitempty" yaml:"Container,omitempty" toml:"Container,omitempty"` User string `json:"User,omitempty" yaml:"User,omitempty" toml:"User,omitempty"` + WorkingDir string `json:"WorkingDir,omitempty" yaml:"WorkingDir,omitempty" toml:"WorkingDir,omitempty"` Context context.Context `json:"-"` Privileged bool `json:"Privileged,omitempty" yaml:"Privileged,omitempty" toml:"Privileged,omitempty"` } @@ -41,6 +43,12 @@ type CreateExecOptions struct { // // See https://goo.gl/60TeBP for more details func (c *Client) CreateExec(opts CreateExecOptions) (*Exec, error) { + if len(opts.Env) > 0 && c.serverAPIVersion.LessThan(apiVersion125) { + return nil, errors.New("exec configuration Env is only supported in API#1.25 and above") + } + if len(opts.WorkingDir) > 0 && c.serverAPIVersion.LessThan(apiVersion135) { + return nil, errors.New("exec configuration WorkingDir is only supported in API#1.35 and above") + } path := fmt.Sprintf("/containers/%s/exec", opts.Container) resp, err := c.do("POST", path, doOptions{data: opts, context: opts.Context}) if err != nil { diff --git a/vendor/github.com/fsouza/go-dockerclient/image.go b/vendor/github.com/fsouza/go-dockerclient/image.go index c386ad5dae..124e78da30 100644 --- a/vendor/github.com/fsouza/go-dockerclient/image.go +++ b/vendor/github.com/fsouza/go-dockerclient/image.go @@ -6,6 +6,7 @@ package docker import ( "bytes" + "context" "encoding/base64" "encoding/json" "errors" @@ -16,8 +17,6 @@ import ( "os" "strings" "time" - - "golang.org/x/net/context" ) // APIImages represent an image returned in the ListImages call. @@ -473,6 +472,8 @@ type BuildImageOptions struct { NetworkMode string `qs:"networkmode"` InactivityTimeout time.Duration `qs:"-"` CgroupParent string `qs:"cgroupparent"` + SecurityOpt []string `qs:"securityopt"` + Target string `gs:"target"` Context context.Context } diff --git a/vendor/github.com/fsouza/go-dockerclient/internal/archive/archive.go b/vendor/github.com/fsouza/go-dockerclient/internal/archive/archive.go new file mode 100644 index 0000000000..a13ee7cca2 --- /dev/null +++ b/vendor/github.com/fsouza/go-dockerclient/internal/archive/archive.go @@ -0,0 +1,505 @@ +// Copyright 2014 Docker authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the DOCKER-LICENSE file. + +package archive + +import ( + "archive/tar" + "bufio" + "compress/gzip" + "fmt" + "io" + "os" + "path/filepath" + "strings" + + "github.com/docker/docker/pkg/fileutils" + "github.com/docker/docker/pkg/idtools" + "github.com/docker/docker/pkg/pools" + "github.com/docker/docker/pkg/system" + "github.com/sirupsen/logrus" +) + +const ( + // Uncompressed represents the uncompressed. + Uncompressed Compression = iota + // Bzip2 is bzip2 compression algorithm. + Bzip2 + // Gzip is gzip compression algorithm. + Gzip + // Xz is xz compression algorithm. + Xz +) + +const ( + modeISDIR = 040000 // Directory + modeISFIFO = 010000 // FIFO + modeISREG = 0100000 // Regular file + modeISLNK = 0120000 // Symbolic link + modeISBLK = 060000 // Block special file + modeISCHR = 020000 // Character special file + modeISSOCK = 0140000 // Socket +) + +// Compression is the state represents if compressed or not. +type Compression int + +// Extension returns the extension of a file that uses the specified compression algorithm. +func (compression *Compression) Extension() string { + switch *compression { + case Uncompressed: + return "tar" + case Bzip2: + return "tar.bz2" + case Gzip: + return "tar.gz" + case Xz: + return "tar.xz" + } + return "" +} + +// WhiteoutFormat is the format of whiteouts unpacked +type WhiteoutFormat int + +// TarOptions wraps the tar options. +type TarOptions struct { + IncludeFiles []string + ExcludePatterns []string + Compression Compression + NoLchown bool + UIDMaps []idtools.IDMap + GIDMaps []idtools.IDMap + ChownOpts *idtools.IDPair + IncludeSourceDir bool + // WhiteoutFormat is the expected on disk format for whiteout files. + // This format will be converted to the standard format on pack + // and from the standard format on unpack. + WhiteoutFormat WhiteoutFormat + // When unpacking, specifies whether overwriting a directory with a + // non-directory is allowed and vice versa. + NoOverwriteDirNonDir bool + // For each include when creating an archive, the included name will be + // replaced with the matching name from this map. + RebaseNames map[string]string + InUserNS bool +} + +// TarWithOptions creates an archive from the directory at `path`, only including files whose relative +// paths are included in `options.IncludeFiles` (if non-nil) or not in `options.ExcludePatterns`. +func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error) { + + // Fix the source path to work with long path names. This is a no-op + // on platforms other than Windows. + srcPath = fixVolumePathPrefix(srcPath) + + pm, err := fileutils.NewPatternMatcher(options.ExcludePatterns) + if err != nil { + return nil, err + } + + pipeReader, pipeWriter := io.Pipe() + + compressWriter, err := CompressStream(pipeWriter, options.Compression) + if err != nil { + return nil, err + } + + go func() { + ta := newTarAppender( + idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps), + compressWriter, + options.ChownOpts, + ) + ta.WhiteoutConverter = getWhiteoutConverter(options.WhiteoutFormat) + + defer func() { + // Make sure to check the error on Close. + if err := ta.TarWriter.Close(); err != nil { + logrus.Errorf("Can't close tar writer: %s", err) + } + if err := compressWriter.Close(); err != nil { + logrus.Errorf("Can't close compress writer: %s", err) + } + if err := pipeWriter.Close(); err != nil { + logrus.Errorf("Can't close pipe writer: %s", err) + } + }() + + // this buffer is needed for the duration of this piped stream + defer pools.BufioWriter32KPool.Put(ta.Buffer) + + // In general we log errors here but ignore them because + // during e.g. a diff operation the container can continue + // mutating the filesystem and we can see transient errors + // from this + + stat, err := os.Lstat(srcPath) + if err != nil { + return + } + + if !stat.IsDir() { + // We can't later join a non-dir with any includes because the + // 'walk' will error if "file/." is stat-ed and "file" is not a + // directory. So, we must split the source path and use the + // basename as the include. + if len(options.IncludeFiles) > 0 { + logrus.Warn("Tar: Can't archive a file with includes") + } + + dir, base := SplitPathDirEntry(srcPath) + srcPath = dir + options.IncludeFiles = []string{base} + } + + if len(options.IncludeFiles) == 0 { + options.IncludeFiles = []string{"."} + } + + seen := make(map[string]bool) + + for _, include := range options.IncludeFiles { + rebaseName := options.RebaseNames[include] + + walkRoot := getWalkRoot(srcPath, include) + filepath.Walk(walkRoot, func(filePath string, f os.FileInfo, err error) error { + if err != nil { + logrus.Errorf("Tar: Can't stat file %s to tar: %s", srcPath, err) + return nil + } + + relFilePath, err := filepath.Rel(srcPath, filePath) + if err != nil || (!options.IncludeSourceDir && relFilePath == "." && f.IsDir()) { + // Error getting relative path OR we are looking + // at the source directory path. Skip in both situations. + return nil + } + + if options.IncludeSourceDir && include == "." && relFilePath != "." { + relFilePath = strings.Join([]string{".", relFilePath}, string(filepath.Separator)) + } + + skip := false + + // If "include" is an exact match for the current file + // then even if there's an "excludePatterns" pattern that + // matches it, don't skip it. IOW, assume an explicit 'include' + // is asking for that file no matter what - which is true + // for some files, like .dockerignore and Dockerfile (sometimes) + if include != relFilePath { + skip, err = pm.Matches(relFilePath) + if err != nil { + logrus.Errorf("Error matching %s: %v", relFilePath, err) + return err + } + } + + if skip { + // If we want to skip this file and its a directory + // then we should first check to see if there's an + // excludes pattern (e.g. !dir/file) that starts with this + // dir. If so then we can't skip this dir. + + // Its not a dir then so we can just return/skip. + if !f.IsDir() { + return nil + } + + // No exceptions (!...) in patterns so just skip dir + if !pm.Exclusions() { + return filepath.SkipDir + } + + dirSlash := relFilePath + string(filepath.Separator) + + for _, pat := range pm.Patterns() { + if !pat.Exclusion() { + continue + } + if strings.HasPrefix(pat.String()+string(filepath.Separator), dirSlash) { + // found a match - so can't skip this dir + return nil + } + } + + // No matching exclusion dir so just skip dir + return filepath.SkipDir + } + + if seen[relFilePath] { + return nil + } + seen[relFilePath] = true + + // Rename the base resource. + if rebaseName != "" { + var replacement string + if rebaseName != string(filepath.Separator) { + // Special case the root directory to replace with an + // empty string instead so that we don't end up with + // double slashes in the paths. + replacement = rebaseName + } + + relFilePath = strings.Replace(relFilePath, include, replacement, 1) + } + + if err := ta.addTarFile(filePath, relFilePath); err != nil { + logrus.Errorf("Can't add file %s to tar: %s", filePath, err) + // if pipe is broken, stop writing tar stream to it + if err == io.ErrClosedPipe { + return err + } + } + return nil + }) + } + }() + + return pipeReader, nil +} + +// CompressStream compresses the dest with specified compression algorithm. +func CompressStream(dest io.Writer, compression Compression) (io.WriteCloser, error) { + p := pools.BufioWriter32KPool + buf := p.Get(dest) + switch compression { + case Uncompressed: + writeBufWrapper := p.NewWriteCloserWrapper(buf, buf) + return writeBufWrapper, nil + case Gzip: + gzWriter := gzip.NewWriter(dest) + writeBufWrapper := p.NewWriteCloserWrapper(buf, gzWriter) + return writeBufWrapper, nil + case Bzip2, Xz: + // archive/bzip2 does not support writing, and there is no xz support at all + // However, this is not a problem as docker only currently generates gzipped tars + return nil, fmt.Errorf("Unsupported compression format %s", (&compression).Extension()) + default: + return nil, fmt.Errorf("Unsupported compression format %s", (&compression).Extension()) + } +} + +type tarWhiteoutConverter interface { + ConvertWrite(*tar.Header, string, os.FileInfo) (*tar.Header, error) + ConvertRead(*tar.Header, string) (bool, error) +} + +type tarAppender struct { + TarWriter *tar.Writer + Buffer *bufio.Writer + + // for hardlink mapping + SeenFiles map[uint64]string + IDMappings *idtools.IDMappings + ChownOpts *idtools.IDPair + + // For packing and unpacking whiteout files in the + // non standard format. The whiteout files defined + // by the AUFS standard are used as the tar whiteout + // standard. + WhiteoutConverter tarWhiteoutConverter +} + +func newTarAppender(idMapping *idtools.IDMappings, writer io.Writer, chownOpts *idtools.IDPair) *tarAppender { + return &tarAppender{ + SeenFiles: make(map[uint64]string), + TarWriter: tar.NewWriter(writer), + Buffer: pools.BufioWriter32KPool.Get(nil), + IDMappings: idMapping, + ChownOpts: chownOpts, + } +} + +// addTarFile adds to the tar archive a file from `path` as `name` +func (ta *tarAppender) addTarFile(path, name string) error { + fi, err := os.Lstat(path) + if err != nil { + return err + } + + var link string + if fi.Mode()&os.ModeSymlink != 0 { + var err error + link, err = os.Readlink(path) + if err != nil { + return err + } + } + + hdr, err := FileInfoHeader(name, fi, link) + if err != nil { + return err + } + if err := ReadSecurityXattrToTarHeader(path, hdr); err != nil { + return err + } + + // if it's not a directory and has more than 1 link, + // it's hard linked, so set the type flag accordingly + if !fi.IsDir() && hasHardlinks(fi) { + inode, err := getInodeFromStat(fi.Sys()) + if err != nil { + return err + } + // a link should have a name that it links too + // and that linked name should be first in the tar archive + if oldpath, ok := ta.SeenFiles[inode]; ok { + hdr.Typeflag = tar.TypeLink + hdr.Linkname = oldpath + hdr.Size = 0 // This Must be here for the writer math to add up! + } else { + ta.SeenFiles[inode] = name + } + } + + //check whether the file is overlayfs whiteout + //if yes, skip re-mapping container ID mappings. + isOverlayWhiteout := fi.Mode()&os.ModeCharDevice != 0 && hdr.Devmajor == 0 && hdr.Devminor == 0 + + //handle re-mapping container ID mappings back to host ID mappings before + //writing tar headers/files. We skip whiteout files because they were written + //by the kernel and already have proper ownership relative to the host + if !isOverlayWhiteout && + !strings.HasPrefix(filepath.Base(hdr.Name), WhiteoutPrefix) && + !ta.IDMappings.Empty() { + fileIDPair, err := getFileUIDGID(fi.Sys()) + if err != nil { + return err + } + hdr.Uid, hdr.Gid, err = ta.IDMappings.ToContainer(fileIDPair) + if err != nil { + return err + } + } + + // explicitly override with ChownOpts + if ta.ChownOpts != nil { + hdr.Uid = ta.ChownOpts.UID + hdr.Gid = ta.ChownOpts.GID + } + + if ta.WhiteoutConverter != nil { + wo, err := ta.WhiteoutConverter.ConvertWrite(hdr, path, fi) + if err != nil { + return err + } + + // If a new whiteout file exists, write original hdr, then + // replace hdr with wo to be written after. Whiteouts should + // always be written after the original. Note the original + // hdr may have been updated to be a whiteout with returning + // a whiteout header + if wo != nil { + if err := ta.TarWriter.WriteHeader(hdr); err != nil { + return err + } + if hdr.Typeflag == tar.TypeReg && hdr.Size > 0 { + return fmt.Errorf("tar: cannot use whiteout for non-empty file") + } + hdr = wo + } + } + + if err := ta.TarWriter.WriteHeader(hdr); err != nil { + return err + } + + if hdr.Typeflag == tar.TypeReg && hdr.Size > 0 { + // We use system.OpenSequential to ensure we use sequential file + // access on Windows to avoid depleting the standby list. + // On Linux, this equates to a regular os.Open. + file, err := system.OpenSequential(path) + if err != nil { + return err + } + + ta.Buffer.Reset(ta.TarWriter) + defer ta.Buffer.Reset(nil) + _, err = io.Copy(ta.Buffer, file) + file.Close() + if err != nil { + return err + } + err = ta.Buffer.Flush() + if err != nil { + return err + } + } + + return nil +} + +// ReadSecurityXattrToTarHeader reads security.capability xattr from filesystem +// to a tar header +func ReadSecurityXattrToTarHeader(path string, hdr *tar.Header) error { + capability, _ := system.Lgetxattr(path, "security.capability") + if capability != nil { + hdr.Xattrs = make(map[string]string) + hdr.Xattrs["security.capability"] = string(capability) + } + return nil +} + +// FileInfoHeader creates a populated Header from fi. +// Compared to archive pkg this function fills in more information. +// Also, regardless of Go version, this function fills file type bits (e.g. hdr.Mode |= modeISDIR), +// which have been deleted since Go 1.9 archive/tar. +func FileInfoHeader(name string, fi os.FileInfo, link string) (*tar.Header, error) { + hdr, err := tar.FileInfoHeader(fi, link) + if err != nil { + return nil, err + } + hdr.Mode = fillGo18FileTypeBits(int64(chmodTarEntry(os.FileMode(hdr.Mode))), fi) + name, err = canonicalTarName(name, fi.IsDir()) + if err != nil { + return nil, fmt.Errorf("tar: cannot canonicalize path: %v", err) + } + hdr.Name = name + if err := setHeaderForSpecialDevice(hdr, name, fi.Sys()); err != nil { + return nil, err + } + return hdr, nil +} + +// fillGo18FileTypeBits fills type bits which have been removed on Go 1.9 archive/tar +// https://github.com/golang/go/commit/66b5a2f +func fillGo18FileTypeBits(mode int64, fi os.FileInfo) int64 { + fm := fi.Mode() + switch { + case fm.IsRegular(): + mode |= modeISREG + case fi.IsDir(): + mode |= modeISDIR + case fm&os.ModeSymlink != 0: + mode |= modeISLNK + case fm&os.ModeDevice != 0: + if fm&os.ModeCharDevice != 0 { + mode |= modeISCHR + } else { + mode |= modeISBLK + } + case fm&os.ModeNamedPipe != 0: + mode |= modeISFIFO + case fm&os.ModeSocket != 0: + mode |= modeISSOCK + } + return mode +} + +// canonicalTarName provides a platform-independent and consistent posix-style +//path for files and directories to be archived regardless of the platform. +func canonicalTarName(name string, isDir bool) (string, error) { + name, err := CanonicalTarNameForPath(name) + if err != nil { + return "", err + } + + // suffix with '/' for directories + if isDir && !strings.HasSuffix(name, "/") { + name += "/" + } + return name, nil +} diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_linux.go b/vendor/github.com/fsouza/go-dockerclient/internal/archive/archive_linux.go similarity index 86% rename from vendor/github.com/docker/docker/pkg/archive/archive_linux.go rename to vendor/github.com/fsouza/go-dockerclient/internal/archive/archive_linux.go index 6e950e93cf..9e1f3f2f14 100644 --- a/vendor/github.com/docker/docker/pkg/archive/archive_linux.go +++ b/vendor/github.com/fsouza/go-dockerclient/internal/archive/archive_linux.go @@ -1,3 +1,7 @@ +// Copyright 2014 Docker authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the DOCKER-LICENSE file. + package archive import ( @@ -10,6 +14,14 @@ import ( "golang.org/x/sys/unix" ) +const ( + // AUFSWhiteoutFormat is the default format for whiteouts + AUFSWhiteoutFormat WhiteoutFormat = iota + // OverlayWhiteoutFormat formats whiteout according to the overlay + // standard. + OverlayWhiteoutFormat +) + func getWhiteoutConverter(format WhiteoutFormat) tarWhiteoutConverter { if format == OverlayWhiteoutFormat { return overlayWhiteoutConverter{} diff --git a/vendor/github.com/fsouza/go-dockerclient/internal/archive/archive_other.go b/vendor/github.com/fsouza/go-dockerclient/internal/archive/archive_other.go new file mode 100644 index 0000000000..72822c8578 --- /dev/null +++ b/vendor/github.com/fsouza/go-dockerclient/internal/archive/archive_other.go @@ -0,0 +1,11 @@ +// Copyright 2014 Docker authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the DOCKER-LICENSE file. + +// +build !linux + +package archive + +func getWhiteoutConverter(format WhiteoutFormat) tarWhiteoutConverter { + return nil +} diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_unix.go b/vendor/github.com/fsouza/go-dockerclient/internal/archive/archive_unix.go similarity index 60% rename from vendor/github.com/docker/docker/pkg/archive/archive_unix.go rename to vendor/github.com/fsouza/go-dockerclient/internal/archive/archive_unix.go index 02e95adff5..2633f50206 100644 --- a/vendor/github.com/docker/docker/pkg/archive/archive_unix.go +++ b/vendor/github.com/fsouza/go-dockerclient/internal/archive/archive_unix.go @@ -1,3 +1,7 @@ +// Copyright 2014 Docker authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the DOCKER-LICENSE file. + // +build !windows package archive @@ -10,11 +14,16 @@ import ( "syscall" "github.com/docker/docker/pkg/idtools" - "github.com/docker/docker/pkg/system" - rsystem "github.com/opencontainers/runc/libcontainer/system" "golang.org/x/sys/unix" ) +// CanonicalTarNameForPath returns platform-specific filepath +// to canonical posix-style path for tar archival. p is relative +// path. +func CanonicalTarNameForPath(p string) (string, error) { + return p, nil // already unix-style +} + // fixVolumePathPrefix does platform specific processing to ensure that if // the path being passed in is not in a volume path format, convert it to one. func fixVolumePathPrefix(srcPath string) string { @@ -29,40 +38,11 @@ func getWalkRoot(srcPath string, include string) string { return srcPath + string(filepath.Separator) + include } -// CanonicalTarNameForPath returns platform-specific filepath -// to canonical posix-style path for tar archival. p is relative -// path. -func CanonicalTarNameForPath(p string) (string, error) { - return p, nil // already unix-style -} - -// chmodTarEntry is used to adjust the file permissions used in tar header based -// on the platform the archival is done. - -func chmodTarEntry(perm os.FileMode) os.FileMode { - return perm // noop for unix as golang APIs provide perm bits correctly -} - -func setHeaderForSpecialDevice(hdr *tar.Header, name string, stat interface{}) (err error) { - s, ok := stat.(*syscall.Stat_t) - - if ok { - // Currently go does not fill in the major/minors - if s.Mode&unix.S_IFBLK != 0 || - s.Mode&unix.S_IFCHR != 0 { - hdr.Devmajor = int64(unix.Major(uint64(s.Rdev))) // nolint: unconvert - hdr.Devminor = int64(unix.Minor(uint64(s.Rdev))) // nolint: unconvert - } - } - - return -} - func getInodeFromStat(stat interface{}) (inode uint64, err error) { s, ok := stat.(*syscall.Stat_t) if ok { - inode = s.Ino + inode = uint64(s.Ino) } return @@ -77,38 +57,21 @@ func getFileUIDGID(stat interface{}) (idtools.IDPair, error) { return idtools.IDPair{UID: int(s.Uid), GID: int(s.Gid)}, nil } -// handleTarTypeBlockCharFifo is an OS-specific helper function used by -// createTarFile to handle the following types of header: Block; Char; Fifo -func handleTarTypeBlockCharFifo(hdr *tar.Header, path string) error { - if rsystem.RunningInUserNS() { - // cannot create a device if running in user namespace - return nil - } - - mode := uint32(hdr.Mode & 07777) - switch hdr.Typeflag { - case tar.TypeBlock: - mode |= unix.S_IFBLK - case tar.TypeChar: - mode |= unix.S_IFCHR - case tar.TypeFifo: - mode |= unix.S_IFIFO - } - - return system.Mknod(path, mode, int(system.Mkdev(hdr.Devmajor, hdr.Devminor))) +func chmodTarEntry(perm os.FileMode) os.FileMode { + return perm // noop for unix as golang APIs provide perm bits correctly } -func handleLChmod(hdr *tar.Header, path string, hdrInfo os.FileInfo) error { - if hdr.Typeflag == tar.TypeLink { - if fi, err := os.Lstat(hdr.Linkname); err == nil && (fi.Mode()&os.ModeSymlink == 0) { - if err := os.Chmod(path, hdrInfo.Mode()); err != nil { - return err - } - } - } else if hdr.Typeflag != tar.TypeSymlink { - if err := os.Chmod(path, hdrInfo.Mode()); err != nil { - return err +func setHeaderForSpecialDevice(hdr *tar.Header, name string, stat interface{}) (err error) { + s, ok := stat.(*syscall.Stat_t) + + if ok { + // Currently go does not fill in the major/minors + if s.Mode&unix.S_IFBLK != 0 || + s.Mode&unix.S_IFCHR != 0 { + hdr.Devmajor = int64(unix.Major(uint64(s.Rdev))) // nolint: unconvert + hdr.Devminor = int64(unix.Minor(uint64(s.Rdev))) // nolint: unconvert } } - return nil + + return } diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_windows.go b/vendor/github.com/fsouza/go-dockerclient/internal/archive/archive_windows.go similarity index 86% rename from vendor/github.com/docker/docker/pkg/archive/archive_windows.go rename to vendor/github.com/fsouza/go-dockerclient/internal/archive/archive_windows.go index a22410c039..c14875cd77 100644 --- a/vendor/github.com/docker/docker/pkg/archive/archive_windows.go +++ b/vendor/github.com/fsouza/go-dockerclient/internal/archive/archive_windows.go @@ -1,4 +1,6 @@ -// +build windows +// Copyright 2014 Docker authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the DOCKER-LICENSE file. package archive @@ -13,18 +15,6 @@ import ( "github.com/docker/docker/pkg/longpath" ) -// fixVolumePathPrefix does platform specific processing to ensure that if -// the path being passed in is not in a volume path format, convert it to one. -func fixVolumePathPrefix(srcPath string) string { - return longpath.AddPrefix(srcPath) -} - -// getWalkRoot calculates the root path when performing a TarWithOptions. -// We use a separate function as this is platform specific. -func getWalkRoot(srcPath string, include string) string { - return filepath.Join(srcPath, include) -} - // CanonicalTarNameForPath returns platform-specific filepath // to canonical posix-style path for tar archival. p is relative // path. @@ -40,6 +30,28 @@ func CanonicalTarNameForPath(p string) (string, error) { } +// fixVolumePathPrefix does platform specific processing to ensure that if +// the path being passed in is not in a volume path format, convert it to one. +func fixVolumePathPrefix(srcPath string) string { + return longpath.AddPrefix(srcPath) +} + +// getWalkRoot calculates the root path when performing a TarWithOptions. +// We use a separate function as this is platform specific. +func getWalkRoot(srcPath string, include string) string { + return filepath.Join(srcPath, include) +} + +func getInodeFromStat(stat interface{}) (inode uint64, err error) { + // do nothing. no notion of Inode in stat on Windows + return +} + +func getFileUIDGID(stat interface{}) (idtools.IDPair, error) { + // no notion of file ownership mapping yet on Windows + return idtools.IDPair{0, 0}, nil +} + // chmodTarEntry is used to adjust the file permissions used in tar header based // on the platform the archival is done. func chmodTarEntry(perm os.FileMode) os.FileMode { @@ -57,23 +69,3 @@ func setHeaderForSpecialDevice(hdr *tar.Header, name string, stat interface{}) ( // do nothing. no notion of Rdev, Nlink in stat on Windows return } - -func getInodeFromStat(stat interface{}) (inode uint64, err error) { - // do nothing. no notion of Inode in stat on Windows - return -} - -// handleTarTypeBlockCharFifo is an OS-specific helper function used by -// createTarFile to handle the following types of header: Block; Char; Fifo -func handleTarTypeBlockCharFifo(hdr *tar.Header, path string) error { - return nil -} - -func handleLChmod(hdr *tar.Header, path string, hdrInfo os.FileInfo) error { - return nil -} - -func getFileUIDGID(stat interface{}) (idtools.IDPair, error) { - // no notion of file ownership mapping yet on Windows - return idtools.IDPair{0, 0}, nil -} diff --git a/vendor/github.com/fsouza/go-dockerclient/internal/archive/changes_unix.go b/vendor/github.com/fsouza/go-dockerclient/internal/archive/changes_unix.go new file mode 100644 index 0000000000..39ea287bfe --- /dev/null +++ b/vendor/github.com/fsouza/go-dockerclient/internal/archive/changes_unix.go @@ -0,0 +1,16 @@ +// Copyright 2014 Docker authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the DOCKER-LICENSE file. + +// +build !windows + +package archive + +import ( + "os" + "syscall" +) + +func hasHardlinks(fi os.FileInfo) bool { + return fi.Sys().(*syscall.Stat_t).Nlink > 1 +} diff --git a/vendor/github.com/fsouza/go-dockerclient/internal/archive/changes_windows.go b/vendor/github.com/fsouza/go-dockerclient/internal/archive/changes_windows.go new file mode 100644 index 0000000000..a93130474a --- /dev/null +++ b/vendor/github.com/fsouza/go-dockerclient/internal/archive/changes_windows.go @@ -0,0 +1,11 @@ +// Copyright 2014 Docker authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the DOCKER-LICENSE file. + +package archive + +import "os" + +func hasHardlinks(fi os.FileInfo) bool { + return false +} diff --git a/vendor/github.com/fsouza/go-dockerclient/internal/archive/copy.go b/vendor/github.com/fsouza/go-dockerclient/internal/archive/copy.go new file mode 100644 index 0000000000..45d45f20ed --- /dev/null +++ b/vendor/github.com/fsouza/go-dockerclient/internal/archive/copy.go @@ -0,0 +1,29 @@ +// Copyright 2014 Docker authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the DOCKER-LICENSE file. + +package archive + +import ( + "os" + "path/filepath" +) + +// SplitPathDirEntry splits the given path between its directory name and its +// basename by first cleaning the path but preserves a trailing "." if the +// original path specified the current directory. +func SplitPathDirEntry(path string) (dir, base string) { + cleanedPath := filepath.Clean(filepath.FromSlash(path)) + + if specifiesCurrentDir(path) { + cleanedPath += string(os.PathSeparator) + "." + } + + return filepath.Dir(cleanedPath), filepath.Base(cleanedPath) +} + +// specifiesCurrentDir returns whether the given path specifies +// a "current directory", i.e., the last path segment is `.`. +func specifiesCurrentDir(path string) bool { + return filepath.Base(path) == "." +} diff --git a/vendor/github.com/docker/docker/pkg/archive/whiteouts.go b/vendor/github.com/fsouza/go-dockerclient/internal/archive/whiteouts.go similarity index 86% rename from vendor/github.com/docker/docker/pkg/archive/whiteouts.go rename to vendor/github.com/fsouza/go-dockerclient/internal/archive/whiteouts.go index d20478a10d..a61c22a083 100644 --- a/vendor/github.com/docker/docker/pkg/archive/whiteouts.go +++ b/vendor/github.com/fsouza/go-dockerclient/internal/archive/whiteouts.go @@ -1,3 +1,7 @@ +// Copyright 2014 Docker authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the DOCKER-LICENSE file. + package archive // Whiteouts are files with a special meaning for the layered filesystem. diff --git a/vendor/github.com/docker/docker/pkg/jsonmessage/jsonmessage.go b/vendor/github.com/fsouza/go-dockerclient/internal/jsonmessage/jsonmessage.go similarity index 91% rename from vendor/github.com/docker/docker/pkg/jsonmessage/jsonmessage.go rename to vendor/github.com/fsouza/go-dockerclient/internal/jsonmessage/jsonmessage.go index 6cfa464830..71b3395cec 100644 --- a/vendor/github.com/docker/docker/pkg/jsonmessage/jsonmessage.go +++ b/vendor/github.com/fsouza/go-dockerclient/internal/jsonmessage/jsonmessage.go @@ -1,3 +1,7 @@ +// Copyright 2014 Docker authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the DOCKER-LICENSE file. + package jsonmessage import ( @@ -8,9 +12,9 @@ import ( "strings" "time" - gotty "github.com/Nvveen/Gotty" - "github.com/docker/docker/pkg/term" - units "github.com/docker/go-units" + "github.com/Nvveen/Gotty" + "github.com/docker/go-units" + "github.com/fsouza/go-dockerclient/internal/term" ) // RFC3339NanoFixed is time.RFC3339Nano with nanoseconds padded using zeros to @@ -40,21 +44,17 @@ type JSONProgress struct { // If true, don't show xB/yB HideCounts bool `json:"hidecounts,omitempty"` Units string `json:"units,omitempty"` + nowFunc func() time.Time + winSize int } func (p *JSONProgress) String() string { var ( - width = 200 + width = p.width() pbBox string numbersBox string timeLeftBox string ) - - ws, err := term.GetWinsize(p.terminalFd) - if err == nil { - width = int(ws.Width) - } - if p.Current <= 0 && p.Total <= 0 { return "" } @@ -103,7 +103,7 @@ func (p *JSONProgress) String() string { } if p.Current > 0 && p.Start > 0 && percentage < 50 { - fromStart := time.Now().UTC().Sub(time.Unix(p.Start, 0)) + fromStart := p.now().Sub(time.Unix(p.Start, 0)) perEntry := fromStart / time.Duration(p.Current) left := time.Duration(p.Total-p.Current) * perEntry left = (left / time.Second) * time.Second @@ -115,6 +115,28 @@ func (p *JSONProgress) String() string { return pbBox + numbersBox + timeLeftBox } +// shim for testing +func (p *JSONProgress) now() time.Time { + if p.nowFunc == nil { + p.nowFunc = func() time.Time { + return time.Now().UTC() + } + } + return p.nowFunc() +} + +// shim for testing +func (p *JSONProgress) width() int { + if p.winSize != 0 { + return p.winSize + } + ws, err := term.GetWinsize(p.terminalFd) + if err == nil { + return int(ws.Width) + } + return 200 +} + // JSONMessage defines a message struct. It describes // the created time, where it from, status, ID of the // message. It's used for docker events. @@ -227,7 +249,7 @@ func (jm *JSONMessage) Display(out io.Writer, termInfo termInfo) error { // DisplayJSONMessagesStream displays a json message stream from `in` to `out`, `isTerminal` // describes if `out` is a terminal. If this is the case, it will print `\n` at the end of // each line and move the cursor while displaying. -func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr, isTerminal bool, auxCallback func(*json.RawMessage)) error { +func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr, isTerminal bool, auxCallback func(JSONMessage)) error { var ( dec = json.NewDecoder(in) ids = make(map[string]int) @@ -259,7 +281,7 @@ func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr, if jm.Aux != nil { if auxCallback != nil { - auxCallback(jm.Aux) + auxCallback(jm) } continue } @@ -312,6 +334,6 @@ type stream interface { } // DisplayJSONMessagesToStream prints json messages to the output stream -func DisplayJSONMessagesToStream(in io.Reader, stream stream, auxCallback func(*json.RawMessage)) error { +func DisplayJSONMessagesToStream(in io.Reader, stream stream, auxCallback func(JSONMessage)) error { return DisplayJSONMessagesStream(in, stream, stream.FD(), stream.IsTerminal(), auxCallback) } diff --git a/vendor/github.com/fsouza/go-dockerclient/internal/term/term.go b/vendor/github.com/fsouza/go-dockerclient/internal/term/term.go new file mode 100644 index 0000000000..af06911d8b --- /dev/null +++ b/vendor/github.com/fsouza/go-dockerclient/internal/term/term.go @@ -0,0 +1,13 @@ +// Copyright 2014 Docker authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the DOCKER-LICENSE file. + +package term + +// Winsize represents the size of the terminal window. +type Winsize struct { + Height uint16 + Width uint16 + x uint16 + y uint16 +} diff --git a/vendor/github.com/docker/docker/pkg/term/winsize.go b/vendor/github.com/fsouza/go-dockerclient/internal/term/winsize.go similarity index 50% rename from vendor/github.com/docker/docker/pkg/term/winsize.go rename to vendor/github.com/fsouza/go-dockerclient/internal/term/winsize.go index 1ef98d5996..2a9964a0df 100644 --- a/vendor/github.com/docker/docker/pkg/term/winsize.go +++ b/vendor/github.com/fsouza/go-dockerclient/internal/term/winsize.go @@ -1,10 +1,12 @@ +// Copyright 2014 Docker authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the DOCKER-LICENSE file. + // +build !windows package term -import ( - "golang.org/x/sys/unix" -) +import "golang.org/x/sys/unix" // GetWinsize returns the window size based on the specified file descriptor. func GetWinsize(fd uintptr) (*Winsize, error) { @@ -12,9 +14,3 @@ func GetWinsize(fd uintptr) (*Winsize, error) { ws := &Winsize{Height: uws.Row, Width: uws.Col, x: uws.Xpixel, y: uws.Ypixel} return ws, err } - -// SetWinsize tries to set the specified window size for the specified file descriptor. -func SetWinsize(fd uintptr, ws *Winsize) error { - uws := &unix.Winsize{Row: ws.Height, Col: ws.Width, Xpixel: ws.x, Ypixel: ws.y} - return unix.IoctlSetWinsize(int(fd), unix.TIOCSWINSZ, uws) -} diff --git a/vendor/github.com/fsouza/go-dockerclient/internal/term/winsize_windows.go b/vendor/github.com/fsouza/go-dockerclient/internal/term/winsize_windows.go new file mode 100644 index 0000000000..4a07a5d19b --- /dev/null +++ b/vendor/github.com/fsouza/go-dockerclient/internal/term/winsize_windows.go @@ -0,0 +1,22 @@ +// Copyright 2014 Docker authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the DOCKER-LICENSE file. + +package term + +import "github.com/Azure/go-ansiterm/winterm" + +// GetWinsize returns the window size based on the specified file descriptor. +func GetWinsize(fd uintptr) (*Winsize, error) { + info, err := winterm.GetConsoleScreenBufferInfo(fd) + if err != nil { + return nil, err + } + + winsize := &Winsize{ + Width: uint16(info.Window.Right - info.Window.Left + 1), + Height: uint16(info.Window.Bottom - info.Window.Top + 1), + } + + return winsize, nil +} diff --git a/vendor/github.com/fsouza/go-dockerclient/misc.go b/vendor/github.com/fsouza/go-dockerclient/misc.go index 0482838abe..1fc37b14ed 100644 --- a/vendor/github.com/fsouza/go-dockerclient/misc.go +++ b/vendor/github.com/fsouza/go-dockerclient/misc.go @@ -5,6 +5,7 @@ package docker import ( + "context" "encoding/json" "net" "strings" @@ -16,7 +17,12 @@ import ( // // See https://goo.gl/mU7yje for more details. func (c *Client) Version() (*Env, error) { - resp, err := c.do("GET", "/version", doOptions{}) + return c.VersionWithContext(nil) +} + +// VersionWithContext returns version information about the docker server. +func (c *Client) VersionWithContext(ctx context.Context) (*Env, error) { + resp, err := c.do("GET", "/version", doOptions{context: ctx}) if err != nil { return nil, err } @@ -68,6 +74,7 @@ type DockerInfo struct { Architecture string IndexServerAddress string RegistryConfig *ServiceConfig + SecurityOptions []string NCPU int MemTotal int64 DockerRootDir string diff --git a/vendor/github.com/fsouza/go-dockerclient/network.go b/vendor/github.com/fsouza/go-dockerclient/network.go index 295efd565d..c6ddb22c62 100644 --- a/vendor/github.com/fsouza/go-dockerclient/network.go +++ b/vendor/github.com/fsouza/go-dockerclient/network.go @@ -5,12 +5,11 @@ package docker import ( + "context" "encoding/json" "errors" "fmt" "net/http" - - "golang.org/x/net/context" ) // ErrNetworkAlreadyExists is the error returned by CreateNetwork when the @@ -112,7 +111,7 @@ func (c *Client) NetworkInfo(id string) (*Network, error) { type CreateNetworkOptions struct { Name string `json:"Name" yaml:"Name" toml:"Name"` Driver string `json:"Driver" yaml:"Driver" toml:"Driver"` - IPAM IPAMOptions `json:"IPAM" yaml:"IPAM" toml:"IPAM"` + IPAM *IPAMOptions `json:"IPAM,omitempty" yaml:"IPAM" toml:"IPAM"` Options map[string]interface{} `json:"Options" yaml:"Options" toml:"Options"` Labels map[string]string `json:"Labels" yaml:"Labels" toml:"Labels"` CheckDuplicate bool `json:"CheckDuplicate" yaml:"CheckDuplicate" toml:"CheckDuplicate"` @@ -125,8 +124,9 @@ type CreateNetworkOptions struct { // // See https://goo.gl/T8kRVH for more details. type IPAMOptions struct { - Driver string `json:"Driver" yaml:"Driver" toml:"Driver"` - Config []IPAMConfig `json:"Config" yaml:"Config" toml:"Config"` + Driver string `json:"Driver" yaml:"Driver" toml:"Driver"` + Config []IPAMConfig `json:"Config" yaml:"Config" toml:"Config"` + Options map[string]string `json:"Options" yaml:"Options" toml:"Options"` } // IPAMConfig represents IPAM configurations diff --git a/vendor/github.com/fsouza/go-dockerclient/plugin.go b/vendor/github.com/fsouza/go-dockerclient/plugin.go new file mode 100644 index 0000000000..a28ff3d1e9 --- /dev/null +++ b/vendor/github.com/fsouza/go-dockerclient/plugin.go @@ -0,0 +1,418 @@ +// Copyright 2018 go-dockerclient authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package docker + +import ( + "context" + "encoding/json" + "io/ioutil" + "net/http" +) + +// PluginPrivilege represents a privilege for a plugin. +type PluginPrivilege struct { + Name string `json:"Name,omitempty" yaml:"Name,omitempty" toml:"Name,omitempty"` + Description string `json:"Description,omitempty" yaml:"Description,omitempty" toml:"Description,omitempty"` + Value []string `json:"Value,omitempty" yaml:"Value,omitempty" toml:"Value,omitempty"` +} + +// InstallPluginOptions specify parameters to the InstallPlugins function. +// +// See https://goo.gl/C4t7Tz for more details. +type InstallPluginOptions struct { + Remote string + Name string + Plugins []PluginPrivilege `qs:"-"` + + Auth AuthConfiguration + + Context context.Context +} + +// InstallPlugins installs a plugin or returns an error in case of failure. +// +// See https://goo.gl/C4t7Tz for more details. +func (c *Client) InstallPlugins(opts InstallPluginOptions) error { + path := "/plugins/pull?" + queryString(opts) + resp, err := c.do("POST", path, doOptions{ + data: opts.Plugins, + context: opts.Context, + }) + defer resp.Body.Close() + if err != nil { + return err + } + return nil +} + +// PluginSettings stores plugin settings. +// +// See https://goo.gl/C4t7Tz for more details. +type PluginSettings struct { + Env []string `json:"Env,omitempty" yaml:"Env,omitempty" toml:"Env,omitempty"` + Args []string `json:"Args,omitempty" yaml:"Args,omitempty" toml:"Args,omitempty"` + Devices []string `json:"Devices,omitempty" yaml:"Devices,omitempty" toml:"Devices,omitempty"` +} + +// PluginInterface stores plugin interface. +// +// See https://goo.gl/C4t7Tz for more details. +type PluginInterface struct { + Types []string `json:"Types,omitempty" yaml:"Types,omitempty" toml:"Types,omitempty"` + Socket string `json:"Socket,omitempty" yaml:"Socket,omitempty" toml:"Socket,omitempty"` +} + +// PluginNetwork stores plugin network type. +// +// See https://goo.gl/C4t7Tz for more details. +type PluginNetwork struct { + Type string `json:"Type,omitempty" yaml:"Type,omitempty" toml:"Type,omitempty"` +} + +// PluginLinux stores plugin linux setting. +// +// See https://goo.gl/C4t7Tz for more details. +type PluginLinux struct { + Capabilities []string `json:"Capabilities,omitempty" yaml:"Capabilities,omitempty" toml:"Capabilities,omitempty"` + AllowAllDevices bool `json:"AllowAllDevices,omitempty" yaml:"AllowAllDevices,omitempty" toml:"AllowAllDevices,omitempty"` + Devices []PluginLinuxDevices `json:"Devices,omitempty" yaml:"Devices,omitempty" toml:"Devices,omitempty"` +} + +// PluginLinuxDevices stores plugin linux device setting. +// +// See https://goo.gl/C4t7Tz for more details. +type PluginLinuxDevices struct { + Name string `json:"Name,omitempty" yaml:"Name,omitempty" toml:"Name,omitempty"` + Description string `json:"Documentation,omitempty" yaml:"Documentation,omitempty" toml:"Documentation,omitempty"` + Settable []string `json:"Settable,omitempty" yaml:"Settable,omitempty" toml:"Settable,omitempty"` + Path string `json:"Path,omitempty" yaml:"Path,omitempty" toml:"Path,omitempty"` +} + +// PluginEnv stores plugin environment. +// +// See https://goo.gl/C4t7Tz for more details. +type PluginEnv struct { + Name string `json:"Name,omitempty" yaml:"Name,omitempty" toml:"Name,omitempty"` + Description string `json:"Description,omitempty" yaml:"Description,omitempty" toml:"Description,omitempty"` + Settable []string `json:"Settable,omitempty" yaml:"Settable,omitempty" toml:"Settable,omitempty"` + Value string `json:"Value,omitempty" yaml:"Value,omitempty" toml:"Value,omitempty"` +} + +// PluginArgs stores plugin arguments. +// +// See https://goo.gl/C4t7Tz for more details. +type PluginArgs struct { + Name string `json:"Name,omitempty" yaml:"Name,omitempty" toml:"Name,omitempty"` + Description string `json:"Description,omitempty" yaml:"Description,omitempty" toml:"Description,omitempty"` + Settable []string `json:"Settable,omitempty" yaml:"Settable,omitempty" toml:"Settable,omitempty"` + Value []string `json:"Value,omitempty" yaml:"Value,omitempty" toml:"Value,omitempty"` +} + +// PluginUser stores plugin user. +// +// See https://goo.gl/C4t7Tz for more details. +type PluginUser struct { + UID int32 `json:"UID,omitempty" yaml:"UID,omitempty" toml:"UID,omitempty"` + GID int32 `json:"GID,omitempty" yaml:"GID,omitempty" toml:"GID,omitempty"` +} + +// PluginConfig stores plugin config. +// +// See https://goo.gl/C4t7Tz for more details. +type PluginConfig struct { + Description string `json:"Description,omitempty" yaml:"Description,omitempty" toml:"Description,omitempty"` + Documentation string + Interface PluginInterface `json:"Interface,omitempty" yaml:"Interface,omitempty" toml:"Interface,omitempty"` + Entrypoint []string `json:"Entrypoint,omitempty" yaml:"Entrypoint,omitempty" toml:"Entrypoint,omitempty"` + WorkDir string `json:"WorkDir,omitempty" yaml:"WorkDir,omitempty" toml:"WorkDir,omitempty"` + User PluginUser `json:"User,omitempty" yaml:"User,omitempty" toml:"User,omitempty"` + Network PluginNetwork `json:"Network,omitempty" yaml:"Network,omitempty" toml:"Network,omitempty"` + Linux PluginLinux `json:"Linux,omitempty" yaml:"Linux,omitempty" toml:"Linux,omitempty"` + PropagatedMount string `json:"PropagatedMount,omitempty" yaml:"PropagatedMount,omitempty" toml:"PropagatedMount,omitempty"` + Mounts []Mount `json:"Mounts,omitempty" yaml:"Mounts,omitempty" toml:"Mounts,omitempty"` + Env []PluginEnv `json:"Env,omitempty" yaml:"Env,omitempty" toml:"Env,omitempty"` + Args PluginArgs `json:"Args,omitempty" yaml:"Args,omitempty" toml:"Args,omitempty"` +} + +// PluginDetail specify results from the ListPlugins function. +// +// See https://goo.gl/C4t7Tz for more details. +type PluginDetail struct { + ID string `json:"Id,omitempty" yaml:"Id,omitempty" toml:"Id,omitempty"` + Name string `json:"Name,omitempty" yaml:"Name,omitempty" toml:"Name,omitempty"` + Tag string `json:"Tag,omitempty" yaml:"Tag,omitempty" toml:"Tag,omitempty"` + Active bool `json:"Active,omitempty" yaml:"Active,omitempty" toml:"Active,omitempty"` + Settings PluginSettings `json:"Settings,omitempty" yaml:"Settings,omitempty" toml:"Settings,omitempty"` + Config PluginConfig `json:"Config,omitempty" yaml:"Config,omitempty" toml:"Config,omitempty"` +} + +// ListPlugins returns pluginDetails or an error. +// +// See https://goo.gl/C4t7Tz for more details. +func (c *Client) ListPlugins(ctx context.Context) ([]PluginDetail, error) { + resp, err := c.do("GET", "/plugins", doOptions{ + context: ctx, + }) + if err != nil { + return nil, err + } + defer resp.Body.Close() + pluginDetails := make([]PluginDetail, 0) + if err := json.NewDecoder(resp.Body).Decode(&pluginDetails); err != nil { + return nil, err + } + return pluginDetails, nil +} + +// ListFilteredPluginsOptions specify parameters to the ListFilteredPlugins function. +// +// See https://goo.gl/C4t7Tz for more details. +type ListFilteredPluginsOptions struct { + Filters map[string][]string + Context context.Context +} + +// ListFilteredPlugins returns pluginDetails or an error. +// +// See https://goo.gl/rmdmWg for more details. +func (c *Client) ListFilteredPlugins(opts ListFilteredPluginsOptions) ([]PluginDetail, error) { + path := "/plugins/json?" + queryString(opts) + resp, err := c.do("GET", path, doOptions{ + context: opts.Context, + }) + if err != nil { + return nil, err + } + defer resp.Body.Close() + pluginDetails := make([]PluginDetail, 0) + if err := json.NewDecoder(resp.Body).Decode(&pluginDetails); err != nil { + return nil, err + } + return pluginDetails, nil +} + +// GetPluginPrivileges returns pulginPrivileges or an error. +// +// See https://goo.gl/C4t7Tz for more details. +func (c *Client) GetPluginPrivileges(name string, ctx context.Context) ([]PluginPrivilege, error) { + resp, err := c.do("GET", "/plugins/privileges?remote="+name, doOptions{ + context: ctx, + }) + if err != nil { + return nil, err + } + defer resp.Body.Close() + var pluginPrivileges []PluginPrivilege + if err := json.NewDecoder(resp.Body).Decode(&pluginPrivileges); err != nil { + return nil, err + } + return pluginPrivileges, nil +} + +// InspectPlugins returns a pluginDetail or an error. +// +// See https://goo.gl/C4t7Tz for more details. +func (c *Client) InspectPlugins(name string, ctx context.Context) (*PluginDetail, error) { + resp, err := c.do("GET", "/plugins/"+name+"/json", doOptions{ + context: ctx, + }) + if err != nil { + return nil, err + } + defer resp.Body.Close() + if err != nil { + if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { + return nil, &NoSuchPlugin{ID: name} + } + return nil, err + } + resp.Body.Close() + var pluginDetail PluginDetail + if err := json.NewDecoder(resp.Body).Decode(&pluginDetail); err != nil { + return nil, err + } + return &pluginDetail, nil +} + +// RemovePluginOptions specify parameters to the RemovePlugin function. +// +// See https://goo.gl/C4t7Tz for more details. +type RemovePluginOptions struct { + // The Name of the plugin. + Name string `qs:"-"` + + Force bool `qs:"force"` + Context context.Context +} + +// RemovePlugin returns a PluginDetail or an error. +// +// See https://goo.gl/C4t7Tz for more details. +func (c *Client) RemovePlugin(opts RemovePluginOptions) (*PluginDetail, error) { + path := "/plugins/" + opts.Name + "?" + queryString(opts) + resp, err := c.do("DELETE", path, doOptions{context: opts.Context}) + if err != nil { + return nil, err + } + defer resp.Body.Close() + if err != nil { + if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { + return nil, &NoSuchPlugin{ID: opts.Name} + } + return nil, err + } + resp.Body.Close() + var pluginDetail PluginDetail + if err := json.NewDecoder(resp.Body).Decode(&pluginDetail); err != nil { + return nil, err + } + return &pluginDetail, nil +} + +// EnablePluginOptions specify parameters to the EnablePlugin function. +// +// See https://goo.gl/C4t7Tz for more details. +type EnablePluginOptions struct { + // The Name of the plugin. + Name string `qs:"-"` + Timeout int64 `qs:"timeout"` + + Context context.Context +} + +// EnablePlugin enables plugin that opts point or returns an error. +// +// See https://goo.gl/C4t7Tz for more details. +func (c *Client) EnablePlugin(opts EnablePluginOptions) error { + path := "/plugins/" + opts.Name + "/enable?" + queryString(opts) + resp, err := c.do("POST", path, doOptions{context: opts.Context}) + defer resp.Body.Close() + if err != nil { + return err + } + resp.Body.Close() + return nil +} + +// DisablePluginOptions specify parameters to the DisablePlugin function. +// +// See https://goo.gl/C4t7Tz for more details. +type DisablePluginOptions struct { + // The Name of the plugin. + Name string `qs:"-"` + + Context context.Context +} + +// DisablePlugin disables plugin that opts point or returns an error. +// +// See https://goo.gl/C4t7Tz for more details. +func (c *Client) DisablePlugin(opts DisablePluginOptions) error { + path := "/plugins/" + opts.Name + "/disable" + resp, err := c.do("POST", path, doOptions{context: opts.Context}) + defer resp.Body.Close() + if err != nil { + return err + } + resp.Body.Close() + return nil +} + +// CreatePluginOptions specify parameters to the CreatePlugin function. +// +// See https://goo.gl/C4t7Tz for more details. +type CreatePluginOptions struct { + // The Name of the plugin. + Name string `qs:"name"` + // Path to tar containing plugin + Path string `qs:"-"` + + Context context.Context +} + +// CreatePlugin creates plugin that opts point or returns an error. +// +// See https://goo.gl/C4t7Tz for more details. +func (c *Client) CreatePlugin(opts CreatePluginOptions) (string, error) { + path := "/plugins/create?" + queryString(opts) + resp, err := c.do("POST", path, doOptions{ + data: opts.Path, + context: opts.Context}) + defer resp.Body.Close() + if err != nil { + return "", err + } + containerNameBytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + return "", err + } + return string(containerNameBytes), nil +} + +// PushPluginOptions specify parameters to PushPlugin function. +// +// See https://goo.gl/C4t7Tz for more details. +type PushPluginOptions struct { + // The Name of the plugin. + Name string + + Context context.Context +} + +// PushPlugin pushes plugin that opts point or returns an error. +// +// See https://goo.gl/C4t7Tz for more details. +func (c *Client) PushPlugin(opts PushPluginOptions) error { + path := "/plugins/" + opts.Name + "/push" + resp, err := c.do("POST", path, doOptions{context: opts.Context}) + defer resp.Body.Close() + if err != nil { + return err + } + return nil +} + +// ConfigurePluginOptions specify parameters to the ConfigurePlugin +// +// See https://goo.gl/C4t7Tz for more details. +type ConfigurePluginOptions struct { + // The Name of the plugin. + Name string `qs:"name"` + Envs []string + + Context context.Context +} + +// ConfigurePlugin configures plugin that opts point or returns an error. +// +// See https://goo.gl/C4t7Tz for more details. +func (c *Client) ConfigurePlugin(opts ConfigurePluginOptions) error { + path := "/plugins/" + opts.Name + "/set" + resp, err := c.do("POST", path, doOptions{ + data: opts.Envs, + context: opts.Context, + }) + defer resp.Body.Close() + if err != nil { + if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { + return &NoSuchPlugin{ID: opts.Name} + } + return err + } + return nil +} + +// NoSuchPlugin is the error returned when a given plugin does not exist. +type NoSuchPlugin struct { + ID string + Err error +} + +func (err *NoSuchPlugin) Error() string { + if err.Err != nil { + return err.Err.Error() + } + return "No such plugin: " + err.ID +} diff --git a/vendor/github.com/fsouza/go-dockerclient/swarm.go b/vendor/github.com/fsouza/go-dockerclient/swarm.go index 6d9086a552..a257758fc2 100644 --- a/vendor/github.com/fsouza/go-dockerclient/swarm.go +++ b/vendor/github.com/fsouza/go-dockerclient/swarm.go @@ -5,6 +5,7 @@ package docker import ( + "context" "encoding/json" "errors" "net/http" @@ -12,7 +13,6 @@ import ( "strconv" "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" ) var ( diff --git a/vendor/github.com/fsouza/go-dockerclient/swarm_configs.go b/vendor/github.com/fsouza/go-dockerclient/swarm_configs.go new file mode 100644 index 0000000000..fb73ab2efb --- /dev/null +++ b/vendor/github.com/fsouza/go-dockerclient/swarm_configs.go @@ -0,0 +1,171 @@ +// Copyright 2017 go-dockerclient authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package docker + +import ( + "context" + "encoding/json" + "net/http" + "net/url" + "strconv" + + "github.com/docker/docker/api/types/swarm" +) + +// NoSuchConfig is the error returned when a given config does not exist. +type NoSuchConfig struct { + ID string + Err error +} + +func (err *NoSuchConfig) Error() string { + if err.Err != nil { + return err.Err.Error() + } + return "No such config: " + err.ID +} + +// CreateConfigOptions specify parameters to the CreateConfig function. +// +// See https://goo.gl/KrVjHz for more details. +type CreateConfigOptions struct { + Auth AuthConfiguration `qs:"-"` + swarm.ConfigSpec + Context context.Context +} + +// CreateConfig creates a new config, returning the config instance +// or an error in case of failure. +// +// See https://goo.gl/KrVjHz for more details. +func (c *Client) CreateConfig(opts CreateConfigOptions) (*swarm.Config, error) { + headers, err := headersWithAuth(opts.Auth) + if err != nil { + return nil, err + } + path := "/configs/create?" + queryString(opts) + resp, err := c.do("POST", path, doOptions{ + headers: headers, + data: opts.ConfigSpec, + forceJSON: true, + context: opts.Context, + }) + if err != nil { + return nil, err + } + defer resp.Body.Close() + var config swarm.Config + if err := json.NewDecoder(resp.Body).Decode(&config); err != nil { + return nil, err + } + return &config, nil +} + +// RemoveConfigOptions encapsulates options to remove a config. +// +// See https://goo.gl/Tqrtya for more details. +type RemoveConfigOptions struct { + ID string `qs:"-"` + Context context.Context +} + +// RemoveConfig removes a config, returning an error in case of failure. +// +// See https://goo.gl/Tqrtya for more details. +func (c *Client) RemoveConfig(opts RemoveConfigOptions) error { + path := "/configs/" + opts.ID + resp, err := c.do("DELETE", path, doOptions{context: opts.Context}) + if err != nil { + if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { + return &NoSuchConfig{ID: opts.ID} + } + return err + } + resp.Body.Close() + return nil +} + +// UpdateConfigOptions specify parameters to the UpdateConfig function. +// +// See https://goo.gl/wu3MmS for more details. +type UpdateConfigOptions struct { + Auth AuthConfiguration `qs:"-"` + swarm.ConfigSpec + Context context.Context + Version uint64 +} + +// UpdateConfig updates the config at ID with the options +// +// Only label can be updated +// https://docs.docker.com/engine/api/v1.33/#operation/ConfigUpdate +// See https://goo.gl/wu3MmS for more details. +func (c *Client) UpdateConfig(id string, opts UpdateConfigOptions) error { + headers, err := headersWithAuth(opts.Auth) + if err != nil { + return err + } + params := make(url.Values) + params.Set("version", strconv.FormatUint(opts.Version, 10)) + resp, err := c.do("POST", "/configs/"+id+"/update?"+params.Encode(), doOptions{ + headers: headers, + data: opts.ConfigSpec, + forceJSON: true, + context: opts.Context, + }) + if err != nil { + if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { + return &NoSuchConfig{ID: id} + } + return err + } + defer resp.Body.Close() + return nil +} + +// InspectConfig returns information about a config by its ID. +// +// See https://goo.gl/dHmr75 for more details. +func (c *Client) InspectConfig(id string) (*swarm.Config, error) { + path := "/configs/" + id + resp, err := c.do("GET", path, doOptions{}) + if err != nil { + if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { + return nil, &NoSuchConfig{ID: id} + } + return nil, err + } + defer resp.Body.Close() + var config swarm.Config + if err := json.NewDecoder(resp.Body).Decode(&config); err != nil { + return nil, err + } + return &config, nil +} + +// ListConfigsOptions specify parameters to the ListConfigs function. +// +// See https://goo.gl/DwvNMd for more details. +type ListConfigsOptions struct { + Filters map[string][]string + Context context.Context +} + +// ListConfigs returns a slice of configs matching the given criteria. +// +// See https://goo.gl/DwvNMd for more details. +func (c *Client) ListConfigs(opts ListConfigsOptions) ([]swarm.Config, error) { + path := "/configs?" + queryString(opts) + resp, err := c.do("GET", path, doOptions{context: opts.Context}) + if err != nil { + return nil, err + } + defer resp.Body.Close() + var configs []swarm.Config + if err := json.NewDecoder(resp.Body).Decode(&configs); err != nil { + return nil, err + } + return configs, nil +} diff --git a/vendor/github.com/fsouza/go-dockerclient/node.go b/vendor/github.com/fsouza/go-dockerclient/swarm_node.go similarity index 99% rename from vendor/github.com/fsouza/go-dockerclient/node.go rename to vendor/github.com/fsouza/go-dockerclient/swarm_node.go index 8434025413..095653cd94 100644 --- a/vendor/github.com/fsouza/go-dockerclient/node.go +++ b/vendor/github.com/fsouza/go-dockerclient/swarm_node.go @@ -5,13 +5,13 @@ package docker import ( + "context" "encoding/json" "net/http" "net/url" "strconv" "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" ) // NoSuchNode is the error returned when a given node does not exist. diff --git a/vendor/github.com/fsouza/go-dockerclient/swarm_secrets.go b/vendor/github.com/fsouza/go-dockerclient/swarm_secrets.go new file mode 100644 index 0000000000..5a3b82ca5d --- /dev/null +++ b/vendor/github.com/fsouza/go-dockerclient/swarm_secrets.go @@ -0,0 +1,171 @@ +// Copyright 2016 go-dockerclient authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package docker + +import ( + "context" + "encoding/json" + "net/http" + "net/url" + "strconv" + + "github.com/docker/docker/api/types/swarm" +) + +// NoSuchSecret is the error returned when a given secret does not exist. +type NoSuchSecret struct { + ID string + Err error +} + +func (err *NoSuchSecret) Error() string { + if err.Err != nil { + return err.Err.Error() + } + return "No such secret: " + err.ID +} + +// CreateSecretOptions specify parameters to the CreateSecret function. +// +// See https://goo.gl/KrVjHz for more details. +type CreateSecretOptions struct { + Auth AuthConfiguration `qs:"-"` + swarm.SecretSpec + Context context.Context +} + +// CreateSecret creates a new secret, returning the secret instance +// or an error in case of failure. +// +// See https://goo.gl/KrVjHz for more details. +func (c *Client) CreateSecret(opts CreateSecretOptions) (*swarm.Secret, error) { + headers, err := headersWithAuth(opts.Auth) + if err != nil { + return nil, err + } + path := "/secrets/create?" + queryString(opts) + resp, err := c.do("POST", path, doOptions{ + headers: headers, + data: opts.SecretSpec, + forceJSON: true, + context: opts.Context, + }) + if err != nil { + return nil, err + } + defer resp.Body.Close() + var secret swarm.Secret + if err := json.NewDecoder(resp.Body).Decode(&secret); err != nil { + return nil, err + } + return &secret, nil +} + +// RemoveSecretOptions encapsulates options to remove a secret. +// +// See https://goo.gl/Tqrtya for more details. +type RemoveSecretOptions struct { + ID string `qs:"-"` + Context context.Context +} + +// RemoveSecret removes a secret, returning an error in case of failure. +// +// See https://goo.gl/Tqrtya for more details. +func (c *Client) RemoveSecret(opts RemoveSecretOptions) error { + path := "/secrets/" + opts.ID + resp, err := c.do("DELETE", path, doOptions{context: opts.Context}) + if err != nil { + if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { + return &NoSuchSecret{ID: opts.ID} + } + return err + } + resp.Body.Close() + return nil +} + +// UpdateSecretOptions specify parameters to the UpdateSecret function. +// +// Only label can be updated +// See https://docs.docker.com/engine/api/v1.33/#operation/SecretUpdate +// See https://goo.gl/wu3MmS for more details. +type UpdateSecretOptions struct { + Auth AuthConfiguration `qs:"-"` + swarm.SecretSpec + Context context.Context + Version uint64 +} + +// UpdateSecret updates the secret at ID with the options +// +// See https://goo.gl/wu3MmS for more details. +func (c *Client) UpdateSecret(id string, opts UpdateSecretOptions) error { + headers, err := headersWithAuth(opts.Auth) + if err != nil { + return err + } + params := make(url.Values) + params.Set("version", strconv.FormatUint(opts.Version, 10)) + resp, err := c.do("POST", "/secrets/"+id+"/update?"+params.Encode(), doOptions{ + headers: headers, + data: opts.SecretSpec, + forceJSON: true, + context: opts.Context, + }) + if err != nil { + if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { + return &NoSuchSecret{ID: id} + } + return err + } + defer resp.Body.Close() + return nil +} + +// InspectSecret returns information about a secret by its ID. +// +// See https://goo.gl/dHmr75 for more details. +func (c *Client) InspectSecret(id string) (*swarm.Secret, error) { + path := "/secrets/" + id + resp, err := c.do("GET", path, doOptions{}) + if err != nil { + if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { + return nil, &NoSuchSecret{ID: id} + } + return nil, err + } + defer resp.Body.Close() + var secret swarm.Secret + if err := json.NewDecoder(resp.Body).Decode(&secret); err != nil { + return nil, err + } + return &secret, nil +} + +// ListSecretsOptions specify parameters to the ListSecrets function. +// +// See https://goo.gl/DwvNMd for more details. +type ListSecretsOptions struct { + Filters map[string][]string + Context context.Context +} + +// ListSecrets returns a slice of secrets matching the given criteria. +// +// See https://goo.gl/DwvNMd for more details. +func (c *Client) ListSecrets(opts ListSecretsOptions) ([]swarm.Secret, error) { + path := "/secrets?" + queryString(opts) + resp, err := c.do("GET", path, doOptions{context: opts.Context}) + if err != nil { + return nil, err + } + defer resp.Body.Close() + var secrets []swarm.Secret + if err := json.NewDecoder(resp.Body).Decode(&secrets); err != nil { + return nil, err + } + return secrets, nil +} diff --git a/vendor/github.com/fsouza/go-dockerclient/service.go b/vendor/github.com/fsouza/go-dockerclient/swarm_service.go similarity index 70% rename from vendor/github.com/fsouza/go-dockerclient/service.go rename to vendor/github.com/fsouza/go-dockerclient/swarm_service.go index fa6c96d837..ca7e237253 100644 --- a/vendor/github.com/fsouza/go-dockerclient/service.go +++ b/vendor/github.com/fsouza/go-dockerclient/swarm_service.go @@ -5,13 +5,13 @@ package docker import ( + "context" "encoding/json" + "io" "net/http" - "net/url" - "strconv" + "time" "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" ) // NoSuchService is the error returned when a given service does not exist. @@ -91,10 +91,11 @@ func (c *Client) RemoveService(opts RemoveServiceOptions) error { // // See https://goo.gl/wu3MmS for more details. type UpdateServiceOptions struct { - Auth AuthConfiguration `qs:"-"` - swarm.ServiceSpec - Context context.Context - Version uint64 + Auth AuthConfiguration `qs:"-"` + swarm.ServiceSpec `qs:"-"` + Context context.Context + Version uint64 + Rollback string } // UpdateService updates the service at ID with the options @@ -105,9 +106,7 @@ func (c *Client) UpdateService(id string, opts UpdateServiceOptions) error { if err != nil { return err } - params := make(url.Values) - params.Set("version", strconv.FormatUint(opts.Version, 10)) - resp, err := c.do("POST", "/services/"+id+"/update?"+params.Encode(), doOptions{ + resp, err := c.do("POST", "/services/"+id+"/update?"+queryString(opts), doOptions{ headers: headers, data: opts.ServiceSpec, forceJSON: true, @@ -167,3 +166,48 @@ func (c *Client) ListServices(opts ListServicesOptions) ([]swarm.Service, error) } return services, nil } + +// LogsServiceOptions represents the set of options used when getting logs from a +// service. +type LogsServiceOptions struct { + Context context.Context + Service string `qs:"-"` + OutputStream io.Writer `qs:"-"` + ErrorStream io.Writer `qs:"-"` + InactivityTimeout time.Duration `qs:"-"` + Tail string + + // Use raw terminal? Usually true when the container contains a TTY. + RawTerminal bool `qs:"-"` + Since int64 + Follow bool + Stdout bool + Stderr bool + Timestamps bool + Details bool +} + +// GetServiceLogs gets stdout and stderr logs from the specified service. +// +// When LogsServiceOptions.RawTerminal is set to false, go-dockerclient will multiplex +// the streams and send the containers stdout to LogsServiceOptions.OutputStream, and +// stderr to LogsServiceOptions.ErrorStream. +// +// When LogsServiceOptions.RawTerminal is true, callers will get the raw stream on +// LogsServiceOptions.OutputStream. +func (c *Client) GetServiceLogs(opts LogsServiceOptions) error { + if opts.Service == "" { + return &NoSuchService{ID: opts.Service} + } + if opts.Tail == "" { + opts.Tail = "all" + } + path := "/services/" + opts.Service + "/logs?" + queryString(opts) + return c.stream("GET", path, streamOptions{ + setRawTerminal: opts.RawTerminal, + stdout: opts.OutputStream, + stderr: opts.ErrorStream, + inactivityTimeout: opts.InactivityTimeout, + context: opts.Context, + }) +} diff --git a/vendor/github.com/fsouza/go-dockerclient/task.go b/vendor/github.com/fsouza/go-dockerclient/swarm_task.go similarity index 98% rename from vendor/github.com/fsouza/go-dockerclient/task.go rename to vendor/github.com/fsouza/go-dockerclient/swarm_task.go index b1dad4b231..3b1161ab98 100644 --- a/vendor/github.com/fsouza/go-dockerclient/task.go +++ b/vendor/github.com/fsouza/go-dockerclient/swarm_task.go @@ -5,11 +5,11 @@ package docker import ( + "context" "encoding/json" "net/http" "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" ) // NoSuchTask is the error returned when a given task does not exist. diff --git a/vendor/github.com/fsouza/go-dockerclient/tar.go b/vendor/github.com/fsouza/go-dockerclient/tar.go index be4dfa573e..611da8c9e0 100644 --- a/vendor/github.com/fsouza/go-dockerclient/tar.go +++ b/vendor/github.com/fsouza/go-dockerclient/tar.go @@ -13,11 +13,16 @@ import ( "path/filepath" "strings" - "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/fileutils" + "github.com/fsouza/go-dockerclient/internal/archive" ) func createTarStream(srcPath, dockerfilePath string) (io.ReadCloser, error) { + srcPath, err := filepath.Abs(srcPath) + if err != nil { + return nil, err + } + excludes, err := parseDockerignore(srcPath) if err != nil { return nil, err diff --git a/vendor/github.com/fsouza/go-dockerclient/volume.go b/vendor/github.com/fsouza/go-dockerclient/volume.go index 3c7bdeaa74..021a262b79 100644 --- a/vendor/github.com/fsouza/go-dockerclient/volume.go +++ b/vendor/github.com/fsouza/go-dockerclient/volume.go @@ -5,11 +5,10 @@ package docker import ( + "context" "encoding/json" "errors" "net/http" - - "golang.org/x/net/context" ) var ( @@ -22,17 +21,18 @@ var ( // Volume represents a volume. // -// See https://goo.gl/FZA4BK for more details. +// See https://goo.gl/3wgTsd for more details. type Volume struct { Name string `json:"Name" yaml:"Name" toml:"Name"` Driver string `json:"Driver,omitempty" yaml:"Driver,omitempty" toml:"Driver,omitempty"` Mountpoint string `json:"Mountpoint,omitempty" yaml:"Mountpoint,omitempty" toml:"Mountpoint,omitempty"` Labels map[string]string `json:"Labels,omitempty" yaml:"Labels,omitempty" toml:"Labels,omitempty"` + Options map[string]string `json:"Options,omitempty" yaml:"Options,omitempty" toml:"Options,omitempty"` } // ListVolumesOptions specify parameters to the ListVolumes function. // -// See https://goo.gl/FZA4BK for more details. +// See https://goo.gl/3wgTsd for more details. type ListVolumesOptions struct { Filters map[string][]string Context context.Context @@ -40,7 +40,7 @@ type ListVolumesOptions struct { // ListVolumes returns a list of available volumes in the server. // -// See https://goo.gl/FZA4BK for more details. +// See https://goo.gl/3wgTsd for more details. func (c *Client) ListVolumes(opts ListVolumesOptions) ([]Volume, error) { resp, err := c.do("GET", "/volumes?"+queryString(opts), doOptions{ context: opts.Context, @@ -70,7 +70,7 @@ func (c *Client) ListVolumes(opts ListVolumesOptions) ([]Volume, error) { // CreateVolumeOptions specify parameters to the CreateVolume function. // -// See https://goo.gl/pBUbZ9 for more details. +// See https://goo.gl/qEhmEC for more details. type CreateVolumeOptions struct { Name string Driver string @@ -81,7 +81,7 @@ type CreateVolumeOptions struct { // CreateVolume creates a volume on the server. // -// See https://goo.gl/pBUbZ9 for more details. +// See https://goo.gl/qEhmEC for more details. func (c *Client) CreateVolume(opts CreateVolumeOptions) (*Volume, error) { resp, err := c.do("POST", "/volumes/create", doOptions{ data: opts, @@ -100,7 +100,7 @@ func (c *Client) CreateVolume(opts CreateVolumeOptions) (*Volume, error) { // InspectVolume returns a volume by its name. // -// See https://goo.gl/0g9A6i for more details. +// See https://goo.gl/GMjsMc for more details. func (c *Client) InspectVolume(name string) (*Volume, error) { resp, err := c.do("GET", "/volumes/"+name, doOptions{}) if err != nil { @@ -119,9 +119,28 @@ func (c *Client) InspectVolume(name string) (*Volume, error) { // RemoveVolume removes a volume by its name. // -// See https://goo.gl/79GNQz for more details. +// Deprecated: Use RemoveVolumeWithOptions instead. func (c *Client) RemoveVolume(name string) error { - resp, err := c.do("DELETE", "/volumes/"+name, doOptions{}) + return c.RemoveVolumeWithOptions(RemoveVolumeOptions{Name: name}) +} + +// RemoveVolumeOptions specify parameters to the RemoveVolumeWithOptions +// function. +// +// See https://goo.gl/nvd6qj for more details. +type RemoveVolumeOptions struct { + Context context.Context + Name string `qs:"-"` + Force bool +} + +// RemoveVolumeWithOptions removes a volume by its name and takes extra +// parameters. +// +// See https://goo.gl/nvd6qj for more details. +func (c *Client) RemoveVolumeWithOptions(opts RemoveVolumeOptions) error { + path := "/volumes/" + opts.Name + resp, err := c.do("DELETE", path+"?"+queryString(opts), doOptions{context: opts.Context}) if err != nil { if e, ok := err.(*Error); ok { if e.Status == http.StatusNotFound { @@ -131,7 +150,7 @@ func (c *Client) RemoveVolume(name string) error { return ErrVolumeInUse } } - return nil + return err } defer resp.Body.Close() return nil @@ -139,7 +158,7 @@ func (c *Client) RemoveVolume(name string) error { // PruneVolumesOptions specify parameters to the PruneVolumes function. // -// See https://goo.gl/pFN1Hj for more details. +// See https://goo.gl/f9XDem for more details. type PruneVolumesOptions struct { Filters map[string][]string Context context.Context @@ -147,7 +166,7 @@ type PruneVolumesOptions struct { // PruneVolumesResults specify results from the PruneVolumes function. // -// See https://goo.gl/pFN1Hj for more details. +// See https://goo.gl/f9XDem for more details. type PruneVolumesResults struct { VolumesDeleted []string SpaceReclaimed int64 @@ -155,7 +174,7 @@ type PruneVolumesResults struct { // PruneVolumes deletes volumes which are unused. // -// See https://goo.gl/pFN1Hj for more details. +// See https://goo.gl/f9XDem for more details. func (c *Client) PruneVolumes(opts PruneVolumesOptions) (*PruneVolumesResults, error) { path := "/volumes/prune?" + queryString(opts) resp, err := c.do("POST", path, doOptions{context: opts.Context}) diff --git a/vendor/github.com/go-redis/redis/.travis.yml b/vendor/github.com/go-redis/redis/.travis.yml index c95b3e6c6c..39ffc2becb 100644 --- a/vendor/github.com/go-redis/redis/.travis.yml +++ b/vendor/github.com/go-redis/redis/.travis.yml @@ -8,6 +8,7 @@ go: - 1.7.x - 1.8.x - 1.9.x + - 1.10.x - tip matrix: diff --git a/vendor/github.com/go-redis/redis/CHANGELOG.md b/vendor/github.com/go-redis/redis/CHANGELOG.md new file mode 100644 index 0000000000..cb0e1b8e97 --- /dev/null +++ b/vendor/github.com/go-redis/redis/CHANGELOG.md @@ -0,0 +1,12 @@ +# Changelog + +## v6.13 + +- Ring got new options called `HashReplicas` and `Hash`. It is recommended to set `HashReplicas = 1000` for better keys distribution between shards. +- Cluster client was optimized to use much less memory when reloading cluster state. +- PubSub.ReceiveMessage is re-worked to not use ReceiveTimeout so it does not lose data when timeout occurres. In most cases it is recommended to use PubSub.Channel instead. +- Dialer.KeepAlive is set to 5 minutes by default. + +## v6.12 + +- ClusterClient got new option called `ClusterSlots` which allows to build cluster of normal Redis Servers that don't have cluster mode enabled. See https://godoc.org/github.com/go-redis/redis#example-NewClusterClient--ManualSetup diff --git a/vendor/github.com/go-redis/redis/Makefile b/vendor/github.com/go-redis/redis/Makefile index 50fdc55a1a..1fbdac91c5 100644 --- a/vendor/github.com/go-redis/redis/Makefile +++ b/vendor/github.com/go-redis/redis/Makefile @@ -1,6 +1,7 @@ all: testdeps go test ./... go test ./... -short -race + env GOOS=linux GOARCH=386 go test ./... go vet testdeps: testdata/redis/src/redis-server @@ -15,5 +16,5 @@ testdata/redis: wget -qO- https://github.com/antirez/redis/archive/unstable.tar.gz | tar xvz --strip-components=1 -C $@ testdata/redis/src/redis-server: testdata/redis - sed -i 's/libjemalloc.a/libjemalloc.a -lrt/g' $ 0 { + addrs = c.clusterAddrs + } else { + addrs = c.allAddrs + } + } c.mu.RUnlock() if closed { @@ -221,63 +287,56 @@ func (c *clusterNodes) Addrs() ([]string, error) { } func (c *clusterNodes) NextGeneration() uint32 { - c.generation++ - return c.generation + return atomic.AddUint32(&c._generation, 1) } // GC removes unused nodes. func (c *clusterNodes) GC(generation uint32) { var collected []*clusterNode c.mu.Lock() - for i := 0; i < len(c.addrs); { - addr := c.addrs[i] - node := c.nodes[addr] + for addr, node := range c.allNodes { if node.Generation() >= generation { - i++ continue } - c.addrs = append(c.addrs[:i], c.addrs[i+1:]...) - delete(c.nodes, addr) + c.clusterAddrs = remove(c.clusterAddrs, addr) + delete(c.allNodes, addr) collected = append(collected, node) } c.mu.Unlock() - time.AfterFunc(time.Minute, func() { - for _, node := range collected { - _ = node.Client.Close() - } - }) + for _, node := range collected { + _ = node.Client.Close() + } } -func (c *clusterNodes) All() ([]*clusterNode, error) { +func (c *clusterNodes) Get(addr string) (*clusterNode, error) { + var node *clusterNode + var err error c.mu.RLock() - defer c.mu.RUnlock() - if c.closed { - return nil, pool.ErrClosed - } - - nodes := make([]*clusterNode, 0, len(c.nodes)) - for _, node := range c.nodes { - nodes = append(nodes, node) + err = pool.ErrClosed + } else { + node = c.allNodes[addr] } - return nodes, nil + c.mu.RUnlock() + return node, err } func (c *clusterNodes) GetOrCreate(addr string) (*clusterNode, error) { - var node *clusterNode - var ok bool - - c.mu.RLock() - if !c.closed { - node, ok = c.nodes[addr] + node, err := c.Get(addr) + if err != nil { + return nil, err } - c.mu.RUnlock() - if ok { + if node != nil { return node, nil } + v, err := c.nodeCreateGroup.Do(addr, func() (interface{}, error) { + node := newClusterNode(c.opt, addr) + return node, nil + }) + c.mu.Lock() defer c.mu.Unlock() @@ -285,15 +344,35 @@ func (c *clusterNodes) GetOrCreate(addr string) (*clusterNode, error) { return nil, pool.ErrClosed } - node, ok = c.nodes[addr] + node, ok := c.allNodes[addr] if ok { - return node, nil + _ = v.(*clusterNode).Close() + return node, err } + node = v.(*clusterNode) - c.addrs = append(c.addrs, addr) - node = newClusterNode(c.opt, addr) - c.nodes[addr] = node - return node, nil + c.allAddrs = appendIfNotExists(c.allAddrs, addr) + if err == nil { + c.clusterAddrs = append(c.clusterAddrs, addr) + } + c.allNodes[addr] = node + + return node, err +} + +func (c *clusterNodes) All() ([]*clusterNode, error) { + c.mu.RLock() + defer c.mu.RUnlock() + + if c.closed { + return nil, pool.ErrClosed + } + + cp := make([]*clusterNode, 0, len(c.allNodes)) + for _, node := range c.allNodes { + cp = append(cp, node) + } + return cp, nil } func (c *clusterNodes) Random() (*clusterNode, error) { @@ -302,40 +381,52 @@ func (c *clusterNodes) Random() (*clusterNode, error) { return nil, err } - var nodeErr error - for i := 0; i <= c.opt.MaxRedirects; i++ { - n := rand.Intn(len(addrs)) - node, err := c.GetOrCreate(addrs[n]) - if err != nil { - return nil, err - } - - nodeErr = node.Client.ClusterInfo().Err() - if nodeErr == nil { - return node, nil - } - } - return nil, nodeErr + n := rand.Intn(len(addrs)) + return c.GetOrCreate(addrs[n]) } //------------------------------------------------------------------------------ +type clusterSlot struct { + start, end int + nodes []*clusterNode +} + +type clusterSlotSlice []*clusterSlot + +func (p clusterSlotSlice) Len() int { + return len(p) +} + +func (p clusterSlotSlice) Less(i, j int) bool { + return p[i].start < p[j].start +} + +func (p clusterSlotSlice) Swap(i, j int) { + p[i], p[j] = p[j], p[i] +} + type clusterState struct { nodes *clusterNodes - masters []*clusterNode - slaves []*clusterNode + Masters []*clusterNode + Slaves []*clusterNode - slots [][]*clusterNode + slots []*clusterSlot generation uint32 + createdAt time.Time } -func newClusterState(nodes *clusterNodes, slots []ClusterSlot, origin string) (*clusterState, error) { +func newClusterState( + nodes *clusterNodes, slots []ClusterSlot, origin string, +) (*clusterState, error) { c := clusterState{ - nodes: nodes, - generation: nodes.NextGeneration(), + nodes: nodes, + + slots: make([]*clusterSlot, 0, len(slots)), - slots: make([][]*clusterNode, hashtag.SlotNumber), + generation: nodes.NextGeneration(), + createdAt: time.Now(), } isLoopbackOrigin := isLoopbackAddr(origin) @@ -343,7 +434,7 @@ func newClusterState(nodes *clusterNodes, slots []ClusterSlot, origin string) (* var nodes []*clusterNode for i, slotNode := range slot.Nodes { addr := slotNode.Addr - if !isLoopbackOrigin && isLoopbackAddr(addr) { + if !isLoopbackOrigin && useOriginAddr(origin, addr) { addr = origin } @@ -356,17 +447,25 @@ func newClusterState(nodes *clusterNodes, slots []ClusterSlot, origin string) (* nodes = append(nodes, node) if i == 0 { - c.masters = appendNode(c.masters, node) + c.Masters = appendUniqueNode(c.Masters, node) } else { - c.slaves = appendNode(c.slaves, node) + c.Slaves = appendUniqueNode(c.Slaves, node) } } - for i := slot.Start; i <= slot.End; i++ { - c.slots[i] = nodes - } + c.slots = append(c.slots, &clusterSlot{ + start: slot.Start, + end: slot.End, + nodes: nodes, + }) } + sort.Sort(clusterSlotSlice(c.slots)) + + time.AfterFunc(time.Minute, func() { + nodes.GC(c.generation) + }) + return &c, nil } @@ -416,20 +515,132 @@ func (c *clusterState) slotClosestNode(slot int) (*clusterNode, error) { if n.Loading() { continue } - if node == nil || node.Latency-n.Latency > threshold { + if node == nil || node.Latency()-n.Latency() > threshold { node = n } } return node, nil } +func (c *clusterState) slotRandomNode(slot int) *clusterNode { + nodes := c.slotNodes(slot) + n := rand.Intn(len(nodes)) + return nodes[n] +} + func (c *clusterState) slotNodes(slot int) []*clusterNode { - if slot >= 0 && slot < len(c.slots) { - return c.slots[slot] + i := sort.Search(len(c.slots), func(i int) bool { + return c.slots[i].end >= slot + }) + if i >= len(c.slots) { + return nil + } + x := c.slots[i] + if slot >= x.start && slot <= x.end { + return x.nodes } return nil } +func (c *clusterState) IsConsistent() bool { + if c.nodes.opt.ClusterSlots != nil { + return true + } + return len(c.Masters) <= len(c.Slaves) +} + +//------------------------------------------------------------------------------ + +type clusterStateHolder struct { + load func() (*clusterState, error) + + state atomic.Value + + firstErrMu sync.RWMutex + firstErr error + + reloading uint32 // atomic +} + +func newClusterStateHolder(fn func() (*clusterState, error)) *clusterStateHolder { + return &clusterStateHolder{ + load: fn, + } +} + +func (c *clusterStateHolder) Reload() (*clusterState, error) { + state, err := c.reload() + if err != nil { + return nil, err + } + if !state.IsConsistent() { + time.AfterFunc(time.Second, c.LazyReload) + } + return state, nil +} + +func (c *clusterStateHolder) reload() (*clusterState, error) { + state, err := c.load() + if err != nil { + c.firstErrMu.Lock() + if c.firstErr == nil { + c.firstErr = err + } + c.firstErrMu.Unlock() + return nil, err + } + c.state.Store(state) + return state, nil +} + +func (c *clusterStateHolder) LazyReload() { + if !atomic.CompareAndSwapUint32(&c.reloading, 0, 1) { + return + } + go func() { + defer atomic.StoreUint32(&c.reloading, 0) + + for { + state, err := c.reload() + if err != nil { + return + } + time.Sleep(100 * time.Millisecond) + if state.IsConsistent() { + return + } + } + }() +} + +func (c *clusterStateHolder) Get() (*clusterState, error) { + v := c.state.Load() + if v != nil { + state := v.(*clusterState) + if time.Since(state.createdAt) > time.Minute { + c.LazyReload() + } + return state, nil + } + + c.firstErrMu.RLock() + err := c.firstErr + c.firstErrMu.RUnlock() + if err != nil { + return nil, err + } + + return nil, errors.New("redis: cluster has no state") +} + +func (c *clusterStateHolder) ReloadOrGet() (*clusterState, error) { + state, err := c.Reload() + if err == nil { + return state, nil + } + return c.Get() +} + //------------------------------------------------------------------------------ // ClusterClient is a Redis Cluster client representing a pool of zero @@ -438,15 +649,16 @@ func (c *clusterState) slotNodes(slot int) []*clusterNode { type ClusterClient struct { cmdable - opt *ClusterOptions - nodes *clusterNodes - _state atomic.Value + ctx context.Context - cmdsInfoOnce internal.Once - cmdsInfo map[string]*CommandInfo + opt *ClusterOptions + nodes *clusterNodes + state *clusterStateHolder + cmdsInfoCache *cmdsInfoCache - // Reports whether slots reloading is in progress. - reloading uint32 + process func(Cmder) error + processPipeline func([]Cmder) error + processTxPipeline func([]Cmder) error } // NewClusterClient returns a Redis Cluster client as described in @@ -458,21 +670,17 @@ func NewClusterClient(opt *ClusterOptions) *ClusterClient { opt: opt, nodes: newClusterNodes(opt), } - c.setProcessor(c.Process) + c.state = newClusterStateHolder(c.loadState) + c.cmdsInfoCache = newCmdsInfoCache(c.cmdsInfo) - // Add initial nodes. - for _, addr := range opt.Addrs { - _, _ = c.nodes.GetOrCreate(addr) - } + c.process = c.defaultProcess + c.processPipeline = c.defaultProcessPipeline + c.processTxPipeline = c.defaultProcessTxPipeline - // Preload cluster slots. - for i := 0; i < 10; i++ { - state, err := c.reloadState() - if err == nil { - c._state.Store(state) - break - } - } + c.init() + + _, _ = c.state.Reload() + _, _ = c.cmdsInfoCache.Get() if opt.IdleCheckFrequency > 0 { go c.reaper(opt.IdleCheckFrequency) @@ -481,6 +689,39 @@ func NewClusterClient(opt *ClusterOptions) *ClusterClient { return c } +// ReloadState reloads cluster state. It calls ClusterSlots func +// to get cluster slots information. +func (c *ClusterClient) ReloadState() error { + _, err := c.state.Reload() + return err +} + +func (c *ClusterClient) init() { + c.cmdable.setProcessor(c.Process) +} + +func (c *ClusterClient) Context() context.Context { + if c.ctx != nil { + return c.ctx + } + return context.Background() +} + +func (c *ClusterClient) WithContext(ctx context.Context) *ClusterClient { + if ctx == nil { + panic("nil context") + } + c2 := c.copy() + c2.ctx = ctx + return c2 +} + +func (c *ClusterClient) copy() *ClusterClient { + cp := *c + cp.init() + return &cp +} + // Options returns read-only Options that were used to create the client. func (c *ClusterClient) Options() *ClusterOptions { return c.opt @@ -490,40 +731,40 @@ func (c *ClusterClient) retryBackoff(attempt int) time.Duration { return internal.RetryBackoff(attempt, c.opt.MinRetryBackoff, c.opt.MaxRetryBackoff) } -func (c *ClusterClient) state() (*clusterState, error) { - v := c._state.Load() - if v != nil { - return v.(*clusterState), nil - } - - _, err := c.nodes.Addrs() +func (c *ClusterClient) cmdsInfo() (map[string]*CommandInfo, error) { + addrs, err := c.nodes.Addrs() if err != nil { return nil, err } - c.lazyReloadState() - return nil, errNilClusterState -} - -func (c *ClusterClient) cmdInfo(name string) *CommandInfo { - err := c.cmdsInfoOnce.Do(func() error { - node, err := c.nodes.Random() + var firstErr error + for _, addr := range addrs { + node, err := c.nodes.Get(addr) if err != nil { - return err + return nil, err + } + if node == nil { + continue } - cmdsInfo, err := node.Client.Command().Result() - if err != nil { - return err + info, err := node.Client.Command().Result() + if err == nil { + return info, nil } + if firstErr == nil { + firstErr = err + } + } + return nil, firstErr +} - c.cmdsInfo = cmdsInfo - return nil - }) +func (c *ClusterClient) cmdInfo(name string) *CommandInfo { + cmdsInfo, err := c.cmdsInfoCache.Get() if err != nil { return nil } - info := c.cmdsInfo[name] + + info := cmdsInfo[name] if info == nil { internal.Logf("info for cmd=%s not found", name) } @@ -543,7 +784,12 @@ func (c *ClusterClient) cmdSlot(cmd Cmder) int { return cmdSlot(cmd, cmdFirstKeyPos(cmd, cmdInfo)) } -func (c *ClusterClient) cmdSlotAndNode(state *clusterState, cmd Cmder) (int, *clusterNode, error) { +func (c *ClusterClient) cmdSlotAndNode(cmd Cmder) (int, *clusterNode, error) { + state, err := c.state.Get() + if err != nil { + return 0, nil, err + } + cmdInfo := c.cmdInfo(cmd.Name()) slot := cmdSlot(cmd, cmdFirstKeyPos(cmd, cmdInfo)) @@ -553,6 +799,11 @@ func (c *ClusterClient) cmdSlotAndNode(state *clusterState, cmd Cmder) (int, *cl return slot, node, err } + if c.opt.RouteRandomly { + node := state.slotRandomNode(slot) + return slot, node, nil + } + node, err := state.slotSlaveNode(slot) return slot, node, err } @@ -561,24 +812,33 @@ func (c *ClusterClient) cmdSlotAndNode(state *clusterState, cmd Cmder) (int, *cl return slot, node, err } -func (c *ClusterClient) Watch(fn func(*Tx) error, keys ...string) error { - if len(keys) == 0 { - return fmt.Errorf("redis: keys don't hash to the same slot") +func (c *ClusterClient) slotMasterNode(slot int) (*clusterNode, error) { + state, err := c.state.Get() + if err != nil { + return nil, err } - state, err := c.state() - if err != nil { - return err + nodes := state.slotNodes(slot) + if len(nodes) > 0 { + return nodes[0], nil + } + return c.nodes.Random() +} + +func (c *ClusterClient) Watch(fn func(*Tx) error, keys ...string) error { + if len(keys) == 0 { + return fmt.Errorf("redis: Watch requires at least one key") } slot := hashtag.Slot(keys[0]) for _, key := range keys[1:] { if hashtag.Slot(key) != slot { - return fmt.Errorf("redis: Watch requires all keys to be in the same slot") + err := fmt.Errorf("redis: Watch requires all keys to be in the same slot") + return err } } - node, err := state.slotMasterNode(slot) + node, err := c.slotMasterNode(slot) if err != nil { return err } @@ -594,12 +854,13 @@ func (c *ClusterClient) Watch(fn func(*Tx) error, keys ...string) error { } if internal.IsRetryableError(err, true) { + c.state.LazyReload() continue } moved, ask, addr := internal.IsMovedError(err) if moved || ask { - c.lazyReloadState() + c.state.LazyReload() node, err = c.nodes.GetOrCreate(addr) if err != nil { return err @@ -608,10 +869,11 @@ func (c *ClusterClient) Watch(fn func(*Tx) error, keys ...string) error { } if err == pool.ErrClosed { - node, err = state.slotMasterNode(slot) + node, err = c.slotMasterNode(slot) if err != nil { return err } + continue } return err @@ -628,25 +890,34 @@ func (c *ClusterClient) Close() error { return c.nodes.Close() } -func (c *ClusterClient) Process(cmd Cmder) error { - state, err := c.state() - if err != nil { - cmd.setErr(err) - return err - } +func (c *ClusterClient) WrapProcess( + fn func(oldProcess func(Cmder) error) func(Cmder) error, +) { + c.process = fn(c.process) +} - _, node, err := c.cmdSlotAndNode(state, cmd) - if err != nil { - cmd.setErr(err) - return err - } +func (c *ClusterClient) Process(cmd Cmder) error { + return c.process(cmd) +} +func (c *ClusterClient) defaultProcess(cmd Cmder) error { + var node *clusterNode var ask bool for attempt := 0; attempt <= c.opt.MaxRedirects; attempt++ { if attempt > 0 { time.Sleep(c.retryBackoff(attempt)) } + if node == nil { + var err error + _, node, err = c.cmdSlotAndNode(cmd) + if err != nil { + cmd.setErr(err) + break + } + } + + var err error if ask { pipe := node.Client.Pipeline() _ = pipe.Process(NewCmd("ASKING")) @@ -665,15 +936,21 @@ func (c *ClusterClient) Process(cmd Cmder) error { // If slave is loading - read from master. if c.opt.ReadOnly && internal.IsLoadingError(err) { - // TODO: race - node.loading = time.Now() + node.MarkAsLoading() continue } if internal.IsRetryableError(err, true) { - var nodeErr error - node, nodeErr = c.nodes.Random() - if nodeErr != nil { + c.state.LazyReload() + + // First retry the same node. + if attempt == 0 { + continue + } + + // Second try random node. + node, err = c.nodes.Random() + if err != nil { break } continue @@ -683,22 +960,18 @@ func (c *ClusterClient) Process(cmd Cmder) error { var addr string moved, ask, addr = internal.IsMovedError(err) if moved || ask { - c.lazyReloadState() + c.state.LazyReload() - var nodeErr error - node, nodeErr = c.nodes.GetOrCreate(addr) - if nodeErr != nil { + node, err = c.nodes.GetOrCreate(addr) + if err != nil { break } continue } if err == pool.ErrClosed { - _, node, err = c.cmdSlotAndNode(state, cmd) - if err != nil { - cmd.setErr(err) - return err - } + node = nil + continue } break @@ -710,14 +983,14 @@ func (c *ClusterClient) Process(cmd Cmder) error { // ForEachMaster concurrently calls the fn on each master node in the cluster. // It returns the first error if any. func (c *ClusterClient) ForEachMaster(fn func(client *Client) error) error { - state, err := c.state() + state, err := c.state.ReloadOrGet() if err != nil { return err } var wg sync.WaitGroup errCh := make(chan error, 1) - for _, master := range state.masters { + for _, master := range state.Masters { wg.Add(1) go func(node *clusterNode) { defer wg.Done() @@ -743,14 +1016,14 @@ func (c *ClusterClient) ForEachMaster(fn func(client *Client) error) error { // ForEachSlave concurrently calls the fn on each slave node in the cluster. // It returns the first error if any. func (c *ClusterClient) ForEachSlave(fn func(client *Client) error) error { - state, err := c.state() + state, err := c.state.ReloadOrGet() if err != nil { return err } var wg sync.WaitGroup errCh := make(chan error, 1) - for _, slave := range state.slaves { + for _, slave := range state.Slaves { wg.Add(1) go func(node *clusterNode) { defer wg.Done() @@ -776,7 +1049,7 @@ func (c *ClusterClient) ForEachSlave(fn func(client *Client) error) error { // ForEachNode concurrently calls the fn on each known node in the cluster. // It returns the first error if any. func (c *ClusterClient) ForEachNode(fn func(client *Client) error) error { - state, err := c.state() + state, err := c.state.ReloadOrGet() if err != nil { return err } @@ -794,11 +1067,11 @@ func (c *ClusterClient) ForEachNode(fn func(client *Client) error) error { } } - for _, node := range state.masters { + for _, node := range state.Masters { wg.Add(1) go worker(node) } - for _, node := range state.slaves { + for _, node := range state.Slaves { wg.Add(1) go worker(node) } @@ -816,12 +1089,12 @@ func (c *ClusterClient) ForEachNode(fn func(client *Client) error) error { func (c *ClusterClient) PoolStats() *PoolStats { var acc PoolStats - state, _ := c.state() + state, _ := c.state.Get() if state == nil { return &acc } - for _, node := range state.masters { + for _, node := range state.Masters { s := node.Client.connPool.Stats() acc.Hits += s.Hits acc.Misses += s.Misses @@ -832,7 +1105,7 @@ func (c *ClusterClient) PoolStats() *PoolStats { acc.StaleConns += s.StaleConns } - for _, node := range state.slaves { + for _, node := range state.Slaves { s := node.Client.connPool.Stats() acc.Hits += s.Hits acc.Misses += s.Misses @@ -846,46 +1119,42 @@ func (c *ClusterClient) PoolStats() *PoolStats { return &acc } -func (c *ClusterClient) lazyReloadState() { - if !atomic.CompareAndSwapUint32(&c.reloading, 0, 1) { - return +func (c *ClusterClient) loadState() (*clusterState, error) { + if c.opt.ClusterSlots != nil { + slots, err := c.opt.ClusterSlots() + if err != nil { + return nil, err + } + return newClusterState(c.nodes, slots, "") } - go func() { - defer atomic.StoreUint32(&c.reloading, 0) + addrs, err := c.nodes.Addrs() + if err != nil { + return nil, err + } - for { - state, err := c.reloadState() - if err == pool.ErrClosed { - return + var firstErr error + for _, addr := range addrs { + node, err := c.nodes.GetOrCreate(addr) + if err != nil { + if firstErr == nil { + firstErr = err } + continue + } - if err != nil { - time.Sleep(time.Millisecond) - continue + slots, err := node.Client.ClusterSlots().Result() + if err != nil { + if firstErr == nil { + firstErr = err } - - c._state.Store(state) - time.Sleep(5 * time.Second) - c.nodes.GC(state.generation) - break + continue } - }() -} - -// Not thread-safe. -func (c *ClusterClient) reloadState() (*clusterState, error) { - node, err := c.nodes.Random() - if err != nil { - return nil, err - } - slots, err := node.Client.ClusterSlots().Result() - if err != nil { - return nil, err + return newClusterState(c.nodes, slots, node.Client.opt.Addr) } - return newClusterState(c.nodes, slots, node.Client.opt.Addr) + return nil, firstErr } // reaper closes idle connections to the cluster. @@ -910,9 +1179,9 @@ func (c *ClusterClient) reaper(idleCheckFrequency time.Duration) { func (c *ClusterClient) Pipeline() Pipeliner { pipe := Pipeline{ - exec: c.pipelineExec, + exec: c.processPipeline, } - pipe.setProcessor(pipe.Process) + pipe.statefulCmdable.setProcessor(pipe.Process) return &pipe } @@ -920,7 +1189,13 @@ func (c *ClusterClient) Pipelined(fn func(Pipeliner) error) ([]Cmder, error) { return c.Pipeline().Pipelined(fn) } -func (c *ClusterClient) pipelineExec(cmds []Cmder) error { +func (c *ClusterClient) WrapProcessPipeline( + fn func(oldProcess func([]Cmder) error) func([]Cmder) error, +) { + c.processPipeline = fn(c.processPipeline) +} + +func (c *ClusterClient) defaultProcessPipeline(cmds []Cmder) error { cmdsMap, err := c.mapCmdsByNode(cmds) if err != nil { setCmdsErr(cmds, err) @@ -935,7 +1210,7 @@ func (c *ClusterClient) pipelineExec(cmds []Cmder) error { failedCmds := make(map[*clusterNode][]Cmder) for node, cmds := range cmdsMap { - cn, _, err := node.Client.getConn() + cn, err := node.Client.getConn() if err != nil { if err == pool.ErrClosed { c.remapCmds(cmds, failedCmds) @@ -947,9 +1222,9 @@ func (c *ClusterClient) pipelineExec(cmds []Cmder) error { err = c.pipelineProcessCmds(node, cn, cmds, failedCmds) if err == nil || internal.IsRedisError(err) { - _ = node.Client.connPool.Put(cn) + node.Client.connPool.Put(cn) } else { - _ = node.Client.connPool.Remove(cn) + node.Client.connPool.Remove(cn) } } @@ -963,16 +1238,23 @@ func (c *ClusterClient) pipelineExec(cmds []Cmder) error { } func (c *ClusterClient) mapCmdsByNode(cmds []Cmder) (map[*clusterNode][]Cmder, error) { - state, err := c.state() + state, err := c.state.Get() if err != nil { setCmdsErr(cmds, err) return nil, err } cmdsMap := make(map[*clusterNode][]Cmder) + cmdsAreReadOnly := c.cmdsAreReadOnly(cmds) for _, cmd := range cmds { - slot := c.cmdSlot(cmd) - node, err := state.slotMasterNode(slot) + var node *clusterNode + var err error + if cmdsAreReadOnly { + _, node, err = c.cmdSlotAndNode(cmd) + } else { + slot := c.cmdSlot(cmd) + node, err = state.slotMasterNode(slot) + } if err != nil { return nil, err } @@ -981,6 +1263,16 @@ func (c *ClusterClient) mapCmdsByNode(cmds []Cmder) (map[*clusterNode][]Cmder, e return cmdsMap, nil } +func (c *ClusterClient) cmdsAreReadOnly(cmds []Cmder) bool { + for _, cmd := range cmds { + cmdInfo := c.cmdInfo(cmd.Name()) + if cmdInfo == nil || !cmdInfo.ReadOnly { + return false + } + } + return true +} + func (c *ClusterClient) remapCmds(cmds []Cmder, failedCmds map[*clusterNode][]Cmder) { remappedCmds, err := c.mapCmdsByNode(cmds) if err != nil { @@ -997,7 +1289,9 @@ func (c *ClusterClient) pipelineProcessCmds( node *clusterNode, cn *pool.Conn, cmds []Cmder, failedCmds map[*clusterNode][]Cmder, ) error { cn.SetWriteTimeout(c.opt.WriteTimeout) - if err := writeCmd(cn, cmds...); err != nil { + + err := writeCmd(cn, cmds...) + if err != nil { setCmdsErr(cmds, err) failedCmds[node] = cmds return err @@ -1037,7 +1331,7 @@ func (c *ClusterClient) checkMovedErr( moved, ask, addr := internal.IsMovedError(err) if moved { - c.lazyReloadState() + c.state.LazyReload() node, err := c.nodes.GetOrCreate(addr) if err != nil { @@ -1064,9 +1358,9 @@ func (c *ClusterClient) checkMovedErr( // TxPipeline acts like Pipeline, but wraps queued commands with MULTI/EXEC. func (c *ClusterClient) TxPipeline() Pipeliner { pipe := Pipeline{ - exec: c.txPipelineExec, + exec: c.processTxPipeline, } - pipe.setProcessor(pipe.Process) + pipe.statefulCmdable.setProcessor(pipe.Process) return &pipe } @@ -1074,8 +1368,8 @@ func (c *ClusterClient) TxPipelined(fn func(Pipeliner) error) ([]Cmder, error) { return c.TxPipeline().Pipelined(fn) } -func (c *ClusterClient) txPipelineExec(cmds []Cmder) error { - state, err := c.state() +func (c *ClusterClient) defaultProcessTxPipeline(cmds []Cmder) error { + state, err := c.state.Get() if err != nil { return err } @@ -1097,7 +1391,7 @@ func (c *ClusterClient) txPipelineExec(cmds []Cmder) error { failedCmds := make(map[*clusterNode][]Cmder) for node, cmds := range cmdsMap { - cn, _, err := node.Client.getConn() + cn, err := node.Client.getConn() if err != nil { if err == pool.ErrClosed { c.remapCmds(cmds, failedCmds) @@ -1109,9 +1403,9 @@ func (c *ClusterClient) txPipelineExec(cmds []Cmder) error { err = c.txPipelineProcessCmds(node, cn, cmds, failedCmds) if err == nil || internal.IsRedisError(err) { - _ = node.Client.connPool.Put(cn) + node.Client.connPool.Put(cn) } else { - _ = node.Client.connPool.Remove(cn) + node.Client.connPool.Remove(cn) } } @@ -1206,11 +1500,9 @@ func (c *ClusterClient) txPipelineReadQueued( } func (c *ClusterClient) pubSub(channels []string) *PubSub { - opt := c.opt.clientOptions() - var node *clusterNode - return &PubSub{ - opt: opt, + pubsub := &PubSub{ + opt: c.opt.clientOptions(), newConn: func(channels []string) (*pool.Conn, error) { if node == nil { @@ -1221,12 +1513,7 @@ func (c *ClusterClient) pubSub(channels []string) *PubSub { slot = -1 } - state, err := c.state() - if err != nil { - return nil, err - } - - masterNode, err := state.slotMasterNode(slot) + masterNode, err := c.slotMasterNode(slot) if err != nil { return nil, err } @@ -1238,6 +1525,8 @@ func (c *ClusterClient) pubSub(channels []string) *PubSub { return node.Client.connPool.CloseConn(cn) }, } + pubsub.init() + return pubsub } // Subscribe subscribes the client to the specified channels. @@ -1260,6 +1549,29 @@ func (c *ClusterClient) PSubscribe(channels ...string) *PubSub { return pubsub } +func useOriginAddr(originAddr, nodeAddr string) bool { + nodeHost, nodePort, err := net.SplitHostPort(nodeAddr) + if err != nil { + return false + } + + nodeIP := net.ParseIP(nodeHost) + if nodeIP == nil { + return false + } + + if !nodeIP.IsLoopback() { + return false + } + + _, originPort, err := net.SplitHostPort(originAddr) + if err != nil { + return false + } + + return nodePort == originPort +} + func isLoopbackAddr(addr string) bool { host, _, err := net.SplitHostPort(addr) if err != nil { @@ -1274,7 +1586,7 @@ func isLoopbackAddr(addr string) bool { return ip.IsLoopback() } -func appendNode(nodes []*clusterNode, node *clusterNode) []*clusterNode { +func appendUniqueNode(nodes []*clusterNode, node *clusterNode) []*clusterNode { for _, n := range nodes { if n == node { return nodes @@ -1282,3 +1594,31 @@ func appendNode(nodes []*clusterNode, node *clusterNode) []*clusterNode { } return append(nodes, node) } + +func appendIfNotExists(ss []string, es ...string) []string { +loop: + for _, e := range es { + for _, s := range ss { + if s == e { + continue loop + } + } + ss = append(ss, e) + } + return ss +} + +func remove(ss []string, es ...string) []string { + if len(es) == 0 { + return ss[:0] + } + for _, e := range es { + for i, s := range ss { + if s == e { + ss = append(ss[:i], ss[i+1:]...) + break + } + } + } + return ss +} diff --git a/vendor/github.com/go-redis/redis/command.go b/vendor/github.com/go-redis/redis/command.go index 598ed98002..11472bec1b 100644 --- a/vendor/github.com/go-redis/redis/command.go +++ b/vendor/github.com/go-redis/redis/command.go @@ -10,6 +10,7 @@ import ( "github.com/go-redis/redis/internal" "github.com/go-redis/redis/internal/pool" "github.com/go-redis/redis/internal/proto" + "github.com/go-redis/redis/internal/util" ) type Cmder interface { @@ -81,9 +82,9 @@ func cmdFirstKeyPos(cmd Cmder, info *CommandInfo) int { case "eval", "evalsha": if cmd.stringArg(2) != "0" { return 3 - } else { - return 0 } + + return 0 case "publish": return 1 } @@ -436,7 +437,7 @@ func NewStringCmd(args ...interface{}) *StringCmd { } func (cmd *StringCmd) Val() string { - return internal.BytesToString(cmd.val) + return util.BytesToString(cmd.val) } func (cmd *StringCmd) Result() (string, error) { @@ -713,6 +714,179 @@ func (cmd *StringStructMapCmd) readReply(cn *pool.Conn) error { //------------------------------------------------------------------------------ +type XStream struct { + Stream string + Messages []*XMessage +} + +type XMessage struct { + ID string + Values map[string]interface{} +} + +//------------------------------------------------------------------------------ + +type XStreamSliceCmd struct { + baseCmd + + val []*XStream +} + +var _ Cmder = (*XStreamSliceCmd)(nil) + +func NewXStreamSliceCmd(args ...interface{}) *XStreamSliceCmd { + return &XStreamSliceCmd{ + baseCmd: baseCmd{_args: args}, + } +} + +func (cmd *XStreamSliceCmd) Val() []*XStream { + return cmd.val +} + +func (cmd *XStreamSliceCmd) Result() ([]*XStream, error) { + return cmd.val, cmd.err +} + +func (cmd *XStreamSliceCmd) String() string { + return cmdString(cmd, cmd.val) +} + +func (cmd *XStreamSliceCmd) readReply(cn *pool.Conn) error { + var v interface{} + v, cmd.err = cn.Rd.ReadArrayReply(xStreamSliceParser) + if cmd.err != nil { + return cmd.err + } + cmd.val = v.([]*XStream) + return nil +} + +// Implements proto.MultiBulkParse +func xStreamSliceParser(rd *proto.Reader, n int64) (interface{}, error) { + xx := make([]*XStream, n) + for i := int64(0); i < n; i++ { + v, err := rd.ReadArrayReply(xStreamParser) + if err != nil { + return nil, err + } + xx[i] = v.(*XStream) + } + return xx, nil +} + +// Implements proto.MultiBulkParse +func xStreamParser(rd *proto.Reader, n int64) (interface{}, error) { + if n != 2 { + return nil, fmt.Errorf("got %d, wanted 2", n) + } + + stream, err := rd.ReadStringReply() + if err != nil { + return nil, err + } + + v, err := rd.ReadArrayReply(xMessageSliceParser) + if err != nil { + return nil, err + } + + return &XStream{ + Stream: stream, + Messages: v.([]*XMessage), + }, nil +} + +//------------------------------------------------------------------------------ + +type XMessageSliceCmd struct { + baseCmd + + val []*XMessage +} + +var _ Cmder = (*XMessageSliceCmd)(nil) + +func NewXMessageSliceCmd(args ...interface{}) *XMessageSliceCmd { + return &XMessageSliceCmd{ + baseCmd: baseCmd{_args: args}, + } +} + +func (cmd *XMessageSliceCmd) Val() []*XMessage { + return cmd.val +} + +func (cmd *XMessageSliceCmd) Result() ([]*XMessage, error) { + return cmd.val, cmd.err +} + +func (cmd *XMessageSliceCmd) String() string { + return cmdString(cmd, cmd.val) +} + +func (cmd *XMessageSliceCmd) readReply(cn *pool.Conn) error { + var v interface{} + v, cmd.err = cn.Rd.ReadArrayReply(xMessageSliceParser) + if cmd.err != nil { + return cmd.err + } + cmd.val = v.([]*XMessage) + return nil +} + +// Implements proto.MultiBulkParse +func xMessageSliceParser(rd *proto.Reader, n int64) (interface{}, error) { + msgs := make([]*XMessage, n) + for i := int64(0); i < n; i++ { + v, err := rd.ReadArrayReply(xMessageParser) + if err != nil { + return nil, err + } + msgs[i] = v.(*XMessage) + } + return msgs, nil +} + +// Implements proto.MultiBulkParse +func xMessageParser(rd *proto.Reader, n int64) (interface{}, error) { + id, err := rd.ReadStringReply() + if err != nil { + return nil, err + } + + v, err := rd.ReadArrayReply(xKeyValueParser) + if err != nil { + return nil, err + } + + return &XMessage{ + ID: id, + Values: v.(map[string]interface{}), + }, nil +} + +// Implements proto.MultiBulkParse +func xKeyValueParser(rd *proto.Reader, n int64) (interface{}, error) { + values := make(map[string]interface{}, n) + for i := int64(0); i < n; i += 2 { + key, err := rd.ReadStringReply() + if err != nil { + return nil, err + } + + value, err := rd.ReadStringReply() + if err != nil { + return nil, err + } + + values[key] = value + } + return values, nil +} + +//------------------------------------------------------------------------------ + type ZSliceCmd struct { baseCmd @@ -1022,3 +1196,30 @@ func (cmd *CommandsInfoCmd) readReply(cn *pool.Conn) error { cmd.val = v.(map[string]*CommandInfo) return nil } + +//------------------------------------------------------------------------------ + +type cmdsInfoCache struct { + fn func() (map[string]*CommandInfo, error) + + once internal.Once + cmds map[string]*CommandInfo +} + +func newCmdsInfoCache(fn func() (map[string]*CommandInfo, error)) *cmdsInfoCache { + return &cmdsInfoCache{ + fn: fn, + } +} + +func (c *cmdsInfoCache) Get() (map[string]*CommandInfo, error) { + err := c.once.Do(func() error { + cmds, err := c.fn() + if err != nil { + return err + } + c.cmds = cmds + return nil + }) + return c.cmds, err +} diff --git a/vendor/github.com/go-redis/redis/commands.go b/vendor/github.com/go-redis/redis/commands.go index 569342cfa1..dddf8acd65 100644 --- a/vendor/github.com/go-redis/redis/commands.go +++ b/vendor/github.com/go-redis/redis/commands.go @@ -1,6 +1,7 @@ package redis import ( + "errors" "io" "time" @@ -38,6 +39,22 @@ func formatSec(dur time.Duration) int64 { return int64(dur / time.Second) } +func appendArgs(dst, src []interface{}) []interface{} { + if len(src) == 1 { + if ss, ok := src[0].([]string); ok { + for _, s := range ss { + dst = append(dst, s) + } + return dst + } + } + + for _, v := range src { + dst = append(dst, v) + } + return dst +} + type Cmdable interface { Pipeline() Pipeliner Pipelined(fn func(Pipeliner) error) ([]Cmder, error) @@ -45,6 +62,7 @@ type Cmdable interface { TxPipelined(fn func(Pipeliner) error) ([]Cmder, error) TxPipeline() Pipeliner + Command() *CommandsInfoCmd ClientGetName() *StringCmd Echo(message interface{}) *StringCmd Ping() *StatusCmd @@ -70,8 +88,10 @@ type Cmdable interface { RenameNX(key, newkey string) *BoolCmd Restore(key string, ttl time.Duration, value string) *StatusCmd RestoreReplace(key string, ttl time.Duration, value string) *StatusCmd - Sort(key string, sort Sort) *StringSliceCmd - SortInterfaces(key string, sort Sort) *SliceCmd + Sort(key string, sort *Sort) *StringSliceCmd + SortStore(key, store string, sort *Sort) *IntCmd + SortInterfaces(key string, sort *Sort) *SliceCmd + Touch(keys ...string) *IntCmd TTL(key string) *DurationCmd Type(key string) *StatusCmd Scan(cursor uint64, match string, count int64) *ScanCmd @@ -152,6 +172,16 @@ type Cmdable interface { SRem(key string, members ...interface{}) *IntCmd SUnion(keys ...string) *StringSliceCmd SUnionStore(destination string, keys ...string) *IntCmd + XAdd(stream, id string, els map[string]interface{}) *StringCmd + XAddExt(opt *XAddExt) *StringCmd + XLen(key string) *IntCmd + XRange(stream, start, stop string) *XMessageSliceCmd + XRangeN(stream, start, stop string, count int64) *XMessageSliceCmd + XRevRange(stream string, start, stop string) *XMessageSliceCmd + XRevRangeN(stream string, start, stop string, count int64) *XMessageSliceCmd + XRead(streams ...string) *XStreamSliceCmd + XReadN(count int64, streams ...string) *XStreamSliceCmd + XReadExt(opt *XReadExt) *XStreamSliceCmd ZAdd(key string, members ...Z) *IntCmd ZAddNX(key string, members ...Z) *IntCmd ZAddXX(key string, members ...Z) *IntCmd @@ -190,11 +220,13 @@ type Cmdable interface { BgRewriteAOF() *StatusCmd BgSave() *StatusCmd ClientKill(ipPort string) *StatusCmd + ClientKillByFilter(keys ...string) *IntCmd ClientList() *StringCmd ClientPause(dur time.Duration) *BoolCmd ConfigGet(parameter string) *SliceCmd ConfigResetStat() *StatusCmd ConfigSet(parameter, value string) *StatusCmd + ConfigRewrite() *StatusCmd DBSize() *IntCmd FlushAll() *StatusCmd FlushAllAsync() *StatusCmd @@ -210,7 +242,7 @@ type Cmdable interface { Time() *TimeCmd Eval(script string, keys []string, args ...interface{}) *Cmd EvalSha(sha1 string, keys []string, args ...interface{}) *Cmd - ScriptExists(scripts ...string) *BoolSliceCmd + ScriptExists(hashes ...string) *BoolSliceCmd ScriptFlush() *StatusCmd ScriptKill() *StatusCmd ScriptLoad(script string) *StringCmd @@ -245,16 +277,17 @@ type Cmdable interface { GeoRadiusByMemberRO(key, member string, query *GeoRadiusQuery) *GeoLocationCmd GeoDist(key string, member1, member2, unit string) *FloatCmd GeoHash(key string, members ...string) *StringSliceCmd - Command() *CommandsInfoCmd + ReadOnly() *StatusCmd + ReadWrite() *StatusCmd + MemoryUsage(key string, samples ...int) *IntCmd } type StatefulCmdable interface { Cmdable Auth(password string) *StatusCmd Select(index int) *StatusCmd + SwapDB(index1, index2 int) *StatusCmd ClientSetName(name string) *BoolCmd - ReadOnly() *StatusCmd - ReadWrite() *StatusCmd } var _ Cmdable = (*Client)(nil) @@ -316,8 +349,20 @@ func (c *statefulCmdable) Select(index int) *StatusCmd { return cmd } +func (c *statefulCmdable) SwapDB(index1, index2 int) *StatusCmd { + cmd := NewStatusCmd("swapdb", index1, index2) + c.process(cmd) + return cmd +} + //------------------------------------------------------------------------------ +func (c *cmdable) Command() *CommandsInfoCmd { + cmd := NewCommandsInfoCmd("command") + c.process(cmd) + return cmd +} + func (c *cmdable) Del(keys ...string) *IntCmd { args := make([]interface{}, 1+len(keys)) args[0] = "del" @@ -384,7 +429,7 @@ func (c *cmdable) Migrate(host, port, key string, db int64, timeout time.Duratio db, formatMs(timeout), ) - cmd.setReadTimeout(readTimeout(timeout)) + cmd.setReadTimeout(timeout) c.process(cmd) return cmd } @@ -484,11 +529,10 @@ func (c *cmdable) RestoreReplace(key string, ttl time.Duration, value string) *S type Sort struct { By string - Offset, Count float64 + Offset, Count int64 Get []string Order string - IsAlpha bool - Store string + Alpha bool } func (sort *Sort) args(key string) []interface{} { @@ -505,27 +549,45 @@ func (sort *Sort) args(key string) []interface{} { if sort.Order != "" { args = append(args, sort.Order) } - if sort.IsAlpha { + if sort.Alpha { args = append(args, "alpha") } - if sort.Store != "" { - args = append(args, "store", sort.Store) - } return args } -func (c *cmdable) Sort(key string, sort Sort) *StringSliceCmd { +func (c *cmdable) Sort(key string, sort *Sort) *StringSliceCmd { cmd := NewStringSliceCmd(sort.args(key)...) c.process(cmd) return cmd } -func (c *cmdable) SortInterfaces(key string, sort Sort) *SliceCmd { +func (c *cmdable) SortStore(key, store string, sort *Sort) *IntCmd { + args := sort.args(key) + if store != "" { + args = append(args, "store", store) + } + cmd := NewIntCmd(args...) + c.process(cmd) + return cmd +} + +func (c *cmdable) SortInterfaces(key string, sort *Sort) *SliceCmd { cmd := NewSliceCmd(sort.args(key)...) c.process(cmd) return cmd } +func (c *cmdable) Touch(keys ...string) *IntCmd { + args := make([]interface{}, len(keys)+1) + args[0] = "touch" + for i, key := range keys { + args[i+1] = key + } + cmd := NewIntCmd(args...) + c.process(cmd) + return cmd +} + func (c *cmdable) TTL(key string) *DurationCmd { cmd := NewDurationCmd(time.Second, "ttl", key) c.process(cmd) @@ -732,22 +794,18 @@ func (c *cmdable) MGet(keys ...string) *SliceCmd { } func (c *cmdable) MSet(pairs ...interface{}) *StatusCmd { - args := make([]interface{}, 1+len(pairs)) + args := make([]interface{}, 1, 1+len(pairs)) args[0] = "mset" - for i, pair := range pairs { - args[1+i] = pair - } + args = appendArgs(args, pairs) cmd := NewStatusCmd(args...) c.process(cmd) return cmd } func (c *cmdable) MSetNX(pairs ...interface{}) *BoolCmd { - args := make([]interface{}, 1+len(pairs)) + args := make([]interface{}, 1, 1+len(pairs)) args[0] = "msetnx" - for i, pair := range pairs { - args[1+i] = pair - } + args = appendArgs(args, pairs) cmd := NewBoolCmd(args...) c.process(cmd) return cmd @@ -945,7 +1003,7 @@ func (c *cmdable) BLPop(timeout time.Duration, keys ...string) *StringSliceCmd { } args[len(args)-1] = formatSec(timeout) cmd := NewStringSliceCmd(args...) - cmd.setReadTimeout(readTimeout(timeout)) + cmd.setReadTimeout(timeout) c.process(cmd) return cmd } @@ -958,7 +1016,7 @@ func (c *cmdable) BRPop(timeout time.Duration, keys ...string) *StringSliceCmd { } args[len(keys)+1] = formatSec(timeout) cmd := NewStringSliceCmd(args...) - cmd.setReadTimeout(readTimeout(timeout)) + cmd.setReadTimeout(timeout) c.process(cmd) return cmd } @@ -970,7 +1028,7 @@ func (c *cmdable) BRPopLPush(source, destination string, timeout time.Duration) destination, formatSec(timeout), ) - cmd.setReadTimeout(readTimeout(timeout)) + cmd.setReadTimeout(timeout) c.process(cmd) return cmd } @@ -1012,12 +1070,10 @@ func (c *cmdable) LPop(key string) *StringCmd { } func (c *cmdable) LPush(key string, values ...interface{}) *IntCmd { - args := make([]interface{}, 2+len(values)) + args := make([]interface{}, 2, 2+len(values)) args[0] = "lpush" args[1] = key - for i, value := range values { - args[2+i] = value - } + args = appendArgs(args, values) cmd := NewIntCmd(args...) c.process(cmd) return cmd @@ -1076,12 +1132,10 @@ func (c *cmdable) RPopLPush(source, destination string) *StringCmd { } func (c *cmdable) RPush(key string, values ...interface{}) *IntCmd { - args := make([]interface{}, 2+len(values)) + args := make([]interface{}, 2, 2+len(values)) args[0] = "rpush" args[1] = key - for i, value := range values { - args[2+i] = value - } + args = appendArgs(args, values) cmd := NewIntCmd(args...) c.process(cmd) return cmd @@ -1096,12 +1150,10 @@ func (c *cmdable) RPushX(key string, value interface{}) *IntCmd { //------------------------------------------------------------------------------ func (c *cmdable) SAdd(key string, members ...interface{}) *IntCmd { - args := make([]interface{}, 2+len(members)) + args := make([]interface{}, 2, 2+len(members)) args[0] = "sadd" args[1] = key - for i, member := range members { - args[2+i] = member - } + args = appendArgs(args, members) cmd := NewIntCmd(args...) c.process(cmd) return cmd @@ -1214,12 +1266,10 @@ func (c *cmdable) SRandMemberN(key string, count int64) *StringSliceCmd { } func (c *cmdable) SRem(key string, members ...interface{}) *IntCmd { - args := make([]interface{}, 2+len(members)) + args := make([]interface{}, 2, 2+len(members)) args[0] = "srem" args[1] = key - for i, member := range members { - args[2+i] = member - } + args = appendArgs(args, members) cmd := NewIntCmd(args...) c.process(cmd) return cmd @@ -1250,6 +1300,129 @@ func (c *cmdable) SUnionStore(destination string, keys ...string) *IntCmd { //------------------------------------------------------------------------------ +type XAddExt struct { + Stream string + MaxLen int64 // MAXLEN N + MaxLenApprox int64 // MAXLEN ~ N + ID string + Values map[string]interface{} +} + +func (c *cmdable) XAddExt(opt *XAddExt) *StringCmd { + a := make([]interface{}, 0, 6+len(opt.Values)*2) + a = append(a, "xadd") + a = append(a, opt.Stream) + if opt.MaxLen > 0 { + a = append(a, "maxlen", opt.MaxLen) + } else if opt.MaxLenApprox > 0 { + a = append(a, "maxlen", "~", opt.MaxLenApprox) + } + if opt.ID != "" { + a = append(a, opt.ID) + } else { + a = append(a, "*") + } + for k, v := range opt.Values { + a = append(a, k) + a = append(a, v) + } + + cmd := NewStringCmd(a...) + c.process(cmd) + return cmd +} + +func (c *cmdable) XAdd(stream, id string, values map[string]interface{}) *StringCmd { + return c.XAddExt(&XAddExt{ + Stream: stream, + ID: id, + Values: values, + }) +} + +func (c *cmdable) XLen(key string) *IntCmd { + cmd := NewIntCmd("xlen", key) + c.process(cmd) + return cmd +} + +func (c *cmdable) XRange(stream, start, stop string) *XMessageSliceCmd { + cmd := NewXMessageSliceCmd("xrange", stream, start, stop) + c.process(cmd) + return cmd +} + +func (c *cmdable) XRangeN(stream, start, stop string, count int64) *XMessageSliceCmd { + cmd := NewXMessageSliceCmd("xrange", stream, start, stop, "count", count) + c.process(cmd) + return cmd +} + +func (c *cmdable) XRevRange(stream, start, stop string) *XMessageSliceCmd { + cmd := NewXMessageSliceCmd("xrevrange", stream, start, stop) + c.process(cmd) + return cmd +} + +func (c *cmdable) XRevRangeN(stream, start, stop string, count int64) *XMessageSliceCmd { + cmd := NewXMessageSliceCmd("xrevrange", stream, start, stop, "count", count) + c.process(cmd) + return cmd +} + +type XReadExt struct { + Streams []string + Count int64 + Block time.Duration +} + +func (c *cmdable) XReadExt(opt *XReadExt) *XStreamSliceCmd { + a := make([]interface{}, 0, 5+len(opt.Streams)) + a = append(a, "xread") + if opt != nil { + if opt.Count > 0 { + a = append(a, "count") + a = append(a, opt.Count) + } + if opt.Block >= 0 { + a = append(a, "block") + a = append(a, int64(opt.Block/time.Millisecond)) + } + } + a = append(a, "streams") + for _, s := range opt.Streams { + a = append(a, s) + } + + cmd := NewXStreamSliceCmd(a...) + c.process(cmd) + return cmd +} + +func (c *cmdable) XRead(streams ...string) *XStreamSliceCmd { + return c.XReadExt(&XReadExt{ + Streams: streams, + Block: -1, + }) +} + +func (c *cmdable) XReadN(count int64, streams ...string) *XStreamSliceCmd { + return c.XReadExt(&XReadExt{ + Streams: streams, + Count: count, + Block: -1, + }) +} + +func (c *cmdable) XReadBlock(block time.Duration, streams ...string) *XStreamSliceCmd { + return c.XReadExt(&XReadExt{ + Streams: streams, + Block: block, + }) +} + +//------------------------------------------------------------------------------ + // Z represents sorted set member. type Z struct { Score float64 @@ -1479,12 +1652,10 @@ func (c *cmdable) ZRank(key, member string) *IntCmd { } func (c *cmdable) ZRem(key string, members ...interface{}) *IntCmd { - args := make([]interface{}, 2+len(members)) + args := make([]interface{}, 2, 2+len(members)) args[0] = "zrem" args[1] = key - for i, member := range members { - args[2+i] = member - } + args = appendArgs(args, members) cmd := NewIntCmd(args...) c.process(cmd) return cmd @@ -1600,12 +1771,10 @@ func (c *cmdable) ZUnionStore(dest string, store ZStore, keys ...string) *IntCmd //------------------------------------------------------------------------------ func (c *cmdable) PFAdd(key string, els ...interface{}) *IntCmd { - args := make([]interface{}, 2+len(els)) + args := make([]interface{}, 2, 2+len(els)) args[0] = "pfadd" args[1] = key - for i, el := range els { - args[2+i] = el - } + args = appendArgs(args, els) cmd := NewIntCmd(args...) c.process(cmd) return cmd @@ -1654,6 +1823,20 @@ func (c *cmdable) ClientKill(ipPort string) *StatusCmd { return cmd } +// ClientKillByFilter is new style synx, while the ClientKill is old +// CLIENT KILL