From b69bbe25acc10a805b8459bb4e79880ad781727f Mon Sep 17 00:00:00 2001 From: David Porter Date: Wed, 3 Nov 2021 17:51:18 -0700 Subject: [PATCH 1/2] Vendor latest k8s.io/cri-api and netlink * Bump k8s.io/cri-api to latest version - v0.23.0-alpha.4 * Vendor github.com/vishvananda/netlink for network stats Signed-off-by: David Porter --- go.mod | 3 +- go.sum | 8 +- integration/client/go.sum | 4 +- .../github.com/vishvananda/netlink/.gitignore | 1 + .../vishvananda/netlink/.travis.yml | 20 + .../vishvananda/netlink/CHANGELOG.md | 5 + vendor/github.com/vishvananda/netlink/LICENSE | 192 + .../github.com/vishvananda/netlink/Makefile | 30 + .../github.com/vishvananda/netlink/README.md | 92 + vendor/github.com/vishvananda/netlink/addr.go | 57 + .../vishvananda/netlink/addr_linux.go | 414 ++ .../vishvananda/netlink/bpf_linux.go | 53 + .../vishvananda/netlink/bridge_linux.go | 112 + .../github.com/vishvananda/netlink/class.go | 239 + .../vishvananda/netlink/class_linux.go | 397 ++ .../vishvananda/netlink/conntrack_linux.go | 454 ++ .../netlink/conntrack_unspecified.go | 53 + .../vishvananda/netlink/devlink_linux.go | 393 ++ .../github.com/vishvananda/netlink/filter.go | 325 ++ .../vishvananda/netlink/filter_linux.go | 815 +++ vendor/github.com/vishvananda/netlink/fou.go | 21 + .../vishvananda/netlink/fou_linux.go | 211 + .../vishvananda/netlink/fou_unspecified.go | 15 + .../vishvananda/netlink/genetlink_linux.go | 171 + .../netlink/genetlink_unspecified.go | 25 + vendor/github.com/vishvananda/netlink/go.mod | 8 + vendor/github.com/vishvananda/netlink/go.sum | 6 + .../vishvananda/netlink/gtp_linux.go | 239 + .../vishvananda/netlink/handle_linux.go | 160 + .../vishvananda/netlink/handle_unspecified.go | 274 + .../vishvananda/netlink/inet_diag.go | 31 + .../vishvananda/netlink/ioctl_linux.go | 90 + .../vishvananda/netlink/ipset_linux.go | 365 ++ vendor/github.com/vishvananda/netlink/link.go | 1275 +++++ .../vishvananda/netlink/link_linux.go | 3305 +++++++++++ .../vishvananda/netlink/link_tuntap_linux.go | 14 + .../github.com/vishvananda/netlink/neigh.go | 32 + .../vishvananda/netlink/neigh_linux.go | 434 ++ .../github.com/vishvananda/netlink/netlink.go | 40 + .../vishvananda/netlink/netlink_linux.go | 11 + .../netlink/netlink_unspecified.go | 241 + .../vishvananda/netlink/netns_linux.go | 141 + .../vishvananda/netlink/netns_unspecified.go | 19 + .../vishvananda/netlink/nl/addr_linux.go | 71 + .../vishvananda/netlink/nl/bridge_linux.go | 74 + .../vishvananda/netlink/nl/conntrack_linux.go | 218 + .../vishvananda/netlink/nl/devlink_linux.go | 63 + .../vishvananda/netlink/nl/genetlink_linux.go | 89 + .../vishvananda/netlink/nl/ipset_linux.go | 222 + .../vishvananda/netlink/nl/link_linux.go | 711 +++ .../vishvananda/netlink/nl/mpls_linux.go | 36 + .../vishvananda/netlink/nl/nl_linux.go | 791 +++ .../vishvananda/netlink/nl/nl_unspecified.go | 11 + .../netlink/nl/parse_attr_linux.go | 79 + .../vishvananda/netlink/nl/rdma_link_linux.go | 35 + .../vishvananda/netlink/nl/route_linux.go | 107 + .../vishvananda/netlink/nl/seg6_linux.go | 154 + .../vishvananda/netlink/nl/seg6local_linux.go | 76 + .../vishvananda/netlink/nl/syscall.go | 76 + .../vishvananda/netlink/nl/tc_linux.go | 983 ++++ .../vishvananda/netlink/nl/xfrm_linux.go | 306 + .../netlink/nl/xfrm_monitor_linux.go | 32 + .../netlink/nl/xfrm_policy_linux.go | 119 + .../netlink/nl/xfrm_state_linux.go | 334 ++ .../github.com/vishvananda/netlink/order.go | 32 + .../vishvananda/netlink/protinfo.go | 62 + .../vishvananda/netlink/protinfo_linux.go | 74 + .../github.com/vishvananda/netlink/qdisc.go | 366 ++ .../vishvananda/netlink/qdisc_linux.go | 713 +++ .../vishvananda/netlink/rdma_link_linux.go | 280 + .../github.com/vishvananda/netlink/route.go | 205 + .../vishvananda/netlink/route_linux.go | 1390 +++++ .../vishvananda/netlink/route_unspecified.go | 21 + vendor/github.com/vishvananda/netlink/rule.go | 56 + .../vishvananda/netlink/rule_linux.go | 296 + .../github.com/vishvananda/netlink/socket.go | 27 + .../vishvananda/netlink/socket_linux.go | 261 + vendor/github.com/vishvananda/netlink/tcp.go | 84 + .../vishvananda/netlink/tcp_linux.go | 353 ++ vendor/github.com/vishvananda/netlink/xfrm.go | 75 + .../vishvananda/netlink/xfrm_monitor_linux.go | 101 + .../vishvananda/netlink/xfrm_policy.go | 97 + .../vishvananda/netlink/xfrm_policy_linux.go | 265 + .../vishvananda/netlink/xfrm_state.go | 131 + .../vishvananda/netlink/xfrm_state_linux.go | 477 ++ vendor/github.com/vishvananda/netns/LICENSE | 192 + vendor/github.com/vishvananda/netns/README.md | 61 + vendor/github.com/vishvananda/netns/go.mod | 5 + vendor/github.com/vishvananda/netns/go.sum | 2 + vendor/github.com/vishvananda/netns/netns.go | 81 + .../vishvananda/netns/netns_linux.go | 266 + .../vishvananda/netns/netns_unspecified.go | 43 + .../cri-api/pkg/apis/runtime/v1/api.pb.go | 5017 ++++++++++++++-- .../cri-api/pkg/apis/runtime/v1/api.proto | 130 + .../pkg/apis/runtime/v1alpha2/api.pb.go | 5021 +++++++++++++++-- .../pkg/apis/runtime/v1alpha2/api.proto | 130 + vendor/modules.txt | 8 +- 97 files changed, 30857 insertions(+), 847 deletions(-) create mode 100644 vendor/github.com/vishvananda/netlink/.gitignore create mode 100644 vendor/github.com/vishvananda/netlink/.travis.yml create mode 100644 vendor/github.com/vishvananda/netlink/CHANGELOG.md create mode 100644 vendor/github.com/vishvananda/netlink/LICENSE create mode 100644 vendor/github.com/vishvananda/netlink/Makefile create mode 100644 vendor/github.com/vishvananda/netlink/README.md create mode 100644 vendor/github.com/vishvananda/netlink/addr.go create mode 100644 vendor/github.com/vishvananda/netlink/addr_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/bpf_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/bridge_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/class.go create mode 100644 vendor/github.com/vishvananda/netlink/class_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/conntrack_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/conntrack_unspecified.go create mode 100644 vendor/github.com/vishvananda/netlink/devlink_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/filter.go create mode 100644 vendor/github.com/vishvananda/netlink/filter_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/fou.go create mode 100644 vendor/github.com/vishvananda/netlink/fou_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/fou_unspecified.go create mode 100644 vendor/github.com/vishvananda/netlink/genetlink_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/genetlink_unspecified.go create mode 100644 vendor/github.com/vishvananda/netlink/go.mod create mode 100644 vendor/github.com/vishvananda/netlink/go.sum create mode 100644 vendor/github.com/vishvananda/netlink/gtp_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/handle_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/handle_unspecified.go create mode 100644 vendor/github.com/vishvananda/netlink/inet_diag.go create mode 100644 vendor/github.com/vishvananda/netlink/ioctl_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/ipset_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/link.go create mode 100644 vendor/github.com/vishvananda/netlink/link_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/link_tuntap_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/neigh.go create mode 100644 vendor/github.com/vishvananda/netlink/neigh_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/netlink.go create mode 100644 vendor/github.com/vishvananda/netlink/netlink_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/netlink_unspecified.go create mode 100644 vendor/github.com/vishvananda/netlink/netns_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/netns_unspecified.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/addr_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/bridge_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/devlink_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/genetlink_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/ipset_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/link_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/mpls_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/nl_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/nl_unspecified.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/parse_attr_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/route_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/seg6_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/syscall.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/tc_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/xfrm_monitor_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/xfrm_policy_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/order.go create mode 100644 vendor/github.com/vishvananda/netlink/protinfo.go create mode 100644 vendor/github.com/vishvananda/netlink/protinfo_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/qdisc.go create mode 100644 vendor/github.com/vishvananda/netlink/qdisc_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/rdma_link_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/route.go create mode 100644 vendor/github.com/vishvananda/netlink/route_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/route_unspecified.go create mode 100644 vendor/github.com/vishvananda/netlink/rule.go create mode 100644 vendor/github.com/vishvananda/netlink/rule_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/socket.go create mode 100644 vendor/github.com/vishvananda/netlink/socket_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/tcp.go create mode 100644 vendor/github.com/vishvananda/netlink/tcp_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/xfrm.go create mode 100644 vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/xfrm_policy.go create mode 100644 vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/xfrm_state.go create mode 100644 vendor/github.com/vishvananda/netlink/xfrm_state_linux.go create mode 100644 vendor/github.com/vishvananda/netns/LICENSE create mode 100644 vendor/github.com/vishvananda/netns/README.md create mode 100644 vendor/github.com/vishvananda/netns/go.mod create mode 100644 vendor/github.com/vishvananda/netns/go.sum create mode 100644 vendor/github.com/vishvananda/netns/netns.go create mode 100644 vendor/github.com/vishvananda/netns/netns_linux.go create mode 100644 vendor/github.com/vishvananda/netns/netns_unspecified.go diff --git a/go.mod b/go.mod index 186b94429..038ce1efb 100644 --- a/go.mod +++ b/go.mod @@ -54,6 +54,7 @@ require ( github.com/stretchr/testify v1.7.0 github.com/tchap/go-patricia v2.2.6+incompatible github.com/urfave/cli v1.22.2 + github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5 go.etcd.io/bbolt v1.3.6 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.24.0 go.opentelemetry.io/otel v1.0.1 @@ -71,7 +72,7 @@ require ( k8s.io/apiserver v0.22.0 k8s.io/client-go v0.22.0 k8s.io/component-base v0.22.0 - k8s.io/cri-api v0.22.0 + k8s.io/cri-api v0.23.0-alpha.4 k8s.io/klog/v2 v2.9.0 k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b ) diff --git a/go.sum b/go.sum index 16abf25f8..63cf8a3ae 100644 --- a/go.sum +++ b/go.sum @@ -591,9 +591,11 @@ github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5 h1:+UB2BJA852UkGH42H+Oee69djmxS3ANzl2b/JtT1YiA= github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA= github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= @@ -734,6 +736,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO1APK1CoO39T4BN/XBw= golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -820,6 +823,7 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 h1:7ZDGnxgHAMw7thfC5bEos0RDAccZKxioiWBhfIe+tvw= golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -997,8 +1001,8 @@ k8s.io/client-go v0.22.0/go.mod h1:GUjIuXR5PiEv/RVK5OODUsm6eZk7wtSWZSaSJbpFdGg= k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0= k8s.io/component-base v0.22.0 h1:ZTmX8hUqH9T9gc0mM42O+KDgtwTYbVTt2MwmLP0eK8A= k8s.io/component-base v0.22.0/go.mod h1:SXj6Z+V6P6GsBhHZVbWCw9hFjUdUYnJerlhhPnYCBCg= -k8s.io/cri-api v0.22.0 h1:YECUji0xxCTCWFO/TUkrL1b44Ip6mZJbiqP6Us/+Vys= -k8s.io/cri-api v0.22.0/go.mod h1:mj5DGUtElRyErU5AZ8EM0ahxbElYsaLAMTPhLPQ40Eg= +k8s.io/cri-api v0.23.0-alpha.4 h1:VY9Bxk+254iz5rop9IWorEfVQIzcv8IkUVEwWcvODgM= +k8s.io/cri-api v0.23.0-alpha.4/go.mod h1:qVxNSzR1gwLmZWK61jKRA5NhbyYrNoXUaZpQ7yOUYOQ= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= diff --git a/integration/client/go.sum b/integration/client/go.sum index febe1097c..db7edb275 100644 --- a/integration/client/go.sum +++ b/integration/client/go.sum @@ -687,6 +687,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO1APK1CoO39T4BN/XBw= golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -774,6 +775,7 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 h1:7ZDGnxgHAMw7thfC5bEos0RDAccZKxioiWBhfIe+tvw= golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -943,7 +945,7 @@ k8s.io/client-go v0.22.0/go.mod h1:GUjIuXR5PiEv/RVK5OODUsm6eZk7wtSWZSaSJbpFdGg= k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0= k8s.io/component-base v0.22.0/go.mod h1:SXj6Z+V6P6GsBhHZVbWCw9hFjUdUYnJerlhhPnYCBCg= k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= -k8s.io/cri-api v0.22.0/go.mod h1:mj5DGUtElRyErU5AZ8EM0ahxbElYsaLAMTPhLPQ40Eg= +k8s.io/cri-api v0.23.0-alpha.4/go.mod h1:qVxNSzR1gwLmZWK61jKRA5NhbyYrNoXUaZpQ7yOUYOQ= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= diff --git a/vendor/github.com/vishvananda/netlink/.gitignore b/vendor/github.com/vishvananda/netlink/.gitignore new file mode 100644 index 000000000..9f11b755a --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/.gitignore @@ -0,0 +1 @@ +.idea/ diff --git a/vendor/github.com/vishvananda/netlink/.travis.yml b/vendor/github.com/vishvananda/netlink/.travis.yml new file mode 100644 index 000000000..80219c69d --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/.travis.yml @@ -0,0 +1,20 @@ +language: go +go: + - "1.12.x" + - "1.13.x" + - "1.14.x" +before_script: + # make sure we keep path in tact when we sudo + - sudo sed -i -e 's/^Defaults\tsecure_path.*$//' /etc/sudoers + # modprobe ip_gre or else the first gre device can't be deleted + - sudo modprobe ip_gre + # modprobe nf_conntrack for the conntrack testing + - sudo modprobe nf_conntrack + - sudo modprobe nf_conntrack_netlink + - sudo modprobe nf_conntrack_ipv4 + - sudo modprobe nf_conntrack_ipv6 + - sudo modprobe sch_hfsc + - sudo modprobe sch_sfq +install: + - go get -v -t ./... +go_import_path: github.com/vishvananda/netlink diff --git a/vendor/github.com/vishvananda/netlink/CHANGELOG.md b/vendor/github.com/vishvananda/netlink/CHANGELOG.md new file mode 100644 index 000000000..b11e59ff6 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## 1.0.0 (2018-03-15) + +Initial release tagging \ No newline at end of file diff --git a/vendor/github.com/vishvananda/netlink/LICENSE b/vendor/github.com/vishvananda/netlink/LICENSE new file mode 100644 index 000000000..9f64db858 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/LICENSE @@ -0,0 +1,192 @@ + + 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 + + Copyright 2014 Vishvananda Ishaya. + Copyright 2014 Docker, Inc. + + 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/vishvananda/netlink/Makefile b/vendor/github.com/vishvananda/netlink/Makefile new file mode 100644 index 000000000..a0e68e7a9 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/Makefile @@ -0,0 +1,30 @@ +DIRS := \ + . \ + nl + +DEPS = \ + github.com/vishvananda/netns \ + golang.org/x/sys/unix + +uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1))) +testdirs = $(call uniq,$(foreach d,$(1),$(dir $(wildcard $(d)/*_test.go)))) +goroot = $(addprefix ../../../,$(1)) +unroot = $(subst ../../../,,$(1)) +fmt = $(addprefix fmt-,$(1)) + +all: test + +$(call goroot,$(DEPS)): + go get $(call unroot,$@) + +.PHONY: $(call testdirs,$(DIRS)) +$(call testdirs,$(DIRS)): + go test -test.exec sudo -test.parallel 4 -timeout 60s -test.v github.com/vishvananda/netlink/$@ + +$(call fmt,$(call testdirs,$(DIRS))): + ! gofmt -l $(subst fmt-,,$@)/*.go | grep -q . + +.PHONY: fmt +fmt: $(call fmt,$(call testdirs,$(DIRS))) + +test: fmt $(call goroot,$(DEPS)) $(call testdirs,$(DIRS)) diff --git a/vendor/github.com/vishvananda/netlink/README.md b/vendor/github.com/vishvananda/netlink/README.md new file mode 100644 index 000000000..a88e2f418 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/README.md @@ -0,0 +1,92 @@ +# netlink - netlink library for go # + +[![Build Status](https://travis-ci.org/vishvananda/netlink.png?branch=master)](https://travis-ci.org/vishvananda/netlink) [![GoDoc](https://godoc.org/github.com/vishvananda/netlink?status.svg)](https://godoc.org/github.com/vishvananda/netlink) + +The netlink package provides a simple netlink library for go. Netlink +is the interface a user-space program in linux uses to communicate with +the kernel. It can be used to add and remove interfaces, set ip addresses +and routes, and configure ipsec. Netlink communication requires elevated +privileges, so in most cases this code needs to be run as root. Since +low-level netlink messages are inscrutable at best, the library attempts +to provide an api that is loosely modeled on the CLI provided by iproute2. +Actions like `ip link add` will be accomplished via a similarly named +function like AddLink(). This library began its life as a fork of the +netlink functionality in +[docker/libcontainer](https://github.com/docker/libcontainer) but was +heavily rewritten to improve testability, performance, and to add new +functionality like ipsec xfrm handling. + +## Local Build and Test ## + +You can use go get command: + + go get github.com/vishvananda/netlink + +Testing dependencies: + + go get github.com/vishvananda/netns + +Testing (requires root): + + sudo -E go test github.com/vishvananda/netlink + +## Examples ## + +Add a new bridge and add eth1 into it: + +```go +package main + +import ( + "fmt" + "github.com/vishvananda/netlink" +) + +func main() { + la := netlink.NewLinkAttrs() + la.Name = "foo" + mybridge := &netlink.Bridge{LinkAttrs: la} + err := netlink.LinkAdd(mybridge) + if err != nil { + fmt.Printf("could not add %s: %v\n", la.Name, err) + } + eth1, _ := netlink.LinkByName("eth1") + netlink.LinkSetMaster(eth1, mybridge) +} + +``` +Note `NewLinkAttrs` constructor, it sets default values in structure. For now +it sets only `TxQLen` to `-1`, so kernel will set default by itself. If you're +using simple initialization(`LinkAttrs{Name: "foo"}`) `TxQLen` will be set to +`0` unless you specify it like `LinkAttrs{Name: "foo", TxQLen: 1000}`. + +Add a new ip address to loopback: + +```go +package main + +import ( + "github.com/vishvananda/netlink" +) + +func main() { + lo, _ := netlink.LinkByName("lo") + addr, _ := netlink.ParseAddr("169.254.169.254/32") + netlink.AddrAdd(lo, addr) +} + +``` + +## Future Work ## + +Many pieces of netlink are not yet fully supported in the high-level +interface. Aspects of virtually all of the high-level objects don't exist. +Many of the underlying primitives are there, so its a matter of putting +the right fields into the high-level objects and making sure that they +are serialized and deserialized correctly in the Add and List methods. + +There are also a few pieces of low level netlink functionality that still +need to be implemented. Routing rules are not in place and some of the +more advanced link types. Hopefully there is decent structure and testing +in place to make these fairly straightforward to add. + diff --git a/vendor/github.com/vishvananda/netlink/addr.go b/vendor/github.com/vishvananda/netlink/addr.go new file mode 100644 index 000000000..653f540db --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/addr.go @@ -0,0 +1,57 @@ +package netlink + +import ( + "fmt" + "net" + "strings" +) + +// Addr represents an IP address from netlink. Netlink ip addresses +// include a mask, so it stores the address as a net.IPNet. +type Addr struct { + *net.IPNet + Label string + Flags int + Scope int + Peer *net.IPNet + Broadcast net.IP + PreferedLft int + ValidLft int + LinkIndex int +} + +// String returns $ip/$netmask $label +func (a Addr) String() string { + return strings.TrimSpace(fmt.Sprintf("%s %s", a.IPNet, a.Label)) +} + +// ParseAddr parses the string representation of an address in the +// form $ip/$netmask $label. The label portion is optional +func ParseAddr(s string) (*Addr, error) { + label := "" + parts := strings.Split(s, " ") + if len(parts) > 1 { + s = parts[0] + label = parts[1] + } + m, err := ParseIPNet(s) + if err != nil { + return nil, err + } + return &Addr{IPNet: m, Label: label}, nil +} + +// Equal returns true if both Addrs have the same net.IPNet value. +func (a Addr) Equal(x Addr) bool { + sizea, _ := a.Mask.Size() + sizeb, _ := x.Mask.Size() + // ignore label for comparison + return a.IP.Equal(x.IP) && sizea == sizeb +} + +func (a Addr) PeerEqual(x Addr) bool { + sizea, _ := a.Peer.Mask.Size() + sizeb, _ := x.Peer.Mask.Size() + // ignore label for comparison + return a.Peer.IP.Equal(x.Peer.IP) && sizea == sizeb +} diff --git a/vendor/github.com/vishvananda/netlink/addr_linux.go b/vendor/github.com/vishvananda/netlink/addr_linux.go new file mode 100644 index 000000000..71da251ca --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/addr_linux.go @@ -0,0 +1,414 @@ +package netlink + +import ( + "fmt" + "net" + "strings" + "syscall" + + "github.com/vishvananda/netlink/nl" + "github.com/vishvananda/netns" + "golang.org/x/sys/unix" +) + +// AddrAdd will add an IP address to a link device. +// +// Equivalent to: `ip addr add $addr dev $link` +// +// If `addr` is an IPv4 address and the broadcast address is not given, it +// will be automatically computed based on the IP mask if /30 or larger. +func AddrAdd(link Link, addr *Addr) error { + return pkgHandle.AddrAdd(link, addr) +} + +// AddrAdd will add an IP address to a link device. +// +// Equivalent to: `ip addr add $addr dev $link` +// +// If `addr` is an IPv4 address and the broadcast address is not given, it +// will be automatically computed based on the IP mask if /30 or larger. +func (h *Handle) AddrAdd(link Link, addr *Addr) error { + req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) + return h.addrHandle(link, addr, req) +} + +// AddrReplace will replace (or, if not present, add) an IP address on a link device. +// +// Equivalent to: `ip addr replace $addr dev $link` +// +// If `addr` is an IPv4 address and the broadcast address is not given, it +// will be automatically computed based on the IP mask if /30 or larger. +func AddrReplace(link Link, addr *Addr) error { + return pkgHandle.AddrReplace(link, addr) +} + +// AddrReplace will replace (or, if not present, add) an IP address on a link device. +// +// Equivalent to: `ip addr replace $addr dev $link` +// +// If `addr` is an IPv4 address and the broadcast address is not given, it +// will be automatically computed based on the IP mask if /30 or larger. +func (h *Handle) AddrReplace(link Link, addr *Addr) error { + req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_REPLACE|unix.NLM_F_ACK) + return h.addrHandle(link, addr, req) +} + +// AddrDel will delete an IP address from a link device. +// +// Equivalent to: `ip addr del $addr dev $link` +// +// If `addr` is an IPv4 address and the broadcast address is not given, it +// will be automatically computed based on the IP mask if /30 or larger. +func AddrDel(link Link, addr *Addr) error { + return pkgHandle.AddrDel(link, addr) +} + +// AddrDel will delete an IP address from a link device. +// Equivalent to: `ip addr del $addr dev $link` +// +// If `addr` is an IPv4 address and the broadcast address is not given, it +// will be automatically computed based on the IP mask if /30 or larger. +func (h *Handle) AddrDel(link Link, addr *Addr) error { + req := h.newNetlinkRequest(unix.RTM_DELADDR, unix.NLM_F_ACK) + return h.addrHandle(link, addr, req) +} + +func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error { + base := link.Attrs() + if addr.Label != "" && !strings.HasPrefix(addr.Label, base.Name) { + return fmt.Errorf("label must begin with interface name") + } + h.ensureIndex(base) + + family := nl.GetIPFamily(addr.IP) + + msg := nl.NewIfAddrmsg(family) + msg.Index = uint32(base.Index) + msg.Scope = uint8(addr.Scope) + mask := addr.Mask + if addr.Peer != nil { + mask = addr.Peer.Mask + } + prefixlen, masklen := mask.Size() + msg.Prefixlen = uint8(prefixlen) + req.AddData(msg) + + var localAddrData []byte + if family == FAMILY_V4 { + localAddrData = addr.IP.To4() + } else { + localAddrData = addr.IP.To16() + } + + localData := nl.NewRtAttr(unix.IFA_LOCAL, localAddrData) + req.AddData(localData) + var peerAddrData []byte + if addr.Peer != nil { + if family == FAMILY_V4 { + peerAddrData = addr.Peer.IP.To4() + } else { + peerAddrData = addr.Peer.IP.To16() + } + } else { + peerAddrData = localAddrData + } + + addressData := nl.NewRtAttr(unix.IFA_ADDRESS, peerAddrData) + req.AddData(addressData) + + if addr.Flags != 0 { + if addr.Flags <= 0xff { + msg.IfAddrmsg.Flags = uint8(addr.Flags) + } else { + b := make([]byte, 4) + native.PutUint32(b, uint32(addr.Flags)) + flagsData := nl.NewRtAttr(unix.IFA_FLAGS, b) + req.AddData(flagsData) + } + } + + if family == FAMILY_V4 { + // Automatically set the broadcast address if it is unset and the + // subnet is large enough to sensibly have one (/30 or larger). + // See: RFC 3021 + if addr.Broadcast == nil && prefixlen < 31 { + calcBroadcast := make(net.IP, masklen/8) + for i := range localAddrData { + calcBroadcast[i] = localAddrData[i] | ^mask[i] + } + addr.Broadcast = calcBroadcast + } + + if addr.Broadcast != nil { + req.AddData(nl.NewRtAttr(unix.IFA_BROADCAST, addr.Broadcast)) + } + + if addr.Label != "" { + labelData := nl.NewRtAttr(unix.IFA_LABEL, nl.ZeroTerminated(addr.Label)) + req.AddData(labelData) + } + } + + // 0 is the default value for these attributes. However, 0 means "expired", while the least-surprising default + // value should be "forever". To compensate for that, only add the attributes if at least one of the values is + // non-zero, which means the caller has explicitly set them + if addr.ValidLft > 0 || addr.PreferedLft > 0 { + cachedata := nl.IfaCacheInfo{unix.IfaCacheinfo{ + Valid: uint32(addr.ValidLft), + Prefered: uint32(addr.PreferedLft), + }} + req.AddData(nl.NewRtAttr(unix.IFA_CACHEINFO, cachedata.Serialize())) + } + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// AddrList gets a list of IP addresses in the system. +// Equivalent to: `ip addr show`. +// The list can be filtered by link and ip family. +func AddrList(link Link, family int) ([]Addr, error) { + return pkgHandle.AddrList(link, family) +} + +// AddrList gets a list of IP addresses in the system. +// Equivalent to: `ip addr show`. +// The list can be filtered by link and ip family. +func (h *Handle) AddrList(link Link, family int) ([]Addr, error) { + req := h.newNetlinkRequest(unix.RTM_GETADDR, unix.NLM_F_DUMP) + msg := nl.NewIfInfomsg(family) + req.AddData(msg) + + msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWADDR) + if err != nil { + return nil, err + } + + indexFilter := 0 + if link != nil { + base := link.Attrs() + h.ensureIndex(base) + indexFilter = base.Index + } + + var res []Addr + for _, m := range msgs { + addr, msgFamily, err := parseAddr(m) + if err != nil { + return res, err + } + + if link != nil && addr.LinkIndex != indexFilter { + // Ignore messages from other interfaces + continue + } + + if family != FAMILY_ALL && msgFamily != family { + continue + } + + res = append(res, addr) + } + + return res, nil +} + +func parseAddr(m []byte) (addr Addr, family int, err error) { + msg := nl.DeserializeIfAddrmsg(m) + + family = -1 + addr.LinkIndex = -1 + + attrs, err1 := nl.ParseRouteAttr(m[msg.Len():]) + if err1 != nil { + err = err1 + return + } + + family = int(msg.Family) + addr.LinkIndex = int(msg.Index) + + var local, dst *net.IPNet + for _, attr := range attrs { + switch attr.Attr.Type { + case unix.IFA_ADDRESS: + dst = &net.IPNet{ + IP: attr.Value, + Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)), + } + case unix.IFA_LOCAL: + // iproute2 manual: + // If a peer address is specified, the local address + // cannot have a prefix length. The network prefix is + // associated with the peer rather than with the local + // address. + n := 8 * len(attr.Value) + local = &net.IPNet{ + IP: attr.Value, + Mask: net.CIDRMask(n, n), + } + case unix.IFA_BROADCAST: + addr.Broadcast = attr.Value + case unix.IFA_LABEL: + addr.Label = string(attr.Value[:len(attr.Value)-1]) + case unix.IFA_FLAGS: + addr.Flags = int(native.Uint32(attr.Value[0:4])) + case unix.IFA_CACHEINFO: + ci := nl.DeserializeIfaCacheInfo(attr.Value) + addr.PreferedLft = int(ci.Prefered) + addr.ValidLft = int(ci.Valid) + } + } + + // libnl addr.c comment: + // IPv6 sends the local address as IFA_ADDRESS with no + // IFA_LOCAL, IPv4 sends both IFA_LOCAL and IFA_ADDRESS + // with IFA_ADDRESS being the peer address if they differ + // + // But obviously, as there are IPv6 PtP addresses, too, + // IFA_LOCAL should also be handled for IPv6. + if local != nil { + if family == FAMILY_V4 && local.IP.Equal(dst.IP) { + addr.IPNet = dst + } else { + addr.IPNet = local + addr.Peer = dst + } + } else { + addr.IPNet = dst + } + + addr.Scope = int(msg.Scope) + + return +} + +type AddrUpdate struct { + LinkAddress net.IPNet + LinkIndex int + Flags int + Scope int + PreferedLft int + ValidLft int + NewAddr bool // true=added false=deleted +} + +// AddrSubscribe takes a chan down which notifications will be sent +// when addresses change. Close the 'done' chan to stop subscription. +func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error { + return addrSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0) +} + +// AddrSubscribeAt works like AddrSubscribe plus it allows the caller +// to choose the network namespace in which to subscribe (ns). +func AddrSubscribeAt(ns netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error { + return addrSubscribeAt(ns, netns.None(), ch, done, nil, false, 0) +} + +// AddrSubscribeOptions contains a set of options to use with +// AddrSubscribeWithOptions. +type AddrSubscribeOptions struct { + Namespace *netns.NsHandle + ErrorCallback func(error) + ListExisting bool + ReceiveBufferSize int +} + +// AddrSubscribeWithOptions work like AddrSubscribe but enable to +// provide additional options to modify the behavior. Currently, the +// namespace can be provided as well as an error callback. +func AddrSubscribeWithOptions(ch chan<- AddrUpdate, done <-chan struct{}, options AddrSubscribeOptions) error { + if options.Namespace == nil { + none := netns.None() + options.Namespace = &none + } + return addrSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting, options.ReceiveBufferSize) +} + +func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}, cberr func(error), listExisting bool, rcvbuf int) error { + s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_IFADDR, unix.RTNLGRP_IPV6_IFADDR) + if err != nil { + return err + } + if done != nil { + go func() { + <-done + s.Close() + }() + } + if rcvbuf != 0 { + err = pkgHandle.SetSocketReceiveBufferSize(rcvbuf, false) + if err != nil { + return err + } + } + if listExisting { + req := pkgHandle.newNetlinkRequest(unix.RTM_GETADDR, + unix.NLM_F_DUMP) + infmsg := nl.NewIfInfomsg(unix.AF_UNSPEC) + req.AddData(infmsg) + if err := s.Send(req); err != nil { + return err + } + } + go func() { + defer close(ch) + for { + msgs, from, err := s.Receive() + if err != nil { + if cberr != nil { + cberr(err) + } + return + } + if from.Pid != nl.PidKernel { + if cberr != nil { + cberr(fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)) + } + continue + } + for _, m := range msgs { + if m.Header.Type == unix.NLMSG_DONE { + continue + } + if m.Header.Type == unix.NLMSG_ERROR { + native := nl.NativeEndian() + error := int32(native.Uint32(m.Data[0:4])) + if error == 0 { + continue + } + if cberr != nil { + cberr(fmt.Errorf("error message: %v", + syscall.Errno(-error))) + } + continue + } + msgType := m.Header.Type + if msgType != unix.RTM_NEWADDR && msgType != unix.RTM_DELADDR { + if cberr != nil { + cberr(fmt.Errorf("bad message type: %d", msgType)) + } + continue + } + + addr, _, err := parseAddr(m.Data) + if err != nil { + if cberr != nil { + cberr(fmt.Errorf("could not parse address: %v", err)) + } + continue + } + + ch <- AddrUpdate{LinkAddress: *addr.IPNet, + LinkIndex: addr.LinkIndex, + NewAddr: msgType == unix.RTM_NEWADDR, + Flags: addr.Flags, + Scope: addr.Scope, + PreferedLft: addr.PreferedLft, + ValidLft: addr.ValidLft} + } + } + }() + + return nil +} diff --git a/vendor/github.com/vishvananda/netlink/bpf_linux.go b/vendor/github.com/vishvananda/netlink/bpf_linux.go new file mode 100644 index 000000000..6631626bf --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/bpf_linux.go @@ -0,0 +1,53 @@ +package netlink + +import ( + "unsafe" + + "golang.org/x/sys/unix" +) + +type BpfProgType uint32 + +const ( + BPF_PROG_TYPE_UNSPEC BpfProgType = iota + BPF_PROG_TYPE_SOCKET_FILTER + BPF_PROG_TYPE_KPROBE + BPF_PROG_TYPE_SCHED_CLS + BPF_PROG_TYPE_SCHED_ACT + BPF_PROG_TYPE_TRACEPOINT + BPF_PROG_TYPE_XDP +) + +type BPFAttr struct { + ProgType uint32 + InsnCnt uint32 + Insns uintptr + License uintptr + LogLevel uint32 + LogSize uint32 + LogBuf uintptr + KernVersion uint32 +} + +// loadSimpleBpf loads a trivial bpf program for testing purposes. +func loadSimpleBpf(progType BpfProgType, ret uint32) (int, error) { + insns := []uint64{ + 0x00000000000000b7 | (uint64(ret) << 32), + 0x0000000000000095, + } + license := []byte{'A', 'S', 'L', '2', '\x00'} + attr := BPFAttr{ + ProgType: uint32(progType), + InsnCnt: uint32(len(insns)), + Insns: uintptr(unsafe.Pointer(&insns[0])), + License: uintptr(unsafe.Pointer(&license[0])), + } + fd, _, errno := unix.Syscall(unix.SYS_BPF, + 5, /* bpf cmd */ + uintptr(unsafe.Pointer(&attr)), + unsafe.Sizeof(attr)) + if errno != 0 { + return 0, errno + } + return int(fd), nil +} diff --git a/vendor/github.com/vishvananda/netlink/bridge_linux.go b/vendor/github.com/vishvananda/netlink/bridge_linux.go new file mode 100644 index 000000000..6e1224c47 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/bridge_linux.go @@ -0,0 +1,112 @@ +package netlink + +import ( + "fmt" + + "github.com/vishvananda/netlink/nl" + "golang.org/x/sys/unix" +) + +// BridgeVlanList gets a map of device id to bridge vlan infos. +// Equivalent to: `bridge vlan show` +func BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) { + return pkgHandle.BridgeVlanList() +} + +// BridgeVlanList gets a map of device id to bridge vlan infos. +// Equivalent to: `bridge vlan show` +func (h *Handle) BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) { + req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP) + msg := nl.NewIfInfomsg(unix.AF_BRIDGE) + req.AddData(msg) + req.AddData(nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(uint32(nl.RTEXT_FILTER_BRVLAN)))) + + msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWLINK) + if err != nil { + return nil, err + } + ret := make(map[int32][]*nl.BridgeVlanInfo) + for _, m := range msgs { + msg := nl.DeserializeIfInfomsg(m) + + attrs, err := nl.ParseRouteAttr(m[msg.Len():]) + if err != nil { + return nil, err + } + for _, attr := range attrs { + switch attr.Attr.Type { + case unix.IFLA_AF_SPEC: + //nested attr + nestAttrs, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return nil, fmt.Errorf("failed to parse nested attr %v", err) + } + for _, nestAttr := range nestAttrs { + switch nestAttr.Attr.Type { + case nl.IFLA_BRIDGE_VLAN_INFO: + vlanInfo := nl.DeserializeBridgeVlanInfo(nestAttr.Value) + ret[msg.Index] = append(ret[msg.Index], vlanInfo) + } + } + } + } + } + return ret, nil +} + +// BridgeVlanAdd adds a new vlan filter entry +// Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]` +func BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) error { + return pkgHandle.BridgeVlanAdd(link, vid, pvid, untagged, self, master) +} + +// BridgeVlanAdd adds a new vlan filter entry +// Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]` +func (h *Handle) BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) error { + return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, pvid, untagged, self, master) +} + +// BridgeVlanDel adds a new vlan filter entry +// Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]` +func BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) error { + return pkgHandle.BridgeVlanDel(link, vid, pvid, untagged, self, master) +} + +// BridgeVlanDel adds a new vlan filter entry +// Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]` +func (h *Handle) BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) error { + return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, pvid, untagged, self, master) +} + +func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged, self, master bool) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(cmd, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_BRIDGE) + msg.Index = int32(base.Index) + req.AddData(msg) + + br := nl.NewRtAttr(unix.IFLA_AF_SPEC, nil) + var flags uint16 + if self { + flags |= nl.BRIDGE_FLAGS_SELF + } + if master { + flags |= nl.BRIDGE_FLAGS_MASTER + } + if flags > 0 { + br.AddRtAttr(nl.IFLA_BRIDGE_FLAGS, nl.Uint16Attr(flags)) + } + vlanInfo := &nl.BridgeVlanInfo{Vid: vid} + if pvid { + vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_PVID + } + if untagged { + vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_UNTAGGED + } + br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize()) + req.AddData(br) + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} diff --git a/vendor/github.com/vishvananda/netlink/class.go b/vendor/github.com/vishvananda/netlink/class.go new file mode 100644 index 000000000..10ceffed8 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/class.go @@ -0,0 +1,239 @@ +package netlink + +import ( + "fmt" +) + +// Class interfaces for all classes +type Class interface { + Attrs() *ClassAttrs + Type() string +} + +// Generic networking statistics for netlink users. +// This file contains "gnet_" prefixed structs and relevant functions. +// See Documentation/networking/getn_stats.txt in Linux source code for more details. + +// GnetStatsBasic Ref: struct gnet_stats_basic { ... } +type GnetStatsBasic struct { + Bytes uint64 // number of seen bytes + Packets uint32 // number of seen packets +} + +// GnetStatsRateEst Ref: struct gnet_stats_rate_est { ... } +type GnetStatsRateEst struct { + Bps uint32 // current byte rate + Pps uint32 // current packet rate +} + +// GnetStatsRateEst64 Ref: struct gnet_stats_rate_est64 { ... } +type GnetStatsRateEst64 struct { + Bps uint64 // current byte rate + Pps uint64 // current packet rate +} + +// GnetStatsQueue Ref: struct gnet_stats_queue { ... } +type GnetStatsQueue struct { + Qlen uint32 // queue length + Backlog uint32 // backlog size of queue + Drops uint32 // number of dropped packets + Requeues uint32 // number of requues + Overlimits uint32 // number of enqueues over the limit +} + +// ClassStatistics representation based on generic networking statistics for netlink. +// See Documentation/networking/gen_stats.txt in Linux source code for more details. +type ClassStatistics struct { + Basic *GnetStatsBasic + Queue *GnetStatsQueue + RateEst *GnetStatsRateEst +} + +// NewClassStatistics Construct a ClassStatistics struct which fields are all initialized by 0. +func NewClassStatistics() *ClassStatistics { + return &ClassStatistics{ + Basic: &GnetStatsBasic{}, + Queue: &GnetStatsQueue{}, + RateEst: &GnetStatsRateEst{}, + } +} + +// ClassAttrs represents a netlink class. A filter is associated with a link, +// has a handle and a parent. The root filter of a device should have a +// parent == HANDLE_ROOT. +type ClassAttrs struct { + LinkIndex int + Handle uint32 + Parent uint32 + Leaf uint32 + Statistics *ClassStatistics +} + +func (q ClassAttrs) String() string { + return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Leaf: %d}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Leaf) +} + +// HtbClassAttrs stores the attributes of HTB class +type HtbClassAttrs struct { + // TODO handle all attributes + Rate uint64 + Ceil uint64 + Buffer uint32 + Cbuffer uint32 + Quantum uint32 + Level uint32 + Prio uint32 +} + +func (q HtbClassAttrs) String() string { + return fmt.Sprintf("{Rate: %d, Ceil: %d, Buffer: %d, Cbuffer: %d}", q.Rate, q.Ceil, q.Buffer, q.Cbuffer) +} + +// HtbClass represents an Htb class +type HtbClass struct { + ClassAttrs + Rate uint64 + Ceil uint64 + Buffer uint32 + Cbuffer uint32 + Quantum uint32 + Level uint32 + Prio uint32 +} + +func (q HtbClass) String() string { + return fmt.Sprintf("{Rate: %d, Ceil: %d, Buffer: %d, Cbuffer: %d}", q.Rate, q.Ceil, q.Buffer, q.Cbuffer) +} + +// Attrs returns the class attributes +func (q *HtbClass) Attrs() *ClassAttrs { + return &q.ClassAttrs +} + +// Type return the class type +func (q *HtbClass) Type() string { + return "htb" +} + +// GenericClass classes represent types that are not currently understood +// by this netlink library. +type GenericClass struct { + ClassAttrs + ClassType string +} + +// Attrs return the class attributes +func (class *GenericClass) Attrs() *ClassAttrs { + return &class.ClassAttrs +} + +// Type return the class type +func (class *GenericClass) Type() string { + return class.ClassType +} + +// ServiceCurve is a nondecreasing function of some time unit, returning the amount of service +// (an allowed or allocated amount of bandwidth) at some specific point in time. The purpose of it +// should be subconsciously obvious: if a class was allowed to transfer not less than the amount +// specified by its service curve, then the service curve is not violated. +type ServiceCurve struct { + m1 uint32 + d uint32 + m2 uint32 +} + +// Attrs return the parameters of the service curve +func (c *ServiceCurve) Attrs() (uint32, uint32, uint32) { + return c.m1, c.d, c.m2 +} + +// Burst returns the burst rate (m1) of the curve +func (c *ServiceCurve) Burst() uint32 { + return c.m1 +} + +// Delay return the delay (d) of the curve +func (c *ServiceCurve) Delay() uint32 { + return c.d +} + +// Rate returns the rate (m2) of the curve +func (c *ServiceCurve) Rate() uint32 { + return c.m2 +} + +// HfscClass is a representation of the HFSC class +type HfscClass struct { + ClassAttrs + Rsc ServiceCurve + Fsc ServiceCurve + Usc ServiceCurve +} + +// SetUsc sets the USC curve. The bandwidth (m1 and m2) is specified in bits and the delay in +// seconds. +func (hfsc *HfscClass) SetUsc(m1 uint32, d uint32, m2 uint32) { + hfsc.Usc = ServiceCurve{m1: m1, d: d, m2: m2} +} + +// SetFsc sets the Fsc curve. The bandwidth (m1 and m2) is specified in bits and the delay in +// seconds. +func (hfsc *HfscClass) SetFsc(m1 uint32, d uint32, m2 uint32) { + hfsc.Fsc = ServiceCurve{m1: m1, d: d, m2: m2} +} + +// SetRsc sets the Rsc curve. The bandwidth (m1 and m2) is specified in bits and the delay in +// seconds. +func (hfsc *HfscClass) SetRsc(m1 uint32, d uint32, m2 uint32) { + hfsc.Rsc = ServiceCurve{m1: m1, d: d, m2: m2} +} + +// SetSC implements the SC from the `tc` CLI. This function behaves the same as if one would set the +// USC through the `tc` command-line tool. This means bandwidth (m1 and m2) is specified in bits and +// the delay in ms. +func (hfsc *HfscClass) SetSC(m1 uint32, d uint32, m2 uint32) { + hfsc.SetRsc(m1, d, m2) + hfsc.SetFsc(m1, d, m2) +} + +// SetUL implements the UL from the `tc` CLI. This function behaves the same as if one would set the +// USC through the `tc` command-line tool. This means bandwidth (m1 and m2) is specified in bits and +// the delay in ms. +func (hfsc *HfscClass) SetUL(m1 uint32, d uint32, m2 uint32) { + hfsc.SetUsc(m1, d, m2) +} + +// SetLS implements the LS from the `tc` CLI. This function behaves the same as if one would set the +// USC through the `tc` command-line tool. This means bandwidth (m1 and m2) is specified in bits and +// the delay in ms. +func (hfsc *HfscClass) SetLS(m1 uint32, d uint32, m2 uint32) { + hfsc.SetFsc(m1, d, m2) +} + +// NewHfscClass returns a new HFSC struct with the set parameters +func NewHfscClass(attrs ClassAttrs) *HfscClass { + return &HfscClass{ + ClassAttrs: attrs, + Rsc: ServiceCurve{}, + Fsc: ServiceCurve{}, + Usc: ServiceCurve{}, + } +} + +// String() returns a string that contains the information and attributes of the HFSC class +func (hfsc *HfscClass) String() string { + return fmt.Sprintf( + "{%s -- {RSC: {m1=%d d=%d m2=%d}} {FSC: {m1=%d d=%d m2=%d}} {USC: {m1=%d d=%d m2=%d}}}", + hfsc.Attrs(), hfsc.Rsc.m1*8, hfsc.Rsc.d, hfsc.Rsc.m2*8, hfsc.Fsc.m1*8, hfsc.Fsc.d, hfsc.Fsc.m2*8, hfsc.Usc.m1*8, hfsc.Usc.d, hfsc.Usc.m2*8, + ) +} + +// Attrs return the Hfsc parameters +func (hfsc *HfscClass) Attrs() *ClassAttrs { + return &hfsc.ClassAttrs +} + +// Type return the type of the class +func (hfsc *HfscClass) Type() string { + return "hfsc" +} diff --git a/vendor/github.com/vishvananda/netlink/class_linux.go b/vendor/github.com/vishvananda/netlink/class_linux.go new file mode 100644 index 000000000..029568a3f --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/class_linux.go @@ -0,0 +1,397 @@ +package netlink + +import ( + "bytes" + "encoding/binary" + "encoding/hex" + "errors" + "fmt" + "syscall" + + "github.com/vishvananda/netlink/nl" + "golang.org/x/sys/unix" +) + +// Internal tc_stats representation in Go struct. +// This is for internal uses only to deserialize the payload of rtattr. +// After the deserialization, this should be converted into the canonical stats +// struct, ClassStatistics, in case of statistics of a class. +// Ref: struct tc_stats { ... } +type tcStats struct { + Bytes uint64 // Number of enqueued bytes + Packets uint32 // Number of enqueued packets + Drops uint32 // Packets dropped because of lack of resources + Overlimits uint32 // Number of throttle events when this flow goes out of allocated bandwidth + Bps uint32 // Current flow byte rate + Pps uint32 // Current flow packet rate + Qlen uint32 + Backlog uint32 +} + +// NewHtbClass NOTE: function is in here because it uses other linux functions +func NewHtbClass(attrs ClassAttrs, cattrs HtbClassAttrs) *HtbClass { + mtu := 1600 + rate := cattrs.Rate / 8 + ceil := cattrs.Ceil / 8 + buffer := cattrs.Buffer + cbuffer := cattrs.Cbuffer + + if ceil == 0 { + ceil = rate + } + + if buffer == 0 { + buffer = uint32(float64(rate)/Hz() + float64(mtu)) + } + buffer = Xmittime(rate, buffer) + + if cbuffer == 0 { + cbuffer = uint32(float64(ceil)/Hz() + float64(mtu)) + } + cbuffer = Xmittime(ceil, cbuffer) + + return &HtbClass{ + ClassAttrs: attrs, + Rate: rate, + Ceil: ceil, + Buffer: buffer, + Cbuffer: cbuffer, + Level: 0, + Prio: cattrs.Prio, + Quantum: cattrs.Quantum, + } +} + +// ClassDel will delete a class from the system. +// Equivalent to: `tc class del $class` +func ClassDel(class Class) error { + return pkgHandle.ClassDel(class) +} + +// ClassDel will delete a class from the system. +// Equivalent to: `tc class del $class` +func (h *Handle) ClassDel(class Class) error { + return h.classModify(unix.RTM_DELTCLASS, 0, class) +} + +// ClassChange will change a class in place +// Equivalent to: `tc class change $class` +// The parent and handle MUST NOT be changed. +func ClassChange(class Class) error { + return pkgHandle.ClassChange(class) +} + +// ClassChange will change a class in place +// Equivalent to: `tc class change $class` +// The parent and handle MUST NOT be changed. +func (h *Handle) ClassChange(class Class) error { + return h.classModify(unix.RTM_NEWTCLASS, 0, class) +} + +// ClassReplace will replace a class to the system. +// quivalent to: `tc class replace $class` +// The handle MAY be changed. +// If a class already exist with this parent/handle pair, the class is changed. +// If a class does not already exist with this parent/handle, a new class is created. +func ClassReplace(class Class) error { + return pkgHandle.ClassReplace(class) +} + +// ClassReplace will replace a class to the system. +// quivalent to: `tc class replace $class` +// The handle MAY be changed. +// If a class already exist with this parent/handle pair, the class is changed. +// If a class does not already exist with this parent/handle, a new class is created. +func (h *Handle) ClassReplace(class Class) error { + return h.classModify(unix.RTM_NEWTCLASS, unix.NLM_F_CREATE, class) +} + +// ClassAdd will add a class to the system. +// Equivalent to: `tc class add $class` +func ClassAdd(class Class) error { + return pkgHandle.ClassAdd(class) +} + +// ClassAdd will add a class to the system. +// Equivalent to: `tc class add $class` +func (h *Handle) ClassAdd(class Class) error { + return h.classModify( + unix.RTM_NEWTCLASS, + unix.NLM_F_CREATE|unix.NLM_F_EXCL, + class, + ) +} + +func (h *Handle) classModify(cmd, flags int, class Class) error { + req := h.newNetlinkRequest(cmd, flags|unix.NLM_F_ACK) + base := class.Attrs() + msg := &nl.TcMsg{ + Family: nl.FAMILY_ALL, + Ifindex: int32(base.LinkIndex), + Handle: base.Handle, + Parent: base.Parent, + } + req.AddData(msg) + + if cmd != unix.RTM_DELTCLASS { + if err := classPayload(req, class); err != nil { + return err + } + } + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +func classPayload(req *nl.NetlinkRequest, class Class) error { + req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(class.Type()))) + + options := nl.NewRtAttr(nl.TCA_OPTIONS, nil) + switch class.Type() { + case "htb": + htb := class.(*HtbClass) + opt := nl.TcHtbCopt{} + opt.Buffer = htb.Buffer + opt.Cbuffer = htb.Cbuffer + opt.Quantum = htb.Quantum + opt.Level = htb.Level + opt.Prio = htb.Prio + // TODO: Handle Debug properly. For now default to 0 + /* Calculate {R,C}Tab and set Rate and Ceil */ + cellLog := -1 + ccellLog := -1 + linklayer := nl.LINKLAYER_ETHERNET + mtu := 1600 + var rtab [256]uint32 + var ctab [256]uint32 + tcrate := nl.TcRateSpec{Rate: uint32(htb.Rate)} + if CalcRtable(&tcrate, rtab[:], cellLog, uint32(mtu), linklayer) < 0 { + return errors.New("HTB: failed to calculate rate table") + } + opt.Rate = tcrate + tcceil := nl.TcRateSpec{Rate: uint32(htb.Ceil)} + if CalcRtable(&tcceil, ctab[:], ccellLog, uint32(mtu), linklayer) < 0 { + return errors.New("HTB: failed to calculate ceil rate table") + } + opt.Ceil = tcceil + options.AddRtAttr(nl.TCA_HTB_PARMS, opt.Serialize()) + options.AddRtAttr(nl.TCA_HTB_RTAB, SerializeRtab(rtab)) + options.AddRtAttr(nl.TCA_HTB_CTAB, SerializeRtab(ctab)) + if htb.Rate >= uint64(1<<32) { + options.AddRtAttr(nl.TCA_HTB_RATE64, nl.Uint64Attr(htb.Rate)) + } + if htb.Ceil >= uint64(1<<32) { + options.AddRtAttr(nl.TCA_HTB_CEIL64, nl.Uint64Attr(htb.Ceil)) + } + case "hfsc": + hfsc := class.(*HfscClass) + opt := nl.HfscCopt{} + rm1, rd, rm2 := hfsc.Rsc.Attrs() + opt.Rsc.Set(rm1/8, rd, rm2/8) + fm1, fd, fm2 := hfsc.Fsc.Attrs() + opt.Fsc.Set(fm1/8, fd, fm2/8) + um1, ud, um2 := hfsc.Usc.Attrs() + opt.Usc.Set(um1/8, ud, um2/8) + nl.NewRtAttrChild(options, nl.TCA_HFSC_RSC, nl.SerializeHfscCurve(&opt.Rsc)) + nl.NewRtAttrChild(options, nl.TCA_HFSC_FSC, nl.SerializeHfscCurve(&opt.Fsc)) + nl.NewRtAttrChild(options, nl.TCA_HFSC_USC, nl.SerializeHfscCurve(&opt.Usc)) + } + req.AddData(options) + return nil +} + +// ClassList gets a list of classes in the system. +// Equivalent to: `tc class show`. +// Generally returns nothing if link and parent are not specified. +func ClassList(link Link, parent uint32) ([]Class, error) { + return pkgHandle.ClassList(link, parent) +} + +// ClassList gets a list of classes in the system. +// Equivalent to: `tc class show`. +// Generally returns nothing if link and parent are not specified. +func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) { + req := h.newNetlinkRequest(unix.RTM_GETTCLASS, unix.NLM_F_DUMP) + msg := &nl.TcMsg{ + Family: nl.FAMILY_ALL, + Parent: parent, + } + if link != nil { + base := link.Attrs() + h.ensureIndex(base) + msg.Ifindex = int32(base.Index) + } + req.AddData(msg) + + msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWTCLASS) + if err != nil { + return nil, err + } + + var res []Class + for _, m := range msgs { + msg := nl.DeserializeTcMsg(m) + + attrs, err := nl.ParseRouteAttr(m[msg.Len():]) + if err != nil { + return nil, err + } + + base := ClassAttrs{ + LinkIndex: int(msg.Ifindex), + Handle: msg.Handle, + Parent: msg.Parent, + Statistics: nil, + } + + var class Class + classType := "" + for _, attr := range attrs { + switch attr.Attr.Type { + case nl.TCA_KIND: + classType = string(attr.Value[:len(attr.Value)-1]) + switch classType { + case "htb": + class = &HtbClass{} + case "hfsc": + class = &HfscClass{} + default: + class = &GenericClass{ClassType: classType} + } + case nl.TCA_OPTIONS: + switch classType { + case "htb": + data, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return nil, err + } + _, err = parseHtbClassData(class, data) + if err != nil { + return nil, err + } + case "hfsc": + data, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return nil, err + } + _, err = parseHfscClassData(class, data) + if err != nil { + return nil, err + } + } + // For backward compatibility. + case nl.TCA_STATS: + base.Statistics, err = parseTcStats(attr.Value) + if err != nil { + return nil, err + } + case nl.TCA_STATS2: + base.Statistics, err = parseTcStats2(attr.Value) + if err != nil { + return nil, err + } + } + } + *class.Attrs() = base + res = append(res, class) + } + + return res, nil +} + +func parseHtbClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, error) { + htb := class.(*HtbClass) + detailed := false + for _, datum := range data { + switch datum.Attr.Type { + case nl.TCA_HTB_PARMS: + opt := nl.DeserializeTcHtbCopt(datum.Value) + htb.Rate = uint64(opt.Rate.Rate) + htb.Ceil = uint64(opt.Ceil.Rate) + htb.Buffer = opt.Buffer + htb.Cbuffer = opt.Cbuffer + htb.Quantum = opt.Quantum + htb.Level = opt.Level + htb.Prio = opt.Prio + case nl.TCA_HTB_RATE64: + htb.Rate = native.Uint64(datum.Value[0:8]) + case nl.TCA_HTB_CEIL64: + htb.Ceil = native.Uint64(datum.Value[0:8]) + } + } + return detailed, nil +} + +func parseHfscClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, error) { + hfsc := class.(*HfscClass) + detailed := false + for _, datum := range data { + m1, d, m2 := nl.DeserializeHfscCurve(datum.Value).Attrs() + switch datum.Attr.Type { + case nl.TCA_HFSC_RSC: + hfsc.Rsc = ServiceCurve{m1: m1 * 8, d: d, m2: m2 * 8} + case nl.TCA_HFSC_FSC: + hfsc.Fsc = ServiceCurve{m1: m1 * 8, d: d, m2: m2 * 8} + case nl.TCA_HFSC_USC: + hfsc.Usc = ServiceCurve{m1: m1 * 8, d: d, m2: m2 * 8} + } + } + return detailed, nil +} + +func parseTcStats(data []byte) (*ClassStatistics, error) { + buf := &bytes.Buffer{} + buf.Write(data) + native := nl.NativeEndian() + tcStats := &tcStats{} + if err := binary.Read(buf, native, tcStats); err != nil { + return nil, err + } + + stats := NewClassStatistics() + stats.Basic.Bytes = tcStats.Bytes + stats.Basic.Packets = tcStats.Packets + stats.Queue.Qlen = tcStats.Qlen + stats.Queue.Backlog = tcStats.Backlog + stats.Queue.Drops = tcStats.Drops + stats.Queue.Overlimits = tcStats.Overlimits + stats.RateEst.Bps = tcStats.Bps + stats.RateEst.Pps = tcStats.Pps + + return stats, nil +} + +func parseGnetStats(data []byte, gnetStats interface{}) error { + buf := &bytes.Buffer{} + buf.Write(data) + native := nl.NativeEndian() + return binary.Read(buf, native, gnetStats) +} + +func parseTcStats2(data []byte) (*ClassStatistics, error) { + rtAttrs, err := nl.ParseRouteAttr(data) + if err != nil { + return nil, err + } + stats := NewClassStatistics() + for _, datum := range rtAttrs { + switch datum.Attr.Type { + case nl.TCA_STATS_BASIC: + if err := parseGnetStats(datum.Value, stats.Basic); err != nil { + return nil, fmt.Errorf("Failed to parse ClassStatistics.Basic with: %v\n%s", + err, hex.Dump(datum.Value)) + } + case nl.TCA_STATS_QUEUE: + if err := parseGnetStats(datum.Value, stats.Queue); err != nil { + return nil, fmt.Errorf("Failed to parse ClassStatistics.Queue with: %v\n%s", + err, hex.Dump(datum.Value)) + } + case nl.TCA_STATS_RATE_EST: + if err := parseGnetStats(datum.Value, stats.RateEst); err != nil { + return nil, fmt.Errorf("Failed to parse ClassStatistics.RateEst with: %v\n%s", + err, hex.Dump(datum.Value)) + } + } + } + + return stats, nil +} diff --git a/vendor/github.com/vishvananda/netlink/conntrack_linux.go b/vendor/github.com/vishvananda/netlink/conntrack_linux.go new file mode 100644 index 000000000..ab91f4e55 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/conntrack_linux.go @@ -0,0 +1,454 @@ +package netlink + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "net" + + "github.com/vishvananda/netlink/nl" + "golang.org/x/sys/unix" +) + +// ConntrackTableType Conntrack table for the netlink operation +type ConntrackTableType uint8 + +const ( + // ConntrackTable Conntrack table + // https://github.com/torvalds/linux/blob/master/include/uapi/linux/netfilter/nfnetlink.h -> #define NFNL_SUBSYS_CTNETLINK 1 + ConntrackTable = 1 + // ConntrackExpectTable Conntrack expect table + // https://github.com/torvalds/linux/blob/master/include/uapi/linux/netfilter/nfnetlink.h -> #define NFNL_SUBSYS_CTNETLINK_EXP 2 + ConntrackExpectTable = 2 +) + +const ( + // backward compatibility with golang 1.6 which does not have io.SeekCurrent + seekCurrent = 1 +) + +// InetFamily Family type +type InetFamily uint8 + +// -L [table] [options] List conntrack or expectation table +// -G [table] parameters Get conntrack or expectation + +// -I [table] parameters Create a conntrack or expectation +// -U [table] parameters Update a conntrack +// -E [table] [options] Show events + +// -C [table] Show counter +// -S Show statistics + +// ConntrackTableList returns the flow list of a table of a specific family +// conntrack -L [table] [options] List conntrack or expectation table +func ConntrackTableList(table ConntrackTableType, family InetFamily) ([]*ConntrackFlow, error) { + return pkgHandle.ConntrackTableList(table, family) +} + +// ConntrackTableFlush flushes all the flows of a specified table +// conntrack -F [table] Flush table +// The flush operation applies to all the family types +func ConntrackTableFlush(table ConntrackTableType) error { + return pkgHandle.ConntrackTableFlush(table) +} + +// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter +// conntrack -D [table] parameters Delete conntrack or expectation +func ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter CustomConntrackFilter) (uint, error) { + return pkgHandle.ConntrackDeleteFilter(table, family, filter) +} + +// ConntrackTableList returns the flow list of a table of a specific family using the netlink handle passed +// conntrack -L [table] [options] List conntrack or expectation table +func (h *Handle) ConntrackTableList(table ConntrackTableType, family InetFamily) ([]*ConntrackFlow, error) { + res, err := h.dumpConntrackTable(table, family) + if err != nil { + return nil, err + } + + // Deserialize all the flows + var result []*ConntrackFlow + for _, dataRaw := range res { + result = append(result, parseRawData(dataRaw)) + } + + return result, nil +} + +// ConntrackTableFlush flushes all the flows of a specified table using the netlink handle passed +// conntrack -F [table] Flush table +// The flush operation applies to all the family types +func (h *Handle) ConntrackTableFlush(table ConntrackTableType) error { + req := h.newConntrackRequest(table, unix.AF_INET, nl.IPCTNL_MSG_CT_DELETE, unix.NLM_F_ACK) + _, err := req.Execute(unix.NETLINK_NETFILTER, 0) + return err +} + +// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter using the netlink handle passed +// conntrack -D [table] parameters Delete conntrack or expectation +func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter CustomConntrackFilter) (uint, error) { + res, err := h.dumpConntrackTable(table, family) + if err != nil { + return 0, err + } + + var matched uint + for _, dataRaw := range res { + flow := parseRawData(dataRaw) + if match := filter.MatchConntrackFlow(flow); match { + req2 := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_DELETE, unix.NLM_F_ACK) + // skip the first 4 byte that are the netfilter header, the newConntrackRequest is adding it already + req2.AddRawData(dataRaw[4:]) + req2.Execute(unix.NETLINK_NETFILTER, 0) + matched++ + } + } + + return matched, nil +} + +func (h *Handle) newConntrackRequest(table ConntrackTableType, family InetFamily, operation, flags int) *nl.NetlinkRequest { + // Create the Netlink request object + req := h.newNetlinkRequest((int(table)<<8)|operation, flags) + // Add the netfilter header + msg := &nl.Nfgenmsg{ + NfgenFamily: uint8(family), + Version: nl.NFNETLINK_V0, + ResId: 0, + } + req.AddData(msg) + return req +} + +func (h *Handle) dumpConntrackTable(table ConntrackTableType, family InetFamily) ([][]byte, error) { + req := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_GET, unix.NLM_F_DUMP) + return req.Execute(unix.NETLINK_NETFILTER, 0) +} + +// The full conntrack flow structure is very complicated and can be found in the file: +// http://git.netfilter.org/libnetfilter_conntrack/tree/include/internal/object.h +// For the time being, the structure below allows to parse and extract the base information of a flow +type ipTuple struct { + Bytes uint64 + DstIP net.IP + DstPort uint16 + Packets uint64 + Protocol uint8 + SrcIP net.IP + SrcPort uint16 +} + +type ConntrackFlow struct { + FamilyType uint8 + Forward ipTuple + Reverse ipTuple + Mark uint32 +} + +func (s *ConntrackFlow) String() string { + // conntrack cmd output: + // udp 17 src=127.0.0.1 dst=127.0.0.1 sport=4001 dport=1234 packets=5 bytes=532 [UNREPLIED] src=127.0.0.1 dst=127.0.0.1 sport=1234 dport=4001 packets=10 bytes=1078 mark=0 + return fmt.Sprintf("%s\t%d src=%s dst=%s sport=%d dport=%d packets=%d bytes=%d\tsrc=%s dst=%s sport=%d dport=%d packets=%d bytes=%d mark=%d", + nl.L4ProtoMap[s.Forward.Protocol], s.Forward.Protocol, + s.Forward.SrcIP.String(), s.Forward.DstIP.String(), s.Forward.SrcPort, s.Forward.DstPort, s.Forward.Packets, s.Forward.Bytes, + s.Reverse.SrcIP.String(), s.Reverse.DstIP.String(), s.Reverse.SrcPort, s.Reverse.DstPort, s.Reverse.Packets, s.Reverse.Bytes, + s.Mark) +} + +// This method parse the ip tuple structure +// The message structure is the following: +// +// +// +// +// +func parseIpTuple(reader *bytes.Reader, tpl *ipTuple) uint8 { + for i := 0; i < 2; i++ { + _, t, _, v := parseNfAttrTLV(reader) + switch t { + case nl.CTA_IP_V4_SRC, nl.CTA_IP_V6_SRC: + tpl.SrcIP = v + case nl.CTA_IP_V4_DST, nl.CTA_IP_V6_DST: + tpl.DstIP = v + } + } + // Skip the next 4 bytes nl.NLA_F_NESTED|nl.CTA_TUPLE_PROTO + reader.Seek(4, seekCurrent) + _, t, _, v := parseNfAttrTLV(reader) + if t == nl.CTA_PROTO_NUM { + tpl.Protocol = uint8(v[0]) + } + // Skip some padding 3 bytes + reader.Seek(3, seekCurrent) + for i := 0; i < 2; i++ { + _, t, _ := parseNfAttrTL(reader) + switch t { + case nl.CTA_PROTO_SRC_PORT: + parseBERaw16(reader, &tpl.SrcPort) + case nl.CTA_PROTO_DST_PORT: + parseBERaw16(reader, &tpl.DstPort) + } + // Skip some padding 2 byte + reader.Seek(2, seekCurrent) + } + return tpl.Protocol +} + +func parseNfAttrTLV(r *bytes.Reader) (isNested bool, attrType, len uint16, value []byte) { + isNested, attrType, len = parseNfAttrTL(r) + + value = make([]byte, len) + binary.Read(r, binary.BigEndian, &value) + return isNested, attrType, len, value +} + +func parseNfAttrTL(r *bytes.Reader) (isNested bool, attrType, len uint16) { + binary.Read(r, nl.NativeEndian(), &len) + len -= nl.SizeofNfattr + + binary.Read(r, nl.NativeEndian(), &attrType) + isNested = (attrType & nl.NLA_F_NESTED) == nl.NLA_F_NESTED + attrType = attrType & (nl.NLA_F_NESTED - 1) + + return isNested, attrType, len +} + +func parseBERaw16(r *bytes.Reader, v *uint16) { + binary.Read(r, binary.BigEndian, v) +} + +func parseBERaw32(r *bytes.Reader, v *uint32) { + binary.Read(r, binary.BigEndian, v) +} + +func parseBERaw64(r *bytes.Reader, v *uint64) { + binary.Read(r, binary.BigEndian, v) +} + +func parseByteAndPacketCounters(r *bytes.Reader) (bytes, packets uint64) { + for i := 0; i < 2; i++ { + switch _, t, _ := parseNfAttrTL(r); t { + case nl.CTA_COUNTERS_BYTES: + parseBERaw64(r, &bytes) + case nl.CTA_COUNTERS_PACKETS: + parseBERaw64(r, &packets) + default: + return + } + } + return +} + +func parseConnectionMark(r *bytes.Reader) (mark uint32) { + parseBERaw32(r, &mark) + return +} + +func parseRawData(data []byte) *ConntrackFlow { + s := &ConntrackFlow{} + // First there is the Nfgenmsg header + // consume only the family field + reader := bytes.NewReader(data) + binary.Read(reader, nl.NativeEndian(), &s.FamilyType) + + // skip rest of the Netfilter header + reader.Seek(3, seekCurrent) + // The message structure is the following: + // 4 bytes + // 4 bytes + // flow information of the forward flow + // 4 bytes + // 4 bytes + // flow information of the reverse flow + for reader.Len() > 0 { + if nested, t, l := parseNfAttrTL(reader); nested { + switch t { + case nl.CTA_TUPLE_ORIG: + if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP { + parseIpTuple(reader, &s.Forward) + } + case nl.CTA_TUPLE_REPLY: + if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP { + parseIpTuple(reader, &s.Reverse) + } else { + // Header not recognized skip it + reader.Seek(int64(l), seekCurrent) + } + case nl.CTA_COUNTERS_ORIG: + s.Forward.Bytes, s.Forward.Packets = parseByteAndPacketCounters(reader) + case nl.CTA_COUNTERS_REPLY: + s.Reverse.Bytes, s.Reverse.Packets = parseByteAndPacketCounters(reader) + } + } else { + switch t { + case nl.CTA_MARK: + s.Mark = parseConnectionMark(reader) + } + } + } + return s +} + +// Conntrack parameters and options: +// -n, --src-nat ip source NAT ip +// -g, --dst-nat ip destination NAT ip +// -j, --any-nat ip source or destination NAT ip +// -m, --mark mark Set mark +// -c, --secmark secmark Set selinux secmark +// -e, --event-mask eventmask Event mask, eg. NEW,DESTROY +// -z, --zero Zero counters while listing +// -o, --output type[,...] Output format, eg. xml +// -l, --label label[,...] conntrack labels + +// Common parameters and options: +// -s, --src, --orig-src ip Source address from original direction +// -d, --dst, --orig-dst ip Destination address from original direction +// -r, --reply-src ip Source address from reply direction +// -q, --reply-dst ip Destination address from reply direction +// -p, --protonum proto Layer 4 Protocol, eg. 'tcp' +// -f, --family proto Layer 3 Protocol, eg. 'ipv6' +// -t, --timeout timeout Set timeout +// -u, --status status Set status, eg. ASSURED +// -w, --zone value Set conntrack zone +// --orig-zone value Set zone for original direction +// --reply-zone value Set zone for reply direction +// -b, --buffer-size Netlink socket buffer size +// --mask-src ip Source mask address +// --mask-dst ip Destination mask address + +// Layer 4 Protocol common parameters and options: +// TCP, UDP, SCTP, UDPLite and DCCP +// --sport, --orig-port-src port Source port in original direction +// --dport, --orig-port-dst port Destination port in original direction + +// Filter types +type ConntrackFilterType uint8 + +const ( + ConntrackOrigSrcIP = iota // -orig-src ip Source address from original direction + ConntrackOrigDstIP // -orig-dst ip Destination address from original direction + ConntrackReplySrcIP // --reply-src ip Reply Source IP + ConntrackReplyDstIP // --reply-dst ip Reply Destination IP + ConntrackReplyAnyIP // Match source or destination reply IP + ConntrackOrigSrcPort // --orig-port-src port Source port in original direction + ConntrackOrigDstPort // --orig-port-dst port Destination port in original direction + ConntrackNatSrcIP = ConntrackReplySrcIP // deprecated use instead ConntrackReplySrcIP + ConntrackNatDstIP = ConntrackReplyDstIP // deprecated use instead ConntrackReplyDstIP + ConntrackNatAnyIP = ConntrackReplyAnyIP // deprecated use instead ConntrackReplyAnyIP +) + +type CustomConntrackFilter interface { + // MatchConntrackFlow applies the filter to the flow and returns true if the flow matches + // the filter or false otherwise + MatchConntrackFlow(flow *ConntrackFlow) bool +} + +type ConntrackFilter struct { + ipFilter map[ConntrackFilterType]net.IP + portFilter map[ConntrackFilterType]uint16 + protoFilter uint8 +} + +// AddIP adds an IP to the conntrack filter +func (f *ConntrackFilter) AddIP(tp ConntrackFilterType, ip net.IP) error { + if f.ipFilter == nil { + f.ipFilter = make(map[ConntrackFilterType]net.IP) + } + if _, ok := f.ipFilter[tp]; ok { + return errors.New("Filter attribute already present") + } + f.ipFilter[tp] = ip + return nil +} + +// AddPort adds a Port to the conntrack filter if the Layer 4 protocol allows it +func (f *ConntrackFilter) AddPort(tp ConntrackFilterType, port uint16) error { + switch f.protoFilter { + // TCP, UDP, DCCP, SCTP, UDPLite + case 6, 17, 33, 132, 136: + default: + return fmt.Errorf("Filter attribute not available without a valid Layer 4 protocol: %d", f.protoFilter) + } + + if f.portFilter == nil { + f.portFilter = make(map[ConntrackFilterType]uint16) + } + if _, ok := f.portFilter[tp]; ok { + return errors.New("Filter attribute already present") + } + f.portFilter[tp] = port + return nil +} + +// AddProtocol adds the Layer 4 protocol to the conntrack filter +func (f *ConntrackFilter) AddProtocol(proto uint8) error { + if f.protoFilter != 0 { + return errors.New("Filter attribute already present") + } + f.protoFilter = proto + return nil +} + +// MatchConntrackFlow applies the filter to the flow and returns true if the flow matches the filter +// false otherwise +func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool { + if len(f.ipFilter) == 0 && len(f.portFilter) == 0 && f.protoFilter == 0 { + // empty filter always not match + return false + } + + // -p, --protonum proto Layer 4 Protocol, eg. 'tcp' + if f.protoFilter != 0 && flow.Forward.Protocol != f.protoFilter { + // different Layer 4 protocol always not match + return false + } + + match := true + + // IP conntrack filter + if len(f.ipFilter) > 0 { + // -orig-src ip Source address from original direction + if elem, found := f.ipFilter[ConntrackOrigSrcIP]; found { + match = match && elem.Equal(flow.Forward.SrcIP) + } + + // -orig-dst ip Destination address from original direction + if elem, found := f.ipFilter[ConntrackOrigDstIP]; match && found { + match = match && elem.Equal(flow.Forward.DstIP) + } + + // -src-nat ip Source NAT ip + if elem, found := f.ipFilter[ConntrackReplySrcIP]; match && found { + match = match && elem.Equal(flow.Reverse.SrcIP) + } + + // -dst-nat ip Destination NAT ip + if elem, found := f.ipFilter[ConntrackReplyDstIP]; match && found { + match = match && elem.Equal(flow.Reverse.DstIP) + } + + // Match source or destination reply IP + if elem, found := f.ipFilter[ConntrackReplyAnyIP]; match && found { + match = match && (elem.Equal(flow.Reverse.SrcIP) || elem.Equal(flow.Reverse.DstIP)) + } + } + + // Layer 4 Port filter + if len(f.portFilter) > 0 { + // -orig-port-src port Source port from original direction + if elem, found := f.portFilter[ConntrackOrigSrcPort]; match && found { + match = match && elem == flow.Forward.SrcPort + } + + // -orig-port-dst port Destination port from original direction + if elem, found := f.portFilter[ConntrackOrigDstPort]; match && found { + match = match && elem == flow.Forward.DstPort + } + } + + return match +} + +var _ CustomConntrackFilter = (*ConntrackFilter)(nil) diff --git a/vendor/github.com/vishvananda/netlink/conntrack_unspecified.go b/vendor/github.com/vishvananda/netlink/conntrack_unspecified.go new file mode 100644 index 000000000..af7af799e --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/conntrack_unspecified.go @@ -0,0 +1,53 @@ +// +build !linux + +package netlink + +// ConntrackTableType Conntrack table for the netlink operation +type ConntrackTableType uint8 + +// InetFamily Family type +type InetFamily uint8 + +// ConntrackFlow placeholder +type ConntrackFlow struct{} + +// ConntrackFilter placeholder +type ConntrackFilter struct{} + +// ConntrackTableList returns the flow list of a table of a specific family +// conntrack -L [table] [options] List conntrack or expectation table +func ConntrackTableList(table ConntrackTableType, family InetFamily) ([]*ConntrackFlow, error) { + return nil, ErrNotImplemented +} + +// ConntrackTableFlush flushes all the flows of a specified table +// conntrack -F [table] Flush table +// The flush operation applies to all the family types +func ConntrackTableFlush(table ConntrackTableType) error { + return ErrNotImplemented +} + +// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter +// conntrack -D [table] parameters Delete conntrack or expectation +func ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter *ConntrackFilter) (uint, error) { + return 0, ErrNotImplemented +} + +// ConntrackTableList returns the flow list of a table of a specific family using the netlink handle passed +// conntrack -L [table] [options] List conntrack or expectation table +func (h *Handle) ConntrackTableList(table ConntrackTableType, family InetFamily) ([]*ConntrackFlow, error) { + return nil, ErrNotImplemented +} + +// ConntrackTableFlush flushes all the flows of a specified table using the netlink handle passed +// conntrack -F [table] Flush table +// The flush operation applies to all the family types +func (h *Handle) ConntrackTableFlush(table ConntrackTableType) error { + return ErrNotImplemented +} + +// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter using the netlink handle passed +// conntrack -D [table] parameters Delete conntrack or expectation +func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter *ConntrackFilter) (uint, error) { + return 0, ErrNotImplemented +} diff --git a/vendor/github.com/vishvananda/netlink/devlink_linux.go b/vendor/github.com/vishvananda/netlink/devlink_linux.go new file mode 100644 index 000000000..7d57080e8 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/devlink_linux.go @@ -0,0 +1,393 @@ +package netlink + +import ( + "syscall" + + "fmt" + "github.com/vishvananda/netlink/nl" + "golang.org/x/sys/unix" +) + +// DevlinkDevEswitchAttr represents device's eswitch attributes +type DevlinkDevEswitchAttr struct { + Mode string + InlineMode string + EncapMode string +} + +// DevlinkDevAttrs represents device attributes +type DevlinkDevAttrs struct { + Eswitch DevlinkDevEswitchAttr +} + +// DevlinkDevice represents device and its attributes +type DevlinkDevice struct { + BusName string + DeviceName string + Attrs DevlinkDevAttrs +} + +// DevlinkPort represents port and its attributes +type DevlinkPort struct { + BusName string + DeviceName string + PortIndex uint32 + PortType uint16 + NetdeviceName string + NetdevIfIndex uint32 + RdmaDeviceName string + PortFlavour uint16 +} + +func parseDevLinkDeviceList(msgs [][]byte) ([]*DevlinkDevice, error) { + devices := make([]*DevlinkDevice, 0, len(msgs)) + for _, m := range msgs { + attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:]) + if err != nil { + return nil, err + } + dev := &DevlinkDevice{} + if err = dev.parseAttributes(attrs); err != nil { + return nil, err + } + devices = append(devices, dev) + } + return devices, nil +} + +func eswitchStringToMode(modeName string) (uint16, error) { + if modeName == "legacy" { + return nl.DEVLINK_ESWITCH_MODE_LEGACY, nil + } else if modeName == "switchdev" { + return nl.DEVLINK_ESWITCH_MODE_SWITCHDEV, nil + } else { + return 0xffff, fmt.Errorf("invalid switchdev mode") + } +} + +func parseEswitchMode(mode uint16) string { + var eswitchMode = map[uint16]string{ + nl.DEVLINK_ESWITCH_MODE_LEGACY: "legacy", + nl.DEVLINK_ESWITCH_MODE_SWITCHDEV: "switchdev", + } + if eswitchMode[mode] == "" { + return "unknown" + } else { + return eswitchMode[mode] + } +} + +func parseEswitchInlineMode(inlinemode uint8) string { + var eswitchInlineMode = map[uint8]string{ + nl.DEVLINK_ESWITCH_INLINE_MODE_NONE: "none", + nl.DEVLINK_ESWITCH_INLINE_MODE_LINK: "link", + nl.DEVLINK_ESWITCH_INLINE_MODE_NETWORK: "network", + nl.DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT: "transport", + } + if eswitchInlineMode[inlinemode] == "" { + return "unknown" + } else { + return eswitchInlineMode[inlinemode] + } +} + +func parseEswitchEncapMode(encapmode uint8) string { + var eswitchEncapMode = map[uint8]string{ + nl.DEVLINK_ESWITCH_ENCAP_MODE_NONE: "disable", + nl.DEVLINK_ESWITCH_ENCAP_MODE_BASIC: "enable", + } + if eswitchEncapMode[encapmode] == "" { + return "unknown" + } else { + return eswitchEncapMode[encapmode] + } +} + +func (d *DevlinkDevice) parseAttributes(attrs []syscall.NetlinkRouteAttr) error { + for _, a := range attrs { + switch a.Attr.Type { + case nl.DEVLINK_ATTR_BUS_NAME: + d.BusName = string(a.Value) + case nl.DEVLINK_ATTR_DEV_NAME: + d.DeviceName = string(a.Value) + case nl.DEVLINK_ATTR_ESWITCH_MODE: + d.Attrs.Eswitch.Mode = parseEswitchMode(native.Uint16(a.Value)) + case nl.DEVLINK_ATTR_ESWITCH_INLINE_MODE: + d.Attrs.Eswitch.InlineMode = parseEswitchInlineMode(uint8(a.Value[0])) + case nl.DEVLINK_ATTR_ESWITCH_ENCAP_MODE: + d.Attrs.Eswitch.EncapMode = parseEswitchEncapMode(uint8(a.Value[0])) + } + } + return nil +} + +func (dev *DevlinkDevice) parseEswitchAttrs(msgs [][]byte) { + m := msgs[0] + attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:]) + if err != nil { + return + } + dev.parseAttributes(attrs) +} + +func (h *Handle) getEswitchAttrs(family *GenlFamily, dev *DevlinkDevice) { + msg := &nl.Genlmsg{ + Command: nl.DEVLINK_CMD_ESWITCH_GET, + Version: nl.GENL_DEVLINK_VERSION, + } + req := h.newNetlinkRequest(int(family.ID), unix.NLM_F_REQUEST|unix.NLM_F_ACK) + req.AddData(msg) + + b := make([]byte, len(dev.BusName)) + copy(b, dev.BusName) + data := nl.NewRtAttr(nl.DEVLINK_ATTR_BUS_NAME, b) + req.AddData(data) + + b = make([]byte, len(dev.DeviceName)) + copy(b, dev.DeviceName) + data = nl.NewRtAttr(nl.DEVLINK_ATTR_DEV_NAME, b) + req.AddData(data) + + msgs, err := req.Execute(unix.NETLINK_GENERIC, 0) + if err != nil { + return + } + dev.parseEswitchAttrs(msgs) +} + +// DevLinkGetDeviceList provides a pointer to devlink devices and nil error, +// otherwise returns an error code. +func (h *Handle) DevLinkGetDeviceList() ([]*DevlinkDevice, error) { + f, err := h.GenlFamilyGet(nl.GENL_DEVLINK_NAME) + if err != nil { + return nil, err + } + msg := &nl.Genlmsg{ + Command: nl.DEVLINK_CMD_GET, + Version: nl.GENL_DEVLINK_VERSION, + } + req := h.newNetlinkRequest(int(f.ID), + unix.NLM_F_REQUEST|unix.NLM_F_ACK|unix.NLM_F_DUMP) + req.AddData(msg) + msgs, err := req.Execute(unix.NETLINK_GENERIC, 0) + if err != nil { + return nil, err + } + devices, err := parseDevLinkDeviceList(msgs) + if err != nil { + return nil, err + } + for _, d := range devices { + h.getEswitchAttrs(f, d) + } + return devices, nil +} + +// DevLinkGetDeviceList provides a pointer to devlink devices and nil error, +// otherwise returns an error code. +func DevLinkGetDeviceList() ([]*DevlinkDevice, error) { + return pkgHandle.DevLinkGetDeviceList() +} + +func parseDevlinkDevice(msgs [][]byte) (*DevlinkDevice, error) { + m := msgs[0] + attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:]) + if err != nil { + return nil, err + } + dev := &DevlinkDevice{} + if err = dev.parseAttributes(attrs); err != nil { + return nil, err + } + return dev, nil +} + +func (h *Handle) createCmdReq(cmd uint8, bus string, device string) (*GenlFamily, *nl.NetlinkRequest, error) { + f, err := h.GenlFamilyGet(nl.GENL_DEVLINK_NAME) + if err != nil { + return nil, nil, err + } + + msg := &nl.Genlmsg{ + Command: cmd, + Version: nl.GENL_DEVLINK_VERSION, + } + req := h.newNetlinkRequest(int(f.ID), + unix.NLM_F_REQUEST|unix.NLM_F_ACK) + req.AddData(msg) + + b := make([]byte, len(bus)+1) + copy(b, bus) + data := nl.NewRtAttr(nl.DEVLINK_ATTR_BUS_NAME, b) + req.AddData(data) + + b = make([]byte, len(device)+1) + copy(b, device) + data = nl.NewRtAttr(nl.DEVLINK_ATTR_DEV_NAME, b) + req.AddData(data) + + return f, req, nil +} + +// DevlinkGetDeviceByName provides a pointer to devlink device and nil error, +// otherwise returns an error code. +func (h *Handle) DevLinkGetDeviceByName(Bus string, Device string) (*DevlinkDevice, error) { + f, req, err := h.createCmdReq(nl.DEVLINK_CMD_GET, Bus, Device) + if err != nil { + return nil, err + } + + respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0) + if err != nil { + return nil, err + } + dev, err := parseDevlinkDevice(respmsg) + if err == nil { + h.getEswitchAttrs(f, dev) + } + return dev, err +} + +// DevlinkGetDeviceByName provides a pointer to devlink device and nil error, +// otherwise returns an error code. +func DevLinkGetDeviceByName(Bus string, Device string) (*DevlinkDevice, error) { + return pkgHandle.DevLinkGetDeviceByName(Bus, Device) +} + +// DevLinkSetEswitchMode sets eswitch mode if able to set successfully or +// returns an error code. +// Equivalent to: `devlink dev eswitch set $dev mode switchdev` +// Equivalent to: `devlink dev eswitch set $dev mode legacy` +func (h *Handle) DevLinkSetEswitchMode(Dev *DevlinkDevice, NewMode string) error { + mode, err := eswitchStringToMode(NewMode) + if err != nil { + return err + } + + _, req, err := h.createCmdReq(nl.DEVLINK_CMD_ESWITCH_SET, Dev.BusName, Dev.DeviceName) + if err != nil { + return err + } + + req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_ESWITCH_MODE, nl.Uint16Attr(mode))) + + _, err = req.Execute(unix.NETLINK_GENERIC, 0) + return err +} + +// DevLinkSetEswitchMode sets eswitch mode if able to set successfully or +// returns an error code. +// Equivalent to: `devlink dev eswitch set $dev mode switchdev` +// Equivalent to: `devlink dev eswitch set $dev mode legacy` +func DevLinkSetEswitchMode(Dev *DevlinkDevice, NewMode string) error { + return pkgHandle.DevLinkSetEswitchMode(Dev, NewMode) +} + +func (port *DevlinkPort) parseAttributes(attrs []syscall.NetlinkRouteAttr) error { + for _, a := range attrs { + switch a.Attr.Type { + case nl.DEVLINK_ATTR_BUS_NAME: + port.BusName = string(a.Value) + case nl.DEVLINK_ATTR_DEV_NAME: + port.DeviceName = string(a.Value) + case nl.DEVLINK_ATTR_PORT_INDEX: + port.PortIndex = native.Uint32(a.Value) + case nl.DEVLINK_ATTR_PORT_TYPE: + port.PortType = native.Uint16(a.Value) + case nl.DEVLINK_ATTR_PORT_NETDEV_NAME: + port.NetdeviceName = string(a.Value) + case nl.DEVLINK_ATTR_PORT_NETDEV_IFINDEX: + port.NetdevIfIndex = native.Uint32(a.Value) + case nl.DEVLINK_ATTR_PORT_IBDEV_NAME: + port.RdmaDeviceName = string(a.Value) + case nl.DEVLINK_ATTR_PORT_FLAVOUR: + port.PortFlavour = native.Uint16(a.Value) + } + } + return nil +} + +func parseDevLinkAllPortList(msgs [][]byte) ([]*DevlinkPort, error) { + ports := make([]*DevlinkPort, 0, len(msgs)) + for _, m := range msgs { + attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:]) + if err != nil { + return nil, err + } + port := &DevlinkPort{} + if err = port.parseAttributes(attrs); err != nil { + return nil, err + } + ports = append(ports, port) + } + return ports, nil +} + +// DevLinkGetPortList provides a pointer to devlink ports and nil error, +// otherwise returns an error code. +func (h *Handle) DevLinkGetAllPortList() ([]*DevlinkPort, error) { + f, err := h.GenlFamilyGet(nl.GENL_DEVLINK_NAME) + if err != nil { + return nil, err + } + msg := &nl.Genlmsg{ + Command: nl.DEVLINK_CMD_PORT_GET, + Version: nl.GENL_DEVLINK_VERSION, + } + req := h.newNetlinkRequest(int(f.ID), + unix.NLM_F_REQUEST|unix.NLM_F_ACK|unix.NLM_F_DUMP) + req.AddData(msg) + msgs, err := req.Execute(unix.NETLINK_GENERIC, 0) + if err != nil { + return nil, err + } + ports, err := parseDevLinkAllPortList(msgs) + if err != nil { + return nil, err + } + return ports, nil +} + +// DevLinkGetPortList provides a pointer to devlink ports and nil error, +// otherwise returns an error code. +func DevLinkGetAllPortList() ([]*DevlinkPort, error) { + return pkgHandle.DevLinkGetAllPortList() +} + +func parseDevlinkPortMsg(msgs [][]byte) (*DevlinkPort, error) { + m := msgs[0] + attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:]) + if err != nil { + return nil, err + } + port := &DevlinkPort{} + if err = port.parseAttributes(attrs); err != nil { + return nil, err + } + return port, nil +} + +// DevLinkGetPortByIndexprovides a pointer to devlink device and nil error, +// otherwise returns an error code. +func (h *Handle) DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint32) (*DevlinkPort, error) { + + _, req, err := h.createCmdReq(nl.DEVLINK_CMD_PORT_GET, Bus, Device) + if err != nil { + return nil, err + } + + req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_INDEX, nl.Uint32Attr(PortIndex))) + + respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0) + if err != nil { + return nil, err + } + port, err := parseDevlinkPortMsg(respmsg) + return port, err +} + +// DevLinkGetPortByIndex provides a pointer to devlink portand nil error, +// otherwise returns an error code. +func DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint32) (*DevlinkPort, error) { + return pkgHandle.DevLinkGetPortByIndex(Bus, Device, PortIndex) +} diff --git a/vendor/github.com/vishvananda/netlink/filter.go b/vendor/github.com/vishvananda/netlink/filter.go new file mode 100644 index 000000000..2dc34b995 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/filter.go @@ -0,0 +1,325 @@ +package netlink + +import ( + "fmt" + "net" +) + +type Filter interface { + Attrs() *FilterAttrs + Type() string +} + +// FilterAttrs represents a netlink filter. A filter is associated with a link, +// has a handle and a parent. The root filter of a device should have a +// parent == HANDLE_ROOT. +type FilterAttrs struct { + LinkIndex int + Handle uint32 + Parent uint32 + Priority uint16 // lower is higher priority + Protocol uint16 // unix.ETH_P_* +} + +func (q FilterAttrs) String() string { + return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Priority: %d, Protocol: %d}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Priority, q.Protocol) +} + +type TcAct int32 + +const ( + TC_ACT_UNSPEC TcAct = -1 + TC_ACT_OK TcAct = 0 + TC_ACT_RECLASSIFY TcAct = 1 + TC_ACT_SHOT TcAct = 2 + TC_ACT_PIPE TcAct = 3 + TC_ACT_STOLEN TcAct = 4 + TC_ACT_QUEUED TcAct = 5 + TC_ACT_REPEAT TcAct = 6 + TC_ACT_REDIRECT TcAct = 7 + TC_ACT_JUMP TcAct = 0x10000000 +) + +func (a TcAct) String() string { + switch a { + case TC_ACT_UNSPEC: + return "unspec" + case TC_ACT_OK: + return "ok" + case TC_ACT_RECLASSIFY: + return "reclassify" + case TC_ACT_SHOT: + return "shot" + case TC_ACT_PIPE: + return "pipe" + case TC_ACT_STOLEN: + return "stolen" + case TC_ACT_QUEUED: + return "queued" + case TC_ACT_REPEAT: + return "repeat" + case TC_ACT_REDIRECT: + return "redirect" + case TC_ACT_JUMP: + return "jump" + } + return fmt.Sprintf("0x%x", int32(a)) +} + +type TcPolAct int32 + +const ( + TC_POLICE_UNSPEC TcPolAct = TcPolAct(TC_ACT_UNSPEC) + TC_POLICE_OK TcPolAct = TcPolAct(TC_ACT_OK) + TC_POLICE_RECLASSIFY TcPolAct = TcPolAct(TC_ACT_RECLASSIFY) + TC_POLICE_SHOT TcPolAct = TcPolAct(TC_ACT_SHOT) + TC_POLICE_PIPE TcPolAct = TcPolAct(TC_ACT_PIPE) +) + +func (a TcPolAct) String() string { + switch a { + case TC_POLICE_UNSPEC: + return "unspec" + case TC_POLICE_OK: + return "ok" + case TC_POLICE_RECLASSIFY: + return "reclassify" + case TC_POLICE_SHOT: + return "shot" + case TC_POLICE_PIPE: + return "pipe" + } + return fmt.Sprintf("0x%x", int32(a)) +} + +type ActionAttrs struct { + Index int + Capab int + Action TcAct + Refcnt int + Bindcnt int +} + +func (q ActionAttrs) String() string { + return fmt.Sprintf("{Index: %d, Capab: %x, Action: %s, Refcnt: %d, Bindcnt: %d}", q.Index, q.Capab, q.Action.String(), q.Refcnt, q.Bindcnt) +} + +// Action represents an action in any supported filter. +type Action interface { + Attrs() *ActionAttrs + Type() string +} + +type GenericAction struct { + ActionAttrs +} + +func (action *GenericAction) Type() string { + return "generic" +} + +func (action *GenericAction) Attrs() *ActionAttrs { + return &action.ActionAttrs +} + +type BpfAction struct { + ActionAttrs + Fd int + Name string +} + +func (action *BpfAction) Type() string { + return "bpf" +} + +func (action *BpfAction) Attrs() *ActionAttrs { + return &action.ActionAttrs +} + +type ConnmarkAction struct { + ActionAttrs + Zone uint16 +} + +func (action *ConnmarkAction) Type() string { + return "connmark" +} + +func (action *ConnmarkAction) Attrs() *ActionAttrs { + return &action.ActionAttrs +} + +func NewConnmarkAction() *ConnmarkAction { + return &ConnmarkAction{ + ActionAttrs: ActionAttrs{ + Action: TC_ACT_PIPE, + }, + } +} + +type MirredAct uint8 + +func (a MirredAct) String() string { + switch a { + case TCA_EGRESS_REDIR: + return "egress redir" + case TCA_EGRESS_MIRROR: + return "egress mirror" + case TCA_INGRESS_REDIR: + return "ingress redir" + case TCA_INGRESS_MIRROR: + return "ingress mirror" + } + return "unknown" +} + +const ( + TCA_EGRESS_REDIR MirredAct = 1 /* packet redirect to EGRESS*/ + TCA_EGRESS_MIRROR MirredAct = 2 /* mirror packet to EGRESS */ + TCA_INGRESS_REDIR MirredAct = 3 /* packet redirect to INGRESS*/ + TCA_INGRESS_MIRROR MirredAct = 4 /* mirror packet to INGRESS */ +) + +type MirredAction struct { + ActionAttrs + MirredAction MirredAct + Ifindex int +} + +func (action *MirredAction) Type() string { + return "mirred" +} + +func (action *MirredAction) Attrs() *ActionAttrs { + return &action.ActionAttrs +} + +func NewMirredAction(redirIndex int) *MirredAction { + return &MirredAction{ + ActionAttrs: ActionAttrs{ + Action: TC_ACT_STOLEN, + }, + MirredAction: TCA_EGRESS_REDIR, + Ifindex: redirIndex, + } +} + +type TunnelKeyAct int8 + +const ( + TCA_TUNNEL_KEY_SET TunnelKeyAct = 1 // set tunnel key + TCA_TUNNEL_KEY_UNSET TunnelKeyAct = 2 // unset tunnel key +) + +type TunnelKeyAction struct { + ActionAttrs + Action TunnelKeyAct + SrcAddr net.IP + DstAddr net.IP + KeyID uint32 + DestPort uint16 +} + +func (action *TunnelKeyAction) Type() string { + return "tunnel_key" +} + +func (action *TunnelKeyAction) Attrs() *ActionAttrs { + return &action.ActionAttrs +} + +func NewTunnelKeyAction() *TunnelKeyAction { + return &TunnelKeyAction{ + ActionAttrs: ActionAttrs{ + Action: TC_ACT_PIPE, + }, + } +} + +type SkbEditAction struct { + ActionAttrs + QueueMapping *uint16 + PType *uint16 + Priority *uint32 + Mark *uint32 +} + +func (action *SkbEditAction) Type() string { + return "skbedit" +} + +func (action *SkbEditAction) Attrs() *ActionAttrs { + return &action.ActionAttrs +} + +func NewSkbEditAction() *SkbEditAction { + return &SkbEditAction{ + ActionAttrs: ActionAttrs{ + Action: TC_ACT_PIPE, + }, + } +} + +// MatchAll filters match all packets +type MatchAll struct { + FilterAttrs + ClassId uint32 + Actions []Action +} + +func (filter *MatchAll) Attrs() *FilterAttrs { + return &filter.FilterAttrs +} + +func (filter *MatchAll) Type() string { + return "matchall" +} + +type FilterFwAttrs struct { + ClassId uint32 + InDev string + Mask uint32 + Index uint32 + Buffer uint32 + Mtu uint32 + Mpu uint16 + Rate uint32 + AvRate uint32 + PeakRate uint32 + Action TcPolAct + Overhead uint16 + LinkLayer int +} + +type BpfFilter struct { + FilterAttrs + ClassId uint32 + Fd int + Name string + DirectAction bool + Id int + Tag string +} + +func (filter *BpfFilter) Type() string { + return "bpf" +} + +func (filter *BpfFilter) Attrs() *FilterAttrs { + return &filter.FilterAttrs +} + +// GenericFilter filters represent types that are not currently understood +// by this netlink library. +type GenericFilter struct { + FilterAttrs + FilterType string +} + +func (filter *GenericFilter) Attrs() *FilterAttrs { + return &filter.FilterAttrs +} + +func (filter *GenericFilter) Type() string { + return filter.FilterType +} diff --git a/vendor/github.com/vishvananda/netlink/filter_linux.go b/vendor/github.com/vishvananda/netlink/filter_linux.go new file mode 100644 index 000000000..2cd46266c --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/filter_linux.go @@ -0,0 +1,815 @@ +package netlink + +import ( + "bytes" + "encoding/binary" + "encoding/hex" + "errors" + "fmt" + "syscall" + + "github.com/vishvananda/netlink/nl" + "golang.org/x/sys/unix" +) + +// Constants used in TcU32Sel.Flags. +const ( + TC_U32_TERMINAL = nl.TC_U32_TERMINAL + TC_U32_OFFSET = nl.TC_U32_OFFSET + TC_U32_VAROFFSET = nl.TC_U32_VAROFFSET + TC_U32_EAT = nl.TC_U32_EAT +) + +// Sel of the U32 filters that contains multiple TcU32Key. This is the type +// alias and the frontend representation of nl.TcU32Sel. It is serialized into +// canonical nl.TcU32Sel with the appropriate endianness. +type TcU32Sel = nl.TcU32Sel + +// TcU32Key contained of Sel in the U32 filters. This is the type alias and the +// frontend representation of nl.TcU32Key. It is serialized into chanonical +// nl.TcU32Sel with the appropriate endianness. +type TcU32Key = nl.TcU32Key + +// U32 filters on many packet related properties +type U32 struct { + FilterAttrs + ClassId uint32 + Divisor uint32 // Divisor MUST be power of 2. + Hash uint32 + Link uint32 + RedirIndex int + Sel *TcU32Sel + Actions []Action +} + +func (filter *U32) Attrs() *FilterAttrs { + return &filter.FilterAttrs +} + +func (filter *U32) Type() string { + return "u32" +} + +// Fw filter filters on firewall marks +// NOTE: this is in filter_linux because it refers to nl.TcPolice which +// is defined in nl/tc_linux.go +type Fw struct { + FilterAttrs + ClassId uint32 + // TODO remove nl type from interface + Police nl.TcPolice + InDev string + // TODO Action + Mask uint32 + AvRate uint32 + Rtab [256]uint32 + Ptab [256]uint32 +} + +func NewFw(attrs FilterAttrs, fattrs FilterFwAttrs) (*Fw, error) { + var rtab [256]uint32 + var ptab [256]uint32 + rcellLog := -1 + pcellLog := -1 + avrate := fattrs.AvRate / 8 + police := nl.TcPolice{} + police.Rate.Rate = fattrs.Rate / 8 + police.PeakRate.Rate = fattrs.PeakRate / 8 + buffer := fattrs.Buffer + linklayer := nl.LINKLAYER_ETHERNET + + if fattrs.LinkLayer != nl.LINKLAYER_UNSPEC { + linklayer = fattrs.LinkLayer + } + + police.Action = int32(fattrs.Action) + if police.Rate.Rate != 0 { + police.Rate.Mpu = fattrs.Mpu + police.Rate.Overhead = fattrs.Overhead + if CalcRtable(&police.Rate, rtab[:], rcellLog, fattrs.Mtu, linklayer) < 0 { + return nil, errors.New("TBF: failed to calculate rate table") + } + police.Burst = Xmittime(uint64(police.Rate.Rate), uint32(buffer)) + } + police.Mtu = fattrs.Mtu + if police.PeakRate.Rate != 0 { + police.PeakRate.Mpu = fattrs.Mpu + police.PeakRate.Overhead = fattrs.Overhead + if CalcRtable(&police.PeakRate, ptab[:], pcellLog, fattrs.Mtu, linklayer) < 0 { + return nil, errors.New("POLICE: failed to calculate peak rate table") + } + } + + return &Fw{ + FilterAttrs: attrs, + ClassId: fattrs.ClassId, + InDev: fattrs.InDev, + Mask: fattrs.Mask, + Police: police, + AvRate: avrate, + Rtab: rtab, + Ptab: ptab, + }, nil +} + +func (filter *Fw) Attrs() *FilterAttrs { + return &filter.FilterAttrs +} + +func (filter *Fw) Type() string { + return "fw" +} + +// FilterDel will delete a filter from the system. +// Equivalent to: `tc filter del $filter` +func FilterDel(filter Filter) error { + return pkgHandle.FilterDel(filter) +} + +// FilterDel will delete a filter from the system. +// Equivalent to: `tc filter del $filter` +func (h *Handle) FilterDel(filter Filter) error { + req := h.newNetlinkRequest(unix.RTM_DELTFILTER, unix.NLM_F_ACK) + base := filter.Attrs() + msg := &nl.TcMsg{ + Family: nl.FAMILY_ALL, + Ifindex: int32(base.LinkIndex), + Handle: base.Handle, + Parent: base.Parent, + Info: MakeHandle(base.Priority, nl.Swap16(base.Protocol)), + } + req.AddData(msg) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// FilterAdd will add a filter to the system. +// Equivalent to: `tc filter add $filter` +func FilterAdd(filter Filter) error { + return pkgHandle.FilterAdd(filter) +} + +// FilterAdd will add a filter to the system. +// Equivalent to: `tc filter add $filter` +func (h *Handle) FilterAdd(filter Filter) error { + return h.filterModify(filter, unix.NLM_F_CREATE|unix.NLM_F_EXCL) +} + +// FilterReplace will replace a filter. +// Equivalent to: `tc filter replace $filter` +func FilterReplace(filter Filter) error { + return pkgHandle.FilterReplace(filter) +} + +// FilterReplace will replace a filter. +// Equivalent to: `tc filter replace $filter` +func (h *Handle) FilterReplace(filter Filter) error { + return h.filterModify(filter, unix.NLM_F_CREATE) +} + +func (h *Handle) filterModify(filter Filter, flags int) error { + native = nl.NativeEndian() + req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, flags|unix.NLM_F_ACK) + base := filter.Attrs() + msg := &nl.TcMsg{ + Family: nl.FAMILY_ALL, + Ifindex: int32(base.LinkIndex), + Handle: base.Handle, + Parent: base.Parent, + Info: MakeHandle(base.Priority, nl.Swap16(base.Protocol)), + } + req.AddData(msg) + req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(filter.Type()))) + + options := nl.NewRtAttr(nl.TCA_OPTIONS, nil) + + switch filter := filter.(type) { + case *U32: + sel := filter.Sel + if sel == nil { + // match all + sel = &nl.TcU32Sel{ + Nkeys: 1, + Flags: nl.TC_U32_TERMINAL, + } + sel.Keys = append(sel.Keys, nl.TcU32Key{}) + } + + if native != networkOrder { + // Copy TcU32Sel. + cSel := *sel + keys := make([]nl.TcU32Key, cap(sel.Keys)) + copy(keys, sel.Keys) + cSel.Keys = keys + sel = &cSel + + // Handle the endianness of attributes + sel.Offmask = native.Uint16(htons(sel.Offmask)) + sel.Hmask = native.Uint32(htonl(sel.Hmask)) + for i, key := range sel.Keys { + sel.Keys[i].Mask = native.Uint32(htonl(key.Mask)) + sel.Keys[i].Val = native.Uint32(htonl(key.Val)) + } + } + sel.Nkeys = uint8(len(sel.Keys)) + options.AddRtAttr(nl.TCA_U32_SEL, sel.Serialize()) + if filter.ClassId != 0 { + options.AddRtAttr(nl.TCA_U32_CLASSID, nl.Uint32Attr(filter.ClassId)) + } + if filter.Divisor != 0 { + if (filter.Divisor-1)&filter.Divisor != 0 { + return fmt.Errorf("illegal divisor %d. Must be a power of 2", filter.Divisor) + } + options.AddRtAttr(nl.TCA_U32_DIVISOR, nl.Uint32Attr(filter.Divisor)) + } + if filter.Hash != 0 { + options.AddRtAttr(nl.TCA_U32_HASH, nl.Uint32Attr(filter.Hash)) + } + if filter.Link != 0 { + options.AddRtAttr(nl.TCA_U32_LINK, nl.Uint32Attr(filter.Link)) + } + actionsAttr := options.AddRtAttr(nl.TCA_U32_ACT, nil) + // backwards compatibility + if filter.RedirIndex != 0 { + filter.Actions = append([]Action{NewMirredAction(filter.RedirIndex)}, filter.Actions...) + } + if err := EncodeActions(actionsAttr, filter.Actions); err != nil { + return err + } + case *Fw: + if filter.Mask != 0 { + b := make([]byte, 4) + native.PutUint32(b, filter.Mask) + options.AddRtAttr(nl.TCA_FW_MASK, b) + } + if filter.InDev != "" { + options.AddRtAttr(nl.TCA_FW_INDEV, nl.ZeroTerminated(filter.InDev)) + } + if (filter.Police != nl.TcPolice{}) { + + police := options.AddRtAttr(nl.TCA_FW_POLICE, nil) + police.AddRtAttr(nl.TCA_POLICE_TBF, filter.Police.Serialize()) + if (filter.Police.Rate != nl.TcRateSpec{}) { + payload := SerializeRtab(filter.Rtab) + police.AddRtAttr(nl.TCA_POLICE_RATE, payload) + } + if (filter.Police.PeakRate != nl.TcRateSpec{}) { + payload := SerializeRtab(filter.Ptab) + police.AddRtAttr(nl.TCA_POLICE_PEAKRATE, payload) + } + } + if filter.ClassId != 0 { + b := make([]byte, 4) + native.PutUint32(b, filter.ClassId) + options.AddRtAttr(nl.TCA_FW_CLASSID, b) + } + case *BpfFilter: + var bpfFlags uint32 + if filter.ClassId != 0 { + options.AddRtAttr(nl.TCA_BPF_CLASSID, nl.Uint32Attr(filter.ClassId)) + } + if filter.Fd >= 0 { + options.AddRtAttr(nl.TCA_BPF_FD, nl.Uint32Attr((uint32(filter.Fd)))) + } + if filter.Name != "" { + options.AddRtAttr(nl.TCA_BPF_NAME, nl.ZeroTerminated(filter.Name)) + } + if filter.DirectAction { + bpfFlags |= nl.TCA_BPF_FLAG_ACT_DIRECT + } + options.AddRtAttr(nl.TCA_BPF_FLAGS, nl.Uint32Attr(bpfFlags)) + case *MatchAll: + actionsAttr := options.AddRtAttr(nl.TCA_MATCHALL_ACT, nil) + if err := EncodeActions(actionsAttr, filter.Actions); err != nil { + return err + } + if filter.ClassId != 0 { + options.AddRtAttr(nl.TCA_MATCHALL_CLASSID, nl.Uint32Attr(filter.ClassId)) + } + } + + req.AddData(options) + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// FilterList gets a list of filters in the system. +// Equivalent to: `tc filter show`. +// Generally returns nothing if link and parent are not specified. +func FilterList(link Link, parent uint32) ([]Filter, error) { + return pkgHandle.FilterList(link, parent) +} + +// FilterList gets a list of filters in the system. +// Equivalent to: `tc filter show`. +// Generally returns nothing if link and parent are not specified. +func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) { + req := h.newNetlinkRequest(unix.RTM_GETTFILTER, unix.NLM_F_DUMP) + msg := &nl.TcMsg{ + Family: nl.FAMILY_ALL, + Parent: parent, + } + if link != nil { + base := link.Attrs() + h.ensureIndex(base) + msg.Ifindex = int32(base.Index) + } + req.AddData(msg) + + msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWTFILTER) + if err != nil { + return nil, err + } + + var res []Filter + for _, m := range msgs { + msg := nl.DeserializeTcMsg(m) + + attrs, err := nl.ParseRouteAttr(m[msg.Len():]) + if err != nil { + return nil, err + } + + base := FilterAttrs{ + LinkIndex: int(msg.Ifindex), + Handle: msg.Handle, + Parent: msg.Parent, + } + base.Priority, base.Protocol = MajorMinor(msg.Info) + base.Protocol = nl.Swap16(base.Protocol) + + var filter Filter + filterType := "" + detailed := false + for _, attr := range attrs { + switch attr.Attr.Type { + case nl.TCA_KIND: + filterType = string(attr.Value[:len(attr.Value)-1]) + switch filterType { + case "u32": + filter = &U32{} + case "fw": + filter = &Fw{} + case "bpf": + filter = &BpfFilter{} + case "matchall": + filter = &MatchAll{} + default: + filter = &GenericFilter{FilterType: filterType} + } + case nl.TCA_OPTIONS: + data, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return nil, err + } + switch filterType { + case "u32": + detailed, err = parseU32Data(filter, data) + if err != nil { + return nil, err + } + case "fw": + detailed, err = parseFwData(filter, data) + if err != nil { + return nil, err + } + case "bpf": + detailed, err = parseBpfData(filter, data) + if err != nil { + return nil, err + } + case "matchall": + detailed, err = parseMatchAllData(filter, data) + if err != nil { + return nil, err + } + default: + detailed = true + } + } + } + // only return the detailed version of the filter + if detailed { + *filter.Attrs() = base + res = append(res, filter) + } + } + + return res, nil +} + +func toTcGen(attrs *ActionAttrs, tcgen *nl.TcGen) { + tcgen.Index = uint32(attrs.Index) + tcgen.Capab = uint32(attrs.Capab) + tcgen.Action = int32(attrs.Action) + tcgen.Refcnt = int32(attrs.Refcnt) + tcgen.Bindcnt = int32(attrs.Bindcnt) +} + +func toAttrs(tcgen *nl.TcGen, attrs *ActionAttrs) { + attrs.Index = int(tcgen.Index) + attrs.Capab = int(tcgen.Capab) + attrs.Action = TcAct(tcgen.Action) + attrs.Refcnt = int(tcgen.Refcnt) + attrs.Bindcnt = int(tcgen.Bindcnt) +} + +func EncodeActions(attr *nl.RtAttr, actions []Action) error { + tabIndex := int(nl.TCA_ACT_TAB) + + for _, action := range actions { + switch action := action.(type) { + default: + return fmt.Errorf("unknown action type %s", action.Type()) + case *MirredAction: + table := attr.AddRtAttr(tabIndex, nil) + tabIndex++ + table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("mirred")) + aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) + mirred := nl.TcMirred{ + Eaction: int32(action.MirredAction), + Ifindex: uint32(action.Ifindex), + } + toTcGen(action.Attrs(), &mirred.TcGen) + aopts.AddRtAttr(nl.TCA_MIRRED_PARMS, mirred.Serialize()) + case *TunnelKeyAction: + table := attr.AddRtAttr(tabIndex, nil) + tabIndex++ + table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("tunnel_key")) + aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) + tun := nl.TcTunnelKey{ + Action: int32(action.Action), + } + toTcGen(action.Attrs(), &tun.TcGen) + aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_PARMS, tun.Serialize()) + if action.Action == TCA_TUNNEL_KEY_SET { + aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_KEY_ID, htonl(action.KeyID)) + if v4 := action.SrcAddr.To4(); v4 != nil { + aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV4_SRC, v4[:]) + } else if v6 := action.SrcAddr.To16(); v6 != nil { + aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV6_SRC, v6[:]) + } else { + return fmt.Errorf("invalid src addr %s for tunnel_key action", action.SrcAddr) + } + if v4 := action.DstAddr.To4(); v4 != nil { + aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV4_DST, v4[:]) + } else if v6 := action.DstAddr.To16(); v6 != nil { + aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV6_DST, v6[:]) + } else { + return fmt.Errorf("invalid dst addr %s for tunnel_key action", action.DstAddr) + } + if action.DestPort != 0 { + aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_DST_PORT, htons(action.DestPort)) + } + } + case *SkbEditAction: + table := attr.AddRtAttr(tabIndex, nil) + tabIndex++ + table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("skbedit")) + aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) + skbedit := nl.TcSkbEdit{} + toTcGen(action.Attrs(), &skbedit.TcGen) + aopts.AddRtAttr(nl.TCA_SKBEDIT_PARMS, skbedit.Serialize()) + if action.QueueMapping != nil { + aopts.AddRtAttr(nl.TCA_SKBEDIT_QUEUE_MAPPING, nl.Uint16Attr(*action.QueueMapping)) + } + if action.Priority != nil { + aopts.AddRtAttr(nl.TCA_SKBEDIT_PRIORITY, nl.Uint32Attr(*action.Priority)) + } + if action.PType != nil { + aopts.AddRtAttr(nl.TCA_SKBEDIT_PTYPE, nl.Uint16Attr(*action.PType)) + } + if action.Mark != nil { + aopts.AddRtAttr(nl.TCA_SKBEDIT_MARK, nl.Uint32Attr(*action.Mark)) + } + case *ConnmarkAction: + table := attr.AddRtAttr(tabIndex, nil) + tabIndex++ + table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("connmark")) + aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) + connmark := nl.TcConnmark{ + Zone: action.Zone, + } + toTcGen(action.Attrs(), &connmark.TcGen) + aopts.AddRtAttr(nl.TCA_CONNMARK_PARMS, connmark.Serialize()) + case *BpfAction: + table := attr.AddRtAttr(tabIndex, nil) + tabIndex++ + table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("bpf")) + aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) + gen := nl.TcGen{} + toTcGen(action.Attrs(), &gen) + aopts.AddRtAttr(nl.TCA_ACT_BPF_PARMS, gen.Serialize()) + aopts.AddRtAttr(nl.TCA_ACT_BPF_FD, nl.Uint32Attr(uint32(action.Fd))) + aopts.AddRtAttr(nl.TCA_ACT_BPF_NAME, nl.ZeroTerminated(action.Name)) + case *GenericAction: + table := attr.AddRtAttr(tabIndex, nil) + tabIndex++ + table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("gact")) + aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) + gen := nl.TcGen{} + toTcGen(action.Attrs(), &gen) + aopts.AddRtAttr(nl.TCA_GACT_PARMS, gen.Serialize()) + } + } + return nil +} + +func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) { + var actions []Action + for _, table := range tables { + var action Action + var actionType string + aattrs, err := nl.ParseRouteAttr(table.Value) + if err != nil { + return nil, err + } + nextattr: + for _, aattr := range aattrs { + switch aattr.Attr.Type { + case nl.TCA_KIND: + actionType = string(aattr.Value[:len(aattr.Value)-1]) + // only parse if the action is mirred or bpf + switch actionType { + case "mirred": + action = &MirredAction{} + case "bpf": + action = &BpfAction{} + case "connmark": + action = &ConnmarkAction{} + case "gact": + action = &GenericAction{} + case "tunnel_key": + action = &TunnelKeyAction{} + case "skbedit": + action = &SkbEditAction{} + default: + break nextattr + } + case nl.TCA_OPTIONS: + adata, err := nl.ParseRouteAttr(aattr.Value) + if err != nil { + return nil, err + } + for _, adatum := range adata { + switch actionType { + case "mirred": + switch adatum.Attr.Type { + case nl.TCA_MIRRED_PARMS: + mirred := *nl.DeserializeTcMirred(adatum.Value) + action.(*MirredAction).ActionAttrs = ActionAttrs{} + toAttrs(&mirred.TcGen, action.Attrs()) + action.(*MirredAction).Ifindex = int(mirred.Ifindex) + action.(*MirredAction).MirredAction = MirredAct(mirred.Eaction) + } + case "tunnel_key": + switch adatum.Attr.Type { + case nl.TCA_TUNNEL_KEY_PARMS: + tun := *nl.DeserializeTunnelKey(adatum.Value) + action.(*TunnelKeyAction).ActionAttrs = ActionAttrs{} + toAttrs(&tun.TcGen, action.Attrs()) + action.(*TunnelKeyAction).Action = TunnelKeyAct(tun.Action) + case nl.TCA_TUNNEL_KEY_ENC_KEY_ID: + action.(*TunnelKeyAction).KeyID = networkOrder.Uint32(adatum.Value[0:4]) + case nl.TCA_TUNNEL_KEY_ENC_IPV6_SRC, nl.TCA_TUNNEL_KEY_ENC_IPV4_SRC: + action.(*TunnelKeyAction).SrcAddr = adatum.Value[:] + case nl.TCA_TUNNEL_KEY_ENC_IPV6_DST, nl.TCA_TUNNEL_KEY_ENC_IPV4_DST: + action.(*TunnelKeyAction).DstAddr = adatum.Value[:] + case nl.TCA_TUNNEL_KEY_ENC_DST_PORT: + action.(*TunnelKeyAction).DestPort = ntohs(adatum.Value) + } + case "skbedit": + switch adatum.Attr.Type { + case nl.TCA_SKBEDIT_PARMS: + skbedit := *nl.DeserializeSkbEdit(adatum.Value) + action.(*SkbEditAction).ActionAttrs = ActionAttrs{} + toAttrs(&skbedit.TcGen, action.Attrs()) + case nl.TCA_SKBEDIT_MARK: + mark := native.Uint32(adatum.Value[0:4]) + action.(*SkbEditAction).Mark = &mark + case nl.TCA_SKBEDIT_PRIORITY: + priority := native.Uint32(adatum.Value[0:4]) + action.(*SkbEditAction).Priority = &priority + case nl.TCA_SKBEDIT_PTYPE: + ptype := native.Uint16(adatum.Value[0:2]) + action.(*SkbEditAction).PType = &ptype + case nl.TCA_SKBEDIT_QUEUE_MAPPING: + mapping := native.Uint16(adatum.Value[0:2]) + action.(*SkbEditAction).QueueMapping = &mapping + } + case "bpf": + switch adatum.Attr.Type { + case nl.TCA_ACT_BPF_PARMS: + gen := *nl.DeserializeTcGen(adatum.Value) + toAttrs(&gen, action.Attrs()) + case nl.TCA_ACT_BPF_FD: + action.(*BpfAction).Fd = int(native.Uint32(adatum.Value[0:4])) + case nl.TCA_ACT_BPF_NAME: + action.(*BpfAction).Name = string(adatum.Value[:len(adatum.Value)-1]) + } + case "connmark": + switch adatum.Attr.Type { + case nl.TCA_CONNMARK_PARMS: + connmark := *nl.DeserializeTcConnmark(adatum.Value) + action.(*ConnmarkAction).ActionAttrs = ActionAttrs{} + toAttrs(&connmark.TcGen, action.Attrs()) + action.(*ConnmarkAction).Zone = connmark.Zone + } + case "gact": + switch adatum.Attr.Type { + case nl.TCA_GACT_PARMS: + gen := *nl.DeserializeTcGen(adatum.Value) + toAttrs(&gen, action.Attrs()) + } + } + } + } + } + actions = append(actions, action) + } + return actions, nil +} + +func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { + native = nl.NativeEndian() + u32 := filter.(*U32) + detailed := false + for _, datum := range data { + switch datum.Attr.Type { + case nl.TCA_U32_SEL: + detailed = true + sel := nl.DeserializeTcU32Sel(datum.Value) + u32.Sel = sel + if native != networkOrder { + // Handle the endianness of attributes + u32.Sel.Offmask = native.Uint16(htons(sel.Offmask)) + u32.Sel.Hmask = native.Uint32(htonl(sel.Hmask)) + for i, key := range u32.Sel.Keys { + u32.Sel.Keys[i].Mask = native.Uint32(htonl(key.Mask)) + u32.Sel.Keys[i].Val = native.Uint32(htonl(key.Val)) + } + } + case nl.TCA_U32_ACT: + tables, err := nl.ParseRouteAttr(datum.Value) + if err != nil { + return detailed, err + } + u32.Actions, err = parseActions(tables) + if err != nil { + return detailed, err + } + for _, action := range u32.Actions { + if action, ok := action.(*MirredAction); ok { + u32.RedirIndex = int(action.Ifindex) + } + } + case nl.TCA_U32_CLASSID: + u32.ClassId = native.Uint32(datum.Value) + case nl.TCA_U32_DIVISOR: + u32.Divisor = native.Uint32(datum.Value) + case nl.TCA_U32_HASH: + u32.Hash = native.Uint32(datum.Value) + case nl.TCA_U32_LINK: + u32.Link = native.Uint32(datum.Value) + } + } + return detailed, nil +} + +func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { + native = nl.NativeEndian() + fw := filter.(*Fw) + detailed := true + for _, datum := range data { + switch datum.Attr.Type { + case nl.TCA_FW_MASK: + fw.Mask = native.Uint32(datum.Value[0:4]) + case nl.TCA_FW_CLASSID: + fw.ClassId = native.Uint32(datum.Value[0:4]) + case nl.TCA_FW_INDEV: + fw.InDev = string(datum.Value[:len(datum.Value)-1]) + case nl.TCA_FW_POLICE: + adata, _ := nl.ParseRouteAttr(datum.Value) + for _, aattr := range adata { + switch aattr.Attr.Type { + case nl.TCA_POLICE_TBF: + fw.Police = *nl.DeserializeTcPolice(aattr.Value) + case nl.TCA_POLICE_RATE: + fw.Rtab = DeserializeRtab(aattr.Value) + case nl.TCA_POLICE_PEAKRATE: + fw.Ptab = DeserializeRtab(aattr.Value) + } + } + } + } + return detailed, nil +} + +func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { + native = nl.NativeEndian() + bpf := filter.(*BpfFilter) + detailed := true + for _, datum := range data { + switch datum.Attr.Type { + case nl.TCA_BPF_FD: + bpf.Fd = int(native.Uint32(datum.Value[0:4])) + case nl.TCA_BPF_NAME: + bpf.Name = string(datum.Value[:len(datum.Value)-1]) + case nl.TCA_BPF_CLASSID: + bpf.ClassId = native.Uint32(datum.Value[0:4]) + case nl.TCA_BPF_FLAGS: + flags := native.Uint32(datum.Value[0:4]) + if (flags & nl.TCA_BPF_FLAG_ACT_DIRECT) != 0 { + bpf.DirectAction = true + } + case nl.TCA_BPF_ID: + bpf.Id = int(native.Uint32(datum.Value[0:4])) + case nl.TCA_BPF_TAG: + bpf.Tag = hex.EncodeToString(datum.Value[:len(datum.Value)-1]) + } + } + return detailed, nil +} + +func parseMatchAllData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { + native = nl.NativeEndian() + matchall := filter.(*MatchAll) + detailed := true + for _, datum := range data { + switch datum.Attr.Type { + case nl.TCA_MATCHALL_CLASSID: + matchall.ClassId = native.Uint32(datum.Value[0:4]) + case nl.TCA_MATCHALL_ACT: + tables, err := nl.ParseRouteAttr(datum.Value) + if err != nil { + return detailed, err + } + matchall.Actions, err = parseActions(tables) + if err != nil { + return detailed, err + } + } + } + return detailed, nil +} + +func AlignToAtm(size uint) uint { + var linksize, cells int + cells = int(size / nl.ATM_CELL_PAYLOAD) + if (size % nl.ATM_CELL_PAYLOAD) > 0 { + cells++ + } + linksize = cells * nl.ATM_CELL_SIZE + return uint(linksize) +} + +func AdjustSize(sz uint, mpu uint, linklayer int) uint { + if sz < mpu { + sz = mpu + } + switch linklayer { + case nl.LINKLAYER_ATM: + return AlignToAtm(sz) + default: + return sz + } +} + +func CalcRtable(rate *nl.TcRateSpec, rtab []uint32, cellLog int, mtu uint32, linklayer int) int { + bps := rate.Rate + mpu := rate.Mpu + var sz uint + if mtu == 0 { + mtu = 2047 + } + if cellLog < 0 { + cellLog = 0 + for (mtu >> uint(cellLog)) > 255 { + cellLog++ + } + } + for i := 0; i < 256; i++ { + sz = AdjustSize(uint((i+1)<= nl.IPSET_ERR_PRIVATE { + err = nl.IPSetError(uintptr(errno)) + } + } + return +} + +func ipsetUnserialize(msgs [][]byte) (result IPSetResult) { + for _, msg := range msgs { + result.unserialize(msg) + } + return result +} + +func (result *IPSetResult) unserialize(msg []byte) { + result.Nfgenmsg = nl.DeserializeNfgenmsg(msg) + + for attr := range nl.ParseAttributes(msg[4:]) { + switch attr.Type { + case nl.IPSET_ATTR_PROTOCOL: + result.Protocol = attr.Value[0] + case nl.IPSET_ATTR_SETNAME: + result.SetName = nl.BytesToString(attr.Value) + case nl.IPSET_ATTR_COMMENT: + result.Comment = nl.BytesToString(attr.Value) + case nl.IPSET_ATTR_TYPENAME: + result.TypeName = nl.BytesToString(attr.Value) + case nl.IPSET_ATTR_REVISION: + result.Revision = attr.Value[0] + case nl.IPSET_ATTR_FAMILY: + result.Family = attr.Value[0] + case nl.IPSET_ATTR_FLAGS: + result.Flags = attr.Value[0] + case nl.IPSET_ATTR_DATA | nl.NLA_F_NESTED: + result.parseAttrData(attr.Value) + case nl.IPSET_ATTR_ADT | nl.NLA_F_NESTED: + result.parseAttrADT(attr.Value) + case nl.IPSET_ATTR_PROTOCOL_MIN: + result.ProtocolMinVersion = attr.Value[0] + default: + log.Printf("unknown ipset attribute from kernel: %+v %v", attr, attr.Type&nl.NLA_TYPE_MASK) + } + } +} + +func (result *IPSetResult) parseAttrData(data []byte) { + for attr := range nl.ParseAttributes(data) { + switch attr.Type { + case nl.IPSET_ATTR_HASHSIZE | nl.NLA_F_NET_BYTEORDER: + result.HashSize = attr.Uint32() + case nl.IPSET_ATTR_MAXELEM | nl.NLA_F_NET_BYTEORDER: + result.MaxElements = attr.Uint32() + case nl.IPSET_ATTR_TIMEOUT | nl.NLA_F_NET_BYTEORDER: + val := attr.Uint32() + result.Timeout = &val + case nl.IPSET_ATTR_ELEMENTS | nl.NLA_F_NET_BYTEORDER: + result.NumEntries = attr.Uint32() + case nl.IPSET_ATTR_REFERENCES | nl.NLA_F_NET_BYTEORDER: + result.References = attr.Uint32() + case nl.IPSET_ATTR_MEMSIZE | nl.NLA_F_NET_BYTEORDER: + result.SizeInMemory = attr.Uint32() + case nl.IPSET_ATTR_CADT_FLAGS | nl.NLA_F_NET_BYTEORDER: + result.CadtFlags = attr.Uint32() + case nl.IPSET_ATTR_IP | nl.NLA_F_NESTED: + for nested := range nl.ParseAttributes(attr.Value) { + switch nested.Type { + case nl.IPSET_ATTR_IP | nl.NLA_F_NET_BYTEORDER: + result.Entries = append(result.Entries, IPSetEntry{IP: nested.Value}) + } + } + case nl.IPSET_ATTR_CADT_LINENO | nl.NLA_F_NET_BYTEORDER: + result.LineNo = attr.Uint32() + case nl.IPSET_ATTR_COMMENT: + result.Comment = nl.BytesToString(attr.Value) + default: + log.Printf("unknown ipset data attribute from kernel: %+v %v", attr, attr.Type&nl.NLA_TYPE_MASK) + } + } +} + +func (result *IPSetResult) parseAttrADT(data []byte) { + for attr := range nl.ParseAttributes(data) { + switch attr.Type { + case nl.IPSET_ATTR_DATA | nl.NLA_F_NESTED: + result.Entries = append(result.Entries, parseIPSetEntry(attr.Value)) + default: + log.Printf("unknown ADT attribute from kernel: %+v %v", attr, attr.Type&nl.NLA_TYPE_MASK) + } + } +} + +func parseIPSetEntry(data []byte) (entry IPSetEntry) { + for attr := range nl.ParseAttributes(data) { + switch attr.Type { + case nl.IPSET_ATTR_TIMEOUT | nl.NLA_F_NET_BYTEORDER: + val := attr.Uint32() + entry.Timeout = &val + case nl.IPSET_ATTR_BYTES | nl.NLA_F_NET_BYTEORDER: + val := attr.Uint64() + entry.Bytes = &val + case nl.IPSET_ATTR_PACKETS | nl.NLA_F_NET_BYTEORDER: + val := attr.Uint64() + entry.Packets = &val + case nl.IPSET_ATTR_ETHER: + entry.MAC = net.HardwareAddr(attr.Value) + case nl.IPSET_ATTR_IP: + entry.IP = net.IP(attr.Value) + case nl.IPSET_ATTR_COMMENT: + entry.Comment = nl.BytesToString(attr.Value) + case nl.IPSET_ATTR_IP | nl.NLA_F_NESTED: + for attr := range nl.ParseAttributes(attr.Value) { + switch attr.Type { + case nl.IPSET_ATTR_IP: + entry.IP = net.IP(attr.Value) + default: + log.Printf("unknown nested ADT attribute from kernel: %+v", attr) + } + } + default: + log.Printf("unknown ADT attribute from kernel: %+v", attr) + } + } + return +} diff --git a/vendor/github.com/vishvananda/netlink/link.go b/vendor/github.com/vishvananda/netlink/link.go new file mode 100644 index 000000000..32ca7cd64 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/link.go @@ -0,0 +1,1275 @@ +package netlink + +import ( + "fmt" + "net" + "os" + "strconv" +) + +// Link represents a link device from netlink. Shared link attributes +// like name may be retrieved using the Attrs() method. Unique data +// can be retrieved by casting the object to the proper type. +type Link interface { + Attrs() *LinkAttrs + Type() string +} + +type ( + NsPid int + NsFd int +) + +// LinkAttrs represents data shared by most link types +type LinkAttrs struct { + Index int + MTU int + TxQLen int // Transmit Queue Length + Name string + HardwareAddr net.HardwareAddr + Flags net.Flags + RawFlags uint32 + ParentIndex int // index of the parent link device + MasterIndex int // must be the index of a bridge + Namespace interface{} // nil | NsPid | NsFd + Alias string + Statistics *LinkStatistics + Promisc int + Xdp *LinkXdp + EncapType string + Protinfo *Protinfo + OperState LinkOperState + NetNsID int + NumTxQueues int + NumRxQueues int + GSOMaxSize uint32 + GSOMaxSegs uint32 + Vfs []VfInfo // virtual functions available on link + Group uint32 + Slave LinkSlave +} + +// LinkSlave represents a slave device. +type LinkSlave interface { + SlaveType() string +} + +// VfInfo represents configuration of virtual function +type VfInfo struct { + ID int + Mac net.HardwareAddr + Vlan int + Qos int + TxRate int // IFLA_VF_TX_RATE Max TxRate + Spoofchk bool + LinkState uint32 + MaxTxRate uint32 // IFLA_VF_RATE Max TxRate + MinTxRate uint32 // IFLA_VF_RATE Min TxRate + RxPackets uint64 + TxPackets uint64 + RxBytes uint64 + TxBytes uint64 + Multicast uint64 + Broadcast uint64 + RxDropped uint64 + TxDropped uint64 + + RssQuery uint32 + Trust uint32 +} + +// LinkOperState represents the values of the IFLA_OPERSTATE link +// attribute, which contains the RFC2863 state of the interface. +type LinkOperState uint8 + +const ( + OperUnknown = iota // Status can't be determined. + OperNotPresent // Some component is missing. + OperDown // Down. + OperLowerLayerDown // Down due to state of lower layer. + OperTesting // In some test mode. + OperDormant // Not up but pending an external event. + OperUp // Up, ready to send packets. +) + +func (s LinkOperState) String() string { + switch s { + case OperNotPresent: + return "not-present" + case OperDown: + return "down" + case OperLowerLayerDown: + return "lower-layer-down" + case OperTesting: + return "testing" + case OperDormant: + return "dormant" + case OperUp: + return "up" + default: + return "unknown" + } +} + +// NewLinkAttrs returns LinkAttrs structure filled with default values +func NewLinkAttrs() LinkAttrs { + return LinkAttrs{ + NetNsID: -1, + TxQLen: -1, + } +} + +type LinkStatistics LinkStatistics64 + +/* +Ref: struct rtnl_link_stats {...} +*/ +type LinkStatistics32 struct { + RxPackets uint32 + TxPackets uint32 + RxBytes uint32 + TxBytes uint32 + RxErrors uint32 + TxErrors uint32 + RxDropped uint32 + TxDropped uint32 + Multicast uint32 + Collisions uint32 + RxLengthErrors uint32 + RxOverErrors uint32 + RxCrcErrors uint32 + RxFrameErrors uint32 + RxFifoErrors uint32 + RxMissedErrors uint32 + TxAbortedErrors uint32 + TxCarrierErrors uint32 + TxFifoErrors uint32 + TxHeartbeatErrors uint32 + TxWindowErrors uint32 + RxCompressed uint32 + TxCompressed uint32 +} + +func (s32 LinkStatistics32) to64() *LinkStatistics64 { + return &LinkStatistics64{ + RxPackets: uint64(s32.RxPackets), + TxPackets: uint64(s32.TxPackets), + RxBytes: uint64(s32.RxBytes), + TxBytes: uint64(s32.TxBytes), + RxErrors: uint64(s32.RxErrors), + TxErrors: uint64(s32.TxErrors), + RxDropped: uint64(s32.RxDropped), + TxDropped: uint64(s32.TxDropped), + Multicast: uint64(s32.Multicast), + Collisions: uint64(s32.Collisions), + RxLengthErrors: uint64(s32.RxLengthErrors), + RxOverErrors: uint64(s32.RxOverErrors), + RxCrcErrors: uint64(s32.RxCrcErrors), + RxFrameErrors: uint64(s32.RxFrameErrors), + RxFifoErrors: uint64(s32.RxFifoErrors), + RxMissedErrors: uint64(s32.RxMissedErrors), + TxAbortedErrors: uint64(s32.TxAbortedErrors), + TxCarrierErrors: uint64(s32.TxCarrierErrors), + TxFifoErrors: uint64(s32.TxFifoErrors), + TxHeartbeatErrors: uint64(s32.TxHeartbeatErrors), + TxWindowErrors: uint64(s32.TxWindowErrors), + RxCompressed: uint64(s32.RxCompressed), + TxCompressed: uint64(s32.TxCompressed), + } +} + +/* +Ref: struct rtnl_link_stats64 {...} +*/ +type LinkStatistics64 struct { + RxPackets uint64 + TxPackets uint64 + RxBytes uint64 + TxBytes uint64 + RxErrors uint64 + TxErrors uint64 + RxDropped uint64 + TxDropped uint64 + Multicast uint64 + Collisions uint64 + RxLengthErrors uint64 + RxOverErrors uint64 + RxCrcErrors uint64 + RxFrameErrors uint64 + RxFifoErrors uint64 + RxMissedErrors uint64 + TxAbortedErrors uint64 + TxCarrierErrors uint64 + TxFifoErrors uint64 + TxHeartbeatErrors uint64 + TxWindowErrors uint64 + RxCompressed uint64 + TxCompressed uint64 +} + +type LinkXdp struct { + Fd int + Attached bool + AttachMode uint32 + Flags uint32 + ProgId uint32 +} + +// Device links cannot be created via netlink. These links +// are links created by udev like 'lo' and 'etho0' +type Device struct { + LinkAttrs +} + +func (device *Device) Attrs() *LinkAttrs { + return &device.LinkAttrs +} + +func (device *Device) Type() string { + return "device" +} + +// Dummy links are dummy ethernet devices +type Dummy struct { + LinkAttrs +} + +func (dummy *Dummy) Attrs() *LinkAttrs { + return &dummy.LinkAttrs +} + +func (dummy *Dummy) Type() string { + return "dummy" +} + +// Ifb links are advanced dummy devices for packet filtering +type Ifb struct { + LinkAttrs +} + +func (ifb *Ifb) Attrs() *LinkAttrs { + return &ifb.LinkAttrs +} + +func (ifb *Ifb) Type() string { + return "ifb" +} + +// Bridge links are simple linux bridges +type Bridge struct { + LinkAttrs + MulticastSnooping *bool + AgeingTime *uint32 + HelloTime *uint32 + VlanFiltering *bool +} + +func (bridge *Bridge) Attrs() *LinkAttrs { + return &bridge.LinkAttrs +} + +func (bridge *Bridge) Type() string { + return "bridge" +} + +// Vlan links have ParentIndex set in their Attrs() +type Vlan struct { + LinkAttrs + VlanId int + VlanProtocol VlanProtocol +} + +func (vlan *Vlan) Attrs() *LinkAttrs { + return &vlan.LinkAttrs +} + +func (vlan *Vlan) Type() string { + return "vlan" +} + +type MacvlanMode uint16 + +const ( + MACVLAN_MODE_DEFAULT MacvlanMode = iota + MACVLAN_MODE_PRIVATE + MACVLAN_MODE_VEPA + MACVLAN_MODE_BRIDGE + MACVLAN_MODE_PASSTHRU + MACVLAN_MODE_SOURCE +) + +// Macvlan links have ParentIndex set in their Attrs() +type Macvlan struct { + LinkAttrs + Mode MacvlanMode + + // MACAddrs is only populated for Macvlan SOURCE links + MACAddrs []net.HardwareAddr +} + +func (macvlan *Macvlan) Attrs() *LinkAttrs { + return &macvlan.LinkAttrs +} + +func (macvlan *Macvlan) Type() string { + return "macvlan" +} + +// Macvtap - macvtap is a virtual interfaces based on macvlan +type Macvtap struct { + Macvlan +} + +func (macvtap Macvtap) Type() string { + return "macvtap" +} + +type TuntapMode uint16 +type TuntapFlag uint16 + +// Tuntap links created via /dev/tun/tap, but can be destroyed via netlink +type Tuntap struct { + LinkAttrs + Mode TuntapMode + Flags TuntapFlag + NonPersist bool + Queues int + Fds []*os.File + Owner uint32 + Group uint32 +} + +func (tuntap *Tuntap) Attrs() *LinkAttrs { + return &tuntap.LinkAttrs +} + +func (tuntap *Tuntap) Type() string { + return "tuntap" +} + +// Veth devices must specify PeerName on create +type Veth struct { + LinkAttrs + PeerName string // veth on create only + PeerHardwareAddr net.HardwareAddr + PeerNamespace interface{} +} + +func (veth *Veth) Attrs() *LinkAttrs { + return &veth.LinkAttrs +} + +func (veth *Veth) Type() string { + return "veth" +} + +// Wireguard represent links of type "wireguard", see https://www.wireguard.com/ +type Wireguard struct { + LinkAttrs +} + +func (wg *Wireguard) Attrs() *LinkAttrs { + return &wg.LinkAttrs +} + +func (wg *Wireguard) Type() string { + return "wireguard" +} + +// GenericLink links represent types that are not currently understood +// by this netlink library. +type GenericLink struct { + LinkAttrs + LinkType string +} + +func (generic *GenericLink) Attrs() *LinkAttrs { + return &generic.LinkAttrs +} + +func (generic *GenericLink) Type() string { + return generic.LinkType +} + +type Vxlan struct { + LinkAttrs + VxlanId int + VtepDevIndex int + SrcAddr net.IP + Group net.IP + TTL int + TOS int + Learning bool + Proxy bool + RSC bool + L2miss bool + L3miss bool + UDPCSum bool + UDP6ZeroCSumTx bool + UDP6ZeroCSumRx bool + NoAge bool + GBP bool + FlowBased bool + Age int + Limit int + Port int + PortLow int + PortHigh int +} + +func (vxlan *Vxlan) Attrs() *LinkAttrs { + return &vxlan.LinkAttrs +} + +func (vxlan *Vxlan) Type() string { + return "vxlan" +} + +type IPVlanMode uint16 + +const ( + IPVLAN_MODE_L2 IPVlanMode = iota + IPVLAN_MODE_L3 + IPVLAN_MODE_L3S + IPVLAN_MODE_MAX +) + +type IPVlanFlag uint16 + +const ( + IPVLAN_FLAG_BRIDGE IPVlanFlag = iota + IPVLAN_FLAG_PRIVATE + IPVLAN_FLAG_VEPA +) + +type IPVlan struct { + LinkAttrs + Mode IPVlanMode + Flag IPVlanFlag +} + +func (ipvlan *IPVlan) Attrs() *LinkAttrs { + return &ipvlan.LinkAttrs +} + +func (ipvlan *IPVlan) Type() string { + return "ipvlan" +} + +// VlanProtocol type +type VlanProtocol int + +func (p VlanProtocol) String() string { + s, ok := VlanProtocolToString[p] + if !ok { + return fmt.Sprintf("VlanProtocol(%d)", p) + } + return s +} + +// StringToVlanProtocol returns vlan protocol, or unknown is the s is invalid. +func StringToVlanProtocol(s string) VlanProtocol { + mode, ok := StringToVlanProtocolMap[s] + if !ok { + return VLAN_PROTOCOL_UNKNOWN + } + return mode +} + +// VlanProtocol possible values +const ( + VLAN_PROTOCOL_UNKNOWN VlanProtocol = 0 + VLAN_PROTOCOL_8021Q VlanProtocol = 0x8100 + VLAN_PROTOCOL_8021AD VlanProtocol = 0x88A8 +) + +var VlanProtocolToString = map[VlanProtocol]string{ + VLAN_PROTOCOL_8021Q: "802.1q", + VLAN_PROTOCOL_8021AD: "802.1ad", +} + +var StringToVlanProtocolMap = map[string]VlanProtocol{ + "802.1q": VLAN_PROTOCOL_8021Q, + "802.1ad": VLAN_PROTOCOL_8021AD, +} + +// BondMode type +type BondMode int + +func (b BondMode) String() string { + s, ok := bondModeToString[b] + if !ok { + return fmt.Sprintf("BondMode(%d)", b) + } + return s +} + +// StringToBondMode returns bond mode, or unknown is the s is invalid. +func StringToBondMode(s string) BondMode { + mode, ok := StringToBondModeMap[s] + if !ok { + return BOND_MODE_UNKNOWN + } + return mode +} + +// Possible BondMode +const ( + BOND_MODE_BALANCE_RR BondMode = iota + BOND_MODE_ACTIVE_BACKUP + BOND_MODE_BALANCE_XOR + BOND_MODE_BROADCAST + BOND_MODE_802_3AD + BOND_MODE_BALANCE_TLB + BOND_MODE_BALANCE_ALB + BOND_MODE_UNKNOWN +) + +var bondModeToString = map[BondMode]string{ + BOND_MODE_BALANCE_RR: "balance-rr", + BOND_MODE_ACTIVE_BACKUP: "active-backup", + BOND_MODE_BALANCE_XOR: "balance-xor", + BOND_MODE_BROADCAST: "broadcast", + BOND_MODE_802_3AD: "802.3ad", + BOND_MODE_BALANCE_TLB: "balance-tlb", + BOND_MODE_BALANCE_ALB: "balance-alb", +} +var StringToBondModeMap = map[string]BondMode{ + "balance-rr": BOND_MODE_BALANCE_RR, + "active-backup": BOND_MODE_ACTIVE_BACKUP, + "balance-xor": BOND_MODE_BALANCE_XOR, + "broadcast": BOND_MODE_BROADCAST, + "802.3ad": BOND_MODE_802_3AD, + "balance-tlb": BOND_MODE_BALANCE_TLB, + "balance-alb": BOND_MODE_BALANCE_ALB, +} + +// BondArpValidate type +type BondArpValidate int + +// Possible BondArpValidate value +const ( + BOND_ARP_VALIDATE_NONE BondArpValidate = iota + BOND_ARP_VALIDATE_ACTIVE + BOND_ARP_VALIDATE_BACKUP + BOND_ARP_VALIDATE_ALL +) + +var bondArpValidateToString = map[BondArpValidate]string{ + BOND_ARP_VALIDATE_NONE: "none", + BOND_ARP_VALIDATE_ACTIVE: "active", + BOND_ARP_VALIDATE_BACKUP: "backup", + BOND_ARP_VALIDATE_ALL: "none", +} +var StringToBondArpValidateMap = map[string]BondArpValidate{ + "none": BOND_ARP_VALIDATE_NONE, + "active": BOND_ARP_VALIDATE_ACTIVE, + "backup": BOND_ARP_VALIDATE_BACKUP, + "all": BOND_ARP_VALIDATE_ALL, +} + +func (b BondArpValidate) String() string { + s, ok := bondArpValidateToString[b] + if !ok { + return fmt.Sprintf("BondArpValidate(%d)", b) + } + return s +} + +// BondPrimaryReselect type +type BondPrimaryReselect int + +// Possible BondPrimaryReselect value +const ( + BOND_PRIMARY_RESELECT_ALWAYS BondPrimaryReselect = iota + BOND_PRIMARY_RESELECT_BETTER + BOND_PRIMARY_RESELECT_FAILURE +) + +var bondPrimaryReselectToString = map[BondPrimaryReselect]string{ + BOND_PRIMARY_RESELECT_ALWAYS: "always", + BOND_PRIMARY_RESELECT_BETTER: "better", + BOND_PRIMARY_RESELECT_FAILURE: "failure", +} +var StringToBondPrimaryReselectMap = map[string]BondPrimaryReselect{ + "always": BOND_PRIMARY_RESELECT_ALWAYS, + "better": BOND_PRIMARY_RESELECT_BETTER, + "failure": BOND_PRIMARY_RESELECT_FAILURE, +} + +func (b BondPrimaryReselect) String() string { + s, ok := bondPrimaryReselectToString[b] + if !ok { + return fmt.Sprintf("BondPrimaryReselect(%d)", b) + } + return s +} + +// BondArpAllTargets type +type BondArpAllTargets int + +// Possible BondArpAllTargets value +const ( + BOND_ARP_ALL_TARGETS_ANY BondArpAllTargets = iota + BOND_ARP_ALL_TARGETS_ALL +) + +var bondArpAllTargetsToString = map[BondArpAllTargets]string{ + BOND_ARP_ALL_TARGETS_ANY: "any", + BOND_ARP_ALL_TARGETS_ALL: "all", +} +var StringToBondArpAllTargetsMap = map[string]BondArpAllTargets{ + "any": BOND_ARP_ALL_TARGETS_ANY, + "all": BOND_ARP_ALL_TARGETS_ALL, +} + +func (b BondArpAllTargets) String() string { + s, ok := bondArpAllTargetsToString[b] + if !ok { + return fmt.Sprintf("BondArpAllTargets(%d)", b) + } + return s +} + +// BondFailOverMac type +type BondFailOverMac int + +// Possible BondFailOverMac value +const ( + BOND_FAIL_OVER_MAC_NONE BondFailOverMac = iota + BOND_FAIL_OVER_MAC_ACTIVE + BOND_FAIL_OVER_MAC_FOLLOW +) + +var bondFailOverMacToString = map[BondFailOverMac]string{ + BOND_FAIL_OVER_MAC_NONE: "none", + BOND_FAIL_OVER_MAC_ACTIVE: "active", + BOND_FAIL_OVER_MAC_FOLLOW: "follow", +} +var StringToBondFailOverMacMap = map[string]BondFailOverMac{ + "none": BOND_FAIL_OVER_MAC_NONE, + "active": BOND_FAIL_OVER_MAC_ACTIVE, + "follow": BOND_FAIL_OVER_MAC_FOLLOW, +} + +func (b BondFailOverMac) String() string { + s, ok := bondFailOverMacToString[b] + if !ok { + return fmt.Sprintf("BondFailOverMac(%d)", b) + } + return s +} + +// BondXmitHashPolicy type +type BondXmitHashPolicy int + +func (b BondXmitHashPolicy) String() string { + s, ok := bondXmitHashPolicyToString[b] + if !ok { + return fmt.Sprintf("XmitHashPolicy(%d)", b) + } + return s +} + +// StringToBondXmitHashPolicy returns bond lacp arte, or unknown is the s is invalid. +func StringToBondXmitHashPolicy(s string) BondXmitHashPolicy { + lacp, ok := StringToBondXmitHashPolicyMap[s] + if !ok { + return BOND_XMIT_HASH_POLICY_UNKNOWN + } + return lacp +} + +// Possible BondXmitHashPolicy value +const ( + BOND_XMIT_HASH_POLICY_LAYER2 BondXmitHashPolicy = iota + BOND_XMIT_HASH_POLICY_LAYER3_4 + BOND_XMIT_HASH_POLICY_LAYER2_3 + BOND_XMIT_HASH_POLICY_ENCAP2_3 + BOND_XMIT_HASH_POLICY_ENCAP3_4 + BOND_XMIT_HASH_POLICY_UNKNOWN +) + +var bondXmitHashPolicyToString = map[BondXmitHashPolicy]string{ + BOND_XMIT_HASH_POLICY_LAYER2: "layer2", + BOND_XMIT_HASH_POLICY_LAYER3_4: "layer3+4", + BOND_XMIT_HASH_POLICY_LAYER2_3: "layer2+3", + BOND_XMIT_HASH_POLICY_ENCAP2_3: "encap2+3", + BOND_XMIT_HASH_POLICY_ENCAP3_4: "encap3+4", +} +var StringToBondXmitHashPolicyMap = map[string]BondXmitHashPolicy{ + "layer2": BOND_XMIT_HASH_POLICY_LAYER2, + "layer3+4": BOND_XMIT_HASH_POLICY_LAYER3_4, + "layer2+3": BOND_XMIT_HASH_POLICY_LAYER2_3, + "encap2+3": BOND_XMIT_HASH_POLICY_ENCAP2_3, + "encap3+4": BOND_XMIT_HASH_POLICY_ENCAP3_4, +} + +// BondLacpRate type +type BondLacpRate int + +func (b BondLacpRate) String() string { + s, ok := bondLacpRateToString[b] + if !ok { + return fmt.Sprintf("LacpRate(%d)", b) + } + return s +} + +// StringToBondLacpRate returns bond lacp arte, or unknown is the s is invalid. +func StringToBondLacpRate(s string) BondLacpRate { + lacp, ok := StringToBondLacpRateMap[s] + if !ok { + return BOND_LACP_RATE_UNKNOWN + } + return lacp +} + +// Possible BondLacpRate value +const ( + BOND_LACP_RATE_SLOW BondLacpRate = iota + BOND_LACP_RATE_FAST + BOND_LACP_RATE_UNKNOWN +) + +var bondLacpRateToString = map[BondLacpRate]string{ + BOND_LACP_RATE_SLOW: "slow", + BOND_LACP_RATE_FAST: "fast", +} +var StringToBondLacpRateMap = map[string]BondLacpRate{ + "slow": BOND_LACP_RATE_SLOW, + "fast": BOND_LACP_RATE_FAST, +} + +// BondAdSelect type +type BondAdSelect int + +// Possible BondAdSelect value +const ( + BOND_AD_SELECT_STABLE BondAdSelect = iota + BOND_AD_SELECT_BANDWIDTH + BOND_AD_SELECT_COUNT +) + +var bondAdSelectToString = map[BondAdSelect]string{ + BOND_AD_SELECT_STABLE: "stable", + BOND_AD_SELECT_BANDWIDTH: "bandwidth", + BOND_AD_SELECT_COUNT: "count", +} +var StringToBondAdSelectMap = map[string]BondAdSelect{ + "stable": BOND_AD_SELECT_STABLE, + "bandwidth": BOND_AD_SELECT_BANDWIDTH, + "count": BOND_AD_SELECT_COUNT, +} + +func (b BondAdSelect) String() string { + s, ok := bondAdSelectToString[b] + if !ok { + return fmt.Sprintf("BondAdSelect(%d)", b) + } + return s +} + +// BondAdInfo represents ad info for bond +type BondAdInfo struct { + AggregatorId int + NumPorts int + ActorKey int + PartnerKey int + PartnerMac net.HardwareAddr +} + +// Bond representation +type Bond struct { + LinkAttrs + Mode BondMode + ActiveSlave int + Miimon int + UpDelay int + DownDelay int + UseCarrier int + ArpInterval int + ArpIpTargets []net.IP + ArpValidate BondArpValidate + ArpAllTargets BondArpAllTargets + Primary int + PrimaryReselect BondPrimaryReselect + FailOverMac BondFailOverMac + XmitHashPolicy BondXmitHashPolicy + ResendIgmp int + NumPeerNotif int + AllSlavesActive int + MinLinks int + LpInterval int + PacketsPerSlave int + LacpRate BondLacpRate + AdSelect BondAdSelect + // looking at iproute tool AdInfo can only be retrived. It can't be set. + AdInfo *BondAdInfo + AdActorSysPrio int + AdUserPortKey int + AdActorSystem net.HardwareAddr + TlbDynamicLb int +} + +func NewLinkBond(atr LinkAttrs) *Bond { + return &Bond{ + LinkAttrs: atr, + Mode: -1, + ActiveSlave: -1, + Miimon: -1, + UpDelay: -1, + DownDelay: -1, + UseCarrier: -1, + ArpInterval: -1, + ArpIpTargets: nil, + ArpValidate: -1, + ArpAllTargets: -1, + Primary: -1, + PrimaryReselect: -1, + FailOverMac: -1, + XmitHashPolicy: -1, + ResendIgmp: -1, + NumPeerNotif: -1, + AllSlavesActive: -1, + MinLinks: -1, + LpInterval: -1, + PacketsPerSlave: -1, + LacpRate: -1, + AdSelect: -1, + AdActorSysPrio: -1, + AdUserPortKey: -1, + AdActorSystem: nil, + TlbDynamicLb: -1, + } +} + +// Flag mask for bond options. Bond.Flagmask must be set to on for option to work. +const ( + BOND_MODE_MASK uint64 = 1 << (1 + iota) + BOND_ACTIVE_SLAVE_MASK + BOND_MIIMON_MASK + BOND_UPDELAY_MASK + BOND_DOWNDELAY_MASK + BOND_USE_CARRIER_MASK + BOND_ARP_INTERVAL_MASK + BOND_ARP_VALIDATE_MASK + BOND_ARP_ALL_TARGETS_MASK + BOND_PRIMARY_MASK + BOND_PRIMARY_RESELECT_MASK + BOND_FAIL_OVER_MAC_MASK + BOND_XMIT_HASH_POLICY_MASK + BOND_RESEND_IGMP_MASK + BOND_NUM_PEER_NOTIF_MASK + BOND_ALL_SLAVES_ACTIVE_MASK + BOND_MIN_LINKS_MASK + BOND_LP_INTERVAL_MASK + BOND_PACKETS_PER_SLAVE_MASK + BOND_LACP_RATE_MASK + BOND_AD_SELECT_MASK +) + +// Attrs implementation. +func (bond *Bond) Attrs() *LinkAttrs { + return &bond.LinkAttrs +} + +// Type implementation fro Vxlan. +func (bond *Bond) Type() string { + return "bond" +} + +// BondSlaveState represents the values of the IFLA_BOND_SLAVE_STATE bond slave +// attribute, which contains the state of the bond slave. +type BondSlaveState uint8 + +const ( + //BondStateActive Link is active. + BondStateActive BondSlaveState = iota + //BondStateBackup Link is backup. + BondStateBackup +) + +func (s BondSlaveState) String() string { + switch s { + case BondStateActive: + return "ACTIVE" + case BondStateBackup: + return "BACKUP" + default: + return strconv.Itoa(int(s)) + } +} + +// BondSlaveMiiStatus represents the values of the IFLA_BOND_SLAVE_MII_STATUS bond slave +// attribute, which contains the status of MII link monitoring +type BondSlaveMiiStatus uint8 + +const ( + //BondLinkUp link is up and running. + BondLinkUp BondSlaveMiiStatus = iota + //BondLinkFail link has just gone down. + BondLinkFail + //BondLinkDown link has been down for too long time. + BondLinkDown + //BondLinkBack link is going back. + BondLinkBack +) + +func (s BondSlaveMiiStatus) String() string { + switch s { + case BondLinkUp: + return "UP" + case BondLinkFail: + return "GOING_DOWN" + case BondLinkDown: + return "DOWN" + case BondLinkBack: + return "GOING_BACK" + default: + return strconv.Itoa(int(s)) + } +} + +type BondSlave struct { + State BondSlaveState + MiiStatus BondSlaveMiiStatus + LinkFailureCount uint32 + PermHardwareAddr net.HardwareAddr + QueueId uint16 + AggregatorId uint16 + AdActorOperPortState uint8 + AdPartnerOperPortState uint16 +} + +func (b *BondSlave) SlaveType() string { + return "bond" +} + +// Geneve devices must specify RemoteIP and ID (VNI) on create +// https://github.com/torvalds/linux/blob/47ec5303d73ea344e84f46660fff693c57641386/drivers/net/geneve.c#L1209-L1223 +type Geneve struct { + LinkAttrs + ID uint32 // vni + Remote net.IP + Ttl uint8 + Tos uint8 + Dport uint16 + UdpCsum uint8 + UdpZeroCsum6Tx uint8 + UdpZeroCsum6Rx uint8 + Link uint32 + FlowBased bool +} + +func (geneve *Geneve) Attrs() *LinkAttrs { + return &geneve.LinkAttrs +} + +func (geneve *Geneve) Type() string { + return "geneve" +} + +// Gretap devices must specify LocalIP and RemoteIP on create +type Gretap struct { + LinkAttrs + IKey uint32 + OKey uint32 + EncapSport uint16 + EncapDport uint16 + Local net.IP + Remote net.IP + IFlags uint16 + OFlags uint16 + PMtuDisc uint8 + Ttl uint8 + Tos uint8 + EncapType uint16 + EncapFlags uint16 + Link uint32 + FlowBased bool +} + +func (gretap *Gretap) Attrs() *LinkAttrs { + return &gretap.LinkAttrs +} + +func (gretap *Gretap) Type() string { + if gretap.Local.To4() == nil { + return "ip6gretap" + } + return "gretap" +} + +type Iptun struct { + LinkAttrs + Ttl uint8 + Tos uint8 + PMtuDisc uint8 + Link uint32 + Local net.IP + Remote net.IP + EncapSport uint16 + EncapDport uint16 + EncapType uint16 + EncapFlags uint16 + FlowBased bool +} + +func (iptun *Iptun) Attrs() *LinkAttrs { + return &iptun.LinkAttrs +} + +func (iptun *Iptun) Type() string { + return "ipip" +} + +type Ip6tnl struct { + LinkAttrs + Link uint32 + Local net.IP + Remote net.IP + Ttl uint8 + Tos uint8 + Flags uint32 + Proto uint8 + FlowInfo uint32 + EncapLimit uint8 + EncapType uint16 + EncapFlags uint16 + EncapSport uint16 + EncapDport uint16 +} + +func (ip6tnl *Ip6tnl) Attrs() *LinkAttrs { + return &ip6tnl.LinkAttrs +} + +func (ip6tnl *Ip6tnl) Type() string { + return "ip6tnl" +} + +type Sittun struct { + LinkAttrs + Link uint32 + Ttl uint8 + Tos uint8 + PMtuDisc uint8 + Proto uint8 + Local net.IP + Remote net.IP + EncapLimit uint8 + EncapType uint16 + EncapFlags uint16 + EncapSport uint16 + EncapDport uint16 +} + +func (sittun *Sittun) Attrs() *LinkAttrs { + return &sittun.LinkAttrs +} + +func (sittun *Sittun) Type() string { + return "sit" +} + +type Vti struct { + LinkAttrs + IKey uint32 + OKey uint32 + Link uint32 + Local net.IP + Remote net.IP +} + +func (vti *Vti) Attrs() *LinkAttrs { + return &vti.LinkAttrs +} + +func (vti *Vti) Type() string { + if vti.Local.To4() == nil { + return "vti6" + } + return "vti" +} + +type Gretun struct { + LinkAttrs + Link uint32 + IFlags uint16 + OFlags uint16 + IKey uint32 + OKey uint32 + Local net.IP + Remote net.IP + Ttl uint8 + Tos uint8 + PMtuDisc uint8 + EncapType uint16 + EncapFlags uint16 + EncapSport uint16 + EncapDport uint16 +} + +func (gretun *Gretun) Attrs() *LinkAttrs { + return &gretun.LinkAttrs +} + +func (gretun *Gretun) Type() string { + if gretun.Local.To4() == nil { + return "ip6gre" + } + return "gre" +} + +type Vrf struct { + LinkAttrs + Table uint32 +} + +func (vrf *Vrf) Attrs() *LinkAttrs { + return &vrf.LinkAttrs +} + +func (vrf *Vrf) Type() string { + return "vrf" +} + +type GTP struct { + LinkAttrs + FD0 int + FD1 int + Role int + PDPHashsize int +} + +func (gtp *GTP) Attrs() *LinkAttrs { + return >p.LinkAttrs +} + +func (gtp *GTP) Type() string { + return "gtp" +} + +// Virtual XFRM Interfaces +// Named "xfrmi" to prevent confusion with XFRM objects +type Xfrmi struct { + LinkAttrs + Ifid uint32 +} + +func (xfrm *Xfrmi) Attrs() *LinkAttrs { + return &xfrm.LinkAttrs +} + +func (xfrm *Xfrmi) Type() string { + return "xfrm" +} + +// IPoIB interface + +type IPoIBMode uint16 + +func (m *IPoIBMode) String() string { + str, ok := iPoIBModeToString[*m] + if !ok { + return fmt.Sprintf("mode(%d)", *m) + } + return str +} + +const ( + IPOIB_MODE_DATAGRAM = iota + IPOIB_MODE_CONNECTED +) + +var iPoIBModeToString = map[IPoIBMode]string{ + IPOIB_MODE_DATAGRAM: "datagram", + IPOIB_MODE_CONNECTED: "connected", +} + +var StringToIPoIBMode = map[string]IPoIBMode{ + "datagram": IPOIB_MODE_DATAGRAM, + "connected": IPOIB_MODE_CONNECTED, +} + +const ( + CAN_STATE_ERROR_ACTIVE = iota + CAN_STATE_ERROR_WARNING + CAN_STATE_ERROR_PASSIVE + CAN_STATE_BUS_OFF + CAN_STATE_STOPPED + CAN_STATE_SLEEPING +) + +type Can struct { + LinkAttrs + + BitRate uint32 + SamplePoint uint32 + TimeQuanta uint32 + PropagationSegment uint32 + PhaseSegment1 uint32 + PhaseSegment2 uint32 + SyncJumpWidth uint32 + BitRatePreScaler uint32 + + Name string + TimeSegment1Min uint32 + TimeSegment1Max uint32 + TimeSegment2Min uint32 + TimeSegment2Max uint32 + SyncJumpWidthMax uint32 + BitRatePreScalerMin uint32 + BitRatePreScalerMax uint32 + BitRatePreScalerInc uint32 + + ClockFrequency uint32 + + State uint32 + + Mask uint32 + Flags uint32 + + TxError uint16 + RxError uint16 + + RestartMs uint32 +} + +func (can *Can) Attrs() *LinkAttrs { + return &can.LinkAttrs +} + +func (can *Can) Type() string { + return "can" +} + +type IPoIB struct { + LinkAttrs + Pkey uint16 + Mode IPoIBMode + Umcast uint16 +} + +func (ipoib *IPoIB) Attrs() *LinkAttrs { + return &ipoib.LinkAttrs +} + +func (ipoib *IPoIB) Type() string { + return "ipoib" +} + +// iproute2 supported devices; +// vlan | veth | vcan | dummy | ifb | macvlan | macvtap | +// bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan | +// gre | gretap | ip6gre | ip6gretap | vti | vti6 | nlmon | +// bond_slave | ipvlan | xfrm + +// LinkNotFoundError wraps the various not found errors when +// getting/reading links. This is intended for better error +// handling by dependent code so that "not found error" can +// be distinguished from other errors +type LinkNotFoundError struct { + error +} diff --git a/vendor/github.com/vishvananda/netlink/link_linux.go b/vendor/github.com/vishvananda/netlink/link_linux.go new file mode 100644 index 000000000..3b959299c --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/link_linux.go @@ -0,0 +1,3305 @@ +package netlink + +import ( + "bytes" + "encoding/binary" + "fmt" + "io/ioutil" + "net" + "os" + "strconv" + "strings" + "syscall" + "unsafe" + + "github.com/vishvananda/netlink/nl" + "github.com/vishvananda/netns" + "golang.org/x/sys/unix" +) + +const ( + SizeofLinkStats32 = 0x5c + SizeofLinkStats64 = 0xb8 +) + +const ( + TUNTAP_MODE_TUN TuntapMode = unix.IFF_TUN + TUNTAP_MODE_TAP TuntapMode = unix.IFF_TAP + TUNTAP_DEFAULTS TuntapFlag = unix.IFF_TUN_EXCL | unix.IFF_ONE_QUEUE + TUNTAP_VNET_HDR TuntapFlag = unix.IFF_VNET_HDR + TUNTAP_TUN_EXCL TuntapFlag = unix.IFF_TUN_EXCL + TUNTAP_NO_PI TuntapFlag = unix.IFF_NO_PI + TUNTAP_ONE_QUEUE TuntapFlag = unix.IFF_ONE_QUEUE + TUNTAP_MULTI_QUEUE TuntapFlag = unix.IFF_MULTI_QUEUE + TUNTAP_MULTI_QUEUE_DEFAULTS TuntapFlag = TUNTAP_MULTI_QUEUE | TUNTAP_NO_PI +) + +var StringToTuntapModeMap = map[string]TuntapMode{ + "tun": TUNTAP_MODE_TUN, + "tap": TUNTAP_MODE_TAP, +} + +func (ttm TuntapMode) String() string { + switch ttm { + case TUNTAP_MODE_TUN: + return "tun" + case TUNTAP_MODE_TAP: + return "tap" + } + return "unknown" +} + +const ( + VF_LINK_STATE_AUTO uint32 = 0 + VF_LINK_STATE_ENABLE uint32 = 1 + VF_LINK_STATE_DISABLE uint32 = 2 +) + +var lookupByDump = false + +var macvlanModes = [...]uint32{ + 0, + nl.MACVLAN_MODE_PRIVATE, + nl.MACVLAN_MODE_VEPA, + nl.MACVLAN_MODE_BRIDGE, + nl.MACVLAN_MODE_PASSTHRU, + nl.MACVLAN_MODE_SOURCE, +} + +func ensureIndex(link *LinkAttrs) { + if link != nil && link.Index == 0 { + newlink, _ := LinkByName(link.Name) + if newlink != nil { + link.Index = newlink.Attrs().Index + } + } +} + +func (h *Handle) ensureIndex(link *LinkAttrs) { + if link != nil && link.Index == 0 { + newlink, _ := h.LinkByName(link.Name) + if newlink != nil { + link.Index = newlink.Attrs().Index + } + } +} + +func (h *Handle) LinkSetARPOff(link Link) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Change |= unix.IFF_NOARP + msg.Flags |= unix.IFF_NOARP + msg.Index = int32(base.Index) + req.AddData(msg) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +func LinkSetARPOff(link Link) error { + return pkgHandle.LinkSetARPOff(link) +} + +func (h *Handle) LinkSetARPOn(link Link) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Change |= unix.IFF_NOARP + msg.Flags &= ^uint32(unix.IFF_NOARP) + msg.Index = int32(base.Index) + req.AddData(msg) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +func LinkSetARPOn(link Link) error { + return pkgHandle.LinkSetARPOn(link) +} + +func (h *Handle) SetPromiscOn(link Link) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Change = unix.IFF_PROMISC + msg.Flags = unix.IFF_PROMISC + msg.Index = int32(base.Index) + req.AddData(msg) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetAllmulticastOn enables the reception of all hardware multicast packets for the link device. +// Equivalent to: `ip link set $link allmulticast on` +func LinkSetAllmulticastOn(link Link) error { + return pkgHandle.LinkSetAllmulticastOn(link) +} + +// LinkSetAllmulticastOn enables the reception of all hardware multicast packets for the link device. +// Equivalent to: `ip link set $link allmulticast on` +func (h *Handle) LinkSetAllmulticastOn(link Link) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Change = unix.IFF_ALLMULTI + msg.Flags = unix.IFF_ALLMULTI + + msg.Index = int32(base.Index) + req.AddData(msg) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetAllmulticastOff disables the reception of all hardware multicast packets for the link device. +// Equivalent to: `ip link set $link allmulticast off` +func LinkSetAllmulticastOff(link Link) error { + return pkgHandle.LinkSetAllmulticastOff(link) +} + +// LinkSetAllmulticastOff disables the reception of all hardware multicast packets for the link device. +// Equivalent to: `ip link set $link allmulticast off` +func (h *Handle) LinkSetAllmulticastOff(link Link) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Change = unix.IFF_ALLMULTI + msg.Index = int32(base.Index) + req.AddData(msg) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +func MacvlanMACAddrAdd(link Link, addr net.HardwareAddr) error { + return pkgHandle.MacvlanMACAddrAdd(link, addr) +} + +func (h *Handle) MacvlanMACAddrAdd(link Link, addr net.HardwareAddr) error { + return h.macvlanMACAddrChange(link, []net.HardwareAddr{addr}, nl.MACVLAN_MACADDR_ADD) +} + +func MacvlanMACAddrDel(link Link, addr net.HardwareAddr) error { + return pkgHandle.MacvlanMACAddrDel(link, addr) +} + +func (h *Handle) MacvlanMACAddrDel(link Link, addr net.HardwareAddr) error { + return h.macvlanMACAddrChange(link, []net.HardwareAddr{addr}, nl.MACVLAN_MACADDR_DEL) +} + +func MacvlanMACAddrFlush(link Link) error { + return pkgHandle.MacvlanMACAddrFlush(link) +} + +func (h *Handle) MacvlanMACAddrFlush(link Link) error { + return h.macvlanMACAddrChange(link, nil, nl.MACVLAN_MACADDR_FLUSH) +} + +func MacvlanMACAddrSet(link Link, addrs []net.HardwareAddr) error { + return pkgHandle.MacvlanMACAddrSet(link, addrs) +} + +func (h *Handle) MacvlanMACAddrSet(link Link, addrs []net.HardwareAddr) error { + return h.macvlanMACAddrChange(link, addrs, nl.MACVLAN_MACADDR_SET) +} + +func (h *Handle) macvlanMACAddrChange(link Link, addrs []net.HardwareAddr, mode uint32) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil) + linkInfo.AddRtAttr(nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type())) + inner := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + + // IFLA_MACVLAN_MACADDR_MODE = mode + b := make([]byte, 4) + native.PutUint32(b, mode) + inner.AddRtAttr(nl.IFLA_MACVLAN_MACADDR_MODE, b) + + // populate message with MAC addrs, if necessary + switch mode { + case nl.MACVLAN_MACADDR_ADD, nl.MACVLAN_MACADDR_DEL: + if len(addrs) == 1 { + inner.AddRtAttr(nl.IFLA_MACVLAN_MACADDR, []byte(addrs[0])) + } + case nl.MACVLAN_MACADDR_SET: + mad := inner.AddRtAttr(nl.IFLA_MACVLAN_MACADDR_DATA, nil) + for _, addr := range addrs { + mad.AddRtAttr(nl.IFLA_MACVLAN_MACADDR, []byte(addr)) + } + } + + req.AddData(linkInfo) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetMacvlanMode sets the mode of a macvlan or macvtap link device. +// Note that passthrough mode cannot be set to and from and will fail. +// Equivalent to: `ip link set $link type (macvlan|macvtap) mode $mode +func LinkSetMacvlanMode(link Link, mode MacvlanMode) error { + return pkgHandle.LinkSetMacvlanMode(link, mode) +} + +// LinkSetMacvlanMode sets the mode of the macvlan or macvtap link device. +// Note that passthrough mode cannot be set to and from and will fail. +// Equivalent to: `ip link set $link type (macvlan|macvtap) mode $mode +func (h *Handle) LinkSetMacvlanMode(link Link, mode MacvlanMode) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil) + linkInfo.AddRtAttr(nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type())) + + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[mode])) + + req.AddData(linkInfo) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +func BridgeSetMcastSnoop(link Link, on bool) error { + return pkgHandle.BridgeSetMcastSnoop(link, on) +} + +func (h *Handle) BridgeSetMcastSnoop(link Link, on bool) error { + bridge := link.(*Bridge) + bridge.MulticastSnooping = &on + return h.linkModify(bridge, unix.NLM_F_ACK) +} + +func BridgeSetVlanFiltering(link Link, on bool) error { + return pkgHandle.BridgeSetVlanFiltering(link, on) +} + +func (h *Handle) BridgeSetVlanFiltering(link Link, on bool) error { + bridge := link.(*Bridge) + bridge.VlanFiltering = &on + return h.linkModify(bridge, unix.NLM_F_ACK) +} + +func SetPromiscOn(link Link) error { + return pkgHandle.SetPromiscOn(link) +} + +func (h *Handle) SetPromiscOff(link Link) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Change = unix.IFF_PROMISC + msg.Index = int32(base.Index) + req.AddData(msg) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +func SetPromiscOff(link Link) error { + return pkgHandle.SetPromiscOff(link) +} + +// LinkSetUp enables the link device. +// Equivalent to: `ip link set $link up` +func LinkSetUp(link Link) error { + return pkgHandle.LinkSetUp(link) +} + +// LinkSetUp enables the link device. +// Equivalent to: `ip link set $link up` +func (h *Handle) LinkSetUp(link Link) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Change = unix.IFF_UP + msg.Flags = unix.IFF_UP + msg.Index = int32(base.Index) + req.AddData(msg) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetDown disables link device. +// Equivalent to: `ip link set $link down` +func LinkSetDown(link Link) error { + return pkgHandle.LinkSetDown(link) +} + +// LinkSetDown disables link device. +// Equivalent to: `ip link set $link down` +func (h *Handle) LinkSetDown(link Link) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Change = unix.IFF_UP + msg.Index = int32(base.Index) + req.AddData(msg) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetMTU sets the mtu of the link device. +// Equivalent to: `ip link set $link mtu $mtu` +func LinkSetMTU(link Link, mtu int) error { + return pkgHandle.LinkSetMTU(link, mtu) +} + +// LinkSetMTU sets the mtu of the link device. +// Equivalent to: `ip link set $link mtu $mtu` +func (h *Handle) LinkSetMTU(link Link, mtu int) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + b := make([]byte, 4) + native.PutUint32(b, uint32(mtu)) + + data := nl.NewRtAttr(unix.IFLA_MTU, b) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetName sets the name of the link device. +// Equivalent to: `ip link set $link name $name` +func LinkSetName(link Link, name string) error { + return pkgHandle.LinkSetName(link, name) +} + +// LinkSetName sets the name of the link device. +// Equivalent to: `ip link set $link name $name` +func (h *Handle) LinkSetName(link Link, name string) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + data := nl.NewRtAttr(unix.IFLA_IFNAME, []byte(name)) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetAlias sets the alias of the link device. +// Equivalent to: `ip link set dev $link alias $name` +func LinkSetAlias(link Link, name string) error { + return pkgHandle.LinkSetAlias(link, name) +} + +// LinkSetAlias sets the alias of the link device. +// Equivalent to: `ip link set dev $link alias $name` +func (h *Handle) LinkSetAlias(link Link, name string) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + data := nl.NewRtAttr(unix.IFLA_IFALIAS, []byte(name)) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetHardwareAddr sets the hardware address of the link device. +// Equivalent to: `ip link set $link address $hwaddr` +func LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error { + return pkgHandle.LinkSetHardwareAddr(link, hwaddr) +} + +// LinkSetHardwareAddr sets the hardware address of the link device. +// Equivalent to: `ip link set $link address $hwaddr` +func (h *Handle) LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + data := nl.NewRtAttr(unix.IFLA_ADDRESS, []byte(hwaddr)) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetVfHardwareAddr sets the hardware address of a vf for the link. +// Equivalent to: `ip link set $link vf $vf mac $hwaddr` +func LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error { + return pkgHandle.LinkSetVfHardwareAddr(link, vf, hwaddr) +} + +// LinkSetVfHardwareAddr sets the hardware address of a vf for the link. +// Equivalent to: `ip link set $link vf $vf mac $hwaddr` +func (h *Handle) LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil) + info := data.AddRtAttr(nl.IFLA_VF_INFO, nil) + vfmsg := nl.VfMac{ + Vf: uint32(vf), + } + copy(vfmsg.Mac[:], []byte(hwaddr)) + info.AddRtAttr(nl.IFLA_VF_MAC, vfmsg.Serialize()) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetVfVlan sets the vlan of a vf for the link. +// Equivalent to: `ip link set $link vf $vf vlan $vlan` +func LinkSetVfVlan(link Link, vf, vlan int) error { + return pkgHandle.LinkSetVfVlan(link, vf, vlan) +} + +// LinkSetVfVlan sets the vlan of a vf for the link. +// Equivalent to: `ip link set $link vf $vf vlan $vlan` +func (h *Handle) LinkSetVfVlan(link Link, vf, vlan int) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil) + info := data.AddRtAttr(nl.IFLA_VF_INFO, nil) + vfmsg := nl.VfVlan{ + Vf: uint32(vf), + Vlan: uint32(vlan), + } + info.AddRtAttr(nl.IFLA_VF_VLAN, vfmsg.Serialize()) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetVfVlanQos sets the vlan and qos priority of a vf for the link. +// Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos` +func LinkSetVfVlanQos(link Link, vf, vlan, qos int) error { + return pkgHandle.LinkSetVfVlanQos(link, vf, vlan, qos) +} + +// LinkSetVfVlanQos sets the vlan and qos priority of a vf for the link. +// Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos` +func (h *Handle) LinkSetVfVlanQos(link Link, vf, vlan, qos int) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil) + info := nl.NewRtAttrChild(data, nl.IFLA_VF_INFO, nil) + vfmsg := nl.VfVlan{ + Vf: uint32(vf), + Vlan: uint32(vlan), + Qos: uint32(qos), + } + nl.NewRtAttrChild(info, nl.IFLA_VF_VLAN, vfmsg.Serialize()) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetVfTxRate sets the tx rate of a vf for the link. +// Equivalent to: `ip link set $link vf $vf rate $rate` +func LinkSetVfTxRate(link Link, vf, rate int) error { + return pkgHandle.LinkSetVfTxRate(link, vf, rate) +} + +// LinkSetVfTxRate sets the tx rate of a vf for the link. +// Equivalent to: `ip link set $link vf $vf rate $rate` +func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil) + info := data.AddRtAttr(nl.IFLA_VF_INFO, nil) + vfmsg := nl.VfTxRate{ + Vf: uint32(vf), + Rate: uint32(rate), + } + info.AddRtAttr(nl.IFLA_VF_TX_RATE, vfmsg.Serialize()) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetVfRate sets the min and max tx rate of a vf for the link. +// Equivalent to: `ip link set $link vf $vf min_tx_rate $min_rate max_tx_rate $max_rate` +func LinkSetVfRate(link Link, vf, minRate, maxRate int) error { + return pkgHandle.LinkSetVfRate(link, vf, minRate, maxRate) +} + +// LinkSetVfRate sets the min and max tx rate of a vf for the link. +// Equivalent to: `ip link set $link vf $vf min_tx_rate $min_rate max_tx_rate $max_rate` +func (h *Handle) LinkSetVfRate(link Link, vf, minRate, maxRate int) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil) + info := data.AddRtAttr(nl.IFLA_VF_INFO, nil) + vfmsg := nl.VfRate{ + Vf: uint32(vf), + MinTxRate: uint32(minRate), + MaxTxRate: uint32(maxRate), + } + info.AddRtAttr(nl.IFLA_VF_RATE, vfmsg.Serialize()) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetVfState enables/disables virtual link state on a vf. +// Equivalent to: `ip link set $link vf $vf state $state` +func LinkSetVfState(link Link, vf int, state uint32) error { + return pkgHandle.LinkSetVfState(link, vf, state) +} + +// LinkSetVfState enables/disables virtual link state on a vf. +// Equivalent to: `ip link set $link vf $vf state $state` +func (h *Handle) LinkSetVfState(link Link, vf int, state uint32) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil) + info := data.AddRtAttr(nl.IFLA_VF_INFO, nil) + vfmsg := nl.VfLinkState{ + Vf: uint32(vf), + LinkState: state, + } + info.AddRtAttr(nl.IFLA_VF_LINK_STATE, vfmsg.Serialize()) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetVfSpoofchk enables/disables spoof check on a vf for the link. +// Equivalent to: `ip link set $link vf $vf spoofchk $check` +func LinkSetVfSpoofchk(link Link, vf int, check bool) error { + return pkgHandle.LinkSetVfSpoofchk(link, vf, check) +} + +// LinkSetVfSpoofchk enables/disables spoof check on a vf for the link. +// Equivalent to: `ip link set $link vf $vf spoofchk $check` +func (h *Handle) LinkSetVfSpoofchk(link Link, vf int, check bool) error { + var setting uint32 + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil) + info := data.AddRtAttr(nl.IFLA_VF_INFO, nil) + if check { + setting = 1 + } + vfmsg := nl.VfSpoofchk{ + Vf: uint32(vf), + Setting: setting, + } + info.AddRtAttr(nl.IFLA_VF_SPOOFCHK, vfmsg.Serialize()) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetVfTrust enables/disables trust state on a vf for the link. +// Equivalent to: `ip link set $link vf $vf trust $state` +func LinkSetVfTrust(link Link, vf int, state bool) error { + return pkgHandle.LinkSetVfTrust(link, vf, state) +} + +// LinkSetVfTrust enables/disables trust state on a vf for the link. +// Equivalent to: `ip link set $link vf $vf trust $state` +func (h *Handle) LinkSetVfTrust(link Link, vf int, state bool) error { + var setting uint32 + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil) + info := data.AddRtAttr(nl.IFLA_VF_INFO, nil) + if state { + setting = 1 + } + vfmsg := nl.VfTrust{ + Vf: uint32(vf), + Setting: setting, + } + info.AddRtAttr(nl.IFLA_VF_TRUST, vfmsg.Serialize()) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetVfNodeGUID sets the node GUID of a vf for the link. +// Equivalent to: `ip link set dev $link vf $vf node_guid $nodeguid` +func LinkSetVfNodeGUID(link Link, vf int, nodeguid net.HardwareAddr) error { + return pkgHandle.LinkSetVfGUID(link, vf, nodeguid, nl.IFLA_VF_IB_NODE_GUID) +} + +// LinkSetVfPortGUID sets the port GUID of a vf for the link. +// Equivalent to: `ip link set dev $link vf $vf port_guid $portguid` +func LinkSetVfPortGUID(link Link, vf int, portguid net.HardwareAddr) error { + return pkgHandle.LinkSetVfGUID(link, vf, portguid, nl.IFLA_VF_IB_PORT_GUID) +} + +// LinkSetVfGUID sets the node or port GUID of a vf for the link. +func (h *Handle) LinkSetVfGUID(link Link, vf int, vfGuid net.HardwareAddr, guidType int) error { + var err error + var guid uint64 + + buf := bytes.NewBuffer(vfGuid) + err = binary.Read(buf, binary.BigEndian, &guid) + if err != nil { + return err + } + + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil) + info := data.AddRtAttr(nl.IFLA_VF_INFO, nil) + vfmsg := nl.VfGUID{ + Vf: uint32(vf), + GUID: guid, + } + info.AddRtAttr(guidType, vfmsg.Serialize()) + req.AddData(data) + + _, err = req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetMaster sets the master of the link device. +// Equivalent to: `ip link set $link master $master` +func LinkSetMaster(link Link, master Link) error { + return pkgHandle.LinkSetMaster(link, master) +} + +// LinkSetMaster sets the master of the link device. +// Equivalent to: `ip link set $link master $master` +func (h *Handle) LinkSetMaster(link Link, master Link) error { + index := 0 + if master != nil { + masterBase := master.Attrs() + h.ensureIndex(masterBase) + index = masterBase.Index + } + if index <= 0 { + return fmt.Errorf("Device does not exist") + } + return h.LinkSetMasterByIndex(link, index) +} + +// LinkSetNoMaster removes the master of the link device. +// Equivalent to: `ip link set $link nomaster` +func LinkSetNoMaster(link Link) error { + return pkgHandle.LinkSetNoMaster(link) +} + +// LinkSetNoMaster removes the master of the link device. +// Equivalent to: `ip link set $link nomaster` +func (h *Handle) LinkSetNoMaster(link Link) error { + return h.LinkSetMasterByIndex(link, 0) +} + +// LinkSetMasterByIndex sets the master of the link device. +// Equivalent to: `ip link set $link master $master` +func LinkSetMasterByIndex(link Link, masterIndex int) error { + return pkgHandle.LinkSetMasterByIndex(link, masterIndex) +} + +// LinkSetMasterByIndex sets the master of the link device. +// Equivalent to: `ip link set $link master $master` +func (h *Handle) LinkSetMasterByIndex(link Link, masterIndex int) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + b := make([]byte, 4) + native.PutUint32(b, uint32(masterIndex)) + + data := nl.NewRtAttr(unix.IFLA_MASTER, b) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetNsPid puts the device into a new network namespace. The +// pid must be a pid of a running process. +// Equivalent to: `ip link set $link netns $pid` +func LinkSetNsPid(link Link, nspid int) error { + return pkgHandle.LinkSetNsPid(link, nspid) +} + +// LinkSetNsPid puts the device into a new network namespace. The +// pid must be a pid of a running process. +// Equivalent to: `ip link set $link netns $pid` +func (h *Handle) LinkSetNsPid(link Link, nspid int) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + b := make([]byte, 4) + native.PutUint32(b, uint32(nspid)) + + data := nl.NewRtAttr(unix.IFLA_NET_NS_PID, b) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetNsFd puts the device into a new network namespace. The +// fd must be an open file descriptor to a network namespace. +// Similar to: `ip link set $link netns $ns` +func LinkSetNsFd(link Link, fd int) error { + return pkgHandle.LinkSetNsFd(link, fd) +} + +// LinkSetNsFd puts the device into a new network namespace. The +// fd must be an open file descriptor to a network namespace. +// Similar to: `ip link set $link netns $ns` +func (h *Handle) LinkSetNsFd(link Link, fd int) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + b := make([]byte, 4) + native.PutUint32(b, uint32(fd)) + + data := nl.NewRtAttr(unix.IFLA_NET_NS_FD, b) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetXdpFd adds a bpf function to the driver. The fd must be a bpf +// program loaded with bpf(type=BPF_PROG_TYPE_XDP) +func LinkSetXdpFd(link Link, fd int) error { + return LinkSetXdpFdWithFlags(link, fd, 0) +} + +// LinkSetXdpFdWithFlags adds a bpf function to the driver with the given +// options. The fd must be a bpf program loaded with bpf(type=BPF_PROG_TYPE_XDP) +func LinkSetXdpFdWithFlags(link Link, fd, flags int) error { + base := link.Attrs() + ensureIndex(base) + req := nl.NewNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + addXdpAttrs(&LinkXdp{Fd: fd, Flags: uint32(flags)}, req) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +func boolAttr(val bool) []byte { + var v uint8 + if val { + v = 1 + } + return nl.Uint8Attr(v) +} + +type vxlanPortRange struct { + Lo, Hi uint16 +} + +func addVxlanAttrs(vxlan *Vxlan, linkInfo *nl.RtAttr) { + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + + if vxlan.FlowBased { + vxlan.VxlanId = 0 + } + + data.AddRtAttr(nl.IFLA_VXLAN_ID, nl.Uint32Attr(uint32(vxlan.VxlanId))) + + if vxlan.VtepDevIndex != 0 { + data.AddRtAttr(nl.IFLA_VXLAN_LINK, nl.Uint32Attr(uint32(vxlan.VtepDevIndex))) + } + if vxlan.SrcAddr != nil { + ip := vxlan.SrcAddr.To4() + if ip != nil { + data.AddRtAttr(nl.IFLA_VXLAN_LOCAL, []byte(ip)) + } else { + ip = vxlan.SrcAddr.To16() + if ip != nil { + data.AddRtAttr(nl.IFLA_VXLAN_LOCAL6, []byte(ip)) + } + } + } + if vxlan.Group != nil { + group := vxlan.Group.To4() + if group != nil { + data.AddRtAttr(nl.IFLA_VXLAN_GROUP, []byte(group)) + } else { + group = vxlan.Group.To16() + if group != nil { + data.AddRtAttr(nl.IFLA_VXLAN_GROUP6, []byte(group)) + } + } + } + + data.AddRtAttr(nl.IFLA_VXLAN_TTL, nl.Uint8Attr(uint8(vxlan.TTL))) + data.AddRtAttr(nl.IFLA_VXLAN_TOS, nl.Uint8Attr(uint8(vxlan.TOS))) + data.AddRtAttr(nl.IFLA_VXLAN_LEARNING, boolAttr(vxlan.Learning)) + data.AddRtAttr(nl.IFLA_VXLAN_PROXY, boolAttr(vxlan.Proxy)) + data.AddRtAttr(nl.IFLA_VXLAN_RSC, boolAttr(vxlan.RSC)) + data.AddRtAttr(nl.IFLA_VXLAN_L2MISS, boolAttr(vxlan.L2miss)) + data.AddRtAttr(nl.IFLA_VXLAN_L3MISS, boolAttr(vxlan.L3miss)) + data.AddRtAttr(nl.IFLA_VXLAN_UDP_ZERO_CSUM6_TX, boolAttr(vxlan.UDP6ZeroCSumTx)) + data.AddRtAttr(nl.IFLA_VXLAN_UDP_ZERO_CSUM6_RX, boolAttr(vxlan.UDP6ZeroCSumRx)) + + if vxlan.UDPCSum { + data.AddRtAttr(nl.IFLA_VXLAN_UDP_CSUM, boolAttr(vxlan.UDPCSum)) + } + if vxlan.GBP { + data.AddRtAttr(nl.IFLA_VXLAN_GBP, []byte{}) + } + if vxlan.FlowBased { + data.AddRtAttr(nl.IFLA_VXLAN_FLOWBASED, boolAttr(vxlan.FlowBased)) + } + if vxlan.NoAge { + data.AddRtAttr(nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(0)) + } else if vxlan.Age > 0 { + data.AddRtAttr(nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(uint32(vxlan.Age))) + } + if vxlan.Limit > 0 { + data.AddRtAttr(nl.IFLA_VXLAN_LIMIT, nl.Uint32Attr(uint32(vxlan.Limit))) + } + if vxlan.Port > 0 { + data.AddRtAttr(nl.IFLA_VXLAN_PORT, htons(uint16(vxlan.Port))) + } + if vxlan.PortLow > 0 || vxlan.PortHigh > 0 { + pr := vxlanPortRange{uint16(vxlan.PortLow), uint16(vxlan.PortHigh)} + + buf := new(bytes.Buffer) + binary.Write(buf, binary.BigEndian, &pr) + + data.AddRtAttr(nl.IFLA_VXLAN_PORT_RANGE, buf.Bytes()) + } +} + +func addBondAttrs(bond *Bond, linkInfo *nl.RtAttr) { + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + if bond.Mode >= 0 { + data.AddRtAttr(nl.IFLA_BOND_MODE, nl.Uint8Attr(uint8(bond.Mode))) + } + if bond.ActiveSlave >= 0 { + data.AddRtAttr(nl.IFLA_BOND_ACTIVE_SLAVE, nl.Uint32Attr(uint32(bond.ActiveSlave))) + } + if bond.Miimon >= 0 { + data.AddRtAttr(nl.IFLA_BOND_MIIMON, nl.Uint32Attr(uint32(bond.Miimon))) + } + if bond.UpDelay >= 0 { + data.AddRtAttr(nl.IFLA_BOND_UPDELAY, nl.Uint32Attr(uint32(bond.UpDelay))) + } + if bond.DownDelay >= 0 { + data.AddRtAttr(nl.IFLA_BOND_DOWNDELAY, nl.Uint32Attr(uint32(bond.DownDelay))) + } + if bond.UseCarrier >= 0 { + data.AddRtAttr(nl.IFLA_BOND_USE_CARRIER, nl.Uint8Attr(uint8(bond.UseCarrier))) + } + if bond.ArpInterval >= 0 { + data.AddRtAttr(nl.IFLA_BOND_ARP_INTERVAL, nl.Uint32Attr(uint32(bond.ArpInterval))) + } + if bond.ArpIpTargets != nil { + msg := data.AddRtAttr(nl.IFLA_BOND_ARP_IP_TARGET, nil) + for i := range bond.ArpIpTargets { + ip := bond.ArpIpTargets[i].To4() + if ip != nil { + msg.AddRtAttr(i, []byte(ip)) + continue + } + ip = bond.ArpIpTargets[i].To16() + if ip != nil { + msg.AddRtAttr(i, []byte(ip)) + } + } + } + if bond.ArpValidate >= 0 { + data.AddRtAttr(nl.IFLA_BOND_ARP_VALIDATE, nl.Uint32Attr(uint32(bond.ArpValidate))) + } + if bond.ArpAllTargets >= 0 { + data.AddRtAttr(nl.IFLA_BOND_ARP_ALL_TARGETS, nl.Uint32Attr(uint32(bond.ArpAllTargets))) + } + if bond.Primary >= 0 { + data.AddRtAttr(nl.IFLA_BOND_PRIMARY, nl.Uint32Attr(uint32(bond.Primary))) + } + if bond.PrimaryReselect >= 0 { + data.AddRtAttr(nl.IFLA_BOND_PRIMARY_RESELECT, nl.Uint8Attr(uint8(bond.PrimaryReselect))) + } + if bond.FailOverMac >= 0 { + data.AddRtAttr(nl.IFLA_BOND_FAIL_OVER_MAC, nl.Uint8Attr(uint8(bond.FailOverMac))) + } + if bond.XmitHashPolicy >= 0 { + data.AddRtAttr(nl.IFLA_BOND_XMIT_HASH_POLICY, nl.Uint8Attr(uint8(bond.XmitHashPolicy))) + } + if bond.ResendIgmp >= 0 { + data.AddRtAttr(nl.IFLA_BOND_RESEND_IGMP, nl.Uint32Attr(uint32(bond.ResendIgmp))) + } + if bond.NumPeerNotif >= 0 { + data.AddRtAttr(nl.IFLA_BOND_NUM_PEER_NOTIF, nl.Uint8Attr(uint8(bond.NumPeerNotif))) + } + if bond.AllSlavesActive >= 0 { + data.AddRtAttr(nl.IFLA_BOND_ALL_SLAVES_ACTIVE, nl.Uint8Attr(uint8(bond.AllSlavesActive))) + } + if bond.MinLinks >= 0 { + data.AddRtAttr(nl.IFLA_BOND_MIN_LINKS, nl.Uint32Attr(uint32(bond.MinLinks))) + } + if bond.LpInterval >= 0 { + data.AddRtAttr(nl.IFLA_BOND_LP_INTERVAL, nl.Uint32Attr(uint32(bond.LpInterval))) + } + if bond.PacketsPerSlave >= 0 { + data.AddRtAttr(nl.IFLA_BOND_PACKETS_PER_SLAVE, nl.Uint32Attr(uint32(bond.PacketsPerSlave))) + } + if bond.LacpRate >= 0 { + data.AddRtAttr(nl.IFLA_BOND_AD_LACP_RATE, nl.Uint8Attr(uint8(bond.LacpRate))) + } + if bond.AdSelect >= 0 { + data.AddRtAttr(nl.IFLA_BOND_AD_SELECT, nl.Uint8Attr(uint8(bond.AdSelect))) + } + if bond.AdActorSysPrio >= 0 { + data.AddRtAttr(nl.IFLA_BOND_AD_ACTOR_SYS_PRIO, nl.Uint16Attr(uint16(bond.AdActorSysPrio))) + } + if bond.AdUserPortKey >= 0 { + data.AddRtAttr(nl.IFLA_BOND_AD_USER_PORT_KEY, nl.Uint16Attr(uint16(bond.AdUserPortKey))) + } + if bond.AdActorSystem != nil { + data.AddRtAttr(nl.IFLA_BOND_AD_ACTOR_SYSTEM, []byte(bond.AdActorSystem)) + } + if bond.TlbDynamicLb >= 0 { + data.AddRtAttr(nl.IFLA_BOND_TLB_DYNAMIC_LB, nl.Uint8Attr(uint8(bond.TlbDynamicLb))) + } +} + +func cleanupFds(fds []*os.File) { + for _, f := range fds { + f.Close() + } +} + +// LinkAdd adds a new link device. The type and features of the device +// are taken from the parameters in the link object. +// Equivalent to: `ip link add $link` +func LinkAdd(link Link) error { + return pkgHandle.LinkAdd(link) +} + +// LinkAdd adds a new link device. The type and features of the device +// are taken from the parameters in the link object. +// Equivalent to: `ip link add $link` +func (h *Handle) LinkAdd(link Link) error { + return h.linkModify(link, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) +} + +func (h *Handle) LinkModify(link Link) error { + return h.linkModify(link, unix.NLM_F_REQUEST|unix.NLM_F_ACK) +} + +func (h *Handle) linkModify(link Link, flags int) error { + // TODO: support extra data for macvlan + base := link.Attrs() + + // if tuntap, then the name can be empty, OS will provide a name + tuntap, isTuntap := link.(*Tuntap) + + if base.Name == "" && !isTuntap { + return fmt.Errorf("LinkAttrs.Name cannot be empty") + } + + if isTuntap { + if tuntap.Mode < unix.IFF_TUN || tuntap.Mode > unix.IFF_TAP { + return fmt.Errorf("Tuntap.Mode %v unknown", tuntap.Mode) + } + + queues := tuntap.Queues + + var fds []*os.File + var req ifReq + copy(req.Name[:15], base.Name) + + req.Flags = uint16(tuntap.Flags) + + if queues == 0 { //Legacy compatibility + queues = 1 + if tuntap.Flags == 0 { + req.Flags = uint16(TUNTAP_DEFAULTS) + } + } else { + // For best peformance set Flags to TUNTAP_MULTI_QUEUE_DEFAULTS | TUNTAP_VNET_HDR + // when a) KVM has support for this ABI and + // b) the value of the flag is queryable using the TUNGETIFF ioctl + if tuntap.Flags == 0 { + req.Flags = uint16(TUNTAP_MULTI_QUEUE_DEFAULTS) + } + } + + req.Flags |= uint16(tuntap.Mode) + const TUN = "/dev/net/tun" + for i := 0; i < queues; i++ { + localReq := req + fd, err := unix.Open(TUN, os.O_RDWR|syscall.O_CLOEXEC, 0) + if err != nil { + cleanupFds(fds) + return err + } + + _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), uintptr(unix.TUNSETIFF), uintptr(unsafe.Pointer(&localReq))) + if errno != 0 { + // close the new fd + unix.Close(fd) + // and the already opened ones + cleanupFds(fds) + return fmt.Errorf("Tuntap IOCTL TUNSETIFF failed [%d], errno %v", i, errno) + } + + _, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.TUNSETOWNER, uintptr(tuntap.Owner)) + if errno != 0 { + cleanupFds(fds) + return fmt.Errorf("Tuntap IOCTL TUNSETOWNER failed [%d], errno %v", i, errno) + } + + _, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.TUNSETGROUP, uintptr(tuntap.Group)) + if errno != 0 { + cleanupFds(fds) + return fmt.Errorf("Tuntap IOCTL TUNSETGROUP failed [%d], errno %v", i, errno) + } + + // Set the tun device to non-blocking before use. The below comment + // taken from: + // + // https://github.com/mistsys/tuntap/commit/161418c25003bbee77d085a34af64d189df62bea + // + // Note there is a complication because in go, if a device node is + // opened, go sets it to use nonblocking I/O. However a /dev/net/tun + // doesn't work with epoll until after the TUNSETIFF ioctl has been + // done. So we open the unix fd directly, do the ioctl, then put the + // fd in nonblocking mode, an then finally wrap it in a os.File, + // which will see the nonblocking mode and add the fd to the + // pollable set, so later on when we Read() from it blocked the + // calling thread in the kernel. + // + // See + // https://github.com/golang/go/issues/30426 + // which got exposed in go 1.13 by the fix to + // https://github.com/golang/go/issues/30624 + err = unix.SetNonblock(fd, true) + if err != nil { + cleanupFds(fds) + return fmt.Errorf("Tuntap set to non-blocking failed [%d], err %v", i, err) + } + + // create the file from the file descriptor and store it + file := os.NewFile(uintptr(fd), TUN) + fds = append(fds, file) + + // 1) we only care for the name of the first tap in the multi queue set + // 2) if the original name was empty, the localReq has now the actual name + // + // In addition: + // This ensures that the link name is always identical to what the kernel returns. + // Not only in case of an empty name, but also when using name templates. + // e.g. when the provided name is "tap%d", the kernel replaces %d with the next available number. + if i == 0 { + link.Attrs().Name = strings.Trim(string(localReq.Name[:]), "\x00") + } + + } + + // only persist interface if NonPersist is NOT set + if !tuntap.NonPersist { + _, _, errno := unix.Syscall(unix.SYS_IOCTL, fds[0].Fd(), uintptr(unix.TUNSETPERSIST), 1) + if errno != 0 { + cleanupFds(fds) + return fmt.Errorf("Tuntap IOCTL TUNSETPERSIST failed, errno %v", errno) + } + } + + h.ensureIndex(base) + + // can't set master during create, so set it afterwards + if base.MasterIndex != 0 { + // TODO: verify MasterIndex is actually a bridge? + err := h.LinkSetMasterByIndex(link, base.MasterIndex) + if err != nil { + // un-persist (e.g. allow the interface to be removed) the tuntap + // should not hurt if not set prior, condition might be not needed + if !tuntap.NonPersist { + _, _, _ = unix.Syscall(unix.SYS_IOCTL, fds[0].Fd(), uintptr(unix.TUNSETPERSIST), 0) + } + cleanupFds(fds) + return err + } + } + + if tuntap.Queues == 0 { + cleanupFds(fds) + } else { + tuntap.Fds = fds + } + + return nil + } + + req := h.newNetlinkRequest(unix.RTM_NEWLINK, flags) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + // TODO: make it shorter + if base.Flags&net.FlagUp != 0 { + msg.Change = unix.IFF_UP + msg.Flags = unix.IFF_UP + } + if base.Flags&net.FlagBroadcast != 0 { + msg.Change |= unix.IFF_BROADCAST + msg.Flags |= unix.IFF_BROADCAST + } + if base.Flags&net.FlagLoopback != 0 { + msg.Change |= unix.IFF_LOOPBACK + msg.Flags |= unix.IFF_LOOPBACK + } + if base.Flags&net.FlagPointToPoint != 0 { + msg.Change |= unix.IFF_POINTOPOINT + msg.Flags |= unix.IFF_POINTOPOINT + } + if base.Flags&net.FlagMulticast != 0 { + msg.Change |= unix.IFF_MULTICAST + msg.Flags |= unix.IFF_MULTICAST + } + if base.Index != 0 { + msg.Index = int32(base.Index) + } + + req.AddData(msg) + + if base.ParentIndex != 0 { + b := make([]byte, 4) + native.PutUint32(b, uint32(base.ParentIndex)) + data := nl.NewRtAttr(unix.IFLA_LINK, b) + req.AddData(data) + } else if link.Type() == "ipvlan" || link.Type() == "ipoib" { + return fmt.Errorf("Can't create %s link without ParentIndex", link.Type()) + } + + nameData := nl.NewRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(base.Name)) + req.AddData(nameData) + + if base.Alias != "" { + alias := nl.NewRtAttr(unix.IFLA_IFALIAS, []byte(base.Alias)) + req.AddData(alias) + } + + if base.MTU > 0 { + mtu := nl.NewRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU))) + req.AddData(mtu) + } + + if base.TxQLen >= 0 { + qlen := nl.NewRtAttr(unix.IFLA_TXQLEN, nl.Uint32Attr(uint32(base.TxQLen))) + req.AddData(qlen) + } + + if base.HardwareAddr != nil { + hwaddr := nl.NewRtAttr(unix.IFLA_ADDRESS, []byte(base.HardwareAddr)) + req.AddData(hwaddr) + } + + if base.NumTxQueues > 0 { + txqueues := nl.NewRtAttr(unix.IFLA_NUM_TX_QUEUES, nl.Uint32Attr(uint32(base.NumTxQueues))) + req.AddData(txqueues) + } + + if base.NumRxQueues > 0 { + rxqueues := nl.NewRtAttr(unix.IFLA_NUM_RX_QUEUES, nl.Uint32Attr(uint32(base.NumRxQueues))) + req.AddData(rxqueues) + } + + if base.GSOMaxSegs > 0 { + gsoAttr := nl.NewRtAttr(unix.IFLA_GSO_MAX_SEGS, nl.Uint32Attr(base.GSOMaxSegs)) + req.AddData(gsoAttr) + } + + if base.GSOMaxSize > 0 { + gsoAttr := nl.NewRtAttr(unix.IFLA_GSO_MAX_SIZE, nl.Uint32Attr(base.GSOMaxSize)) + req.AddData(gsoAttr) + } + + if base.Group > 0 { + groupAttr := nl.NewRtAttr(unix.IFLA_GROUP, nl.Uint32Attr(base.Group)) + req.AddData(groupAttr) + } + + if base.Namespace != nil { + var attr *nl.RtAttr + switch ns := base.Namespace.(type) { + case NsPid: + val := nl.Uint32Attr(uint32(ns)) + attr = nl.NewRtAttr(unix.IFLA_NET_NS_PID, val) + case NsFd: + val := nl.Uint32Attr(uint32(ns)) + attr = nl.NewRtAttr(unix.IFLA_NET_NS_FD, val) + } + + req.AddData(attr) + } + + if base.Xdp != nil { + addXdpAttrs(base.Xdp, req) + } + + linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil) + linkInfo.AddRtAttr(nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type())) + + switch link := link.(type) { + case *Vlan: + b := make([]byte, 2) + native.PutUint16(b, uint16(link.VlanId)) + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + data.AddRtAttr(nl.IFLA_VLAN_ID, b) + + if link.VlanProtocol != VLAN_PROTOCOL_UNKNOWN { + data.AddRtAttr(nl.IFLA_VLAN_PROTOCOL, htons(uint16(link.VlanProtocol))) + } + case *Veth: + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + peer := data.AddRtAttr(nl.VETH_INFO_PEER, nil) + nl.NewIfInfomsgChild(peer, unix.AF_UNSPEC) + peer.AddRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(link.PeerName)) + if base.TxQLen >= 0 { + peer.AddRtAttr(unix.IFLA_TXQLEN, nl.Uint32Attr(uint32(base.TxQLen))) + } + if base.NumTxQueues > 0 { + peer.AddRtAttr(unix.IFLA_NUM_TX_QUEUES, nl.Uint32Attr(uint32(base.NumTxQueues))) + } + if base.NumRxQueues > 0 { + peer.AddRtAttr(unix.IFLA_NUM_RX_QUEUES, nl.Uint32Attr(uint32(base.NumRxQueues))) + } + if base.MTU > 0 { + peer.AddRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU))) + } + if link.PeerHardwareAddr != nil { + peer.AddRtAttr(unix.IFLA_ADDRESS, []byte(link.PeerHardwareAddr)) + } + if link.PeerNamespace != nil { + switch ns := link.PeerNamespace.(type) { + case NsPid: + val := nl.Uint32Attr(uint32(ns)) + peer.AddRtAttr(unix.IFLA_NET_NS_PID, val) + case NsFd: + val := nl.Uint32Attr(uint32(ns)) + peer.AddRtAttr(unix.IFLA_NET_NS_FD, val) + } + } + case *Vxlan: + addVxlanAttrs(link, linkInfo) + case *Bond: + addBondAttrs(link, linkInfo) + case *IPVlan: + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode))) + data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag))) + case *Macvlan: + if link.Mode != MACVLAN_MODE_DEFAULT { + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode])) + } + case *Macvtap: + if link.Mode != MACVLAN_MODE_DEFAULT { + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode])) + } + case *Geneve: + addGeneveAttrs(link, linkInfo) + case *Gretap: + addGretapAttrs(link, linkInfo) + case *Iptun: + addIptunAttrs(link, linkInfo) + case *Ip6tnl: + addIp6tnlAttrs(link, linkInfo) + case *Sittun: + addSittunAttrs(link, linkInfo) + case *Gretun: + addGretunAttrs(link, linkInfo) + case *Vti: + addVtiAttrs(link, linkInfo) + case *Vrf: + addVrfAttrs(link, linkInfo) + case *Bridge: + addBridgeAttrs(link, linkInfo) + case *GTP: + addGTPAttrs(link, linkInfo) + case *Xfrmi: + addXfrmiAttrs(link, linkInfo) + case *IPoIB: + addIPoIBAttrs(link, linkInfo) + } + + req.AddData(linkInfo) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + if err != nil { + return err + } + + h.ensureIndex(base) + + // can't set master during create, so set it afterwards + if base.MasterIndex != 0 { + // TODO: verify MasterIndex is actually a bridge? + return h.LinkSetMasterByIndex(link, base.MasterIndex) + } + return nil +} + +// LinkDel deletes link device. Either Index or Name must be set in +// the link object for it to be deleted. The other values are ignored. +// Equivalent to: `ip link del $link` +func LinkDel(link Link) error { + return pkgHandle.LinkDel(link) +} + +// LinkDel deletes link device. Either Index or Name must be set in +// the link object for it to be deleted. The other values are ignored. +// Equivalent to: `ip link del $link` +func (h *Handle) LinkDel(link Link) error { + base := link.Attrs() + + h.ensureIndex(base) + + req := h.newNetlinkRequest(unix.RTM_DELLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +func (h *Handle) linkByNameDump(name string) (Link, error) { + links, err := h.LinkList() + if err != nil { + return nil, err + } + + for _, link := range links { + if link.Attrs().Name == name { + return link, nil + } + } + return nil, LinkNotFoundError{fmt.Errorf("Link %s not found", name)} +} + +func (h *Handle) linkByAliasDump(alias string) (Link, error) { + links, err := h.LinkList() + if err != nil { + return nil, err + } + + for _, link := range links { + if link.Attrs().Alias == alias { + return link, nil + } + } + return nil, LinkNotFoundError{fmt.Errorf("Link alias %s not found", alias)} +} + +// LinkByName finds a link by name and returns a pointer to the object. +func LinkByName(name string) (Link, error) { + return pkgHandle.LinkByName(name) +} + +// LinkByName finds a link by name and returns a pointer to the object. +func (h *Handle) LinkByName(name string) (Link, error) { + if h.lookupByDump { + return h.linkByNameDump(name) + } + + req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + req.AddData(msg) + + attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF)) + req.AddData(attr) + + nameData := nl.NewRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(name)) + req.AddData(nameData) + + link, err := execGetLink(req) + if err == unix.EINVAL { + // older kernels don't support looking up via IFLA_IFNAME + // so fall back to dumping all links + h.lookupByDump = true + return h.linkByNameDump(name) + } + + return link, err +} + +// LinkByAlias finds a link by its alias and returns a pointer to the object. +// If there are multiple links with the alias it returns the first one +func LinkByAlias(alias string) (Link, error) { + return pkgHandle.LinkByAlias(alias) +} + +// LinkByAlias finds a link by its alias and returns a pointer to the object. +// If there are multiple links with the alias it returns the first one +func (h *Handle) LinkByAlias(alias string) (Link, error) { + if h.lookupByDump { + return h.linkByAliasDump(alias) + } + + req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + req.AddData(msg) + + attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF)) + req.AddData(attr) + + nameData := nl.NewRtAttr(unix.IFLA_IFALIAS, nl.ZeroTerminated(alias)) + req.AddData(nameData) + + link, err := execGetLink(req) + if err == unix.EINVAL { + // older kernels don't support looking up via IFLA_IFALIAS + // so fall back to dumping all links + h.lookupByDump = true + return h.linkByAliasDump(alias) + } + + return link, err +} + +// LinkByIndex finds a link by index and returns a pointer to the object. +func LinkByIndex(index int) (Link, error) { + return pkgHandle.LinkByIndex(index) +} + +// LinkByIndex finds a link by index and returns a pointer to the object. +func (h *Handle) LinkByIndex(index int) (Link, error) { + req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(index) + req.AddData(msg) + attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF)) + req.AddData(attr) + + return execGetLink(req) +} + +func execGetLink(req *nl.NetlinkRequest) (Link, error) { + msgs, err := req.Execute(unix.NETLINK_ROUTE, 0) + if err != nil { + if errno, ok := err.(syscall.Errno); ok { + if errno == unix.ENODEV { + return nil, LinkNotFoundError{fmt.Errorf("Link not found")} + } + } + return nil, err + } + + switch { + case len(msgs) == 0: + return nil, LinkNotFoundError{fmt.Errorf("Link not found")} + + case len(msgs) == 1: + return LinkDeserialize(nil, msgs[0]) + + default: + return nil, fmt.Errorf("More than one link found") + } +} + +// linkDeserialize deserializes a raw message received from netlink into +// a link object. +func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) { + msg := nl.DeserializeIfInfomsg(m) + + attrs, err := nl.ParseRouteAttr(m[msg.Len():]) + if err != nil { + return nil, err + } + + base := NewLinkAttrs() + base.Index = int(msg.Index) + base.RawFlags = msg.Flags + base.Flags = linkFlags(msg.Flags) + base.EncapType = msg.EncapType() + if msg.Flags&unix.IFF_PROMISC != 0 { + base.Promisc = 1 + } + var ( + link Link + stats32 *LinkStatistics32 + stats64 *LinkStatistics64 + linkType string + linkSlave LinkSlave + slaveType string + ) + for _, attr := range attrs { + switch attr.Attr.Type { + case unix.IFLA_LINKINFO: + infos, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return nil, err + } + for _, info := range infos { + switch info.Attr.Type { + case nl.IFLA_INFO_KIND: + linkType = string(info.Value[:len(info.Value)-1]) + switch linkType { + case "dummy": + link = &Dummy{} + case "ifb": + link = &Ifb{} + case "bridge": + link = &Bridge{} + case "vlan": + link = &Vlan{} + case "veth": + link = &Veth{} + case "wireguard": + link = &Wireguard{} + case "vxlan": + link = &Vxlan{} + case "bond": + link = &Bond{} + case "ipvlan": + link = &IPVlan{} + case "macvlan": + link = &Macvlan{} + case "macvtap": + link = &Macvtap{} + case "geneve": + link = &Geneve{} + case "gretap": + link = &Gretap{} + case "ip6gretap": + link = &Gretap{} + case "ipip": + link = &Iptun{} + case "ip6tnl": + link = &Ip6tnl{} + case "sit": + link = &Sittun{} + case "gre": + link = &Gretun{} + case "ip6gre": + link = &Gretun{} + case "vti", "vti6": + link = &Vti{} + case "vrf": + link = &Vrf{} + case "gtp": + link = >P{} + case "xfrm": + link = &Xfrmi{} + case "tun": + link = &Tuntap{} + case "ipoib": + link = &IPoIB{} + case "can": + link = &Can{} + default: + link = &GenericLink{LinkType: linkType} + } + case nl.IFLA_INFO_DATA: + data, err := nl.ParseRouteAttr(info.Value) + if err != nil { + return nil, err + } + switch linkType { + case "vlan": + parseVlanData(link, data) + case "vxlan": + parseVxlanData(link, data) + case "bond": + parseBondData(link, data) + case "ipvlan": + parseIPVlanData(link, data) + case "macvlan": + parseMacvlanData(link, data) + case "macvtap": + parseMacvtapData(link, data) + case "geneve": + parseGeneveData(link, data) + case "gretap": + parseGretapData(link, data) + case "ip6gretap": + parseGretapData(link, data) + case "ipip": + parseIptunData(link, data) + case "ip6tnl": + parseIp6tnlData(link, data) + case "sit": + parseSittunData(link, data) + case "gre": + parseGretunData(link, data) + case "ip6gre": + parseGretunData(link, data) + case "vti", "vti6": + parseVtiData(link, data) + case "vrf": + parseVrfData(link, data) + case "bridge": + parseBridgeData(link, data) + case "gtp": + parseGTPData(link, data) + case "xfrm": + parseXfrmiData(link, data) + case "tun": + parseTuntapData(link, data) + case "ipoib": + parseIPoIBData(link, data) + case "can": + parseCanData(link, data) + } + case nl.IFLA_INFO_SLAVE_KIND: + slaveType = string(info.Value[:len(info.Value)-1]) + switch slaveType { + case "bond": + linkSlave = &BondSlave{} + } + case nl.IFLA_INFO_SLAVE_DATA: + switch slaveType { + case "bond": + data, err := nl.ParseRouteAttr(info.Value) + if err != nil { + return nil, err + } + parseBondSlaveData(linkSlave, data) + } + } + } + case unix.IFLA_ADDRESS: + var nonzero bool + for _, b := range attr.Value { + if b != 0 { + nonzero = true + } + } + if nonzero { + base.HardwareAddr = attr.Value[:] + } + case unix.IFLA_IFNAME: + base.Name = string(attr.Value[:len(attr.Value)-1]) + case unix.IFLA_MTU: + base.MTU = int(native.Uint32(attr.Value[0:4])) + case unix.IFLA_LINK: + base.ParentIndex = int(native.Uint32(attr.Value[0:4])) + case unix.IFLA_MASTER: + base.MasterIndex = int(native.Uint32(attr.Value[0:4])) + case unix.IFLA_TXQLEN: + base.TxQLen = int(native.Uint32(attr.Value[0:4])) + case unix.IFLA_IFALIAS: + base.Alias = string(attr.Value[:len(attr.Value)-1]) + case unix.IFLA_STATS: + stats32 = new(LinkStatistics32) + if err := binary.Read(bytes.NewBuffer(attr.Value[:]), nl.NativeEndian(), stats32); err != nil { + return nil, err + } + case unix.IFLA_STATS64: + stats64 = new(LinkStatistics64) + if err := binary.Read(bytes.NewBuffer(attr.Value[:]), nl.NativeEndian(), stats64); err != nil { + return nil, err + } + case unix.IFLA_XDP: + xdp, err := parseLinkXdp(attr.Value[:]) + if err != nil { + return nil, err + } + base.Xdp = xdp + case unix.IFLA_PROTINFO | unix.NLA_F_NESTED: + if hdr != nil && hdr.Type == unix.RTM_NEWLINK && + msg.Family == unix.AF_BRIDGE { + attrs, err := nl.ParseRouteAttr(attr.Value[:]) + if err != nil { + return nil, err + } + protinfo := parseProtinfo(attrs) + base.Protinfo = &protinfo + } + case unix.IFLA_OPERSTATE: + base.OperState = LinkOperState(uint8(attr.Value[0])) + case unix.IFLA_LINK_NETNSID: + base.NetNsID = int(native.Uint32(attr.Value[0:4])) + case unix.IFLA_GSO_MAX_SIZE: + base.GSOMaxSize = native.Uint32(attr.Value[0:4]) + case unix.IFLA_GSO_MAX_SEGS: + base.GSOMaxSegs = native.Uint32(attr.Value[0:4]) + case unix.IFLA_VFINFO_LIST: + data, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return nil, err + } + vfs, err := parseVfInfoList(data) + if err != nil { + return nil, err + } + base.Vfs = vfs + case unix.IFLA_NUM_TX_QUEUES: + base.NumTxQueues = int(native.Uint32(attr.Value[0:4])) + case unix.IFLA_NUM_RX_QUEUES: + base.NumRxQueues = int(native.Uint32(attr.Value[0:4])) + case unix.IFLA_GROUP: + base.Group = native.Uint32(attr.Value[0:4]) + } + } + + if stats64 != nil { + base.Statistics = (*LinkStatistics)(stats64) + } else if stats32 != nil { + base.Statistics = (*LinkStatistics)(stats32.to64()) + } + + // Links that don't have IFLA_INFO_KIND are hardware devices + if link == nil { + link = &Device{} + } + *link.Attrs() = base + link.Attrs().Slave = linkSlave + + // If the tuntap attributes are not updated by netlink due to + // an older driver, use sysfs + if link != nil && linkType == "tun" { + tuntap := link.(*Tuntap) + + if tuntap.Mode == 0 { + ifname := tuntap.Attrs().Name + if flags, err := readSysPropAsInt64(ifname, "tun_flags"); err == nil { + + if flags&unix.IFF_TUN != 0 { + tuntap.Mode = unix.IFF_TUN + } else if flags&unix.IFF_TAP != 0 { + tuntap.Mode = unix.IFF_TAP + } + + tuntap.NonPersist = false + if flags&unix.IFF_PERSIST == 0 { + tuntap.NonPersist = true + } + } + + // The sysfs interface for owner/group returns -1 for root user, instead of returning 0. + // So explicitly check for negative value, before assigning the owner uid/gid. + if owner, err := readSysPropAsInt64(ifname, "owner"); err == nil && owner > 0 { + tuntap.Owner = uint32(owner) + } + + if group, err := readSysPropAsInt64(ifname, "group"); err == nil && group > 0 { + tuntap.Group = uint32(group) + } + } + } + + return link, nil +} + +func readSysPropAsInt64(ifname, prop string) (int64, error) { + fname := fmt.Sprintf("/sys/class/net/%s/%s", ifname, prop) + contents, err := ioutil.ReadFile(fname) + if err != nil { + return 0, err + } + + num, err := strconv.ParseInt(strings.TrimSpace(string(contents)), 0, 64) + if err == nil { + return num, nil + } + + return 0, err +} + +// LinkList gets a list of link devices. +// Equivalent to: `ip link show` +func LinkList() ([]Link, error) { + return pkgHandle.LinkList() +} + +// LinkList gets a list of link devices. +// Equivalent to: `ip link show` +func (h *Handle) LinkList() ([]Link, error) { + // NOTE(vish): This duplicates functionality in net/iface_linux.go, but we need + // to get the message ourselves to parse link type. + req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + req.AddData(msg) + attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF)) + req.AddData(attr) + + msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWLINK) + if err != nil { + return nil, err + } + + var res []Link + for _, m := range msgs { + link, err := LinkDeserialize(nil, m) + if err != nil { + return nil, err + } + res = append(res, link) + } + + return res, nil +} + +// LinkUpdate is used to pass information back from LinkSubscribe() +type LinkUpdate struct { + nl.IfInfomsg + Header unix.NlMsghdr + Link +} + +// LinkSubscribe takes a chan down which notifications will be sent +// when links change. Close the 'done' chan to stop subscription. +func LinkSubscribe(ch chan<- LinkUpdate, done <-chan struct{}) error { + return linkSubscribeAt(netns.None(), netns.None(), ch, done, nil, false) +} + +// LinkSubscribeAt works like LinkSubscribe plus it allows the caller +// to choose the network namespace in which to subscribe (ns). +func LinkSubscribeAt(ns netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}) error { + return linkSubscribeAt(ns, netns.None(), ch, done, nil, false) +} + +// LinkSubscribeOptions contains a set of options to use with +// LinkSubscribeWithOptions. +type LinkSubscribeOptions struct { + Namespace *netns.NsHandle + ErrorCallback func(error) + ListExisting bool +} + +// LinkSubscribeWithOptions work like LinkSubscribe but enable to +// provide additional options to modify the behavior. Currently, the +// namespace can be provided as well as an error callback. +func LinkSubscribeWithOptions(ch chan<- LinkUpdate, done <-chan struct{}, options LinkSubscribeOptions) error { + if options.Namespace == nil { + none := netns.None() + options.Namespace = &none + } + return linkSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting) +} + +func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error { + s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_LINK) + if err != nil { + return err + } + if done != nil { + go func() { + <-done + s.Close() + }() + } + if listExisting { + req := pkgHandle.newNetlinkRequest(unix.RTM_GETLINK, + unix.NLM_F_DUMP) + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + req.AddData(msg) + if err := s.Send(req); err != nil { + return err + } + } + go func() { + defer close(ch) + for { + msgs, from, err := s.Receive() + if err != nil { + if cberr != nil { + cberr(err) + } + return + } + if from.Pid != nl.PidKernel { + if cberr != nil { + cberr(fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)) + } + continue + } + for _, m := range msgs { + if m.Header.Type == unix.NLMSG_DONE { + continue + } + if m.Header.Type == unix.NLMSG_ERROR { + native := nl.NativeEndian() + error := int32(native.Uint32(m.Data[0:4])) + if error == 0 { + continue + } + if cberr != nil { + cberr(syscall.Errno(-error)) + } + return + } + ifmsg := nl.DeserializeIfInfomsg(m.Data) + header := unix.NlMsghdr(m.Header) + link, err := LinkDeserialize(&header, m.Data) + if err != nil { + if cberr != nil { + cberr(err) + } + return + } + ch <- LinkUpdate{IfInfomsg: *ifmsg, Header: header, Link: link} + } + } + }() + + return nil +} + +func LinkSetHairpin(link Link, mode bool) error { + return pkgHandle.LinkSetHairpin(link, mode) +} + +func (h *Handle) LinkSetHairpin(link Link, mode bool) error { + return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_MODE) +} + +func LinkSetGuard(link Link, mode bool) error { + return pkgHandle.LinkSetGuard(link, mode) +} + +func (h *Handle) LinkSetGuard(link Link, mode bool) error { + return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_GUARD) +} + +func LinkSetFastLeave(link Link, mode bool) error { + return pkgHandle.LinkSetFastLeave(link, mode) +} + +func (h *Handle) LinkSetFastLeave(link Link, mode bool) error { + return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_FAST_LEAVE) +} + +func LinkSetLearning(link Link, mode bool) error { + return pkgHandle.LinkSetLearning(link, mode) +} + +func (h *Handle) LinkSetLearning(link Link, mode bool) error { + return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_LEARNING) +} + +func LinkSetRootBlock(link Link, mode bool) error { + return pkgHandle.LinkSetRootBlock(link, mode) +} + +func (h *Handle) LinkSetRootBlock(link Link, mode bool) error { + return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROTECT) +} + +func LinkSetFlood(link Link, mode bool) error { + return pkgHandle.LinkSetFlood(link, mode) +} + +func (h *Handle) LinkSetFlood(link Link, mode bool) error { + return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_UNICAST_FLOOD) +} + +func LinkSetBrProxyArp(link Link, mode bool) error { + return pkgHandle.LinkSetBrProxyArp(link, mode) +} + +func (h *Handle) LinkSetBrProxyArp(link Link, mode bool) error { + return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROXYARP) +} + +func LinkSetBrProxyArpWiFi(link Link, mode bool) error { + return pkgHandle.LinkSetBrProxyArpWiFi(link, mode) +} + +func (h *Handle) LinkSetBrProxyArpWiFi(link Link, mode bool) error { + return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROXYARP_WIFI) +} + +func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_BRIDGE) + msg.Index = int32(base.Index) + req.AddData(msg) + + br := nl.NewRtAttr(unix.IFLA_PROTINFO|unix.NLA_F_NESTED, nil) + br.AddRtAttr(attr, boolToByte(mode)) + req.AddData(br) + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + if err != nil { + return err + } + return nil +} + +// LinkSetTxQLen sets the transaction queue length for the link. +// Equivalent to: `ip link set $link txqlen $qlen` +func LinkSetTxQLen(link Link, qlen int) error { + return pkgHandle.LinkSetTxQLen(link, qlen) +} + +// LinkSetTxQLen sets the transaction queue length for the link. +// Equivalent to: `ip link set $link txqlen $qlen` +func (h *Handle) LinkSetTxQLen(link Link, qlen int) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + b := make([]byte, 4) + native.PutUint32(b, uint32(qlen)) + + data := nl.NewRtAttr(unix.IFLA_TXQLEN, b) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetGroup sets the link group id which can be used to perform mass actions +// with iproute2 as well use it as a reference in nft filters. +// Equivalent to: `ip link set $link group $id` +func LinkSetGroup(link Link, group int) error { + return pkgHandle.LinkSetGroup(link, group) +} + +// LinkSetGroup sets the link group id which can be used to perform mass actions +// with iproute2 as well use it as a reference in nft filters. +// Equivalent to: `ip link set $link group $id` +func (h *Handle) LinkSetGroup(link Link, group int) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + b := make([]byte, 4) + native.PutUint32(b, uint32(group)) + + data := nl.NewRtAttr(unix.IFLA_GROUP, b) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +func parseVlanData(link Link, data []syscall.NetlinkRouteAttr) { + vlan := link.(*Vlan) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_VLAN_ID: + vlan.VlanId = int(native.Uint16(datum.Value[0:2])) + case nl.IFLA_VLAN_PROTOCOL: + vlan.VlanProtocol = VlanProtocol(int(ntohs(datum.Value[0:2]))) + } + } +} + +func parseVxlanData(link Link, data []syscall.NetlinkRouteAttr) { + vxlan := link.(*Vxlan) + for _, datum := range data { + // NOTE(vish): Apparently some messages can be sent with no value. + // We special case GBP here to not change existing + // functionality. It appears that GBP sends a datum.Value + // of null. + if len(datum.Value) == 0 && datum.Attr.Type != nl.IFLA_VXLAN_GBP { + continue + } + switch datum.Attr.Type { + case nl.IFLA_VXLAN_ID: + vxlan.VxlanId = int(native.Uint32(datum.Value[0:4])) + case nl.IFLA_VXLAN_LINK: + vxlan.VtepDevIndex = int(native.Uint32(datum.Value[0:4])) + case nl.IFLA_VXLAN_LOCAL: + vxlan.SrcAddr = net.IP(datum.Value[0:4]) + case nl.IFLA_VXLAN_LOCAL6: + vxlan.SrcAddr = net.IP(datum.Value[0:16]) + case nl.IFLA_VXLAN_GROUP: + vxlan.Group = net.IP(datum.Value[0:4]) + case nl.IFLA_VXLAN_GROUP6: + vxlan.Group = net.IP(datum.Value[0:16]) + case nl.IFLA_VXLAN_TTL: + vxlan.TTL = int(datum.Value[0]) + case nl.IFLA_VXLAN_TOS: + vxlan.TOS = int(datum.Value[0]) + case nl.IFLA_VXLAN_LEARNING: + vxlan.Learning = int8(datum.Value[0]) != 0 + case nl.IFLA_VXLAN_PROXY: + vxlan.Proxy = int8(datum.Value[0]) != 0 + case nl.IFLA_VXLAN_RSC: + vxlan.RSC = int8(datum.Value[0]) != 0 + case nl.IFLA_VXLAN_L2MISS: + vxlan.L2miss = int8(datum.Value[0]) != 0 + case nl.IFLA_VXLAN_L3MISS: + vxlan.L3miss = int8(datum.Value[0]) != 0 + case nl.IFLA_VXLAN_UDP_CSUM: + vxlan.UDPCSum = int8(datum.Value[0]) != 0 + case nl.IFLA_VXLAN_UDP_ZERO_CSUM6_TX: + vxlan.UDP6ZeroCSumTx = int8(datum.Value[0]) != 0 + case nl.IFLA_VXLAN_UDP_ZERO_CSUM6_RX: + vxlan.UDP6ZeroCSumRx = int8(datum.Value[0]) != 0 + case nl.IFLA_VXLAN_GBP: + vxlan.GBP = true + case nl.IFLA_VXLAN_FLOWBASED: + vxlan.FlowBased = int8(datum.Value[0]) != 0 + case nl.IFLA_VXLAN_AGEING: + vxlan.Age = int(native.Uint32(datum.Value[0:4])) + vxlan.NoAge = vxlan.Age == 0 + case nl.IFLA_VXLAN_LIMIT: + vxlan.Limit = int(native.Uint32(datum.Value[0:4])) + case nl.IFLA_VXLAN_PORT: + vxlan.Port = int(ntohs(datum.Value[0:2])) + case nl.IFLA_VXLAN_PORT_RANGE: + buf := bytes.NewBuffer(datum.Value[0:4]) + var pr vxlanPortRange + if binary.Read(buf, binary.BigEndian, &pr) != nil { + vxlan.PortLow = int(pr.Lo) + vxlan.PortHigh = int(pr.Hi) + } + } + } +} + +func parseBondData(link Link, data []syscall.NetlinkRouteAttr) { + bond := link.(*Bond) + for i := range data { + switch data[i].Attr.Type { + case nl.IFLA_BOND_MODE: + bond.Mode = BondMode(data[i].Value[0]) + case nl.IFLA_BOND_ACTIVE_SLAVE: + bond.ActiveSlave = int(native.Uint32(data[i].Value[0:4])) + case nl.IFLA_BOND_MIIMON: + bond.Miimon = int(native.Uint32(data[i].Value[0:4])) + case nl.IFLA_BOND_UPDELAY: + bond.UpDelay = int(native.Uint32(data[i].Value[0:4])) + case nl.IFLA_BOND_DOWNDELAY: + bond.DownDelay = int(native.Uint32(data[i].Value[0:4])) + case nl.IFLA_BOND_USE_CARRIER: + bond.UseCarrier = int(data[i].Value[0]) + case nl.IFLA_BOND_ARP_INTERVAL: + bond.ArpInterval = int(native.Uint32(data[i].Value[0:4])) + case nl.IFLA_BOND_ARP_IP_TARGET: + bond.ArpIpTargets = parseBondArpIpTargets(data[i].Value) + case nl.IFLA_BOND_ARP_VALIDATE: + bond.ArpValidate = BondArpValidate(native.Uint32(data[i].Value[0:4])) + case nl.IFLA_BOND_ARP_ALL_TARGETS: + bond.ArpAllTargets = BondArpAllTargets(native.Uint32(data[i].Value[0:4])) + case nl.IFLA_BOND_PRIMARY: + bond.Primary = int(native.Uint32(data[i].Value[0:4])) + case nl.IFLA_BOND_PRIMARY_RESELECT: + bond.PrimaryReselect = BondPrimaryReselect(data[i].Value[0]) + case nl.IFLA_BOND_FAIL_OVER_MAC: + bond.FailOverMac = BondFailOverMac(data[i].Value[0]) + case nl.IFLA_BOND_XMIT_HASH_POLICY: + bond.XmitHashPolicy = BondXmitHashPolicy(data[i].Value[0]) + case nl.IFLA_BOND_RESEND_IGMP: + bond.ResendIgmp = int(native.Uint32(data[i].Value[0:4])) + case nl.IFLA_BOND_NUM_PEER_NOTIF: + bond.NumPeerNotif = int(data[i].Value[0]) + case nl.IFLA_BOND_ALL_SLAVES_ACTIVE: + bond.AllSlavesActive = int(data[i].Value[0]) + case nl.IFLA_BOND_MIN_LINKS: + bond.MinLinks = int(native.Uint32(data[i].Value[0:4])) + case nl.IFLA_BOND_LP_INTERVAL: + bond.LpInterval = int(native.Uint32(data[i].Value[0:4])) + case nl.IFLA_BOND_PACKETS_PER_SLAVE: + bond.PacketsPerSlave = int(native.Uint32(data[i].Value[0:4])) + case nl.IFLA_BOND_AD_LACP_RATE: + bond.LacpRate = BondLacpRate(data[i].Value[0]) + case nl.IFLA_BOND_AD_SELECT: + bond.AdSelect = BondAdSelect(data[i].Value[0]) + case nl.IFLA_BOND_AD_INFO: + // TODO: implement + case nl.IFLA_BOND_AD_ACTOR_SYS_PRIO: + bond.AdActorSysPrio = int(native.Uint16(data[i].Value[0:2])) + case nl.IFLA_BOND_AD_USER_PORT_KEY: + bond.AdUserPortKey = int(native.Uint16(data[i].Value[0:2])) + case nl.IFLA_BOND_AD_ACTOR_SYSTEM: + bond.AdActorSystem = net.HardwareAddr(data[i].Value[0:6]) + case nl.IFLA_BOND_TLB_DYNAMIC_LB: + bond.TlbDynamicLb = int(data[i].Value[0]) + } + } +} + +func parseBondArpIpTargets(value []byte) []net.IP { + data, err := nl.ParseRouteAttr(value) + if err != nil { + return nil + } + + targets := []net.IP{} + for i := range data { + target := net.IP(data[i].Value) + if ip := target.To4(); ip != nil { + targets = append(targets, ip) + continue + } + if ip := target.To16(); ip != nil { + targets = append(targets, ip) + } + } + + return targets +} + +func addBondSlaveAttrs(bondSlave *BondSlave, linkInfo *nl.RtAttr) { + data := linkInfo.AddRtAttr(nl.IFLA_INFO_SLAVE_DATA, nil) + + data.AddRtAttr(nl.IFLA_BOND_SLAVE_STATE, nl.Uint8Attr(uint8(bondSlave.State))) + data.AddRtAttr(nl.IFLA_BOND_SLAVE_MII_STATUS, nl.Uint8Attr(uint8(bondSlave.MiiStatus))) + data.AddRtAttr(nl.IFLA_BOND_SLAVE_LINK_FAILURE_COUNT, nl.Uint32Attr(bondSlave.LinkFailureCount)) + data.AddRtAttr(nl.IFLA_BOND_SLAVE_QUEUE_ID, nl.Uint16Attr(bondSlave.QueueId)) + data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_AGGREGATOR_ID, nl.Uint16Attr(bondSlave.AggregatorId)) + data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE, nl.Uint8Attr(bondSlave.AdActorOperPortState)) + data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE, nl.Uint16Attr(bondSlave.AdPartnerOperPortState)) + + if mac := bondSlave.PermHardwareAddr; mac != nil { + data.AddRtAttr(nl.IFLA_BOND_SLAVE_PERM_HWADDR, []byte(mac)) + } +} + +func parseBondSlaveData(slave LinkSlave, data []syscall.NetlinkRouteAttr) { + bondSlave := slave.(*BondSlave) + for i := range data { + switch data[i].Attr.Type { + case nl.IFLA_BOND_SLAVE_STATE: + bondSlave.State = BondSlaveState(data[i].Value[0]) + case nl.IFLA_BOND_SLAVE_MII_STATUS: + bondSlave.MiiStatus = BondSlaveMiiStatus(data[i].Value[0]) + case nl.IFLA_BOND_SLAVE_LINK_FAILURE_COUNT: + bondSlave.LinkFailureCount = native.Uint32(data[i].Value[0:4]) + case nl.IFLA_BOND_SLAVE_PERM_HWADDR: + bondSlave.PermHardwareAddr = net.HardwareAddr(data[i].Value[0:6]) + case nl.IFLA_BOND_SLAVE_QUEUE_ID: + bondSlave.QueueId = native.Uint16(data[i].Value[0:2]) + case nl.IFLA_BOND_SLAVE_AD_AGGREGATOR_ID: + bondSlave.AggregatorId = native.Uint16(data[i].Value[0:2]) + case nl.IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE: + bondSlave.AdActorOperPortState = uint8(data[i].Value[0]) + case nl.IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE: + bondSlave.AdPartnerOperPortState = native.Uint16(data[i].Value[0:2]) + } + } +} + +func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) { + ipv := link.(*IPVlan) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_IPVLAN_MODE: + ipv.Mode = IPVlanMode(native.Uint32(datum.Value[0:4])) + case nl.IFLA_IPVLAN_FLAG: + ipv.Flag = IPVlanFlag(native.Uint32(datum.Value[0:4])) + } + } +} + +func parseMacvtapData(link Link, data []syscall.NetlinkRouteAttr) { + macv := link.(*Macvtap) + parseMacvlanData(&macv.Macvlan, data) +} + +func parseMacvlanData(link Link, data []syscall.NetlinkRouteAttr) { + macv := link.(*Macvlan) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_MACVLAN_MODE: + switch native.Uint32(datum.Value[0:4]) { + case nl.MACVLAN_MODE_PRIVATE: + macv.Mode = MACVLAN_MODE_PRIVATE + case nl.MACVLAN_MODE_VEPA: + macv.Mode = MACVLAN_MODE_VEPA + case nl.MACVLAN_MODE_BRIDGE: + macv.Mode = MACVLAN_MODE_BRIDGE + case nl.MACVLAN_MODE_PASSTHRU: + macv.Mode = MACVLAN_MODE_PASSTHRU + case nl.MACVLAN_MODE_SOURCE: + macv.Mode = MACVLAN_MODE_SOURCE + } + case nl.IFLA_MACVLAN_MACADDR_COUNT: + macv.MACAddrs = make([]net.HardwareAddr, 0, int(native.Uint32(datum.Value[0:4]))) + case nl.IFLA_MACVLAN_MACADDR_DATA: + macs, err := nl.ParseRouteAttr(datum.Value[:]) + if err != nil { + panic(fmt.Sprintf("failed to ParseRouteAttr for IFLA_MACVLAN_MACADDR_DATA: %v", err)) + } + for _, macDatum := range macs { + macv.MACAddrs = append(macv.MACAddrs, net.HardwareAddr(macDatum.Value[0:6])) + } + } + } +} + +// copied from pkg/net_linux.go +func linkFlags(rawFlags uint32) net.Flags { + var f net.Flags + if rawFlags&unix.IFF_UP != 0 { + f |= net.FlagUp + } + if rawFlags&unix.IFF_BROADCAST != 0 { + f |= net.FlagBroadcast + } + if rawFlags&unix.IFF_LOOPBACK != 0 { + f |= net.FlagLoopback + } + if rawFlags&unix.IFF_POINTOPOINT != 0 { + f |= net.FlagPointToPoint + } + if rawFlags&unix.IFF_MULTICAST != 0 { + f |= net.FlagMulticast + } + return f +} + +func addGeneveAttrs(geneve *Geneve, linkInfo *nl.RtAttr) { + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + + if geneve.FlowBased { + // In flow based mode, no other attributes need to be configured + linkInfo.AddRtAttr(nl.IFLA_GENEVE_COLLECT_METADATA, boolAttr(geneve.FlowBased)) + return + } + + if ip := geneve.Remote; ip != nil { + if ip4 := ip.To4(); ip4 != nil { + data.AddRtAttr(nl.IFLA_GENEVE_REMOTE, ip.To4()) + } else { + data.AddRtAttr(nl.IFLA_GENEVE_REMOTE6, []byte(ip)) + } + } + + if geneve.ID != 0 { + data.AddRtAttr(nl.IFLA_GENEVE_ID, nl.Uint32Attr(geneve.ID)) + } + + if geneve.Dport != 0 { + data.AddRtAttr(nl.IFLA_GENEVE_PORT, htons(geneve.Dport)) + } + + if geneve.Ttl != 0 { + data.AddRtAttr(nl.IFLA_GENEVE_TTL, nl.Uint8Attr(geneve.Ttl)) + } + + if geneve.Tos != 0 { + data.AddRtAttr(nl.IFLA_GENEVE_TOS, nl.Uint8Attr(geneve.Tos)) + } +} + +func parseGeneveData(link Link, data []syscall.NetlinkRouteAttr) { + geneve := link.(*Geneve) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_GENEVE_ID: + geneve.ID = native.Uint32(datum.Value[0:4]) + case nl.IFLA_GENEVE_REMOTE, nl.IFLA_GENEVE_REMOTE6: + geneve.Remote = datum.Value + case nl.IFLA_GENEVE_PORT: + geneve.Dport = ntohs(datum.Value[0:2]) + case nl.IFLA_GENEVE_TTL: + geneve.Ttl = uint8(datum.Value[0]) + case nl.IFLA_GENEVE_TOS: + geneve.Tos = uint8(datum.Value[0]) + } + } +} + +func addGretapAttrs(gretap *Gretap, linkInfo *nl.RtAttr) { + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + + if gretap.FlowBased { + // In flow based mode, no other attributes need to be configured + data.AddRtAttr(nl.IFLA_GRE_COLLECT_METADATA, boolAttr(gretap.FlowBased)) + return + } + + if ip := gretap.Local; ip != nil { + if ip.To4() != nil { + ip = ip.To4() + } + data.AddRtAttr(nl.IFLA_GRE_LOCAL, []byte(ip)) + } + + if ip := gretap.Remote; ip != nil { + if ip.To4() != nil { + ip = ip.To4() + } + data.AddRtAttr(nl.IFLA_GRE_REMOTE, []byte(ip)) + } + + if gretap.IKey != 0 { + data.AddRtAttr(nl.IFLA_GRE_IKEY, htonl(gretap.IKey)) + gretap.IFlags |= uint16(nl.GRE_KEY) + } + + if gretap.OKey != 0 { + data.AddRtAttr(nl.IFLA_GRE_OKEY, htonl(gretap.OKey)) + gretap.OFlags |= uint16(nl.GRE_KEY) + } + + data.AddRtAttr(nl.IFLA_GRE_IFLAGS, htons(gretap.IFlags)) + data.AddRtAttr(nl.IFLA_GRE_OFLAGS, htons(gretap.OFlags)) + + if gretap.Link != 0 { + data.AddRtAttr(nl.IFLA_GRE_LINK, nl.Uint32Attr(gretap.Link)) + } + + data.AddRtAttr(nl.IFLA_GRE_PMTUDISC, nl.Uint8Attr(gretap.PMtuDisc)) + data.AddRtAttr(nl.IFLA_GRE_TTL, nl.Uint8Attr(gretap.Ttl)) + data.AddRtAttr(nl.IFLA_GRE_TOS, nl.Uint8Attr(gretap.Tos)) + data.AddRtAttr(nl.IFLA_GRE_ENCAP_TYPE, nl.Uint16Attr(gretap.EncapType)) + data.AddRtAttr(nl.IFLA_GRE_ENCAP_FLAGS, nl.Uint16Attr(gretap.EncapFlags)) + data.AddRtAttr(nl.IFLA_GRE_ENCAP_SPORT, htons(gretap.EncapSport)) + data.AddRtAttr(nl.IFLA_GRE_ENCAP_DPORT, htons(gretap.EncapDport)) +} + +func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) { + gre := link.(*Gretap) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_GRE_OKEY: + gre.IKey = ntohl(datum.Value[0:4]) + case nl.IFLA_GRE_IKEY: + gre.OKey = ntohl(datum.Value[0:4]) + case nl.IFLA_GRE_LOCAL: + gre.Local = net.IP(datum.Value) + case nl.IFLA_GRE_REMOTE: + gre.Remote = net.IP(datum.Value) + case nl.IFLA_GRE_ENCAP_SPORT: + gre.EncapSport = ntohs(datum.Value[0:2]) + case nl.IFLA_GRE_ENCAP_DPORT: + gre.EncapDport = ntohs(datum.Value[0:2]) + case nl.IFLA_GRE_IFLAGS: + gre.IFlags = ntohs(datum.Value[0:2]) + case nl.IFLA_GRE_OFLAGS: + gre.OFlags = ntohs(datum.Value[0:2]) + case nl.IFLA_GRE_TTL: + gre.Ttl = uint8(datum.Value[0]) + case nl.IFLA_GRE_TOS: + gre.Tos = uint8(datum.Value[0]) + case nl.IFLA_GRE_PMTUDISC: + gre.PMtuDisc = uint8(datum.Value[0]) + case nl.IFLA_GRE_ENCAP_TYPE: + gre.EncapType = native.Uint16(datum.Value[0:2]) + case nl.IFLA_GRE_ENCAP_FLAGS: + gre.EncapFlags = native.Uint16(datum.Value[0:2]) + case nl.IFLA_GRE_COLLECT_METADATA: + gre.FlowBased = true + } + } +} + +func addGretunAttrs(gre *Gretun, linkInfo *nl.RtAttr) { + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + + if ip := gre.Local; ip != nil { + if ip.To4() != nil { + ip = ip.To4() + } + data.AddRtAttr(nl.IFLA_GRE_LOCAL, []byte(ip)) + } + + if ip := gre.Remote; ip != nil { + if ip.To4() != nil { + ip = ip.To4() + } + data.AddRtAttr(nl.IFLA_GRE_REMOTE, []byte(ip)) + } + + if gre.IKey != 0 { + data.AddRtAttr(nl.IFLA_GRE_IKEY, htonl(gre.IKey)) + gre.IFlags |= uint16(nl.GRE_KEY) + } + + if gre.OKey != 0 { + data.AddRtAttr(nl.IFLA_GRE_OKEY, htonl(gre.OKey)) + gre.OFlags |= uint16(nl.GRE_KEY) + } + + data.AddRtAttr(nl.IFLA_GRE_IFLAGS, htons(gre.IFlags)) + data.AddRtAttr(nl.IFLA_GRE_OFLAGS, htons(gre.OFlags)) + + if gre.Link != 0 { + data.AddRtAttr(nl.IFLA_GRE_LINK, nl.Uint32Attr(gre.Link)) + } + + data.AddRtAttr(nl.IFLA_GRE_PMTUDISC, nl.Uint8Attr(gre.PMtuDisc)) + data.AddRtAttr(nl.IFLA_GRE_TTL, nl.Uint8Attr(gre.Ttl)) + data.AddRtAttr(nl.IFLA_GRE_TOS, nl.Uint8Attr(gre.Tos)) + data.AddRtAttr(nl.IFLA_GRE_ENCAP_TYPE, nl.Uint16Attr(gre.EncapType)) + data.AddRtAttr(nl.IFLA_GRE_ENCAP_FLAGS, nl.Uint16Attr(gre.EncapFlags)) + data.AddRtAttr(nl.IFLA_GRE_ENCAP_SPORT, htons(gre.EncapSport)) + data.AddRtAttr(nl.IFLA_GRE_ENCAP_DPORT, htons(gre.EncapDport)) +} + +func parseGretunData(link Link, data []syscall.NetlinkRouteAttr) { + gre := link.(*Gretun) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_GRE_IKEY: + gre.IKey = ntohl(datum.Value[0:4]) + case nl.IFLA_GRE_OKEY: + gre.OKey = ntohl(datum.Value[0:4]) + case nl.IFLA_GRE_LOCAL: + gre.Local = net.IP(datum.Value) + case nl.IFLA_GRE_REMOTE: + gre.Remote = net.IP(datum.Value) + case nl.IFLA_GRE_IFLAGS: + gre.IFlags = ntohs(datum.Value[0:2]) + case nl.IFLA_GRE_OFLAGS: + gre.OFlags = ntohs(datum.Value[0:2]) + case nl.IFLA_GRE_TTL: + gre.Ttl = uint8(datum.Value[0]) + case nl.IFLA_GRE_TOS: + gre.Tos = uint8(datum.Value[0]) + case nl.IFLA_GRE_PMTUDISC: + gre.PMtuDisc = uint8(datum.Value[0]) + case nl.IFLA_GRE_ENCAP_TYPE: + gre.EncapType = native.Uint16(datum.Value[0:2]) + case nl.IFLA_GRE_ENCAP_FLAGS: + gre.EncapFlags = native.Uint16(datum.Value[0:2]) + case nl.IFLA_GRE_ENCAP_SPORT: + gre.EncapSport = ntohs(datum.Value[0:2]) + case nl.IFLA_GRE_ENCAP_DPORT: + gre.EncapDport = ntohs(datum.Value[0:2]) + } + } +} + +func addXdpAttrs(xdp *LinkXdp, req *nl.NetlinkRequest) { + attrs := nl.NewRtAttr(unix.IFLA_XDP|unix.NLA_F_NESTED, nil) + b := make([]byte, 4) + native.PutUint32(b, uint32(xdp.Fd)) + attrs.AddRtAttr(nl.IFLA_XDP_FD, b) + if xdp.Flags != 0 { + b := make([]byte, 4) + native.PutUint32(b, xdp.Flags) + attrs.AddRtAttr(nl.IFLA_XDP_FLAGS, b) + } + req.AddData(attrs) +} + +func parseLinkXdp(data []byte) (*LinkXdp, error) { + attrs, err := nl.ParseRouteAttr(data) + if err != nil { + return nil, err + } + xdp := &LinkXdp{} + for _, attr := range attrs { + switch attr.Attr.Type { + case nl.IFLA_XDP_FD: + xdp.Fd = int(native.Uint32(attr.Value[0:4])) + case nl.IFLA_XDP_ATTACHED: + xdp.AttachMode = uint32(attr.Value[0]) + xdp.Attached = xdp.AttachMode != 0 + case nl.IFLA_XDP_FLAGS: + xdp.Flags = native.Uint32(attr.Value[0:4]) + case nl.IFLA_XDP_PROG_ID: + xdp.ProgId = native.Uint32(attr.Value[0:4]) + } + } + return xdp, nil +} + +func addIptunAttrs(iptun *Iptun, linkInfo *nl.RtAttr) { + if iptun.FlowBased { + // In flow based mode, no other attributes need to be configured + linkInfo.AddRtAttr(nl.IFLA_IPTUN_COLLECT_METADATA, boolAttr(iptun.FlowBased)) + return + } + + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + + ip := iptun.Local.To4() + if ip != nil { + data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip)) + } + + ip = iptun.Remote.To4() + if ip != nil { + data.AddRtAttr(nl.IFLA_IPTUN_REMOTE, []byte(ip)) + } + + if iptun.Link != 0 { + data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(iptun.Link)) + } + data.AddRtAttr(nl.IFLA_IPTUN_PMTUDISC, nl.Uint8Attr(iptun.PMtuDisc)) + data.AddRtAttr(nl.IFLA_IPTUN_TTL, nl.Uint8Attr(iptun.Ttl)) + data.AddRtAttr(nl.IFLA_IPTUN_TOS, nl.Uint8Attr(iptun.Tos)) + data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_TYPE, nl.Uint16Attr(iptun.EncapType)) + data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_FLAGS, nl.Uint16Attr(iptun.EncapFlags)) + data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_SPORT, htons(iptun.EncapSport)) + data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_DPORT, htons(iptun.EncapDport)) +} + +func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) { + iptun := link.(*Iptun) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_IPTUN_LOCAL: + iptun.Local = net.IP(datum.Value[0:4]) + case nl.IFLA_IPTUN_REMOTE: + iptun.Remote = net.IP(datum.Value[0:4]) + case nl.IFLA_IPTUN_TTL: + iptun.Ttl = uint8(datum.Value[0]) + case nl.IFLA_IPTUN_TOS: + iptun.Tos = uint8(datum.Value[0]) + case nl.IFLA_IPTUN_PMTUDISC: + iptun.PMtuDisc = uint8(datum.Value[0]) + case nl.IFLA_IPTUN_ENCAP_SPORT: + iptun.EncapSport = ntohs(datum.Value[0:2]) + case nl.IFLA_IPTUN_ENCAP_DPORT: + iptun.EncapDport = ntohs(datum.Value[0:2]) + case nl.IFLA_IPTUN_ENCAP_TYPE: + iptun.EncapType = native.Uint16(datum.Value[0:2]) + case nl.IFLA_IPTUN_ENCAP_FLAGS: + iptun.EncapFlags = native.Uint16(datum.Value[0:2]) + case nl.IFLA_IPTUN_COLLECT_METADATA: + iptun.FlowBased = true + } + } +} + +func addIp6tnlAttrs(ip6tnl *Ip6tnl, linkInfo *nl.RtAttr) { + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + + if ip6tnl.Link != 0 { + data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(ip6tnl.Link)) + } + + ip := ip6tnl.Local.To16() + if ip != nil { + data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip)) + } + + ip = ip6tnl.Remote.To16() + if ip != nil { + data.AddRtAttr(nl.IFLA_IPTUN_REMOTE, []byte(ip)) + } + + data.AddRtAttr(nl.IFLA_IPTUN_TTL, nl.Uint8Attr(ip6tnl.Ttl)) + data.AddRtAttr(nl.IFLA_IPTUN_TOS, nl.Uint8Attr(ip6tnl.Tos)) + data.AddRtAttr(nl.IFLA_IPTUN_FLAGS, nl.Uint32Attr(ip6tnl.Flags)) + data.AddRtAttr(nl.IFLA_IPTUN_PROTO, nl.Uint8Attr(ip6tnl.Proto)) + data.AddRtAttr(nl.IFLA_IPTUN_FLOWINFO, nl.Uint32Attr(ip6tnl.FlowInfo)) + data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_LIMIT, nl.Uint8Attr(ip6tnl.EncapLimit)) + data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_TYPE, nl.Uint16Attr(ip6tnl.EncapType)) + data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_FLAGS, nl.Uint16Attr(ip6tnl.EncapFlags)) + data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_SPORT, htons(ip6tnl.EncapSport)) + data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_DPORT, htons(ip6tnl.EncapDport)) +} + +func parseIp6tnlData(link Link, data []syscall.NetlinkRouteAttr) { + ip6tnl := link.(*Ip6tnl) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_IPTUN_LOCAL: + ip6tnl.Local = net.IP(datum.Value[:16]) + case nl.IFLA_IPTUN_REMOTE: + ip6tnl.Remote = net.IP(datum.Value[:16]) + case nl.IFLA_IPTUN_TTL: + ip6tnl.Ttl = datum.Value[0] + case nl.IFLA_IPTUN_TOS: + ip6tnl.Tos = datum.Value[0] + case nl.IFLA_IPTUN_FLAGS: + ip6tnl.Flags = native.Uint32(datum.Value[:4]) + case nl.IFLA_IPTUN_PROTO: + ip6tnl.Proto = datum.Value[0] + case nl.IFLA_IPTUN_FLOWINFO: + ip6tnl.FlowInfo = native.Uint32(datum.Value[:4]) + case nl.IFLA_IPTUN_ENCAP_LIMIT: + ip6tnl.EncapLimit = datum.Value[0] + case nl.IFLA_IPTUN_ENCAP_TYPE: + ip6tnl.EncapType = native.Uint16(datum.Value[0:2]) + case nl.IFLA_IPTUN_ENCAP_FLAGS: + ip6tnl.EncapFlags = native.Uint16(datum.Value[0:2]) + case nl.IFLA_IPTUN_ENCAP_SPORT: + ip6tnl.EncapSport = ntohs(datum.Value[0:2]) + case nl.IFLA_IPTUN_ENCAP_DPORT: + ip6tnl.EncapDport = ntohs(datum.Value[0:2]) + } + } +} + +func addSittunAttrs(sittun *Sittun, linkInfo *nl.RtAttr) { + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + + if sittun.Link != 0 { + data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(sittun.Link)) + } + + ip := sittun.Local.To4() + if ip != nil { + data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip)) + } + + ip = sittun.Remote.To4() + if ip != nil { + data.AddRtAttr(nl.IFLA_IPTUN_REMOTE, []byte(ip)) + } + + if sittun.Ttl > 0 { + // Would otherwise fail on 3.10 kernel + data.AddRtAttr(nl.IFLA_IPTUN_TTL, nl.Uint8Attr(sittun.Ttl)) + } + + data.AddRtAttr(nl.IFLA_IPTUN_PROTO, nl.Uint8Attr(sittun.Proto)) + data.AddRtAttr(nl.IFLA_IPTUN_TOS, nl.Uint8Attr(sittun.Tos)) + data.AddRtAttr(nl.IFLA_IPTUN_PMTUDISC, nl.Uint8Attr(sittun.PMtuDisc)) + data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_LIMIT, nl.Uint8Attr(sittun.EncapLimit)) + data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_TYPE, nl.Uint16Attr(sittun.EncapType)) + data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_FLAGS, nl.Uint16Attr(sittun.EncapFlags)) + data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_SPORT, htons(sittun.EncapSport)) + data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_DPORT, htons(sittun.EncapDport)) +} + +func parseSittunData(link Link, data []syscall.NetlinkRouteAttr) { + sittun := link.(*Sittun) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_IPTUN_LOCAL: + sittun.Local = net.IP(datum.Value[0:4]) + case nl.IFLA_IPTUN_REMOTE: + sittun.Remote = net.IP(datum.Value[0:4]) + case nl.IFLA_IPTUN_TTL: + sittun.Ttl = datum.Value[0] + case nl.IFLA_IPTUN_TOS: + sittun.Tos = datum.Value[0] + case nl.IFLA_IPTUN_PMTUDISC: + sittun.PMtuDisc = datum.Value[0] + case nl.IFLA_IPTUN_PROTO: + sittun.Proto = datum.Value[0] + case nl.IFLA_IPTUN_ENCAP_TYPE: + sittun.EncapType = native.Uint16(datum.Value[0:2]) + case nl.IFLA_IPTUN_ENCAP_FLAGS: + sittun.EncapFlags = native.Uint16(datum.Value[0:2]) + case nl.IFLA_IPTUN_ENCAP_SPORT: + sittun.EncapSport = ntohs(datum.Value[0:2]) + case nl.IFLA_IPTUN_ENCAP_DPORT: + sittun.EncapDport = ntohs(datum.Value[0:2]) + } + } +} + +func addVtiAttrs(vti *Vti, linkInfo *nl.RtAttr) { + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + + family := FAMILY_V4 + if vti.Local.To4() == nil { + family = FAMILY_V6 + } + + var ip net.IP + + if family == FAMILY_V4 { + ip = vti.Local.To4() + } else { + ip = vti.Local + } + if ip != nil { + data.AddRtAttr(nl.IFLA_VTI_LOCAL, []byte(ip)) + } + + if family == FAMILY_V4 { + ip = vti.Remote.To4() + } else { + ip = vti.Remote + } + if ip != nil { + data.AddRtAttr(nl.IFLA_VTI_REMOTE, []byte(ip)) + } + + if vti.Link != 0 { + data.AddRtAttr(nl.IFLA_VTI_LINK, nl.Uint32Attr(vti.Link)) + } + + data.AddRtAttr(nl.IFLA_VTI_IKEY, htonl(vti.IKey)) + data.AddRtAttr(nl.IFLA_VTI_OKEY, htonl(vti.OKey)) +} + +func parseVtiData(link Link, data []syscall.NetlinkRouteAttr) { + vti := link.(*Vti) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_VTI_LOCAL: + vti.Local = net.IP(datum.Value) + case nl.IFLA_VTI_REMOTE: + vti.Remote = net.IP(datum.Value) + case nl.IFLA_VTI_IKEY: + vti.IKey = ntohl(datum.Value[0:4]) + case nl.IFLA_VTI_OKEY: + vti.OKey = ntohl(datum.Value[0:4]) + } + } +} + +func addVrfAttrs(vrf *Vrf, linkInfo *nl.RtAttr) { + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + b := make([]byte, 4) + native.PutUint32(b, uint32(vrf.Table)) + data.AddRtAttr(nl.IFLA_VRF_TABLE, b) +} + +func parseVrfData(link Link, data []syscall.NetlinkRouteAttr) { + vrf := link.(*Vrf) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_VRF_TABLE: + vrf.Table = native.Uint32(datum.Value[0:4]) + } + } +} + +func addBridgeAttrs(bridge *Bridge, linkInfo *nl.RtAttr) { + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + if bridge.MulticastSnooping != nil { + data.AddRtAttr(nl.IFLA_BR_MCAST_SNOOPING, boolToByte(*bridge.MulticastSnooping)) + } + if bridge.AgeingTime != nil { + data.AddRtAttr(nl.IFLA_BR_AGEING_TIME, nl.Uint32Attr(*bridge.AgeingTime)) + } + if bridge.HelloTime != nil { + data.AddRtAttr(nl.IFLA_BR_HELLO_TIME, nl.Uint32Attr(*bridge.HelloTime)) + } + if bridge.VlanFiltering != nil { + data.AddRtAttr(nl.IFLA_BR_VLAN_FILTERING, boolToByte(*bridge.VlanFiltering)) + } +} + +func parseBridgeData(bridge Link, data []syscall.NetlinkRouteAttr) { + br := bridge.(*Bridge) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_BR_AGEING_TIME: + ageingTime := native.Uint32(datum.Value[0:4]) + br.AgeingTime = &ageingTime + case nl.IFLA_BR_HELLO_TIME: + helloTime := native.Uint32(datum.Value[0:4]) + br.HelloTime = &helloTime + case nl.IFLA_BR_MCAST_SNOOPING: + mcastSnooping := datum.Value[0] == 1 + br.MulticastSnooping = &mcastSnooping + case nl.IFLA_BR_VLAN_FILTERING: + vlanFiltering := datum.Value[0] == 1 + br.VlanFiltering = &vlanFiltering + } + } +} + +func addGTPAttrs(gtp *GTP, linkInfo *nl.RtAttr) { + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + data.AddRtAttr(nl.IFLA_GTP_FD0, nl.Uint32Attr(uint32(gtp.FD0))) + data.AddRtAttr(nl.IFLA_GTP_FD1, nl.Uint32Attr(uint32(gtp.FD1))) + data.AddRtAttr(nl.IFLA_GTP_PDP_HASHSIZE, nl.Uint32Attr(131072)) + if gtp.Role != nl.GTP_ROLE_GGSN { + data.AddRtAttr(nl.IFLA_GTP_ROLE, nl.Uint32Attr(uint32(gtp.Role))) + } +} + +func parseGTPData(link Link, data []syscall.NetlinkRouteAttr) { + gtp := link.(*GTP) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_GTP_FD0: + gtp.FD0 = int(native.Uint32(datum.Value)) + case nl.IFLA_GTP_FD1: + gtp.FD1 = int(native.Uint32(datum.Value)) + case nl.IFLA_GTP_PDP_HASHSIZE: + gtp.PDPHashsize = int(native.Uint32(datum.Value)) + case nl.IFLA_GTP_ROLE: + gtp.Role = int(native.Uint32(datum.Value)) + } + } +} + +func parseVfInfoList(data []syscall.NetlinkRouteAttr) ([]VfInfo, error) { + var vfs []VfInfo + + for i, element := range data { + if element.Attr.Type != nl.IFLA_VF_INFO { + return nil, fmt.Errorf("Incorrect element type in vf info list: %d", element.Attr.Type) + } + vfAttrs, err := nl.ParseRouteAttr(element.Value) + if err != nil { + return nil, err + } + vfs = append(vfs, parseVfInfo(vfAttrs, i)) + } + return vfs, nil +} + +func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) VfInfo { + vf := VfInfo{ID: id} + for _, element := range data { + switch element.Attr.Type { + case nl.IFLA_VF_MAC: + mac := nl.DeserializeVfMac(element.Value[:]) + vf.Mac = mac.Mac[:6] + case nl.IFLA_VF_VLAN: + vl := nl.DeserializeVfVlan(element.Value[:]) + vf.Vlan = int(vl.Vlan) + vf.Qos = int(vl.Qos) + case nl.IFLA_VF_TX_RATE: + txr := nl.DeserializeVfTxRate(element.Value[:]) + vf.TxRate = int(txr.Rate) + case nl.IFLA_VF_SPOOFCHK: + sp := nl.DeserializeVfSpoofchk(element.Value[:]) + vf.Spoofchk = sp.Setting != 0 + case nl.IFLA_VF_LINK_STATE: + ls := nl.DeserializeVfLinkState(element.Value[:]) + vf.LinkState = ls.LinkState + case nl.IFLA_VF_RATE: + vfr := nl.DeserializeVfRate(element.Value[:]) + vf.MaxTxRate = vfr.MaxTxRate + vf.MinTxRate = vfr.MinTxRate + case nl.IFLA_VF_STATS: + vfstats := nl.DeserializeVfStats(element.Value[:]) + vf.RxPackets = vfstats.RxPackets + vf.TxPackets = vfstats.TxPackets + vf.RxBytes = vfstats.RxBytes + vf.TxBytes = vfstats.TxBytes + vf.Multicast = vfstats.Multicast + vf.Broadcast = vfstats.Broadcast + vf.RxDropped = vfstats.RxDropped + vf.TxDropped = vfstats.TxDropped + + case nl.IFLA_VF_RSS_QUERY_EN: + result := nl.DeserializeVfRssQueryEn(element.Value) + vf.RssQuery = result.Setting + + case nl.IFLA_VF_TRUST: + result := nl.DeserializeVfTrust(element.Value) + vf.Trust = result.Setting + } + } + return vf +} + +func addXfrmiAttrs(xfrmi *Xfrmi, linkInfo *nl.RtAttr) { + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + data.AddRtAttr(nl.IFLA_XFRM_LINK, nl.Uint32Attr(uint32(xfrmi.ParentIndex))) + data.AddRtAttr(nl.IFLA_XFRM_IF_ID, nl.Uint32Attr(xfrmi.Ifid)) + +} + +func parseXfrmiData(link Link, data []syscall.NetlinkRouteAttr) { + xfrmi := link.(*Xfrmi) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_XFRM_LINK: + xfrmi.ParentIndex = int(native.Uint32(datum.Value)) + case nl.IFLA_XFRM_IF_ID: + xfrmi.Ifid = native.Uint32(datum.Value) + } + } +} + +// LinkSetBondSlave add slave to bond link via ioctl interface. +func LinkSetBondSlave(link Link, master *Bond) error { + fd, err := getSocketUDP() + if err != nil { + return err + } + defer syscall.Close(fd) + + ifreq := newIocltSlaveReq(link.Attrs().Name, master.Attrs().Name) + + _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), unix.SIOCBONDENSLAVE, uintptr(unsafe.Pointer(ifreq))) + if errno != 0 { + return fmt.Errorf("Failed to enslave %q to %q, errno=%v", link.Attrs().Name, master.Attrs().Name, errno) + } + return nil +} + +// LinkSetBondSlaveQueueId modify bond slave queue-id. +func (h *Handle) LinkSetBondSlaveQueueId(link Link, queueId uint16) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil) + data := linkInfo.AddRtAttr(nl.IFLA_INFO_SLAVE_DATA, nil) + data.AddRtAttr(nl.IFLA_BOND_SLAVE_QUEUE_ID, nl.Uint16Attr(queueId)) + + req.AddData(linkInfo) + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetBondSlaveQueueId modify bond slave queue-id. +func LinkSetBondSlaveQueueId(link Link, queueId uint16) error { + return pkgHandle.LinkSetBondSlaveQueueId(link, queueId) +} + +func vethStatsSerialize(stats ethtoolStats) ([]byte, error) { + statsSize := int(unsafe.Sizeof(stats)) + int(stats.nStats)*int(unsafe.Sizeof(uint64(0))) + b := make([]byte, 0, statsSize) + buf := bytes.NewBuffer(b) + err := binary.Write(buf, nl.NativeEndian(), stats) + return buf.Bytes()[:statsSize], err +} + +type vethEthtoolStats struct { + Cmd uint32 + NStats uint32 + Peer uint64 + // Newer kernels have XDP stats in here, but we only care + // to extract the peer ifindex here. +} + +func vethStatsDeserialize(b []byte) (vethEthtoolStats, error) { + var stats = vethEthtoolStats{} + err := binary.Read(bytes.NewReader(b), nl.NativeEndian(), &stats) + return stats, err +} + +// VethPeerIndex get veth peer index. +func VethPeerIndex(link *Veth) (int, error) { + fd, err := getSocketUDP() + if err != nil { + return -1, err + } + defer syscall.Close(fd) + + ifreq, sSet := newIocltStringSetReq(link.Name) + _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), SIOCETHTOOL, uintptr(unsafe.Pointer(ifreq))) + if errno != 0 { + return -1, fmt.Errorf("SIOCETHTOOL request for %q failed, errno=%v", link.Attrs().Name, errno) + } + + stats := ethtoolStats{ + cmd: ETHTOOL_GSTATS, + nStats: sSet.data[0], + } + + buffer, err := vethStatsSerialize(stats) + if err != nil { + return -1, err + } + + ifreq.Data = uintptr(unsafe.Pointer(&buffer[0])) + _, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), SIOCETHTOOL, uintptr(unsafe.Pointer(ifreq))) + if errno != 0 { + return -1, fmt.Errorf("SIOCETHTOOL request for %q failed, errno=%v", link.Attrs().Name, errno) + } + + vstats, err := vethStatsDeserialize(buffer) + if err != nil { + return -1, err + } + + return int(vstats.Peer), nil +} + +func parseTuntapData(link Link, data []syscall.NetlinkRouteAttr) { + tuntap := link.(*Tuntap) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_TUN_OWNER: + tuntap.Owner = native.Uint32(datum.Value) + case nl.IFLA_TUN_GROUP: + tuntap.Group = native.Uint32(datum.Value) + case nl.IFLA_TUN_TYPE: + tuntap.Mode = TuntapMode(uint8(datum.Value[0])) + case nl.IFLA_TUN_PERSIST: + tuntap.NonPersist = false + if uint8(datum.Value[0]) == 0 { + tuntap.NonPersist = true + } + } + } +} + +func parseIPoIBData(link Link, data []syscall.NetlinkRouteAttr) { + ipoib := link.(*IPoIB) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_IPOIB_PKEY: + ipoib.Pkey = uint16(native.Uint16(datum.Value)) + case nl.IFLA_IPOIB_MODE: + ipoib.Mode = IPoIBMode(native.Uint16(datum.Value)) + case nl.IFLA_IPOIB_UMCAST: + ipoib.Umcast = uint16(native.Uint16(datum.Value)) + } + } +} + +func parseCanData(link Link, data []syscall.NetlinkRouteAttr) { + can := link.(*Can) + for _, datum := range data { + + switch datum.Attr.Type { + case nl.IFLA_CAN_BITTIMING: + can.BitRate = native.Uint32(datum.Value) + can.SamplePoint = native.Uint32(datum.Value[4:]) + can.TimeQuanta = native.Uint32(datum.Value[8:]) + can.PropagationSegment = native.Uint32(datum.Value[12:]) + can.PhaseSegment1 = native.Uint32(datum.Value[16:]) + can.PhaseSegment2 = native.Uint32(datum.Value[20:]) + can.SyncJumpWidth = native.Uint32(datum.Value[24:]) + can.BitRatePreScaler = native.Uint32(datum.Value[28:]) + case nl.IFLA_CAN_BITTIMING_CONST: + can.Name = string(datum.Value[:16]) + can.TimeSegment1Min = native.Uint32(datum.Value[16:]) + can.TimeSegment1Max = native.Uint32(datum.Value[20:]) + can.TimeSegment2Min = native.Uint32(datum.Value[24:]) + can.TimeSegment2Max = native.Uint32(datum.Value[28:]) + can.SyncJumpWidthMax = native.Uint32(datum.Value[32:]) + can.BitRatePreScalerMin = native.Uint32(datum.Value[36:]) + can.BitRatePreScalerMax = native.Uint32(datum.Value[40:]) + can.BitRatePreScalerInc = native.Uint32(datum.Value[44:]) + case nl.IFLA_CAN_CLOCK: + can.ClockFrequency = native.Uint32(datum.Value) + case nl.IFLA_CAN_STATE: + can.State = native.Uint32(datum.Value) + case nl.IFLA_CAN_CTRLMODE: + can.Mask = native.Uint32(datum.Value) + can.Flags = native.Uint32(datum.Value[4:]) + case nl.IFLA_CAN_BERR_COUNTER: + can.TxError = native.Uint16(datum.Value) + can.RxError = native.Uint16(datum.Value[2:]) + case nl.IFLA_CAN_RESTART_MS: + can.RestartMs = native.Uint32(datum.Value) + case nl.IFLA_CAN_DATA_BITTIMING_CONST: + case nl.IFLA_CAN_RESTART: + case nl.IFLA_CAN_DATA_BITTIMING: + case nl.IFLA_CAN_TERMINATION: + case nl.IFLA_CAN_TERMINATION_CONST: + case nl.IFLA_CAN_BITRATE_CONST: + case nl.IFLA_CAN_DATA_BITRATE_CONST: + case nl.IFLA_CAN_BITRATE_MAX: + } + } +} + +func addIPoIBAttrs(ipoib *IPoIB, linkInfo *nl.RtAttr) { + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + data.AddRtAttr(nl.IFLA_IPOIB_PKEY, nl.Uint16Attr(uint16(ipoib.Pkey))) + data.AddRtAttr(nl.IFLA_IPOIB_MODE, nl.Uint16Attr(uint16(ipoib.Mode))) + data.AddRtAttr(nl.IFLA_IPOIB_UMCAST, nl.Uint16Attr(uint16(ipoib.Umcast))) +} diff --git a/vendor/github.com/vishvananda/netlink/link_tuntap_linux.go b/vendor/github.com/vishvananda/netlink/link_tuntap_linux.go new file mode 100644 index 000000000..310bd33d8 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/link_tuntap_linux.go @@ -0,0 +1,14 @@ +package netlink + +// ideally golang.org/x/sys/unix would define IfReq but it only has +// IFNAMSIZ, hence this minimalistic implementation +const ( + SizeOfIfReq = 40 + IFNAMSIZ = 16 +) + +type ifReq struct { + Name [IFNAMSIZ]byte + Flags uint16 + pad [SizeOfIfReq - IFNAMSIZ - 2]byte +} diff --git a/vendor/github.com/vishvananda/netlink/neigh.go b/vendor/github.com/vishvananda/netlink/neigh.go new file mode 100644 index 000000000..379e5655f --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/neigh.go @@ -0,0 +1,32 @@ +package netlink + +import ( + "fmt" + "net" +) + +// Neigh represents a link layer neighbor from netlink. +type Neigh struct { + LinkIndex int + Family int + State int + Type int + Flags int + IP net.IP + HardwareAddr net.HardwareAddr + LLIPAddr net.IP //Used in the case of NHRP + Vlan int + VNI int + MasterIndex int +} + +// String returns $ip/$hwaddr $label +func (neigh *Neigh) String() string { + return fmt.Sprintf("%s %s", neigh.IP, neigh.HardwareAddr) +} + +// NeighUpdate is sent when a neighbor changes - type is RTM_NEWNEIGH or RTM_DELNEIGH. +type NeighUpdate struct { + Type uint16 + Neigh +} diff --git a/vendor/github.com/vishvananda/netlink/neigh_linux.go b/vendor/github.com/vishvananda/netlink/neigh_linux.go new file mode 100644 index 000000000..fb220d141 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/neigh_linux.go @@ -0,0 +1,434 @@ +package netlink + +import ( + "fmt" + "net" + "syscall" + "unsafe" + + "github.com/vishvananda/netlink/nl" + "github.com/vishvananda/netns" + "golang.org/x/sys/unix" +) + +const ( + NDA_UNSPEC = iota + NDA_DST + NDA_LLADDR + NDA_CACHEINFO + NDA_PROBES + NDA_VLAN + NDA_PORT + NDA_VNI + NDA_IFINDEX + NDA_MASTER + NDA_LINK_NETNSID + NDA_SRC_VNI + NDA_MAX = NDA_SRC_VNI +) + +// Neighbor Cache Entry States. +const ( + NUD_NONE = 0x00 + NUD_INCOMPLETE = 0x01 + NUD_REACHABLE = 0x02 + NUD_STALE = 0x04 + NUD_DELAY = 0x08 + NUD_PROBE = 0x10 + NUD_FAILED = 0x20 + NUD_NOARP = 0x40 + NUD_PERMANENT = 0x80 +) + +// Neighbor Flags +const ( + NTF_USE = 0x01 + NTF_SELF = 0x02 + NTF_MASTER = 0x04 + NTF_PROXY = 0x08 + NTF_ROUTER = 0x80 +) + +// Ndmsg is for adding, removing or receiving information about a neighbor table entry +type Ndmsg struct { + Family uint8 + Index uint32 + State uint16 + Flags uint8 + Type uint8 +} + +func deserializeNdmsg(b []byte) *Ndmsg { + var dummy Ndmsg + return (*Ndmsg)(unsafe.Pointer(&b[0:unsafe.Sizeof(dummy)][0])) +} + +func (msg *Ndmsg) Serialize() []byte { + return (*(*[unsafe.Sizeof(*msg)]byte)(unsafe.Pointer(msg)))[:] +} + +func (msg *Ndmsg) Len() int { + return int(unsafe.Sizeof(*msg)) +} + +// NeighAdd will add an IP to MAC mapping to the ARP table +// Equivalent to: `ip neigh add ....` +func NeighAdd(neigh *Neigh) error { + return pkgHandle.NeighAdd(neigh) +} + +// NeighAdd will add an IP to MAC mapping to the ARP table +// Equivalent to: `ip neigh add ....` +func (h *Handle) NeighAdd(neigh *Neigh) error { + return h.neighAdd(neigh, unix.NLM_F_CREATE|unix.NLM_F_EXCL) +} + +// NeighSet will add or replace an IP to MAC mapping to the ARP table +// Equivalent to: `ip neigh replace....` +func NeighSet(neigh *Neigh) error { + return pkgHandle.NeighSet(neigh) +} + +// NeighSet will add or replace an IP to MAC mapping to the ARP table +// Equivalent to: `ip neigh replace....` +func (h *Handle) NeighSet(neigh *Neigh) error { + return h.neighAdd(neigh, unix.NLM_F_CREATE|unix.NLM_F_REPLACE) +} + +// NeighAppend will append an entry to FDB +// Equivalent to: `bridge fdb append...` +func NeighAppend(neigh *Neigh) error { + return pkgHandle.NeighAppend(neigh) +} + +// NeighAppend will append an entry to FDB +// Equivalent to: `bridge fdb append...` +func (h *Handle) NeighAppend(neigh *Neigh) error { + return h.neighAdd(neigh, unix.NLM_F_CREATE|unix.NLM_F_APPEND) +} + +// NeighAppend will append an entry to FDB +// Equivalent to: `bridge fdb append...` +func neighAdd(neigh *Neigh, mode int) error { + return pkgHandle.neighAdd(neigh, mode) +} + +// NeighAppend will append an entry to FDB +// Equivalent to: `bridge fdb append...` +func (h *Handle) neighAdd(neigh *Neigh, mode int) error { + req := h.newNetlinkRequest(unix.RTM_NEWNEIGH, mode|unix.NLM_F_ACK) + return neighHandle(neigh, req) +} + +// NeighDel will delete an IP address from a link device. +// Equivalent to: `ip addr del $addr dev $link` +func NeighDel(neigh *Neigh) error { + return pkgHandle.NeighDel(neigh) +} + +// NeighDel will delete an IP address from a link device. +// Equivalent to: `ip addr del $addr dev $link` +func (h *Handle) NeighDel(neigh *Neigh) error { + req := h.newNetlinkRequest(unix.RTM_DELNEIGH, unix.NLM_F_ACK) + return neighHandle(neigh, req) +} + +func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error { + var family int + + if neigh.Family > 0 { + family = neigh.Family + } else { + family = nl.GetIPFamily(neigh.IP) + } + + msg := Ndmsg{ + Family: uint8(family), + Index: uint32(neigh.LinkIndex), + State: uint16(neigh.State), + Type: uint8(neigh.Type), + Flags: uint8(neigh.Flags), + } + req.AddData(&msg) + + ipData := neigh.IP.To4() + if ipData == nil { + ipData = neigh.IP.To16() + } + + dstData := nl.NewRtAttr(NDA_DST, ipData) + req.AddData(dstData) + + if neigh.LLIPAddr != nil { + llIPData := nl.NewRtAttr(NDA_LLADDR, neigh.LLIPAddr.To4()) + req.AddData(llIPData) + } else if neigh.Flags != NTF_PROXY || neigh.HardwareAddr != nil { + hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr)) + req.AddData(hwData) + } + + if neigh.Vlan != 0 { + vlanData := nl.NewRtAttr(NDA_VLAN, nl.Uint16Attr(uint16(neigh.Vlan))) + req.AddData(vlanData) + } + + if neigh.VNI != 0 { + vniData := nl.NewRtAttr(NDA_VNI, nl.Uint32Attr(uint32(neigh.VNI))) + req.AddData(vniData) + } + + if neigh.MasterIndex != 0 { + masterData := nl.NewRtAttr(NDA_MASTER, nl.Uint32Attr(uint32(neigh.MasterIndex))) + req.AddData(masterData) + } + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// NeighList returns a list of IP-MAC mappings in the system (ARP table). +// Equivalent to: `ip neighbor show`. +// The list can be filtered by link and ip family. +func NeighList(linkIndex, family int) ([]Neigh, error) { + return pkgHandle.NeighList(linkIndex, family) +} + +// NeighProxyList returns a list of neighbor proxies in the system. +// Equivalent to: `ip neighbor show proxy`. +// The list can be filtered by link and ip family. +func NeighProxyList(linkIndex, family int) ([]Neigh, error) { + return pkgHandle.NeighProxyList(linkIndex, family) +} + +// NeighList returns a list of IP-MAC mappings in the system (ARP table). +// Equivalent to: `ip neighbor show`. +// The list can be filtered by link and ip family. +func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) { + return h.NeighListExecute(Ndmsg{ + Family: uint8(family), + Index: uint32(linkIndex), + }) +} + +// NeighProxyList returns a list of neighbor proxies in the system. +// Equivalent to: `ip neighbor show proxy`. +// The list can be filtered by link, ip family. +func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) { + return h.NeighListExecute(Ndmsg{ + Family: uint8(family), + Index: uint32(linkIndex), + Flags: NTF_PROXY, + }) +} + +// NeighListExecute returns a list of neighbour entries filtered by link, ip family, flag and state. +func NeighListExecute(msg Ndmsg) ([]Neigh, error) { + return pkgHandle.NeighListExecute(msg) +} + +// NeighListExecute returns a list of neighbour entries filtered by link, ip family, flag and state. +func (h *Handle) NeighListExecute(msg Ndmsg) ([]Neigh, error) { + req := h.newNetlinkRequest(unix.RTM_GETNEIGH, unix.NLM_F_DUMP) + req.AddData(&msg) + + msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNEIGH) + if err != nil { + return nil, err + } + + var res []Neigh + for _, m := range msgs { + ndm := deserializeNdmsg(m) + if msg.Index != 0 && ndm.Index != msg.Index { + // Ignore messages from other interfaces + continue + } + if msg.Family != 0 && ndm.Family != msg.Family { + continue + } + if msg.State != 0 && ndm.State != msg.State { + continue + } + if msg.Type != 0 && ndm.Type != msg.Type { + continue + } + if msg.Flags != 0 && ndm.Flags != msg.Flags { + continue + } + + neigh, err := NeighDeserialize(m) + if err != nil { + continue + } + + res = append(res, *neigh) + } + + return res, nil +} + +func NeighDeserialize(m []byte) (*Neigh, error) { + msg := deserializeNdmsg(m) + + neigh := Neigh{ + LinkIndex: int(msg.Index), + Family: int(msg.Family), + State: int(msg.State), + Type: int(msg.Type), + Flags: int(msg.Flags), + } + + attrs, err := nl.ParseRouteAttr(m[msg.Len():]) + if err != nil { + return nil, err + } + + for _, attr := range attrs { + switch attr.Attr.Type { + case NDA_DST: + neigh.IP = net.IP(attr.Value) + case NDA_LLADDR: + // BUG: Is this a bug in the netlink library? + // #define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len)) + // #define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0)) + attrLen := attr.Attr.Len - unix.SizeofRtAttr + if attrLen == 4 { + neigh.LLIPAddr = net.IP(attr.Value) + } else if attrLen == 16 { + // Can be IPv6 or FireWire HWAddr + link, err := LinkByIndex(neigh.LinkIndex) + if err == nil && link.Attrs().EncapType == "tunnel6" { + neigh.IP = net.IP(attr.Value) + } else { + neigh.HardwareAddr = net.HardwareAddr(attr.Value) + } + } else { + neigh.HardwareAddr = net.HardwareAddr(attr.Value) + } + case NDA_VLAN: + neigh.Vlan = int(native.Uint16(attr.Value[0:2])) + case NDA_VNI: + neigh.VNI = int(native.Uint32(attr.Value[0:4])) + case NDA_MASTER: + neigh.MasterIndex = int(native.Uint32(attr.Value[0:4])) + } + } + + return &neigh, nil +} + +// NeighSubscribe takes a chan down which notifications will be sent +// when neighbors are added or deleted. Close the 'done' chan to stop subscription. +func NeighSubscribe(ch chan<- NeighUpdate, done <-chan struct{}) error { + return neighSubscribeAt(netns.None(), netns.None(), ch, done, nil, false) +} + +// NeighSubscribeAt works like NeighSubscribe plus it allows the caller +// to choose the network namespace in which to subscribe (ns). +func NeighSubscribeAt(ns netns.NsHandle, ch chan<- NeighUpdate, done <-chan struct{}) error { + return neighSubscribeAt(ns, netns.None(), ch, done, nil, false) +} + +// NeighSubscribeOptions contains a set of options to use with +// NeighSubscribeWithOptions. +type NeighSubscribeOptions struct { + Namespace *netns.NsHandle + ErrorCallback func(error) + ListExisting bool +} + +// NeighSubscribeWithOptions work like NeighSubscribe but enable to +// provide additional options to modify the behavior. Currently, the +// namespace can be provided as well as an error callback. +func NeighSubscribeWithOptions(ch chan<- NeighUpdate, done <-chan struct{}, options NeighSubscribeOptions) error { + if options.Namespace == nil { + none := netns.None() + options.Namespace = &none + } + return neighSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting) +} + +func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error { + s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_NEIGH) + makeRequest := func(family int) error { + req := pkgHandle.newNetlinkRequest(unix.RTM_GETNEIGH, + unix.NLM_F_DUMP) + infmsg := nl.NewIfInfomsg(family) + req.AddData(infmsg) + if err := s.Send(req); err != nil { + return err + } + return nil + } + if err != nil { + return err + } + if done != nil { + go func() { + <-done + s.Close() + }() + } + if listExisting { + if err := makeRequest(unix.AF_UNSPEC); err != nil { + return err + } + // We have to wait for NLMSG_DONE before making AF_BRIDGE request + } + go func() { + defer close(ch) + for { + msgs, from, err := s.Receive() + if err != nil { + if cberr != nil { + cberr(err) + } + return + } + if from.Pid != nl.PidKernel { + if cberr != nil { + cberr(fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)) + } + continue + } + for _, m := range msgs { + if m.Header.Type == unix.NLMSG_DONE { + if listExisting { + // This will be called after handling AF_UNSPEC + // list request, we have to wait for NLMSG_DONE + // before making another request + if err := makeRequest(unix.AF_BRIDGE); err != nil { + if cberr != nil { + cberr(err) + } + return + } + listExisting = false + } + continue + } + if m.Header.Type == unix.NLMSG_ERROR { + native := nl.NativeEndian() + error := int32(native.Uint32(m.Data[0:4])) + if error == 0 { + continue + } + if cberr != nil { + cberr(syscall.Errno(-error)) + } + return + } + neigh, err := NeighDeserialize(m.Data) + if err != nil { + if cberr != nil { + cberr(err) + } + return + } + ch <- NeighUpdate{Type: m.Header.Type, Neigh: *neigh} + } + } + }() + + return nil +} diff --git a/vendor/github.com/vishvananda/netlink/netlink.go b/vendor/github.com/vishvananda/netlink/netlink.go new file mode 100644 index 000000000..9cb685dc8 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/netlink.go @@ -0,0 +1,40 @@ +// Package netlink provides a simple library for netlink. Netlink is +// the interface a user-space program in linux uses to communicate with +// the kernel. It can be used to add and remove interfaces, set up ip +// addresses and routes, and confiugre ipsec. Netlink communication +// requires elevated privileges, so in most cases this code needs to +// be run as root. The low level primitives for netlink are contained +// in the nl subpackage. This package attempts to provide a high-level +// interface that is loosly modeled on the iproute2 cli. +package netlink + +import ( + "errors" + "net" +) + +var ( + // ErrNotImplemented is returned when a requested feature is not implemented. + ErrNotImplemented = errors.New("not implemented") +) + +// ParseIPNet parses a string in ip/net format and returns a net.IPNet. +// This is valuable because addresses in netlink are often IPNets and +// ParseCIDR returns an IPNet with the IP part set to the base IP of the +// range. +func ParseIPNet(s string) (*net.IPNet, error) { + ip, ipNet, err := net.ParseCIDR(s) + if err != nil { + return nil, err + } + ipNet.IP = ip + return ipNet, nil +} + +// NewIPNet generates an IPNet from an ip address using a netmask of 32 or 128. +func NewIPNet(ip net.IP) *net.IPNet { + if ip.To4() != nil { + return &net.IPNet{IP: ip, Mask: net.CIDRMask(32, 32)} + } + return &net.IPNet{IP: ip, Mask: net.CIDRMask(128, 128)} +} diff --git a/vendor/github.com/vishvananda/netlink/netlink_linux.go b/vendor/github.com/vishvananda/netlink/netlink_linux.go new file mode 100644 index 000000000..a20d293d8 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/netlink_linux.go @@ -0,0 +1,11 @@ +package netlink + +import "github.com/vishvananda/netlink/nl" + +// Family type definitions +const ( + FAMILY_ALL = nl.FAMILY_ALL + FAMILY_V4 = nl.FAMILY_V4 + FAMILY_V6 = nl.FAMILY_V6 + FAMILY_MPLS = nl.FAMILY_MPLS +) diff --git a/vendor/github.com/vishvananda/netlink/netlink_unspecified.go b/vendor/github.com/vishvananda/netlink/netlink_unspecified.go new file mode 100644 index 000000000..71436f25c --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/netlink_unspecified.go @@ -0,0 +1,241 @@ +// +build !linux + +package netlink + +import "net" + +func LinkSetUp(link Link) error { + return ErrNotImplemented +} + +func LinkSetDown(link Link) error { + return ErrNotImplemented +} + +func LinkSetMTU(link Link, mtu int) error { + return ErrNotImplemented +} + +func LinkSetMaster(link Link, master Link) error { + return ErrNotImplemented +} + +func LinkSetNsPid(link Link, nspid int) error { + return ErrNotImplemented +} + +func LinkSetNsFd(link Link, fd int) error { + return ErrNotImplemented +} + +func LinkSetName(link Link, name string) error { + return ErrNotImplemented +} + +func LinkSetAlias(link Link, name string) error { + return ErrNotImplemented +} + +func LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error { + return ErrNotImplemented +} + +func LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error { + return ErrNotImplemented +} + +func LinkSetVfVlan(link Link, vf, vlan int) error { + return ErrNotImplemented +} + +func LinkSetVfVlanQos(link Link, vf, vlan, qos int) error { + return ErrNotImplemented +} + +func LinkSetVfTxRate(link Link, vf, rate int) error { + return ErrNotImplemented +} + +func LinkSetVfRate(link Link, vf, minRate, maxRate int) error { + return ErrNotImplemented +} + +func LinkSetNoMaster(link Link) error { + return ErrNotImplemented +} + +func LinkSetMasterByIndex(link Link, masterIndex int) error { + return ErrNotImplemented +} + +func LinkSetXdpFd(link Link, fd int) error { + return ErrNotImplemented +} + +func LinkSetXdpFdWithFlags(link Link, fd, flags int) error { + return ErrNotImplemented +} + +func LinkSetARPOff(link Link) error { + return ErrNotImplemented +} + +func LinkSetARPOn(link Link) error { + return ErrNotImplemented +} + +func LinkByName(name string) (Link, error) { + return nil, ErrNotImplemented +} + +func LinkByAlias(alias string) (Link, error) { + return nil, ErrNotImplemented +} + +func LinkByIndex(index int) (Link, error) { + return nil, ErrNotImplemented +} + +func LinkSetHairpin(link Link, mode bool) error { + return ErrNotImplemented +} + +func LinkSetGuard(link Link, mode bool) error { + return ErrNotImplemented +} + +func LinkSetFastLeave(link Link, mode bool) error { + return ErrNotImplemented +} + +func LinkSetLearning(link Link, mode bool) error { + return ErrNotImplemented +} + +func LinkSetRootBlock(link Link, mode bool) error { + return ErrNotImplemented +} + +func LinkSetFlood(link Link, mode bool) error { + return ErrNotImplemented +} + +func LinkSetTxQLen(link Link, qlen int) error { + return ErrNotImplemented +} + +func LinkAdd(link Link) error { + return ErrNotImplemented +} + +func LinkDel(link Link) error { + return ErrNotImplemented +} + +func SetHairpin(link Link, mode bool) error { + return ErrNotImplemented +} + +func SetGuard(link Link, mode bool) error { + return ErrNotImplemented +} + +func SetFastLeave(link Link, mode bool) error { + return ErrNotImplemented +} + +func SetLearning(link Link, mode bool) error { + return ErrNotImplemented +} + +func SetRootBlock(link Link, mode bool) error { + return ErrNotImplemented +} + +func SetFlood(link Link, mode bool) error { + return ErrNotImplemented +} + +func LinkList() ([]Link, error) { + return nil, ErrNotImplemented +} + +func AddrAdd(link Link, addr *Addr) error { + return ErrNotImplemented +} + +func AddrReplace(link Link, addr *Addr) error { + return ErrNotImplemented +} + +func AddrDel(link Link, addr *Addr) error { + return ErrNotImplemented +} + +func AddrList(link Link, family int) ([]Addr, error) { + return nil, ErrNotImplemented +} + +func RouteAdd(route *Route) error { + return ErrNotImplemented +} + +func RouteDel(route *Route) error { + return ErrNotImplemented +} + +func RouteList(link Link, family int) ([]Route, error) { + return nil, ErrNotImplemented +} + +func XfrmPolicyAdd(policy *XfrmPolicy) error { + return ErrNotImplemented +} + +func XfrmPolicyDel(policy *XfrmPolicy) error { + return ErrNotImplemented +} + +func XfrmPolicyList(family int) ([]XfrmPolicy, error) { + return nil, ErrNotImplemented +} + +func XfrmStateAdd(policy *XfrmState) error { + return ErrNotImplemented +} + +func XfrmStateDel(policy *XfrmState) error { + return ErrNotImplemented +} + +func XfrmStateList(family int) ([]XfrmState, error) { + return nil, ErrNotImplemented +} + +func NeighAdd(neigh *Neigh) error { + return ErrNotImplemented +} + +func NeighSet(neigh *Neigh) error { + return ErrNotImplemented +} + +func NeighAppend(neigh *Neigh) error { + return ErrNotImplemented +} + +func NeighDel(neigh *Neigh) error { + return ErrNotImplemented +} + +func NeighList(linkIndex, family int) ([]Neigh, error) { + return nil, ErrNotImplemented +} + +func NeighDeserialize(m []byte) (*Neigh, error) { + return nil, ErrNotImplemented +} + +func SocketGet(local, remote net.Addr) (*Socket, error) { + return nil, ErrNotImplemented +} diff --git a/vendor/github.com/vishvananda/netlink/netns_linux.go b/vendor/github.com/vishvananda/netlink/netns_linux.go new file mode 100644 index 000000000..77cf6f469 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/netns_linux.go @@ -0,0 +1,141 @@ +package netlink + +// Network namespace ID functions +// +// The kernel has a weird concept called the network namespace ID. +// This is different from the file reference in proc (and any bind-mounted +// namespaces, etc.) +// +// Instead, namespaces can be assigned a numeric ID at any time. Once set, +// the ID is fixed. The ID can either be set manually by the user, or +// automatically, triggered by certain kernel actions. The most common kernel +// action that triggers namespace ID creation is moving one end of a veth pair +// in to that namespace. + +import ( + "fmt" + + "github.com/vishvananda/netlink/nl" + "golang.org/x/sys/unix" +) + +// These can be replaced by the values from sys/unix when it is next released. +const ( + _ = iota + NETNSA_NSID + NETNSA_PID + NETNSA_FD +) + +// GetNetNsIdByPid looks up the network namespace ID for a given pid (really thread id). +// Returns -1 if the namespace does not have an ID set. +func (h *Handle) GetNetNsIdByPid(pid int) (int, error) { + return h.getNetNsId(NETNSA_PID, uint32(pid)) +} + +// GetNetNsIdByPid looks up the network namespace ID for a given pid (really thread id). +// Returns -1 if the namespace does not have an ID set. +func GetNetNsIdByPid(pid int) (int, error) { + return pkgHandle.GetNetNsIdByPid(pid) +} + +// SetNetNSIdByPid sets the ID of the network namespace for a given pid (really thread id). +// The ID can only be set for namespaces without an ID already set. +func (h *Handle) SetNetNsIdByPid(pid, nsid int) error { + return h.setNetNsId(NETNSA_PID, uint32(pid), uint32(nsid)) +} + +// SetNetNSIdByPid sets the ID of the network namespace for a given pid (really thread id). +// The ID can only be set for namespaces without an ID already set. +func SetNetNsIdByPid(pid, nsid int) error { + return pkgHandle.SetNetNsIdByPid(pid, nsid) +} + +// GetNetNsIdByFd looks up the network namespace ID for a given fd. +// fd must be an open file descriptor to a namespace file. +// Returns -1 if the namespace does not have an ID set. +func (h *Handle) GetNetNsIdByFd(fd int) (int, error) { + return h.getNetNsId(NETNSA_FD, uint32(fd)) +} + +// GetNetNsIdByFd looks up the network namespace ID for a given fd. +// fd must be an open file descriptor to a namespace file. +// Returns -1 if the namespace does not have an ID set. +func GetNetNsIdByFd(fd int) (int, error) { + return pkgHandle.GetNetNsIdByFd(fd) +} + +// SetNetNSIdByFd sets the ID of the network namespace for a given fd. +// fd must be an open file descriptor to a namespace file. +// The ID can only be set for namespaces without an ID already set. +func (h *Handle) SetNetNsIdByFd(fd, nsid int) error { + return h.setNetNsId(NETNSA_FD, uint32(fd), uint32(nsid)) +} + +// SetNetNSIdByFd sets the ID of the network namespace for a given fd. +// fd must be an open file descriptor to a namespace file. +// The ID can only be set for namespaces without an ID already set. +func SetNetNsIdByFd(fd, nsid int) error { + return pkgHandle.SetNetNsIdByFd(fd, nsid) +} + +// getNetNsId requests the netnsid for a given type-val pair +// type should be either NETNSA_PID or NETNSA_FD +func (h *Handle) getNetNsId(attrType int, val uint32) (int, error) { + req := h.newNetlinkRequest(unix.RTM_GETNSID, unix.NLM_F_REQUEST) + + rtgen := nl.NewRtGenMsg() + req.AddData(rtgen) + + b := make([]byte, 4, 4) + native.PutUint32(b, val) + attr := nl.NewRtAttr(attrType, b) + req.AddData(attr) + + msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNSID) + + if err != nil { + return 0, err + } + + for _, m := range msgs { + msg := nl.DeserializeRtGenMsg(m) + + attrs, err := nl.ParseRouteAttr(m[msg.Len():]) + if err != nil { + return 0, err + } + + for _, attr := range attrs { + switch attr.Attr.Type { + case NETNSA_NSID: + return int(int32(native.Uint32(attr.Value))), nil + } + } + } + + return 0, fmt.Errorf("unexpected empty result") +} + +// setNetNsId sets the netnsid for a given type-val pair +// type should be either NETNSA_PID or NETNSA_FD +// The ID can only be set for namespaces without an ID already set +func (h *Handle) setNetNsId(attrType int, val uint32, newnsid uint32) error { + req := h.newNetlinkRequest(unix.RTM_NEWNSID, unix.NLM_F_REQUEST|unix.NLM_F_ACK) + + rtgen := nl.NewRtGenMsg() + req.AddData(rtgen) + + b := make([]byte, 4, 4) + native.PutUint32(b, val) + attr := nl.NewRtAttr(attrType, b) + req.AddData(attr) + + b1 := make([]byte, 4, 4) + native.PutUint32(b1, newnsid) + attr1 := nl.NewRtAttr(NETNSA_NSID, b1) + req.AddData(attr1) + + _, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNSID) + return err +} diff --git a/vendor/github.com/vishvananda/netlink/netns_unspecified.go b/vendor/github.com/vishvananda/netlink/netns_unspecified.go new file mode 100644 index 000000000..5c5899e36 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/netns_unspecified.go @@ -0,0 +1,19 @@ +// +build !linux + +package netlink + +func GetNetNsIdByPid(pid int) (int, error) { + return 0, ErrNotImplemented +} + +func SetNetNsIdByPid(pid, nsid int) error { + return ErrNotImplemented +} + +func GetNetNsIdByFd(fd int) (int, error) { + return 0, ErrNotImplemented +} + +func SetNetNsIdByFd(fd, nsid int) error { + return ErrNotImplemented +} diff --git a/vendor/github.com/vishvananda/netlink/nl/addr_linux.go b/vendor/github.com/vishvananda/netlink/nl/addr_linux.go new file mode 100644 index 000000000..6bea4ed02 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/addr_linux.go @@ -0,0 +1,71 @@ +package nl + +import ( + "unsafe" + + "golang.org/x/sys/unix" +) + +type IfAddrmsg struct { + unix.IfAddrmsg +} + +func NewIfAddrmsg(family int) *IfAddrmsg { + return &IfAddrmsg{ + IfAddrmsg: unix.IfAddrmsg{ + Family: uint8(family), + }, + } +} + +// struct ifaddrmsg { +// __u8 ifa_family; +// __u8 ifa_prefixlen; /* The prefix length */ +// __u8 ifa_flags; /* Flags */ +// __u8 ifa_scope; /* Address scope */ +// __u32 ifa_index; /* Link index */ +// }; + +// type IfAddrmsg struct { +// Family uint8 +// Prefixlen uint8 +// Flags uint8 +// Scope uint8 +// Index uint32 +// } +// SizeofIfAddrmsg = 0x8 + +func DeserializeIfAddrmsg(b []byte) *IfAddrmsg { + return (*IfAddrmsg)(unsafe.Pointer(&b[0:unix.SizeofIfAddrmsg][0])) +} + +func (msg *IfAddrmsg) Serialize() []byte { + return (*(*[unix.SizeofIfAddrmsg]byte)(unsafe.Pointer(msg)))[:] +} + +func (msg *IfAddrmsg) Len() int { + return unix.SizeofIfAddrmsg +} + +// struct ifa_cacheinfo { +// __u32 ifa_prefered; +// __u32 ifa_valid; +// __u32 cstamp; /* created timestamp, hundredths of seconds */ +// __u32 tstamp; /* updated timestamp, hundredths of seconds */ +// }; + +type IfaCacheInfo struct { + unix.IfaCacheinfo +} + +func (msg *IfaCacheInfo) Len() int { + return unix.SizeofIfaCacheinfo +} + +func DeserializeIfaCacheInfo(b []byte) *IfaCacheInfo { + return (*IfaCacheInfo)(unsafe.Pointer(&b[0:unix.SizeofIfaCacheinfo][0])) +} + +func (msg *IfaCacheInfo) Serialize() []byte { + return (*(*[unix.SizeofIfaCacheinfo]byte)(unsafe.Pointer(msg)))[:] +} diff --git a/vendor/github.com/vishvananda/netlink/nl/bridge_linux.go b/vendor/github.com/vishvananda/netlink/nl/bridge_linux.go new file mode 100644 index 000000000..34e78ba8d --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/bridge_linux.go @@ -0,0 +1,74 @@ +package nl + +import ( + "fmt" + "unsafe" +) + +const ( + SizeofBridgeVlanInfo = 0x04 +) + +/* Bridge Flags */ +const ( + BRIDGE_FLAGS_MASTER = iota + 1 /* Bridge command to/from master */ + BRIDGE_FLAGS_SELF /* Bridge command to/from lowerdev */ +) + +/* Bridge management nested attributes + * [IFLA_AF_SPEC] = { + * [IFLA_BRIDGE_FLAGS] + * [IFLA_BRIDGE_MODE] + * [IFLA_BRIDGE_VLAN_INFO] + * } + */ +const ( + IFLA_BRIDGE_FLAGS = iota + IFLA_BRIDGE_MODE + IFLA_BRIDGE_VLAN_INFO +) + +const ( + BRIDGE_VLAN_INFO_MASTER = 1 << iota + BRIDGE_VLAN_INFO_PVID + BRIDGE_VLAN_INFO_UNTAGGED + BRIDGE_VLAN_INFO_RANGE_BEGIN + BRIDGE_VLAN_INFO_RANGE_END +) + +// struct bridge_vlan_info { +// __u16 flags; +// __u16 vid; +// }; + +type BridgeVlanInfo struct { + Flags uint16 + Vid uint16 +} + +func (b *BridgeVlanInfo) Serialize() []byte { + return (*(*[SizeofBridgeVlanInfo]byte)(unsafe.Pointer(b)))[:] +} + +func DeserializeBridgeVlanInfo(b []byte) *BridgeVlanInfo { + return (*BridgeVlanInfo)(unsafe.Pointer(&b[0:SizeofBridgeVlanInfo][0])) +} + +func (b *BridgeVlanInfo) PortVID() bool { + return b.Flags&BRIDGE_VLAN_INFO_PVID > 0 +} + +func (b *BridgeVlanInfo) EngressUntag() bool { + return b.Flags&BRIDGE_VLAN_INFO_UNTAGGED > 0 +} + +func (b *BridgeVlanInfo) String() string { + return fmt.Sprintf("%+v", *b) +} + +/* New extended info filters for IFLA_EXT_MASK */ +const ( + RTEXT_FILTER_VF = 1 << iota + RTEXT_FILTER_BRVLAN + RTEXT_FILTER_BRVLAN_COMPRESSED +) diff --git a/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go b/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go new file mode 100644 index 000000000..14924027e --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go @@ -0,0 +1,218 @@ +package nl + +import "unsafe" + +// Track the message sizes for the correct serialization/deserialization +const ( + SizeofNfgenmsg = 4 + SizeofNfattr = 4 + SizeofNfConntrack = 376 + SizeofNfctTupleHead = 52 +) + +var L4ProtoMap = map[uint8]string{ + 6: "tcp", + 17: "udp", +} + +// All the following constants are coming from: +// https://github.com/torvalds/linux/blob/master/include/uapi/linux/netfilter/nfnetlink_conntrack.h + +// enum cntl_msg_types { +// IPCTNL_MSG_CT_NEW, +// IPCTNL_MSG_CT_GET, +// IPCTNL_MSG_CT_DELETE, +// IPCTNL_MSG_CT_GET_CTRZERO, +// IPCTNL_MSG_CT_GET_STATS_CPU, +// IPCTNL_MSG_CT_GET_STATS, +// IPCTNL_MSG_CT_GET_DYING, +// IPCTNL_MSG_CT_GET_UNCONFIRMED, +// +// IPCTNL_MSG_MAX +// }; +const ( + IPCTNL_MSG_CT_GET = 1 + IPCTNL_MSG_CT_DELETE = 2 +) + +// #define NFNETLINK_V0 0 +const ( + NFNETLINK_V0 = 0 +) + +const ( + NLA_F_NESTED uint16 = (1 << 15) // #define NLA_F_NESTED (1 << 15) + NLA_F_NET_BYTEORDER uint16 = (1 << 14) // #define NLA_F_NESTED (1 << 14) + NLA_TYPE_MASK = ^(NLA_F_NESTED | NLA_F_NET_BYTEORDER) +) + +// enum ctattr_type { +// CTA_UNSPEC, +// CTA_TUPLE_ORIG, +// CTA_TUPLE_REPLY, +// CTA_STATUS, +// CTA_PROTOINFO, +// CTA_HELP, +// CTA_NAT_SRC, +// #define CTA_NAT CTA_NAT_SRC /* backwards compatibility */ +// CTA_TIMEOUT, +// CTA_MARK, +// CTA_COUNTERS_ORIG, +// CTA_COUNTERS_REPLY, +// CTA_USE, +// CTA_ID, +// CTA_NAT_DST, +// CTA_TUPLE_MASTER, +// CTA_SEQ_ADJ_ORIG, +// CTA_NAT_SEQ_ADJ_ORIG = CTA_SEQ_ADJ_ORIG, +// CTA_SEQ_ADJ_REPLY, +// CTA_NAT_SEQ_ADJ_REPLY = CTA_SEQ_ADJ_REPLY, +// CTA_SECMARK, /* obsolete */ +// CTA_ZONE, +// CTA_SECCTX, +// CTA_TIMESTAMP, +// CTA_MARK_MASK, +// CTA_LABELS, +// CTA_LABELS_MASK, +// __CTA_MAX +// }; +const ( + CTA_TUPLE_ORIG = 1 + CTA_TUPLE_REPLY = 2 + CTA_STATUS = 3 + CTA_PROTOINFO = 4 + CTA_TIMEOUT = 7 + CTA_MARK = 8 + CTA_COUNTERS_ORIG = 9 + CTA_COUNTERS_REPLY = 10 + CTA_USE = 11 + CTA_ID = 12 + CTA_TIMESTAMP = 20 +) + +// enum ctattr_tuple { +// CTA_TUPLE_UNSPEC, +// CTA_TUPLE_IP, +// CTA_TUPLE_PROTO, +// CTA_TUPLE_ZONE, +// __CTA_TUPLE_MAX +// }; +// #define CTA_TUPLE_MAX (__CTA_TUPLE_MAX - 1) +const ( + CTA_TUPLE_IP = 1 + CTA_TUPLE_PROTO = 2 +) + +// enum ctattr_ip { +// CTA_IP_UNSPEC, +// CTA_IP_V4_SRC, +// CTA_IP_V4_DST, +// CTA_IP_V6_SRC, +// CTA_IP_V6_DST, +// __CTA_IP_MAX +// }; +// #define CTA_IP_MAX (__CTA_IP_MAX - 1) +const ( + CTA_IP_V4_SRC = 1 + CTA_IP_V4_DST = 2 + CTA_IP_V6_SRC = 3 + CTA_IP_V6_DST = 4 +) + +// enum ctattr_l4proto { +// CTA_PROTO_UNSPEC, +// CTA_PROTO_NUM, +// CTA_PROTO_SRC_PORT, +// CTA_PROTO_DST_PORT, +// CTA_PROTO_ICMP_ID, +// CTA_PROTO_ICMP_TYPE, +// CTA_PROTO_ICMP_CODE, +// CTA_PROTO_ICMPV6_ID, +// CTA_PROTO_ICMPV6_TYPE, +// CTA_PROTO_ICMPV6_CODE, +// __CTA_PROTO_MAX +// }; +// #define CTA_PROTO_MAX (__CTA_PROTO_MAX - 1) +const ( + CTA_PROTO_NUM = 1 + CTA_PROTO_SRC_PORT = 2 + CTA_PROTO_DST_PORT = 3 +) + +// enum ctattr_protoinfo { +// CTA_PROTOINFO_UNSPEC, +// CTA_PROTOINFO_TCP, +// CTA_PROTOINFO_DCCP, +// CTA_PROTOINFO_SCTP, +// __CTA_PROTOINFO_MAX +// }; +// #define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1) +const ( + CTA_PROTOINFO_TCP = 1 +) + +// enum ctattr_protoinfo_tcp { +// CTA_PROTOINFO_TCP_UNSPEC, +// CTA_PROTOINFO_TCP_STATE, +// CTA_PROTOINFO_TCP_WSCALE_ORIGINAL, +// CTA_PROTOINFO_TCP_WSCALE_REPLY, +// CTA_PROTOINFO_TCP_FLAGS_ORIGINAL, +// CTA_PROTOINFO_TCP_FLAGS_REPLY, +// __CTA_PROTOINFO_TCP_MAX +// }; +// #define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1) +const ( + CTA_PROTOINFO_TCP_STATE = 1 + CTA_PROTOINFO_TCP_WSCALE_ORIGINAL = 2 + CTA_PROTOINFO_TCP_WSCALE_REPLY = 3 + CTA_PROTOINFO_TCP_FLAGS_ORIGINAL = 4 + CTA_PROTOINFO_TCP_FLAGS_REPLY = 5 +) + +// enum ctattr_counters { +// CTA_COUNTERS_UNSPEC, +// CTA_COUNTERS_PACKETS, /* 64bit counters */ +// CTA_COUNTERS_BYTES, /* 64bit counters */ +// CTA_COUNTERS32_PACKETS, /* old 32bit counters, unused */ +// CTA_COUNTERS32_BYTES, /* old 32bit counters, unused */ +// CTA_COUNTERS_PAD, +// __CTA_COUNTERS_M +// }; +// #define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1) +const ( + CTA_COUNTERS_PACKETS = 1 + CTA_COUNTERS_BYTES = 2 +) + +// enum CTA TIMESTAMP TLVs +// CTA_TIMESTAMP_START /* 64bit value */ +// CTA_TIMESTAMP_STOP /* 64bit value */ +const ( + CTA_TIMESTAMP_START = 1 + CTA_TIMESTAMP_STOP = 2 +) + +// /* General form of address family dependent message. +// */ +// struct nfgenmsg { +// __u8 nfgen_family; /* AF_xxx */ +// __u8 version; /* nfnetlink version */ +// __be16 res_id; /* resource id */ +// }; +type Nfgenmsg struct { + NfgenFamily uint8 + Version uint8 + ResId uint16 // big endian +} + +func (msg *Nfgenmsg) Len() int { + return SizeofNfgenmsg +} + +func DeserializeNfgenmsg(b []byte) *Nfgenmsg { + return (*Nfgenmsg)(unsafe.Pointer(&b[0:SizeofNfgenmsg][0])) +} + +func (msg *Nfgenmsg) Serialize() []byte { + return (*(*[SizeofNfgenmsg]byte)(unsafe.Pointer(msg)))[:] +} diff --git a/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go b/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go new file mode 100644 index 000000000..aa6155e21 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go @@ -0,0 +1,63 @@ +package nl + +// All the following constants are coming from: +// https://github.com/torvalds/linux/blob/master/include/uapi/linux/devlink.h + +const ( + GENL_DEVLINK_VERSION = 1 + GENL_DEVLINK_NAME = "devlink" +) + +const ( + DEVLINK_CMD_GET = 1 + DEVLINK_CMD_PORT_GET = 5 + DEVLINK_CMD_ESWITCH_GET = 29 + DEVLINK_CMD_ESWITCH_SET = 30 +) + +const ( + DEVLINK_ATTR_BUS_NAME = 1 + DEVLINK_ATTR_DEV_NAME = 2 + DEVLINK_ATTR_PORT_INDEX = 3 + DEVLINK_ATTR_PORT_TYPE = 4 + DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 6 + DEVLINK_ATTR_PORT_NETDEV_NAME = 7 + DEVLINK_ATTR_PORT_IBDEV_NAME = 8 + DEVLINK_ATTR_ESWITCH_MODE = 25 + DEVLINK_ATTR_ESWITCH_INLINE_MODE = 26 + DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 62 + DEVLINK_ATTR_PORT_FLAVOUR = 77 +) + +const ( + DEVLINK_ESWITCH_MODE_LEGACY = 0 + DEVLINK_ESWITCH_MODE_SWITCHDEV = 1 +) + +const ( + DEVLINK_ESWITCH_INLINE_MODE_NONE = 0 + DEVLINK_ESWITCH_INLINE_MODE_LINK = 1 + DEVLINK_ESWITCH_INLINE_MODE_NETWORK = 2 + DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT = 3 +) + +const ( + DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0 + DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 1 +) + +const ( + DEVLINK_PORT_FLAVOUR_PHYSICAL = 0 + DEVLINK_PORT_FLAVOUR_CPU = 1 + DEVLINK_PORT_FLAVOUR_DSA = 2 + DEVLINK_PORT_FLAVOUR_PCI_PF = 3 + DEVLINK_PORT_FLAVOUR_PCI_VF = 4 + DEVLINK_PORT_FLAVOUR_VIRTUAL = 5 +) + +const ( + DEVLINK_PORT_TYPE_NOTSET = 0 + DEVLINK_PORT_TYPE_AUTO = 1 + DEVLINK_PORT_TYPE_ETH = 2 + DEVLINK_PORT_TYPE_IB = 3 +) diff --git a/vendor/github.com/vishvananda/netlink/nl/genetlink_linux.go b/vendor/github.com/vishvananda/netlink/nl/genetlink_linux.go new file mode 100644 index 000000000..81b46f2c7 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/genetlink_linux.go @@ -0,0 +1,89 @@ +package nl + +import ( + "unsafe" +) + +const SizeofGenlmsg = 4 + +const ( + GENL_ID_CTRL = 0x10 + GENL_CTRL_VERSION = 2 + GENL_CTRL_NAME = "nlctrl" +) + +const ( + GENL_CTRL_CMD_GETFAMILY = 3 +) + +const ( + GENL_CTRL_ATTR_UNSPEC = iota + GENL_CTRL_ATTR_FAMILY_ID + GENL_CTRL_ATTR_FAMILY_NAME + GENL_CTRL_ATTR_VERSION + GENL_CTRL_ATTR_HDRSIZE + GENL_CTRL_ATTR_MAXATTR + GENL_CTRL_ATTR_OPS + GENL_CTRL_ATTR_MCAST_GROUPS +) + +const ( + GENL_CTRL_ATTR_OP_UNSPEC = iota + GENL_CTRL_ATTR_OP_ID + GENL_CTRL_ATTR_OP_FLAGS +) + +const ( + GENL_ADMIN_PERM = 1 << iota + GENL_CMD_CAP_DO + GENL_CMD_CAP_DUMP + GENL_CMD_CAP_HASPOL +) + +const ( + GENL_CTRL_ATTR_MCAST_GRP_UNSPEC = iota + GENL_CTRL_ATTR_MCAST_GRP_NAME + GENL_CTRL_ATTR_MCAST_GRP_ID +) + +const ( + GENL_GTP_VERSION = 0 + GENL_GTP_NAME = "gtp" +) + +const ( + GENL_GTP_CMD_NEWPDP = iota + GENL_GTP_CMD_DELPDP + GENL_GTP_CMD_GETPDP +) + +const ( + GENL_GTP_ATTR_UNSPEC = iota + GENL_GTP_ATTR_LINK + GENL_GTP_ATTR_VERSION + GENL_GTP_ATTR_TID + GENL_GTP_ATTR_PEER_ADDRESS + GENL_GTP_ATTR_MS_ADDRESS + GENL_GTP_ATTR_FLOW + GENL_GTP_ATTR_NET_NS_FD + GENL_GTP_ATTR_I_TEI + GENL_GTP_ATTR_O_TEI + GENL_GTP_ATTR_PAD +) + +type Genlmsg struct { + Command uint8 + Version uint8 +} + +func (msg *Genlmsg) Len() int { + return SizeofGenlmsg +} + +func DeserializeGenlmsg(b []byte) *Genlmsg { + return (*Genlmsg)(unsafe.Pointer(&b[0:SizeofGenlmsg][0])) +} + +func (msg *Genlmsg) Serialize() []byte { + return (*(*[SizeofGenlmsg]byte)(unsafe.Pointer(msg)))[:] +} diff --git a/vendor/github.com/vishvananda/netlink/nl/ipset_linux.go b/vendor/github.com/vishvananda/netlink/nl/ipset_linux.go new file mode 100644 index 000000000..a60b4b09d --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/ipset_linux.go @@ -0,0 +1,222 @@ +package nl + +import ( + "strconv" + + "golang.org/x/sys/unix" +) + +const ( + /* The protocol version */ + IPSET_PROTOCOL = 6 + + /* The max length of strings including NUL: set and type identifiers */ + IPSET_MAXNAMELEN = 32 + + /* The maximum permissible comment length we will accept over netlink */ + IPSET_MAX_COMMENT_SIZE = 255 +) + +const ( + _ = iota + IPSET_CMD_PROTOCOL /* 1: Return protocol version */ + IPSET_CMD_CREATE /* 2: Create a new (empty) set */ + IPSET_CMD_DESTROY /* 3: Destroy a (empty) set */ + IPSET_CMD_FLUSH /* 4: Remove all elements from a set */ + IPSET_CMD_RENAME /* 5: Rename a set */ + IPSET_CMD_SWAP /* 6: Swap two sets */ + IPSET_CMD_LIST /* 7: List sets */ + IPSET_CMD_SAVE /* 8: Save sets */ + IPSET_CMD_ADD /* 9: Add an element to a set */ + IPSET_CMD_DEL /* 10: Delete an element from a set */ + IPSET_CMD_TEST /* 11: Test an element in a set */ + IPSET_CMD_HEADER /* 12: Get set header data only */ + IPSET_CMD_TYPE /* 13: Get set type */ +) + +/* Attributes at command level */ +const ( + _ = iota + IPSET_ATTR_PROTOCOL /* 1: Protocol version */ + IPSET_ATTR_SETNAME /* 2: Name of the set */ + IPSET_ATTR_TYPENAME /* 3: Typename */ + IPSET_ATTR_REVISION /* 4: Settype revision */ + IPSET_ATTR_FAMILY /* 5: Settype family */ + IPSET_ATTR_FLAGS /* 6: Flags at command level */ + IPSET_ATTR_DATA /* 7: Nested attributes */ + IPSET_ATTR_ADT /* 8: Multiple data containers */ + IPSET_ATTR_LINENO /* 9: Restore lineno */ + IPSET_ATTR_PROTOCOL_MIN /* 10: Minimal supported version number */ + + IPSET_ATTR_SETNAME2 = IPSET_ATTR_TYPENAME /* Setname at rename/swap */ + IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN /* type rev min */ +) + +/* CADT specific attributes */ +const ( + IPSET_ATTR_IP = 1 + IPSET_ATTR_IP_FROM = 1 + IPSET_ATTR_IP_TO = 2 + IPSET_ATTR_CIDR = 3 + IPSET_ATTR_PORT = 4 + IPSET_ATTR_PORT_FROM = 4 + IPSET_ATTR_PORT_TO = 5 + IPSET_ATTR_TIMEOUT = 6 + IPSET_ATTR_PROTO = 7 + IPSET_ATTR_CADT_FLAGS = 8 + IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO /* 9 */ + IPSET_ATTR_MARK = 10 + IPSET_ATTR_MARKMASK = 11 + + /* Reserve empty slots */ + IPSET_ATTR_CADT_MAX = 16 + + /* Create-only specific attributes */ + IPSET_ATTR_GC = 3 + iota + IPSET_ATTR_HASHSIZE + IPSET_ATTR_MAXELEM + IPSET_ATTR_NETMASK + IPSET_ATTR_PROBES + IPSET_ATTR_RESIZE + IPSET_ATTR_SIZE + + /* Kernel-only */ + IPSET_ATTR_ELEMENTS + IPSET_ATTR_REFERENCES + IPSET_ATTR_MEMSIZE + + SET_ATTR_CREATE_MAX +) + +/* ADT specific attributes */ +const ( + IPSET_ATTR_ETHER = IPSET_ATTR_CADT_MAX + iota + 1 + IPSET_ATTR_NAME + IPSET_ATTR_NAMEREF + IPSET_ATTR_IP2 + IPSET_ATTR_CIDR2 + IPSET_ATTR_IP2_TO + IPSET_ATTR_IFACE + IPSET_ATTR_BYTES + IPSET_ATTR_PACKETS + IPSET_ATTR_COMMENT + IPSET_ATTR_SKBMARK + IPSET_ATTR_SKBPRIO + IPSET_ATTR_SKBQUEUE +) + +/* Flags at CADT attribute level, upper half of cmdattrs */ +const ( + IPSET_FLAG_BIT_BEFORE = 0 + IPSET_FLAG_BEFORE = (1 << IPSET_FLAG_BIT_BEFORE) + IPSET_FLAG_BIT_PHYSDEV = 1 + IPSET_FLAG_PHYSDEV = (1 << IPSET_FLAG_BIT_PHYSDEV) + IPSET_FLAG_BIT_NOMATCH = 2 + IPSET_FLAG_NOMATCH = (1 << IPSET_FLAG_BIT_NOMATCH) + IPSET_FLAG_BIT_WITH_COUNTERS = 3 + IPSET_FLAG_WITH_COUNTERS = (1 << IPSET_FLAG_BIT_WITH_COUNTERS) + IPSET_FLAG_BIT_WITH_COMMENT = 4 + IPSET_FLAG_WITH_COMMENT = (1 << IPSET_FLAG_BIT_WITH_COMMENT) + IPSET_FLAG_BIT_WITH_FORCEADD = 5 + IPSET_FLAG_WITH_FORCEADD = (1 << IPSET_FLAG_BIT_WITH_FORCEADD) + IPSET_FLAG_BIT_WITH_SKBINFO = 6 + IPSET_FLAG_WITH_SKBINFO = (1 << IPSET_FLAG_BIT_WITH_SKBINFO) + IPSET_FLAG_CADT_MAX = 15 +) + +const ( + IPSET_ERR_PRIVATE = 4096 + iota + IPSET_ERR_PROTOCOL + IPSET_ERR_FIND_TYPE + IPSET_ERR_MAX_SETS + IPSET_ERR_BUSY + IPSET_ERR_EXIST_SETNAME2 + IPSET_ERR_TYPE_MISMATCH + IPSET_ERR_EXIST + IPSET_ERR_INVALID_CIDR + IPSET_ERR_INVALID_NETMASK + IPSET_ERR_INVALID_FAMILY + IPSET_ERR_TIMEOUT + IPSET_ERR_REFERENCED + IPSET_ERR_IPADDR_IPV4 + IPSET_ERR_IPADDR_IPV6 + IPSET_ERR_COUNTER + IPSET_ERR_COMMENT + IPSET_ERR_INVALID_MARKMASK + IPSET_ERR_SKBINFO + + /* Type specific error codes */ + IPSET_ERR_TYPE_SPECIFIC = 4352 +) + +type IPSetError uintptr + +func (e IPSetError) Error() string { + switch int(e) { + case IPSET_ERR_PRIVATE: + return "private" + case IPSET_ERR_PROTOCOL: + return "invalid protocol" + case IPSET_ERR_FIND_TYPE: + return "invalid type" + case IPSET_ERR_MAX_SETS: + return "max sets reached" + case IPSET_ERR_BUSY: + return "busy" + case IPSET_ERR_EXIST_SETNAME2: + return "exist_setname2" + case IPSET_ERR_TYPE_MISMATCH: + return "type mismatch" + case IPSET_ERR_EXIST: + return "exist" + case IPSET_ERR_INVALID_CIDR: + return "invalid cidr" + case IPSET_ERR_INVALID_NETMASK: + return "invalid netmask" + case IPSET_ERR_INVALID_FAMILY: + return "invalid family" + case IPSET_ERR_TIMEOUT: + return "timeout" + case IPSET_ERR_REFERENCED: + return "referenced" + case IPSET_ERR_IPADDR_IPV4: + return "invalid ipv4 address" + case IPSET_ERR_IPADDR_IPV6: + return "invalid ipv6 address" + case IPSET_ERR_COUNTER: + return "invalid counter" + case IPSET_ERR_COMMENT: + return "invalid comment" + case IPSET_ERR_INVALID_MARKMASK: + return "invalid markmask" + case IPSET_ERR_SKBINFO: + return "skbinfo" + default: + return "errno " + strconv.Itoa(int(e)) + } +} + +func GetIpsetFlags(cmd int) int { + switch cmd { + case IPSET_CMD_CREATE: + return unix.NLM_F_REQUEST | unix.NLM_F_ACK | unix.NLM_F_CREATE + case IPSET_CMD_DESTROY, + IPSET_CMD_FLUSH, + IPSET_CMD_RENAME, + IPSET_CMD_SWAP, + IPSET_CMD_TEST: + return unix.NLM_F_REQUEST | unix.NLM_F_ACK + case IPSET_CMD_LIST, + IPSET_CMD_SAVE: + return unix.NLM_F_REQUEST | unix.NLM_F_ACK | unix.NLM_F_ROOT | unix.NLM_F_MATCH | unix.NLM_F_DUMP + case IPSET_CMD_ADD, + IPSET_CMD_DEL: + return unix.NLM_F_REQUEST | unix.NLM_F_ACK + case IPSET_CMD_HEADER, + IPSET_CMD_TYPE, + IPSET_CMD_PROTOCOL: + return unix.NLM_F_REQUEST + default: + return 0 + } +} diff --git a/vendor/github.com/vishvananda/netlink/nl/link_linux.go b/vendor/github.com/vishvananda/netlink/nl/link_linux.go new file mode 100644 index 000000000..c72cc436e --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/link_linux.go @@ -0,0 +1,711 @@ +package nl + +import ( + "bytes" + "encoding/binary" + "unsafe" +) + +const ( + DEFAULT_CHANGE = 0xFFFFFFFF +) + +const ( + IFLA_INFO_UNSPEC = iota + IFLA_INFO_KIND + IFLA_INFO_DATA + IFLA_INFO_XSTATS + IFLA_INFO_SLAVE_KIND + IFLA_INFO_SLAVE_DATA + IFLA_INFO_MAX = IFLA_INFO_SLAVE_DATA +) + +const ( + IFLA_VLAN_UNSPEC = iota + IFLA_VLAN_ID + IFLA_VLAN_FLAGS + IFLA_VLAN_EGRESS_QOS + IFLA_VLAN_INGRESS_QOS + IFLA_VLAN_PROTOCOL + IFLA_VLAN_MAX = IFLA_VLAN_PROTOCOL +) + +const ( + VETH_INFO_UNSPEC = iota + VETH_INFO_PEER + VETH_INFO_MAX = VETH_INFO_PEER +) + +const ( + IFLA_VXLAN_UNSPEC = iota + IFLA_VXLAN_ID + IFLA_VXLAN_GROUP + IFLA_VXLAN_LINK + IFLA_VXLAN_LOCAL + IFLA_VXLAN_TTL + IFLA_VXLAN_TOS + IFLA_VXLAN_LEARNING + IFLA_VXLAN_AGEING + IFLA_VXLAN_LIMIT + IFLA_VXLAN_PORT_RANGE + IFLA_VXLAN_PROXY + IFLA_VXLAN_RSC + IFLA_VXLAN_L2MISS + IFLA_VXLAN_L3MISS + IFLA_VXLAN_PORT + IFLA_VXLAN_GROUP6 + IFLA_VXLAN_LOCAL6 + IFLA_VXLAN_UDP_CSUM + IFLA_VXLAN_UDP_ZERO_CSUM6_TX + IFLA_VXLAN_UDP_ZERO_CSUM6_RX + IFLA_VXLAN_REMCSUM_TX + IFLA_VXLAN_REMCSUM_RX + IFLA_VXLAN_GBP + IFLA_VXLAN_REMCSUM_NOPARTIAL + IFLA_VXLAN_FLOWBASED + IFLA_VXLAN_MAX = IFLA_VXLAN_FLOWBASED +) + +const ( + BRIDGE_MODE_UNSPEC = iota + BRIDGE_MODE_HAIRPIN +) + +const ( + IFLA_BRPORT_UNSPEC = iota + IFLA_BRPORT_STATE + IFLA_BRPORT_PRIORITY + IFLA_BRPORT_COST + IFLA_BRPORT_MODE + IFLA_BRPORT_GUARD + IFLA_BRPORT_PROTECT + IFLA_BRPORT_FAST_LEAVE + IFLA_BRPORT_LEARNING + IFLA_BRPORT_UNICAST_FLOOD + IFLA_BRPORT_PROXYARP + IFLA_BRPORT_LEARNING_SYNC + IFLA_BRPORT_PROXYARP_WIFI + IFLA_BRPORT_MAX = IFLA_BRPORT_PROXYARP_WIFI +) + +const ( + IFLA_IPVLAN_UNSPEC = iota + IFLA_IPVLAN_MODE + IFLA_IPVLAN_FLAG + IFLA_IPVLAN_MAX = IFLA_IPVLAN_FLAG +) + +const ( + IFLA_MACVLAN_UNSPEC = iota + IFLA_MACVLAN_MODE + IFLA_MACVLAN_FLAGS + IFLA_MACVLAN_MACADDR_MODE + IFLA_MACVLAN_MACADDR + IFLA_MACVLAN_MACADDR_DATA + IFLA_MACVLAN_MACADDR_COUNT + IFLA_MACVLAN_MAX = IFLA_MACVLAN_FLAGS +) + +const ( + MACVLAN_MODE_PRIVATE = 1 + MACVLAN_MODE_VEPA = 2 + MACVLAN_MODE_BRIDGE = 4 + MACVLAN_MODE_PASSTHRU = 8 + MACVLAN_MODE_SOURCE = 16 +) + +const ( + MACVLAN_MACADDR_ADD = iota + MACVLAN_MACADDR_DEL + MACVLAN_MACADDR_FLUSH + MACVLAN_MACADDR_SET +) + +const ( + IFLA_BOND_UNSPEC = iota + IFLA_BOND_MODE + IFLA_BOND_ACTIVE_SLAVE + IFLA_BOND_MIIMON + IFLA_BOND_UPDELAY + IFLA_BOND_DOWNDELAY + IFLA_BOND_USE_CARRIER + IFLA_BOND_ARP_INTERVAL + IFLA_BOND_ARP_IP_TARGET + IFLA_BOND_ARP_VALIDATE + IFLA_BOND_ARP_ALL_TARGETS + IFLA_BOND_PRIMARY + IFLA_BOND_PRIMARY_RESELECT + IFLA_BOND_FAIL_OVER_MAC + IFLA_BOND_XMIT_HASH_POLICY + IFLA_BOND_RESEND_IGMP + IFLA_BOND_NUM_PEER_NOTIF + IFLA_BOND_ALL_SLAVES_ACTIVE + IFLA_BOND_MIN_LINKS + IFLA_BOND_LP_INTERVAL + IFLA_BOND_PACKETS_PER_SLAVE + IFLA_BOND_AD_LACP_RATE + IFLA_BOND_AD_SELECT + IFLA_BOND_AD_INFO + IFLA_BOND_AD_ACTOR_SYS_PRIO + IFLA_BOND_AD_USER_PORT_KEY + IFLA_BOND_AD_ACTOR_SYSTEM + IFLA_BOND_TLB_DYNAMIC_LB +) + +const ( + IFLA_BOND_AD_INFO_UNSPEC = iota + IFLA_BOND_AD_INFO_AGGREGATOR + IFLA_BOND_AD_INFO_NUM_PORTS + IFLA_BOND_AD_INFO_ACTOR_KEY + IFLA_BOND_AD_INFO_PARTNER_KEY + IFLA_BOND_AD_INFO_PARTNER_MAC +) + +const ( + IFLA_BOND_SLAVE_UNSPEC = iota + IFLA_BOND_SLAVE_STATE + IFLA_BOND_SLAVE_MII_STATUS + IFLA_BOND_SLAVE_LINK_FAILURE_COUNT + IFLA_BOND_SLAVE_PERM_HWADDR + IFLA_BOND_SLAVE_QUEUE_ID + IFLA_BOND_SLAVE_AD_AGGREGATOR_ID + IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE + IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE +) + +const ( + IFLA_GENEVE_UNSPEC = iota + IFLA_GENEVE_ID // vni + IFLA_GENEVE_REMOTE + IFLA_GENEVE_TTL + IFLA_GENEVE_TOS + IFLA_GENEVE_PORT // destination port + IFLA_GENEVE_COLLECT_METADATA + IFLA_GENEVE_REMOTE6 + IFLA_GENEVE_UDP_CSUM + IFLA_GENEVE_UDP_ZERO_CSUM6_TX + IFLA_GENEVE_UDP_ZERO_CSUM6_RX + IFLA_GENEVE_LABEL + IFLA_GENEVE_MAX = IFLA_GENEVE_LABEL +) + +const ( + IFLA_GRE_UNSPEC = iota + IFLA_GRE_LINK + IFLA_GRE_IFLAGS + IFLA_GRE_OFLAGS + IFLA_GRE_IKEY + IFLA_GRE_OKEY + IFLA_GRE_LOCAL + IFLA_GRE_REMOTE + IFLA_GRE_TTL + IFLA_GRE_TOS + IFLA_GRE_PMTUDISC + IFLA_GRE_ENCAP_LIMIT + IFLA_GRE_FLOWINFO + IFLA_GRE_FLAGS + IFLA_GRE_ENCAP_TYPE + IFLA_GRE_ENCAP_FLAGS + IFLA_GRE_ENCAP_SPORT + IFLA_GRE_ENCAP_DPORT + IFLA_GRE_COLLECT_METADATA + IFLA_GRE_MAX = IFLA_GRE_COLLECT_METADATA +) + +const ( + GRE_CSUM = 0x8000 + GRE_ROUTING = 0x4000 + GRE_KEY = 0x2000 + GRE_SEQ = 0x1000 + GRE_STRICT = 0x0800 + GRE_REC = 0x0700 + GRE_FLAGS = 0x00F8 + GRE_VERSION = 0x0007 +) + +const ( + IFLA_VF_INFO_UNSPEC = iota + IFLA_VF_INFO + IFLA_VF_INFO_MAX = IFLA_VF_INFO +) + +const ( + IFLA_VF_UNSPEC = iota + IFLA_VF_MAC /* Hardware queue specific attributes */ + IFLA_VF_VLAN + IFLA_VF_TX_RATE /* Max TX Bandwidth Allocation */ + IFLA_VF_SPOOFCHK /* Spoof Checking on/off switch */ + IFLA_VF_LINK_STATE /* link state enable/disable/auto switch */ + IFLA_VF_RATE /* Min and Max TX Bandwidth Allocation */ + IFLA_VF_RSS_QUERY_EN /* RSS Redirection Table and Hash Key query + * on/off switch + */ + IFLA_VF_STATS /* network device statistics */ + IFLA_VF_TRUST /* Trust state of VF */ + IFLA_VF_IB_NODE_GUID /* VF Infiniband node GUID */ + IFLA_VF_IB_PORT_GUID /* VF Infiniband port GUID */ + IFLA_VF_MAX = IFLA_VF_IB_PORT_GUID +) + +const ( + IFLA_VF_LINK_STATE_AUTO = iota /* link state of the uplink */ + IFLA_VF_LINK_STATE_ENABLE /* link always up */ + IFLA_VF_LINK_STATE_DISABLE /* link always down */ + IFLA_VF_LINK_STATE_MAX = IFLA_VF_LINK_STATE_DISABLE +) + +const ( + IFLA_VF_STATS_RX_PACKETS = iota + IFLA_VF_STATS_TX_PACKETS + IFLA_VF_STATS_RX_BYTES + IFLA_VF_STATS_TX_BYTES + IFLA_VF_STATS_BROADCAST + IFLA_VF_STATS_MULTICAST + IFLA_VF_STATS_RX_DROPPED + IFLA_VF_STATS_TX_DROPPED + IFLA_VF_STATS_MAX = IFLA_VF_STATS_TX_DROPPED +) + +const ( + SizeofVfMac = 0x24 + SizeofVfVlan = 0x0c + SizeofVfTxRate = 0x08 + SizeofVfRate = 0x0c + SizeofVfSpoofchk = 0x08 + SizeofVfLinkState = 0x08 + SizeofVfRssQueryEn = 0x08 + SizeofVfTrust = 0x08 + SizeofVfGUID = 0x10 +) + +// struct ifla_vf_mac { +// __u32 vf; +// __u8 mac[32]; /* MAX_ADDR_LEN */ +// }; + +type VfMac struct { + Vf uint32 + Mac [32]byte +} + +func (msg *VfMac) Len() int { + return SizeofVfMac +} + +func DeserializeVfMac(b []byte) *VfMac { + return (*VfMac)(unsafe.Pointer(&b[0:SizeofVfMac][0])) +} + +func (msg *VfMac) Serialize() []byte { + return (*(*[SizeofVfMac]byte)(unsafe.Pointer(msg)))[:] +} + +// struct ifla_vf_vlan { +// __u32 vf; +// __u32 vlan; /* 0 - 4095, 0 disables VLAN filter */ +// __u32 qos; +// }; + +type VfVlan struct { + Vf uint32 + Vlan uint32 + Qos uint32 +} + +func (msg *VfVlan) Len() int { + return SizeofVfVlan +} + +func DeserializeVfVlan(b []byte) *VfVlan { + return (*VfVlan)(unsafe.Pointer(&b[0:SizeofVfVlan][0])) +} + +func (msg *VfVlan) Serialize() []byte { + return (*(*[SizeofVfVlan]byte)(unsafe.Pointer(msg)))[:] +} + +// struct ifla_vf_tx_rate { +// __u32 vf; +// __u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */ +// }; + +type VfTxRate struct { + Vf uint32 + Rate uint32 +} + +func (msg *VfTxRate) Len() int { + return SizeofVfTxRate +} + +func DeserializeVfTxRate(b []byte) *VfTxRate { + return (*VfTxRate)(unsafe.Pointer(&b[0:SizeofVfTxRate][0])) +} + +func (msg *VfTxRate) Serialize() []byte { + return (*(*[SizeofVfTxRate]byte)(unsafe.Pointer(msg)))[:] +} + +//struct ifla_vf_stats { +// __u64 rx_packets; +// __u64 tx_packets; +// __u64 rx_bytes; +// __u64 tx_bytes; +// __u64 broadcast; +// __u64 multicast; +//}; + +type VfStats struct { + RxPackets uint64 + TxPackets uint64 + RxBytes uint64 + TxBytes uint64 + Multicast uint64 + Broadcast uint64 + RxDropped uint64 + TxDropped uint64 +} + +func DeserializeVfStats(b []byte) VfStats { + var vfstat VfStats + stats, err := ParseRouteAttr(b) + if err != nil { + return vfstat + } + var valueVar uint64 + for _, stat := range stats { + if err := binary.Read(bytes.NewBuffer(stat.Value), NativeEndian(), &valueVar); err != nil { + break + } + switch stat.Attr.Type { + case IFLA_VF_STATS_RX_PACKETS: + vfstat.RxPackets = valueVar + case IFLA_VF_STATS_TX_PACKETS: + vfstat.TxPackets = valueVar + case IFLA_VF_STATS_RX_BYTES: + vfstat.RxBytes = valueVar + case IFLA_VF_STATS_TX_BYTES: + vfstat.TxBytes = valueVar + case IFLA_VF_STATS_MULTICAST: + vfstat.Multicast = valueVar + case IFLA_VF_STATS_BROADCAST: + vfstat.Broadcast = valueVar + case IFLA_VF_STATS_RX_DROPPED: + vfstat.RxDropped = valueVar + case IFLA_VF_STATS_TX_DROPPED: + vfstat.TxDropped = valueVar + } + } + return vfstat +} + +// struct ifla_vf_rate { +// __u32 vf; +// __u32 min_tx_rate; /* Min Bandwidth in Mbps */ +// __u32 max_tx_rate; /* Max Bandwidth in Mbps */ +// }; + +type VfRate struct { + Vf uint32 + MinTxRate uint32 + MaxTxRate uint32 +} + +func (msg *VfRate) Len() int { + return SizeofVfRate +} + +func DeserializeVfRate(b []byte) *VfRate { + return (*VfRate)(unsafe.Pointer(&b[0:SizeofVfRate][0])) +} + +func (msg *VfRate) Serialize() []byte { + return (*(*[SizeofVfRate]byte)(unsafe.Pointer(msg)))[:] +} + +// struct ifla_vf_spoofchk { +// __u32 vf; +// __u32 setting; +// }; + +type VfSpoofchk struct { + Vf uint32 + Setting uint32 +} + +func (msg *VfSpoofchk) Len() int { + return SizeofVfSpoofchk +} + +func DeserializeVfSpoofchk(b []byte) *VfSpoofchk { + return (*VfSpoofchk)(unsafe.Pointer(&b[0:SizeofVfSpoofchk][0])) +} + +func (msg *VfSpoofchk) Serialize() []byte { + return (*(*[SizeofVfSpoofchk]byte)(unsafe.Pointer(msg)))[:] +} + +// struct ifla_vf_link_state { +// __u32 vf; +// __u32 link_state; +// }; + +type VfLinkState struct { + Vf uint32 + LinkState uint32 +} + +func (msg *VfLinkState) Len() int { + return SizeofVfLinkState +} + +func DeserializeVfLinkState(b []byte) *VfLinkState { + return (*VfLinkState)(unsafe.Pointer(&b[0:SizeofVfLinkState][0])) +} + +func (msg *VfLinkState) Serialize() []byte { + return (*(*[SizeofVfLinkState]byte)(unsafe.Pointer(msg)))[:] +} + +// struct ifla_vf_rss_query_en { +// __u32 vf; +// __u32 setting; +// }; + +type VfRssQueryEn struct { + Vf uint32 + Setting uint32 +} + +func (msg *VfRssQueryEn) Len() int { + return SizeofVfRssQueryEn +} + +func DeserializeVfRssQueryEn(b []byte) *VfRssQueryEn { + return (*VfRssQueryEn)(unsafe.Pointer(&b[0:SizeofVfRssQueryEn][0])) +} + +func (msg *VfRssQueryEn) Serialize() []byte { + return (*(*[SizeofVfRssQueryEn]byte)(unsafe.Pointer(msg)))[:] +} + +// struct ifla_vf_trust { +// __u32 vf; +// __u32 setting; +// }; + +type VfTrust struct { + Vf uint32 + Setting uint32 +} + +func (msg *VfTrust) Len() int { + return SizeofVfTrust +} + +func DeserializeVfTrust(b []byte) *VfTrust { + return (*VfTrust)(unsafe.Pointer(&b[0:SizeofVfTrust][0])) +} + +func (msg *VfTrust) Serialize() []byte { + return (*(*[SizeofVfTrust]byte)(unsafe.Pointer(msg)))[:] +} + +// struct ifla_vf_guid { +// __u32 vf; +// __u32 rsvd; +// __u64 guid; +// }; + +type VfGUID struct { + Vf uint32 + Rsvd uint32 + GUID uint64 +} + +func (msg *VfGUID) Len() int { + return SizeofVfGUID +} + +func DeserializeVfGUID(b []byte) *VfGUID { + return (*VfGUID)(unsafe.Pointer(&b[0:SizeofVfGUID][0])) +} + +func (msg *VfGUID) Serialize() []byte { + return (*(*[SizeofVfGUID]byte)(unsafe.Pointer(msg)))[:] +} + +const ( + XDP_FLAGS_UPDATE_IF_NOEXIST = 1 << iota + XDP_FLAGS_SKB_MODE + XDP_FLAGS_DRV_MODE + XDP_FLAGS_MASK = XDP_FLAGS_UPDATE_IF_NOEXIST | XDP_FLAGS_SKB_MODE | XDP_FLAGS_DRV_MODE +) + +const ( + IFLA_XDP_UNSPEC = iota + IFLA_XDP_FD /* fd of xdp program to attach, or -1 to remove */ + IFLA_XDP_ATTACHED /* read-only bool indicating if prog is attached */ + IFLA_XDP_FLAGS /* xdp prog related flags */ + IFLA_XDP_PROG_ID /* xdp prog id */ + IFLA_XDP_MAX = IFLA_XDP_PROG_ID +) + +// XDP program attach mode (used as dump value for IFLA_XDP_ATTACHED) +const ( + XDP_ATTACHED_NONE = iota + XDP_ATTACHED_DRV + XDP_ATTACHED_SKB + XDP_ATTACHED_HW +) + +const ( + IFLA_IPTUN_UNSPEC = iota + IFLA_IPTUN_LINK + IFLA_IPTUN_LOCAL + IFLA_IPTUN_REMOTE + IFLA_IPTUN_TTL + IFLA_IPTUN_TOS + IFLA_IPTUN_ENCAP_LIMIT + IFLA_IPTUN_FLOWINFO + IFLA_IPTUN_FLAGS + IFLA_IPTUN_PROTO + IFLA_IPTUN_PMTUDISC + IFLA_IPTUN_6RD_PREFIX + IFLA_IPTUN_6RD_RELAY_PREFIX + IFLA_IPTUN_6RD_PREFIXLEN + IFLA_IPTUN_6RD_RELAY_PREFIXLEN + IFLA_IPTUN_ENCAP_TYPE + IFLA_IPTUN_ENCAP_FLAGS + IFLA_IPTUN_ENCAP_SPORT + IFLA_IPTUN_ENCAP_DPORT + IFLA_IPTUN_COLLECT_METADATA + IFLA_IPTUN_MAX = IFLA_IPTUN_COLLECT_METADATA +) + +const ( + IFLA_VTI_UNSPEC = iota + IFLA_VTI_LINK + IFLA_VTI_IKEY + IFLA_VTI_OKEY + IFLA_VTI_LOCAL + IFLA_VTI_REMOTE + IFLA_VTI_MAX = IFLA_VTI_REMOTE +) + +const ( + IFLA_VRF_UNSPEC = iota + IFLA_VRF_TABLE +) + +const ( + IFLA_BR_UNSPEC = iota + IFLA_BR_FORWARD_DELAY + IFLA_BR_HELLO_TIME + IFLA_BR_MAX_AGE + IFLA_BR_AGEING_TIME + IFLA_BR_STP_STATE + IFLA_BR_PRIORITY + IFLA_BR_VLAN_FILTERING + IFLA_BR_VLAN_PROTOCOL + IFLA_BR_GROUP_FWD_MASK + IFLA_BR_ROOT_ID + IFLA_BR_BRIDGE_ID + IFLA_BR_ROOT_PORT + IFLA_BR_ROOT_PATH_COST + IFLA_BR_TOPOLOGY_CHANGE + IFLA_BR_TOPOLOGY_CHANGE_DETECTED + IFLA_BR_HELLO_TIMER + IFLA_BR_TCN_TIMER + IFLA_BR_TOPOLOGY_CHANGE_TIMER + IFLA_BR_GC_TIMER + IFLA_BR_GROUP_ADDR + IFLA_BR_FDB_FLUSH + IFLA_BR_MCAST_ROUTER + IFLA_BR_MCAST_SNOOPING + IFLA_BR_MCAST_QUERY_USE_IFADDR + IFLA_BR_MCAST_QUERIER + IFLA_BR_MCAST_HASH_ELASTICITY + IFLA_BR_MCAST_HASH_MAX + IFLA_BR_MCAST_LAST_MEMBER_CNT + IFLA_BR_MCAST_STARTUP_QUERY_CNT + IFLA_BR_MCAST_LAST_MEMBER_INTVL + IFLA_BR_MCAST_MEMBERSHIP_INTVL + IFLA_BR_MCAST_QUERIER_INTVL + IFLA_BR_MCAST_QUERY_INTVL + IFLA_BR_MCAST_QUERY_RESPONSE_INTVL + IFLA_BR_MCAST_STARTUP_QUERY_INTVL + IFLA_BR_NF_CALL_IPTABLES + IFLA_BR_NF_CALL_IP6TABLES + IFLA_BR_NF_CALL_ARPTABLES + IFLA_BR_VLAN_DEFAULT_PVID + IFLA_BR_PAD + IFLA_BR_VLAN_STATS_ENABLED + IFLA_BR_MCAST_STATS_ENABLED + IFLA_BR_MCAST_IGMP_VERSION + IFLA_BR_MCAST_MLD_VERSION + IFLA_BR_MAX = IFLA_BR_MCAST_MLD_VERSION +) + +const ( + IFLA_GTP_UNSPEC = iota + IFLA_GTP_FD0 + IFLA_GTP_FD1 + IFLA_GTP_PDP_HASHSIZE + IFLA_GTP_ROLE +) + +const ( + GTP_ROLE_GGSN = iota + GTP_ROLE_SGSN +) + +const ( + IFLA_XFRM_UNSPEC = iota + IFLA_XFRM_LINK + IFLA_XFRM_IF_ID + + IFLA_XFRM_MAX = iota - 1 +) + +const ( + IFLA_TUN_UNSPEC = iota + IFLA_TUN_OWNER + IFLA_TUN_GROUP + IFLA_TUN_TYPE + IFLA_TUN_PI + IFLA_TUN_VNET_HDR + IFLA_TUN_PERSIST + IFLA_TUN_MULTI_QUEUE + IFLA_TUN_NUM_QUEUES + IFLA_TUN_NUM_DISABLED_QUEUES + IFLA_TUN_MAX = IFLA_TUN_NUM_DISABLED_QUEUES +) + +const ( + IFLA_IPOIB_UNSPEC = iota + IFLA_IPOIB_PKEY + IFLA_IPOIB_MODE + IFLA_IPOIB_UMCAST + IFLA_IPOIB_MAX = IFLA_IPOIB_UMCAST +) + +const ( + IFLA_CAN_UNSPEC = iota + IFLA_CAN_BITTIMING + IFLA_CAN_BITTIMING_CONST + IFLA_CAN_CLOCK + IFLA_CAN_STATE + IFLA_CAN_CTRLMODE + IFLA_CAN_RESTART_MS + IFLA_CAN_RESTART + IFLA_CAN_BERR_COUNTER + IFLA_CAN_DATA_BITTIMING + IFLA_CAN_DATA_BITTIMING_CONST + IFLA_CAN_TERMINATION + IFLA_CAN_TERMINATION_CONST + IFLA_CAN_BITRATE_CONST + IFLA_CAN_DATA_BITRATE_CONST + IFLA_CAN_BITRATE_MAX + IFLA_CAN_MAX = IFLA_CAN_BITRATE_MAX +) diff --git a/vendor/github.com/vishvananda/netlink/nl/mpls_linux.go b/vendor/github.com/vishvananda/netlink/nl/mpls_linux.go new file mode 100644 index 000000000..3915b7eec --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/mpls_linux.go @@ -0,0 +1,36 @@ +package nl + +import "encoding/binary" + +const ( + MPLS_LS_LABEL_SHIFT = 12 + MPLS_LS_S_SHIFT = 8 +) + +func EncodeMPLSStack(labels ...int) []byte { + b := make([]byte, 4*len(labels)) + for idx, label := range labels { + l := label << MPLS_LS_LABEL_SHIFT + if idx == len(labels)-1 { + l |= 1 << MPLS_LS_S_SHIFT + } + binary.BigEndian.PutUint32(b[idx*4:], uint32(l)) + } + return b +} + +func DecodeMPLSStack(buf []byte) []int { + if len(buf)%4 != 0 { + return nil + } + stack := make([]int, 0, len(buf)/4) + for len(buf) > 0 { + l := binary.BigEndian.Uint32(buf[:4]) + buf = buf[4:] + stack = append(stack, int(l)>>MPLS_LS_LABEL_SHIFT) + if (l>>MPLS_LS_S_SHIFT)&1 > 0 { + break + } + } + return stack +} diff --git a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go new file mode 100644 index 000000000..dcd4b9469 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go @@ -0,0 +1,791 @@ +// Package nl has low level primitives for making Netlink calls. +package nl + +import ( + "bytes" + "encoding/binary" + "fmt" + "net" + "runtime" + "sync" + "sync/atomic" + "syscall" + "unsafe" + + "github.com/vishvananda/netns" + "golang.org/x/sys/unix" +) + +const ( + // Family type definitions + FAMILY_ALL = unix.AF_UNSPEC + FAMILY_V4 = unix.AF_INET + FAMILY_V6 = unix.AF_INET6 + FAMILY_MPLS = unix.AF_MPLS + // Arbitrary set value (greater than default 4k) to allow receiving + // from kernel more verbose messages e.g. for statistics, + // tc rules or filters, or other more memory requiring data. + RECEIVE_BUFFER_SIZE = 65536 + // Kernel netlink pid + PidKernel uint32 = 0 +) + +// SupportedNlFamilies contains the list of netlink families this netlink package supports +var SupportedNlFamilies = []int{unix.NETLINK_ROUTE, unix.NETLINK_XFRM, unix.NETLINK_NETFILTER} + +var nextSeqNr uint32 + +// Default netlink socket timeout, 60s +var SocketTimeoutTv = unix.Timeval{Sec: 60, Usec: 0} + +// GetIPFamily returns the family type of a net.IP. +func GetIPFamily(ip net.IP) int { + if len(ip) <= net.IPv4len { + return FAMILY_V4 + } + if ip.To4() != nil { + return FAMILY_V4 + } + return FAMILY_V6 +} + +var nativeEndian binary.ByteOrder + +// NativeEndian gets native endianness for the system +func NativeEndian() binary.ByteOrder { + if nativeEndian == nil { + var x uint32 = 0x01020304 + if *(*byte)(unsafe.Pointer(&x)) == 0x01 { + nativeEndian = binary.BigEndian + } else { + nativeEndian = binary.LittleEndian + } + } + return nativeEndian +} + +// Byte swap a 16 bit value if we aren't big endian +func Swap16(i uint16) uint16 { + if NativeEndian() == binary.BigEndian { + return i + } + return (i&0xff00)>>8 | (i&0xff)<<8 +} + +// Byte swap a 32 bit value if aren't big endian +func Swap32(i uint32) uint32 { + if NativeEndian() == binary.BigEndian { + return i + } + return (i&0xff000000)>>24 | (i&0xff0000)>>8 | (i&0xff00)<<8 | (i&0xff)<<24 +} + +type NetlinkRequestData interface { + Len() int + Serialize() []byte +} + +// IfInfomsg is related to links, but it is used for list requests as well +type IfInfomsg struct { + unix.IfInfomsg +} + +// Create an IfInfomsg with family specified +func NewIfInfomsg(family int) *IfInfomsg { + return &IfInfomsg{ + IfInfomsg: unix.IfInfomsg{ + Family: uint8(family), + }, + } +} + +func DeserializeIfInfomsg(b []byte) *IfInfomsg { + return (*IfInfomsg)(unsafe.Pointer(&b[0:unix.SizeofIfInfomsg][0])) +} + +func (msg *IfInfomsg) Serialize() []byte { + return (*(*[unix.SizeofIfInfomsg]byte)(unsafe.Pointer(msg)))[:] +} + +func (msg *IfInfomsg) Len() int { + return unix.SizeofIfInfomsg +} + +func (msg *IfInfomsg) EncapType() string { + switch msg.Type { + case 0: + return "generic" + case unix.ARPHRD_ETHER: + return "ether" + case unix.ARPHRD_EETHER: + return "eether" + case unix.ARPHRD_AX25: + return "ax25" + case unix.ARPHRD_PRONET: + return "pronet" + case unix.ARPHRD_CHAOS: + return "chaos" + case unix.ARPHRD_IEEE802: + return "ieee802" + case unix.ARPHRD_ARCNET: + return "arcnet" + case unix.ARPHRD_APPLETLK: + return "atalk" + case unix.ARPHRD_DLCI: + return "dlci" + case unix.ARPHRD_ATM: + return "atm" + case unix.ARPHRD_METRICOM: + return "metricom" + case unix.ARPHRD_IEEE1394: + return "ieee1394" + case unix.ARPHRD_INFINIBAND: + return "infiniband" + case unix.ARPHRD_SLIP: + return "slip" + case unix.ARPHRD_CSLIP: + return "cslip" + case unix.ARPHRD_SLIP6: + return "slip6" + case unix.ARPHRD_CSLIP6: + return "cslip6" + case unix.ARPHRD_RSRVD: + return "rsrvd" + case unix.ARPHRD_ADAPT: + return "adapt" + case unix.ARPHRD_ROSE: + return "rose" + case unix.ARPHRD_X25: + return "x25" + case unix.ARPHRD_HWX25: + return "hwx25" + case unix.ARPHRD_PPP: + return "ppp" + case unix.ARPHRD_HDLC: + return "hdlc" + case unix.ARPHRD_LAPB: + return "lapb" + case unix.ARPHRD_DDCMP: + return "ddcmp" + case unix.ARPHRD_RAWHDLC: + return "rawhdlc" + case unix.ARPHRD_TUNNEL: + return "ipip" + case unix.ARPHRD_TUNNEL6: + return "tunnel6" + case unix.ARPHRD_FRAD: + return "frad" + case unix.ARPHRD_SKIP: + return "skip" + case unix.ARPHRD_LOOPBACK: + return "loopback" + case unix.ARPHRD_LOCALTLK: + return "ltalk" + case unix.ARPHRD_FDDI: + return "fddi" + case unix.ARPHRD_BIF: + return "bif" + case unix.ARPHRD_SIT: + return "sit" + case unix.ARPHRD_IPDDP: + return "ip/ddp" + case unix.ARPHRD_IPGRE: + return "gre" + case unix.ARPHRD_PIMREG: + return "pimreg" + case unix.ARPHRD_HIPPI: + return "hippi" + case unix.ARPHRD_ASH: + return "ash" + case unix.ARPHRD_ECONET: + return "econet" + case unix.ARPHRD_IRDA: + return "irda" + case unix.ARPHRD_FCPP: + return "fcpp" + case unix.ARPHRD_FCAL: + return "fcal" + case unix.ARPHRD_FCPL: + return "fcpl" + case unix.ARPHRD_FCFABRIC: + return "fcfb0" + case unix.ARPHRD_FCFABRIC + 1: + return "fcfb1" + case unix.ARPHRD_FCFABRIC + 2: + return "fcfb2" + case unix.ARPHRD_FCFABRIC + 3: + return "fcfb3" + case unix.ARPHRD_FCFABRIC + 4: + return "fcfb4" + case unix.ARPHRD_FCFABRIC + 5: + return "fcfb5" + case unix.ARPHRD_FCFABRIC + 6: + return "fcfb6" + case unix.ARPHRD_FCFABRIC + 7: + return "fcfb7" + case unix.ARPHRD_FCFABRIC + 8: + return "fcfb8" + case unix.ARPHRD_FCFABRIC + 9: + return "fcfb9" + case unix.ARPHRD_FCFABRIC + 10: + return "fcfb10" + case unix.ARPHRD_FCFABRIC + 11: + return "fcfb11" + case unix.ARPHRD_FCFABRIC + 12: + return "fcfb12" + case unix.ARPHRD_IEEE802_TR: + return "tr" + case unix.ARPHRD_IEEE80211: + return "ieee802.11" + case unix.ARPHRD_IEEE80211_PRISM: + return "ieee802.11/prism" + case unix.ARPHRD_IEEE80211_RADIOTAP: + return "ieee802.11/radiotap" + case unix.ARPHRD_IEEE802154: + return "ieee802.15.4" + + case 65534: + return "none" + case 65535: + return "void" + } + return fmt.Sprintf("unknown%d", msg.Type) +} + +func rtaAlignOf(attrlen int) int { + return (attrlen + unix.RTA_ALIGNTO - 1) & ^(unix.RTA_ALIGNTO - 1) +} + +func NewIfInfomsgChild(parent *RtAttr, family int) *IfInfomsg { + msg := NewIfInfomsg(family) + parent.children = append(parent.children, msg) + return msg +} + +type Uint32Attribute struct { + Type uint16 + Value uint32 +} + +func (a *Uint32Attribute) Serialize() []byte { + native := NativeEndian() + buf := make([]byte, rtaAlignOf(8)) + native.PutUint16(buf[0:2], 8) + native.PutUint16(buf[2:4], a.Type) + + if a.Type&NLA_F_NET_BYTEORDER != 0 { + binary.BigEndian.PutUint32(buf[4:], a.Value) + } else { + native.PutUint32(buf[4:], a.Value) + } + return buf +} + +func (a *Uint32Attribute) Len() int { + return 8 +} + +// Extend RtAttr to handle data and children +type RtAttr struct { + unix.RtAttr + Data []byte + children []NetlinkRequestData +} + +// Create a new Extended RtAttr object +func NewRtAttr(attrType int, data []byte) *RtAttr { + return &RtAttr{ + RtAttr: unix.RtAttr{ + Type: uint16(attrType), + }, + children: []NetlinkRequestData{}, + Data: data, + } +} + +// NewRtAttrChild adds an RtAttr as a child to the parent and returns the new attribute +// +// Deprecated: Use AddRtAttr() on the parent object +func NewRtAttrChild(parent *RtAttr, attrType int, data []byte) *RtAttr { + return parent.AddRtAttr(attrType, data) +} + +// AddRtAttr adds an RtAttr as a child and returns the new attribute +func (a *RtAttr) AddRtAttr(attrType int, data []byte) *RtAttr { + attr := NewRtAttr(attrType, data) + a.children = append(a.children, attr) + return attr +} + +// AddChild adds an existing NetlinkRequestData as a child. +func (a *RtAttr) AddChild(attr NetlinkRequestData) { + a.children = append(a.children, attr) +} + +func (a *RtAttr) Len() int { + if len(a.children) == 0 { + return (unix.SizeofRtAttr + len(a.Data)) + } + + l := 0 + for _, child := range a.children { + l += rtaAlignOf(child.Len()) + } + l += unix.SizeofRtAttr + return rtaAlignOf(l + len(a.Data)) +} + +// Serialize the RtAttr into a byte array +// This can't just unsafe.cast because it must iterate through children. +func (a *RtAttr) Serialize() []byte { + native := NativeEndian() + + length := a.Len() + buf := make([]byte, rtaAlignOf(length)) + + next := 4 + if a.Data != nil { + copy(buf[next:], a.Data) + next += rtaAlignOf(len(a.Data)) + } + if len(a.children) > 0 { + for _, child := range a.children { + childBuf := child.Serialize() + copy(buf[next:], childBuf) + next += rtaAlignOf(len(childBuf)) + } + } + + if l := uint16(length); l != 0 { + native.PutUint16(buf[0:2], l) + } + native.PutUint16(buf[2:4], a.Type) + return buf +} + +type NetlinkRequest struct { + unix.NlMsghdr + Data []NetlinkRequestData + RawData []byte + Sockets map[int]*SocketHandle +} + +// Serialize the Netlink Request into a byte array +func (req *NetlinkRequest) Serialize() []byte { + length := unix.SizeofNlMsghdr + dataBytes := make([][]byte, len(req.Data)) + for i, data := range req.Data { + dataBytes[i] = data.Serialize() + length = length + len(dataBytes[i]) + } + length += len(req.RawData) + + req.Len = uint32(length) + b := make([]byte, length) + hdr := (*(*[unix.SizeofNlMsghdr]byte)(unsafe.Pointer(req)))[:] + next := unix.SizeofNlMsghdr + copy(b[0:next], hdr) + for _, data := range dataBytes { + for _, dataByte := range data { + b[next] = dataByte + next = next + 1 + } + } + // Add the raw data if any + if len(req.RawData) > 0 { + copy(b[next:length], req.RawData) + } + return b +} + +func (req *NetlinkRequest) AddData(data NetlinkRequestData) { + req.Data = append(req.Data, data) +} + +// AddRawData adds raw bytes to the end of the NetlinkRequest object during serialization +func (req *NetlinkRequest) AddRawData(data []byte) { + req.RawData = append(req.RawData, data...) +} + +// Execute the request against a the given sockType. +// Returns a list of netlink messages in serialized format, optionally filtered +// by resType. +func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, error) { + var ( + s *NetlinkSocket + err error + ) + + if req.Sockets != nil { + if sh, ok := req.Sockets[sockType]; ok { + s = sh.Socket + req.Seq = atomic.AddUint32(&sh.Seq, 1) + } + } + sharedSocket := s != nil + + if s == nil { + s, err = getNetlinkSocket(sockType) + if err != nil { + return nil, err + } + + if err := s.SetSendTimeout(&SocketTimeoutTv); err != nil { + return nil, err + } + if err := s.SetReceiveTimeout(&SocketTimeoutTv); err != nil { + return nil, err + } + + defer s.Close() + } else { + s.Lock() + defer s.Unlock() + } + + if err := s.Send(req); err != nil { + return nil, err + } + + pid, err := s.GetPid() + if err != nil { + return nil, err + } + + var res [][]byte + +done: + for { + msgs, from, err := s.Receive() + if err != nil { + return nil, err + } + if from.Pid != PidKernel { + return nil, fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, PidKernel) + } + for _, m := range msgs { + if m.Header.Seq != req.Seq { + if sharedSocket { + continue + } + return nil, fmt.Errorf("Wrong Seq nr %d, expected %d", m.Header.Seq, req.Seq) + } + if m.Header.Pid != pid { + continue + } + if m.Header.Type == unix.NLMSG_DONE || m.Header.Type == unix.NLMSG_ERROR { + native := NativeEndian() + error := int32(native.Uint32(m.Data[0:4])) + if error == 0 { + break done + } + return nil, syscall.Errno(-error) + } + if resType != 0 && m.Header.Type != resType { + continue + } + res = append(res, m.Data) + if m.Header.Flags&unix.NLM_F_MULTI == 0 { + break done + } + } + } + return res, nil +} + +// Create a new netlink request from proto and flags +// Note the Len value will be inaccurate once data is added until +// the message is serialized +func NewNetlinkRequest(proto, flags int) *NetlinkRequest { + return &NetlinkRequest{ + NlMsghdr: unix.NlMsghdr{ + Len: uint32(unix.SizeofNlMsghdr), + Type: uint16(proto), + Flags: unix.NLM_F_REQUEST | uint16(flags), + Seq: atomic.AddUint32(&nextSeqNr, 1), + }, + } +} + +type NetlinkSocket struct { + fd int32 + lsa unix.SockaddrNetlink + sync.Mutex +} + +func getNetlinkSocket(protocol int) (*NetlinkSocket, error) { + fd, err := unix.Socket(unix.AF_NETLINK, unix.SOCK_RAW|unix.SOCK_CLOEXEC, protocol) + if err != nil { + return nil, err + } + s := &NetlinkSocket{ + fd: int32(fd), + } + s.lsa.Family = unix.AF_NETLINK + if err := unix.Bind(fd, &s.lsa); err != nil { + unix.Close(fd) + return nil, err + } + + return s, nil +} + +// GetNetlinkSocketAt opens a netlink socket in the network namespace newNs +// and positions the thread back into the network namespace specified by curNs, +// when done. If curNs is close, the function derives the current namespace and +// moves back into it when done. If newNs is close, the socket will be opened +// in the current network namespace. +func GetNetlinkSocketAt(newNs, curNs netns.NsHandle, protocol int) (*NetlinkSocket, error) { + c, err := executeInNetns(newNs, curNs) + if err != nil { + return nil, err + } + defer c() + return getNetlinkSocket(protocol) +} + +// executeInNetns sets execution of the code following this call to the +// network namespace newNs, then moves the thread back to curNs if open, +// otherwise to the current netns at the time the function was invoked +// In case of success, the caller is expected to execute the returned function +// at the end of the code that needs to be executed in the network namespace. +// Example: +// func jobAt(...) error { +// d, err := executeInNetns(...) +// if err != nil { return err} +// defer d() +// < code which needs to be executed in specific netns> +// } +// TODO: his function probably belongs to netns pkg. +func executeInNetns(newNs, curNs netns.NsHandle) (func(), error) { + var ( + err error + moveBack func(netns.NsHandle) error + closeNs func() error + unlockThd func() + ) + restore := func() { + // order matters + if moveBack != nil { + moveBack(curNs) + } + if closeNs != nil { + closeNs() + } + if unlockThd != nil { + unlockThd() + } + } + if newNs.IsOpen() { + runtime.LockOSThread() + unlockThd = runtime.UnlockOSThread + if !curNs.IsOpen() { + if curNs, err = netns.Get(); err != nil { + restore() + return nil, fmt.Errorf("could not get current namespace while creating netlink socket: %v", err) + } + closeNs = curNs.Close + } + if err := netns.Set(newNs); err != nil { + restore() + return nil, fmt.Errorf("failed to set into network namespace %d while creating netlink socket: %v", newNs, err) + } + moveBack = netns.Set + } + return restore, nil +} + +// Create a netlink socket with a given protocol (e.g. NETLINK_ROUTE) +// and subscribe it to multicast groups passed in variable argument list. +// Returns the netlink socket on which Receive() method can be called +// to retrieve the messages from the kernel. +func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) { + fd, err := unix.Socket(unix.AF_NETLINK, unix.SOCK_RAW, protocol) + if err != nil { + return nil, err + } + s := &NetlinkSocket{ + fd: int32(fd), + } + s.lsa.Family = unix.AF_NETLINK + + for _, g := range groups { + s.lsa.Groups |= (1 << (g - 1)) + } + + if err := unix.Bind(fd, &s.lsa); err != nil { + unix.Close(fd) + return nil, err + } + + return s, nil +} + +// SubscribeAt works like Subscribe plus let's the caller choose the network +// namespace in which the socket would be opened (newNs). Then control goes back +// to curNs if open, otherwise to the netns at the time this function was called. +func SubscribeAt(newNs, curNs netns.NsHandle, protocol int, groups ...uint) (*NetlinkSocket, error) { + c, err := executeInNetns(newNs, curNs) + if err != nil { + return nil, err + } + defer c() + return Subscribe(protocol, groups...) +} + +func (s *NetlinkSocket) Close() { + fd := int(atomic.SwapInt32(&s.fd, -1)) + unix.Close(fd) +} + +func (s *NetlinkSocket) GetFd() int { + return int(atomic.LoadInt32(&s.fd)) +} + +func (s *NetlinkSocket) Send(request *NetlinkRequest) error { + fd := int(atomic.LoadInt32(&s.fd)) + if fd < 0 { + return fmt.Errorf("Send called on a closed socket") + } + if err := unix.Sendto(fd, request.Serialize(), 0, &s.lsa); err != nil { + return err + } + return nil +} + +func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, *unix.SockaddrNetlink, error) { + fd := int(atomic.LoadInt32(&s.fd)) + if fd < 0 { + return nil, nil, fmt.Errorf("Receive called on a closed socket") + } + var fromAddr *unix.SockaddrNetlink + var rb [RECEIVE_BUFFER_SIZE]byte + nr, from, err := unix.Recvfrom(fd, rb[:], 0) + if err != nil { + return nil, nil, err + } + fromAddr, ok := from.(*unix.SockaddrNetlink) + if !ok { + return nil, nil, fmt.Errorf("Error converting to netlink sockaddr") + } + if nr < unix.NLMSG_HDRLEN { + return nil, nil, fmt.Errorf("Got short response from netlink") + } + rb2 := make([]byte, nr) + copy(rb2, rb[:nr]) + nl, err := syscall.ParseNetlinkMessage(rb2) + if err != nil { + return nil, nil, err + } + return nl, fromAddr, nil +} + +// SetSendTimeout allows to set a send timeout on the socket +func (s *NetlinkSocket) SetSendTimeout(timeout *unix.Timeval) error { + // Set a send timeout of SOCKET_SEND_TIMEOUT, this will allow the Send to periodically unblock and avoid that a routine + // remains stuck on a send on a closed fd + return unix.SetsockoptTimeval(int(s.fd), unix.SOL_SOCKET, unix.SO_SNDTIMEO, timeout) +} + +// SetReceiveTimeout allows to set a receive timeout on the socket +func (s *NetlinkSocket) SetReceiveTimeout(timeout *unix.Timeval) error { + // Set a read timeout of SOCKET_READ_TIMEOUT, this will allow the Read to periodically unblock and avoid that a routine + // remains stuck on a recvmsg on a closed fd + return unix.SetsockoptTimeval(int(s.fd), unix.SOL_SOCKET, unix.SO_RCVTIMEO, timeout) +} + +func (s *NetlinkSocket) GetPid() (uint32, error) { + fd := int(atomic.LoadInt32(&s.fd)) + lsa, err := unix.Getsockname(fd) + if err != nil { + return 0, err + } + switch v := lsa.(type) { + case *unix.SockaddrNetlink: + return v.Pid, nil + } + return 0, fmt.Errorf("Wrong socket type") +} + +func ZeroTerminated(s string) []byte { + bytes := make([]byte, len(s)+1) + for i := 0; i < len(s); i++ { + bytes[i] = s[i] + } + bytes[len(s)] = 0 + return bytes +} + +func NonZeroTerminated(s string) []byte { + bytes := make([]byte, len(s)) + for i := 0; i < len(s); i++ { + bytes[i] = s[i] + } + return bytes +} + +func BytesToString(b []byte) string { + n := bytes.Index(b, []byte{0}) + return string(b[:n]) +} + +func Uint8Attr(v uint8) []byte { + return []byte{byte(v)} +} + +func Uint16Attr(v uint16) []byte { + native := NativeEndian() + bytes := make([]byte, 2) + native.PutUint16(bytes, v) + return bytes +} + +func Uint32Attr(v uint32) []byte { + native := NativeEndian() + bytes := make([]byte, 4) + native.PutUint32(bytes, v) + return bytes +} + +func Uint64Attr(v uint64) []byte { + native := NativeEndian() + bytes := make([]byte, 8) + native.PutUint64(bytes, v) + return bytes +} + +func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) { + var attrs []syscall.NetlinkRouteAttr + for len(b) >= unix.SizeofRtAttr { + a, vbuf, alen, err := netlinkRouteAttrAndValue(b) + if err != nil { + return nil, err + } + ra := syscall.NetlinkRouteAttr{Attr: syscall.RtAttr(*a), Value: vbuf[:int(a.Len)-unix.SizeofRtAttr]} + attrs = append(attrs, ra) + b = b[alen:] + } + return attrs, nil +} + +func netlinkRouteAttrAndValue(b []byte) (*unix.RtAttr, []byte, int, error) { + a := (*unix.RtAttr)(unsafe.Pointer(&b[0])) + if int(a.Len) < unix.SizeofRtAttr || int(a.Len) > len(b) { + return nil, nil, 0, unix.EINVAL + } + return a, b[unix.SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil +} + +// SocketHandle contains the netlink socket and the associated +// sequence counter for a specific netlink family +type SocketHandle struct { + Seq uint32 + Socket *NetlinkSocket +} + +// Close closes the netlink socket +func (sh *SocketHandle) Close() { + if sh.Socket != nil { + sh.Socket.Close() + } +} diff --git a/vendor/github.com/vishvananda/netlink/nl/nl_unspecified.go b/vendor/github.com/vishvananda/netlink/nl/nl_unspecified.go new file mode 100644 index 000000000..dfc0be660 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/nl_unspecified.go @@ -0,0 +1,11 @@ +// +build !linux + +package nl + +import "encoding/binary" + +var SupportedNlFamilies = []int{} + +func NativeEndian() binary.ByteOrder { + return nil +} diff --git a/vendor/github.com/vishvananda/netlink/nl/parse_attr_linux.go b/vendor/github.com/vishvananda/netlink/nl/parse_attr_linux.go new file mode 100644 index 000000000..7f49125cf --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/parse_attr_linux.go @@ -0,0 +1,79 @@ +package nl + +import ( + "encoding/binary" + "fmt" + "log" +) + +type Attribute struct { + Type uint16 + Value []byte +} + +func ParseAttributes(data []byte) <-chan Attribute { + native := NativeEndian() + result := make(chan Attribute) + + go func() { + i := 0 + for i+4 < len(data) { + length := int(native.Uint16(data[i : i+2])) + attrType := native.Uint16(data[i+2 : i+4]) + + if length < 4 { + log.Printf("attribute 0x%02x has invalid length of %d bytes", attrType, length) + break + } + + if len(data) < i+length { + log.Printf("attribute 0x%02x of length %d is truncated, only %d bytes remaining", attrType, length, len(data)-i) + break + } + + result <- Attribute{ + Type: attrType, + Value: data[i+4 : i+length], + } + i += rtaAlignOf(length) + } + close(result) + }() + + return result +} + +func PrintAttributes(data []byte) { + printAttributes(data, 0) +} + +func printAttributes(data []byte, level int) { + for attr := range ParseAttributes(data) { + for i := 0; i < level; i++ { + print("> ") + } + nested := attr.Type&NLA_F_NESTED != 0 + fmt.Printf("type=%d nested=%v len=%v %v\n", attr.Type&NLA_TYPE_MASK, nested, len(attr.Value), attr.Value) + if nested { + printAttributes(attr.Value, level+1) + } + } +} + +// Uint32 returns the uint32 value respecting the NET_BYTEORDER flag +func (attr *Attribute) Uint32() uint32 { + if attr.Type&NLA_F_NET_BYTEORDER != 0 { + return binary.BigEndian.Uint32(attr.Value) + } else { + return NativeEndian().Uint32(attr.Value) + } +} + +// Uint64 returns the uint64 value respecting the NET_BYTEORDER flag +func (attr *Attribute) Uint64() uint64 { + if attr.Type&NLA_F_NET_BYTEORDER != 0 { + return binary.BigEndian.Uint64(attr.Value) + } else { + return NativeEndian().Uint64(attr.Value) + } +} diff --git a/vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go b/vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go new file mode 100644 index 000000000..1224b747d --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go @@ -0,0 +1,35 @@ +package nl + +const ( + RDMA_NL_GET_CLIENT_SHIFT = 10 +) + +const ( + RDMA_NL_NLDEV = 5 +) + +const ( + RDMA_NLDEV_CMD_GET = 1 + RDMA_NLDEV_CMD_SET = 2 + RDMA_NLDEV_CMD_SYS_GET = 6 + RDMA_NLDEV_CMD_SYS_SET = 7 +) + +const ( + RDMA_NLDEV_ATTR_DEV_INDEX = 1 + RDMA_NLDEV_ATTR_DEV_NAME = 2 + RDMA_NLDEV_ATTR_PORT_INDEX = 3 + RDMA_NLDEV_ATTR_CAP_FLAGS = 4 + RDMA_NLDEV_ATTR_FW_VERSION = 5 + RDMA_NLDEV_ATTR_NODE_GUID = 6 + RDMA_NLDEV_ATTR_SYS_IMAGE_GUID = 7 + RDMA_NLDEV_ATTR_SUBNET_PREFIX = 8 + RDMA_NLDEV_ATTR_LID = 9 + RDMA_NLDEV_ATTR_SM_LID = 10 + RDMA_NLDEV_ATTR_LMC = 11 + RDMA_NLDEV_ATTR_PORT_STATE = 12 + RDMA_NLDEV_ATTR_PORT_PHYS_STATE = 13 + RDMA_NLDEV_ATTR_DEV_NODE_TYPE = 14 + RDMA_NLDEV_SYS_ATTR_NETNS_MODE = 66 + RDMA_NLDEV_NET_NS_FD = 68 +) diff --git a/vendor/github.com/vishvananda/netlink/nl/route_linux.go b/vendor/github.com/vishvananda/netlink/nl/route_linux.go new file mode 100644 index 000000000..03c1900ff --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/route_linux.go @@ -0,0 +1,107 @@ +package nl + +import ( + "unsafe" + + "golang.org/x/sys/unix" +) + +type RtMsg struct { + unix.RtMsg +} + +func NewRtMsg() *RtMsg { + return &RtMsg{ + RtMsg: unix.RtMsg{ + Table: unix.RT_TABLE_MAIN, + Scope: unix.RT_SCOPE_UNIVERSE, + Protocol: unix.RTPROT_BOOT, + Type: unix.RTN_UNICAST, + }, + } +} + +func NewRtDelMsg() *RtMsg { + return &RtMsg{ + RtMsg: unix.RtMsg{ + Table: unix.RT_TABLE_MAIN, + Scope: unix.RT_SCOPE_NOWHERE, + }, + } +} + +func (msg *RtMsg) Len() int { + return unix.SizeofRtMsg +} + +func DeserializeRtMsg(b []byte) *RtMsg { + return (*RtMsg)(unsafe.Pointer(&b[0:unix.SizeofRtMsg][0])) +} + +func (msg *RtMsg) Serialize() []byte { + return (*(*[unix.SizeofRtMsg]byte)(unsafe.Pointer(msg)))[:] +} + +type RtNexthop struct { + unix.RtNexthop + Children []NetlinkRequestData +} + +func DeserializeRtNexthop(b []byte) *RtNexthop { + return (*RtNexthop)(unsafe.Pointer(&b[0:unix.SizeofRtNexthop][0])) +} + +func (msg *RtNexthop) Len() int { + if len(msg.Children) == 0 { + return unix.SizeofRtNexthop + } + + l := 0 + for _, child := range msg.Children { + l += rtaAlignOf(child.Len()) + } + l += unix.SizeofRtNexthop + return rtaAlignOf(l) +} + +func (msg *RtNexthop) Serialize() []byte { + length := msg.Len() + msg.RtNexthop.Len = uint16(length) + buf := make([]byte, length) + copy(buf, (*(*[unix.SizeofRtNexthop]byte)(unsafe.Pointer(msg)))[:]) + next := rtaAlignOf(unix.SizeofRtNexthop) + if len(msg.Children) > 0 { + for _, child := range msg.Children { + childBuf := child.Serialize() + copy(buf[next:], childBuf) + next += rtaAlignOf(len(childBuf)) + } + } + return buf +} + +type RtGenMsg struct { + unix.RtGenmsg +} + +func NewRtGenMsg() *RtGenMsg { + return &RtGenMsg{ + RtGenmsg: unix.RtGenmsg{ + Family: unix.AF_UNSPEC, + }, + } +} + +func (msg *RtGenMsg) Len() int { + return rtaAlignOf(unix.SizeofRtGenmsg) +} + +func DeserializeRtGenMsg(b []byte) *RtGenMsg { + return &RtGenMsg{RtGenmsg: unix.RtGenmsg{Family: b[0]}} +} + +func (msg *RtGenMsg) Serialize() []byte { + out := make([]byte, msg.Len()) + out[0] = msg.Family + return out +} diff --git a/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go b/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go new file mode 100644 index 000000000..5774cbb15 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go @@ -0,0 +1,154 @@ +package nl + +import ( + "errors" + "fmt" + "net" +) + +type IPv6SrHdr struct { + nextHdr uint8 + hdrLen uint8 + routingType uint8 + segmentsLeft uint8 + firstSegment uint8 + flags uint8 + reserved uint16 + + Segments []net.IP +} + +func (s1 *IPv6SrHdr) Equal(s2 IPv6SrHdr) bool { + if len(s1.Segments) != len(s2.Segments) { + return false + } + for i := range s1.Segments { + if s1.Segments[i].Equal(s2.Segments[i]) != true { + return false + } + } + return s1.nextHdr == s2.nextHdr && + s1.hdrLen == s2.hdrLen && + s1.routingType == s2.routingType && + s1.segmentsLeft == s2.segmentsLeft && + s1.firstSegment == s2.firstSegment && + s1.flags == s2.flags + // reserved doesn't need to be identical. +} + +// seg6 encap mode +const ( + SEG6_IPTUN_MODE_INLINE = iota + SEG6_IPTUN_MODE_ENCAP +) + +// number of nested RTATTR +// from include/uapi/linux/seg6_iptunnel.h +const ( + SEG6_IPTUNNEL_UNSPEC = iota + SEG6_IPTUNNEL_SRH + __SEG6_IPTUNNEL_MAX +) +const ( + SEG6_IPTUNNEL_MAX = __SEG6_IPTUNNEL_MAX - 1 +) + +func EncodeSEG6Encap(mode int, segments []net.IP) ([]byte, error) { + nsegs := len(segments) // nsegs: number of segments + if nsegs == 0 { + return nil, errors.New("EncodeSEG6Encap: No Segment in srh") + } + b := make([]byte, 12, 12+len(segments)*16) + native := NativeEndian() + native.PutUint32(b, uint32(mode)) + b[4] = 0 // srh.nextHdr (0 when calling netlink) + b[5] = uint8(16 * nsegs >> 3) // srh.hdrLen (in 8-octets unit) + b[6] = IPV6_SRCRT_TYPE_4 // srh.routingType (assigned by IANA) + b[7] = uint8(nsegs - 1) // srh.segmentsLeft + b[8] = uint8(nsegs - 1) // srh.firstSegment + b[9] = 0 // srh.flags (SR6_FLAG1_HMAC for srh_hmac) + // srh.reserved: Defined as "Tag" in draft-ietf-6man-segment-routing-header-07 + native.PutUint16(b[10:], 0) // srh.reserved + for _, netIP := range segments { + b = append(b, netIP...) // srh.Segments + } + return b, nil +} + +func DecodeSEG6Encap(buf []byte) (int, []net.IP, error) { + native := NativeEndian() + mode := int(native.Uint32(buf)) + srh := IPv6SrHdr{ + nextHdr: buf[4], + hdrLen: buf[5], + routingType: buf[6], + segmentsLeft: buf[7], + firstSegment: buf[8], + flags: buf[9], + reserved: native.Uint16(buf[10:12]), + } + buf = buf[12:] + if len(buf)%16 != 0 { + err := fmt.Errorf("DecodeSEG6Encap: error parsing Segment List (buf len: %d)\n", len(buf)) + return mode, nil, err + } + for len(buf) > 0 { + srh.Segments = append(srh.Segments, net.IP(buf[:16])) + buf = buf[16:] + } + return mode, srh.Segments, nil +} + +func DecodeSEG6Srh(buf []byte) ([]net.IP, error) { + native := NativeEndian() + srh := IPv6SrHdr{ + nextHdr: buf[0], + hdrLen: buf[1], + routingType: buf[2], + segmentsLeft: buf[3], + firstSegment: buf[4], + flags: buf[5], + reserved: native.Uint16(buf[6:8]), + } + buf = buf[8:] + if len(buf)%16 != 0 { + err := fmt.Errorf("DecodeSEG6Srh: error parsing Segment List (buf len: %d)", len(buf)) + return nil, err + } + for len(buf) > 0 { + srh.Segments = append(srh.Segments, net.IP(buf[:16])) + buf = buf[16:] + } + return srh.Segments, nil +} +func EncodeSEG6Srh(segments []net.IP) ([]byte, error) { + nsegs := len(segments) // nsegs: number of segments + if nsegs == 0 { + return nil, errors.New("EncodeSEG6Srh: No Segments") + } + b := make([]byte, 8, 8+len(segments)*16) + native := NativeEndian() + b[0] = 0 // srh.nextHdr (0 when calling netlink) + b[1] = uint8(16 * nsegs >> 3) // srh.hdrLen (in 8-octets unit) + b[2] = IPV6_SRCRT_TYPE_4 // srh.routingType (assigned by IANA) + b[3] = uint8(nsegs - 1) // srh.segmentsLeft + b[4] = uint8(nsegs - 1) // srh.firstSegment + b[5] = 0 // srh.flags (SR6_FLAG1_HMAC for srh_hmac) + // srh.reserved: Defined as "Tag" in draft-ietf-6man-segment-routing-header-07 + native.PutUint16(b[6:], 0) // srh.reserved + for _, netIP := range segments { + b = append(b, netIP...) // srh.Segments + } + return b, nil +} + +// Helper functions +func SEG6EncapModeString(mode int) string { + switch mode { + case SEG6_IPTUN_MODE_INLINE: + return "inline" + case SEG6_IPTUN_MODE_ENCAP: + return "encap" + } + return "unknown" +} diff --git a/vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go b/vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go new file mode 100644 index 000000000..150017726 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go @@ -0,0 +1,76 @@ +package nl + +import () + +// seg6local parameters +const ( + SEG6_LOCAL_UNSPEC = iota + SEG6_LOCAL_ACTION + SEG6_LOCAL_SRH + SEG6_LOCAL_TABLE + SEG6_LOCAL_NH4 + SEG6_LOCAL_NH6 + SEG6_LOCAL_IIF + SEG6_LOCAL_OIF + __SEG6_LOCAL_MAX +) +const ( + SEG6_LOCAL_MAX = __SEG6_LOCAL_MAX +) + +// seg6local actions +const ( + SEG6_LOCAL_ACTION_END = iota + 1 // 1 + SEG6_LOCAL_ACTION_END_X // 2 + SEG6_LOCAL_ACTION_END_T // 3 + SEG6_LOCAL_ACTION_END_DX2 // 4 + SEG6_LOCAL_ACTION_END_DX6 // 5 + SEG6_LOCAL_ACTION_END_DX4 // 6 + SEG6_LOCAL_ACTION_END_DT6 // 7 + SEG6_LOCAL_ACTION_END_DT4 // 8 + SEG6_LOCAL_ACTION_END_B6 // 9 + SEG6_LOCAL_ACTION_END_B6_ENCAPS // 10 + SEG6_LOCAL_ACTION_END_BM // 11 + SEG6_LOCAL_ACTION_END_S // 12 + SEG6_LOCAL_ACTION_END_AS // 13 + SEG6_LOCAL_ACTION_END_AM // 14 + __SEG6_LOCAL_ACTION_MAX +) +const ( + SEG6_LOCAL_ACTION_MAX = __SEG6_LOCAL_ACTION_MAX - 1 +) + +// Helper functions +func SEG6LocalActionString(action int) string { + switch action { + case SEG6_LOCAL_ACTION_END: + return "End" + case SEG6_LOCAL_ACTION_END_X: + return "End.X" + case SEG6_LOCAL_ACTION_END_T: + return "End.T" + case SEG6_LOCAL_ACTION_END_DX2: + return "End.DX2" + case SEG6_LOCAL_ACTION_END_DX6: + return "End.DX6" + case SEG6_LOCAL_ACTION_END_DX4: + return "End.DX4" + case SEG6_LOCAL_ACTION_END_DT6: + return "End.DT6" + case SEG6_LOCAL_ACTION_END_DT4: + return "End.DT4" + case SEG6_LOCAL_ACTION_END_B6: + return "End.B6" + case SEG6_LOCAL_ACTION_END_B6_ENCAPS: + return "End.B6.Encaps" + case SEG6_LOCAL_ACTION_END_BM: + return "End.BM" + case SEG6_LOCAL_ACTION_END_S: + return "End.S" + case SEG6_LOCAL_ACTION_END_AS: + return "End.AS" + case SEG6_LOCAL_ACTION_END_AM: + return "End.AM" + } + return "unknown" +} diff --git a/vendor/github.com/vishvananda/netlink/nl/syscall.go b/vendor/github.com/vishvananda/netlink/nl/syscall.go new file mode 100644 index 000000000..4a01e6e59 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/syscall.go @@ -0,0 +1,76 @@ +package nl + +// syscall package lack of rule atributes type. +// Thus there are defined below +const ( + FRA_UNSPEC = iota + FRA_DST /* destination address */ + FRA_SRC /* source address */ + FRA_IIFNAME /* interface name */ + FRA_GOTO /* target to jump to (FR_ACT_GOTO) */ + FRA_UNUSED2 + FRA_PRIORITY /* priority/preference */ + FRA_UNUSED3 + FRA_UNUSED4 + FRA_UNUSED5 + FRA_FWMARK /* mark */ + FRA_FLOW /* flow/class id */ + FRA_TUN_ID + FRA_SUPPRESS_IFGROUP + FRA_SUPPRESS_PREFIXLEN + FRA_TABLE /* Extended table id */ + FRA_FWMASK /* mask for netfilter mark */ + FRA_OIFNAME + FRA_PAD + FRA_L3MDEV /* iif or oif is l3mdev goto its table */ + FRA_UID_RANGE /* UID range */ + FRA_PROTOCOL /* Originator of the rule */ + FRA_IP_PROTO /* ip proto */ + FRA_SPORT_RANGE /* sport */ + FRA_DPORT_RANGE /* dport */ +) + +// ip rule netlink request types +const ( + FR_ACT_UNSPEC = iota + FR_ACT_TO_TBL /* Pass to fixed table */ + FR_ACT_GOTO /* Jump to another rule */ + FR_ACT_NOP /* No operation */ + FR_ACT_RES3 + FR_ACT_RES4 + FR_ACT_BLACKHOLE /* Drop without notification */ + FR_ACT_UNREACHABLE /* Drop with ENETUNREACH */ + FR_ACT_PROHIBIT /* Drop with EACCES */ +) + +// socket diags related +const ( + SOCK_DIAG_BY_FAMILY = 20 /* linux.sock_diag.h */ + TCPDIAG_NOCOOKIE = 0xFFFFFFFF /* TCPDIAG_NOCOOKIE in net/ipv4/tcp_diag.h*/ +) + +// RTA_ENCAP subtype +const ( + MPLS_IPTUNNEL_UNSPEC = iota + MPLS_IPTUNNEL_DST +) + +// light weight tunnel encap types +const ( + LWTUNNEL_ENCAP_NONE = iota + LWTUNNEL_ENCAP_MPLS + LWTUNNEL_ENCAP_IP + LWTUNNEL_ENCAP_ILA + LWTUNNEL_ENCAP_IP6 + LWTUNNEL_ENCAP_SEG6 + LWTUNNEL_ENCAP_BPF + LWTUNNEL_ENCAP_SEG6_LOCAL +) + +// routing header types +const ( + IPV6_SRCRT_STRICT = 0x01 // Deprecated; will be removed + IPV6_SRCRT_TYPE_0 = 0 // Deprecated; will be removed + IPV6_SRCRT_TYPE_2 = 2 // IPv6 type 2 Routing Header + IPV6_SRCRT_TYPE_4 = 4 // Segment Routing with IPv6 +) diff --git a/vendor/github.com/vishvananda/netlink/nl/tc_linux.go b/vendor/github.com/vishvananda/netlink/nl/tc_linux.go new file mode 100644 index 000000000..c24d53eb7 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/tc_linux.go @@ -0,0 +1,983 @@ +package nl + +import ( + "encoding/binary" + "unsafe" +) + +// LinkLayer +const ( + LINKLAYER_UNSPEC = iota + LINKLAYER_ETHERNET + LINKLAYER_ATM +) + +// ATM +const ( + ATM_CELL_PAYLOAD = 48 + ATM_CELL_SIZE = 53 +) + +const TC_LINKLAYER_MASK = 0x0F + +// Police +const ( + TCA_POLICE_UNSPEC = iota + TCA_POLICE_TBF + TCA_POLICE_RATE + TCA_POLICE_PEAKRATE + TCA_POLICE_AVRATE + TCA_POLICE_RESULT + TCA_POLICE_MAX = TCA_POLICE_RESULT +) + +// Message types +const ( + TCA_UNSPEC = iota + TCA_KIND + TCA_OPTIONS + TCA_STATS + TCA_XSTATS + TCA_RATE + TCA_FCNT + TCA_STATS2 + TCA_STAB + TCA_MAX = TCA_STAB +) + +const ( + TCA_ACT_TAB = 1 + TCAA_MAX = 1 +) + +const ( + TCA_ACT_UNSPEC = iota + TCA_ACT_KIND + TCA_ACT_OPTIONS + TCA_ACT_INDEX + TCA_ACT_STATS + TCA_ACT_MAX +) + +const ( + TCA_PRIO_UNSPEC = iota + TCA_PRIO_MQ + TCA_PRIO_MAX = TCA_PRIO_MQ +) + +const ( + TCA_STATS_UNSPEC = iota + TCA_STATS_BASIC + TCA_STATS_RATE_EST + TCA_STATS_QUEUE + TCA_STATS_APP + TCA_STATS_MAX = TCA_STATS_APP +) + +const ( + SizeofTcMsg = 0x14 + SizeofTcActionMsg = 0x04 + SizeofTcPrioMap = 0x14 + SizeofTcRateSpec = 0x0c + SizeofTcNetemQopt = 0x18 + SizeofTcNetemCorr = 0x0c + SizeofTcNetemReorder = 0x08 + SizeofTcNetemCorrupt = 0x08 + SizeofTcTbfQopt = 2*SizeofTcRateSpec + 0x0c + SizeofTcHtbCopt = 2*SizeofTcRateSpec + 0x14 + SizeofTcHtbGlob = 0x14 + SizeofTcU32Key = 0x10 + SizeofTcU32Sel = 0x10 // without keys + SizeofTcGen = 0x14 + SizeofTcConnmark = SizeofTcGen + 0x04 + SizeofTcMirred = SizeofTcGen + 0x08 + SizeofTcTunnelKey = SizeofTcGen + 0x04 + SizeofTcSkbEdit = SizeofTcGen + SizeofTcPolice = 2*SizeofTcRateSpec + 0x20 + SizeofTcSfqQopt = 0x0b + SizeofTcSfqRedStats = 0x18 + SizeofTcSfqQoptV1 = SizeofTcSfqQopt + SizeofTcSfqRedStats + 0x1c +) + +// struct tcmsg { +// unsigned char tcm_family; +// unsigned char tcm__pad1; +// unsigned short tcm__pad2; +// int tcm_ifindex; +// __u32 tcm_handle; +// __u32 tcm_parent; +// __u32 tcm_info; +// }; + +type TcMsg struct { + Family uint8 + Pad [3]byte + Ifindex int32 + Handle uint32 + Parent uint32 + Info uint32 +} + +func (msg *TcMsg) Len() int { + return SizeofTcMsg +} + +func DeserializeTcMsg(b []byte) *TcMsg { + return (*TcMsg)(unsafe.Pointer(&b[0:SizeofTcMsg][0])) +} + +func (x *TcMsg) Serialize() []byte { + return (*(*[SizeofTcMsg]byte)(unsafe.Pointer(x)))[:] +} + +// struct tcamsg { +// unsigned char tca_family; +// unsigned char tca__pad1; +// unsigned short tca__pad2; +// }; + +type TcActionMsg struct { + Family uint8 + Pad [3]byte +} + +func (msg *TcActionMsg) Len() int { + return SizeofTcActionMsg +} + +func DeserializeTcActionMsg(b []byte) *TcActionMsg { + return (*TcActionMsg)(unsafe.Pointer(&b[0:SizeofTcActionMsg][0])) +} + +func (x *TcActionMsg) Serialize() []byte { + return (*(*[SizeofTcActionMsg]byte)(unsafe.Pointer(x)))[:] +} + +const ( + TC_PRIO_MAX = 15 +) + +// struct tc_prio_qopt { +// int bands; /* Number of bands */ +// __u8 priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> PRIO band */ +// }; + +type TcPrioMap struct { + Bands int32 + Priomap [TC_PRIO_MAX + 1]uint8 +} + +func (msg *TcPrioMap) Len() int { + return SizeofTcPrioMap +} + +func DeserializeTcPrioMap(b []byte) *TcPrioMap { + return (*TcPrioMap)(unsafe.Pointer(&b[0:SizeofTcPrioMap][0])) +} + +func (x *TcPrioMap) Serialize() []byte { + return (*(*[SizeofTcPrioMap]byte)(unsafe.Pointer(x)))[:] +} + +const ( + TCA_TBF_UNSPEC = iota + TCA_TBF_PARMS + TCA_TBF_RTAB + TCA_TBF_PTAB + TCA_TBF_RATE64 + TCA_TBF_PRATE64 + TCA_TBF_BURST + TCA_TBF_PBURST + TCA_TBF_MAX = TCA_TBF_PBURST +) + +// struct tc_ratespec { +// unsigned char cell_log; +// __u8 linklayer; /* lower 4 bits */ +// unsigned short overhead; +// short cell_align; +// unsigned short mpu; +// __u32 rate; +// }; + +type TcRateSpec struct { + CellLog uint8 + Linklayer uint8 + Overhead uint16 + CellAlign int16 + Mpu uint16 + Rate uint32 +} + +func (msg *TcRateSpec) Len() int { + return SizeofTcRateSpec +} + +func DeserializeTcRateSpec(b []byte) *TcRateSpec { + return (*TcRateSpec)(unsafe.Pointer(&b[0:SizeofTcRateSpec][0])) +} + +func (x *TcRateSpec) Serialize() []byte { + return (*(*[SizeofTcRateSpec]byte)(unsafe.Pointer(x)))[:] +} + +/** +* NETEM + */ + +const ( + TCA_NETEM_UNSPEC = iota + TCA_NETEM_CORR + TCA_NETEM_DELAY_DIST + TCA_NETEM_REORDER + TCA_NETEM_CORRUPT + TCA_NETEM_LOSS + TCA_NETEM_RATE + TCA_NETEM_ECN + TCA_NETEM_RATE64 + TCA_NETEM_MAX = TCA_NETEM_RATE64 +) + +// struct tc_netem_qopt { +// __u32 latency; /* added delay (us) */ +// __u32 limit; /* fifo limit (packets) */ +// __u32 loss; /* random packet loss (0=none ~0=100%) */ +// __u32 gap; /* re-ordering gap (0 for none) */ +// __u32 duplicate; /* random packet dup (0=none ~0=100%) */ +// __u32 jitter; /* random jitter in latency (us) */ +// }; + +type TcNetemQopt struct { + Latency uint32 + Limit uint32 + Loss uint32 + Gap uint32 + Duplicate uint32 + Jitter uint32 +} + +func (msg *TcNetemQopt) Len() int { + return SizeofTcNetemQopt +} + +func DeserializeTcNetemQopt(b []byte) *TcNetemQopt { + return (*TcNetemQopt)(unsafe.Pointer(&b[0:SizeofTcNetemQopt][0])) +} + +func (x *TcNetemQopt) Serialize() []byte { + return (*(*[SizeofTcNetemQopt]byte)(unsafe.Pointer(x)))[:] +} + +// struct tc_netem_corr { +// __u32 delay_corr; /* delay correlation */ +// __u32 loss_corr; /* packet loss correlation */ +// __u32 dup_corr; /* duplicate correlation */ +// }; + +type TcNetemCorr struct { + DelayCorr uint32 + LossCorr uint32 + DupCorr uint32 +} + +func (msg *TcNetemCorr) Len() int { + return SizeofTcNetemCorr +} + +func DeserializeTcNetemCorr(b []byte) *TcNetemCorr { + return (*TcNetemCorr)(unsafe.Pointer(&b[0:SizeofTcNetemCorr][0])) +} + +func (x *TcNetemCorr) Serialize() []byte { + return (*(*[SizeofTcNetemCorr]byte)(unsafe.Pointer(x)))[:] +} + +// struct tc_netem_reorder { +// __u32 probability; +// __u32 correlation; +// }; + +type TcNetemReorder struct { + Probability uint32 + Correlation uint32 +} + +func (msg *TcNetemReorder) Len() int { + return SizeofTcNetemReorder +} + +func DeserializeTcNetemReorder(b []byte) *TcNetemReorder { + return (*TcNetemReorder)(unsafe.Pointer(&b[0:SizeofTcNetemReorder][0])) +} + +func (x *TcNetemReorder) Serialize() []byte { + return (*(*[SizeofTcNetemReorder]byte)(unsafe.Pointer(x)))[:] +} + +// struct tc_netem_corrupt { +// __u32 probability; +// __u32 correlation; +// }; + +type TcNetemCorrupt struct { + Probability uint32 + Correlation uint32 +} + +func (msg *TcNetemCorrupt) Len() int { + return SizeofTcNetemCorrupt +} + +func DeserializeTcNetemCorrupt(b []byte) *TcNetemCorrupt { + return (*TcNetemCorrupt)(unsafe.Pointer(&b[0:SizeofTcNetemCorrupt][0])) +} + +func (x *TcNetemCorrupt) Serialize() []byte { + return (*(*[SizeofTcNetemCorrupt]byte)(unsafe.Pointer(x)))[:] +} + +// struct tc_tbf_qopt { +// struct tc_ratespec rate; +// struct tc_ratespec peakrate; +// __u32 limit; +// __u32 buffer; +// __u32 mtu; +// }; + +type TcTbfQopt struct { + Rate TcRateSpec + Peakrate TcRateSpec + Limit uint32 + Buffer uint32 + Mtu uint32 +} + +func (msg *TcTbfQopt) Len() int { + return SizeofTcTbfQopt +} + +func DeserializeTcTbfQopt(b []byte) *TcTbfQopt { + return (*TcTbfQopt)(unsafe.Pointer(&b[0:SizeofTcTbfQopt][0])) +} + +func (x *TcTbfQopt) Serialize() []byte { + return (*(*[SizeofTcTbfQopt]byte)(unsafe.Pointer(x)))[:] +} + +const ( + TCA_HTB_UNSPEC = iota + TCA_HTB_PARMS + TCA_HTB_INIT + TCA_HTB_CTAB + TCA_HTB_RTAB + TCA_HTB_DIRECT_QLEN + TCA_HTB_RATE64 + TCA_HTB_CEIL64 + TCA_HTB_MAX = TCA_HTB_CEIL64 +) + +//struct tc_htb_opt { +// struct tc_ratespec rate; +// struct tc_ratespec ceil; +// __u32 buffer; +// __u32 cbuffer; +// __u32 quantum; +// __u32 level; /* out only */ +// __u32 prio; +//}; + +type TcHtbCopt struct { + Rate TcRateSpec + Ceil TcRateSpec + Buffer uint32 + Cbuffer uint32 + Quantum uint32 + Level uint32 + Prio uint32 +} + +func (msg *TcHtbCopt) Len() int { + return SizeofTcHtbCopt +} + +func DeserializeTcHtbCopt(b []byte) *TcHtbCopt { + return (*TcHtbCopt)(unsafe.Pointer(&b[0:SizeofTcHtbCopt][0])) +} + +func (x *TcHtbCopt) Serialize() []byte { + return (*(*[SizeofTcHtbCopt]byte)(unsafe.Pointer(x)))[:] +} + +type TcHtbGlob struct { + Version uint32 + Rate2Quantum uint32 + Defcls uint32 + Debug uint32 + DirectPkts uint32 +} + +func (msg *TcHtbGlob) Len() int { + return SizeofTcHtbGlob +} + +func DeserializeTcHtbGlob(b []byte) *TcHtbGlob { + return (*TcHtbGlob)(unsafe.Pointer(&b[0:SizeofTcHtbGlob][0])) +} + +func (x *TcHtbGlob) Serialize() []byte { + return (*(*[SizeofTcHtbGlob]byte)(unsafe.Pointer(x)))[:] +} + +// HFSC + +type Curve struct { + m1 uint32 + d uint32 + m2 uint32 +} + +type HfscCopt struct { + Rsc Curve + Fsc Curve + Usc Curve +} + +func (c *Curve) Attrs() (uint32, uint32, uint32) { + return c.m1, c.d, c.m2 +} + +func (c *Curve) Set(m1 uint32, d uint32, m2 uint32) { + c.m1 = m1 + c.d = d + c.m2 = m2 +} + +func DeserializeHfscCurve(b []byte) *Curve { + return &Curve{ + m1: binary.LittleEndian.Uint32(b[0:4]), + d: binary.LittleEndian.Uint32(b[4:8]), + m2: binary.LittleEndian.Uint32(b[8:12]), + } +} + +func SerializeHfscCurve(c *Curve) (b []byte) { + t := make([]byte, binary.MaxVarintLen32) + binary.LittleEndian.PutUint32(t, c.m1) + b = append(b, t[:4]...) + binary.LittleEndian.PutUint32(t, c.d) + b = append(b, t[:4]...) + binary.LittleEndian.PutUint32(t, c.m2) + b = append(b, t[:4]...) + return b +} + +type TcHfscOpt struct { + Defcls uint16 +} + +func (x *TcHfscOpt) Serialize() []byte { + return (*(*[2]byte)(unsafe.Pointer(x)))[:] +} + +const ( + TCA_U32_UNSPEC = iota + TCA_U32_CLASSID + TCA_U32_HASH + TCA_U32_LINK + TCA_U32_DIVISOR + TCA_U32_SEL + TCA_U32_POLICE + TCA_U32_ACT + TCA_U32_INDEV + TCA_U32_PCNT + TCA_U32_MARK + TCA_U32_MAX = TCA_U32_MARK +) + +// struct tc_u32_key { +// __be32 mask; +// __be32 val; +// int off; +// int offmask; +// }; + +type TcU32Key struct { + Mask uint32 // big endian + Val uint32 // big endian + Off int32 + OffMask int32 +} + +func (msg *TcU32Key) Len() int { + return SizeofTcU32Key +} + +func DeserializeTcU32Key(b []byte) *TcU32Key { + return (*TcU32Key)(unsafe.Pointer(&b[0:SizeofTcU32Key][0])) +} + +func (x *TcU32Key) Serialize() []byte { + return (*(*[SizeofTcU32Key]byte)(unsafe.Pointer(x)))[:] +} + +// struct tc_u32_sel { +// unsigned char flags; +// unsigned char offshift; +// unsigned char nkeys; +// +// __be16 offmask; +// __u16 off; +// short offoff; +// +// short hoff; +// __be32 hmask; +// struct tc_u32_key keys[0]; +// }; + +const ( + TC_U32_TERMINAL = 1 << iota + TC_U32_OFFSET = 1 << iota + TC_U32_VAROFFSET = 1 << iota + TC_U32_EAT = 1 << iota +) + +type TcU32Sel struct { + Flags uint8 + Offshift uint8 + Nkeys uint8 + Pad uint8 + Offmask uint16 // big endian + Off uint16 + Offoff int16 + Hoff int16 + Hmask uint32 // big endian + Keys []TcU32Key +} + +func (msg *TcU32Sel) Len() int { + return SizeofTcU32Sel + int(msg.Nkeys)*SizeofTcU32Key +} + +func DeserializeTcU32Sel(b []byte) *TcU32Sel { + x := &TcU32Sel{} + copy((*(*[SizeofTcU32Sel]byte)(unsafe.Pointer(x)))[:], b) + next := SizeofTcU32Sel + var i uint8 + for i = 0; i < x.Nkeys; i++ { + x.Keys = append(x.Keys, *DeserializeTcU32Key(b[next:])) + next += SizeofTcU32Key + } + return x +} + +func (x *TcU32Sel) Serialize() []byte { + // This can't just unsafe.cast because it must iterate through keys. + buf := make([]byte, x.Len()) + copy(buf, (*(*[SizeofTcU32Sel]byte)(unsafe.Pointer(x)))[:]) + next := SizeofTcU32Sel + for _, key := range x.Keys { + keyBuf := key.Serialize() + copy(buf[next:], keyBuf) + next += SizeofTcU32Key + } + return buf +} + +type TcGen struct { + Index uint32 + Capab uint32 + Action int32 + Refcnt int32 + Bindcnt int32 +} + +func (msg *TcGen) Len() int { + return SizeofTcGen +} + +func DeserializeTcGen(b []byte) *TcGen { + return (*TcGen)(unsafe.Pointer(&b[0:SizeofTcGen][0])) +} + +func (x *TcGen) Serialize() []byte { + return (*(*[SizeofTcGen]byte)(unsafe.Pointer(x)))[:] +} + +// #define tc_gen \ +// __u32 index; \ +// __u32 capab; \ +// int action; \ +// int refcnt; \ +// int bindcnt + +const ( + TCA_ACT_GACT = 5 +) + +const ( + TCA_GACT_UNSPEC = iota + TCA_GACT_TM + TCA_GACT_PARMS + TCA_GACT_PROB + TCA_GACT_MAX = TCA_GACT_PROB +) + +type TcGact TcGen + +const ( + TCA_ACT_BPF = 13 +) + +const ( + TCA_ACT_BPF_UNSPEC = iota + TCA_ACT_BPF_TM + TCA_ACT_BPF_PARMS + TCA_ACT_BPF_OPS_LEN + TCA_ACT_BPF_OPS + TCA_ACT_BPF_FD + TCA_ACT_BPF_NAME + TCA_ACT_BPF_MAX = TCA_ACT_BPF_NAME +) + +const ( + TCA_BPF_FLAG_ACT_DIRECT uint32 = 1 << iota +) + +const ( + TCA_BPF_UNSPEC = iota + TCA_BPF_ACT + TCA_BPF_POLICE + TCA_BPF_CLASSID + TCA_BPF_OPS_LEN + TCA_BPF_OPS + TCA_BPF_FD + TCA_BPF_NAME + TCA_BPF_FLAGS + TCA_BPF_FLAGS_GEN + TCA_BPF_TAG + TCA_BPF_ID + TCA_BPF_MAX = TCA_BPF_ID +) + +type TcBpf TcGen + +const ( + TCA_ACT_CONNMARK = 14 +) + +const ( + TCA_CONNMARK_UNSPEC = iota + TCA_CONNMARK_PARMS + TCA_CONNMARK_TM + TCA_CONNMARK_MAX = TCA_CONNMARK_TM +) + +// struct tc_connmark { +// tc_gen; +// __u16 zone; +// }; + +type TcConnmark struct { + TcGen + Zone uint16 +} + +func (msg *TcConnmark) Len() int { + return SizeofTcConnmark +} + +func DeserializeTcConnmark(b []byte) *TcConnmark { + return (*TcConnmark)(unsafe.Pointer(&b[0:SizeofTcConnmark][0])) +} + +func (x *TcConnmark) Serialize() []byte { + return (*(*[SizeofTcConnmark]byte)(unsafe.Pointer(x)))[:] +} + +const ( + TCA_ACT_MIRRED = 8 +) + +const ( + TCA_MIRRED_UNSPEC = iota + TCA_MIRRED_TM + TCA_MIRRED_PARMS + TCA_MIRRED_MAX = TCA_MIRRED_PARMS +) + +// struct tc_mirred { +// tc_gen; +// int eaction; /* one of IN/EGRESS_MIRROR/REDIR */ +// __u32 ifindex; /* ifindex of egress port */ +// }; + +type TcMirred struct { + TcGen + Eaction int32 + Ifindex uint32 +} + +func (msg *TcMirred) Len() int { + return SizeofTcMirred +} + +func DeserializeTcMirred(b []byte) *TcMirred { + return (*TcMirred)(unsafe.Pointer(&b[0:SizeofTcMirred][0])) +} + +func (x *TcMirred) Serialize() []byte { + return (*(*[SizeofTcMirred]byte)(unsafe.Pointer(x)))[:] +} + +const ( + TCA_TUNNEL_KEY_UNSPEC = iota + TCA_TUNNEL_KEY_TM + TCA_TUNNEL_KEY_PARMS + TCA_TUNNEL_KEY_ENC_IPV4_SRC + TCA_TUNNEL_KEY_ENC_IPV4_DST + TCA_TUNNEL_KEY_ENC_IPV6_SRC + TCA_TUNNEL_KEY_ENC_IPV6_DST + TCA_TUNNEL_KEY_ENC_KEY_ID + TCA_TUNNEL_KEY_PAD + TCA_TUNNEL_KEY_ENC_DST_PORT + TCA_TUNNEL_KEY_NO_CSUM + TCA_TUNNEL_KEY_ENC_OPTS + TCA_TUNNEL_KEY_ENC_TOS + TCA_TUNNEL_KEY_ENC_TTL + TCA_TUNNEL_KEY_MAX +) + +type TcTunnelKey struct { + TcGen + Action int32 +} + +func (x *TcTunnelKey) Len() int { + return SizeofTcTunnelKey +} + +func DeserializeTunnelKey(b []byte) *TcTunnelKey { + return (*TcTunnelKey)(unsafe.Pointer(&b[0:SizeofTcTunnelKey][0])) +} + +func (x *TcTunnelKey) Serialize() []byte { + return (*(*[SizeofTcTunnelKey]byte)(unsafe.Pointer(x)))[:] +} + +const ( + TCA_SKBEDIT_UNSPEC = iota + TCA_SKBEDIT_TM + TCA_SKBEDIT_PARMS + TCA_SKBEDIT_PRIORITY + TCA_SKBEDIT_QUEUE_MAPPING + TCA_SKBEDIT_MARK + TCA_SKBEDIT_PAD + TCA_SKBEDIT_PTYPE + TCA_SKBEDIT_MAX = TCA_SKBEDIT_MARK +) + +type TcSkbEdit struct { + TcGen +} + +func (x *TcSkbEdit) Len() int { + return SizeofTcSkbEdit +} + +func DeserializeSkbEdit(b []byte) *TcSkbEdit { + return (*TcSkbEdit)(unsafe.Pointer(&b[0:SizeofTcSkbEdit][0])) +} + +func (x *TcSkbEdit) Serialize() []byte { + return (*(*[SizeofTcSkbEdit]byte)(unsafe.Pointer(x)))[:] +} + +// struct tc_police { +// __u32 index; +// int action; +// __u32 limit; +// __u32 burst; +// __u32 mtu; +// struct tc_ratespec rate; +// struct tc_ratespec peakrate; +// int refcnt; +// int bindcnt; +// __u32 capab; +// }; + +type TcPolice struct { + Index uint32 + Action int32 + Limit uint32 + Burst uint32 + Mtu uint32 + Rate TcRateSpec + PeakRate TcRateSpec + Refcnt int32 + Bindcnt int32 + Capab uint32 +} + +func (msg *TcPolice) Len() int { + return SizeofTcPolice +} + +func DeserializeTcPolice(b []byte) *TcPolice { + return (*TcPolice)(unsafe.Pointer(&b[0:SizeofTcPolice][0])) +} + +func (x *TcPolice) Serialize() []byte { + return (*(*[SizeofTcPolice]byte)(unsafe.Pointer(x)))[:] +} + +const ( + TCA_FW_UNSPEC = iota + TCA_FW_CLASSID + TCA_FW_POLICE + TCA_FW_INDEV + TCA_FW_ACT + TCA_FW_MASK + TCA_FW_MAX = TCA_FW_MASK +) + +const ( + TCA_MATCHALL_UNSPEC = iota + TCA_MATCHALL_CLASSID + TCA_MATCHALL_ACT + TCA_MATCHALL_FLAGS +) + +const ( + TCA_FQ_UNSPEC = iota + TCA_FQ_PLIMIT // limit of total number of packets in queue + TCA_FQ_FLOW_PLIMIT // limit of packets per flow + TCA_FQ_QUANTUM // RR quantum + TCA_FQ_INITIAL_QUANTUM // RR quantum for new flow + TCA_FQ_RATE_ENABLE // enable/disable rate limiting + TCA_FQ_FLOW_DEFAULT_RATE // obsolete do not use + TCA_FQ_FLOW_MAX_RATE // per flow max rate + TCA_FQ_BUCKETS_LOG // log2(number of buckets) + TCA_FQ_FLOW_REFILL_DELAY // flow credit refill delay in usec + TCA_FQ_ORPHAN_MASK // mask applied to orphaned skb hashes + TCA_FQ_LOW_RATE_THRESHOLD // per packet delay under this rate +) + +const ( + TCA_FQ_CODEL_UNSPEC = iota + TCA_FQ_CODEL_TARGET + TCA_FQ_CODEL_LIMIT + TCA_FQ_CODEL_INTERVAL + TCA_FQ_CODEL_ECN + TCA_FQ_CODEL_FLOWS + TCA_FQ_CODEL_QUANTUM + TCA_FQ_CODEL_CE_THRESHOLD + TCA_FQ_CODEL_DROP_BATCH_SIZE + TCA_FQ_CODEL_MEMORY_LIMIT +) + +const ( + TCA_HFSC_UNSPEC = iota + TCA_HFSC_RSC + TCA_HFSC_FSC + TCA_HFSC_USC +) + +// struct tc_sfq_qopt { +// unsigned quantum; /* Bytes per round allocated to flow */ +// int perturb_period; /* Period of hash perturbation */ +// __u32 limit; /* Maximal packets in queue */ +// unsigned divisor; /* Hash divisor */ +// unsigned flows; /* Maximal number of flows */ +// }; + +type TcSfqQopt struct { + Quantum uint8 + Perturb int32 + Limit uint32 + Divisor uint8 + Flows uint8 +} + +func (x *TcSfqQopt) Len() int { + return SizeofTcSfqQopt +} + +func DeserializeTcSfqQopt(b []byte) *TcSfqQopt { + return (*TcSfqQopt)(unsafe.Pointer(&b[0:SizeofTcSfqQopt][0])) +} + +func (x *TcSfqQopt) Serialize() []byte { + return (*(*[SizeofTcSfqQopt]byte)(unsafe.Pointer(x)))[:] +} + +// struct tc_sfqred_stats { +// __u32 prob_drop; /* Early drops, below max threshold */ +// __u32 forced_drop; /* Early drops, after max threshold */ +// __u32 prob_mark; /* Marked packets, below max threshold */ +// __u32 forced_mark; /* Marked packets, after max threshold */ +// __u32 prob_mark_head; /* Marked packets, below max threshold */ +// __u32 forced_mark_head;/* Marked packets, after max threshold */ +// }; +type TcSfqRedStats struct { + ProbDrop uint32 + ForcedDrop uint32 + ProbMark uint32 + ForcedMark uint32 + ProbMarkHead uint32 + ForcedMarkHead uint32 +} + +func (x *TcSfqRedStats) Len() int { + return SizeofTcSfqRedStats +} + +func DeserializeTcSfqRedStats(b []byte) *TcSfqRedStats { + return (*TcSfqRedStats)(unsafe.Pointer(&b[0:SizeofTcSfqRedStats][0])) +} + +func (x *TcSfqRedStats) Serialize() []byte { + return (*(*[SizeofTcSfqRedStats]byte)(unsafe.Pointer(x)))[:] +} + +// struct tc_sfq_qopt_v1 { +// struct tc_sfq_qopt v0; +// unsigned int depth; /* max number of packets per flow */ +// unsigned int headdrop; +// /* SFQRED parameters */ +// __u32 limit; /* HARD maximal flow queue length (bytes) */ +// __u32 qth_min; /* Min average length threshold (bytes) */ +// __u32 qth_max; /* Max average length threshold (bytes) */ +// unsigned char Wlog; /* log(W) */ +// unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */ +// unsigned char Scell_log; /* cell size for idle damping */ +// unsigned char flags; +// __u32 max_P; /* probability, high resolution */ +// /* SFQRED stats */ +// struct tc_sfqred_stats stats; +// }; +type TcSfqQoptV1 struct { + TcSfqQopt + Depth uint32 + HeadDrop uint32 + Limit uint32 + QthMin uint32 + QthMax uint32 + Wlog byte + Plog byte + ScellLog byte + Flags byte + MaxP uint32 + TcSfqRedStats +} + +func (x *TcSfqQoptV1) Len() int { + return SizeofTcSfqQoptV1 +} + +func DeserializeTcSfqQoptV1(b []byte) *TcSfqQoptV1 { + return (*TcSfqQoptV1)(unsafe.Pointer(&b[0:SizeofTcSfqQoptV1][0])) +} + +func (x *TcSfqQoptV1) Serialize() []byte { + return (*(*[SizeofTcSfqQoptV1]byte)(unsafe.Pointer(x)))[:] +} diff --git a/vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go b/vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go new file mode 100644 index 000000000..dce9073f7 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go @@ -0,0 +1,306 @@ +package nl + +import ( + "bytes" + "net" + "unsafe" +) + +// Infinity for packet and byte counts +const ( + XFRM_INF = ^uint64(0) +) + +type XfrmMsgType uint8 + +type XfrmMsg interface { + Type() XfrmMsgType +} + +// Message Types +const ( + XFRM_MSG_BASE XfrmMsgType = 0x10 + XFRM_MSG_NEWSA = 0x10 + XFRM_MSG_DELSA = 0x11 + XFRM_MSG_GETSA = 0x12 + XFRM_MSG_NEWPOLICY = 0x13 + XFRM_MSG_DELPOLICY = 0x14 + XFRM_MSG_GETPOLICY = 0x15 + XFRM_MSG_ALLOCSPI = 0x16 + XFRM_MSG_ACQUIRE = 0x17 + XFRM_MSG_EXPIRE = 0x18 + XFRM_MSG_UPDPOLICY = 0x19 + XFRM_MSG_UPDSA = 0x1a + XFRM_MSG_POLEXPIRE = 0x1b + XFRM_MSG_FLUSHSA = 0x1c + XFRM_MSG_FLUSHPOLICY = 0x1d + XFRM_MSG_NEWAE = 0x1e + XFRM_MSG_GETAE = 0x1f + XFRM_MSG_REPORT = 0x20 + XFRM_MSG_MIGRATE = 0x21 + XFRM_MSG_NEWSADINFO = 0x22 + XFRM_MSG_GETSADINFO = 0x23 + XFRM_MSG_NEWSPDINFO = 0x24 + XFRM_MSG_GETSPDINFO = 0x25 + XFRM_MSG_MAPPING = 0x26 + XFRM_MSG_MAX = 0x26 + XFRM_NR_MSGTYPES = 0x17 +) + +// Attribute types +const ( + /* Netlink message attributes. */ + XFRMA_UNSPEC = iota + XFRMA_ALG_AUTH /* struct xfrm_algo */ + XFRMA_ALG_CRYPT /* struct xfrm_algo */ + XFRMA_ALG_COMP /* struct xfrm_algo */ + XFRMA_ENCAP /* struct xfrm_algo + struct xfrm_encap_tmpl */ + XFRMA_TMPL /* 1 or more struct xfrm_user_tmpl */ + XFRMA_SA /* struct xfrm_usersa_info */ + XFRMA_POLICY /* struct xfrm_userpolicy_info */ + XFRMA_SEC_CTX /* struct xfrm_sec_ctx */ + XFRMA_LTIME_VAL + XFRMA_REPLAY_VAL + XFRMA_REPLAY_THRESH + XFRMA_ETIMER_THRESH + XFRMA_SRCADDR /* xfrm_address_t */ + XFRMA_COADDR /* xfrm_address_t */ + XFRMA_LASTUSED /* unsigned long */ + XFRMA_POLICY_TYPE /* struct xfrm_userpolicy_type */ + XFRMA_MIGRATE + XFRMA_ALG_AEAD /* struct xfrm_algo_aead */ + XFRMA_KMADDRESS /* struct xfrm_user_kmaddress */ + XFRMA_ALG_AUTH_TRUNC /* struct xfrm_algo_auth */ + XFRMA_MARK /* struct xfrm_mark */ + XFRMA_TFCPAD /* __u32 */ + XFRMA_REPLAY_ESN_VAL /* struct xfrm_replay_esn */ + XFRMA_SA_EXTRA_FLAGS /* __u32 */ + XFRMA_PROTO /* __u8 */ + XFRMA_ADDRESS_FILTER /* struct xfrm_address_filter */ + XFRMA_PAD + XFRMA_OFFLOAD_DEV /* struct xfrm_state_offload */ + XFRMA_SET_MARK /* __u32 */ + XFRMA_SET_MARK_MASK /* __u32 */ + XFRMA_IF_ID /* __u32 */ + + XFRMA_MAX = iota - 1 +) + +const XFRMA_OUTPUT_MARK = XFRMA_SET_MARK + +const ( + SizeofXfrmAddress = 0x10 + SizeofXfrmSelector = 0x38 + SizeofXfrmLifetimeCfg = 0x40 + SizeofXfrmLifetimeCur = 0x20 + SizeofXfrmId = 0x18 + SizeofXfrmMark = 0x08 +) + +// Netlink groups +const ( + XFRMNLGRP_NONE = 0x0 + XFRMNLGRP_ACQUIRE = 0x1 + XFRMNLGRP_EXPIRE = 0x2 + XFRMNLGRP_SA = 0x3 + XFRMNLGRP_POLICY = 0x4 + XFRMNLGRP_AEVENTS = 0x5 + XFRMNLGRP_REPORT = 0x6 + XFRMNLGRP_MIGRATE = 0x7 + XFRMNLGRP_MAPPING = 0x8 + __XFRMNLGRP_MAX = 0x9 +) + +// typedef union { +// __be32 a4; +// __be32 a6[4]; +// } xfrm_address_t; + +type XfrmAddress [SizeofXfrmAddress]byte + +func (x *XfrmAddress) ToIP() net.IP { + var empty = [12]byte{} + ip := make(net.IP, net.IPv6len) + if bytes.Equal(x[4:16], empty[:]) { + ip[10] = 0xff + ip[11] = 0xff + copy(ip[12:16], x[0:4]) + } else { + copy(ip[:], x[:]) + } + return ip +} + +func (x *XfrmAddress) ToIPNet(prefixlen uint8) *net.IPNet { + ip := x.ToIP() + if GetIPFamily(ip) == FAMILY_V4 { + return &net.IPNet{IP: ip, Mask: net.CIDRMask(int(prefixlen), 32)} + } + return &net.IPNet{IP: ip, Mask: net.CIDRMask(int(prefixlen), 128)} +} + +func (x *XfrmAddress) FromIP(ip net.IP) { + var empty = [16]byte{} + if len(ip) < net.IPv4len { + copy(x[4:16], empty[:]) + } else if GetIPFamily(ip) == FAMILY_V4 { + copy(x[0:4], ip.To4()[0:4]) + copy(x[4:16], empty[:12]) + } else { + copy(x[0:16], ip.To16()[0:16]) + } +} + +func DeserializeXfrmAddress(b []byte) *XfrmAddress { + return (*XfrmAddress)(unsafe.Pointer(&b[0:SizeofXfrmAddress][0])) +} + +func (x *XfrmAddress) Serialize() []byte { + return (*(*[SizeofXfrmAddress]byte)(unsafe.Pointer(x)))[:] +} + +// struct xfrm_selector { +// xfrm_address_t daddr; +// xfrm_address_t saddr; +// __be16 dport; +// __be16 dport_mask; +// __be16 sport; +// __be16 sport_mask; +// __u16 family; +// __u8 prefixlen_d; +// __u8 prefixlen_s; +// __u8 proto; +// int ifindex; +// __kernel_uid32_t user; +// }; + +type XfrmSelector struct { + Daddr XfrmAddress + Saddr XfrmAddress + Dport uint16 // big endian + DportMask uint16 // big endian + Sport uint16 // big endian + SportMask uint16 // big endian + Family uint16 + PrefixlenD uint8 + PrefixlenS uint8 + Proto uint8 + Pad [3]byte + Ifindex int32 + User uint32 +} + +func (msg *XfrmSelector) Len() int { + return SizeofXfrmSelector +} + +func DeserializeXfrmSelector(b []byte) *XfrmSelector { + return (*XfrmSelector)(unsafe.Pointer(&b[0:SizeofXfrmSelector][0])) +} + +func (msg *XfrmSelector) Serialize() []byte { + return (*(*[SizeofXfrmSelector]byte)(unsafe.Pointer(msg)))[:] +} + +// struct xfrm_lifetime_cfg { +// __u64 soft_byte_limit; +// __u64 hard_byte_limit; +// __u64 soft_packet_limit; +// __u64 hard_packet_limit; +// __u64 soft_add_expires_seconds; +// __u64 hard_add_expires_seconds; +// __u64 soft_use_expires_seconds; +// __u64 hard_use_expires_seconds; +// }; +// + +type XfrmLifetimeCfg struct { + SoftByteLimit uint64 + HardByteLimit uint64 + SoftPacketLimit uint64 + HardPacketLimit uint64 + SoftAddExpiresSeconds uint64 + HardAddExpiresSeconds uint64 + SoftUseExpiresSeconds uint64 + HardUseExpiresSeconds uint64 +} + +func (msg *XfrmLifetimeCfg) Len() int { + return SizeofXfrmLifetimeCfg +} + +func DeserializeXfrmLifetimeCfg(b []byte) *XfrmLifetimeCfg { + return (*XfrmLifetimeCfg)(unsafe.Pointer(&b[0:SizeofXfrmLifetimeCfg][0])) +} + +func (msg *XfrmLifetimeCfg) Serialize() []byte { + return (*(*[SizeofXfrmLifetimeCfg]byte)(unsafe.Pointer(msg)))[:] +} + +// struct xfrm_lifetime_cur { +// __u64 bytes; +// __u64 packets; +// __u64 add_time; +// __u64 use_time; +// }; + +type XfrmLifetimeCur struct { + Bytes uint64 + Packets uint64 + AddTime uint64 + UseTime uint64 +} + +func (msg *XfrmLifetimeCur) Len() int { + return SizeofXfrmLifetimeCur +} + +func DeserializeXfrmLifetimeCur(b []byte) *XfrmLifetimeCur { + return (*XfrmLifetimeCur)(unsafe.Pointer(&b[0:SizeofXfrmLifetimeCur][0])) +} + +func (msg *XfrmLifetimeCur) Serialize() []byte { + return (*(*[SizeofXfrmLifetimeCur]byte)(unsafe.Pointer(msg)))[:] +} + +// struct xfrm_id { +// xfrm_address_t daddr; +// __be32 spi; +// __u8 proto; +// }; + +type XfrmId struct { + Daddr XfrmAddress + Spi uint32 // big endian + Proto uint8 + Pad [3]byte +} + +func (msg *XfrmId) Len() int { + return SizeofXfrmId +} + +func DeserializeXfrmId(b []byte) *XfrmId { + return (*XfrmId)(unsafe.Pointer(&b[0:SizeofXfrmId][0])) +} + +func (msg *XfrmId) Serialize() []byte { + return (*(*[SizeofXfrmId]byte)(unsafe.Pointer(msg)))[:] +} + +type XfrmMark struct { + Value uint32 + Mask uint32 +} + +func (msg *XfrmMark) Len() int { + return SizeofXfrmMark +} + +func DeserializeXfrmMark(b []byte) *XfrmMark { + return (*XfrmMark)(unsafe.Pointer(&b[0:SizeofXfrmMark][0])) +} + +func (msg *XfrmMark) Serialize() []byte { + return (*(*[SizeofXfrmMark]byte)(unsafe.Pointer(msg)))[:] +} diff --git a/vendor/github.com/vishvananda/netlink/nl/xfrm_monitor_linux.go b/vendor/github.com/vishvananda/netlink/nl/xfrm_monitor_linux.go new file mode 100644 index 000000000..715df4cc5 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/xfrm_monitor_linux.go @@ -0,0 +1,32 @@ +package nl + +import ( + "unsafe" +) + +const ( + SizeofXfrmUserExpire = 0xe8 +) + +// struct xfrm_user_expire { +// struct xfrm_usersa_info state; +// __u8 hard; +// }; + +type XfrmUserExpire struct { + XfrmUsersaInfo XfrmUsersaInfo + Hard uint8 + Pad [7]byte +} + +func (msg *XfrmUserExpire) Len() int { + return SizeofXfrmUserExpire +} + +func DeserializeXfrmUserExpire(b []byte) *XfrmUserExpire { + return (*XfrmUserExpire)(unsafe.Pointer(&b[0:SizeofXfrmUserExpire][0])) +} + +func (msg *XfrmUserExpire) Serialize() []byte { + return (*(*[SizeofXfrmUserExpire]byte)(unsafe.Pointer(msg)))[:] +} diff --git a/vendor/github.com/vishvananda/netlink/nl/xfrm_policy_linux.go b/vendor/github.com/vishvananda/netlink/nl/xfrm_policy_linux.go new file mode 100644 index 000000000..66f7e03d2 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/xfrm_policy_linux.go @@ -0,0 +1,119 @@ +package nl + +import ( + "unsafe" +) + +const ( + SizeofXfrmUserpolicyId = 0x40 + SizeofXfrmUserpolicyInfo = 0xa8 + SizeofXfrmUserTmpl = 0x40 +) + +// struct xfrm_userpolicy_id { +// struct xfrm_selector sel; +// __u32 index; +// __u8 dir; +// }; +// + +type XfrmUserpolicyId struct { + Sel XfrmSelector + Index uint32 + Dir uint8 + Pad [3]byte +} + +func (msg *XfrmUserpolicyId) Len() int { + return SizeofXfrmUserpolicyId +} + +func DeserializeXfrmUserpolicyId(b []byte) *XfrmUserpolicyId { + return (*XfrmUserpolicyId)(unsafe.Pointer(&b[0:SizeofXfrmUserpolicyId][0])) +} + +func (msg *XfrmUserpolicyId) Serialize() []byte { + return (*(*[SizeofXfrmUserpolicyId]byte)(unsafe.Pointer(msg)))[:] +} + +// struct xfrm_userpolicy_info { +// struct xfrm_selector sel; +// struct xfrm_lifetime_cfg lft; +// struct xfrm_lifetime_cur curlft; +// __u32 priority; +// __u32 index; +// __u8 dir; +// __u8 action; +// #define XFRM_POLICY_ALLOW 0 +// #define XFRM_POLICY_BLOCK 1 +// __u8 flags; +// #define XFRM_POLICY_LOCALOK 1 /* Allow user to override global policy */ +// /* Automatically expand selector to include matching ICMP payloads. */ +// #define XFRM_POLICY_ICMP 2 +// __u8 share; +// }; + +type XfrmUserpolicyInfo struct { + Sel XfrmSelector + Lft XfrmLifetimeCfg + Curlft XfrmLifetimeCur + Priority uint32 + Index uint32 + Dir uint8 + Action uint8 + Flags uint8 + Share uint8 + Pad [4]byte +} + +func (msg *XfrmUserpolicyInfo) Len() int { + return SizeofXfrmUserpolicyInfo +} + +func DeserializeXfrmUserpolicyInfo(b []byte) *XfrmUserpolicyInfo { + return (*XfrmUserpolicyInfo)(unsafe.Pointer(&b[0:SizeofXfrmUserpolicyInfo][0])) +} + +func (msg *XfrmUserpolicyInfo) Serialize() []byte { + return (*(*[SizeofXfrmUserpolicyInfo]byte)(unsafe.Pointer(msg)))[:] +} + +// struct xfrm_user_tmpl { +// struct xfrm_id id; +// __u16 family; +// xfrm_address_t saddr; +// __u32 reqid; +// __u8 mode; +// __u8 share; +// __u8 optional; +// __u32 aalgos; +// __u32 ealgos; +// __u32 calgos; +// } + +type XfrmUserTmpl struct { + XfrmId XfrmId + Family uint16 + Pad1 [2]byte + Saddr XfrmAddress + Reqid uint32 + Mode uint8 + Share uint8 + Optional uint8 + Pad2 byte + Aalgos uint32 + Ealgos uint32 + Calgos uint32 +} + +func (msg *XfrmUserTmpl) Len() int { + return SizeofXfrmUserTmpl +} + +func DeserializeXfrmUserTmpl(b []byte) *XfrmUserTmpl { + return (*XfrmUserTmpl)(unsafe.Pointer(&b[0:SizeofXfrmUserTmpl][0])) +} + +func (msg *XfrmUserTmpl) Serialize() []byte { + return (*(*[SizeofXfrmUserTmpl]byte)(unsafe.Pointer(msg)))[:] +} diff --git a/vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go b/vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go new file mode 100644 index 000000000..43a947f22 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go @@ -0,0 +1,334 @@ +package nl + +import ( + "unsafe" +) + +const ( + SizeofXfrmUsersaId = 0x18 + SizeofXfrmStats = 0x0c + SizeofXfrmUsersaInfo = 0xe0 + SizeofXfrmUserSpiInfo = 0xe8 + SizeofXfrmAlgo = 0x44 + SizeofXfrmAlgoAuth = 0x48 + SizeofXfrmAlgoAEAD = 0x48 + SizeofXfrmEncapTmpl = 0x18 + SizeofXfrmUsersaFlush = 0x1 + SizeofXfrmReplayStateEsn = 0x18 +) + +const ( + XFRM_STATE_NOECN = 1 + XFRM_STATE_DECAP_DSCP = 2 + XFRM_STATE_NOPMTUDISC = 4 + XFRM_STATE_WILDRECV = 8 + XFRM_STATE_ICMP = 16 + XFRM_STATE_AF_UNSPEC = 32 + XFRM_STATE_ALIGN4 = 64 + XFRM_STATE_ESN = 128 +) + +// struct xfrm_usersa_id { +// xfrm_address_t daddr; +// __be32 spi; +// __u16 family; +// __u8 proto; +// }; + +type XfrmUsersaId struct { + Daddr XfrmAddress + Spi uint32 // big endian + Family uint16 + Proto uint8 + Pad byte +} + +func (msg *XfrmUsersaId) Len() int { + return SizeofXfrmUsersaId +} + +func DeserializeXfrmUsersaId(b []byte) *XfrmUsersaId { + return (*XfrmUsersaId)(unsafe.Pointer(&b[0:SizeofXfrmUsersaId][0])) +} + +func (msg *XfrmUsersaId) Serialize() []byte { + return (*(*[SizeofXfrmUsersaId]byte)(unsafe.Pointer(msg)))[:] +} + +// struct xfrm_stats { +// __u32 replay_window; +// __u32 replay; +// __u32 integrity_failed; +// }; + +type XfrmStats struct { + ReplayWindow uint32 + Replay uint32 + IntegrityFailed uint32 +} + +func (msg *XfrmStats) Len() int { + return SizeofXfrmStats +} + +func DeserializeXfrmStats(b []byte) *XfrmStats { + return (*XfrmStats)(unsafe.Pointer(&b[0:SizeofXfrmStats][0])) +} + +func (msg *XfrmStats) Serialize() []byte { + return (*(*[SizeofXfrmStats]byte)(unsafe.Pointer(msg)))[:] +} + +// struct xfrm_usersa_info { +// struct xfrm_selector sel; +// struct xfrm_id id; +// xfrm_address_t saddr; +// struct xfrm_lifetime_cfg lft; +// struct xfrm_lifetime_cur curlft; +// struct xfrm_stats stats; +// __u32 seq; +// __u32 reqid; +// __u16 family; +// __u8 mode; /* XFRM_MODE_xxx */ +// __u8 replay_window; +// __u8 flags; +// #define XFRM_STATE_NOECN 1 +// #define XFRM_STATE_DECAP_DSCP 2 +// #define XFRM_STATE_NOPMTUDISC 4 +// #define XFRM_STATE_WILDRECV 8 +// #define XFRM_STATE_ICMP 16 +// #define XFRM_STATE_AF_UNSPEC 32 +// #define XFRM_STATE_ALIGN4 64 +// #define XFRM_STATE_ESN 128 +// }; +// +// #define XFRM_SA_XFLAG_DONT_ENCAP_DSCP 1 +// + +type XfrmUsersaInfo struct { + Sel XfrmSelector + Id XfrmId + Saddr XfrmAddress + Lft XfrmLifetimeCfg + Curlft XfrmLifetimeCur + Stats XfrmStats + Seq uint32 + Reqid uint32 + Family uint16 + Mode uint8 + ReplayWindow uint8 + Flags uint8 + Pad [7]byte +} + +func (msg *XfrmUsersaInfo) Len() int { + return SizeofXfrmUsersaInfo +} + +func DeserializeXfrmUsersaInfo(b []byte) *XfrmUsersaInfo { + return (*XfrmUsersaInfo)(unsafe.Pointer(&b[0:SizeofXfrmUsersaInfo][0])) +} + +func (msg *XfrmUsersaInfo) Serialize() []byte { + return (*(*[SizeofXfrmUsersaInfo]byte)(unsafe.Pointer(msg)))[:] +} + +// struct xfrm_userspi_info { +// struct xfrm_usersa_info info; +// __u32 min; +// __u32 max; +// }; + +type XfrmUserSpiInfo struct { + XfrmUsersaInfo XfrmUsersaInfo + Min uint32 + Max uint32 +} + +func (msg *XfrmUserSpiInfo) Len() int { + return SizeofXfrmUserSpiInfo +} + +func DeserializeXfrmUserSpiInfo(b []byte) *XfrmUserSpiInfo { + return (*XfrmUserSpiInfo)(unsafe.Pointer(&b[0:SizeofXfrmUserSpiInfo][0])) +} + +func (msg *XfrmUserSpiInfo) Serialize() []byte { + return (*(*[SizeofXfrmUserSpiInfo]byte)(unsafe.Pointer(msg)))[:] +} + +// struct xfrm_algo { +// char alg_name[64]; +// unsigned int alg_key_len; /* in bits */ +// char alg_key[0]; +// }; + +type XfrmAlgo struct { + AlgName [64]byte + AlgKeyLen uint32 + AlgKey []byte +} + +func (msg *XfrmAlgo) Len() int { + return SizeofXfrmAlgo + int(msg.AlgKeyLen/8) +} + +func DeserializeXfrmAlgo(b []byte) *XfrmAlgo { + ret := XfrmAlgo{} + copy(ret.AlgName[:], b[0:64]) + ret.AlgKeyLen = *(*uint32)(unsafe.Pointer(&b[64])) + ret.AlgKey = b[68:ret.Len()] + return &ret +} + +func (msg *XfrmAlgo) Serialize() []byte { + b := make([]byte, msg.Len()) + copy(b[0:64], msg.AlgName[:]) + copy(b[64:68], (*(*[4]byte)(unsafe.Pointer(&msg.AlgKeyLen)))[:]) + copy(b[68:msg.Len()], msg.AlgKey[:]) + return b +} + +// struct xfrm_algo_auth { +// char alg_name[64]; +// unsigned int alg_key_len; /* in bits */ +// unsigned int alg_trunc_len; /* in bits */ +// char alg_key[0]; +// }; + +type XfrmAlgoAuth struct { + AlgName [64]byte + AlgKeyLen uint32 + AlgTruncLen uint32 + AlgKey []byte +} + +func (msg *XfrmAlgoAuth) Len() int { + return SizeofXfrmAlgoAuth + int(msg.AlgKeyLen/8) +} + +func DeserializeXfrmAlgoAuth(b []byte) *XfrmAlgoAuth { + ret := XfrmAlgoAuth{} + copy(ret.AlgName[:], b[0:64]) + ret.AlgKeyLen = *(*uint32)(unsafe.Pointer(&b[64])) + ret.AlgTruncLen = *(*uint32)(unsafe.Pointer(&b[68])) + ret.AlgKey = b[72:ret.Len()] + return &ret +} + +func (msg *XfrmAlgoAuth) Serialize() []byte { + b := make([]byte, msg.Len()) + copy(b[0:64], msg.AlgName[:]) + copy(b[64:68], (*(*[4]byte)(unsafe.Pointer(&msg.AlgKeyLen)))[:]) + copy(b[68:72], (*(*[4]byte)(unsafe.Pointer(&msg.AlgTruncLen)))[:]) + copy(b[72:msg.Len()], msg.AlgKey[:]) + return b +} + +// struct xfrm_algo_aead { +// char alg_name[64]; +// unsigned int alg_key_len; /* in bits */ +// unsigned int alg_icv_len; /* in bits */ +// char alg_key[0]; +// } + +type XfrmAlgoAEAD struct { + AlgName [64]byte + AlgKeyLen uint32 + AlgICVLen uint32 + AlgKey []byte +} + +func (msg *XfrmAlgoAEAD) Len() int { + return SizeofXfrmAlgoAEAD + int(msg.AlgKeyLen/8) +} + +func DeserializeXfrmAlgoAEAD(b []byte) *XfrmAlgoAEAD { + ret := XfrmAlgoAEAD{} + copy(ret.AlgName[:], b[0:64]) + ret.AlgKeyLen = *(*uint32)(unsafe.Pointer(&b[64])) + ret.AlgICVLen = *(*uint32)(unsafe.Pointer(&b[68])) + ret.AlgKey = b[72:ret.Len()] + return &ret +} + +func (msg *XfrmAlgoAEAD) Serialize() []byte { + b := make([]byte, msg.Len()) + copy(b[0:64], msg.AlgName[:]) + copy(b[64:68], (*(*[4]byte)(unsafe.Pointer(&msg.AlgKeyLen)))[:]) + copy(b[68:72], (*(*[4]byte)(unsafe.Pointer(&msg.AlgICVLen)))[:]) + copy(b[72:msg.Len()], msg.AlgKey[:]) + return b +} + +// struct xfrm_encap_tmpl { +// __u16 encap_type; +// __be16 encap_sport; +// __be16 encap_dport; +// xfrm_address_t encap_oa; +// }; + +type XfrmEncapTmpl struct { + EncapType uint16 + EncapSport uint16 // big endian + EncapDport uint16 // big endian + Pad [2]byte + EncapOa XfrmAddress +} + +func (msg *XfrmEncapTmpl) Len() int { + return SizeofXfrmEncapTmpl +} + +func DeserializeXfrmEncapTmpl(b []byte) *XfrmEncapTmpl { + return (*XfrmEncapTmpl)(unsafe.Pointer(&b[0:SizeofXfrmEncapTmpl][0])) +} + +func (msg *XfrmEncapTmpl) Serialize() []byte { + return (*(*[SizeofXfrmEncapTmpl]byte)(unsafe.Pointer(msg)))[:] +} + +// struct xfrm_usersa_flush { +// __u8 proto; +// }; + +type XfrmUsersaFlush struct { + Proto uint8 +} + +func (msg *XfrmUsersaFlush) Len() int { + return SizeofXfrmUsersaFlush +} + +func DeserializeXfrmUsersaFlush(b []byte) *XfrmUsersaFlush { + return (*XfrmUsersaFlush)(unsafe.Pointer(&b[0:SizeofXfrmUsersaFlush][0])) +} + +func (msg *XfrmUsersaFlush) Serialize() []byte { + return (*(*[SizeofXfrmUsersaFlush]byte)(unsafe.Pointer(msg)))[:] +} + +// struct xfrm_replay_state_esn { +// unsigned int bmp_len; +// __u32 oseq; +// __u32 seq; +// __u32 oseq_hi; +// __u32 seq_hi; +// __u32 replay_window; +// __u32 bmp[0]; +// }; + +type XfrmReplayStateEsn struct { + BmpLen uint32 + OSeq uint32 + Seq uint32 + OSeqHi uint32 + SeqHi uint32 + ReplayWindow uint32 + Bmp []uint32 +} + +func (msg *XfrmReplayStateEsn) Serialize() []byte { + // We deliberately do not pass Bmp, as it gets set by the kernel. + return (*(*[SizeofXfrmReplayStateEsn]byte)(unsafe.Pointer(msg)))[:] +} diff --git a/vendor/github.com/vishvananda/netlink/order.go b/vendor/github.com/vishvananda/netlink/order.go new file mode 100644 index 000000000..e28e153a1 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/order.go @@ -0,0 +1,32 @@ +package netlink + +import ( + "encoding/binary" + + "github.com/vishvananda/netlink/nl" +) + +var ( + native = nl.NativeEndian() + networkOrder = binary.BigEndian +) + +func htonl(val uint32) []byte { + bytes := make([]byte, 4) + binary.BigEndian.PutUint32(bytes, val) + return bytes +} + +func htons(val uint16) []byte { + bytes := make([]byte, 2) + binary.BigEndian.PutUint16(bytes, val) + return bytes +} + +func ntohl(buf []byte) uint32 { + return binary.BigEndian.Uint32(buf) +} + +func ntohs(buf []byte) uint16 { + return binary.BigEndian.Uint16(buf) +} diff --git a/vendor/github.com/vishvananda/netlink/protinfo.go b/vendor/github.com/vishvananda/netlink/protinfo.go new file mode 100644 index 000000000..60b23b374 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/protinfo.go @@ -0,0 +1,62 @@ +package netlink + +import ( + "strings" +) + +// Protinfo represents bridge flags from netlink. +type Protinfo struct { + Hairpin bool + Guard bool + FastLeave bool + RootBlock bool + Learning bool + Flood bool + ProxyArp bool + ProxyArpWiFi bool +} + +// String returns a list of enabled flags +func (prot *Protinfo) String() string { + if prot == nil { + return "" + } + + var boolStrings []string + if prot.Hairpin { + boolStrings = append(boolStrings, "Hairpin") + } + if prot.Guard { + boolStrings = append(boolStrings, "Guard") + } + if prot.FastLeave { + boolStrings = append(boolStrings, "FastLeave") + } + if prot.RootBlock { + boolStrings = append(boolStrings, "RootBlock") + } + if prot.Learning { + boolStrings = append(boolStrings, "Learning") + } + if prot.Flood { + boolStrings = append(boolStrings, "Flood") + } + if prot.ProxyArp { + boolStrings = append(boolStrings, "ProxyArp") + } + if prot.ProxyArpWiFi { + boolStrings = append(boolStrings, "ProxyArpWiFi") + } + return strings.Join(boolStrings, " ") +} + +func boolToByte(x bool) []byte { + if x { + return []byte{1} + } + return []byte{0} +} + +func byteToBool(x byte) bool { + return uint8(x) != 0 +} diff --git a/vendor/github.com/vishvananda/netlink/protinfo_linux.go b/vendor/github.com/vishvananda/netlink/protinfo_linux.go new file mode 100644 index 000000000..15b65123c --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/protinfo_linux.go @@ -0,0 +1,74 @@ +package netlink + +import ( + "fmt" + "syscall" + + "github.com/vishvananda/netlink/nl" + "golang.org/x/sys/unix" +) + +func LinkGetProtinfo(link Link) (Protinfo, error) { + return pkgHandle.LinkGetProtinfo(link) +} + +func (h *Handle) LinkGetProtinfo(link Link) (Protinfo, error) { + base := link.Attrs() + h.ensureIndex(base) + var pi Protinfo + req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP) + msg := nl.NewIfInfomsg(unix.AF_BRIDGE) + req.AddData(msg) + msgs, err := req.Execute(unix.NETLINK_ROUTE, 0) + if err != nil { + return pi, err + } + + for _, m := range msgs { + ans := nl.DeserializeIfInfomsg(m) + if int(ans.Index) != base.Index { + continue + } + attrs, err := nl.ParseRouteAttr(m[ans.Len():]) + if err != nil { + return pi, err + } + for _, attr := range attrs { + if attr.Attr.Type != unix.IFLA_PROTINFO|unix.NLA_F_NESTED { + continue + } + infos, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return pi, err + } + pi = parseProtinfo(infos) + + return pi, nil + } + } + return pi, fmt.Errorf("Device with index %d not found", base.Index) +} + +func parseProtinfo(infos []syscall.NetlinkRouteAttr) (pi Protinfo) { + for _, info := range infos { + switch info.Attr.Type { + case nl.IFLA_BRPORT_MODE: + pi.Hairpin = byteToBool(info.Value[0]) + case nl.IFLA_BRPORT_GUARD: + pi.Guard = byteToBool(info.Value[0]) + case nl.IFLA_BRPORT_FAST_LEAVE: + pi.FastLeave = byteToBool(info.Value[0]) + case nl.IFLA_BRPORT_PROTECT: + pi.RootBlock = byteToBool(info.Value[0]) + case nl.IFLA_BRPORT_LEARNING: + pi.Learning = byteToBool(info.Value[0]) + case nl.IFLA_BRPORT_UNICAST_FLOOD: + pi.Flood = byteToBool(info.Value[0]) + case nl.IFLA_BRPORT_PROXYARP: + pi.ProxyArp = byteToBool(info.Value[0]) + case nl.IFLA_BRPORT_PROXYARP_WIFI: + pi.ProxyArpWiFi = byteToBool(info.Value[0]) + } + } + return +} diff --git a/vendor/github.com/vishvananda/netlink/qdisc.go b/vendor/github.com/vishvananda/netlink/qdisc.go new file mode 100644 index 000000000..f594c9c21 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/qdisc.go @@ -0,0 +1,366 @@ +package netlink + +import ( + "fmt" + "math" +) + +const ( + HANDLE_NONE = 0 + HANDLE_INGRESS = 0xFFFFFFF1 + HANDLE_CLSACT = HANDLE_INGRESS + HANDLE_ROOT = 0xFFFFFFFF + PRIORITY_MAP_LEN = 16 +) +const ( + HANDLE_MIN_INGRESS = 0xFFFFFFF2 + HANDLE_MIN_EGRESS = 0xFFFFFFF3 +) + +type Qdisc interface { + Attrs() *QdiscAttrs + Type() string +} + +// QdiscAttrs represents a netlink qdisc. A qdisc is associated with a link, +// has a handle, a parent and a refcnt. The root qdisc of a device should +// have parent == HANDLE_ROOT. +type QdiscAttrs struct { + LinkIndex int + Handle uint32 + Parent uint32 + Refcnt uint32 // read only +} + +func (q QdiscAttrs) String() string { + return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Refcnt: %d}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Refcnt) +} + +func MakeHandle(major, minor uint16) uint32 { + return (uint32(major) << 16) | uint32(minor) +} + +func MajorMinor(handle uint32) (uint16, uint16) { + return uint16((handle & 0xFFFF0000) >> 16), uint16(handle & 0x0000FFFFF) +} + +func HandleStr(handle uint32) string { + switch handle { + case HANDLE_NONE: + return "none" + case HANDLE_INGRESS: + return "ingress" + case HANDLE_ROOT: + return "root" + default: + major, minor := MajorMinor(handle) + return fmt.Sprintf("%x:%x", major, minor) + } +} + +func Percentage2u32(percentage float32) uint32 { + // FIXME this is most likely not the best way to convert from % to uint32 + if percentage == 100 { + return math.MaxUint32 + } + return uint32(math.MaxUint32 * (percentage / 100)) +} + +// PfifoFast is the default qdisc created by the kernel if one has not +// been defined for the interface +type PfifoFast struct { + QdiscAttrs + Bands uint8 + PriorityMap [PRIORITY_MAP_LEN]uint8 +} + +func (qdisc *PfifoFast) Attrs() *QdiscAttrs { + return &qdisc.QdiscAttrs +} + +func (qdisc *PfifoFast) Type() string { + return "pfifo_fast" +} + +// Prio is a basic qdisc that works just like PfifoFast +type Prio struct { + QdiscAttrs + Bands uint8 + PriorityMap [PRIORITY_MAP_LEN]uint8 +} + +func NewPrio(attrs QdiscAttrs) *Prio { + return &Prio{ + QdiscAttrs: attrs, + Bands: 3, + PriorityMap: [PRIORITY_MAP_LEN]uint8{1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, + } +} + +func (qdisc *Prio) Attrs() *QdiscAttrs { + return &qdisc.QdiscAttrs +} + +func (qdisc *Prio) Type() string { + return "prio" +} + +// Htb is a classful qdisc that rate limits based on tokens +type Htb struct { + QdiscAttrs + Version uint32 + Rate2Quantum uint32 + Defcls uint32 + Debug uint32 + DirectPkts uint32 +} + +func NewHtb(attrs QdiscAttrs) *Htb { + return &Htb{ + QdiscAttrs: attrs, + Version: 3, + Defcls: 0, + Rate2Quantum: 10, + Debug: 0, + DirectPkts: 0, + } +} + +func (qdisc *Htb) Attrs() *QdiscAttrs { + return &qdisc.QdiscAttrs +} + +func (qdisc *Htb) Type() string { + return "htb" +} + +// Netem is a classless qdisc that rate limits based on tokens + +type NetemQdiscAttrs struct { + Latency uint32 // in us + DelayCorr float32 // in % + Limit uint32 + Loss float32 // in % + LossCorr float32 // in % + Gap uint32 + Duplicate float32 // in % + DuplicateCorr float32 // in % + Jitter uint32 // in us + ReorderProb float32 // in % + ReorderCorr float32 // in % + CorruptProb float32 // in % + CorruptCorr float32 // in % +} + +func (q NetemQdiscAttrs) String() string { + return fmt.Sprintf( + "{Latency: %d, Limit: %d, Loss: %f, Gap: %d, Duplicate: %f, Jitter: %d}", + q.Latency, q.Limit, q.Loss, q.Gap, q.Duplicate, q.Jitter, + ) +} + +type Netem struct { + QdiscAttrs + Latency uint32 + DelayCorr uint32 + Limit uint32 + Loss uint32 + LossCorr uint32 + Gap uint32 + Duplicate uint32 + DuplicateCorr uint32 + Jitter uint32 + ReorderProb uint32 + ReorderCorr uint32 + CorruptProb uint32 + CorruptCorr uint32 +} + +func (netem *Netem) String() string { + return fmt.Sprintf( + "{Latency: %v, Limit: %v, Loss: %v, Gap: %v, Duplicate: %v, Jitter: %v}", + netem.Latency, netem.Limit, netem.Loss, netem.Gap, netem.Duplicate, netem.Jitter, + ) +} + +func (qdisc *Netem) Attrs() *QdiscAttrs { + return &qdisc.QdiscAttrs +} + +func (qdisc *Netem) Type() string { + return "netem" +} + +// Tbf is a classless qdisc that rate limits based on tokens +type Tbf struct { + QdiscAttrs + Rate uint64 + Limit uint32 + Buffer uint32 + Peakrate uint64 + Minburst uint32 + // TODO: handle other settings +} + +func (qdisc *Tbf) Attrs() *QdiscAttrs { + return &qdisc.QdiscAttrs +} + +func (qdisc *Tbf) Type() string { + return "tbf" +} + +// Ingress is a qdisc for adding ingress filters +type Ingress struct { + QdiscAttrs +} + +func (qdisc *Ingress) Attrs() *QdiscAttrs { + return &qdisc.QdiscAttrs +} + +func (qdisc *Ingress) Type() string { + return "ingress" +} + +// GenericQdisc qdiscs represent types that are not currently understood +// by this netlink library. +type GenericQdisc struct { + QdiscAttrs + QdiscType string +} + +func (qdisc *GenericQdisc) Attrs() *QdiscAttrs { + return &qdisc.QdiscAttrs +} + +func (qdisc *GenericQdisc) Type() string { + return qdisc.QdiscType +} + +type Hfsc struct { + QdiscAttrs + Defcls uint16 +} + +func NewHfsc(attrs QdiscAttrs) *Hfsc { + return &Hfsc{ + QdiscAttrs: attrs, + Defcls: 1, + } +} + +func (hfsc *Hfsc) Attrs() *QdiscAttrs { + return &hfsc.QdiscAttrs +} + +func (hfsc *Hfsc) Type() string { + return "hfsc" +} + +func (hfsc *Hfsc) String() string { + return fmt.Sprintf( + "{%v -- default: %d}", + hfsc.Attrs(), hfsc.Defcls, + ) +} + +// Fq is a classless packet scheduler meant to be mostly used for locally generated traffic. +type Fq struct { + QdiscAttrs + PacketLimit uint32 + FlowPacketLimit uint32 + // In bytes + Quantum uint32 + InitialQuantum uint32 + // called RateEnable under the hood + Pacing uint32 + FlowDefaultRate uint32 + FlowMaxRate uint32 + // called BucketsLog under the hood + Buckets uint32 + FlowRefillDelay uint32 + LowRateThreshold uint32 +} + +func (fq *Fq) String() string { + return fmt.Sprintf( + "{PacketLimit: %v, FlowPacketLimit: %v, Quantum: %v, InitialQuantum: %v, Pacing: %v, FlowDefaultRate: %v, FlowMaxRate: %v, Buckets: %v, FlowRefillDelay: %v, LowRateThreshold: %v}", + fq.PacketLimit, fq.FlowPacketLimit, fq.Quantum, fq.InitialQuantum, fq.Pacing, fq.FlowDefaultRate, fq.FlowMaxRate, fq.Buckets, fq.FlowRefillDelay, fq.LowRateThreshold, + ) +} + +func NewFq(attrs QdiscAttrs) *Fq { + return &Fq{ + QdiscAttrs: attrs, + Pacing: 1, + } +} + +func (qdisc *Fq) Attrs() *QdiscAttrs { + return &qdisc.QdiscAttrs +} + +func (qdisc *Fq) Type() string { + return "fq" +} + +// FQ_Codel (Fair Queuing Controlled Delay) is queuing discipline that combines Fair Queuing with the CoDel AQM scheme. +type FqCodel struct { + QdiscAttrs + Target uint32 + Limit uint32 + Interval uint32 + ECN uint32 + Flows uint32 + Quantum uint32 + CEThreshold uint32 + DropBatchSize uint32 + MemoryLimit uint32 +} + +func (fqcodel *FqCodel) String() string { + return fmt.Sprintf( + "{%v -- Target: %v, Limit: %v, Interval: %v, ECM: %v, Flows: %v, Quantum: %v}", + fqcodel.Attrs(), fqcodel.Target, fqcodel.Limit, fqcodel.Interval, fqcodel.ECN, fqcodel.Flows, fqcodel.Quantum, + ) +} + +func NewFqCodel(attrs QdiscAttrs) *FqCodel { + return &FqCodel{ + QdiscAttrs: attrs, + ECN: 1, + } +} + +func (qdisc *FqCodel) Attrs() *QdiscAttrs { + return &qdisc.QdiscAttrs +} + +func (qdisc *FqCodel) Type() string { + return "fq_codel" +} + +type Sfq struct { + QdiscAttrs + // TODO: Only the simplified options for SFQ are handled here. Support for the extended one can be added later. + Quantum uint8 + Perturb uint8 + Limit uint32 + Divisor uint8 +} + +func (sfq *Sfq) String() string { + return fmt.Sprintf( + "{%v -- Quantum: %v, Perturb: %v, Limit: %v, Divisor: %v}", + sfq.Attrs(), sfq.Quantum, sfq.Perturb, sfq.Limit, sfq.Divisor, + ) +} + +func (qdisc *Sfq) Attrs() *QdiscAttrs { + return &qdisc.QdiscAttrs +} + +func (qdisc *Sfq) Type() string { + return "sfq" +} diff --git a/vendor/github.com/vishvananda/netlink/qdisc_linux.go b/vendor/github.com/vishvananda/netlink/qdisc_linux.go new file mode 100644 index 000000000..edc4b726a --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/qdisc_linux.go @@ -0,0 +1,713 @@ +package netlink + +import ( + "fmt" + "io/ioutil" + "strconv" + "strings" + "syscall" + + "github.com/vishvananda/netlink/nl" + "golang.org/x/sys/unix" +) + +// NOTE function is here because it uses other linux functions +func NewNetem(attrs QdiscAttrs, nattrs NetemQdiscAttrs) *Netem { + var limit uint32 = 1000 + var lossCorr, delayCorr, duplicateCorr uint32 + var reorderProb, reorderCorr uint32 + var corruptProb, corruptCorr uint32 + + latency := nattrs.Latency + loss := Percentage2u32(nattrs.Loss) + gap := nattrs.Gap + duplicate := Percentage2u32(nattrs.Duplicate) + jitter := nattrs.Jitter + + // Correlation + if latency > 0 && jitter > 0 { + delayCorr = Percentage2u32(nattrs.DelayCorr) + } + if loss > 0 { + lossCorr = Percentage2u32(nattrs.LossCorr) + } + if duplicate > 0 { + duplicateCorr = Percentage2u32(nattrs.DuplicateCorr) + } + // FIXME should validate values(like loss/duplicate are percentages...) + latency = time2Tick(latency) + + if nattrs.Limit != 0 { + limit = nattrs.Limit + } + // Jitter is only value if latency is > 0 + if latency > 0 { + jitter = time2Tick(jitter) + } + + reorderProb = Percentage2u32(nattrs.ReorderProb) + reorderCorr = Percentage2u32(nattrs.ReorderCorr) + + if reorderProb > 0 { + // ERROR if lantency == 0 + if gap == 0 { + gap = 1 + } + } + + corruptProb = Percentage2u32(nattrs.CorruptProb) + corruptCorr = Percentage2u32(nattrs.CorruptCorr) + + return &Netem{ + QdiscAttrs: attrs, + Latency: latency, + DelayCorr: delayCorr, + Limit: limit, + Loss: loss, + LossCorr: lossCorr, + Gap: gap, + Duplicate: duplicate, + DuplicateCorr: duplicateCorr, + Jitter: jitter, + ReorderProb: reorderProb, + ReorderCorr: reorderCorr, + CorruptProb: corruptProb, + CorruptCorr: corruptCorr, + } +} + +// QdiscDel will delete a qdisc from the system. +// Equivalent to: `tc qdisc del $qdisc` +func QdiscDel(qdisc Qdisc) error { + return pkgHandle.QdiscDel(qdisc) +} + +// QdiscDel will delete a qdisc from the system. +// Equivalent to: `tc qdisc del $qdisc` +func (h *Handle) QdiscDel(qdisc Qdisc) error { + return h.qdiscModify(unix.RTM_DELQDISC, 0, qdisc) +} + +// QdiscChange will change a qdisc in place +// Equivalent to: `tc qdisc change $qdisc` +// The parent and handle MUST NOT be changed. +func QdiscChange(qdisc Qdisc) error { + return pkgHandle.QdiscChange(qdisc) +} + +// QdiscChange will change a qdisc in place +// Equivalent to: `tc qdisc change $qdisc` +// The parent and handle MUST NOT be changed. +func (h *Handle) QdiscChange(qdisc Qdisc) error { + return h.qdiscModify(unix.RTM_NEWQDISC, 0, qdisc) +} + +// QdiscReplace will replace a qdisc to the system. +// Equivalent to: `tc qdisc replace $qdisc` +// The handle MUST change. +func QdiscReplace(qdisc Qdisc) error { + return pkgHandle.QdiscReplace(qdisc) +} + +// QdiscReplace will replace a qdisc to the system. +// Equivalent to: `tc qdisc replace $qdisc` +// The handle MUST change. +func (h *Handle) QdiscReplace(qdisc Qdisc) error { + return h.qdiscModify( + unix.RTM_NEWQDISC, + unix.NLM_F_CREATE|unix.NLM_F_REPLACE, + qdisc) +} + +// QdiscAdd will add a qdisc to the system. +// Equivalent to: `tc qdisc add $qdisc` +func QdiscAdd(qdisc Qdisc) error { + return pkgHandle.QdiscAdd(qdisc) +} + +// QdiscAdd will add a qdisc to the system. +// Equivalent to: `tc qdisc add $qdisc` +func (h *Handle) QdiscAdd(qdisc Qdisc) error { + return h.qdiscModify( + unix.RTM_NEWQDISC, + unix.NLM_F_CREATE|unix.NLM_F_EXCL, + qdisc) +} + +func (h *Handle) qdiscModify(cmd, flags int, qdisc Qdisc) error { + req := h.newNetlinkRequest(cmd, flags|unix.NLM_F_ACK) + base := qdisc.Attrs() + msg := &nl.TcMsg{ + Family: nl.FAMILY_ALL, + Ifindex: int32(base.LinkIndex), + Handle: base.Handle, + Parent: base.Parent, + } + req.AddData(msg) + + // When deleting don't bother building the rest of the netlink payload + if cmd != unix.RTM_DELQDISC { + if err := qdiscPayload(req, qdisc); err != nil { + return err + } + } + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error { + + req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(qdisc.Type()))) + + options := nl.NewRtAttr(nl.TCA_OPTIONS, nil) + + switch qdisc := qdisc.(type) { + case *Prio: + tcmap := nl.TcPrioMap{ + Bands: int32(qdisc.Bands), + Priomap: qdisc.PriorityMap, + } + options = nl.NewRtAttr(nl.TCA_OPTIONS, tcmap.Serialize()) + case *Tbf: + opt := nl.TcTbfQopt{} + opt.Rate.Rate = uint32(qdisc.Rate) + opt.Peakrate.Rate = uint32(qdisc.Peakrate) + opt.Limit = qdisc.Limit + opt.Buffer = qdisc.Buffer + options.AddRtAttr(nl.TCA_TBF_PARMS, opt.Serialize()) + if qdisc.Rate >= uint64(1<<32) { + options.AddRtAttr(nl.TCA_TBF_RATE64, nl.Uint64Attr(qdisc.Rate)) + } + if qdisc.Peakrate >= uint64(1<<32) { + options.AddRtAttr(nl.TCA_TBF_PRATE64, nl.Uint64Attr(qdisc.Peakrate)) + } + if qdisc.Peakrate > 0 { + options.AddRtAttr(nl.TCA_TBF_PBURST, nl.Uint32Attr(qdisc.Minburst)) + } + case *Htb: + opt := nl.TcHtbGlob{} + opt.Version = qdisc.Version + opt.Rate2Quantum = qdisc.Rate2Quantum + opt.Defcls = qdisc.Defcls + // TODO: Handle Debug properly. For now default to 0 + opt.Debug = qdisc.Debug + opt.DirectPkts = qdisc.DirectPkts + options.AddRtAttr(nl.TCA_HTB_INIT, opt.Serialize()) + // options.AddRtAttr(nl.TCA_HTB_DIRECT_QLEN, opt.Serialize()) + case *Hfsc: + opt := nl.TcHfscOpt{} + opt.Defcls = qdisc.Defcls + options = nl.NewRtAttr(nl.TCA_OPTIONS, opt.Serialize()) + case *Netem: + opt := nl.TcNetemQopt{} + opt.Latency = qdisc.Latency + opt.Limit = qdisc.Limit + opt.Loss = qdisc.Loss + opt.Gap = qdisc.Gap + opt.Duplicate = qdisc.Duplicate + opt.Jitter = qdisc.Jitter + options = nl.NewRtAttr(nl.TCA_OPTIONS, opt.Serialize()) + // Correlation + corr := nl.TcNetemCorr{} + corr.DelayCorr = qdisc.DelayCorr + corr.LossCorr = qdisc.LossCorr + corr.DupCorr = qdisc.DuplicateCorr + + if corr.DelayCorr > 0 || corr.LossCorr > 0 || corr.DupCorr > 0 { + options.AddRtAttr(nl.TCA_NETEM_CORR, corr.Serialize()) + } + // Corruption + corruption := nl.TcNetemCorrupt{} + corruption.Probability = qdisc.CorruptProb + corruption.Correlation = qdisc.CorruptCorr + if corruption.Probability > 0 { + options.AddRtAttr(nl.TCA_NETEM_CORRUPT, corruption.Serialize()) + } + // Reorder + reorder := nl.TcNetemReorder{} + reorder.Probability = qdisc.ReorderProb + reorder.Correlation = qdisc.ReorderCorr + if reorder.Probability > 0 { + options.AddRtAttr(nl.TCA_NETEM_REORDER, reorder.Serialize()) + } + case *Ingress: + // ingress filters must use the proper handle + if qdisc.Attrs().Parent != HANDLE_INGRESS { + return fmt.Errorf("Ingress filters must set Parent to HANDLE_INGRESS") + } + case *FqCodel: + options.AddRtAttr(nl.TCA_FQ_CODEL_ECN, nl.Uint32Attr((uint32(qdisc.ECN)))) + if qdisc.Limit > 0 { + options.AddRtAttr(nl.TCA_FQ_CODEL_LIMIT, nl.Uint32Attr((uint32(qdisc.Limit)))) + } + if qdisc.Interval > 0 { + options.AddRtAttr(nl.TCA_FQ_CODEL_INTERVAL, nl.Uint32Attr((uint32(qdisc.Interval)))) + } + if qdisc.Flows > 0 { + options.AddRtAttr(nl.TCA_FQ_CODEL_FLOWS, nl.Uint32Attr((uint32(qdisc.Flows)))) + } + if qdisc.Quantum > 0 { + options.AddRtAttr(nl.TCA_FQ_CODEL_QUANTUM, nl.Uint32Attr((uint32(qdisc.Quantum)))) + } + if qdisc.CEThreshold > 0 { + options.AddRtAttr(nl.TCA_FQ_CODEL_CE_THRESHOLD, nl.Uint32Attr(qdisc.CEThreshold)) + } + if qdisc.DropBatchSize > 0 { + options.AddRtAttr(nl.TCA_FQ_CODEL_DROP_BATCH_SIZE, nl.Uint32Attr(qdisc.DropBatchSize)) + } + if qdisc.MemoryLimit > 0 { + options.AddRtAttr(nl.TCA_FQ_CODEL_MEMORY_LIMIT, nl.Uint32Attr(qdisc.MemoryLimit)) + } + case *Fq: + options.AddRtAttr(nl.TCA_FQ_RATE_ENABLE, nl.Uint32Attr((uint32(qdisc.Pacing)))) + + if qdisc.Buckets > 0 { + options.AddRtAttr(nl.TCA_FQ_BUCKETS_LOG, nl.Uint32Attr((uint32(qdisc.Buckets)))) + } + if qdisc.LowRateThreshold > 0 { + options.AddRtAttr(nl.TCA_FQ_LOW_RATE_THRESHOLD, nl.Uint32Attr((uint32(qdisc.LowRateThreshold)))) + } + if qdisc.Quantum > 0 { + options.AddRtAttr(nl.TCA_FQ_QUANTUM, nl.Uint32Attr((uint32(qdisc.Quantum)))) + } + if qdisc.InitialQuantum > 0 { + options.AddRtAttr(nl.TCA_FQ_INITIAL_QUANTUM, nl.Uint32Attr((uint32(qdisc.InitialQuantum)))) + } + if qdisc.FlowRefillDelay > 0 { + options.AddRtAttr(nl.TCA_FQ_FLOW_REFILL_DELAY, nl.Uint32Attr((uint32(qdisc.FlowRefillDelay)))) + } + if qdisc.FlowPacketLimit > 0 { + options.AddRtAttr(nl.TCA_FQ_FLOW_PLIMIT, nl.Uint32Attr((uint32(qdisc.FlowPacketLimit)))) + } + if qdisc.FlowMaxRate > 0 { + options.AddRtAttr(nl.TCA_FQ_FLOW_MAX_RATE, nl.Uint32Attr((uint32(qdisc.FlowMaxRate)))) + } + if qdisc.FlowDefaultRate > 0 { + options.AddRtAttr(nl.TCA_FQ_FLOW_DEFAULT_RATE, nl.Uint32Attr((uint32(qdisc.FlowDefaultRate)))) + } + case *Sfq: + opt := nl.TcSfqQoptV1{} + opt.TcSfqQopt.Quantum = qdisc.Quantum + opt.TcSfqQopt.Perturb = int32(qdisc.Perturb) + opt.TcSfqQopt.Limit = qdisc.Limit + opt.TcSfqQopt.Divisor = qdisc.Divisor + + options = nl.NewRtAttr(nl.TCA_OPTIONS, opt.Serialize()) + default: + options = nil + } + + if options != nil { + req.AddData(options) + } + return nil +} + +// QdiscList gets a list of qdiscs in the system. +// Equivalent to: `tc qdisc show`. +// The list can be filtered by link. +func QdiscList(link Link) ([]Qdisc, error) { + return pkgHandle.QdiscList(link) +} + +// QdiscList gets a list of qdiscs in the system. +// Equivalent to: `tc qdisc show`. +// The list can be filtered by link. +func (h *Handle) QdiscList(link Link) ([]Qdisc, error) { + req := h.newNetlinkRequest(unix.RTM_GETQDISC, unix.NLM_F_DUMP) + index := int32(0) + if link != nil { + base := link.Attrs() + h.ensureIndex(base) + index = int32(base.Index) + } + msg := &nl.TcMsg{ + Family: nl.FAMILY_ALL, + Ifindex: index, + } + req.AddData(msg) + + msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWQDISC) + if err != nil { + return nil, err + } + + var res []Qdisc + for _, m := range msgs { + msg := nl.DeserializeTcMsg(m) + + attrs, err := nl.ParseRouteAttr(m[msg.Len():]) + if err != nil { + return nil, err + } + + // skip qdiscs from other interfaces + if link != nil && msg.Ifindex != index { + continue + } + + base := QdiscAttrs{ + LinkIndex: int(msg.Ifindex), + Handle: msg.Handle, + Parent: msg.Parent, + Refcnt: msg.Info, + } + var qdisc Qdisc + qdiscType := "" + for _, attr := range attrs { + switch attr.Attr.Type { + case nl.TCA_KIND: + qdiscType = string(attr.Value[:len(attr.Value)-1]) + switch qdiscType { + case "pfifo_fast": + qdisc = &PfifoFast{} + case "prio": + qdisc = &Prio{} + case "tbf": + qdisc = &Tbf{} + case "ingress": + qdisc = &Ingress{} + case "htb": + qdisc = &Htb{} + case "fq": + qdisc = &Fq{} + case "hfsc": + qdisc = &Hfsc{} + case "fq_codel": + qdisc = &FqCodel{} + case "netem": + qdisc = &Netem{} + case "sfq": + qdisc = &Sfq{} + default: + qdisc = &GenericQdisc{QdiscType: qdiscType} + } + case nl.TCA_OPTIONS: + switch qdiscType { + case "pfifo_fast": + // pfifo returns TcPrioMap directly without wrapping it in rtattr + if err := parsePfifoFastData(qdisc, attr.Value); err != nil { + return nil, err + } + case "prio": + // prio returns TcPrioMap directly without wrapping it in rtattr + if err := parsePrioData(qdisc, attr.Value); err != nil { + return nil, err + } + case "tbf": + data, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return nil, err + } + if err := parseTbfData(qdisc, data); err != nil { + return nil, err + } + case "hfsc": + if err := parseHfscData(qdisc, attr.Value); err != nil { + return nil, err + } + case "htb": + data, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return nil, err + } + if err := parseHtbData(qdisc, data); err != nil { + return nil, err + } + case "fq": + data, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return nil, err + } + if err := parseFqData(qdisc, data); err != nil { + return nil, err + } + case "fq_codel": + data, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return nil, err + } + if err := parseFqCodelData(qdisc, data); err != nil { + return nil, err + } + case "netem": + if err := parseNetemData(qdisc, attr.Value); err != nil { + return nil, err + } + case "sfq": + if err := parseSfqData(qdisc, attr.Value); err != nil { + return nil, err + } + + // no options for ingress + } + } + } + *qdisc.Attrs() = base + res = append(res, qdisc) + } + + return res, nil +} + +func parsePfifoFastData(qdisc Qdisc, value []byte) error { + pfifo := qdisc.(*PfifoFast) + tcmap := nl.DeserializeTcPrioMap(value) + pfifo.PriorityMap = tcmap.Priomap + pfifo.Bands = uint8(tcmap.Bands) + return nil +} + +func parsePrioData(qdisc Qdisc, value []byte) error { + prio := qdisc.(*Prio) + tcmap := nl.DeserializeTcPrioMap(value) + prio.PriorityMap = tcmap.Priomap + prio.Bands = uint8(tcmap.Bands) + return nil +} + +func parseHtbData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { + native = nl.NativeEndian() + htb := qdisc.(*Htb) + for _, datum := range data { + switch datum.Attr.Type { + case nl.TCA_HTB_INIT: + opt := nl.DeserializeTcHtbGlob(datum.Value) + htb.Version = opt.Version + htb.Rate2Quantum = opt.Rate2Quantum + htb.Defcls = opt.Defcls + htb.Debug = opt.Debug + htb.DirectPkts = opt.DirectPkts + case nl.TCA_HTB_DIRECT_QLEN: + // TODO + //htb.DirectQlen = native.uint32(datum.Value) + } + } + return nil +} + +func parseFqCodelData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { + native = nl.NativeEndian() + fqCodel := qdisc.(*FqCodel) + for _, datum := range data { + + switch datum.Attr.Type { + case nl.TCA_FQ_CODEL_TARGET: + fqCodel.Target = native.Uint32(datum.Value) + case nl.TCA_FQ_CODEL_LIMIT: + fqCodel.Limit = native.Uint32(datum.Value) + case nl.TCA_FQ_CODEL_INTERVAL: + fqCodel.Interval = native.Uint32(datum.Value) + case nl.TCA_FQ_CODEL_ECN: + fqCodel.ECN = native.Uint32(datum.Value) + case nl.TCA_FQ_CODEL_FLOWS: + fqCodel.Flows = native.Uint32(datum.Value) + case nl.TCA_FQ_CODEL_QUANTUM: + fqCodel.Quantum = native.Uint32(datum.Value) + case nl.TCA_FQ_CODEL_CE_THRESHOLD: + fqCodel.CEThreshold = native.Uint32(datum.Value) + case nl.TCA_FQ_CODEL_DROP_BATCH_SIZE: + fqCodel.DropBatchSize = native.Uint32(datum.Value) + case nl.TCA_FQ_CODEL_MEMORY_LIMIT: + fqCodel.MemoryLimit = native.Uint32(datum.Value) + } + } + return nil +} + +func parseHfscData(qdisc Qdisc, data []byte) error { + Hfsc := qdisc.(*Hfsc) + native = nl.NativeEndian() + Hfsc.Defcls = native.Uint16(data) + return nil +} + +func parseFqData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { + native = nl.NativeEndian() + fq := qdisc.(*Fq) + for _, datum := range data { + switch datum.Attr.Type { + case nl.TCA_FQ_BUCKETS_LOG: + fq.Buckets = native.Uint32(datum.Value) + case nl.TCA_FQ_LOW_RATE_THRESHOLD: + fq.LowRateThreshold = native.Uint32(datum.Value) + case nl.TCA_FQ_QUANTUM: + fq.Quantum = native.Uint32(datum.Value) + case nl.TCA_FQ_RATE_ENABLE: + fq.Pacing = native.Uint32(datum.Value) + case nl.TCA_FQ_INITIAL_QUANTUM: + fq.InitialQuantum = native.Uint32(datum.Value) + case nl.TCA_FQ_ORPHAN_MASK: + // TODO + case nl.TCA_FQ_FLOW_REFILL_DELAY: + fq.FlowRefillDelay = native.Uint32(datum.Value) + case nl.TCA_FQ_FLOW_PLIMIT: + fq.FlowPacketLimit = native.Uint32(datum.Value) + case nl.TCA_FQ_PLIMIT: + fq.PacketLimit = native.Uint32(datum.Value) + case nl.TCA_FQ_FLOW_MAX_RATE: + fq.FlowMaxRate = native.Uint32(datum.Value) + case nl.TCA_FQ_FLOW_DEFAULT_RATE: + fq.FlowDefaultRate = native.Uint32(datum.Value) + } + } + return nil +} + +func parseNetemData(qdisc Qdisc, value []byte) error { + netem := qdisc.(*Netem) + opt := nl.DeserializeTcNetemQopt(value) + netem.Latency = opt.Latency + netem.Limit = opt.Limit + netem.Loss = opt.Loss + netem.Gap = opt.Gap + netem.Duplicate = opt.Duplicate + netem.Jitter = opt.Jitter + data, err := nl.ParseRouteAttr(value[nl.SizeofTcNetemQopt:]) + if err != nil { + return err + } + for _, datum := range data { + switch datum.Attr.Type { + case nl.TCA_NETEM_CORR: + opt := nl.DeserializeTcNetemCorr(datum.Value) + netem.DelayCorr = opt.DelayCorr + netem.LossCorr = opt.LossCorr + netem.DuplicateCorr = opt.DupCorr + case nl.TCA_NETEM_CORRUPT: + opt := nl.DeserializeTcNetemCorrupt(datum.Value) + netem.CorruptProb = opt.Probability + netem.CorruptCorr = opt.Correlation + case nl.TCA_NETEM_REORDER: + opt := nl.DeserializeTcNetemReorder(datum.Value) + netem.ReorderProb = opt.Probability + netem.ReorderCorr = opt.Correlation + } + } + return nil +} + +func parseTbfData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { + native = nl.NativeEndian() + tbf := qdisc.(*Tbf) + for _, datum := range data { + switch datum.Attr.Type { + case nl.TCA_TBF_PARMS: + opt := nl.DeserializeTcTbfQopt(datum.Value) + tbf.Rate = uint64(opt.Rate.Rate) + tbf.Peakrate = uint64(opt.Peakrate.Rate) + tbf.Limit = opt.Limit + tbf.Buffer = opt.Buffer + case nl.TCA_TBF_RATE64: + tbf.Rate = native.Uint64(datum.Value[0:8]) + case nl.TCA_TBF_PRATE64: + tbf.Peakrate = native.Uint64(datum.Value[0:8]) + case nl.TCA_TBF_PBURST: + tbf.Minburst = native.Uint32(datum.Value[0:4]) + } + } + return nil +} + +func parseSfqData(qdisc Qdisc, value []byte) error { + sfq := qdisc.(*Sfq) + opt := nl.DeserializeTcSfqQoptV1(value) + sfq.Quantum = opt.TcSfqQopt.Quantum + sfq.Perturb = uint8(opt.TcSfqQopt.Perturb) + sfq.Limit = opt.TcSfqQopt.Limit + sfq.Divisor = opt.TcSfqQopt.Divisor + + return nil +} + +const ( + TIME_UNITS_PER_SEC = 1000000 +) + +var ( + tickInUsec float64 + clockFactor float64 + hz float64 +) + +func initClock() { + data, err := ioutil.ReadFile("/proc/net/psched") + if err != nil { + return + } + parts := strings.Split(strings.TrimSpace(string(data)), " ") + if len(parts) < 4 { + return + } + var vals [4]uint64 + for i := range vals { + val, err := strconv.ParseUint(parts[i], 16, 32) + if err != nil { + return + } + vals[i] = val + } + // compatibility + if vals[2] == 1000000000 { + vals[0] = vals[1] + } + clockFactor = float64(vals[2]) / TIME_UNITS_PER_SEC + tickInUsec = float64(vals[0]) / float64(vals[1]) * clockFactor + if vals[2] == 1000000 { + // ref https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/lib/utils.c#n963 + hz = float64(vals[3]) + } else { + hz = 100 + } +} + +func TickInUsec() float64 { + if tickInUsec == 0.0 { + initClock() + } + return tickInUsec +} + +func ClockFactor() float64 { + if clockFactor == 0.0 { + initClock() + } + return clockFactor +} + +func Hz() float64 { + if hz == 0.0 { + initClock() + } + return hz +} + +func time2Tick(time uint32) uint32 { + return uint32(float64(time) * TickInUsec()) +} + +func tick2Time(tick uint32) uint32 { + return uint32(float64(tick) / TickInUsec()) +} + +func time2Ktime(time uint32) uint32 { + return uint32(float64(time) * ClockFactor()) +} + +func ktime2Time(ktime uint32) uint32 { + return uint32(float64(ktime) / ClockFactor()) +} + +func burst(rate uint64, buffer uint32) uint32 { + return uint32(float64(rate) * float64(tick2Time(buffer)) / TIME_UNITS_PER_SEC) +} + +func latency(rate uint64, limit, buffer uint32) float64 { + return TIME_UNITS_PER_SEC*(float64(limit)/float64(rate)) - float64(tick2Time(buffer)) +} + +func Xmittime(rate uint64, size uint32) uint32 { + // https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/tc/tc_core.c#n62 + return time2Tick(uint32(TIME_UNITS_PER_SEC * (float64(size) / float64(rate)))) +} diff --git a/vendor/github.com/vishvananda/netlink/rdma_link_linux.go b/vendor/github.com/vishvananda/netlink/rdma_link_linux.go new file mode 100644 index 000000000..ff014ca4c --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/rdma_link_linux.go @@ -0,0 +1,280 @@ +package netlink + +import ( + "bytes" + "encoding/binary" + "fmt" + "net" + + "github.com/vishvananda/netlink/nl" + "golang.org/x/sys/unix" +) + +// LinkAttrs represents data shared by most link types +type RdmaLinkAttrs struct { + Index uint32 + Name string + FirmwareVersion string + NodeGuid string + SysImageGuid string +} + +// Link represents a rdma device from netlink. +type RdmaLink struct { + Attrs RdmaLinkAttrs +} + +func getProtoField(clientType int, op int) int { + return ((clientType << nl.RDMA_NL_GET_CLIENT_SHIFT) | op) +} + +func uint64ToGuidString(guid uint64) string { + //Convert to byte array + sysGuidBytes := new(bytes.Buffer) + binary.Write(sysGuidBytes, binary.LittleEndian, guid) + + //Convert to HardwareAddr + sysGuidNet := net.HardwareAddr(sysGuidBytes.Bytes()) + + //Get the String + return sysGuidNet.String() +} + +func executeOneGetRdmaLink(data []byte) (*RdmaLink, error) { + + link := RdmaLink{} + + reader := bytes.NewReader(data) + for reader.Len() >= 4 { + _, attrType, len, value := parseNfAttrTLV(reader) + + switch attrType { + case nl.RDMA_NLDEV_ATTR_DEV_INDEX: + var Index uint32 + r := bytes.NewReader(value) + binary.Read(r, nl.NativeEndian(), &Index) + link.Attrs.Index = Index + case nl.RDMA_NLDEV_ATTR_DEV_NAME: + link.Attrs.Name = string(value[0 : len-1]) + case nl.RDMA_NLDEV_ATTR_FW_VERSION: + link.Attrs.FirmwareVersion = string(value[0 : len-1]) + case nl.RDMA_NLDEV_ATTR_NODE_GUID: + var guid uint64 + r := bytes.NewReader(value) + binary.Read(r, nl.NativeEndian(), &guid) + link.Attrs.NodeGuid = uint64ToGuidString(guid) + case nl.RDMA_NLDEV_ATTR_SYS_IMAGE_GUID: + var sysGuid uint64 + r := bytes.NewReader(value) + binary.Read(r, nl.NativeEndian(), &sysGuid) + link.Attrs.SysImageGuid = uint64ToGuidString(sysGuid) + } + if (len % 4) != 0 { + // Skip pad bytes + reader.Seek(int64(4-(len%4)), seekCurrent) + } + } + return &link, nil +} + +func execRdmaSetLink(req *nl.NetlinkRequest) error { + + _, err := req.Execute(unix.NETLINK_RDMA, 0) + return err +} + +// RdmaLinkList gets a list of RDMA link devices. +// Equivalent to: `rdma dev show` +func RdmaLinkList() ([]*RdmaLink, error) { + return pkgHandle.RdmaLinkList() +} + +// RdmaLinkList gets a list of RDMA link devices. +// Equivalent to: `rdma dev show` +func (h *Handle) RdmaLinkList() ([]*RdmaLink, error) { + proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_GET) + req := h.newNetlinkRequest(proto, unix.NLM_F_ACK|unix.NLM_F_DUMP) + + msgs, err := req.Execute(unix.NETLINK_RDMA, 0) + if err != nil { + return nil, err + } + + var res []*RdmaLink + for _, m := range msgs { + link, err := executeOneGetRdmaLink(m) + if err != nil { + return nil, err + } + res = append(res, link) + } + + return res, nil +} + +// RdmaLinkByName finds a link by name and returns a pointer to the object if +// found and nil error, otherwise returns error code. +func RdmaLinkByName(name string) (*RdmaLink, error) { + return pkgHandle.RdmaLinkByName(name) +} + +// RdmaLinkByName finds a link by name and returns a pointer to the object if +// found and nil error, otherwise returns error code. +func (h *Handle) RdmaLinkByName(name string) (*RdmaLink, error) { + links, err := h.RdmaLinkList() + if err != nil { + return nil, err + } + for _, link := range links { + if link.Attrs.Name == name { + return link, nil + } + } + return nil, fmt.Errorf("Rdma device %v not found", name) +} + +// RdmaLinkSetName sets the name of the rdma link device. Return nil on success +// or error otherwise. +// Equivalent to: `rdma dev set $old_devname name $name` +func RdmaLinkSetName(link *RdmaLink, name string) error { + return pkgHandle.RdmaLinkSetName(link, name) +} + +// RdmaLinkSetName sets the name of the rdma link device. Return nil on success +// or error otherwise. +// Equivalent to: `rdma dev set $old_devname name $name` +func (h *Handle) RdmaLinkSetName(link *RdmaLink, name string) error { + proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_SET) + req := h.newNetlinkRequest(proto, unix.NLM_F_ACK) + + b := make([]byte, 4) + native.PutUint32(b, uint32(link.Attrs.Index)) + data := nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_DEV_INDEX, b) + req.AddData(data) + + b = make([]byte, len(name)+1) + copy(b, name) + data = nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_DEV_NAME, b) + req.AddData(data) + + return execRdmaSetLink(req) +} + +func netnsModeToString(mode uint8) string { + switch mode { + case 0: + return "exclusive" + case 1: + return "shared" + default: + return "unknown" + } +} + +func executeOneGetRdmaNetnsMode(data []byte) (string, error) { + reader := bytes.NewReader(data) + for reader.Len() >= 4 { + _, attrType, len, value := parseNfAttrTLV(reader) + + switch attrType { + case nl.RDMA_NLDEV_SYS_ATTR_NETNS_MODE: + var mode uint8 + r := bytes.NewReader(value) + binary.Read(r, nl.NativeEndian(), &mode) + return netnsModeToString(mode), nil + } + if (len % 4) != 0 { + // Skip pad bytes + reader.Seek(int64(4-(len%4)), seekCurrent) + } + } + return "", fmt.Errorf("Invalid netns mode") +} + +// RdmaSystemGetNetnsMode gets the net namespace mode for RDMA subsystem +// Returns mode string and error status as nil on success or returns error +// otherwise. +// Equivalent to: `rdma system show netns' +func RdmaSystemGetNetnsMode() (string, error) { + return pkgHandle.RdmaSystemGetNetnsMode() +} + +// RdmaSystemGetNetnsMode gets the net namespace mode for RDMA subsystem +// Returns mode string and error status as nil on success or returns error +// otherwise. +// Equivalent to: `rdma system show netns' +func (h *Handle) RdmaSystemGetNetnsMode() (string, error) { + + proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_SYS_GET) + req := h.newNetlinkRequest(proto, unix.NLM_F_ACK) + + msgs, err := req.Execute(unix.NETLINK_RDMA, 0) + if err != nil { + return "", err + } + if len(msgs) == 0 { + return "", fmt.Errorf("No valid response from kernel") + } + return executeOneGetRdmaNetnsMode(msgs[0]) +} + +func netnsModeStringToUint8(mode string) (uint8, error) { + switch mode { + case "exclusive": + return 0, nil + case "shared": + return 1, nil + default: + return 0, fmt.Errorf("Invalid mode; %q", mode) + } +} + +// RdmaSystemSetNetnsMode sets the net namespace mode for RDMA subsystem +// Returns nil on success or appropriate error code. +// Equivalent to: `rdma system set netns { shared | exclusive }' +func RdmaSystemSetNetnsMode(NewMode string) error { + return pkgHandle.RdmaSystemSetNetnsMode(NewMode) +} + +// RdmaSystemSetNetnsMode sets the net namespace mode for RDMA subsystem +// Returns nil on success or appropriate error code. +// Equivalent to: `rdma system set netns { shared | exclusive }' +func (h *Handle) RdmaSystemSetNetnsMode(NewMode string) error { + value, err := netnsModeStringToUint8(NewMode) + if err != nil { + return err + } + + proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_SYS_SET) + req := h.newNetlinkRequest(proto, unix.NLM_F_ACK) + + data := nl.NewRtAttr(nl.RDMA_NLDEV_SYS_ATTR_NETNS_MODE, []byte{value}) + req.AddData(data) + + _, err = req.Execute(unix.NETLINK_RDMA, 0) + return err +} + +// RdmaLinkSetNsFd puts the RDMA device into a new network namespace. The +// fd must be an open file descriptor to a network namespace. +// Similar to: `rdma dev set $dev netns $ns` +func RdmaLinkSetNsFd(link *RdmaLink, fd uint32) error { + return pkgHandle.RdmaLinkSetNsFd(link, fd) +} + +// RdmaLinkSetNsFd puts the RDMA device into a new network namespace. The +// fd must be an open file descriptor to a network namespace. +// Similar to: `rdma dev set $dev netns $ns` +func (h *Handle) RdmaLinkSetNsFd(link *RdmaLink, fd uint32) error { + proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_SET) + req := h.newNetlinkRequest(proto, unix.NLM_F_ACK) + + data := nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_DEV_INDEX, + nl.Uint32Attr(link.Attrs.Index)) + req.AddData(data) + + data = nl.NewRtAttr(nl.RDMA_NLDEV_NET_NS_FD, nl.Uint32Attr(fd)) + req.AddData(data) + + return execRdmaSetLink(req) +} diff --git a/vendor/github.com/vishvananda/netlink/route.go b/vendor/github.com/vishvananda/netlink/route.go new file mode 100644 index 000000000..845f41808 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/route.go @@ -0,0 +1,205 @@ +package netlink + +import ( + "fmt" + "net" + "strings" +) + +// Scope is an enum representing a route scope. +type Scope uint8 + +type NextHopFlag int + +type Destination interface { + Family() int + Decode([]byte) error + Encode() ([]byte, error) + String() string + Equal(Destination) bool +} + +type Encap interface { + Type() int + Decode([]byte) error + Encode() ([]byte, error) + String() string + Equal(Encap) bool +} + +//Protocol describe what was the originator of the route +type RouteProtocol int + +// Route represents a netlink route. +type Route struct { + LinkIndex int + ILinkIndex int + Scope Scope + Dst *net.IPNet + Src net.IP + Gw net.IP + MultiPath []*NexthopInfo + Protocol RouteProtocol + Priority int + Table int + Type int + Tos int + Flags int + MPLSDst *int + NewDst Destination + Encap Encap + Via Destination + MTU int + Window int + Rtt int + RttVar int + Ssthresh int + Cwnd int + AdvMSS int + Reordering int + Hoplimit int + InitCwnd int + Features int + RtoMin int + InitRwnd int + QuickACK int + Congctl string + FastOpenNoCookie int +} + +func (r Route) String() string { + elems := []string{} + if len(r.MultiPath) == 0 { + elems = append(elems, fmt.Sprintf("Ifindex: %d", r.LinkIndex)) + } + if r.MPLSDst != nil { + elems = append(elems, fmt.Sprintf("Dst: %d", r.MPLSDst)) + } else { + elems = append(elems, fmt.Sprintf("Dst: %s", r.Dst)) + } + if r.NewDst != nil { + elems = append(elems, fmt.Sprintf("NewDst: %s", r.NewDst)) + } + if r.Encap != nil { + elems = append(elems, fmt.Sprintf("Encap: %s", r.Encap)) + } + if r.Via != nil { + elems = append(elems, fmt.Sprintf("Via: %s", r.Via)) + } + elems = append(elems, fmt.Sprintf("Src: %s", r.Src)) + if len(r.MultiPath) > 0 { + elems = append(elems, fmt.Sprintf("Gw: %s", r.MultiPath)) + } else { + elems = append(elems, fmt.Sprintf("Gw: %s", r.Gw)) + } + elems = append(elems, fmt.Sprintf("Flags: %s", r.ListFlags())) + elems = append(elems, fmt.Sprintf("Table: %d", r.Table)) + return fmt.Sprintf("{%s}", strings.Join(elems, " ")) +} + +func (r Route) Equal(x Route) bool { + return r.LinkIndex == x.LinkIndex && + r.ILinkIndex == x.ILinkIndex && + r.Scope == x.Scope && + ipNetEqual(r.Dst, x.Dst) && + r.Src.Equal(x.Src) && + r.Gw.Equal(x.Gw) && + nexthopInfoSlice(r.MultiPath).Equal(x.MultiPath) && + r.Protocol == x.Protocol && + r.Priority == x.Priority && + r.Table == x.Table && + r.Type == x.Type && + r.Tos == x.Tos && + r.Hoplimit == x.Hoplimit && + r.Flags == x.Flags && + (r.MPLSDst == x.MPLSDst || (r.MPLSDst != nil && x.MPLSDst != nil && *r.MPLSDst == *x.MPLSDst)) && + (r.NewDst == x.NewDst || (r.NewDst != nil && r.NewDst.Equal(x.NewDst))) && + (r.Via == x.Via || (r.Via != nil && r.Via.Equal(x.Via))) && + (r.Encap == x.Encap || (r.Encap != nil && r.Encap.Equal(x.Encap))) +} + +func (r *Route) SetFlag(flag NextHopFlag) { + r.Flags |= int(flag) +} + +func (r *Route) ClearFlag(flag NextHopFlag) { + r.Flags &^= int(flag) +} + +type flagString struct { + f NextHopFlag + s string +} + +// RouteUpdate is sent when a route changes - type is RTM_NEWROUTE or RTM_DELROUTE +type RouteUpdate struct { + Type uint16 + Route +} + +type NexthopInfo struct { + LinkIndex int + Hops int + Gw net.IP + Flags int + NewDst Destination + Encap Encap + Via Destination +} + +func (n *NexthopInfo) String() string { + elems := []string{} + elems = append(elems, fmt.Sprintf("Ifindex: %d", n.LinkIndex)) + if n.NewDst != nil { + elems = append(elems, fmt.Sprintf("NewDst: %s", n.NewDst)) + } + if n.Encap != nil { + elems = append(elems, fmt.Sprintf("Encap: %s", n.Encap)) + } + if n.Via != nil { + elems = append(elems, fmt.Sprintf("Via: %s", n.Via)) + } + elems = append(elems, fmt.Sprintf("Weight: %d", n.Hops+1)) + elems = append(elems, fmt.Sprintf("Gw: %s", n.Gw)) + elems = append(elems, fmt.Sprintf("Flags: %s", n.ListFlags())) + return fmt.Sprintf("{%s}", strings.Join(elems, " ")) +} + +func (n NexthopInfo) Equal(x NexthopInfo) bool { + return n.LinkIndex == x.LinkIndex && + n.Hops == x.Hops && + n.Gw.Equal(x.Gw) && + n.Flags == x.Flags && + (n.NewDst == x.NewDst || (n.NewDst != nil && n.NewDst.Equal(x.NewDst))) && + (n.Encap == x.Encap || (n.Encap != nil && n.Encap.Equal(x.Encap))) +} + +type nexthopInfoSlice []*NexthopInfo + +func (n nexthopInfoSlice) Equal(x []*NexthopInfo) bool { + if len(n) != len(x) { + return false + } + for i := range n { + if n[i] == nil || x[i] == nil { + return false + } + if !n[i].Equal(*x[i]) { + return false + } + } + return true +} + +// ipNetEqual returns true iff both IPNet are equal +func ipNetEqual(ipn1 *net.IPNet, ipn2 *net.IPNet) bool { + if ipn1 == ipn2 { + return true + } + if ipn1 == nil || ipn2 == nil { + return false + } + m1, _ := ipn1.Mask.Size() + m2, _ := ipn2.Mask.Size() + return m1 == m2 && ipn1.IP.Equal(ipn2.IP) +} diff --git a/vendor/github.com/vishvananda/netlink/route_linux.go b/vendor/github.com/vishvananda/netlink/route_linux.go new file mode 100644 index 000000000..32641cb0d --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/route_linux.go @@ -0,0 +1,1390 @@ +package netlink + +import ( + "bytes" + "encoding/binary" + "fmt" + "net" + "strconv" + "strings" + "syscall" + + "github.com/vishvananda/netlink/nl" + "github.com/vishvananda/netns" + "golang.org/x/sys/unix" +) + +// RtAttr is shared so it is in netlink_linux.go + +const ( + SCOPE_UNIVERSE Scope = unix.RT_SCOPE_UNIVERSE + SCOPE_SITE Scope = unix.RT_SCOPE_SITE + SCOPE_LINK Scope = unix.RT_SCOPE_LINK + SCOPE_HOST Scope = unix.RT_SCOPE_HOST + SCOPE_NOWHERE Scope = unix.RT_SCOPE_NOWHERE +) + +func (s Scope) String() string { + switch s { + case SCOPE_UNIVERSE: + return "universe" + case SCOPE_SITE: + return "site" + case SCOPE_LINK: + return "link" + case SCOPE_HOST: + return "host" + case SCOPE_NOWHERE: + return "nowhere" + default: + return "unknown" + } +} + +const ( + RT_FILTER_PROTOCOL uint64 = 1 << (1 + iota) + RT_FILTER_SCOPE + RT_FILTER_TYPE + RT_FILTER_TOS + RT_FILTER_IIF + RT_FILTER_OIF + RT_FILTER_DST + RT_FILTER_SRC + RT_FILTER_GW + RT_FILTER_TABLE + RT_FILTER_HOPLIMIT + RT_FILTER_PRIORITY + RT_FILTER_MARK + RT_FILTER_MASK +) + +const ( + FLAG_ONLINK NextHopFlag = unix.RTNH_F_ONLINK + FLAG_PERVASIVE NextHopFlag = unix.RTNH_F_PERVASIVE +) + +var testFlags = []flagString{ + {f: FLAG_ONLINK, s: "onlink"}, + {f: FLAG_PERVASIVE, s: "pervasive"}, +} + +func listFlags(flag int) []string { + var flags []string + for _, tf := range testFlags { + if flag&int(tf.f) != 0 { + flags = append(flags, tf.s) + } + } + return flags +} + +func (r *Route) ListFlags() []string { + return listFlags(r.Flags) +} + +func (n *NexthopInfo) ListFlags() []string { + return listFlags(n.Flags) +} + +type MPLSDestination struct { + Labels []int +} + +func (d *MPLSDestination) Family() int { + return nl.FAMILY_MPLS +} + +func (d *MPLSDestination) Decode(buf []byte) error { + d.Labels = nl.DecodeMPLSStack(buf) + return nil +} + +func (d *MPLSDestination) Encode() ([]byte, error) { + return nl.EncodeMPLSStack(d.Labels...), nil +} + +func (d *MPLSDestination) String() string { + s := make([]string, 0, len(d.Labels)) + for _, l := range d.Labels { + s = append(s, fmt.Sprintf("%d", l)) + } + return strings.Join(s, "/") +} + +func (d *MPLSDestination) Equal(x Destination) bool { + o, ok := x.(*MPLSDestination) + if !ok { + return false + } + if d == nil && o == nil { + return true + } + if d == nil || o == nil { + return false + } + if d.Labels == nil && o.Labels == nil { + return true + } + if d.Labels == nil || o.Labels == nil { + return false + } + if len(d.Labels) != len(o.Labels) { + return false + } + for i := range d.Labels { + if d.Labels[i] != o.Labels[i] { + return false + } + } + return true +} + +type MPLSEncap struct { + Labels []int +} + +func (e *MPLSEncap) Type() int { + return nl.LWTUNNEL_ENCAP_MPLS +} + +func (e *MPLSEncap) Decode(buf []byte) error { + if len(buf) < 4 { + return fmt.Errorf("lack of bytes") + } + native := nl.NativeEndian() + l := native.Uint16(buf) + if len(buf) < int(l) { + return fmt.Errorf("lack of bytes") + } + buf = buf[:l] + typ := native.Uint16(buf[2:]) + if typ != nl.MPLS_IPTUNNEL_DST { + return fmt.Errorf("unknown MPLS Encap Type: %d", typ) + } + e.Labels = nl.DecodeMPLSStack(buf[4:]) + return nil +} + +func (e *MPLSEncap) Encode() ([]byte, error) { + s := nl.EncodeMPLSStack(e.Labels...) + native := nl.NativeEndian() + hdr := make([]byte, 4) + native.PutUint16(hdr, uint16(len(s)+4)) + native.PutUint16(hdr[2:], nl.MPLS_IPTUNNEL_DST) + return append(hdr, s...), nil +} + +func (e *MPLSEncap) String() string { + s := make([]string, 0, len(e.Labels)) + for _, l := range e.Labels { + s = append(s, fmt.Sprintf("%d", l)) + } + return strings.Join(s, "/") +} + +func (e *MPLSEncap) Equal(x Encap) bool { + o, ok := x.(*MPLSEncap) + if !ok { + return false + } + if e == nil && o == nil { + return true + } + if e == nil || o == nil { + return false + } + if e.Labels == nil && o.Labels == nil { + return true + } + if e.Labels == nil || o.Labels == nil { + return false + } + if len(e.Labels) != len(o.Labels) { + return false + } + for i := range e.Labels { + if e.Labels[i] != o.Labels[i] { + return false + } + } + return true +} + +// SEG6 definitions +type SEG6Encap struct { + Mode int + Segments []net.IP +} + +func (e *SEG6Encap) Type() int { + return nl.LWTUNNEL_ENCAP_SEG6 +} +func (e *SEG6Encap) Decode(buf []byte) error { + if len(buf) < 4 { + return fmt.Errorf("lack of bytes") + } + native := nl.NativeEndian() + // Get Length(l) & Type(typ) : 2 + 2 bytes + l := native.Uint16(buf) + if len(buf) < int(l) { + return fmt.Errorf("lack of bytes") + } + buf = buf[:l] // make sure buf size upper limit is Length + typ := native.Uint16(buf[2:]) + // LWTUNNEL_ENCAP_SEG6 has only one attr type SEG6_IPTUNNEL_SRH + if typ != nl.SEG6_IPTUNNEL_SRH { + return fmt.Errorf("unknown SEG6 Type: %d", typ) + } + + var err error + e.Mode, e.Segments, err = nl.DecodeSEG6Encap(buf[4:]) + + return err +} +func (e *SEG6Encap) Encode() ([]byte, error) { + s, err := nl.EncodeSEG6Encap(e.Mode, e.Segments) + native := nl.NativeEndian() + hdr := make([]byte, 4) + native.PutUint16(hdr, uint16(len(s)+4)) + native.PutUint16(hdr[2:], nl.SEG6_IPTUNNEL_SRH) + return append(hdr, s...), err +} +func (e *SEG6Encap) String() string { + segs := make([]string, 0, len(e.Segments)) + // append segment backwards (from n to 0) since seg#0 is the last segment. + for i := len(e.Segments); i > 0; i-- { + segs = append(segs, fmt.Sprintf("%s", e.Segments[i-1])) + } + str := fmt.Sprintf("mode %s segs %d [ %s ]", nl.SEG6EncapModeString(e.Mode), + len(e.Segments), strings.Join(segs, " ")) + return str +} +func (e *SEG6Encap) Equal(x Encap) bool { + o, ok := x.(*SEG6Encap) + if !ok { + return false + } + if e == o { + return true + } + if e == nil || o == nil { + return false + } + if e.Mode != o.Mode { + return false + } + if len(e.Segments) != len(o.Segments) { + return false + } + for i := range e.Segments { + if !e.Segments[i].Equal(o.Segments[i]) { + return false + } + } + return true +} + +// SEG6LocalEncap definitions +type SEG6LocalEncap struct { + Flags [nl.SEG6_LOCAL_MAX]bool + Action int + Segments []net.IP // from SRH in seg6_local_lwt + Table int // table id for End.T and End.DT6 + InAddr net.IP + In6Addr net.IP + Iif int + Oif int +} + +func (e *SEG6LocalEncap) Type() int { + return nl.LWTUNNEL_ENCAP_SEG6_LOCAL +} +func (e *SEG6LocalEncap) Decode(buf []byte) error { + attrs, err := nl.ParseRouteAttr(buf) + if err != nil { + return err + } + native := nl.NativeEndian() + for _, attr := range attrs { + switch attr.Attr.Type { + case nl.SEG6_LOCAL_ACTION: + e.Action = int(native.Uint32(attr.Value[0:4])) + e.Flags[nl.SEG6_LOCAL_ACTION] = true + case nl.SEG6_LOCAL_SRH: + e.Segments, err = nl.DecodeSEG6Srh(attr.Value[:]) + e.Flags[nl.SEG6_LOCAL_SRH] = true + case nl.SEG6_LOCAL_TABLE: + e.Table = int(native.Uint32(attr.Value[0:4])) + e.Flags[nl.SEG6_LOCAL_TABLE] = true + case nl.SEG6_LOCAL_NH4: + e.InAddr = net.IP(attr.Value[0:4]) + e.Flags[nl.SEG6_LOCAL_NH4] = true + case nl.SEG6_LOCAL_NH6: + e.In6Addr = net.IP(attr.Value[0:16]) + e.Flags[nl.SEG6_LOCAL_NH6] = true + case nl.SEG6_LOCAL_IIF: + e.Iif = int(native.Uint32(attr.Value[0:4])) + e.Flags[nl.SEG6_LOCAL_IIF] = true + case nl.SEG6_LOCAL_OIF: + e.Oif = int(native.Uint32(attr.Value[0:4])) + e.Flags[nl.SEG6_LOCAL_OIF] = true + } + } + return err +} +func (e *SEG6LocalEncap) Encode() ([]byte, error) { + var err error + native := nl.NativeEndian() + res := make([]byte, 8) + native.PutUint16(res, 8) // length + native.PutUint16(res[2:], nl.SEG6_LOCAL_ACTION) + native.PutUint32(res[4:], uint32(e.Action)) + if e.Flags[nl.SEG6_LOCAL_SRH] { + srh, err := nl.EncodeSEG6Srh(e.Segments) + if err != nil { + return nil, err + } + attr := make([]byte, 4) + native.PutUint16(attr, uint16(len(srh)+4)) + native.PutUint16(attr[2:], nl.SEG6_LOCAL_SRH) + attr = append(attr, srh...) + res = append(res, attr...) + } + if e.Flags[nl.SEG6_LOCAL_TABLE] { + attr := make([]byte, 8) + native.PutUint16(attr, 8) + native.PutUint16(attr[2:], nl.SEG6_LOCAL_TABLE) + native.PutUint32(attr[4:], uint32(e.Table)) + res = append(res, attr...) + } + if e.Flags[nl.SEG6_LOCAL_NH4] { + attr := make([]byte, 4) + native.PutUint16(attr, 8) + native.PutUint16(attr[2:], nl.SEG6_LOCAL_NH4) + ipv4 := e.InAddr.To4() + if ipv4 == nil { + err = fmt.Errorf("SEG6_LOCAL_NH4 has invalid IPv4 address") + return nil, err + } + attr = append(attr, ipv4...) + res = append(res, attr...) + } + if e.Flags[nl.SEG6_LOCAL_NH6] { + attr := make([]byte, 4) + native.PutUint16(attr, 20) + native.PutUint16(attr[2:], nl.SEG6_LOCAL_NH6) + attr = append(attr, e.In6Addr...) + res = append(res, attr...) + } + if e.Flags[nl.SEG6_LOCAL_IIF] { + attr := make([]byte, 8) + native.PutUint16(attr, 8) + native.PutUint16(attr[2:], nl.SEG6_LOCAL_IIF) + native.PutUint32(attr[4:], uint32(e.Iif)) + res = append(res, attr...) + } + if e.Flags[nl.SEG6_LOCAL_OIF] { + attr := make([]byte, 8) + native.PutUint16(attr, 8) + native.PutUint16(attr[2:], nl.SEG6_LOCAL_OIF) + native.PutUint32(attr[4:], uint32(e.Oif)) + res = append(res, attr...) + } + return res, err +} +func (e *SEG6LocalEncap) String() string { + strs := make([]string, 0, nl.SEG6_LOCAL_MAX) + strs = append(strs, fmt.Sprintf("action %s", nl.SEG6LocalActionString(e.Action))) + + if e.Flags[nl.SEG6_LOCAL_TABLE] { + strs = append(strs, fmt.Sprintf("table %d", e.Table)) + } + if e.Flags[nl.SEG6_LOCAL_NH4] { + strs = append(strs, fmt.Sprintf("nh4 %s", e.InAddr)) + } + if e.Flags[nl.SEG6_LOCAL_NH6] { + strs = append(strs, fmt.Sprintf("nh6 %s", e.In6Addr)) + } + if e.Flags[nl.SEG6_LOCAL_IIF] { + link, err := LinkByIndex(e.Iif) + if err != nil { + strs = append(strs, fmt.Sprintf("iif %d", e.Iif)) + } else { + strs = append(strs, fmt.Sprintf("iif %s", link.Attrs().Name)) + } + } + if e.Flags[nl.SEG6_LOCAL_OIF] { + link, err := LinkByIndex(e.Oif) + if err != nil { + strs = append(strs, fmt.Sprintf("oif %d", e.Oif)) + } else { + strs = append(strs, fmt.Sprintf("oif %s", link.Attrs().Name)) + } + } + if e.Flags[nl.SEG6_LOCAL_SRH] { + segs := make([]string, 0, len(e.Segments)) + //append segment backwards (from n to 0) since seg#0 is the last segment. + for i := len(e.Segments); i > 0; i-- { + segs = append(segs, fmt.Sprintf("%s", e.Segments[i-1])) + } + strs = append(strs, fmt.Sprintf("segs %d [ %s ]", len(e.Segments), strings.Join(segs, " "))) + } + return strings.Join(strs, " ") +} +func (e *SEG6LocalEncap) Equal(x Encap) bool { + o, ok := x.(*SEG6LocalEncap) + if !ok { + return false + } + if e == o { + return true + } + if e == nil || o == nil { + return false + } + // compare all arrays first + for i := range e.Flags { + if e.Flags[i] != o.Flags[i] { + return false + } + } + if len(e.Segments) != len(o.Segments) { + return false + } + for i := range e.Segments { + if !e.Segments[i].Equal(o.Segments[i]) { + return false + } + } + // compare values + if !e.InAddr.Equal(o.InAddr) || !e.In6Addr.Equal(o.In6Addr) { + return false + } + if e.Action != o.Action || e.Table != o.Table || e.Iif != o.Iif || e.Oif != o.Oif { + return false + } + return true +} + +type Via struct { + AddrFamily int + Addr net.IP +} + +func (v *Via) Equal(x Destination) bool { + o, ok := x.(*Via) + if !ok { + return false + } + if v.AddrFamily == x.Family() && v.Addr.Equal(o.Addr) { + return true + } + return false +} + +func (v *Via) String() string { + return fmt.Sprintf("Family: %d, Address: %s", v.AddrFamily, v.Addr.String()) +} + +func (v *Via) Family() int { + return v.AddrFamily +} + +func (v *Via) Encode() ([]byte, error) { + buf := &bytes.Buffer{} + err := binary.Write(buf, native, uint16(v.AddrFamily)) + if err != nil { + return nil, err + } + err = binary.Write(buf, native, v.Addr) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func (v *Via) Decode(b []byte) error { + native := nl.NativeEndian() + if len(b) < 6 { + return fmt.Errorf("decoding failed: buffer too small (%d bytes)", len(b)) + } + v.AddrFamily = int(native.Uint16(b[0:2])) + if v.AddrFamily == nl.FAMILY_V4 { + v.Addr = net.IP(b[2:6]) + return nil + } else if v.AddrFamily == nl.FAMILY_V6 { + if len(b) < 18 { + return fmt.Errorf("decoding failed: buffer too small (%d bytes)", len(b)) + } + v.Addr = net.IP(b[2:]) + return nil + } + return fmt.Errorf("decoding failed: address family %d unknown", v.AddrFamily) +} + +// RouteAdd will add a route to the system. +// Equivalent to: `ip route add $route` +func RouteAdd(route *Route) error { + return pkgHandle.RouteAdd(route) +} + +// RouteAdd will add a route to the system. +// Equivalent to: `ip route add $route` +func (h *Handle) RouteAdd(route *Route) error { + flags := unix.NLM_F_CREATE | unix.NLM_F_EXCL | unix.NLM_F_ACK + req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags) + return h.routeHandle(route, req, nl.NewRtMsg()) +} + +// RouteAppend will append a route to the system. +// Equivalent to: `ip route append $route` +func RouteAppend(route *Route) error { + return pkgHandle.RouteAppend(route) +} + +// RouteAppend will append a route to the system. +// Equivalent to: `ip route append $route` +func (h *Handle) RouteAppend(route *Route) error { + flags := unix.NLM_F_CREATE | unix.NLM_F_APPEND | unix.NLM_F_ACK + req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags) + return h.routeHandle(route, req, nl.NewRtMsg()) +} + +// RouteAddEcmp will add a route to the system. +func RouteAddEcmp(route *Route) error { + return pkgHandle.RouteAddEcmp(route) +} + +// RouteAddEcmp will add a route to the system. +func (h *Handle) RouteAddEcmp(route *Route) error { + flags := unix.NLM_F_CREATE | unix.NLM_F_ACK + req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags) + return h.routeHandle(route, req, nl.NewRtMsg()) +} + +// RouteReplace will add a route to the system. +// Equivalent to: `ip route replace $route` +func RouteReplace(route *Route) error { + return pkgHandle.RouteReplace(route) +} + +// RouteReplace will add a route to the system. +// Equivalent to: `ip route replace $route` +func (h *Handle) RouteReplace(route *Route) error { + flags := unix.NLM_F_CREATE | unix.NLM_F_REPLACE | unix.NLM_F_ACK + req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags) + return h.routeHandle(route, req, nl.NewRtMsg()) +} + +// RouteDel will delete a route from the system. +// Equivalent to: `ip route del $route` +func RouteDel(route *Route) error { + return pkgHandle.RouteDel(route) +} + +// RouteDel will delete a route from the system. +// Equivalent to: `ip route del $route` +func (h *Handle) RouteDel(route *Route) error { + req := h.newNetlinkRequest(unix.RTM_DELROUTE, unix.NLM_F_ACK) + return h.routeHandle(route, req, nl.NewRtDelMsg()) +} + +func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error { + if (route.Dst == nil || route.Dst.IP == nil) && route.Src == nil && route.Gw == nil && route.MPLSDst == nil { + return fmt.Errorf("one of Dst.IP, Src, or Gw must not be nil") + } + + family := -1 + var rtAttrs []*nl.RtAttr + + if route.Dst != nil && route.Dst.IP != nil { + dstLen, _ := route.Dst.Mask.Size() + msg.Dst_len = uint8(dstLen) + dstFamily := nl.GetIPFamily(route.Dst.IP) + family = dstFamily + var dstData []byte + if dstFamily == FAMILY_V4 { + dstData = route.Dst.IP.To4() + } else { + dstData = route.Dst.IP.To16() + } + rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_DST, dstData)) + } else if route.MPLSDst != nil { + family = nl.FAMILY_MPLS + msg.Dst_len = uint8(20) + msg.Type = unix.RTN_UNICAST + rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_DST, nl.EncodeMPLSStack(*route.MPLSDst))) + } + + if route.NewDst != nil { + if family != -1 && family != route.NewDst.Family() { + return fmt.Errorf("new destination and destination are not the same address family") + } + buf, err := route.NewDst.Encode() + if err != nil { + return err + } + rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_NEWDST, buf)) + } + + if route.Encap != nil { + buf := make([]byte, 2) + native.PutUint16(buf, uint16(route.Encap.Type())) + rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP_TYPE, buf)) + buf, err := route.Encap.Encode() + if err != nil { + return err + } + rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP, buf)) + } + + if route.Src != nil { + srcFamily := nl.GetIPFamily(route.Src) + if family != -1 && family != srcFamily { + return fmt.Errorf("source and destination ip are not the same IP family") + } + family = srcFamily + var srcData []byte + if srcFamily == FAMILY_V4 { + srcData = route.Src.To4() + } else { + srcData = route.Src.To16() + } + // The commonly used src ip for routes is actually PREFSRC + rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_PREFSRC, srcData)) + } + + if route.Gw != nil { + gwFamily := nl.GetIPFamily(route.Gw) + if family != -1 && family != gwFamily { + return fmt.Errorf("gateway, source, and destination ip are not the same IP family") + } + family = gwFamily + var gwData []byte + if gwFamily == FAMILY_V4 { + gwData = route.Gw.To4() + } else { + gwData = route.Gw.To16() + } + rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_GATEWAY, gwData)) + } + + if route.Via != nil { + buf, err := route.Via.Encode() + if err != nil { + return fmt.Errorf("failed to encode RTA_VIA: %v", err) + } + rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_VIA, buf)) + } + + if len(route.MultiPath) > 0 { + buf := []byte{} + for _, nh := range route.MultiPath { + rtnh := &nl.RtNexthop{ + RtNexthop: unix.RtNexthop{ + Hops: uint8(nh.Hops), + Ifindex: int32(nh.LinkIndex), + Flags: uint8(nh.Flags), + }, + } + children := []nl.NetlinkRequestData{} + if nh.Gw != nil { + gwFamily := nl.GetIPFamily(nh.Gw) + if family != -1 && family != gwFamily { + return fmt.Errorf("gateway, source, and destination ip are not the same IP family") + } + if gwFamily == FAMILY_V4 { + children = append(children, nl.NewRtAttr(unix.RTA_GATEWAY, []byte(nh.Gw.To4()))) + } else { + children = append(children, nl.NewRtAttr(unix.RTA_GATEWAY, []byte(nh.Gw.To16()))) + } + } + if nh.NewDst != nil { + if family != -1 && family != nh.NewDst.Family() { + return fmt.Errorf("new destination and destination are not the same address family") + } + buf, err := nh.NewDst.Encode() + if err != nil { + return err + } + children = append(children, nl.NewRtAttr(unix.RTA_NEWDST, buf)) + } + if nh.Encap != nil { + buf := make([]byte, 2) + native.PutUint16(buf, uint16(nh.Encap.Type())) + children = append(children, nl.NewRtAttr(unix.RTA_ENCAP_TYPE, buf)) + buf, err := nh.Encap.Encode() + if err != nil { + return err + } + children = append(children, nl.NewRtAttr(unix.RTA_ENCAP, buf)) + } + if nh.Via != nil { + buf, err := nh.Via.Encode() + if err != nil { + return err + } + children = append(children, nl.NewRtAttr(unix.RTA_VIA, buf)) + } + rtnh.Children = children + buf = append(buf, rtnh.Serialize()...) + } + rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_MULTIPATH, buf)) + } + + if route.Table > 0 { + if route.Table >= 256 { + msg.Table = unix.RT_TABLE_UNSPEC + b := make([]byte, 4) + native.PutUint32(b, uint32(route.Table)) + rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_TABLE, b)) + } else { + msg.Table = uint8(route.Table) + } + } + + if route.Priority > 0 { + b := make([]byte, 4) + native.PutUint32(b, uint32(route.Priority)) + rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_PRIORITY, b)) + } + if route.Tos > 0 { + msg.Tos = uint8(route.Tos) + } + if route.Protocol > 0 { + msg.Protocol = uint8(route.Protocol) + } + if route.Type > 0 { + msg.Type = uint8(route.Type) + } + + var metrics []*nl.RtAttr + if route.MTU > 0 { + b := nl.Uint32Attr(uint32(route.MTU)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_MTU, b)) + } + if route.Window > 0 { + b := nl.Uint32Attr(uint32(route.Window)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_WINDOW, b)) + } + if route.Rtt > 0 { + b := nl.Uint32Attr(uint32(route.Rtt)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_RTT, b)) + } + if route.RttVar > 0 { + b := nl.Uint32Attr(uint32(route.RttVar)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_RTTVAR, b)) + } + if route.Ssthresh > 0 { + b := nl.Uint32Attr(uint32(route.Ssthresh)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_SSTHRESH, b)) + } + if route.Cwnd > 0 { + b := nl.Uint32Attr(uint32(route.Cwnd)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_CWND, b)) + } + if route.AdvMSS > 0 { + b := nl.Uint32Attr(uint32(route.AdvMSS)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_ADVMSS, b)) + } + if route.Reordering > 0 { + b := nl.Uint32Attr(uint32(route.Reordering)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_REORDERING, b)) + } + if route.Hoplimit > 0 { + b := nl.Uint32Attr(uint32(route.Hoplimit)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_HOPLIMIT, b)) + } + if route.InitCwnd > 0 { + b := nl.Uint32Attr(uint32(route.InitCwnd)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_INITCWND, b)) + } + if route.Features > 0 { + b := nl.Uint32Attr(uint32(route.Features)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_FEATURES, b)) + } + if route.RtoMin > 0 { + b := nl.Uint32Attr(uint32(route.RtoMin)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_RTO_MIN, b)) + } + if route.InitRwnd > 0 { + b := nl.Uint32Attr(uint32(route.InitRwnd)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_INITRWND, b)) + } + if route.QuickACK > 0 { + b := nl.Uint32Attr(uint32(route.QuickACK)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_QUICKACK, b)) + } + if route.Congctl != "" { + b := nl.ZeroTerminated(route.Congctl) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_CC_ALGO, b)) + } + if route.FastOpenNoCookie > 0 { + b := nl.Uint32Attr(uint32(route.FastOpenNoCookie)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_FASTOPEN_NO_COOKIE, b)) + } + + if metrics != nil { + attr := nl.NewRtAttr(unix.RTA_METRICS, nil) + for _, metric := range metrics { + attr.AddChild(metric) + } + rtAttrs = append(rtAttrs, attr) + } + + msg.Flags = uint32(route.Flags) + msg.Scope = uint8(route.Scope) + msg.Family = uint8(family) + req.AddData(msg) + for _, attr := range rtAttrs { + req.AddData(attr) + } + + var ( + b = make([]byte, 4) + native = nl.NativeEndian() + ) + native.PutUint32(b, uint32(route.LinkIndex)) + + req.AddData(nl.NewRtAttr(unix.RTA_OIF, b)) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// RouteList gets a list of routes in the system. +// Equivalent to: `ip route show`. +// The list can be filtered by link and ip family. +func RouteList(link Link, family int) ([]Route, error) { + return pkgHandle.RouteList(link, family) +} + +// RouteList gets a list of routes in the system. +// Equivalent to: `ip route show`. +// The list can be filtered by link and ip family. +func (h *Handle) RouteList(link Link, family int) ([]Route, error) { + var routeFilter *Route + if link != nil { + routeFilter = &Route{ + LinkIndex: link.Attrs().Index, + } + } + return h.RouteListFiltered(family, routeFilter, RT_FILTER_OIF) +} + +// RouteListFiltered gets a list of routes in the system filtered with specified rules. +// All rules must be defined in RouteFilter struct +func RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) { + return pkgHandle.RouteListFiltered(family, filter, filterMask) +} + +// RouteListFiltered gets a list of routes in the system filtered with specified rules. +// All rules must be defined in RouteFilter struct +func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) { + req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_DUMP) + infmsg := nl.NewIfInfomsg(family) + req.AddData(infmsg) + + msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE) + if err != nil { + return nil, err + } + + var res []Route + for _, m := range msgs { + msg := nl.DeserializeRtMsg(m) + if msg.Flags&unix.RTM_F_CLONED != 0 { + // Ignore cloned routes + continue + } + if msg.Table != unix.RT_TABLE_MAIN { + if filter == nil || filter != nil && filterMask&RT_FILTER_TABLE == 0 { + // Ignore non-main tables + continue + } + } + route, err := deserializeRoute(m) + if err != nil { + return nil, err + } + if filter != nil { + switch { + case filterMask&RT_FILTER_TABLE != 0 && filter.Table != unix.RT_TABLE_UNSPEC && route.Table != filter.Table: + continue + case filterMask&RT_FILTER_PROTOCOL != 0 && route.Protocol != filter.Protocol: + continue + case filterMask&RT_FILTER_SCOPE != 0 && route.Scope != filter.Scope: + continue + case filterMask&RT_FILTER_TYPE != 0 && route.Type != filter.Type: + continue + case filterMask&RT_FILTER_TOS != 0 && route.Tos != filter.Tos: + continue + case filterMask&RT_FILTER_OIF != 0 && route.LinkIndex != filter.LinkIndex: + continue + case filterMask&RT_FILTER_IIF != 0 && route.ILinkIndex != filter.ILinkIndex: + continue + case filterMask&RT_FILTER_GW != 0 && !route.Gw.Equal(filter.Gw): + continue + case filterMask&RT_FILTER_SRC != 0 && !route.Src.Equal(filter.Src): + continue + case filterMask&RT_FILTER_DST != 0: + if filter.MPLSDst == nil || route.MPLSDst == nil || (*filter.MPLSDst) != (*route.MPLSDst) { + if !ipNetEqual(route.Dst, filter.Dst) { + continue + } + } + case filterMask&RT_FILTER_HOPLIMIT != 0 && route.Hoplimit != filter.Hoplimit: + continue + } + } + res = append(res, route) + } + return res, nil +} + +// deserializeRoute decodes a binary netlink message into a Route struct +func deserializeRoute(m []byte) (Route, error) { + msg := nl.DeserializeRtMsg(m) + attrs, err := nl.ParseRouteAttr(m[msg.Len():]) + if err != nil { + return Route{}, err + } + route := Route{ + Scope: Scope(msg.Scope), + Protocol: RouteProtocol(int(msg.Protocol)), + Table: int(msg.Table), + Type: int(msg.Type), + Tos: int(msg.Tos), + Flags: int(msg.Flags), + } + + native := nl.NativeEndian() + var encap, encapType syscall.NetlinkRouteAttr + for _, attr := range attrs { + switch attr.Attr.Type { + case unix.RTA_GATEWAY: + route.Gw = net.IP(attr.Value) + case unix.RTA_PREFSRC: + route.Src = net.IP(attr.Value) + case unix.RTA_DST: + if msg.Family == nl.FAMILY_MPLS { + stack := nl.DecodeMPLSStack(attr.Value) + if len(stack) == 0 || len(stack) > 1 { + return route, fmt.Errorf("invalid MPLS RTA_DST") + } + route.MPLSDst = &stack[0] + } else { + route.Dst = &net.IPNet{ + IP: attr.Value, + Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attr.Value)), + } + } + case unix.RTA_OIF: + route.LinkIndex = int(native.Uint32(attr.Value[0:4])) + case unix.RTA_IIF: + route.ILinkIndex = int(native.Uint32(attr.Value[0:4])) + case unix.RTA_PRIORITY: + route.Priority = int(native.Uint32(attr.Value[0:4])) + case unix.RTA_TABLE: + route.Table = int(native.Uint32(attr.Value[0:4])) + case unix.RTA_MULTIPATH: + parseRtNexthop := func(value []byte) (*NexthopInfo, []byte, error) { + if len(value) < unix.SizeofRtNexthop { + return nil, nil, fmt.Errorf("lack of bytes") + } + nh := nl.DeserializeRtNexthop(value) + if len(value) < int(nh.RtNexthop.Len) { + return nil, nil, fmt.Errorf("lack of bytes") + } + info := &NexthopInfo{ + LinkIndex: int(nh.RtNexthop.Ifindex), + Hops: int(nh.RtNexthop.Hops), + Flags: int(nh.RtNexthop.Flags), + } + attrs, err := nl.ParseRouteAttr(value[unix.SizeofRtNexthop:int(nh.RtNexthop.Len)]) + if err != nil { + return nil, nil, err + } + var encap, encapType syscall.NetlinkRouteAttr + for _, attr := range attrs { + switch attr.Attr.Type { + case unix.RTA_GATEWAY: + info.Gw = net.IP(attr.Value) + case unix.RTA_NEWDST: + var d Destination + switch msg.Family { + case nl.FAMILY_MPLS: + d = &MPLSDestination{} + } + if err := d.Decode(attr.Value); err != nil { + return nil, nil, err + } + info.NewDst = d + case unix.RTA_ENCAP_TYPE: + encapType = attr + case unix.RTA_ENCAP: + encap = attr + case unix.RTA_VIA: + d := &Via{} + if err := d.Decode(attr.Value); err != nil { + return nil, nil, err + } + info.Via = d + } + } + + if len(encap.Value) != 0 && len(encapType.Value) != 0 { + typ := int(native.Uint16(encapType.Value[0:2])) + var e Encap + switch typ { + case nl.LWTUNNEL_ENCAP_MPLS: + e = &MPLSEncap{} + if err := e.Decode(encap.Value); err != nil { + return nil, nil, err + } + } + info.Encap = e + } + + return info, value[int(nh.RtNexthop.Len):], nil + } + rest := attr.Value + for len(rest) > 0 { + info, buf, err := parseRtNexthop(rest) + if err != nil { + return route, err + } + route.MultiPath = append(route.MultiPath, info) + rest = buf + } + case unix.RTA_NEWDST: + var d Destination + switch msg.Family { + case nl.FAMILY_MPLS: + d = &MPLSDestination{} + } + if err := d.Decode(attr.Value); err != nil { + return route, err + } + route.NewDst = d + case unix.RTA_VIA: + v := &Via{} + if err := v.Decode(attr.Value); err != nil { + return route, err + } + route.Via = v + case unix.RTA_ENCAP_TYPE: + encapType = attr + case unix.RTA_ENCAP: + encap = attr + case unix.RTA_METRICS: + metrics, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return route, err + } + for _, metric := range metrics { + switch metric.Attr.Type { + case unix.RTAX_MTU: + route.MTU = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_WINDOW: + route.Window = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_RTT: + route.Rtt = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_RTTVAR: + route.RttVar = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_SSTHRESH: + route.Ssthresh = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_CWND: + route.Cwnd = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_ADVMSS: + route.AdvMSS = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_REORDERING: + route.Reordering = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_HOPLIMIT: + route.Hoplimit = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_INITCWND: + route.InitCwnd = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_FEATURES: + route.Features = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_RTO_MIN: + route.RtoMin = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_INITRWND: + route.InitRwnd = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_QUICKACK: + route.QuickACK = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_CC_ALGO: + route.Congctl = nl.BytesToString(metric.Value) + case unix.RTAX_FASTOPEN_NO_COOKIE: + route.FastOpenNoCookie = int(native.Uint32(metric.Value[0:4])) + } + } + } + } + + if len(encap.Value) != 0 && len(encapType.Value) != 0 { + typ := int(native.Uint16(encapType.Value[0:2])) + var e Encap + switch typ { + case nl.LWTUNNEL_ENCAP_MPLS: + e = &MPLSEncap{} + if err := e.Decode(encap.Value); err != nil { + return route, err + } + case nl.LWTUNNEL_ENCAP_SEG6: + e = &SEG6Encap{} + if err := e.Decode(encap.Value); err != nil { + return route, err + } + case nl.LWTUNNEL_ENCAP_SEG6_LOCAL: + e = &SEG6LocalEncap{} + if err := e.Decode(encap.Value); err != nil { + return route, err + } + } + route.Encap = e + } + + return route, nil +} + +// RouteGetOptions contains a set of options to use with +// RouteGetWithOptions +type RouteGetOptions struct { + VrfName string + SrcAddr net.IP +} + +// RouteGetWithOptions gets a route to a specific destination from the host system. +// Equivalent to: 'ip route get <> vrf '. +func RouteGetWithOptions(destination net.IP, options *RouteGetOptions) ([]Route, error) { + return pkgHandle.RouteGetWithOptions(destination, options) +} + +// RouteGet gets a route to a specific destination from the host system. +// Equivalent to: 'ip route get'. +func RouteGet(destination net.IP) ([]Route, error) { + return pkgHandle.RouteGet(destination) +} + +// RouteGetWithOptions gets a route to a specific destination from the host system. +// Equivalent to: 'ip route get <> vrf '. +func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOptions) ([]Route, error) { + req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_REQUEST) + family := nl.GetIPFamily(destination) + var destinationData []byte + var bitlen uint8 + if family == FAMILY_V4 { + destinationData = destination.To4() + bitlen = 32 + } else { + destinationData = destination.To16() + bitlen = 128 + } + msg := &nl.RtMsg{} + msg.Family = uint8(family) + msg.Dst_len = bitlen + if options != nil && options.SrcAddr != nil { + msg.Src_len = bitlen + } + msg.Flags = unix.RTM_F_LOOKUP_TABLE + req.AddData(msg) + + rtaDst := nl.NewRtAttr(unix.RTA_DST, destinationData) + req.AddData(rtaDst) + + if options != nil { + if options.VrfName != "" { + link, err := LinkByName(options.VrfName) + if err != nil { + return nil, err + } + var ( + b = make([]byte, 4) + native = nl.NativeEndian() + ) + native.PutUint32(b, uint32(link.Attrs().Index)) + + req.AddData(nl.NewRtAttr(unix.RTA_OIF, b)) + } + + if options.SrcAddr != nil { + var srcAddr []byte + if family == FAMILY_V4 { + srcAddr = options.SrcAddr.To4() + } else { + srcAddr = options.SrcAddr.To16() + } + + req.AddData(nl.NewRtAttr(unix.RTA_SRC, srcAddr)) + } + } + + msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE) + if err != nil { + return nil, err + } + + var res []Route + for _, m := range msgs { + route, err := deserializeRoute(m) + if err != nil { + return nil, err + } + res = append(res, route) + } + return res, nil +} + +// RouteGet gets a route to a specific destination from the host system. +// Equivalent to: 'ip route get'. +func (h *Handle) RouteGet(destination net.IP) ([]Route, error) { + return h.RouteGetWithOptions(destination, nil) +} + +// RouteSubscribe takes a chan down which notifications will be sent +// when routes are added or deleted. Close the 'done' chan to stop subscription. +func RouteSubscribe(ch chan<- RouteUpdate, done <-chan struct{}) error { + return routeSubscribeAt(netns.None(), netns.None(), ch, done, nil, false) +} + +// RouteSubscribeAt works like RouteSubscribe plus it allows the caller +// to choose the network namespace in which to subscribe (ns). +func RouteSubscribeAt(ns netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}) error { + return routeSubscribeAt(ns, netns.None(), ch, done, nil, false) +} + +// RouteSubscribeOptions contains a set of options to use with +// RouteSubscribeWithOptions. +type RouteSubscribeOptions struct { + Namespace *netns.NsHandle + ErrorCallback func(error) + ListExisting bool +} + +// RouteSubscribeWithOptions work like RouteSubscribe but enable to +// provide additional options to modify the behavior. Currently, the +// namespace can be provided as well as an error callback. +func RouteSubscribeWithOptions(ch chan<- RouteUpdate, done <-chan struct{}, options RouteSubscribeOptions) error { + if options.Namespace == nil { + none := netns.None() + options.Namespace = &none + } + return routeSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting) +} + +func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error { + s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_ROUTE, unix.RTNLGRP_IPV6_ROUTE) + if err != nil { + return err + } + if done != nil { + go func() { + <-done + s.Close() + }() + } + if listExisting { + req := pkgHandle.newNetlinkRequest(unix.RTM_GETROUTE, + unix.NLM_F_DUMP) + infmsg := nl.NewIfInfomsg(unix.AF_UNSPEC) + req.AddData(infmsg) + if err := s.Send(req); err != nil { + return err + } + } + go func() { + defer close(ch) + for { + msgs, from, err := s.Receive() + if err != nil { + if cberr != nil { + cberr(err) + } + return + } + if from.Pid != nl.PidKernel { + if cberr != nil { + cberr(fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)) + } + continue + } + for _, m := range msgs { + if m.Header.Type == unix.NLMSG_DONE { + continue + } + if m.Header.Type == unix.NLMSG_ERROR { + native := nl.NativeEndian() + error := int32(native.Uint32(m.Data[0:4])) + if error == 0 { + continue + } + if cberr != nil { + cberr(syscall.Errno(-error)) + } + return + } + route, err := deserializeRoute(m.Data) + if err != nil { + if cberr != nil { + cberr(err) + } + return + } + ch <- RouteUpdate{Type: m.Header.Type, Route: route} + } + } + }() + + return nil +} + +func (p RouteProtocol) String() string { + switch int(p) { + case unix.RTPROT_BABEL: + return "babel" + case unix.RTPROT_BGP: + return "bgp" + case unix.RTPROT_BIRD: + return "bird" + case unix.RTPROT_BOOT: + return "boot" + case unix.RTPROT_DHCP: + return "dhcp" + case unix.RTPROT_DNROUTED: + return "dnrouted" + case unix.RTPROT_EIGRP: + return "eigrp" + case unix.RTPROT_GATED: + return "gated" + case unix.RTPROT_ISIS: + return "isis" + //case unix.RTPROT_KEEPALIVED: + // return "keepalived" + case unix.RTPROT_KERNEL: + return "kernel" + case unix.RTPROT_MROUTED: + return "mrouted" + case unix.RTPROT_MRT: + return "mrt" + case unix.RTPROT_NTK: + return "ntk" + case unix.RTPROT_OSPF: + return "ospf" + case unix.RTPROT_RA: + return "ra" + case unix.RTPROT_REDIRECT: + return "redirect" + case unix.RTPROT_RIP: + return "rip" + case unix.RTPROT_STATIC: + return "static" + case unix.RTPROT_UNSPEC: + return "unspec" + case unix.RTPROT_XORP: + return "xorp" + case unix.RTPROT_ZEBRA: + return "zebra" + default: + return strconv.Itoa(int(p)) + } +} diff --git a/vendor/github.com/vishvananda/netlink/route_unspecified.go b/vendor/github.com/vishvananda/netlink/route_unspecified.go new file mode 100644 index 000000000..db7372689 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/route_unspecified.go @@ -0,0 +1,21 @@ +// +build !linux + +package netlink + +import "strconv" + +func (r *Route) ListFlags() []string { + return []string{} +} + +func (n *NexthopInfo) ListFlags() []string { + return []string{} +} + +func (s Scope) String() string { + return "unknown" +} + +func (p RouteProtocol) String() string { + return strconv.Itoa(int(p)) +} diff --git a/vendor/github.com/vishvananda/netlink/rule.go b/vendor/github.com/vishvananda/netlink/rule.go new file mode 100644 index 000000000..95f2facfb --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/rule.go @@ -0,0 +1,56 @@ +package netlink + +import ( + "fmt" + "net" +) + +// Rule represents a netlink rule. +type Rule struct { + Priority int + Family int + Table int + Mark int + Mask int + Tos uint + TunID uint + Goto int + Src *net.IPNet + Dst *net.IPNet + Flow int + IifName string + OifName string + SuppressIfgroup int + SuppressPrefixlen int + Invert bool + Dport *RulePortRange + Sport *RulePortRange +} + +func (r Rule) String() string { + return fmt.Sprintf("ip rule %d: from %s table %d", r.Priority, r.Src, r.Table) +} + +// NewRule return empty rules. +func NewRule() *Rule { + return &Rule{ + SuppressIfgroup: -1, + SuppressPrefixlen: -1, + Priority: -1, + Mark: -1, + Mask: -1, + Goto: -1, + Flow: -1, + } +} + +// NewRulePortRange creates rule sport/dport range. +func NewRulePortRange(start, end uint16) *RulePortRange { + return &RulePortRange{Start: start, End: end} +} + +// RulePortRange represents rule sport/dport range. +type RulePortRange struct { + Start uint16 + End uint16 +} diff --git a/vendor/github.com/vishvananda/netlink/rule_linux.go b/vendor/github.com/vishvananda/netlink/rule_linux.go new file mode 100644 index 000000000..40474f30e --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/rule_linux.go @@ -0,0 +1,296 @@ +package netlink + +import ( + "bytes" + "fmt" + "net" + + "github.com/vishvananda/netlink/nl" + "golang.org/x/sys/unix" +) + +const FibRuleInvert = 0x2 + +// RuleAdd adds a rule to the system. +// Equivalent to: ip rule add +func RuleAdd(rule *Rule) error { + return pkgHandle.RuleAdd(rule) +} + +// RuleAdd adds a rule to the system. +// Equivalent to: ip rule add +func (h *Handle) RuleAdd(rule *Rule) error { + req := h.newNetlinkRequest(unix.RTM_NEWRULE, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) + return ruleHandle(rule, req) +} + +// RuleDel deletes a rule from the system. +// Equivalent to: ip rule del +func RuleDel(rule *Rule) error { + return pkgHandle.RuleDel(rule) +} + +// RuleDel deletes a rule from the system. +// Equivalent to: ip rule del +func (h *Handle) RuleDel(rule *Rule) error { + req := h.newNetlinkRequest(unix.RTM_DELRULE, unix.NLM_F_ACK) + return ruleHandle(rule, req) +} + +func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error { + msg := nl.NewRtMsg() + msg.Family = unix.AF_INET + msg.Protocol = unix.RTPROT_BOOT + msg.Scope = unix.RT_SCOPE_UNIVERSE + msg.Table = unix.RT_TABLE_UNSPEC + msg.Type = unix.RTN_UNSPEC + if req.NlMsghdr.Flags&unix.NLM_F_CREATE > 0 { + msg.Type = unix.RTN_UNICAST + } + if rule.Invert { + msg.Flags |= FibRuleInvert + } + if rule.Family != 0 { + msg.Family = uint8(rule.Family) + } + if rule.Table >= 0 && rule.Table < 256 { + msg.Table = uint8(rule.Table) + } + if rule.Tos != 0 { + msg.Tos = uint8(rule.Tos) + } + + var dstFamily uint8 + var rtAttrs []*nl.RtAttr + if rule.Dst != nil && rule.Dst.IP != nil { + dstLen, _ := rule.Dst.Mask.Size() + msg.Dst_len = uint8(dstLen) + msg.Family = uint8(nl.GetIPFamily(rule.Dst.IP)) + dstFamily = msg.Family + var dstData []byte + if msg.Family == unix.AF_INET { + dstData = rule.Dst.IP.To4() + } else { + dstData = rule.Dst.IP.To16() + } + rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_DST, dstData)) + } + + if rule.Src != nil && rule.Src.IP != nil { + msg.Family = uint8(nl.GetIPFamily(rule.Src.IP)) + if dstFamily != 0 && dstFamily != msg.Family { + return fmt.Errorf("source and destination ip are not the same IP family") + } + srcLen, _ := rule.Src.Mask.Size() + msg.Src_len = uint8(srcLen) + var srcData []byte + if msg.Family == unix.AF_INET { + srcData = rule.Src.IP.To4() + } else { + srcData = rule.Src.IP.To16() + } + rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_SRC, srcData)) + } + + req.AddData(msg) + for i := range rtAttrs { + req.AddData(rtAttrs[i]) + } + + native := nl.NativeEndian() + + if rule.Priority >= 0 { + b := make([]byte, 4) + native.PutUint32(b, uint32(rule.Priority)) + req.AddData(nl.NewRtAttr(nl.FRA_PRIORITY, b)) + } + if rule.Mark >= 0 { + b := make([]byte, 4) + native.PutUint32(b, uint32(rule.Mark)) + req.AddData(nl.NewRtAttr(nl.FRA_FWMARK, b)) + } + if rule.Mask >= 0 { + b := make([]byte, 4) + native.PutUint32(b, uint32(rule.Mask)) + req.AddData(nl.NewRtAttr(nl.FRA_FWMASK, b)) + } + if rule.Flow >= 0 { + b := make([]byte, 4) + native.PutUint32(b, uint32(rule.Flow)) + req.AddData(nl.NewRtAttr(nl.FRA_FLOW, b)) + } + if rule.TunID > 0 { + b := make([]byte, 4) + native.PutUint32(b, uint32(rule.TunID)) + req.AddData(nl.NewRtAttr(nl.FRA_TUN_ID, b)) + } + if rule.Table >= 256 { + b := make([]byte, 4) + native.PutUint32(b, uint32(rule.Table)) + req.AddData(nl.NewRtAttr(nl.FRA_TABLE, b)) + } + if msg.Table > 0 { + if rule.SuppressPrefixlen >= 0 { + b := make([]byte, 4) + native.PutUint32(b, uint32(rule.SuppressPrefixlen)) + req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_PREFIXLEN, b)) + } + if rule.SuppressIfgroup >= 0 { + b := make([]byte, 4) + native.PutUint32(b, uint32(rule.SuppressIfgroup)) + req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_IFGROUP, b)) + } + } + if rule.IifName != "" { + req.AddData(nl.NewRtAttr(nl.FRA_IIFNAME, []byte(rule.IifName+"\x00"))) + } + if rule.OifName != "" { + req.AddData(nl.NewRtAttr(nl.FRA_OIFNAME, []byte(rule.OifName+"\x00"))) + } + if rule.Goto >= 0 { + msg.Type = nl.FR_ACT_GOTO + b := make([]byte, 4) + native.PutUint32(b, uint32(rule.Goto)) + req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b)) + } + + if rule.Dport != nil { + b := rule.Dport.toRtAttrData() + req.AddData(nl.NewRtAttr(nl.FRA_DPORT_RANGE, b)) + } + + if rule.Sport != nil { + b := rule.Sport.toRtAttrData() + req.AddData(nl.NewRtAttr(nl.FRA_SPORT_RANGE, b)) + } + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// RuleList lists rules in the system. +// Equivalent to: ip rule list +func RuleList(family int) ([]Rule, error) { + return pkgHandle.RuleList(family) +} + +// RuleList lists rules in the system. +// Equivalent to: ip rule list +func (h *Handle) RuleList(family int) ([]Rule, error) { + return h.RuleListFiltered(family, nil, 0) +} + +// RuleListFiltered gets a list of rules in the system filtered by the +// specified rule template `filter`. +// Equivalent to: ip rule list +func RuleListFiltered(family int, filter *Rule, filterMask uint64) ([]Rule, error) { + return pkgHandle.RuleListFiltered(family, filter, filterMask) +} + +// RuleListFiltered lists rules in the system. +// Equivalent to: ip rule list +func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) ([]Rule, error) { + req := h.newNetlinkRequest(unix.RTM_GETRULE, unix.NLM_F_DUMP|unix.NLM_F_REQUEST) + msg := nl.NewIfInfomsg(family) + req.AddData(msg) + + msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWRULE) + if err != nil { + return nil, err + } + + native := nl.NativeEndian() + var res = make([]Rule, 0) + for i := range msgs { + msg := nl.DeserializeRtMsg(msgs[i]) + attrs, err := nl.ParseRouteAttr(msgs[i][msg.Len():]) + if err != nil { + return nil, err + } + + rule := NewRule() + + rule.Invert = msg.Flags&FibRuleInvert > 0 + rule.Tos = uint(msg.Tos) + + for j := range attrs { + switch attrs[j].Attr.Type { + case unix.RTA_TABLE: + rule.Table = int(native.Uint32(attrs[j].Value[0:4])) + case nl.FRA_SRC: + rule.Src = &net.IPNet{ + IP: attrs[j].Value, + Mask: net.CIDRMask(int(msg.Src_len), 8*len(attrs[j].Value)), + } + case nl.FRA_DST: + rule.Dst = &net.IPNet{ + IP: attrs[j].Value, + Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attrs[j].Value)), + } + case nl.FRA_FWMARK: + rule.Mark = int(native.Uint32(attrs[j].Value[0:4])) + case nl.FRA_FWMASK: + rule.Mask = int(native.Uint32(attrs[j].Value[0:4])) + case nl.FRA_TUN_ID: + rule.TunID = uint(native.Uint64(attrs[j].Value[0:4])) + case nl.FRA_IIFNAME: + rule.IifName = string(attrs[j].Value[:len(attrs[j].Value)-1]) + case nl.FRA_OIFNAME: + rule.OifName = string(attrs[j].Value[:len(attrs[j].Value)-1]) + case nl.FRA_SUPPRESS_PREFIXLEN: + i := native.Uint32(attrs[j].Value[0:4]) + if i != 0xffffffff { + rule.SuppressPrefixlen = int(i) + } + case nl.FRA_SUPPRESS_IFGROUP: + i := native.Uint32(attrs[j].Value[0:4]) + if i != 0xffffffff { + rule.SuppressIfgroup = int(i) + } + case nl.FRA_FLOW: + rule.Flow = int(native.Uint32(attrs[j].Value[0:4])) + case nl.FRA_GOTO: + rule.Goto = int(native.Uint32(attrs[j].Value[0:4])) + case nl.FRA_PRIORITY: + rule.Priority = int(native.Uint32(attrs[j].Value[0:4])) + case nl.FRA_DPORT_RANGE: + rule.Dport = NewRulePortRange(native.Uint16(attrs[j].Value[0:2]), native.Uint16(attrs[j].Value[2:4])) + case nl.FRA_SPORT_RANGE: + rule.Sport = NewRulePortRange(native.Uint16(attrs[j].Value[0:2]), native.Uint16(attrs[j].Value[2:4])) + } + } + + if filter != nil { + switch { + case filterMask&RT_FILTER_SRC != 0 && + (rule.Src == nil || rule.Src.String() != filter.Src.String()): + continue + case filterMask&RT_FILTER_DST != 0 && + (rule.Dst == nil || rule.Dst.String() != filter.Dst.String()): + continue + case filterMask&RT_FILTER_TABLE != 0 && + filter.Table != unix.RT_TABLE_UNSPEC && rule.Table != filter.Table: + continue + case filterMask&RT_FILTER_TOS != 0 && rule.Tos != filter.Tos: + continue + case filterMask&RT_FILTER_PRIORITY != 0 && rule.Priority != filter.Priority: + continue + case filterMask&RT_FILTER_MARK != 0 && rule.Mark != filter.Mark: + continue + case filterMask&RT_FILTER_MASK != 0 && rule.Mask != filter.Mask: + continue + } + } + + res = append(res, *rule) + } + + return res, nil +} + +func (pr *RulePortRange) toRtAttrData() []byte { + b := [][]byte{make([]byte, 2), make([]byte, 2)} + native.PutUint16(b[0], pr.Start) + native.PutUint16(b[1], pr.End) + return bytes.Join(b, []byte{}) +} diff --git a/vendor/github.com/vishvananda/netlink/socket.go b/vendor/github.com/vishvananda/netlink/socket.go new file mode 100644 index 000000000..41aa72624 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/socket.go @@ -0,0 +1,27 @@ +package netlink + +import "net" + +// SocketID identifies a single socket. +type SocketID struct { + SourcePort uint16 + DestinationPort uint16 + Source net.IP + Destination net.IP + Interface uint32 + Cookie [2]uint32 +} + +// Socket represents a netlink socket. +type Socket struct { + Family uint8 + State uint8 + Timer uint8 + Retrans uint8 + ID SocketID + Expires uint32 + RQueue uint32 + WQueue uint32 + UID uint32 + INode uint32 +} diff --git a/vendor/github.com/vishvananda/netlink/socket_linux.go b/vendor/github.com/vishvananda/netlink/socket_linux.go new file mode 100644 index 000000000..9b0f4a081 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/socket_linux.go @@ -0,0 +1,261 @@ +package netlink + +import ( + "errors" + "fmt" + "net" + "syscall" + + "github.com/vishvananda/netlink/nl" + "golang.org/x/sys/unix" +) + +const ( + sizeofSocketID = 0x30 + sizeofSocketRequest = sizeofSocketID + 0x8 + sizeofSocket = sizeofSocketID + 0x18 +) + +type socketRequest struct { + Family uint8 + Protocol uint8 + Ext uint8 + pad uint8 + States uint32 + ID SocketID +} + +type writeBuffer struct { + Bytes []byte + pos int +} + +func (b *writeBuffer) Write(c byte) { + b.Bytes[b.pos] = c + b.pos++ +} + +func (b *writeBuffer) Next(n int) []byte { + s := b.Bytes[b.pos : b.pos+n] + b.pos += n + return s +} + +func (r *socketRequest) Serialize() []byte { + b := writeBuffer{Bytes: make([]byte, sizeofSocketRequest)} + b.Write(r.Family) + b.Write(r.Protocol) + b.Write(r.Ext) + b.Write(r.pad) + native.PutUint32(b.Next(4), r.States) + networkOrder.PutUint16(b.Next(2), r.ID.SourcePort) + networkOrder.PutUint16(b.Next(2), r.ID.DestinationPort) + if r.Family == unix.AF_INET6 { + copy(b.Next(16), r.ID.Source) + copy(b.Next(16), r.ID.Destination) + } else { + copy(b.Next(4), r.ID.Source.To4()) + b.Next(12) + copy(b.Next(4), r.ID.Destination.To4()) + b.Next(12) + } + native.PutUint32(b.Next(4), r.ID.Interface) + native.PutUint32(b.Next(4), r.ID.Cookie[0]) + native.PutUint32(b.Next(4), r.ID.Cookie[1]) + return b.Bytes +} + +func (r *socketRequest) Len() int { return sizeofSocketRequest } + +type readBuffer struct { + Bytes []byte + pos int +} + +func (b *readBuffer) Read() byte { + c := b.Bytes[b.pos] + b.pos++ + return c +} + +func (b *readBuffer) Next(n int) []byte { + s := b.Bytes[b.pos : b.pos+n] + b.pos += n + return s +} + +func (s *Socket) deserialize(b []byte) error { + if len(b) < sizeofSocket { + return fmt.Errorf("socket data short read (%d); want %d", len(b), sizeofSocket) + } + rb := readBuffer{Bytes: b} + s.Family = rb.Read() + s.State = rb.Read() + s.Timer = rb.Read() + s.Retrans = rb.Read() + s.ID.SourcePort = networkOrder.Uint16(rb.Next(2)) + s.ID.DestinationPort = networkOrder.Uint16(rb.Next(2)) + if s.Family == unix.AF_INET6 { + s.ID.Source = net.IP(rb.Next(16)) + s.ID.Destination = net.IP(rb.Next(16)) + } else { + s.ID.Source = net.IPv4(rb.Read(), rb.Read(), rb.Read(), rb.Read()) + rb.Next(12) + s.ID.Destination = net.IPv4(rb.Read(), rb.Read(), rb.Read(), rb.Read()) + rb.Next(12) + } + s.ID.Interface = native.Uint32(rb.Next(4)) + s.ID.Cookie[0] = native.Uint32(rb.Next(4)) + s.ID.Cookie[1] = native.Uint32(rb.Next(4)) + s.Expires = native.Uint32(rb.Next(4)) + s.RQueue = native.Uint32(rb.Next(4)) + s.WQueue = native.Uint32(rb.Next(4)) + s.UID = native.Uint32(rb.Next(4)) + s.INode = native.Uint32(rb.Next(4)) + return nil +} + +// SocketGet returns the Socket identified by its local and remote addresses. +func SocketGet(local, remote net.Addr) (*Socket, error) { + localTCP, ok := local.(*net.TCPAddr) + if !ok { + return nil, ErrNotImplemented + } + remoteTCP, ok := remote.(*net.TCPAddr) + if !ok { + return nil, ErrNotImplemented + } + localIP := localTCP.IP.To4() + if localIP == nil { + return nil, ErrNotImplemented + } + remoteIP := remoteTCP.IP.To4() + if remoteIP == nil { + return nil, ErrNotImplemented + } + + s, err := nl.Subscribe(unix.NETLINK_INET_DIAG) + if err != nil { + return nil, err + } + defer s.Close() + req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, 0) + req.AddData(&socketRequest{ + Family: unix.AF_INET, + Protocol: unix.IPPROTO_TCP, + ID: SocketID{ + SourcePort: uint16(localTCP.Port), + DestinationPort: uint16(remoteTCP.Port), + Source: localIP, + Destination: remoteIP, + Cookie: [2]uint32{nl.TCPDIAG_NOCOOKIE, nl.TCPDIAG_NOCOOKIE}, + }, + }) + s.Send(req) + msgs, from, err := s.Receive() + if err != nil { + return nil, err + } + if from.Pid != nl.PidKernel { + return nil, fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel) + } + if len(msgs) == 0 { + return nil, errors.New("no message nor error from netlink") + } + if len(msgs) > 2 { + return nil, fmt.Errorf("multiple (%d) matching sockets", len(msgs)) + } + sock := &Socket{} + if err := sock.deserialize(msgs[0].Data); err != nil { + return nil, err + } + return sock, nil +} + +// SocketDiagTCPInfo requests INET_DIAG_INFO for TCP protocol for specified family type. +func SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) { + s, err := nl.Subscribe(unix.NETLINK_INET_DIAG) + if err != nil { + return nil, err + } + defer s.Close() + + req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP) + req.AddData(&socketRequest{ + Family: family, + Protocol: unix.IPPROTO_TCP, + Ext: (1 << (INET_DIAG_VEGASINFO - 1)) | (1 << (INET_DIAG_INFO - 1)), + States: uint32(0xfff), // All TCP states + }) + s.Send(req) + + var result []*InetDiagTCPInfoResp +loop: + for { + msgs, from, err := s.Receive() + if err != nil { + return nil, err + } + if from.Pid != nl.PidKernel { + return nil, fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel) + } + if len(msgs) == 0 { + return nil, errors.New("no message nor error from netlink") + } + + for _, m := range msgs { + switch m.Header.Type { + case unix.NLMSG_DONE: + break loop + case unix.NLMSG_ERROR: + native := nl.NativeEndian() + error := int32(native.Uint32(m.Data[0:4])) + return nil, syscall.Errno(-error) + } + sockInfo := &Socket{} + if err := sockInfo.deserialize(m.Data); err != nil { + return nil, err + } + attrs, err := nl.ParseRouteAttr(m.Data[sizeofSocket:]) + if err != nil { + return nil, err + } + + res, err := attrsToInetDiagTCPInfoResp(attrs, sockInfo) + if err != nil { + return nil, err + } + + result = append(result, res) + } + } + return result, nil +} + +func attrsToInetDiagTCPInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *Socket) (*InetDiagTCPInfoResp, error) { + var tcpInfo *TCPInfo + var tcpBBRInfo *TCPBBRInfo + for _, a := range attrs { + if a.Attr.Type == INET_DIAG_INFO { + tcpInfo = &TCPInfo{} + if err := tcpInfo.deserialize(a.Value); err != nil { + return nil, err + } + continue + } + + if a.Attr.Type == INET_DIAG_BBRINFO { + tcpBBRInfo = &TCPBBRInfo{} + if err := tcpBBRInfo.deserialize(a.Value); err != nil { + return nil, err + } + continue + } + } + + return &InetDiagTCPInfoResp{ + InetDiagMsg: sockInfo, + TCPInfo: tcpInfo, + TCPBBRInfo: tcpBBRInfo, + }, nil +} diff --git a/vendor/github.com/vishvananda/netlink/tcp.go b/vendor/github.com/vishvananda/netlink/tcp.go new file mode 100644 index 000000000..23ca014d4 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/tcp.go @@ -0,0 +1,84 @@ +package netlink + +// TCP States +const ( + TCP_ESTABLISHED = iota + 0x01 + TCP_SYN_SENT + TCP_SYN_RECV + TCP_FIN_WAIT1 + TCP_FIN_WAIT2 + TCP_TIME_WAIT + TCP_CLOSE + TCP_CLOSE_WAIT + TCP_LAST_ACK + TCP_LISTEN + TCP_CLOSING + TCP_NEW_SYN_REC + TCP_MAX_STATES +) + +type TCPInfo struct { + State uint8 + Ca_state uint8 + Retransmits uint8 + Probes uint8 + Backoff uint8 + Options uint8 + Snd_wscale uint8 // no uint4 + Rcv_wscale uint8 + Delivery_rate_app_limited uint8 + Fastopen_client_fail uint8 + Rto uint32 + Ato uint32 + Snd_mss uint32 + Rcv_mss uint32 + Unacked uint32 + Sacked uint32 + Lost uint32 + Retrans uint32 + Fackets uint32 + Last_data_sent uint32 + Last_ack_sent uint32 + Last_data_recv uint32 + Last_ack_recv uint32 + Pmtu uint32 + Rcv_ssthresh uint32 + Rtt uint32 + Rttvar uint32 + Snd_ssthresh uint32 + Snd_cwnd uint32 + Advmss uint32 + Reordering uint32 + Rcv_rtt uint32 + Rcv_space uint32 + Total_retrans uint32 + Pacing_rate uint64 + Max_pacing_rate uint64 + Bytes_acked uint64 /* RFC4898 tcpEStatsAppHCThruOctetsAcked */ + Bytes_received uint64 /* RFC4898 tcpEStatsAppHCThruOctetsReceived */ + Segs_out uint32 /* RFC4898 tcpEStatsPerfSegsOut */ + Segs_in uint32 /* RFC4898 tcpEStatsPerfSegsIn */ + Notsent_bytes uint32 + Min_rtt uint32 + Data_segs_in uint32 /* RFC4898 tcpEStatsDataSegsIn */ + Data_segs_out uint32 /* RFC4898 tcpEStatsDataSegsOut */ + Delivery_rate uint64 + Busy_time uint64 /* Time (usec) busy sending data */ + Rwnd_limited uint64 /* Time (usec) limited by receive window */ + Sndbuf_limited uint64 /* Time (usec) limited by send buffer */ + Delivered uint32 + Delivered_ce uint32 + Bytes_sent uint64 /* RFC4898 tcpEStatsPerfHCDataOctetsOut */ + Bytes_retrans uint64 /* RFC4898 tcpEStatsPerfOctetsRetrans */ + Dsack_dups uint32 /* RFC4898 tcpEStatsStackDSACKDups */ + Reord_seen uint32 /* reordering events seen */ + Rcv_ooopack uint32 /* Out-of-order packets received */ + Snd_wnd uint32 /* peer's advertised receive window after * scaling (bytes) */ +} + +type TCPBBRInfo struct { + BBRBW uint64 + BBRMinRTT uint32 + BBRPacingGain uint32 + BBRCwndGain uint32 +} diff --git a/vendor/github.com/vishvananda/netlink/tcp_linux.go b/vendor/github.com/vishvananda/netlink/tcp_linux.go new file mode 100644 index 000000000..293858738 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/tcp_linux.go @@ -0,0 +1,353 @@ +package netlink + +import ( + "bytes" + "errors" + "io" +) + +const ( + tcpBBRInfoLen = 20 +) + +func checkDeserErr(err error) error { + if err == io.EOF { + return nil + } + return err +} + +func (t *TCPInfo) deserialize(b []byte) error { + var err error + rb := bytes.NewBuffer(b) + + t.State, err = rb.ReadByte() + if err != nil { + return checkDeserErr(err) + } + + t.Ca_state, err = rb.ReadByte() + if err != nil { + return checkDeserErr(err) + } + + t.Retransmits, err = rb.ReadByte() + if err != nil { + return checkDeserErr(err) + } + + t.Probes, err = rb.ReadByte() + if err != nil { + return checkDeserErr(err) + } + + t.Backoff, err = rb.ReadByte() + if err != nil { + return checkDeserErr(err) + } + t.Options, err = rb.ReadByte() + if err != nil { + return checkDeserErr(err) + } + + scales, err := rb.ReadByte() + if err != nil { + return checkDeserErr(err) + } + t.Snd_wscale = scales >> 4 // first 4 bits + t.Rcv_wscale = scales & 0xf // last 4 bits + + rateLimAndFastOpen, err := rb.ReadByte() + if err != nil { + return checkDeserErr(err) + } + t.Delivery_rate_app_limited = rateLimAndFastOpen >> 7 // get first bit + t.Fastopen_client_fail = rateLimAndFastOpen >> 5 & 3 // get next two bits + + next := rb.Next(4) + if len(next) == 0 { + return nil + } + t.Rto = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Ato = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Snd_mss = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Rcv_mss = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Unacked = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Sacked = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Lost = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Retrans = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Fackets = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Last_data_sent = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Last_ack_sent = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Last_data_recv = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Last_ack_recv = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Pmtu = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Rcv_ssthresh = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Rtt = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Rttvar = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Snd_ssthresh = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Snd_cwnd = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Advmss = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Reordering = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Rcv_rtt = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Rcv_space = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Total_retrans = native.Uint32(next) + + next = rb.Next(8) + if len(next) == 0 { + return nil + } + t.Pacing_rate = native.Uint64(next) + + next = rb.Next(8) + if len(next) == 0 { + return nil + } + t.Max_pacing_rate = native.Uint64(next) + + next = rb.Next(8) + if len(next) == 0 { + return nil + } + t.Bytes_acked = native.Uint64(next) + + next = rb.Next(8) + if len(next) == 0 { + return nil + } + t.Bytes_received = native.Uint64(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Segs_out = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Segs_in = native.Uint32(next) + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Notsent_bytes = native.Uint32(next) + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Min_rtt = native.Uint32(next) + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Data_segs_in = native.Uint32(next) + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Data_segs_out = native.Uint32(next) + + next = rb.Next(8) + if len(next) == 0 { + return nil + } + t.Delivery_rate = native.Uint64(next) + + next = rb.Next(8) + if len(next) == 0 { + return nil + } + t.Busy_time = native.Uint64(next) + + next = rb.Next(8) + if len(next) == 0 { + return nil + } + t.Rwnd_limited = native.Uint64(next) + + next = rb.Next(8) + if len(next) == 0 { + return nil + } + t.Sndbuf_limited = native.Uint64(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Delivered = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Delivered_ce = native.Uint32(next) + + next = rb.Next(8) + if len(next) == 0 { + return nil + } + t.Bytes_sent = native.Uint64(next) + + next = rb.Next(8) + if len(next) == 0 { + return nil + } + t.Bytes_retrans = native.Uint64(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Dsack_dups = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Reord_seen = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Rcv_ooopack = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Snd_wnd = native.Uint32(next) + return nil +} + +func (t *TCPBBRInfo) deserialize(b []byte) error { + if len(b) != tcpBBRInfoLen { + return errors.New("Invalid length") + } + + rb := bytes.NewBuffer(b) + t.BBRBW = native.Uint64(rb.Next(8)) + t.BBRMinRTT = native.Uint32(rb.Next(4)) + t.BBRPacingGain = native.Uint32(rb.Next(4)) + t.BBRCwndGain = native.Uint32(rb.Next(4)) + + return nil +} diff --git a/vendor/github.com/vishvananda/netlink/xfrm.go b/vendor/github.com/vishvananda/netlink/xfrm.go new file mode 100644 index 000000000..02b41842e --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/xfrm.go @@ -0,0 +1,75 @@ +package netlink + +import ( + "fmt" + + "golang.org/x/sys/unix" +) + +// Proto is an enum representing an ipsec protocol. +type Proto uint8 + +const ( + XFRM_PROTO_ROUTE2 Proto = unix.IPPROTO_ROUTING + XFRM_PROTO_ESP Proto = unix.IPPROTO_ESP + XFRM_PROTO_AH Proto = unix.IPPROTO_AH + XFRM_PROTO_HAO Proto = unix.IPPROTO_DSTOPTS + XFRM_PROTO_COMP Proto = 0x6c // NOTE not defined on darwin + XFRM_PROTO_IPSEC_ANY Proto = unix.IPPROTO_RAW +) + +func (p Proto) String() string { + switch p { + case XFRM_PROTO_ROUTE2: + return "route2" + case XFRM_PROTO_ESP: + return "esp" + case XFRM_PROTO_AH: + return "ah" + case XFRM_PROTO_HAO: + return "hao" + case XFRM_PROTO_COMP: + return "comp" + case XFRM_PROTO_IPSEC_ANY: + return "ipsec-any" + } + return fmt.Sprintf("%d", p) +} + +// Mode is an enum representing an ipsec transport. +type Mode uint8 + +const ( + XFRM_MODE_TRANSPORT Mode = iota + XFRM_MODE_TUNNEL + XFRM_MODE_ROUTEOPTIMIZATION + XFRM_MODE_IN_TRIGGER + XFRM_MODE_BEET + XFRM_MODE_MAX +) + +func (m Mode) String() string { + switch m { + case XFRM_MODE_TRANSPORT: + return "transport" + case XFRM_MODE_TUNNEL: + return "tunnel" + case XFRM_MODE_ROUTEOPTIMIZATION: + return "ro" + case XFRM_MODE_IN_TRIGGER: + return "in_trigger" + case XFRM_MODE_BEET: + return "beet" + } + return fmt.Sprintf("%d", m) +} + +// XfrmMark represents the mark associated to the state or policy +type XfrmMark struct { + Value uint32 + Mask uint32 +} + +func (m *XfrmMark) String() string { + return fmt.Sprintf("(0x%x,0x%x)", m.Value, m.Mask) +} diff --git a/vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go new file mode 100644 index 000000000..985d3a915 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go @@ -0,0 +1,101 @@ +package netlink + +import ( + "fmt" + + "github.com/vishvananda/netlink/nl" + "github.com/vishvananda/netns" + "golang.org/x/sys/unix" +) + +type XfrmMsg interface { + Type() nl.XfrmMsgType +} + +type XfrmMsgExpire struct { + XfrmState *XfrmState + Hard bool +} + +func (ue *XfrmMsgExpire) Type() nl.XfrmMsgType { + return nl.XFRM_MSG_EXPIRE +} + +func parseXfrmMsgExpire(b []byte) *XfrmMsgExpire { + var e XfrmMsgExpire + + msg := nl.DeserializeXfrmUserExpire(b) + e.XfrmState = xfrmStateFromXfrmUsersaInfo(&msg.XfrmUsersaInfo) + e.Hard = msg.Hard == 1 + + return &e +} + +func XfrmMonitor(ch chan<- XfrmMsg, done <-chan struct{}, errorChan chan<- error, + types ...nl.XfrmMsgType) error { + + groups, err := xfrmMcastGroups(types) + if err != nil { + return nil + } + s, err := nl.SubscribeAt(netns.None(), netns.None(), unix.NETLINK_XFRM, groups...) + if err != nil { + return err + } + + if done != nil { + go func() { + <-done + s.Close() + }() + + } + + go func() { + defer close(ch) + for { + msgs, from, err := s.Receive() + if err != nil { + errorChan <- err + return + } + if from.Pid != nl.PidKernel { + errorChan <- fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel) + return + } + for _, m := range msgs { + switch m.Header.Type { + case nl.XFRM_MSG_EXPIRE: + ch <- parseXfrmMsgExpire(m.Data) + default: + errorChan <- fmt.Errorf("unsupported msg type: %x", m.Header.Type) + } + } + } + }() + + return nil +} + +func xfrmMcastGroups(types []nl.XfrmMsgType) ([]uint, error) { + groups := make([]uint, 0) + + if len(types) == 0 { + return nil, fmt.Errorf("no xfrm msg type specified") + } + + for _, t := range types { + var group uint + + switch t { + case nl.XFRM_MSG_EXPIRE: + group = nl.XFRMNLGRP_EXPIRE + default: + return nil, fmt.Errorf("unsupported group: %x", t) + } + + groups = append(groups, group) + } + + return groups, nil +} diff --git a/vendor/github.com/vishvananda/netlink/xfrm_policy.go b/vendor/github.com/vishvananda/netlink/xfrm_policy.go new file mode 100644 index 000000000..b7532b092 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/xfrm_policy.go @@ -0,0 +1,97 @@ +package netlink + +import ( + "fmt" + "net" +) + +// Dir is an enum representing an ipsec template direction. +type Dir uint8 + +const ( + XFRM_DIR_IN Dir = iota + XFRM_DIR_OUT + XFRM_DIR_FWD + XFRM_SOCKET_IN + XFRM_SOCKET_OUT + XFRM_SOCKET_FWD +) + +func (d Dir) String() string { + switch d { + case XFRM_DIR_IN: + return "dir in" + case XFRM_DIR_OUT: + return "dir out" + case XFRM_DIR_FWD: + return "dir fwd" + case XFRM_SOCKET_IN: + return "socket in" + case XFRM_SOCKET_OUT: + return "socket out" + case XFRM_SOCKET_FWD: + return "socket fwd" + } + return fmt.Sprintf("socket %d", d-XFRM_SOCKET_IN) +} + +// PolicyAction is an enum representing an ipsec policy action. +type PolicyAction uint8 + +const ( + XFRM_POLICY_ALLOW PolicyAction = 0 + XFRM_POLICY_BLOCK PolicyAction = 1 +) + +func (a PolicyAction) String() string { + switch a { + case XFRM_POLICY_ALLOW: + return "allow" + case XFRM_POLICY_BLOCK: + return "block" + default: + return fmt.Sprintf("action %d", a) + } +} + +// XfrmPolicyTmpl encapsulates a rule for the base addresses of an ipsec +// policy. These rules are matched with XfrmState to determine encryption +// and authentication algorithms. +type XfrmPolicyTmpl struct { + Dst net.IP + Src net.IP + Proto Proto + Mode Mode + Spi int + Reqid int + Optional int +} + +func (t XfrmPolicyTmpl) String() string { + return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, Mode: %s, Spi: 0x%x, Reqid: 0x%x}", + t.Dst, t.Src, t.Proto, t.Mode, t.Spi, t.Reqid) +} + +// XfrmPolicy represents an ipsec policy. It represents the overlay network +// and has a list of XfrmPolicyTmpls representing the base addresses of +// the policy. +type XfrmPolicy struct { + Dst *net.IPNet + Src *net.IPNet + Proto Proto + DstPort int + SrcPort int + Dir Dir + Priority int + Index int + Action PolicyAction + Ifindex int + Ifid int + Mark *XfrmMark + Tmpls []XfrmPolicyTmpl +} + +func (p XfrmPolicy) String() string { + return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, DstPort: %d, SrcPort: %d, Dir: %s, Priority: %d, Index: %d, Action: %s, Ifindex: %d, Ifid: %d, Mark: %s, Tmpls: %s}", + p.Dst, p.Src, p.Proto, p.DstPort, p.SrcPort, p.Dir, p.Priority, p.Index, p.Action, p.Ifindex, p.Ifid, p.Mark, p.Tmpls) +} diff --git a/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go new file mode 100644 index 000000000..694bd74e6 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go @@ -0,0 +1,265 @@ +package netlink + +import ( + "github.com/vishvananda/netlink/nl" + "golang.org/x/sys/unix" +) + +func selFromPolicy(sel *nl.XfrmSelector, policy *XfrmPolicy) { + sel.Family = uint16(nl.FAMILY_V4) + if policy.Dst != nil { + sel.Family = uint16(nl.GetIPFamily(policy.Dst.IP)) + sel.Daddr.FromIP(policy.Dst.IP) + prefixlenD, _ := policy.Dst.Mask.Size() + sel.PrefixlenD = uint8(prefixlenD) + } + if policy.Src != nil { + sel.Saddr.FromIP(policy.Src.IP) + prefixlenS, _ := policy.Src.Mask.Size() + sel.PrefixlenS = uint8(prefixlenS) + } + sel.Proto = uint8(policy.Proto) + sel.Dport = nl.Swap16(uint16(policy.DstPort)) + sel.Sport = nl.Swap16(uint16(policy.SrcPort)) + if sel.Dport != 0 { + sel.DportMask = ^uint16(0) + } + if sel.Sport != 0 { + sel.SportMask = ^uint16(0) + } + sel.Ifindex = int32(policy.Ifindex) +} + +// XfrmPolicyAdd will add an xfrm policy to the system. +// Equivalent to: `ip xfrm policy add $policy` +func XfrmPolicyAdd(policy *XfrmPolicy) error { + return pkgHandle.XfrmPolicyAdd(policy) +} + +// XfrmPolicyAdd will add an xfrm policy to the system. +// Equivalent to: `ip xfrm policy add $policy` +func (h *Handle) XfrmPolicyAdd(policy *XfrmPolicy) error { + return h.xfrmPolicyAddOrUpdate(policy, nl.XFRM_MSG_NEWPOLICY) +} + +// XfrmPolicyUpdate will update an xfrm policy to the system. +// Equivalent to: `ip xfrm policy update $policy` +func XfrmPolicyUpdate(policy *XfrmPolicy) error { + return pkgHandle.XfrmPolicyUpdate(policy) +} + +// XfrmPolicyUpdate will update an xfrm policy to the system. +// Equivalent to: `ip xfrm policy update $policy` +func (h *Handle) XfrmPolicyUpdate(policy *XfrmPolicy) error { + return h.xfrmPolicyAddOrUpdate(policy, nl.XFRM_MSG_UPDPOLICY) +} + +func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error { + req := h.newNetlinkRequest(nlProto, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) + + msg := &nl.XfrmUserpolicyInfo{} + selFromPolicy(&msg.Sel, policy) + msg.Priority = uint32(policy.Priority) + msg.Index = uint32(policy.Index) + msg.Dir = uint8(policy.Dir) + msg.Action = uint8(policy.Action) + msg.Lft.SoftByteLimit = nl.XFRM_INF + msg.Lft.HardByteLimit = nl.XFRM_INF + msg.Lft.SoftPacketLimit = nl.XFRM_INF + msg.Lft.HardPacketLimit = nl.XFRM_INF + req.AddData(msg) + + tmplData := make([]byte, nl.SizeofXfrmUserTmpl*len(policy.Tmpls)) + for i, tmpl := range policy.Tmpls { + start := i * nl.SizeofXfrmUserTmpl + userTmpl := nl.DeserializeXfrmUserTmpl(tmplData[start : start+nl.SizeofXfrmUserTmpl]) + userTmpl.XfrmId.Daddr.FromIP(tmpl.Dst) + userTmpl.Saddr.FromIP(tmpl.Src) + userTmpl.XfrmId.Proto = uint8(tmpl.Proto) + userTmpl.XfrmId.Spi = nl.Swap32(uint32(tmpl.Spi)) + userTmpl.Mode = uint8(tmpl.Mode) + userTmpl.Reqid = uint32(tmpl.Reqid) + userTmpl.Optional = uint8(tmpl.Optional) + userTmpl.Aalgos = ^uint32(0) + userTmpl.Ealgos = ^uint32(0) + userTmpl.Calgos = ^uint32(0) + } + if len(tmplData) > 0 { + tmpls := nl.NewRtAttr(nl.XFRMA_TMPL, tmplData) + req.AddData(tmpls) + } + if policy.Mark != nil { + out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(policy.Mark)) + req.AddData(out) + } + + ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(policy.Ifid))) + req.AddData(ifId) + + _, err := req.Execute(unix.NETLINK_XFRM, 0) + return err +} + +// XfrmPolicyDel will delete an xfrm policy from the system. Note that +// the Tmpls are ignored when matching the policy to delete. +// Equivalent to: `ip xfrm policy del $policy` +func XfrmPolicyDel(policy *XfrmPolicy) error { + return pkgHandle.XfrmPolicyDel(policy) +} + +// XfrmPolicyDel will delete an xfrm policy from the system. Note that +// the Tmpls are ignored when matching the policy to delete. +// Equivalent to: `ip xfrm policy del $policy` +func (h *Handle) XfrmPolicyDel(policy *XfrmPolicy) error { + _, err := h.xfrmPolicyGetOrDelete(policy, nl.XFRM_MSG_DELPOLICY) + return err +} + +// XfrmPolicyList gets a list of xfrm policies in the system. +// Equivalent to: `ip xfrm policy show`. +// The list can be filtered by ip family. +func XfrmPolicyList(family int) ([]XfrmPolicy, error) { + return pkgHandle.XfrmPolicyList(family) +} + +// XfrmPolicyList gets a list of xfrm policies in the system. +// Equivalent to: `ip xfrm policy show`. +// The list can be filtered by ip family. +func (h *Handle) XfrmPolicyList(family int) ([]XfrmPolicy, error) { + req := h.newNetlinkRequest(nl.XFRM_MSG_GETPOLICY, unix.NLM_F_DUMP) + + msg := nl.NewIfInfomsg(family) + req.AddData(msg) + + msgs, err := req.Execute(unix.NETLINK_XFRM, nl.XFRM_MSG_NEWPOLICY) + if err != nil { + return nil, err + } + + var res []XfrmPolicy + for _, m := range msgs { + if policy, err := parseXfrmPolicy(m, family); err == nil { + res = append(res, *policy) + } else if err == familyError { + continue + } else { + return nil, err + } + } + return res, nil +} + +// XfrmPolicyGet gets a the policy described by the index or selector, if found. +// Equivalent to: `ip xfrm policy get { SELECTOR | index INDEX } dir DIR [ctx CTX ] [ mark MARK [ mask MASK ] ] [ ptype PTYPE ]`. +func XfrmPolicyGet(policy *XfrmPolicy) (*XfrmPolicy, error) { + return pkgHandle.XfrmPolicyGet(policy) +} + +// XfrmPolicyGet gets a the policy described by the index or selector, if found. +// Equivalent to: `ip xfrm policy get { SELECTOR | index INDEX } dir DIR [ctx CTX ] [ mark MARK [ mask MASK ] ] [ ptype PTYPE ]`. +func (h *Handle) XfrmPolicyGet(policy *XfrmPolicy) (*XfrmPolicy, error) { + return h.xfrmPolicyGetOrDelete(policy, nl.XFRM_MSG_GETPOLICY) +} + +// XfrmPolicyFlush will flush the policies on the system. +// Equivalent to: `ip xfrm policy flush` +func XfrmPolicyFlush() error { + return pkgHandle.XfrmPolicyFlush() +} + +// XfrmPolicyFlush will flush the policies on the system. +// Equivalent to: `ip xfrm policy flush` +func (h *Handle) XfrmPolicyFlush() error { + req := h.newNetlinkRequest(nl.XFRM_MSG_FLUSHPOLICY, unix.NLM_F_ACK) + _, err := req.Execute(unix.NETLINK_XFRM, 0) + return err +} + +func (h *Handle) xfrmPolicyGetOrDelete(policy *XfrmPolicy, nlProto int) (*XfrmPolicy, error) { + req := h.newNetlinkRequest(nlProto, unix.NLM_F_ACK) + + msg := &nl.XfrmUserpolicyId{} + selFromPolicy(&msg.Sel, policy) + msg.Index = uint32(policy.Index) + msg.Dir = uint8(policy.Dir) + req.AddData(msg) + + if policy.Mark != nil { + out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(policy.Mark)) + req.AddData(out) + } + + ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(policy.Ifid))) + req.AddData(ifId) + + resType := nl.XFRM_MSG_NEWPOLICY + if nlProto == nl.XFRM_MSG_DELPOLICY { + resType = 0 + } + + msgs, err := req.Execute(unix.NETLINK_XFRM, uint16(resType)) + if err != nil { + return nil, err + } + + if nlProto == nl.XFRM_MSG_DELPOLICY { + return nil, err + } + + return parseXfrmPolicy(msgs[0], FAMILY_ALL) +} + +func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) { + msg := nl.DeserializeXfrmUserpolicyInfo(m) + + // This is mainly for the policy dump + if family != FAMILY_ALL && family != int(msg.Sel.Family) { + return nil, familyError + } + + var policy XfrmPolicy + + policy.Dst = msg.Sel.Daddr.ToIPNet(msg.Sel.PrefixlenD) + policy.Src = msg.Sel.Saddr.ToIPNet(msg.Sel.PrefixlenS) + policy.Proto = Proto(msg.Sel.Proto) + policy.DstPort = int(nl.Swap16(msg.Sel.Dport)) + policy.SrcPort = int(nl.Swap16(msg.Sel.Sport)) + policy.Ifindex = int(msg.Sel.Ifindex) + policy.Priority = int(msg.Priority) + policy.Index = int(msg.Index) + policy.Dir = Dir(msg.Dir) + policy.Action = PolicyAction(msg.Action) + + attrs, err := nl.ParseRouteAttr(m[msg.Len():]) + if err != nil { + return nil, err + } + + for _, attr := range attrs { + switch attr.Attr.Type { + case nl.XFRMA_TMPL: + max := len(attr.Value) + for i := 0; i < max; i += nl.SizeofXfrmUserTmpl { + var resTmpl XfrmPolicyTmpl + tmpl := nl.DeserializeXfrmUserTmpl(attr.Value[i : i+nl.SizeofXfrmUserTmpl]) + resTmpl.Dst = tmpl.XfrmId.Daddr.ToIP() + resTmpl.Src = tmpl.Saddr.ToIP() + resTmpl.Proto = Proto(tmpl.XfrmId.Proto) + resTmpl.Mode = Mode(tmpl.Mode) + resTmpl.Spi = int(nl.Swap32(tmpl.XfrmId.Spi)) + resTmpl.Reqid = int(tmpl.Reqid) + resTmpl.Optional = int(tmpl.Optional) + policy.Tmpls = append(policy.Tmpls, resTmpl) + } + case nl.XFRMA_MARK: + mark := nl.DeserializeXfrmMark(attr.Value[:]) + policy.Mark = new(XfrmMark) + policy.Mark.Value = mark.Value + policy.Mark.Mask = mark.Mask + case nl.XFRMA_IF_ID: + policy.Ifid = int(native.Uint32(attr.Value)) + } + } + + return &policy, nil +} diff --git a/vendor/github.com/vishvananda/netlink/xfrm_state.go b/vendor/github.com/vishvananda/netlink/xfrm_state.go new file mode 100644 index 000000000..19df82c76 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/xfrm_state.go @@ -0,0 +1,131 @@ +package netlink + +import ( + "fmt" + "net" + "time" +) + +// XfrmStateAlgo represents the algorithm to use for the ipsec encryption. +type XfrmStateAlgo struct { + Name string + Key []byte + TruncateLen int // Auth only + ICVLen int // AEAD only +} + +func (a XfrmStateAlgo) String() string { + base := fmt.Sprintf("{Name: %s, Key: 0x%x", a.Name, a.Key) + if a.TruncateLen != 0 { + base = fmt.Sprintf("%s, Truncate length: %d", base, a.TruncateLen) + } + if a.ICVLen != 0 { + base = fmt.Sprintf("%s, ICV length: %d", base, a.ICVLen) + } + return fmt.Sprintf("%s}", base) +} + +// EncapType is an enum representing the optional packet encapsulation. +type EncapType uint8 + +const ( + XFRM_ENCAP_ESPINUDP_NONIKE EncapType = iota + 1 + XFRM_ENCAP_ESPINUDP +) + +func (e EncapType) String() string { + switch e { + case XFRM_ENCAP_ESPINUDP_NONIKE: + return "espinudp-non-ike" + case XFRM_ENCAP_ESPINUDP: + return "espinudp" + } + return "unknown" +} + +// XfrmStateEncap represents the encapsulation to use for the ipsec encryption. +type XfrmStateEncap struct { + Type EncapType + SrcPort int + DstPort int + OriginalAddress net.IP +} + +func (e XfrmStateEncap) String() string { + return fmt.Sprintf("{Type: %s, Srcport: %d, DstPort: %d, OriginalAddress: %v}", + e.Type, e.SrcPort, e.DstPort, e.OriginalAddress) +} + +// XfrmStateLimits represents the configured limits for the state. +type XfrmStateLimits struct { + ByteSoft uint64 + ByteHard uint64 + PacketSoft uint64 + PacketHard uint64 + TimeSoft uint64 + TimeHard uint64 + TimeUseSoft uint64 + TimeUseHard uint64 +} + +// XfrmStateStats represents the current number of bytes/packets +// processed by this State, the State's installation and first use +// time and the replay window counters. +type XfrmStateStats struct { + ReplayWindow uint32 + Replay uint32 + Failed uint32 + Bytes uint64 + Packets uint64 + AddTime uint64 + UseTime uint64 +} + +// XfrmState represents the state of an ipsec policy. It optionally +// contains an XfrmStateAlgo for encryption and one for authentication. +type XfrmState struct { + Dst net.IP + Src net.IP + Proto Proto + Mode Mode + Spi int + Reqid int + ReplayWindow int + Limits XfrmStateLimits + Statistics XfrmStateStats + Mark *XfrmMark + OutputMark *XfrmMark + Ifid int + Auth *XfrmStateAlgo + Crypt *XfrmStateAlgo + Aead *XfrmStateAlgo + Encap *XfrmStateEncap + ESN bool +} + +func (sa XfrmState) String() string { + return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, OutputMark: %v, Ifid: %d, Auth: %v, Crypt: %v, Aead: %v, Encap: %v, ESN: %t", + sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.OutputMark, sa.Ifid, sa.Auth, sa.Crypt, sa.Aead, sa.Encap, sa.ESN) +} +func (sa XfrmState) Print(stats bool) string { + if !stats { + return sa.String() + } + at := time.Unix(int64(sa.Statistics.AddTime), 0).Format(time.UnixDate) + ut := "-" + if sa.Statistics.UseTime > 0 { + ut = time.Unix(int64(sa.Statistics.UseTime), 0).Format(time.UnixDate) + } + return fmt.Sprintf("%s, ByteSoft: %s, ByteHard: %s, PacketSoft: %s, PacketHard: %s, TimeSoft: %d, TimeHard: %d, TimeUseSoft: %d, TimeUseHard: %d, Bytes: %d, Packets: %d, "+ + "AddTime: %s, UseTime: %s, ReplayWindow: %d, Replay: %d, Failed: %d", + sa.String(), printLimit(sa.Limits.ByteSoft), printLimit(sa.Limits.ByteHard), printLimit(sa.Limits.PacketSoft), printLimit(sa.Limits.PacketHard), + sa.Limits.TimeSoft, sa.Limits.TimeHard, sa.Limits.TimeUseSoft, sa.Limits.TimeUseHard, sa.Statistics.Bytes, sa.Statistics.Packets, at, ut, + sa.Statistics.ReplayWindow, sa.Statistics.Replay, sa.Statistics.Failed) +} + +func printLimit(lmt uint64) string { + if lmt == ^uint64(0) { + return "(INF)" + } + return fmt.Sprintf("%d", lmt) +} diff --git a/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go new file mode 100644 index 000000000..5b1b6c31a --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go @@ -0,0 +1,477 @@ +package netlink + +import ( + "fmt" + "unsafe" + + "github.com/vishvananda/netlink/nl" + "golang.org/x/sys/unix" +) + +func writeStateAlgo(a *XfrmStateAlgo) []byte { + algo := nl.XfrmAlgo{ + AlgKeyLen: uint32(len(a.Key) * 8), + AlgKey: a.Key, + } + end := len(a.Name) + if end > 64 { + end = 64 + } + copy(algo.AlgName[:end], a.Name) + return algo.Serialize() +} + +func writeStateAlgoAuth(a *XfrmStateAlgo) []byte { + algo := nl.XfrmAlgoAuth{ + AlgKeyLen: uint32(len(a.Key) * 8), + AlgTruncLen: uint32(a.TruncateLen), + AlgKey: a.Key, + } + end := len(a.Name) + if end > 64 { + end = 64 + } + copy(algo.AlgName[:end], a.Name) + return algo.Serialize() +} + +func writeStateAlgoAead(a *XfrmStateAlgo) []byte { + algo := nl.XfrmAlgoAEAD{ + AlgKeyLen: uint32(len(a.Key) * 8), + AlgICVLen: uint32(a.ICVLen), + AlgKey: a.Key, + } + end := len(a.Name) + if end > 64 { + end = 64 + } + copy(algo.AlgName[:end], a.Name) + return algo.Serialize() +} + +func writeMark(m *XfrmMark) []byte { + mark := &nl.XfrmMark{ + Value: m.Value, + Mask: m.Mask, + } + if mark.Mask == 0 { + mark.Mask = ^uint32(0) + } + return mark.Serialize() +} + +func writeReplayEsn(replayWindow int) []byte { + replayEsn := &nl.XfrmReplayStateEsn{ + OSeq: 0, + Seq: 0, + OSeqHi: 0, + SeqHi: 0, + ReplayWindow: uint32(replayWindow), + } + + // Linux stores the bitmap to identify the already received sequence packets in blocks of uint32 elements. + // Therefore bitmap length is the minimum number of uint32 elements needed. The following is a ceiling operation. + bytesPerElem := int(unsafe.Sizeof(replayEsn.BmpLen)) // Any uint32 variable is good for this + replayEsn.BmpLen = uint32((replayWindow + (bytesPerElem * 8) - 1) / (bytesPerElem * 8)) + + return replayEsn.Serialize() +} + +// XfrmStateAdd will add an xfrm state to the system. +// Equivalent to: `ip xfrm state add $state` +func XfrmStateAdd(state *XfrmState) error { + return pkgHandle.XfrmStateAdd(state) +} + +// XfrmStateAdd will add an xfrm state to the system. +// Equivalent to: `ip xfrm state add $state` +func (h *Handle) XfrmStateAdd(state *XfrmState) error { + return h.xfrmStateAddOrUpdate(state, nl.XFRM_MSG_NEWSA) +} + +// XfrmStateAllocSpi will allocate an xfrm state in the system. +// Equivalent to: `ip xfrm state allocspi` +func XfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) { + return pkgHandle.xfrmStateAllocSpi(state) +} + +// XfrmStateUpdate will update an xfrm state to the system. +// Equivalent to: `ip xfrm state update $state` +func XfrmStateUpdate(state *XfrmState) error { + return pkgHandle.XfrmStateUpdate(state) +} + +// XfrmStateUpdate will update an xfrm state to the system. +// Equivalent to: `ip xfrm state update $state` +func (h *Handle) XfrmStateUpdate(state *XfrmState) error { + return h.xfrmStateAddOrUpdate(state, nl.XFRM_MSG_UPDSA) +} + +func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error { + + // A state with spi 0 can't be deleted so don't allow it to be set + if state.Spi == 0 { + return fmt.Errorf("Spi must be set when adding xfrm state.") + } + req := h.newNetlinkRequest(nlProto, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) + + msg := xfrmUsersaInfoFromXfrmState(state) + + if state.ESN { + if state.ReplayWindow == 0 { + return fmt.Errorf("ESN flag set without ReplayWindow") + } + msg.Flags |= nl.XFRM_STATE_ESN + msg.ReplayWindow = 0 + } + + limitsToLft(state.Limits, &msg.Lft) + req.AddData(msg) + + if state.Auth != nil { + out := nl.NewRtAttr(nl.XFRMA_ALG_AUTH_TRUNC, writeStateAlgoAuth(state.Auth)) + req.AddData(out) + } + if state.Crypt != nil { + out := nl.NewRtAttr(nl.XFRMA_ALG_CRYPT, writeStateAlgo(state.Crypt)) + req.AddData(out) + } + if state.Aead != nil { + out := nl.NewRtAttr(nl.XFRMA_ALG_AEAD, writeStateAlgoAead(state.Aead)) + req.AddData(out) + } + if state.Encap != nil { + encapData := make([]byte, nl.SizeofXfrmEncapTmpl) + encap := nl.DeserializeXfrmEncapTmpl(encapData) + encap.EncapType = uint16(state.Encap.Type) + encap.EncapSport = nl.Swap16(uint16(state.Encap.SrcPort)) + encap.EncapDport = nl.Swap16(uint16(state.Encap.DstPort)) + encap.EncapOa.FromIP(state.Encap.OriginalAddress) + out := nl.NewRtAttr(nl.XFRMA_ENCAP, encapData) + req.AddData(out) + } + if state.Mark != nil { + out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(state.Mark)) + req.AddData(out) + } + if state.ESN { + out := nl.NewRtAttr(nl.XFRMA_REPLAY_ESN_VAL, writeReplayEsn(state.ReplayWindow)) + req.AddData(out) + } + if state.OutputMark != nil { + out := nl.NewRtAttr(nl.XFRMA_SET_MARK, nl.Uint32Attr(state.OutputMark.Value)) + req.AddData(out) + if state.OutputMark.Mask != 0 { + out = nl.NewRtAttr(nl.XFRMA_SET_MARK_MASK, nl.Uint32Attr(state.OutputMark.Mask)) + req.AddData(out) + } + } + + ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid))) + req.AddData(ifId) + + _, err := req.Execute(unix.NETLINK_XFRM, 0) + return err +} + +func (h *Handle) xfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) { + req := h.newNetlinkRequest(nl.XFRM_MSG_ALLOCSPI, + unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) + + msg := &nl.XfrmUserSpiInfo{} + msg.XfrmUsersaInfo = *(xfrmUsersaInfoFromXfrmState(state)) + // 1-255 is reserved by IANA for future use + msg.Min = 0x100 + msg.Max = 0xffffffff + req.AddData(msg) + + if state.Mark != nil { + out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(state.Mark)) + req.AddData(out) + } + + msgs, err := req.Execute(unix.NETLINK_XFRM, 0) + if err != nil { + return nil, err + } + + return parseXfrmState(msgs[0], FAMILY_ALL) +} + +// XfrmStateDel will delete an xfrm state from the system. Note that +// the Algos are ignored when matching the state to delete. +// Equivalent to: `ip xfrm state del $state` +func XfrmStateDel(state *XfrmState) error { + return pkgHandle.XfrmStateDel(state) +} + +// XfrmStateDel will delete an xfrm state from the system. Note that +// the Algos are ignored when matching the state to delete. +// Equivalent to: `ip xfrm state del $state` +func (h *Handle) XfrmStateDel(state *XfrmState) error { + _, err := h.xfrmStateGetOrDelete(state, nl.XFRM_MSG_DELSA) + return err +} + +// XfrmStateList gets a list of xfrm states in the system. +// Equivalent to: `ip [-4|-6] xfrm state show`. +// The list can be filtered by ip family. +func XfrmStateList(family int) ([]XfrmState, error) { + return pkgHandle.XfrmStateList(family) +} + +// XfrmStateList gets a list of xfrm states in the system. +// Equivalent to: `ip xfrm state show`. +// The list can be filtered by ip family. +func (h *Handle) XfrmStateList(family int) ([]XfrmState, error) { + req := h.newNetlinkRequest(nl.XFRM_MSG_GETSA, unix.NLM_F_DUMP) + + msgs, err := req.Execute(unix.NETLINK_XFRM, nl.XFRM_MSG_NEWSA) + if err != nil { + return nil, err + } + + var res []XfrmState + for _, m := range msgs { + if state, err := parseXfrmState(m, family); err == nil { + res = append(res, *state) + } else if err == familyError { + continue + } else { + return nil, err + } + } + return res, nil +} + +// XfrmStateGet gets the xfrm state described by the ID, if found. +// Equivalent to: `ip xfrm state get ID [ mark MARK [ mask MASK ] ]`. +// Only the fields which constitue the SA ID must be filled in: +// ID := [ src ADDR ] [ dst ADDR ] [ proto XFRM-PROTO ] [ spi SPI ] +// mark is optional +func XfrmStateGet(state *XfrmState) (*XfrmState, error) { + return pkgHandle.XfrmStateGet(state) +} + +// XfrmStateGet gets the xfrm state described by the ID, if found. +// Equivalent to: `ip xfrm state get ID [ mark MARK [ mask MASK ] ]`. +// Only the fields which constitue the SA ID must be filled in: +// ID := [ src ADDR ] [ dst ADDR ] [ proto XFRM-PROTO ] [ spi SPI ] +// mark is optional +func (h *Handle) XfrmStateGet(state *XfrmState) (*XfrmState, error) { + return h.xfrmStateGetOrDelete(state, nl.XFRM_MSG_GETSA) +} + +func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState, error) { + req := h.newNetlinkRequest(nlProto, unix.NLM_F_ACK) + + msg := &nl.XfrmUsersaId{} + msg.Family = uint16(nl.GetIPFamily(state.Dst)) + msg.Daddr.FromIP(state.Dst) + msg.Proto = uint8(state.Proto) + msg.Spi = nl.Swap32(uint32(state.Spi)) + req.AddData(msg) + + if state.Mark != nil { + out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(state.Mark)) + req.AddData(out) + } + if state.Src != nil { + out := nl.NewRtAttr(nl.XFRMA_SRCADDR, state.Src.To16()) + req.AddData(out) + } + + ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid))) + req.AddData(ifId) + + resType := nl.XFRM_MSG_NEWSA + if nlProto == nl.XFRM_MSG_DELSA { + resType = 0 + } + + msgs, err := req.Execute(unix.NETLINK_XFRM, uint16(resType)) + if err != nil { + return nil, err + } + + if nlProto == nl.XFRM_MSG_DELSA { + return nil, nil + } + + s, err := parseXfrmState(msgs[0], FAMILY_ALL) + if err != nil { + return nil, err + } + + return s, nil +} + +var familyError = fmt.Errorf("family error") + +func xfrmStateFromXfrmUsersaInfo(msg *nl.XfrmUsersaInfo) *XfrmState { + var state XfrmState + + state.Dst = msg.Id.Daddr.ToIP() + state.Src = msg.Saddr.ToIP() + state.Proto = Proto(msg.Id.Proto) + state.Mode = Mode(msg.Mode) + state.Spi = int(nl.Swap32(msg.Id.Spi)) + state.Reqid = int(msg.Reqid) + state.ReplayWindow = int(msg.ReplayWindow) + lftToLimits(&msg.Lft, &state.Limits) + curToStats(&msg.Curlft, &msg.Stats, &state.Statistics) + + return &state +} + +func parseXfrmState(m []byte, family int) (*XfrmState, error) { + msg := nl.DeserializeXfrmUsersaInfo(m) + + // This is mainly for the state dump + if family != FAMILY_ALL && family != int(msg.Family) { + return nil, familyError + } + + state := xfrmStateFromXfrmUsersaInfo(msg) + + attrs, err := nl.ParseRouteAttr(m[nl.SizeofXfrmUsersaInfo:]) + if err != nil { + return nil, err + } + + for _, attr := range attrs { + switch attr.Attr.Type { + case nl.XFRMA_ALG_AUTH, nl.XFRMA_ALG_CRYPT: + var resAlgo *XfrmStateAlgo + if attr.Attr.Type == nl.XFRMA_ALG_AUTH { + if state.Auth == nil { + state.Auth = new(XfrmStateAlgo) + } + resAlgo = state.Auth + } else { + state.Crypt = new(XfrmStateAlgo) + resAlgo = state.Crypt + } + algo := nl.DeserializeXfrmAlgo(attr.Value[:]) + (*resAlgo).Name = nl.BytesToString(algo.AlgName[:]) + (*resAlgo).Key = algo.AlgKey + case nl.XFRMA_ALG_AUTH_TRUNC: + if state.Auth == nil { + state.Auth = new(XfrmStateAlgo) + } + algo := nl.DeserializeXfrmAlgoAuth(attr.Value[:]) + state.Auth.Name = nl.BytesToString(algo.AlgName[:]) + state.Auth.Key = algo.AlgKey + state.Auth.TruncateLen = int(algo.AlgTruncLen) + case nl.XFRMA_ALG_AEAD: + state.Aead = new(XfrmStateAlgo) + algo := nl.DeserializeXfrmAlgoAEAD(attr.Value[:]) + state.Aead.Name = nl.BytesToString(algo.AlgName[:]) + state.Aead.Key = algo.AlgKey + state.Aead.ICVLen = int(algo.AlgICVLen) + case nl.XFRMA_ENCAP: + encap := nl.DeserializeXfrmEncapTmpl(attr.Value[:]) + state.Encap = new(XfrmStateEncap) + state.Encap.Type = EncapType(encap.EncapType) + state.Encap.SrcPort = int(nl.Swap16(encap.EncapSport)) + state.Encap.DstPort = int(nl.Swap16(encap.EncapDport)) + state.Encap.OriginalAddress = encap.EncapOa.ToIP() + case nl.XFRMA_MARK: + mark := nl.DeserializeXfrmMark(attr.Value[:]) + state.Mark = new(XfrmMark) + state.Mark.Value = mark.Value + state.Mark.Mask = mark.Mask + case nl.XFRMA_SET_MARK: + if state.OutputMark == nil { + state.OutputMark = new(XfrmMark) + } + state.OutputMark.Value = native.Uint32(attr.Value) + case nl.XFRMA_SET_MARK_MASK: + if state.OutputMark == nil { + state.OutputMark = new(XfrmMark) + } + state.OutputMark.Mask = native.Uint32(attr.Value) + if state.OutputMark.Mask == 0xffffffff { + state.OutputMark.Mask = 0 + } + case nl.XFRMA_IF_ID: + state.Ifid = int(native.Uint32(attr.Value)) + } + } + + return state, nil +} + +// XfrmStateFlush will flush the xfrm state on the system. +// proto = 0 means any transformation protocols +// Equivalent to: `ip xfrm state flush [ proto XFRM-PROTO ]` +func XfrmStateFlush(proto Proto) error { + return pkgHandle.XfrmStateFlush(proto) +} + +// XfrmStateFlush will flush the xfrm state on the system. +// proto = 0 means any transformation protocols +// Equivalent to: `ip xfrm state flush [ proto XFRM-PROTO ]` +func (h *Handle) XfrmStateFlush(proto Proto) error { + req := h.newNetlinkRequest(nl.XFRM_MSG_FLUSHSA, unix.NLM_F_ACK) + + req.AddData(&nl.XfrmUsersaFlush{Proto: uint8(proto)}) + + _, err := req.Execute(unix.NETLINK_XFRM, 0) + return err +} + +func limitsToLft(lmts XfrmStateLimits, lft *nl.XfrmLifetimeCfg) { + if lmts.ByteSoft != 0 { + lft.SoftByteLimit = lmts.ByteSoft + } else { + lft.SoftByteLimit = nl.XFRM_INF + } + if lmts.ByteHard != 0 { + lft.HardByteLimit = lmts.ByteHard + } else { + lft.HardByteLimit = nl.XFRM_INF + } + if lmts.PacketSoft != 0 { + lft.SoftPacketLimit = lmts.PacketSoft + } else { + lft.SoftPacketLimit = nl.XFRM_INF + } + if lmts.PacketHard != 0 { + lft.HardPacketLimit = lmts.PacketHard + } else { + lft.HardPacketLimit = nl.XFRM_INF + } + lft.SoftAddExpiresSeconds = lmts.TimeSoft + lft.HardAddExpiresSeconds = lmts.TimeHard + lft.SoftUseExpiresSeconds = lmts.TimeUseSoft + lft.HardUseExpiresSeconds = lmts.TimeUseHard +} + +func lftToLimits(lft *nl.XfrmLifetimeCfg, lmts *XfrmStateLimits) { + *lmts = *(*XfrmStateLimits)(unsafe.Pointer(lft)) +} + +func curToStats(cur *nl.XfrmLifetimeCur, wstats *nl.XfrmStats, stats *XfrmStateStats) { + stats.Bytes = cur.Bytes + stats.Packets = cur.Packets + stats.AddTime = cur.AddTime + stats.UseTime = cur.UseTime + stats.ReplayWindow = wstats.ReplayWindow + stats.Replay = wstats.Replay + stats.Failed = wstats.IntegrityFailed +} + +func xfrmUsersaInfoFromXfrmState(state *XfrmState) *nl.XfrmUsersaInfo { + msg := &nl.XfrmUsersaInfo{} + msg.Family = uint16(nl.GetIPFamily(state.Dst)) + msg.Id.Daddr.FromIP(state.Dst) + msg.Saddr.FromIP(state.Src) + msg.Id.Proto = uint8(state.Proto) + msg.Mode = uint8(state.Mode) + msg.Id.Spi = nl.Swap32(uint32(state.Spi)) + msg.Reqid = uint32(state.Reqid) + msg.ReplayWindow = uint8(state.ReplayWindow) + + return msg +} diff --git a/vendor/github.com/vishvananda/netns/LICENSE b/vendor/github.com/vishvananda/netns/LICENSE new file mode 100644 index 000000000..9f64db858 --- /dev/null +++ b/vendor/github.com/vishvananda/netns/LICENSE @@ -0,0 +1,192 @@ + + 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 + + Copyright 2014 Vishvananda Ishaya. + Copyright 2014 Docker, Inc. + + 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/vishvananda/netns/README.md b/vendor/github.com/vishvananda/netns/README.md new file mode 100644 index 000000000..1fdb2d3e4 --- /dev/null +++ b/vendor/github.com/vishvananda/netns/README.md @@ -0,0 +1,61 @@ +# netns - network namespaces in go # + +The netns package provides an ultra-simple interface for handling +network namespaces in go. Changing namespaces requires elevated +privileges, so in most cases this code needs to be run as root. + +## Local Build and Test ## + +You can use go get command: + + go get github.com/vishvananda/netns + +Testing (requires root): + + sudo -E go test github.com/vishvananda/netns + +## Example ## + +```go +package main + +import ( + "fmt" + "net" + "runtime" + "github.com/vishvananda/netns" +) + +func main() { + // Lock the OS Thread so we don't accidentally switch namespaces + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + // Save the current network namespace + origns, _ := netns.Get() + defer origns.Close() + + // Create a new network namespace + newns, _ := netns.New() + defer newns.Close() + + // Do something with the network namespace + ifaces, _ := net.Interfaces() + fmt.Printf("Interfaces: %v\n", ifaces) + + // Switch back to the original namespace + netns.Set(origns) +} + +``` + +## NOTE + +The library can be safely used only with Go >= 1.10 due to [golang/go#20676](https://github.com/golang/go/issues/20676). + +After locking a goroutine to its current OS thread with `runtime.LockOSThread()` +and changing its network namespace, any new subsequent goroutine won't be +scheduled on that thread while it's locked. Therefore, the new goroutine +will run in a different namespace leading to unexpected results. + +See [here](https://www.weave.works/blog/linux-namespaces-golang-followup) for more details. diff --git a/vendor/github.com/vishvananda/netns/go.mod b/vendor/github.com/vishvananda/netns/go.mod new file mode 100644 index 000000000..9cdf577ad --- /dev/null +++ b/vendor/github.com/vishvananda/netns/go.mod @@ -0,0 +1,5 @@ +module github.com/vishvananda/netns + +go 1.12 + +require golang.org/x/sys v0.0.0-20200217220822-9197077df867 diff --git a/vendor/github.com/vishvananda/netns/go.sum b/vendor/github.com/vishvananda/netns/go.sum new file mode 100644 index 000000000..1d4adf451 --- /dev/null +++ b/vendor/github.com/vishvananda/netns/go.sum @@ -0,0 +1,2 @@ +golang.org/x/sys v0.0.0-20200217220822-9197077df867 h1:JoRuNIf+rpHl+VhScRQQvzbHed86tKkqwPMV34T8myw= +golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vendor/github.com/vishvananda/netns/netns.go b/vendor/github.com/vishvananda/netns/netns.go new file mode 100644 index 000000000..116befd54 --- /dev/null +++ b/vendor/github.com/vishvananda/netns/netns.go @@ -0,0 +1,81 @@ +// Package netns allows ultra-simple network namespace handling. NsHandles +// can be retrieved and set. Note that the current namespace is thread +// local so actions that set and reset namespaces should use LockOSThread +// to make sure the namespace doesn't change due to a goroutine switch. +// It is best to close NsHandles when you are done with them. This can be +// accomplished via a `defer ns.Close()` on the handle. Changing namespaces +// requires elevated privileges, so in most cases this code needs to be run +// as root. +package netns + +import ( + "fmt" + + "golang.org/x/sys/unix" +) + +// NsHandle is a handle to a network namespace. It can be cast directly +// to an int and used as a file descriptor. +type NsHandle int + +// Equal determines if two network handles refer to the same network +// namespace. This is done by comparing the device and inode that the +// file descriptors point to. +func (ns NsHandle) Equal(other NsHandle) bool { + if ns == other { + return true + } + var s1, s2 unix.Stat_t + if err := unix.Fstat(int(ns), &s1); err != nil { + return false + } + if err := unix.Fstat(int(other), &s2); err != nil { + return false + } + return (s1.Dev == s2.Dev) && (s1.Ino == s2.Ino) +} + +// String shows the file descriptor number and its dev and inode. +func (ns NsHandle) String() string { + if ns == -1 { + return "NS(None)" + } + var s unix.Stat_t + if err := unix.Fstat(int(ns), &s); err != nil { + return fmt.Sprintf("NS(%d: unknown)", ns) + } + return fmt.Sprintf("NS(%d: %d, %d)", ns, s.Dev, s.Ino) +} + +// UniqueId returns a string which uniquely identifies the namespace +// associated with the network handle. +func (ns NsHandle) UniqueId() string { + if ns == -1 { + return "NS(none)" + } + var s unix.Stat_t + if err := unix.Fstat(int(ns), &s); err != nil { + return "NS(unknown)" + } + return fmt.Sprintf("NS(%d:%d)", s.Dev, s.Ino) +} + +// IsOpen returns true if Close() has not been called. +func (ns NsHandle) IsOpen() bool { + return ns != -1 +} + +// Close closes the NsHandle and resets its file descriptor to -1. +// It is not safe to use an NsHandle after Close() is called. +func (ns *NsHandle) Close() error { + if err := unix.Close(int(*ns)); err != nil { + return err + } + (*ns) = -1 + return nil +} + +// None gets an empty (closed) NsHandle. +func None() NsHandle { + return NsHandle(-1) +} diff --git a/vendor/github.com/vishvananda/netns/netns_linux.go b/vendor/github.com/vishvananda/netns/netns_linux.go new file mode 100644 index 000000000..36e64906b --- /dev/null +++ b/vendor/github.com/vishvananda/netns/netns_linux.go @@ -0,0 +1,266 @@ +// +build linux,go1.10 + +package netns + +import ( + "fmt" + "io/ioutil" + "os" + "path" + "path/filepath" + "strconv" + "strings" + "syscall" + + "golang.org/x/sys/unix" +) + +// Deprecated: use syscall pkg instead (go >= 1.5 needed). +const ( + CLONE_NEWUTS = 0x04000000 /* New utsname group? */ + CLONE_NEWIPC = 0x08000000 /* New ipcs */ + CLONE_NEWUSER = 0x10000000 /* New user namespace */ + CLONE_NEWPID = 0x20000000 /* New pid namespace */ + CLONE_NEWNET = 0x40000000 /* New network namespace */ + CLONE_IO = 0x80000000 /* Get io context */ + bindMountPath = "/run/netns" /* Bind mount path for named netns */ +) + +// Setns sets namespace using syscall. Note that this should be a method +// in syscall but it has not been added. +func Setns(ns NsHandle, nstype int) (err error) { + return unix.Setns(int(ns), nstype) +} + +// Set sets the current network namespace to the namespace represented +// by NsHandle. +func Set(ns NsHandle) (err error) { + return Setns(ns, CLONE_NEWNET) +} + +// New creates a new network namespace, sets it as current and returns +// a handle to it. +func New() (ns NsHandle, err error) { + if err := unix.Unshare(CLONE_NEWNET); err != nil { + return -1, err + } + return Get() +} + +// NewNamed creates a new named network namespace and returns a handle to it +func NewNamed(name string) (NsHandle, error) { + if _, err := os.Stat(bindMountPath); os.IsNotExist(err) { + err = os.MkdirAll(bindMountPath, 0755) + if err != nil { + return None(), err + } + } + + newNs, err := New() + if err != nil { + return None(), err + } + + namedPath := path.Join(bindMountPath, name) + + f, err := os.OpenFile(namedPath, os.O_CREATE|os.O_EXCL, 0444) + if err != nil { + return None(), err + } + f.Close() + + nsPath := fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), syscall.Gettid()) + err = syscall.Mount(nsPath, namedPath, "bind", syscall.MS_BIND, "") + if err != nil { + return None(), err + } + + return newNs, nil +} + +// DeleteNamed deletes a named network namespace +func DeleteNamed(name string) error { + namedPath := path.Join(bindMountPath, name) + + err := syscall.Unmount(namedPath, syscall.MNT_DETACH) + if err != nil { + return err + } + + return os.Remove(namedPath) +} + +// Get gets a handle to the current threads network namespace. +func Get() (NsHandle, error) { + return GetFromThread(os.Getpid(), unix.Gettid()) +} + +// GetFromPath gets a handle to a network namespace +// identified by the path +func GetFromPath(path string) (NsHandle, error) { + fd, err := unix.Open(path, unix.O_RDONLY|unix.O_CLOEXEC, 0) + if err != nil { + return -1, err + } + return NsHandle(fd), nil +} + +// GetFromName gets a handle to a named network namespace such as one +// created by `ip netns add`. +func GetFromName(name string) (NsHandle, error) { + return GetFromPath(fmt.Sprintf("/var/run/netns/%s", name)) +} + +// GetFromPid gets a handle to the network namespace of a given pid. +func GetFromPid(pid int) (NsHandle, error) { + return GetFromPath(fmt.Sprintf("/proc/%d/ns/net", pid)) +} + +// GetFromThread gets a handle to the network namespace of a given pid and tid. +func GetFromThread(pid, tid int) (NsHandle, error) { + return GetFromPath(fmt.Sprintf("/proc/%d/task/%d/ns/net", pid, tid)) +} + +// GetFromDocker gets a handle to the network namespace of a docker container. +// Id is prefixed matched against the running docker containers, so a short +// identifier can be used as long as it isn't ambiguous. +func GetFromDocker(id string) (NsHandle, error) { + pid, err := getPidForContainer(id) + if err != nil { + return -1, err + } + return GetFromPid(pid) +} + +// borrowed from docker/utils/utils.go +func findCgroupMountpoint(cgroupType string) (string, error) { + output, err := ioutil.ReadFile("/proc/mounts") + if err != nil { + return "", err + } + + // /proc/mounts has 6 fields per line, one mount per line, e.g. + // cgroup /sys/fs/cgroup/devices cgroup rw,relatime,devices 0 0 + for _, line := range strings.Split(string(output), "\n") { + parts := strings.Split(line, " ") + if len(parts) == 6 && parts[2] == "cgroup" { + for _, opt := range strings.Split(parts[3], ",") { + if opt == cgroupType { + return parts[1], nil + } + } + } + } + + return "", fmt.Errorf("cgroup mountpoint not found for %s", cgroupType) +} + +// Returns the relative path to the cgroup docker is running in. +// borrowed from docker/utils/utils.go +// modified to get the docker pid instead of using /proc/self +func getThisCgroup(cgroupType string) (string, error) { + dockerpid, err := ioutil.ReadFile("/var/run/docker.pid") + if err != nil { + return "", err + } + result := strings.Split(string(dockerpid), "\n") + if len(result) == 0 || len(result[0]) == 0 { + return "", fmt.Errorf("docker pid not found in /var/run/docker.pid") + } + pid, err := strconv.Atoi(result[0]) + if err != nil { + return "", err + } + output, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cgroup", pid)) + if err != nil { + return "", err + } + for _, line := range strings.Split(string(output), "\n") { + parts := strings.Split(line, ":") + // any type used by docker should work + if parts[1] == cgroupType { + return parts[2], nil + } + } + return "", fmt.Errorf("cgroup '%s' not found in /proc/%d/cgroup", cgroupType, pid) +} + +// Returns the first pid in a container. +// borrowed from docker/utils/utils.go +// modified to only return the first pid +// modified to glob with id +// modified to search for newer docker containers +func getPidForContainer(id string) (int, error) { + pid := 0 + + // memory is chosen randomly, any cgroup used by docker works + cgroupType := "memory" + + cgroupRoot, err := findCgroupMountpoint(cgroupType) + if err != nil { + return pid, err + } + + cgroupThis, err := getThisCgroup(cgroupType) + if err != nil { + return pid, err + } + + id += "*" + + attempts := []string{ + filepath.Join(cgroupRoot, cgroupThis, id, "tasks"), + // With more recent lxc versions use, cgroup will be in lxc/ + filepath.Join(cgroupRoot, cgroupThis, "lxc", id, "tasks"), + // With more recent docker, cgroup will be in docker/ + filepath.Join(cgroupRoot, cgroupThis, "docker", id, "tasks"), + // Even more recent docker versions under systemd use docker-.scope/ + filepath.Join(cgroupRoot, "system.slice", "docker-"+id+".scope", "tasks"), + // Even more recent docker versions under cgroup/systemd/docker// + filepath.Join(cgroupRoot, "..", "systemd", "docker", id, "tasks"), + // Kubernetes with docker and CNI is even more different. Works for BestEffort and Burstable QoS + filepath.Join(cgroupRoot, "..", "systemd", "kubepods", "*", "pod*", id, "tasks"), + // Same as above but for Guaranteed QoS + filepath.Join(cgroupRoot, "..", "systemd", "kubepods", "pod*", id, "tasks"), + // Another flavor of containers location in recent kubernetes 1.11+. Works for BestEffort and Burstable QoS + filepath.Join(cgroupRoot, cgroupThis, "kubepods.slice", "*.slice", "*", "docker-"+id+".scope", "tasks"), + // Same as above but for Guaranteed QoS + filepath.Join(cgroupRoot, cgroupThis, "kubepods.slice", "*", "docker-"+id+".scope", "tasks"), + // When runs inside of a container with recent kubernetes 1.11+. Works for BestEffort and Burstable QoS + filepath.Join(cgroupRoot, "kubepods.slice", "*.slice", "*", "docker-"+id+".scope", "tasks"), + // Same as above but for Guaranteed QoS + filepath.Join(cgroupRoot, "kubepods.slice", "*", "docker-"+id+".scope", "tasks"), + } + + var filename string + for _, attempt := range attempts { + filenames, _ := filepath.Glob(attempt) + if len(filenames) > 1 { + return pid, fmt.Errorf("Ambiguous id supplied: %v", filenames) + } else if len(filenames) == 1 { + filename = filenames[0] + break + } + } + + if filename == "" { + return pid, fmt.Errorf("Unable to find container: %v", id[:len(id)-1]) + } + + output, err := ioutil.ReadFile(filename) + if err != nil { + return pid, err + } + + result := strings.Split(string(output), "\n") + if len(result) == 0 || len(result[0]) == 0 { + return pid, fmt.Errorf("No pid found for container") + } + + pid, err = strconv.Atoi(result[0]) + if err != nil { + return pid, fmt.Errorf("Invalid pid '%s': %s", result[0], err) + } + + return pid, nil +} diff --git a/vendor/github.com/vishvananda/netns/netns_unspecified.go b/vendor/github.com/vishvananda/netns/netns_unspecified.go new file mode 100644 index 000000000..d06af62b6 --- /dev/null +++ b/vendor/github.com/vishvananda/netns/netns_unspecified.go @@ -0,0 +1,43 @@ +// +build !linux + +package netns + +import ( + "errors" +) + +var ( + ErrNotImplemented = errors.New("not implemented") +) + +func Set(ns NsHandle) (err error) { + return ErrNotImplemented +} + +func New() (ns NsHandle, err error) { + return -1, ErrNotImplemented +} + +func Get() (NsHandle, error) { + return -1, ErrNotImplemented +} + +func GetFromPath(path string) (NsHandle, error) { + return -1, ErrNotImplemented +} + +func GetFromName(name string) (NsHandle, error) { + return -1, ErrNotImplemented +} + +func GetFromPid(pid int) (NsHandle, error) { + return -1, ErrNotImplemented +} + +func GetFromThread(pid, tid int) (NsHandle, error) { + return -1, ErrNotImplemented +} + +func GetFromDocker(id string) (NsHandle, error) { + return -1, ErrNotImplemented +} diff --git a/vendor/k8s.io/cri-api/pkg/apis/runtime/v1/api.pb.go b/vendor/k8s.io/cri-api/pkg/apis/runtime/v1/api.pb.go index 9504bf0d9..85d48cd65 100644 --- a/vendor/k8s.io/cri-api/pkg/apis/runtime/v1/api.pb.go +++ b/vendor/k8s.io/cri-api/pkg/apis/runtime/v1/api.pb.go @@ -933,9 +933,13 @@ type LinuxPodSandboxConfig struct { // LinuxSandboxSecurityContext holds sandbox security attributes. SecurityContext *LinuxSandboxSecurityContext `protobuf:"bytes,2,opt,name=security_context,json=securityContext,proto3" json:"security_context,omitempty"` // Sysctls holds linux sysctls config for the sandbox. - Sysctls map[string]string `protobuf:"bytes,3,rep,name=sysctls,proto3" json:"sysctls,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_sizecache int32 `json:"-"` + Sysctls map[string]string `protobuf:"bytes,3,rep,name=sysctls,proto3" json:"sysctls,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // Optional overhead represents the overheads associated with this sandbox + Overhead *LinuxContainerResources `protobuf:"bytes,4,opt,name=overhead,proto3" json:"overhead,omitempty"` + // Optional resources represents the sum of container resources for this sandbox + Resources *LinuxContainerResources `protobuf:"bytes,5,opt,name=resources,proto3" json:"resources,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *LinuxPodSandboxConfig) Reset() { *m = LinuxPodSandboxConfig{} } @@ -991,6 +995,20 @@ func (m *LinuxPodSandboxConfig) GetSysctls() map[string]string { return nil } +func (m *LinuxPodSandboxConfig) GetOverhead() *LinuxContainerResources { + if m != nil { + return m.Overhead + } + return nil +} + +func (m *LinuxPodSandboxConfig) GetResources() *LinuxContainerResources { + if m != nil { + return m.Resources + } + return nil +} + // PodSandboxMetadata holds all necessary information for building the sandbox name. // The container runtime is encouraged to expose the metadata associated with the // PodSandbox in its user interface for better user experience. For example, @@ -2230,6 +2248,716 @@ func (m *ListPodSandboxResponse) GetItems() []*PodSandbox { return nil } +type PodSandboxStatsRequest struct { + // ID of the pod sandbox for which to retrieve stats. + PodSandboxId string `protobuf:"bytes,1,opt,name=pod_sandbox_id,json=podSandboxId,proto3" json:"pod_sandbox_id,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PodSandboxStatsRequest) Reset() { *m = PodSandboxStatsRequest{} } +func (*PodSandboxStatsRequest) ProtoMessage() {} +func (*PodSandboxStatsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{30} +} +func (m *PodSandboxStatsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PodSandboxStatsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PodSandboxStatsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PodSandboxStatsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_PodSandboxStatsRequest.Merge(m, src) +} +func (m *PodSandboxStatsRequest) XXX_Size() int { + return m.Size() +} +func (m *PodSandboxStatsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_PodSandboxStatsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_PodSandboxStatsRequest proto.InternalMessageInfo + +func (m *PodSandboxStatsRequest) GetPodSandboxId() string { + if m != nil { + return m.PodSandboxId + } + return "" +} + +type PodSandboxStatsResponse struct { + Stats *PodSandboxStats `protobuf:"bytes,1,opt,name=stats,proto3" json:"stats,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PodSandboxStatsResponse) Reset() { *m = PodSandboxStatsResponse{} } +func (*PodSandboxStatsResponse) ProtoMessage() {} +func (*PodSandboxStatsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{31} +} +func (m *PodSandboxStatsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PodSandboxStatsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PodSandboxStatsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PodSandboxStatsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_PodSandboxStatsResponse.Merge(m, src) +} +func (m *PodSandboxStatsResponse) XXX_Size() int { + return m.Size() +} +func (m *PodSandboxStatsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_PodSandboxStatsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_PodSandboxStatsResponse proto.InternalMessageInfo + +func (m *PodSandboxStatsResponse) GetStats() *PodSandboxStats { + if m != nil { + return m.Stats + } + return nil +} + +// PodSandboxStatsFilter is used to filter the list of pod sandboxes to retrieve stats for. +// All those fields are combined with 'AND'. +type PodSandboxStatsFilter struct { + // ID of the pod sandbox. + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // LabelSelector to select matches. + // Only api.MatchLabels is supported for now and the requirements + // are ANDed. MatchExpressions is not supported yet. + LabelSelector map[string]string `protobuf:"bytes,2,rep,name=label_selector,json=labelSelector,proto3" json:"label_selector,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PodSandboxStatsFilter) Reset() { *m = PodSandboxStatsFilter{} } +func (*PodSandboxStatsFilter) ProtoMessage() {} +func (*PodSandboxStatsFilter) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{32} +} +func (m *PodSandboxStatsFilter) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PodSandboxStatsFilter) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PodSandboxStatsFilter.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PodSandboxStatsFilter) XXX_Merge(src proto.Message) { + xxx_messageInfo_PodSandboxStatsFilter.Merge(m, src) +} +func (m *PodSandboxStatsFilter) XXX_Size() int { + return m.Size() +} +func (m *PodSandboxStatsFilter) XXX_DiscardUnknown() { + xxx_messageInfo_PodSandboxStatsFilter.DiscardUnknown(m) +} + +var xxx_messageInfo_PodSandboxStatsFilter proto.InternalMessageInfo + +func (m *PodSandboxStatsFilter) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +func (m *PodSandboxStatsFilter) GetLabelSelector() map[string]string { + if m != nil { + return m.LabelSelector + } + return nil +} + +type ListPodSandboxStatsRequest struct { + // Filter for the list request. + Filter *PodSandboxStatsFilter `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ListPodSandboxStatsRequest) Reset() { *m = ListPodSandboxStatsRequest{} } +func (*ListPodSandboxStatsRequest) ProtoMessage() {} +func (*ListPodSandboxStatsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{33} +} +func (m *ListPodSandboxStatsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ListPodSandboxStatsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ListPodSandboxStatsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ListPodSandboxStatsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListPodSandboxStatsRequest.Merge(m, src) +} +func (m *ListPodSandboxStatsRequest) XXX_Size() int { + return m.Size() +} +func (m *ListPodSandboxStatsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ListPodSandboxStatsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ListPodSandboxStatsRequest proto.InternalMessageInfo + +func (m *ListPodSandboxStatsRequest) GetFilter() *PodSandboxStatsFilter { + if m != nil { + return m.Filter + } + return nil +} + +type ListPodSandboxStatsResponse struct { + // Stats of the pod sandbox. + Stats []*PodSandboxStats `protobuf:"bytes,1,rep,name=stats,proto3" json:"stats,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ListPodSandboxStatsResponse) Reset() { *m = ListPodSandboxStatsResponse{} } +func (*ListPodSandboxStatsResponse) ProtoMessage() {} +func (*ListPodSandboxStatsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{34} +} +func (m *ListPodSandboxStatsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ListPodSandboxStatsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ListPodSandboxStatsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ListPodSandboxStatsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListPodSandboxStatsResponse.Merge(m, src) +} +func (m *ListPodSandboxStatsResponse) XXX_Size() int { + return m.Size() +} +func (m *ListPodSandboxStatsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ListPodSandboxStatsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_ListPodSandboxStatsResponse proto.InternalMessageInfo + +func (m *ListPodSandboxStatsResponse) GetStats() []*PodSandboxStats { + if m != nil { + return m.Stats + } + return nil +} + +// PodSandboxAttributes provides basic information of the pod sandbox. +type PodSandboxAttributes struct { + // ID of the pod. + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Metadata of the pod. + Metadata *PodSandboxMetadata `protobuf:"bytes,2,opt,name=metadata,proto3" json:"metadata,omitempty"` + // Key-value pairs that may be used to scope and select individual resources. + Labels map[string]string `protobuf:"bytes,3,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // Unstructured key-value map holding arbitrary metadata. + // Annotations MUST NOT be altered by the runtime; the value of this field + // MUST be identical to that of the corresponding PodSandboxStatus used to + // instantiate the PodSandbox this status represents. + Annotations map[string]string `protobuf:"bytes,4,rep,name=annotations,proto3" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PodSandboxAttributes) Reset() { *m = PodSandboxAttributes{} } +func (*PodSandboxAttributes) ProtoMessage() {} +func (*PodSandboxAttributes) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{35} +} +func (m *PodSandboxAttributes) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PodSandboxAttributes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PodSandboxAttributes.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PodSandboxAttributes) XXX_Merge(src proto.Message) { + xxx_messageInfo_PodSandboxAttributes.Merge(m, src) +} +func (m *PodSandboxAttributes) XXX_Size() int { + return m.Size() +} +func (m *PodSandboxAttributes) XXX_DiscardUnknown() { + xxx_messageInfo_PodSandboxAttributes.DiscardUnknown(m) +} + +var xxx_messageInfo_PodSandboxAttributes proto.InternalMessageInfo + +func (m *PodSandboxAttributes) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +func (m *PodSandboxAttributes) GetMetadata() *PodSandboxMetadata { + if m != nil { + return m.Metadata + } + return nil +} + +func (m *PodSandboxAttributes) GetLabels() map[string]string { + if m != nil { + return m.Labels + } + return nil +} + +func (m *PodSandboxAttributes) GetAnnotations() map[string]string { + if m != nil { + return m.Annotations + } + return nil +} + +// PodSandboxStats provides the resource usage statistics for a pod. +// The linux or windows field will be populated depending on the platform. +type PodSandboxStats struct { + // Information of the pod. + Attributes *PodSandboxAttributes `protobuf:"bytes,1,opt,name=attributes,proto3" json:"attributes,omitempty"` + // Stats from linux. + Linux *LinuxPodSandboxStats `protobuf:"bytes,2,opt,name=linux,proto3" json:"linux,omitempty"` + // Stats from windows. + Windows *WindowsPodSandboxStats `protobuf:"bytes,3,opt,name=windows,proto3" json:"windows,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PodSandboxStats) Reset() { *m = PodSandboxStats{} } +func (*PodSandboxStats) ProtoMessage() {} +func (*PodSandboxStats) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{36} +} +func (m *PodSandboxStats) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PodSandboxStats) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PodSandboxStats.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PodSandboxStats) XXX_Merge(src proto.Message) { + xxx_messageInfo_PodSandboxStats.Merge(m, src) +} +func (m *PodSandboxStats) XXX_Size() int { + return m.Size() +} +func (m *PodSandboxStats) XXX_DiscardUnknown() { + xxx_messageInfo_PodSandboxStats.DiscardUnknown(m) +} + +var xxx_messageInfo_PodSandboxStats proto.InternalMessageInfo + +func (m *PodSandboxStats) GetAttributes() *PodSandboxAttributes { + if m != nil { + return m.Attributes + } + return nil +} + +func (m *PodSandboxStats) GetLinux() *LinuxPodSandboxStats { + if m != nil { + return m.Linux + } + return nil +} + +func (m *PodSandboxStats) GetWindows() *WindowsPodSandboxStats { + if m != nil { + return m.Windows + } + return nil +} + +// LinuxPodSandboxStats provides the resource usage statistics for a pod sandbox on linux. +type LinuxPodSandboxStats struct { + // CPU usage gathered for the pod sandbox. + Cpu *CpuUsage `protobuf:"bytes,1,opt,name=cpu,proto3" json:"cpu,omitempty"` + // Memory usage gathered for the pod sandbox. + Memory *MemoryUsage `protobuf:"bytes,2,opt,name=memory,proto3" json:"memory,omitempty"` + // Network usage gathered for the pod sandbox + Network *NetworkUsage `protobuf:"bytes,3,opt,name=network,proto3" json:"network,omitempty"` + // Stats pertaining to processes in the pod sandbox. + Process *ProcessUsage `protobuf:"bytes,4,opt,name=process,proto3" json:"process,omitempty"` + // Stats of containers in the measured pod sandbox. + Containers []*ContainerStats `protobuf:"bytes,5,rep,name=containers,proto3" json:"containers,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *LinuxPodSandboxStats) Reset() { *m = LinuxPodSandboxStats{} } +func (*LinuxPodSandboxStats) ProtoMessage() {} +func (*LinuxPodSandboxStats) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{37} +} +func (m *LinuxPodSandboxStats) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *LinuxPodSandboxStats) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_LinuxPodSandboxStats.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *LinuxPodSandboxStats) XXX_Merge(src proto.Message) { + xxx_messageInfo_LinuxPodSandboxStats.Merge(m, src) +} +func (m *LinuxPodSandboxStats) XXX_Size() int { + return m.Size() +} +func (m *LinuxPodSandboxStats) XXX_DiscardUnknown() { + xxx_messageInfo_LinuxPodSandboxStats.DiscardUnknown(m) +} + +var xxx_messageInfo_LinuxPodSandboxStats proto.InternalMessageInfo + +func (m *LinuxPodSandboxStats) GetCpu() *CpuUsage { + if m != nil { + return m.Cpu + } + return nil +} + +func (m *LinuxPodSandboxStats) GetMemory() *MemoryUsage { + if m != nil { + return m.Memory + } + return nil +} + +func (m *LinuxPodSandboxStats) GetNetwork() *NetworkUsage { + if m != nil { + return m.Network + } + return nil +} + +func (m *LinuxPodSandboxStats) GetProcess() *ProcessUsage { + if m != nil { + return m.Process + } + return nil +} + +func (m *LinuxPodSandboxStats) GetContainers() []*ContainerStats { + if m != nil { + return m.Containers + } + return nil +} + +// WindowsPodSandboxStats provides the resource usage statistics for a pod sandbox on windows +type WindowsPodSandboxStats struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *WindowsPodSandboxStats) Reset() { *m = WindowsPodSandboxStats{} } +func (*WindowsPodSandboxStats) ProtoMessage() {} +func (*WindowsPodSandboxStats) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{38} +} +func (m *WindowsPodSandboxStats) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *WindowsPodSandboxStats) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_WindowsPodSandboxStats.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *WindowsPodSandboxStats) XXX_Merge(src proto.Message) { + xxx_messageInfo_WindowsPodSandboxStats.Merge(m, src) +} +func (m *WindowsPodSandboxStats) XXX_Size() int { + return m.Size() +} +func (m *WindowsPodSandboxStats) XXX_DiscardUnknown() { + xxx_messageInfo_WindowsPodSandboxStats.DiscardUnknown(m) +} + +var xxx_messageInfo_WindowsPodSandboxStats proto.InternalMessageInfo + +// NetworkUsage contains data about network resources. +type NetworkUsage struct { + // The time at which these stats were updated. + Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // Stats for the default network interface. + DefaultInterface *NetworkInterfaceUsage `protobuf:"bytes,2,opt,name=default_interface,json=defaultInterface,proto3" json:"default_interface,omitempty"` + // Stats for all found network interfaces, excluding the default. + Interfaces []*NetworkInterfaceUsage `protobuf:"bytes,3,rep,name=interfaces,proto3" json:"interfaces,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *NetworkUsage) Reset() { *m = NetworkUsage{} } +func (*NetworkUsage) ProtoMessage() {} +func (*NetworkUsage) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{39} +} +func (m *NetworkUsage) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *NetworkUsage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_NetworkUsage.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *NetworkUsage) XXX_Merge(src proto.Message) { + xxx_messageInfo_NetworkUsage.Merge(m, src) +} +func (m *NetworkUsage) XXX_Size() int { + return m.Size() +} +func (m *NetworkUsage) XXX_DiscardUnknown() { + xxx_messageInfo_NetworkUsage.DiscardUnknown(m) +} + +var xxx_messageInfo_NetworkUsage proto.InternalMessageInfo + +func (m *NetworkUsage) GetTimestamp() int64 { + if m != nil { + return m.Timestamp + } + return 0 +} + +func (m *NetworkUsage) GetDefaultInterface() *NetworkInterfaceUsage { + if m != nil { + return m.DefaultInterface + } + return nil +} + +func (m *NetworkUsage) GetInterfaces() []*NetworkInterfaceUsage { + if m != nil { + return m.Interfaces + } + return nil +} + +// NetworkInterfaceUsage contains resource value data about a network interface. +type NetworkInterfaceUsage struct { + // The name of the network interface. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // Cumulative count of bytes received. + RxBytes *UInt64Value `protobuf:"bytes,2,opt,name=rx_bytes,json=rxBytes,proto3" json:"rx_bytes,omitempty"` + // Cumulative count of receive errors encountered. + RxErrors *UInt64Value `protobuf:"bytes,3,opt,name=rx_errors,json=rxErrors,proto3" json:"rx_errors,omitempty"` + // Cumulative count of bytes transmitted. + TxBytes *UInt64Value `protobuf:"bytes,4,opt,name=tx_bytes,json=txBytes,proto3" json:"tx_bytes,omitempty"` + // Cumulative count of transmit errors encountered. + TxErrors *UInt64Value `protobuf:"bytes,5,opt,name=tx_errors,json=txErrors,proto3" json:"tx_errors,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *NetworkInterfaceUsage) Reset() { *m = NetworkInterfaceUsage{} } +func (*NetworkInterfaceUsage) ProtoMessage() {} +func (*NetworkInterfaceUsage) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{40} +} +func (m *NetworkInterfaceUsage) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *NetworkInterfaceUsage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_NetworkInterfaceUsage.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *NetworkInterfaceUsage) XXX_Merge(src proto.Message) { + xxx_messageInfo_NetworkInterfaceUsage.Merge(m, src) +} +func (m *NetworkInterfaceUsage) XXX_Size() int { + return m.Size() +} +func (m *NetworkInterfaceUsage) XXX_DiscardUnknown() { + xxx_messageInfo_NetworkInterfaceUsage.DiscardUnknown(m) +} + +var xxx_messageInfo_NetworkInterfaceUsage proto.InternalMessageInfo + +func (m *NetworkInterfaceUsage) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *NetworkInterfaceUsage) GetRxBytes() *UInt64Value { + if m != nil { + return m.RxBytes + } + return nil +} + +func (m *NetworkInterfaceUsage) GetRxErrors() *UInt64Value { + if m != nil { + return m.RxErrors + } + return nil +} + +func (m *NetworkInterfaceUsage) GetTxBytes() *UInt64Value { + if m != nil { + return m.TxBytes + } + return nil +} + +func (m *NetworkInterfaceUsage) GetTxErrors() *UInt64Value { + if m != nil { + return m.TxErrors + } + return nil +} + +// ProcessUsage are stats pertaining to processes. +type ProcessUsage struct { + // The time at which these stats were updated. + Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // Number of processes. + ProcessCount *UInt64Value `protobuf:"bytes,2,opt,name=process_count,json=processCount,proto3" json:"process_count,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ProcessUsage) Reset() { *m = ProcessUsage{} } +func (*ProcessUsage) ProtoMessage() {} +func (*ProcessUsage) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{41} +} +func (m *ProcessUsage) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ProcessUsage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ProcessUsage.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ProcessUsage) XXX_Merge(src proto.Message) { + xxx_messageInfo_ProcessUsage.Merge(m, src) +} +func (m *ProcessUsage) XXX_Size() int { + return m.Size() +} +func (m *ProcessUsage) XXX_DiscardUnknown() { + xxx_messageInfo_ProcessUsage.DiscardUnknown(m) +} + +var xxx_messageInfo_ProcessUsage proto.InternalMessageInfo + +func (m *ProcessUsage) GetTimestamp() int64 { + if m != nil { + return m.Timestamp + } + return 0 +} + +func (m *ProcessUsage) GetProcessCount() *UInt64Value { + if m != nil { + return m.ProcessCount + } + return nil +} + // ImageSpec is an internal representation of an image. type ImageSpec struct { // Container's Image field (e.g. imageID or imageDigest). @@ -2245,7 +2973,7 @@ type ImageSpec struct { func (m *ImageSpec) Reset() { *m = ImageSpec{} } func (*ImageSpec) ProtoMessage() {} func (*ImageSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{30} + return fileDescriptor_00212fb1f9d3bf1c, []int{42} } func (m *ImageSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2298,7 +3026,7 @@ type KeyValue struct { func (m *KeyValue) Reset() { *m = KeyValue{} } func (*KeyValue) ProtoMessage() {} func (*KeyValue) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{31} + return fileDescriptor_00212fb1f9d3bf1c, []int{43} } func (m *KeyValue) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2373,7 +3101,7 @@ type LinuxContainerResources struct { func (m *LinuxContainerResources) Reset() { *m = LinuxContainerResources{} } func (*LinuxContainerResources) ProtoMessage() {} func (*LinuxContainerResources) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{32} + return fileDescriptor_00212fb1f9d3bf1c, []int{44} } func (m *LinuxContainerResources) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2488,7 +3216,7 @@ type HugepageLimit struct { func (m *HugepageLimit) Reset() { *m = HugepageLimit{} } func (*HugepageLimit) ProtoMessage() {} func (*HugepageLimit) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{33} + return fileDescriptor_00212fb1f9d3bf1c, []int{45} } func (m *HugepageLimit) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2544,7 +3272,7 @@ type SELinuxOption struct { func (m *SELinuxOption) Reset() { *m = SELinuxOption{} } func (*SELinuxOption) ProtoMessage() {} func (*SELinuxOption) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{34} + return fileDescriptor_00212fb1f9d3bf1c, []int{46} } func (m *SELinuxOption) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2614,7 +3342,7 @@ type Capability struct { func (m *Capability) Reset() { *m = Capability{} } func (*Capability) ProtoMessage() {} func (*Capability) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{35} + return fileDescriptor_00212fb1f9d3bf1c, []int{47} } func (m *Capability) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2734,7 +3462,7 @@ type LinuxContainerSecurityContext struct { func (m *LinuxContainerSecurityContext) Reset() { *m = LinuxContainerSecurityContext{} } func (*LinuxContainerSecurityContext) ProtoMessage() {} func (*LinuxContainerSecurityContext) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{36} + return fileDescriptor_00212fb1f9d3bf1c, []int{48} } func (m *LinuxContainerSecurityContext) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2891,7 +3619,7 @@ type LinuxContainerConfig struct { func (m *LinuxContainerConfig) Reset() { *m = LinuxContainerConfig{} } func (*LinuxContainerConfig) ProtoMessage() {} func (*LinuxContainerConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{37} + return fileDescriptor_00212fb1f9d3bf1c, []int{49} } func (m *LinuxContainerConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2953,7 +3681,7 @@ type WindowsSandboxSecurityContext struct { func (m *WindowsSandboxSecurityContext) Reset() { *m = WindowsSandboxSecurityContext{} } func (*WindowsSandboxSecurityContext) ProtoMessage() {} func (*WindowsSandboxSecurityContext) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{38} + return fileDescriptor_00212fb1f9d3bf1c, []int{50} } func (m *WindowsSandboxSecurityContext) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3015,7 +3743,7 @@ type WindowsPodSandboxConfig struct { func (m *WindowsPodSandboxConfig) Reset() { *m = WindowsPodSandboxConfig{} } func (*WindowsPodSandboxConfig) ProtoMessage() {} func (*WindowsPodSandboxConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{39} + return fileDescriptor_00212fb1f9d3bf1c, []int{51} } func (m *WindowsPodSandboxConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3068,7 +3796,7 @@ type WindowsContainerSecurityContext struct { func (m *WindowsContainerSecurityContext) Reset() { *m = WindowsContainerSecurityContext{} } func (*WindowsContainerSecurityContext) ProtoMessage() {} func (*WindowsContainerSecurityContext) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{40} + return fileDescriptor_00212fb1f9d3bf1c, []int{52} } func (m *WindowsContainerSecurityContext) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3132,7 +3860,7 @@ type WindowsContainerConfig struct { func (m *WindowsContainerConfig) Reset() { *m = WindowsContainerConfig{} } func (*WindowsContainerConfig) ProtoMessage() {} func (*WindowsContainerConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{41} + return fileDescriptor_00212fb1f9d3bf1c, []int{53} } func (m *WindowsContainerConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3193,7 +3921,7 @@ type WindowsContainerResources struct { func (m *WindowsContainerResources) Reset() { *m = WindowsContainerResources{} } func (*WindowsContainerResources) ProtoMessage() {} func (*WindowsContainerResources) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{42} + return fileDescriptor_00212fb1f9d3bf1c, []int{54} } func (m *WindowsContainerResources) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3267,7 +3995,7 @@ type ContainerMetadata struct { func (m *ContainerMetadata) Reset() { *m = ContainerMetadata{} } func (*ContainerMetadata) ProtoMessage() {} func (*ContainerMetadata) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{43} + return fileDescriptor_00212fb1f9d3bf1c, []int{55} } func (m *ContainerMetadata) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3328,7 +4056,7 @@ type Device struct { func (m *Device) Reset() { *m = Device{} } func (*Device) ProtoMessage() {} func (*Device) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{44} + return fileDescriptor_00212fb1f9d3bf1c, []int{56} } func (m *Device) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3445,7 +4173,7 @@ type ContainerConfig struct { func (m *ContainerConfig) Reset() { *m = ContainerConfig{} } func (*ContainerConfig) ProtoMessage() {} func (*ContainerConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{45} + return fileDescriptor_00212fb1f9d3bf1c, []int{57} } func (m *ContainerConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3603,7 +4331,7 @@ type CreateContainerRequest struct { func (m *CreateContainerRequest) Reset() { *m = CreateContainerRequest{} } func (*CreateContainerRequest) ProtoMessage() {} func (*CreateContainerRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{46} + return fileDescriptor_00212fb1f9d3bf1c, []int{58} } func (m *CreateContainerRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3663,7 +4391,7 @@ type CreateContainerResponse struct { func (m *CreateContainerResponse) Reset() { *m = CreateContainerResponse{} } func (*CreateContainerResponse) ProtoMessage() {} func (*CreateContainerResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{47} + return fileDescriptor_00212fb1f9d3bf1c, []int{59} } func (m *CreateContainerResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3709,7 +4437,7 @@ type StartContainerRequest struct { func (m *StartContainerRequest) Reset() { *m = StartContainerRequest{} } func (*StartContainerRequest) ProtoMessage() {} func (*StartContainerRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{48} + return fileDescriptor_00212fb1f9d3bf1c, []int{60} } func (m *StartContainerRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3753,7 +4481,7 @@ type StartContainerResponse struct { func (m *StartContainerResponse) Reset() { *m = StartContainerResponse{} } func (*StartContainerResponse) ProtoMessage() {} func (*StartContainerResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{49} + return fileDescriptor_00212fb1f9d3bf1c, []int{61} } func (m *StartContainerResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3795,7 +4523,7 @@ type StopContainerRequest struct { func (m *StopContainerRequest) Reset() { *m = StopContainerRequest{} } func (*StopContainerRequest) ProtoMessage() {} func (*StopContainerRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{50} + return fileDescriptor_00212fb1f9d3bf1c, []int{62} } func (m *StopContainerRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3846,7 +4574,7 @@ type StopContainerResponse struct { func (m *StopContainerResponse) Reset() { *m = StopContainerResponse{} } func (*StopContainerResponse) ProtoMessage() {} func (*StopContainerResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{51} + return fileDescriptor_00212fb1f9d3bf1c, []int{63} } func (m *StopContainerResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3885,7 +4613,7 @@ type RemoveContainerRequest struct { func (m *RemoveContainerRequest) Reset() { *m = RemoveContainerRequest{} } func (*RemoveContainerRequest) ProtoMessage() {} func (*RemoveContainerRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{52} + return fileDescriptor_00212fb1f9d3bf1c, []int{64} } func (m *RemoveContainerRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3929,7 +4657,7 @@ type RemoveContainerResponse struct { func (m *RemoveContainerResponse) Reset() { *m = RemoveContainerResponse{} } func (*RemoveContainerResponse) ProtoMessage() {} func (*RemoveContainerResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{53} + return fileDescriptor_00212fb1f9d3bf1c, []int{65} } func (m *RemoveContainerResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3969,7 +4697,7 @@ type ContainerStateValue struct { func (m *ContainerStateValue) Reset() { *m = ContainerStateValue{} } func (*ContainerStateValue) ProtoMessage() {} func (*ContainerStateValue) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{54} + return fileDescriptor_00212fb1f9d3bf1c, []int{66} } func (m *ContainerStateValue) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4025,7 +4753,7 @@ type ContainerFilter struct { func (m *ContainerFilter) Reset() { *m = ContainerFilter{} } func (*ContainerFilter) ProtoMessage() {} func (*ContainerFilter) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{55} + return fileDescriptor_00212fb1f9d3bf1c, []int{67} } func (m *ContainerFilter) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4091,7 +4819,7 @@ type ListContainersRequest struct { func (m *ListContainersRequest) Reset() { *m = ListContainersRequest{} } func (*ListContainersRequest) ProtoMessage() {} func (*ListContainersRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{56} + return fileDescriptor_00212fb1f9d3bf1c, []int{68} } func (m *ListContainersRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4160,7 +4888,7 @@ type Container struct { func (m *Container) Reset() { *m = Container{} } func (*Container) ProtoMessage() {} func (*Container) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{57} + return fileDescriptor_00212fb1f9d3bf1c, []int{69} } func (m *Container) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4262,7 +4990,7 @@ type ListContainersResponse struct { func (m *ListContainersResponse) Reset() { *m = ListContainersResponse{} } func (*ListContainersResponse) ProtoMessage() {} func (*ListContainersResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{58} + return fileDescriptor_00212fb1f9d3bf1c, []int{70} } func (m *ListContainersResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4310,7 +5038,7 @@ type ContainerStatusRequest struct { func (m *ContainerStatusRequest) Reset() { *m = ContainerStatusRequest{} } func (*ContainerStatusRequest) ProtoMessage() {} func (*ContainerStatusRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{59} + return fileDescriptor_00212fb1f9d3bf1c, []int{71} } func (m *ContainerStatusRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4397,7 +5125,7 @@ type ContainerStatus struct { func (m *ContainerStatus) Reset() { *m = ContainerStatus{} } func (*ContainerStatus) ProtoMessage() {} func (*ContainerStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{60} + return fileDescriptor_00212fb1f9d3bf1c, []int{72} } func (m *ContainerStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4546,7 +5274,7 @@ type ContainerStatusResponse struct { func (m *ContainerStatusResponse) Reset() { *m = ContainerStatusResponse{} } func (*ContainerStatusResponse) ProtoMessage() {} func (*ContainerStatusResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{61} + return fileDescriptor_00212fb1f9d3bf1c, []int{73} } func (m *ContainerStatusResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4607,7 +5335,7 @@ type UpdateContainerResourcesRequest struct { func (m *UpdateContainerResourcesRequest) Reset() { *m = UpdateContainerResourcesRequest{} } func (*UpdateContainerResourcesRequest) ProtoMessage() {} func (*UpdateContainerResourcesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{62} + return fileDescriptor_00212fb1f9d3bf1c, []int{74} } func (m *UpdateContainerResourcesRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4672,7 +5400,7 @@ type UpdateContainerResourcesResponse struct { func (m *UpdateContainerResourcesResponse) Reset() { *m = UpdateContainerResourcesResponse{} } func (*UpdateContainerResourcesResponse) ProtoMessage() {} func (*UpdateContainerResourcesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{63} + return fileDescriptor_00212fb1f9d3bf1c, []int{75} } func (m *UpdateContainerResourcesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4715,7 +5443,7 @@ type ExecSyncRequest struct { func (m *ExecSyncRequest) Reset() { *m = ExecSyncRequest{} } func (*ExecSyncRequest) ProtoMessage() {} func (*ExecSyncRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{64} + return fileDescriptor_00212fb1f9d3bf1c, []int{76} } func (m *ExecSyncRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4779,7 +5507,7 @@ type ExecSyncResponse struct { func (m *ExecSyncResponse) Reset() { *m = ExecSyncResponse{} } func (*ExecSyncResponse) ProtoMessage() {} func (*ExecSyncResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{65} + return fileDescriptor_00212fb1f9d3bf1c, []int{77} } func (m *ExecSyncResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4855,7 +5583,7 @@ type ExecRequest struct { func (m *ExecRequest) Reset() { *m = ExecRequest{} } func (*ExecRequest) ProtoMessage() {} func (*ExecRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{66} + return fileDescriptor_00212fb1f9d3bf1c, []int{78} } func (m *ExecRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4936,7 +5664,7 @@ type ExecResponse struct { func (m *ExecResponse) Reset() { *m = ExecResponse{} } func (*ExecResponse) ProtoMessage() {} func (*ExecResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{67} + return fileDescriptor_00212fb1f9d3bf1c, []int{79} } func (m *ExecResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4997,7 +5725,7 @@ type AttachRequest struct { func (m *AttachRequest) Reset() { *m = AttachRequest{} } func (*AttachRequest) ProtoMessage() {} func (*AttachRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{68} + return fileDescriptor_00212fb1f9d3bf1c, []int{80} } func (m *AttachRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5071,7 +5799,7 @@ type AttachResponse struct { func (m *AttachResponse) Reset() { *m = AttachResponse{} } func (*AttachResponse) ProtoMessage() {} func (*AttachResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{69} + return fileDescriptor_00212fb1f9d3bf1c, []int{81} } func (m *AttachResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5119,7 +5847,7 @@ type PortForwardRequest struct { func (m *PortForwardRequest) Reset() { *m = PortForwardRequest{} } func (*PortForwardRequest) ProtoMessage() {} func (*PortForwardRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{70} + return fileDescriptor_00212fb1f9d3bf1c, []int{82} } func (m *PortForwardRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5172,7 +5900,7 @@ type PortForwardResponse struct { func (m *PortForwardResponse) Reset() { *m = PortForwardResponse{} } func (*PortForwardResponse) ProtoMessage() {} func (*PortForwardResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{71} + return fileDescriptor_00212fb1f9d3bf1c, []int{83} } func (m *PortForwardResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5218,7 +5946,7 @@ type ImageFilter struct { func (m *ImageFilter) Reset() { *m = ImageFilter{} } func (*ImageFilter) ProtoMessage() {} func (*ImageFilter) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{72} + return fileDescriptor_00212fb1f9d3bf1c, []int{84} } func (m *ImageFilter) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5264,7 +5992,7 @@ type ListImagesRequest struct { func (m *ListImagesRequest) Reset() { *m = ListImagesRequest{} } func (*ListImagesRequest) ProtoMessage() {} func (*ListImagesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{73} + return fileDescriptor_00212fb1f9d3bf1c, []int{85} } func (m *ListImagesRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5326,7 +6054,7 @@ type Image struct { func (m *Image) Reset() { *m = Image{} } func (*Image) ProtoMessage() {} func (*Image) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{74} + return fileDescriptor_00212fb1f9d3bf1c, []int{86} } func (m *Image) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5414,7 +6142,7 @@ type ListImagesResponse struct { func (m *ListImagesResponse) Reset() { *m = ListImagesResponse{} } func (*ListImagesResponse) ProtoMessage() {} func (*ListImagesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{75} + return fileDescriptor_00212fb1f9d3bf1c, []int{87} } func (m *ListImagesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5462,7 +6190,7 @@ type ImageStatusRequest struct { func (m *ImageStatusRequest) Reset() { *m = ImageStatusRequest{} } func (*ImageStatusRequest) ProtoMessage() {} func (*ImageStatusRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{76} + return fileDescriptor_00212fb1f9d3bf1c, []int{88} } func (m *ImageStatusRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5520,7 +6248,7 @@ type ImageStatusResponse struct { func (m *ImageStatusResponse) Reset() { *m = ImageStatusResponse{} } func (*ImageStatusResponse) ProtoMessage() {} func (*ImageStatusResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{77} + return fileDescriptor_00212fb1f9d3bf1c, []int{89} } func (m *ImageStatusResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5581,7 +6309,7 @@ type AuthConfig struct { func (m *AuthConfig) Reset() { *m = AuthConfig{} } func (*AuthConfig) ProtoMessage() {} func (*AuthConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{78} + return fileDescriptor_00212fb1f9d3bf1c, []int{90} } func (m *AuthConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5666,7 +6394,7 @@ type PullImageRequest struct { func (m *PullImageRequest) Reset() { *m = PullImageRequest{} } func (*PullImageRequest) ProtoMessage() {} func (*PullImageRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{79} + return fileDescriptor_00212fb1f9d3bf1c, []int{91} } func (m *PullImageRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5727,7 +6455,7 @@ type PullImageResponse struct { func (m *PullImageResponse) Reset() { *m = PullImageResponse{} } func (*PullImageResponse) ProtoMessage() {} func (*PullImageResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{80} + return fileDescriptor_00212fb1f9d3bf1c, []int{92} } func (m *PullImageResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5773,7 +6501,7 @@ type RemoveImageRequest struct { func (m *RemoveImageRequest) Reset() { *m = RemoveImageRequest{} } func (*RemoveImageRequest) ProtoMessage() {} func (*RemoveImageRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{81} + return fileDescriptor_00212fb1f9d3bf1c, []int{93} } func (m *RemoveImageRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5817,7 +6545,7 @@ type RemoveImageResponse struct { func (m *RemoveImageResponse) Reset() { *m = RemoveImageResponse{} } func (*RemoveImageResponse) ProtoMessage() {} func (*RemoveImageResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{82} + return fileDescriptor_00212fb1f9d3bf1c, []int{94} } func (m *RemoveImageResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5857,7 +6585,7 @@ type NetworkConfig struct { func (m *NetworkConfig) Reset() { *m = NetworkConfig{} } func (*NetworkConfig) ProtoMessage() {} func (*NetworkConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{83} + return fileDescriptor_00212fb1f9d3bf1c, []int{95} } func (m *NetworkConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5902,7 +6630,7 @@ type RuntimeConfig struct { func (m *RuntimeConfig) Reset() { *m = RuntimeConfig{} } func (*RuntimeConfig) ProtoMessage() {} func (*RuntimeConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{84} + return fileDescriptor_00212fb1f9d3bf1c, []int{96} } func (m *RuntimeConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5947,7 +6675,7 @@ type UpdateRuntimeConfigRequest struct { func (m *UpdateRuntimeConfigRequest) Reset() { *m = UpdateRuntimeConfigRequest{} } func (*UpdateRuntimeConfigRequest) ProtoMessage() {} func (*UpdateRuntimeConfigRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{85} + return fileDescriptor_00212fb1f9d3bf1c, []int{97} } func (m *UpdateRuntimeConfigRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5991,7 +6719,7 @@ type UpdateRuntimeConfigResponse struct { func (m *UpdateRuntimeConfigResponse) Reset() { *m = UpdateRuntimeConfigResponse{} } func (*UpdateRuntimeConfigResponse) ProtoMessage() {} func (*UpdateRuntimeConfigResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{86} + return fileDescriptor_00212fb1f9d3bf1c, []int{98} } func (m *UpdateRuntimeConfigResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6049,7 +6777,7 @@ type RuntimeCondition struct { func (m *RuntimeCondition) Reset() { *m = RuntimeCondition{} } func (*RuntimeCondition) ProtoMessage() {} func (*RuntimeCondition) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{87} + return fileDescriptor_00212fb1f9d3bf1c, []int{99} } func (m *RuntimeCondition) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6117,7 +6845,7 @@ type RuntimeStatus struct { func (m *RuntimeStatus) Reset() { *m = RuntimeStatus{} } func (*RuntimeStatus) ProtoMessage() {} func (*RuntimeStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{88} + return fileDescriptor_00212fb1f9d3bf1c, []int{100} } func (m *RuntimeStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6163,7 +6891,7 @@ type StatusRequest struct { func (m *StatusRequest) Reset() { *m = StatusRequest{} } func (*StatusRequest) ProtoMessage() {} func (*StatusRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{89} + return fileDescriptor_00212fb1f9d3bf1c, []int{101} } func (m *StatusRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6214,7 +6942,7 @@ type StatusResponse struct { func (m *StatusResponse) Reset() { *m = StatusResponse{} } func (*StatusResponse) ProtoMessage() {} func (*StatusResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{90} + return fileDescriptor_00212fb1f9d3bf1c, []int{102} } func (m *StatusResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6265,7 +6993,7 @@ type ImageFsInfoRequest struct { func (m *ImageFsInfoRequest) Reset() { *m = ImageFsInfoRequest{} } func (*ImageFsInfoRequest) ProtoMessage() {} func (*ImageFsInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{91} + return fileDescriptor_00212fb1f9d3bf1c, []int{103} } func (m *ImageFsInfoRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6305,7 +7033,7 @@ type UInt64Value struct { func (m *UInt64Value) Reset() { *m = UInt64Value{} } func (*UInt64Value) ProtoMessage() {} func (*UInt64Value) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{92} + return fileDescriptor_00212fb1f9d3bf1c, []int{104} } func (m *UInt64Value) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6352,7 +7080,7 @@ type FilesystemIdentifier struct { func (m *FilesystemIdentifier) Reset() { *m = FilesystemIdentifier{} } func (*FilesystemIdentifier) ProtoMessage() {} func (*FilesystemIdentifier) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{93} + return fileDescriptor_00212fb1f9d3bf1c, []int{105} } func (m *FilesystemIdentifier) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6409,7 +7137,7 @@ type FilesystemUsage struct { func (m *FilesystemUsage) Reset() { *m = FilesystemUsage{} } func (*FilesystemUsage) ProtoMessage() {} func (*FilesystemUsage) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{94} + return fileDescriptor_00212fb1f9d3bf1c, []int{106} } func (m *FilesystemUsage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6476,7 +7204,7 @@ type ImageFsInfoResponse struct { func (m *ImageFsInfoResponse) Reset() { *m = ImageFsInfoResponse{} } func (*ImageFsInfoResponse) ProtoMessage() {} func (*ImageFsInfoResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{95} + return fileDescriptor_00212fb1f9d3bf1c, []int{107} } func (m *ImageFsInfoResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6522,7 +7250,7 @@ type ContainerStatsRequest struct { func (m *ContainerStatsRequest) Reset() { *m = ContainerStatsRequest{} } func (*ContainerStatsRequest) ProtoMessage() {} func (*ContainerStatsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{96} + return fileDescriptor_00212fb1f9d3bf1c, []int{108} } func (m *ContainerStatsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6568,7 +7296,7 @@ type ContainerStatsResponse struct { func (m *ContainerStatsResponse) Reset() { *m = ContainerStatsResponse{} } func (*ContainerStatsResponse) ProtoMessage() {} func (*ContainerStatsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{97} + return fileDescriptor_00212fb1f9d3bf1c, []int{109} } func (m *ContainerStatsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6614,7 +7342,7 @@ type ListContainerStatsRequest struct { func (m *ListContainerStatsRequest) Reset() { *m = ListContainerStatsRequest{} } func (*ListContainerStatsRequest) ProtoMessage() {} func (*ListContainerStatsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{98} + return fileDescriptor_00212fb1f9d3bf1c, []int{110} } func (m *ListContainerStatsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6668,7 +7396,7 @@ type ContainerStatsFilter struct { func (m *ContainerStatsFilter) Reset() { *m = ContainerStatsFilter{} } func (*ContainerStatsFilter) ProtoMessage() {} func (*ContainerStatsFilter) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{99} + return fileDescriptor_00212fb1f9d3bf1c, []int{111} } func (m *ContainerStatsFilter) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6728,7 +7456,7 @@ type ListContainerStatsResponse struct { func (m *ListContainerStatsResponse) Reset() { *m = ListContainerStatsResponse{} } func (*ListContainerStatsResponse) ProtoMessage() {} func (*ListContainerStatsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{100} + return fileDescriptor_00212fb1f9d3bf1c, []int{112} } func (m *ListContainerStatsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6784,7 +7512,7 @@ type ContainerAttributes struct { func (m *ContainerAttributes) Reset() { *m = ContainerAttributes{} } func (*ContainerAttributes) ProtoMessage() {} func (*ContainerAttributes) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{101} + return fileDescriptor_00212fb1f9d3bf1c, []int{113} } func (m *ContainerAttributes) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6858,7 +7586,7 @@ type ContainerStats struct { func (m *ContainerStats) Reset() { *m = ContainerStats{} } func (*ContainerStats) ProtoMessage() {} func (*ContainerStats) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{102} + return fileDescriptor_00212fb1f9d3bf1c, []int{114} } func (m *ContainerStats) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6921,6 +7649,9 @@ type CpuUsage struct { Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Cumulative CPU usage (sum across all cores) since object creation. UsageCoreNanoSeconds *UInt64Value `protobuf:"bytes,2,opt,name=usage_core_nano_seconds,json=usageCoreNanoSeconds,proto3" json:"usage_core_nano_seconds,omitempty"` + // Total CPU usage (sum of all cores) averaged over the sample window. + // The "core" unit can be interpreted as CPU core-nanoseconds per second. + UsageNanoCores *UInt64Value `protobuf:"bytes,3,opt,name=usage_nano_cores,json=usageNanoCores,proto3" json:"usage_nano_cores,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_sizecache int32 `json:"-"` } @@ -6928,7 +7659,7 @@ type CpuUsage struct { func (m *CpuUsage) Reset() { *m = CpuUsage{} } func (*CpuUsage) ProtoMessage() {} func (*CpuUsage) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{103} + return fileDescriptor_00212fb1f9d3bf1c, []int{115} } func (m *CpuUsage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6971,12 +7702,29 @@ func (m *CpuUsage) GetUsageCoreNanoSeconds() *UInt64Value { return nil } +func (m *CpuUsage) GetUsageNanoCores() *UInt64Value { + if m != nil { + return m.UsageNanoCores + } + return nil +} + // MemoryUsage provides the memory usage information. type MemoryUsage struct { // Timestamp in nanoseconds at which the information were collected. Must be > 0. Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // The amount of working set memory in bytes. - WorkingSetBytes *UInt64Value `protobuf:"bytes,2,opt,name=working_set_bytes,json=workingSetBytes,proto3" json:"working_set_bytes,omitempty"` + WorkingSetBytes *UInt64Value `protobuf:"bytes,2,opt,name=working_set_bytes,json=workingSetBytes,proto3" json:"working_set_bytes,omitempty"` + // Available memory for use. This is defined as the memory limit - workingSetBytes. + AvailableBytes *UInt64Value `protobuf:"bytes,3,opt,name=available_bytes,json=availableBytes,proto3" json:"available_bytes,omitempty"` + // Total memory in use. This includes all memory regardless of when it was accessed. + UsageBytes *UInt64Value `protobuf:"bytes,4,opt,name=usage_bytes,json=usageBytes,proto3" json:"usage_bytes,omitempty"` + // The amount of anonymous and swap cache memory (includes transparent hugepages). + RssBytes *UInt64Value `protobuf:"bytes,5,opt,name=rss_bytes,json=rssBytes,proto3" json:"rss_bytes,omitempty"` + // Cumulative number of minor page faults. + PageFaults *UInt64Value `protobuf:"bytes,6,opt,name=page_faults,json=pageFaults,proto3" json:"page_faults,omitempty"` + // Cumulative number of major page faults. + MajorPageFaults *UInt64Value `protobuf:"bytes,7,opt,name=major_page_faults,json=majorPageFaults,proto3" json:"major_page_faults,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_sizecache int32 `json:"-"` } @@ -6984,7 +7732,7 @@ type MemoryUsage struct { func (m *MemoryUsage) Reset() { *m = MemoryUsage{} } func (*MemoryUsage) ProtoMessage() {} func (*MemoryUsage) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{104} + return fileDescriptor_00212fb1f9d3bf1c, []int{116} } func (m *MemoryUsage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -7027,6 +7775,41 @@ func (m *MemoryUsage) GetWorkingSetBytes() *UInt64Value { return nil } +func (m *MemoryUsage) GetAvailableBytes() *UInt64Value { + if m != nil { + return m.AvailableBytes + } + return nil +} + +func (m *MemoryUsage) GetUsageBytes() *UInt64Value { + if m != nil { + return m.UsageBytes + } + return nil +} + +func (m *MemoryUsage) GetRssBytes() *UInt64Value { + if m != nil { + return m.RssBytes + } + return nil +} + +func (m *MemoryUsage) GetPageFaults() *UInt64Value { + if m != nil { + return m.PageFaults + } + return nil +} + +func (m *MemoryUsage) GetMajorPageFaults() *UInt64Value { + if m != nil { + return m.MajorPageFaults + } + return nil +} + type ReopenContainerLogRequest struct { // ID of the container for which to reopen the log. ContainerId string `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` @@ -7037,7 +7820,7 @@ type ReopenContainerLogRequest struct { func (m *ReopenContainerLogRequest) Reset() { *m = ReopenContainerLogRequest{} } func (*ReopenContainerLogRequest) ProtoMessage() {} func (*ReopenContainerLogRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{105} + return fileDescriptor_00212fb1f9d3bf1c, []int{117} } func (m *ReopenContainerLogRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -7081,7 +7864,7 @@ type ReopenContainerLogResponse struct { func (m *ReopenContainerLogResponse) Reset() { *m = ReopenContainerLogResponse{} } func (*ReopenContainerLogResponse) ProtoMessage() {} func (*ReopenContainerLogResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{106} + return fileDescriptor_00212fb1f9d3bf1c, []int{118} } func (m *ReopenContainerLogResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -7156,6 +7939,21 @@ func init() { proto.RegisterMapType((map[string]string)(nil), "runtime.v1.PodSandbox.AnnotationsEntry") proto.RegisterMapType((map[string]string)(nil), "runtime.v1.PodSandbox.LabelsEntry") proto.RegisterType((*ListPodSandboxResponse)(nil), "runtime.v1.ListPodSandboxResponse") + proto.RegisterType((*PodSandboxStatsRequest)(nil), "runtime.v1.PodSandboxStatsRequest") + proto.RegisterType((*PodSandboxStatsResponse)(nil), "runtime.v1.PodSandboxStatsResponse") + proto.RegisterType((*PodSandboxStatsFilter)(nil), "runtime.v1.PodSandboxStatsFilter") + proto.RegisterMapType((map[string]string)(nil), "runtime.v1.PodSandboxStatsFilter.LabelSelectorEntry") + proto.RegisterType((*ListPodSandboxStatsRequest)(nil), "runtime.v1.ListPodSandboxStatsRequest") + proto.RegisterType((*ListPodSandboxStatsResponse)(nil), "runtime.v1.ListPodSandboxStatsResponse") + proto.RegisterType((*PodSandboxAttributes)(nil), "runtime.v1.PodSandboxAttributes") + proto.RegisterMapType((map[string]string)(nil), "runtime.v1.PodSandboxAttributes.AnnotationsEntry") + proto.RegisterMapType((map[string]string)(nil), "runtime.v1.PodSandboxAttributes.LabelsEntry") + proto.RegisterType((*PodSandboxStats)(nil), "runtime.v1.PodSandboxStats") + proto.RegisterType((*LinuxPodSandboxStats)(nil), "runtime.v1.LinuxPodSandboxStats") + proto.RegisterType((*WindowsPodSandboxStats)(nil), "runtime.v1.WindowsPodSandboxStats") + proto.RegisterType((*NetworkUsage)(nil), "runtime.v1.NetworkUsage") + proto.RegisterType((*NetworkInterfaceUsage)(nil), "runtime.v1.NetworkInterfaceUsage") + proto.RegisterType((*ProcessUsage)(nil), "runtime.v1.ProcessUsage") proto.RegisterType((*ImageSpec)(nil), "runtime.v1.ImageSpec") proto.RegisterMapType((map[string]string)(nil), "runtime.v1.ImageSpec.AnnotationsEntry") proto.RegisterType((*KeyValue)(nil), "runtime.v1.KeyValue") @@ -7254,327 +8052,357 @@ func init() { func init() { proto.RegisterFile("api.proto", fileDescriptor_00212fb1f9d3bf1c) } var fileDescriptor_00212fb1f9d3bf1c = []byte{ - // 5113 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x7c, 0xcf, 0x73, 0x1b, 0xc9, - 0x75, 0x3f, 0x07, 0x00, 0x49, 0xe0, 0x81, 0x00, 0xc1, 0x16, 0x45, 0x42, 0xa0, 0x44, 0x91, 0xa3, - 0x5d, 0xfd, 0xdc, 0xe5, 0x6a, 0xa5, 0x5d, 0xad, 0x56, 0xde, 0x5f, 0x10, 0xc9, 0x95, 0xb0, 0x96, - 0x40, 0x78, 0x40, 0xca, 0x5e, 0xfb, 0x5b, 0x9e, 0xef, 0x08, 0xd3, 0x04, 0xc7, 0x02, 0x66, 0xc6, - 0x33, 0x03, 0x51, 0xf4, 0x29, 0xd7, 0xe4, 0x94, 0xaa, 0x94, 0xe3, 0xaa, 0x54, 0xaa, 0x72, 0xcc, - 0xc1, 0x07, 0xe7, 0x92, 0x94, 0x2f, 0xce, 0x29, 0x07, 0x57, 0xaa, 0x5c, 0xe5, 0x4b, 0xaa, 0xf6, - 0x90, 0xaa, 0xd8, 0x9b, 0x5b, 0x0e, 0x39, 0xf9, 0x0f, 0x48, 0xf5, 0xaf, 0xc1, 0xf4, 0xcc, 0x60, - 0x48, 0x6a, 0xb5, 0xde, 0x3d, 0x11, 0xfd, 0xfa, 0xf5, 0xeb, 0xd7, 0xdd, 0xaf, 0x5f, 0xbf, 0xfe, - 0xbc, 0x1e, 0x42, 0xc9, 0x70, 0xad, 0x0d, 0xd7, 0x73, 0x02, 0x07, 0x81, 0x37, 0xb2, 0x03, 0x6b, - 0x88, 0x37, 0x9e, 0xbf, 0xdd, 0x78, 0xb3, 0x6f, 0x05, 0x07, 0xa3, 0xa7, 0x1b, 0x3d, 0x67, 0xf8, - 0x56, 0xdf, 0xe9, 0x3b, 0x6f, 0x51, 0x96, 0xa7, 0xa3, 0x7d, 0x5a, 0xa2, 0x05, 0xfa, 0x8b, 0x35, - 0x55, 0xaf, 0x43, 0xf5, 0x09, 0xf6, 0x7c, 0xcb, 0xb1, 0x35, 0xfc, 0xd3, 0x11, 0xf6, 0x03, 0x54, - 0x87, 0xd9, 0xe7, 0x8c, 0x52, 0x57, 0xd6, 0x94, 0xab, 0x25, 0x4d, 0x14, 0xd5, 0x7f, 0x54, 0x60, - 0x3e, 0x64, 0xf6, 0x5d, 0xc7, 0xf6, 0xf1, 0x64, 0x6e, 0xb4, 0x0e, 0x73, 0x5c, 0x2d, 0xdd, 0x36, - 0x86, 0xb8, 0x9e, 0xa3, 0xd5, 0x65, 0x4e, 0x6b, 0x1b, 0x43, 0x8c, 0xae, 0xc0, 0xbc, 0x60, 0x11, - 0x42, 0xf2, 0x94, 0xab, 0xca, 0xc9, 0xbc, 0x37, 0xb4, 0x01, 0x67, 0x04, 0xa3, 0xe1, 0x5a, 0x21, - 0x73, 0x81, 0x32, 0x2f, 0xf0, 0xaa, 0xa6, 0x6b, 0x71, 0x7e, 0xf5, 0x47, 0x50, 0xda, 0x6a, 0x77, - 0x37, 0x1d, 0x7b, 0xdf, 0xea, 0x13, 0x15, 0x7d, 0xec, 0x91, 0x36, 0x75, 0x65, 0x2d, 0x4f, 0x54, - 0xe4, 0x45, 0xd4, 0x80, 0xa2, 0x8f, 0x0d, 0xaf, 0x77, 0x80, 0xfd, 0x7a, 0x8e, 0x56, 0x85, 0x65, - 0xd2, 0xca, 0x71, 0x03, 0xcb, 0xb1, 0xfd, 0x7a, 0x9e, 0xb5, 0xe2, 0x45, 0xf5, 0xef, 0x15, 0x28, - 0x77, 0x1c, 0x2f, 0x78, 0x6c, 0xb8, 0xae, 0x65, 0xf7, 0xd1, 0x4d, 0x28, 0xd2, 0xb9, 0xec, 0x39, - 0x03, 0x3a, 0x07, 0xd5, 0x5b, 0x8b, 0x1b, 0xe3, 0x05, 0xd9, 0xe8, 0xf0, 0x3a, 0x2d, 0xe4, 0x42, - 0xaf, 0x43, 0xb5, 0xe7, 0xd8, 0x81, 0x61, 0xd9, 0xd8, 0xd3, 0x5d, 0xc7, 0x0b, 0xe8, 0xe4, 0x4c, - 0x6b, 0x95, 0x90, 0x4a, 0xe4, 0xa3, 0x15, 0x28, 0x1d, 0x38, 0x7e, 0xc0, 0x38, 0xf2, 0x94, 0xa3, - 0x48, 0x08, 0xb4, 0x72, 0x19, 0x66, 0x69, 0xa5, 0xe5, 0xf2, 0x69, 0x98, 0x21, 0xc5, 0x96, 0xab, - 0xfe, 0x5e, 0x81, 0xe9, 0xc7, 0xce, 0xc8, 0x0e, 0x62, 0xdd, 0x18, 0xc1, 0x01, 0x5f, 0xa2, 0x48, - 0x37, 0x46, 0x70, 0x30, 0xee, 0x86, 0x70, 0xb0, 0x55, 0x62, 0xdd, 0x90, 0xca, 0x06, 0x14, 0x3d, - 0x6c, 0x98, 0x8e, 0x3d, 0x38, 0xa2, 0x2a, 0x14, 0xb5, 0xb0, 0x4c, 0x96, 0xcf, 0xc7, 0x03, 0xcb, - 0x1e, 0xbd, 0xd0, 0x3d, 0x3c, 0x30, 0x9e, 0xe2, 0x01, 0x55, 0xa5, 0xa8, 0x55, 0x39, 0x59, 0x63, - 0x54, 0xf4, 0x11, 0x94, 0x5d, 0xcf, 0x71, 0x8d, 0xbe, 0x41, 0x66, 0xb0, 0x3e, 0x4d, 0x27, 0xe9, - 0x7c, 0x74, 0x92, 0xa8, 0xc2, 0x9d, 0x31, 0x8f, 0x16, 0x6d, 0xa0, 0xfe, 0x46, 0x81, 0x79, 0x62, - 0x30, 0xbe, 0x6b, 0xf4, 0xf0, 0x0e, 0x5d, 0x06, 0x74, 0x1b, 0x66, 0x6d, 0x1c, 0x1c, 0x3a, 0xde, - 0x33, 0x3e, 0xe9, 0xe7, 0xa2, 0xf2, 0x42, 0xee, 0xc7, 0x8e, 0x89, 0x35, 0xc1, 0x89, 0x6e, 0x40, - 0xde, 0xb5, 0x4c, 0x3a, 0xc8, 0xcc, 0x06, 0x84, 0x8b, 0x30, 0x5b, 0x6e, 0x8f, 0x8e, 0x3a, 0x9b, - 0xd9, 0x72, 0x7b, 0x64, 0x12, 0x03, 0xc3, 0xeb, 0xe3, 0x40, 0xb7, 0x4c, 0xbe, 0x20, 0x45, 0x46, - 0x68, 0x99, 0xaa, 0x0a, 0xd0, 0xb2, 0x83, 0x3b, 0xef, 0x3c, 0x31, 0x06, 0x23, 0x8c, 0x16, 0x61, - 0xfa, 0x39, 0xf9, 0x41, 0xf5, 0xce, 0x6b, 0xac, 0xa0, 0xfe, 0xa6, 0x00, 0x2b, 0x8f, 0xc8, 0xa4, - 0x75, 0x0d, 0xdb, 0x7c, 0xea, 0xbc, 0xe8, 0xe2, 0xde, 0xc8, 0xb3, 0x82, 0xa3, 0x4d, 0xc7, 0x0e, - 0xf0, 0x8b, 0x00, 0x3d, 0x84, 0x05, 0x5b, 0x74, 0xab, 0x0b, 0xcb, 0x24, 0x12, 0xca, 0xb7, 0x56, - 0x52, 0x75, 0x63, 0xf3, 0xa4, 0xd5, 0x6c, 0x99, 0xe0, 0xa3, 0xfb, 0xe3, 0x65, 0x13, 0x72, 0x72, - 0x54, 0x8e, 0x34, 0xc6, 0xee, 0x36, 0xd5, 0x86, 0x4b, 0x11, 0x2b, 0x2a, 0x64, 0xdc, 0x01, 0xb2, - 0x91, 0x75, 0xc3, 0xd7, 0x47, 0x3e, 0xf6, 0xe8, 0x1c, 0x95, 0x6f, 0x2d, 0x45, 0xdb, 0x8f, 0x07, - 0xac, 0x95, 0xbc, 0x91, 0xdd, 0xf4, 0xf7, 0x7c, 0xec, 0xa1, 0xbb, 0xd4, 0x29, 0x90, 0x76, 0x7d, - 0xcf, 0x19, 0xb9, 0xf5, 0x62, 0x66, 0x43, 0xa0, 0x0d, 0x1f, 0x10, 0x4e, 0xea, 0x2b, 0xb8, 0xe1, - 0xe9, 0x9e, 0xe3, 0x04, 0xfb, 0xbe, 0x30, 0x36, 0x41, 0xd6, 0x28, 0x15, 0xbd, 0x05, 0x67, 0xfc, - 0x91, 0xeb, 0x0e, 0xf0, 0x10, 0xdb, 0x81, 0x31, 0x60, 0x1d, 0xf9, 0xf5, 0xe9, 0xb5, 0xfc, 0xd5, - 0xbc, 0x86, 0xa2, 0x55, 0x54, 0xb0, 0x8f, 0x56, 0x01, 0x5c, 0xcf, 0x7a, 0x6e, 0x0d, 0x70, 0x1f, - 0x9b, 0xf5, 0x19, 0x2a, 0x34, 0x42, 0x41, 0xef, 0x12, 0xff, 0xd1, 0xeb, 0x39, 0x43, 0xb7, 0x5e, - 0x4a, 0xce, 0xb7, 0x58, 0xa7, 0x8e, 0xe7, 0xec, 0x5b, 0x03, 0xac, 0x09, 0x5e, 0xf4, 0x1e, 0x14, - 0x0d, 0xd7, 0x35, 0xbc, 0xa1, 0xe3, 0xd5, 0xe1, 0xf8, 0x76, 0x21, 0x33, 0x7a, 0x07, 0x16, 0xb9, - 0x0c, 0xdd, 0x65, 0x95, 0x6c, 0x6b, 0xce, 0x12, 0xab, 0xba, 0x9f, 0xab, 0x2b, 0x1a, 0xe2, 0xf5, - 0xbc, 0x2d, 0xd9, 0xa8, 0xea, 0xbf, 0x29, 0x30, 0x1f, 0x93, 0x89, 0x3e, 0x83, 0x39, 0x21, 0x21, - 0x38, 0x72, 0x31, 0xdf, 0x28, 0x57, 0x32, 0xd4, 0xd8, 0xe0, 0x7f, 0x77, 0x8f, 0x5c, 0x4c, 0xf7, - 0xa0, 0x28, 0xa0, 0x4b, 0x50, 0x19, 0x38, 0x3d, 0x63, 0x40, 0x5d, 0x85, 0x87, 0xf7, 0xb9, 0xa7, - 0x98, 0x0b, 0x89, 0x1a, 0xde, 0x57, 0x3f, 0x81, 0x72, 0x44, 0x00, 0x42, 0x50, 0xd5, 0x58, 0x57, - 0x5b, 0x78, 0xdf, 0x18, 0x0d, 0x82, 0xda, 0x14, 0xaa, 0x02, 0xec, 0xd9, 0x3d, 0xe2, 0x99, 0x6d, - 0x6c, 0xd6, 0x14, 0x54, 0x81, 0xd2, 0x23, 0x21, 0xa2, 0x96, 0x53, 0xff, 0x36, 0x07, 0x67, 0xa9, - 0xe1, 0x75, 0x1c, 0x93, 0xef, 0x04, 0xee, 0xc6, 0x2f, 0x41, 0xa5, 0x47, 0xd7, 0x52, 0x77, 0x0d, - 0x0f, 0xdb, 0x01, 0x77, 0x66, 0x73, 0x8c, 0xd8, 0xa1, 0x34, 0xa4, 0x41, 0xcd, 0xe7, 0x23, 0xd2, - 0x7b, 0x6c, 0xe7, 0x70, 0xe3, 0x96, 0x46, 0x9d, 0xb1, 0xd1, 0xb4, 0x79, 0x3f, 0xb1, 0xf3, 0x66, - 0xfd, 0x23, 0xbf, 0x17, 0x0c, 0xd8, 0x49, 0x50, 0xbe, 0xb5, 0x91, 0x10, 0x15, 0x57, 0x76, 0xa3, - 0xcb, 0x1a, 0x6c, 0xdb, 0x81, 0x77, 0xa4, 0x89, 0xe6, 0x8d, 0x7b, 0x30, 0x17, 0xad, 0x40, 0x35, - 0xc8, 0x3f, 0xc3, 0x47, 0x7c, 0x20, 0xe4, 0xe7, 0xd8, 0x37, 0xb0, 0xd9, 0x65, 0x85, 0x7b, 0xb9, - 0xbb, 0x8a, 0xea, 0x01, 0x1a, 0xf7, 0xf2, 0x18, 0x07, 0x86, 0x69, 0x04, 0x06, 0x42, 0x50, 0xa0, - 0x87, 0x2b, 0x13, 0x41, 0x7f, 0x13, 0xa9, 0x23, 0xee, 0xe4, 0x4a, 0x1a, 0xf9, 0x89, 0xce, 0x43, - 0x29, 0xf4, 0x02, 0xfc, 0x84, 0x1d, 0x13, 0xc8, 0x49, 0x67, 0x04, 0x01, 0x1e, 0xba, 0x01, 0xdd, - 0x51, 0x15, 0x4d, 0x14, 0xd5, 0xbf, 0x9c, 0x86, 0x5a, 0x62, 0x1d, 0xee, 0x41, 0x71, 0xc8, 0xbb, - 0xe7, 0xfe, 0x67, 0x55, 0x3a, 0xee, 0x12, 0x4a, 0x6a, 0x21, 0x3f, 0x39, 0x4d, 0xc8, 0x3a, 0x47, - 0xe2, 0x81, 0xb0, 0xcc, 0x0c, 0xac, 0xaf, 0x9b, 0x96, 0x87, 0x7b, 0x81, 0xe3, 0x1d, 0x71, 0x45, - 0xe7, 0x06, 0x4e, 0x7f, 0x4b, 0xd0, 0xd0, 0x3b, 0x00, 0xa6, 0xed, 0xeb, 0xd4, 0x7e, 0xfa, 0x54, - 0xdd, 0xf2, 0xad, 0xb3, 0xd1, 0xee, 0xc3, 0x63, 0x5f, 0x2b, 0x99, 0xb6, 0xcf, 0x55, 0xfe, 0x00, - 0x2a, 0xe4, 0x0c, 0xd5, 0x87, 0xec, 0xc4, 0x66, 0xce, 0xa0, 0x7c, 0x6b, 0x59, 0xd6, 0x3b, 0x3c, - 0xd1, 0xb5, 0x39, 0x77, 0x5c, 0xf0, 0xd1, 0x27, 0x30, 0x43, 0x8f, 0x31, 0xbf, 0x3e, 0x43, 0x9b, - 0x5d, 0x4d, 0x1f, 0x2e, 0x5f, 0xf9, 0x47, 0x94, 0x95, 0x2d, 0x3c, 0x6f, 0x87, 0x76, 0xa0, 0x6c, - 0xd8, 0xb6, 0x13, 0x18, 0xcc, 0xdb, 0xce, 0x52, 0x31, 0x6f, 0x66, 0x8a, 0x69, 0x8e, 0xf9, 0x99, - 0xac, 0xa8, 0x04, 0xf4, 0x1e, 0x4c, 0x53, 0x77, 0xcc, 0xfd, 0xe7, 0xfa, 0xb1, 0x06, 0xa9, 0x31, - 0x7e, 0xf4, 0x21, 0xcc, 0x1e, 0x5a, 0xb6, 0xe9, 0x1c, 0xfa, 0xdc, 0x97, 0x5d, 0x8a, 0x36, 0xfd, - 0x3e, 0xab, 0x4a, 0x34, 0x16, 0x6d, 0x1a, 0xef, 0x43, 0x39, 0x32, 0xbe, 0xd3, 0xd8, 0x6f, 0xe3, - 0x23, 0xa8, 0xc5, 0xc7, 0x74, 0x2a, 0xfb, 0x1f, 0xc1, 0xa2, 0x36, 0xb2, 0xc7, 0xaa, 0x89, 0x70, - 0xf5, 0x1d, 0x98, 0xe1, 0xd6, 0xc0, 0x8c, 0xf1, 0x7c, 0xd6, 0xb4, 0x6a, 0x9c, 0x37, 0x1a, 0x79, - 0x1e, 0x18, 0xb6, 0x39, 0xc0, 0x1e, 0xef, 0x51, 0x44, 0x9e, 0x0f, 0x19, 0x55, 0xfd, 0x10, 0xce, - 0xc6, 0xba, 0xe5, 0x81, 0xef, 0x6b, 0x50, 0x75, 0x1d, 0x53, 0xf7, 0x19, 0x99, 0x9c, 0xfa, 0xdc, - 0x1f, 0xb9, 0x21, 0x6f, 0xcb, 0x24, 0xcd, 0xbb, 0x81, 0xe3, 0x26, 0xd5, 0x3e, 0x59, 0xf3, 0x3a, - 0x2c, 0xc5, 0x9b, 0xb3, 0xee, 0xd5, 0x8f, 0x61, 0x59, 0xc3, 0x43, 0xe7, 0x39, 0x7e, 0x59, 0xd1, - 0x0d, 0xa8, 0x27, 0x05, 0x70, 0xe1, 0x9f, 0xc3, 0xf2, 0x98, 0xda, 0x0d, 0x8c, 0x60, 0xe4, 0x9f, - 0x4a, 0x38, 0xbf, 0x15, 0x3c, 0x75, 0x7c, 0xb6, 0x90, 0x45, 0x4d, 0x14, 0xd5, 0x65, 0x98, 0xee, - 0x38, 0x66, 0xab, 0x83, 0xaa, 0x90, 0xb3, 0x5c, 0xde, 0x38, 0x67, 0xb9, 0x6a, 0x2f, 0xda, 0x67, - 0x9b, 0xc5, 0x6b, 0xac, 0xeb, 0x38, 0x2b, 0xba, 0x0b, 0x55, 0xc3, 0x34, 0x2d, 0x62, 0x48, 0xc6, - 0x40, 0xb7, 0x5c, 0x16, 0xbc, 0x97, 0x6f, 0x2d, 0xc4, 0x96, 0xbe, 0xd5, 0xd1, 0x2a, 0x63, 0xc6, - 0x96, 0xeb, 0xab, 0xf7, 0xa1, 0x14, 0xc6, 0x47, 0xe4, 0x5c, 0x97, 0xe3, 0x9f, 0xcc, 0x38, 0x2a, - 0x0c, 0xff, 0xdb, 0x89, 0x03, 0x8a, 0xab, 0xf9, 0x2e, 0x40, 0xe8, 0x54, 0x45, 0x68, 0x76, 0x36, - 0x55, 0xa4, 0x16, 0x61, 0x54, 0xff, 0xab, 0x10, 0x75, 0xb2, 0x91, 0x21, 0x9b, 0xe1, 0x90, 0x4d, - 0xc9, 0xe9, 0xe6, 0x4e, 0xe9, 0x74, 0xdf, 0x86, 0x69, 0x3f, 0x30, 0x02, 0xcc, 0x23, 0xd9, 0x95, - 0xf4, 0x86, 0xa4, 0x63, 0xac, 0x31, 0x4e, 0x74, 0x01, 0xa0, 0xe7, 0x61, 0x23, 0xc0, 0xa6, 0x6e, - 0xb0, 0x53, 0x21, 0xaf, 0x95, 0x38, 0xa5, 0x19, 0x10, 0x2f, 0x22, 0x62, 0xef, 0xe9, 0xa4, 0x17, - 0x99, 0xb0, 0x8c, 0xe3, 0x28, 0x3c, 0xf4, 0x5e, 0x33, 0xc7, 0x7a, 0x2f, 0xde, 0x94, 0x7b, 0xaf, - 0xb1, 0x27, 0x9e, 0xcd, 0xf2, 0xc4, 0xac, 0xd1, 0x49, 0x3c, 0x71, 0x31, 0xcb, 0x13, 0x73, 0x31, - 0xd9, 0x9e, 0x38, 0xc5, 0x91, 0x94, 0xd2, 0x1c, 0xc9, 0x37, 0xe9, 0x3a, 0x7f, 0xa7, 0x40, 0x3d, - 0xb9, 0x9f, 0xb9, 0x1f, 0x7b, 0x07, 0x66, 0x7c, 0x4a, 0xc9, 0xf6, 0x9f, 0xbc, 0x15, 0xe7, 0x45, - 0xf7, 0xa1, 0x60, 0xd9, 0xfb, 0x0e, 0xdf, 0x78, 0x1b, 0x99, 0x6d, 0x78, 0x4f, 0x1b, 0x2d, 0x7b, - 0xdf, 0x61, 0x33, 0x48, 0xdb, 0x36, 0xde, 0x83, 0x52, 0x48, 0x3a, 0xd5, 0x78, 0x5a, 0xb0, 0x18, - 0xb3, 0x5b, 0x76, 0xb1, 0x0a, 0x0d, 0x5d, 0x39, 0xa9, 0xa1, 0xab, 0x7f, 0x52, 0xa2, 0x9b, 0xef, - 0x53, 0x6b, 0x10, 0x60, 0x2f, 0xb1, 0xf9, 0xee, 0x08, 0xb9, 0x6c, 0xe7, 0xad, 0x65, 0xc8, 0x65, - 0xf7, 0x16, 0xbe, 0x8b, 0x9e, 0x40, 0x95, 0x9a, 0x9d, 0xee, 0xe3, 0x01, 0x8d, 0x5f, 0x78, 0xfc, - 0xf8, 0x56, 0xba, 0x00, 0xd6, 0x3b, 0x33, 0xdb, 0x2e, 0x6f, 0xc1, 0xe6, 0xab, 0x32, 0x88, 0xd2, - 0x1a, 0x9f, 0x00, 0x4a, 0x32, 0x9d, 0x6a, 0x06, 0x1f, 0x13, 0x1f, 0xe6, 0x07, 0xa9, 0xa7, 0xe9, - 0x3e, 0x55, 0x23, 0xdb, 0x1a, 0x98, 0xaa, 0x1a, 0xe7, 0x55, 0xff, 0x23, 0x0f, 0x30, 0xae, 0xfc, - 0x96, 0x3b, 0xaf, 0x7b, 0xa1, 0x13, 0x61, 0x51, 0xa0, 0x9a, 0x2e, 0x32, 0xd5, 0x7d, 0xb4, 0x64, - 0xf7, 0xc1, 0xe2, 0xc1, 0x2b, 0x13, 0x04, 0x9c, 0xda, 0x71, 0xcc, 0x7e, 0xdb, 0x1c, 0xc7, 0xa7, - 0xb0, 0x14, 0x37, 0x13, 0xee, 0x35, 0xde, 0x80, 0x69, 0x2b, 0xc0, 0x43, 0x86, 0xa8, 0xc5, 0x2e, - 0xf0, 0x11, 0x76, 0xc6, 0xa4, 0xfe, 0x52, 0x81, 0x52, 0x6b, 0x68, 0xf4, 0x71, 0xd7, 0xc5, 0x3d, - 0xd2, 0x9f, 0x45, 0x0a, 0x5c, 0x07, 0x56, 0x40, 0x0f, 0xe5, 0xa9, 0x65, 0x8e, 0xe5, 0xb2, 0x04, - 0x0c, 0x08, 0x09, 0xd9, 0x33, 0xfb, 0x95, 0x47, 0x7d, 0x0b, 0x8a, 0xdf, 0xc5, 0x47, 0xcc, 0xa5, - 0x9c, 0xb0, 0x9d, 0xfa, 0xf3, 0x02, 0x2c, 0xd3, 0xa3, 0x6b, 0x53, 0x40, 0x6b, 0x1a, 0xf6, 0x9d, - 0x91, 0xd7, 0xc3, 0x3e, 0xb5, 0x47, 0x77, 0xa4, 0xbb, 0xd8, 0xb3, 0x1c, 0x93, 0x83, 0x3e, 0xa5, - 0x9e, 0x3b, 0xea, 0x50, 0x02, 0x5a, 0x01, 0x52, 0xd0, 0x7f, 0x3a, 0x72, 0xf8, 0xf6, 0xc8, 0x6b, - 0xc5, 0x9e, 0x3b, 0xfa, 0x1e, 0x29, 0x8b, 0xb6, 0xfe, 0x81, 0xe1, 0x61, 0x9f, 0xee, 0x01, 0xd6, - 0xb6, 0x4b, 0x09, 0xe8, 0x6d, 0x38, 0x3b, 0xc4, 0x43, 0xc7, 0x3b, 0xd2, 0x07, 0xd6, 0xd0, 0x0a, - 0x74, 0xcb, 0xd6, 0x9f, 0x1e, 0x05, 0xd8, 0xe7, 0x56, 0x8f, 0x58, 0xe5, 0x23, 0x52, 0xd7, 0xb2, - 0xef, 0x93, 0x1a, 0xa4, 0x42, 0xc5, 0x71, 0x86, 0xba, 0xdf, 0x73, 0x3c, 0xac, 0x1b, 0xe6, 0x4f, - 0xe8, 0x09, 0x9e, 0xd7, 0xca, 0x8e, 0x33, 0xec, 0x12, 0x5a, 0xd3, 0xfc, 0x09, 0xba, 0x08, 0xe5, - 0x9e, 0x3b, 0xf2, 0x71, 0xa0, 0x93, 0x3f, 0xf4, 0x98, 0x2e, 0x69, 0xc0, 0x48, 0x9b, 0xee, 0xc8, - 0x8f, 0x30, 0x0c, 0x89, 0x11, 0xcc, 0x46, 0x19, 0x1e, 0xe3, 0x21, 0xc5, 0x98, 0x0e, 0x46, 0x7d, - 0xec, 0x1a, 0x7d, 0xcc, 0x54, 0x13, 0x67, 0xad, 0x84, 0x31, 0x3d, 0xe4, 0x2c, 0x54, 0x41, 0xad, - 0x7a, 0x10, 0x2d, 0xfa, 0xe8, 0x33, 0x98, 0x1d, 0xd9, 0xd6, 0xbe, 0x85, 0xcd, 0x7a, 0x89, 0xb6, - 0xbd, 0x99, 0x08, 0x14, 0x92, 0xb3, 0xbd, 0xb1, 0xc7, 0x9a, 0xf0, 0x9b, 0x37, 0x17, 0x80, 0xee, - 0x41, 0x83, 0x4f, 0x94, 0x7f, 0x68, 0xb8, 0xf1, 0xd9, 0x02, 0x3a, 0x05, 0x4b, 0x8c, 0xa3, 0x7b, - 0x68, 0xb8, 0xd1, 0x19, 0x23, 0xb7, 0xf6, 0xa8, 0xd0, 0x53, 0xd9, 0xd2, 0x7d, 0xa8, 0x48, 0x83, - 0x24, 0xab, 0x4d, 0x27, 0xc5, 0xb7, 0x7e, 0x26, 0x36, 0x40, 0x91, 0x10, 0xba, 0xd6, 0xcf, 0x28, - 0x32, 0x48, 0x35, 0xa3, 0x72, 0x0a, 0x1a, 0x2b, 0xa8, 0x06, 0x54, 0x24, 0x30, 0x8e, 0x5c, 0xfa, - 0x29, 0xea, 0xc6, 0x2f, 0xfd, 0xe4, 0x37, 0xa1, 0x79, 0xce, 0x40, 0x68, 0x40, 0x7f, 0x13, 0x1a, - 0x85, 0x7d, 0xd8, 0x45, 0x9a, 0xfe, 0xa6, 0x5d, 0xe0, 0xe7, 0x1c, 0xa9, 0x2d, 0x69, 0xac, 0xa0, - 0x9a, 0x00, 0x9b, 0x86, 0x6b, 0x3c, 0xb5, 0x06, 0x56, 0x70, 0x84, 0xae, 0x41, 0xcd, 0x30, 0x4d, - 0xbd, 0x27, 0x28, 0x16, 0x16, 0xc8, 0xf9, 0xbc, 0x61, 0x9a, 0x9b, 0x11, 0x32, 0xba, 0x01, 0x0b, - 0xa6, 0xe7, 0xb8, 0x32, 0x2f, 0x83, 0xd2, 0x6b, 0xa4, 0x22, 0xca, 0xac, 0xfe, 0xeb, 0x0c, 0x5c, - 0x90, 0x97, 0x2d, 0x0e, 0x72, 0xde, 0x83, 0xb9, 0x58, 0xaf, 0x09, 0x78, 0x70, 0xac, 0xa7, 0x26, - 0xf1, 0xc6, 0x60, 0xbc, 0x5c, 0x02, 0xc6, 0x4b, 0x05, 0x50, 0xf3, 0xaf, 0x08, 0x40, 0x2d, 0x7c, - 0x45, 0x00, 0x75, 0xfa, 0x65, 0x01, 0xd4, 0xb9, 0x13, 0x03, 0xa8, 0x97, 0xe9, 0x81, 0x23, 0x7a, - 0xa4, 0x10, 0x0c, 0xdb, 0xd8, 0x95, 0x50, 0xba, 0x2d, 0x92, 0x32, 0x31, 0xa0, 0x75, 0xf6, 0x34, - 0x40, 0x6b, 0x71, 0x22, 0xd0, 0xba, 0x06, 0x73, 0xb6, 0xa3, 0xdb, 0xf8, 0x50, 0x27, 0xcb, 0xe2, - 0xd7, 0xcb, 0x6c, 0x8d, 0x6c, 0xa7, 0x8d, 0x0f, 0x3b, 0x84, 0x82, 0xd6, 0x61, 0x6e, 0x68, 0xf8, - 0xcf, 0xb0, 0x49, 0x11, 0x4f, 0xbf, 0x5e, 0xa1, 0x96, 0x54, 0x66, 0xb4, 0x0e, 0x21, 0xa1, 0xd7, - 0x21, 0xd4, 0x83, 0x33, 0x55, 0x29, 0x53, 0x45, 0x50, 0x19, 0x5b, 0x04, 0xb4, 0x9d, 0x7f, 0x49, - 0xd0, 0xb6, 0x76, 0x1a, 0xd0, 0xf6, 0x4d, 0xa8, 0x89, 0xdf, 0x02, 0xb5, 0x65, 0x17, 0x01, 0x0a, - 0xd8, 0xce, 0x8b, 0x3a, 0x81, 0xcc, 0x4e, 0xc2, 0x78, 0x21, 0x13, 0xe3, 0xfd, 0x95, 0x02, 0x8b, - 0xf2, 0x06, 0xe2, 0x00, 0x57, 0x13, 0x4a, 0x9e, 0xf0, 0x80, 0x7c, 0xd3, 0x5c, 0x3a, 0x81, 0xb3, - 0xd4, 0xc6, 0xad, 0xd0, 0xee, 0x44, 0xe4, 0xf4, 0xda, 0x64, 0x49, 0xc7, 0x61, 0xa7, 0xea, 0xdf, - 0x28, 0x70, 0x81, 0xa3, 0x4a, 0x13, 0xf2, 0x1a, 0x29, 0x66, 0xa9, 0x4c, 0x30, 0xcb, 0x9e, 0x87, - 0x4d, 0x6c, 0x07, 0x96, 0x31, 0xd0, 0x7d, 0x17, 0xf7, 0x04, 0x62, 0x33, 0x26, 0xd3, 0xf0, 0x62, - 0x1d, 0xe6, 0x58, 0x3a, 0xcb, 0x73, 0x7a, 0xd8, 0xf7, 0x79, 0xd6, 0xaa, 0x4c, 0x33, 0x5a, 0x8c, - 0xa4, 0x3a, 0xb0, 0x3c, 0x01, 0xea, 0x4a, 0x9d, 0x06, 0x25, 0x39, 0x0d, 0x99, 0x63, 0x4a, 0x4e, - 0xc3, 0xcf, 0x15, 0xb8, 0xc8, 0x9b, 0x4c, 0xf4, 0x7d, 0xdf, 0xc4, 0x44, 0xfc, 0xb3, 0x02, 0x4b, - 0x71, 0xbd, 0xf8, 0x44, 0x6c, 0x26, 0x4d, 0xea, 0xf5, 0x94, 0x19, 0xc8, 0x36, 0xaa, 0x27, 0x13, - 0x8d, 0xea, 0x46, 0x96, 0xac, 0x63, 0xe7, 0xf3, 0x97, 0x0a, 0x9c, 0x9b, 0xa8, 0x40, 0x2c, 0x68, - 0x52, 0xe2, 0x41, 0x13, 0x0f, 0xb8, 0x7a, 0xce, 0xc8, 0x0e, 0x22, 0x01, 0xd7, 0x26, 0xcd, 0x99, - 0xb2, 0xc8, 0x46, 0x1f, 0x1a, 0x2f, 0xac, 0xe1, 0x68, 0xc8, 0x23, 0x2e, 0x22, 0xee, 0x31, 0xa3, - 0xbc, 0x44, 0xc8, 0xa5, 0x36, 0x61, 0x21, 0xd4, 0x32, 0x13, 0xb9, 0x8f, 0x20, 0xf1, 0x39, 0x19, - 0x89, 0xb7, 0x61, 0x66, 0x0b, 0x3f, 0xb7, 0x7a, 0xf8, 0x95, 0x24, 0x75, 0xd7, 0xa0, 0xec, 0x62, - 0x6f, 0x68, 0xf9, 0x7e, 0x78, 0x08, 0x96, 0xb4, 0x28, 0x49, 0xfd, 0xd5, 0x0c, 0xcc, 0xc7, 0x2d, - 0xe2, 0xfd, 0x04, 0xf0, 0x7f, 0x41, 0x3a, 0x98, 0xe3, 0x43, 0x8c, 0xdc, 0xe2, 0x6e, 0x88, 0x90, - 0x3f, 0x97, 0x44, 0xc5, 0xc2, 0xb0, 0x5e, 0xdc, 0x04, 0xea, 0x30, 0xdb, 0x73, 0x86, 0x43, 0xc3, - 0x36, 0x45, 0xe6, 0x9d, 0x17, 0xc9, 0x9c, 0x19, 0x5e, 0x9f, 0x4c, 0x35, 0x21, 0xd3, 0xdf, 0x64, - 0xc1, 0x0e, 0x1d, 0xef, 0x99, 0x65, 0xd3, 0xd4, 0x01, 0x3d, 0x48, 0x4b, 0x1a, 0x70, 0xd2, 0x96, - 0xe5, 0xa1, 0xab, 0x50, 0xc0, 0xf6, 0x73, 0x71, 0x59, 0x93, 0x52, 0xf3, 0x22, 0xcc, 0xd7, 0x28, - 0x07, 0xba, 0x06, 0x33, 0x43, 0x62, 0x04, 0x02, 0x5e, 0x5a, 0x48, 0x64, 0xa8, 0x35, 0xce, 0x80, - 0xde, 0x80, 0x59, 0x93, 0xae, 0x87, 0x88, 0x6b, 0x91, 0x94, 0x84, 0xa0, 0x55, 0x9a, 0x60, 0x41, - 0x1f, 0x87, 0x57, 0xce, 0x52, 0xf2, 0xc6, 0x18, 0x9b, 0xe6, 0xd4, 0x7b, 0x67, 0x5b, 0xbe, 0x1c, - 0x01, 0x95, 0xf2, 0x46, 0x96, 0x94, 0xec, 0xcb, 0xe7, 0x39, 0x28, 0x0e, 0x9c, 0x3e, 0x33, 0x8e, - 0x32, 0x7b, 0xb6, 0x31, 0x70, 0xfa, 0xd4, 0x36, 0x16, 0xc9, 0x85, 0xdb, 0xb4, 0x6c, 0x1a, 0x59, - 0x14, 0x35, 0x56, 0x20, 0x5b, 0x8a, 0xfe, 0xd0, 0x1d, 0xbb, 0x87, 0xeb, 0x15, 0x5a, 0x55, 0xa2, - 0x94, 0x1d, 0xbb, 0x47, 0xaf, 0x49, 0x41, 0x70, 0x54, 0xaf, 0x52, 0x3a, 0xf9, 0x89, 0xee, 0x08, - 0x8c, 0x6f, 0x3e, 0x89, 0x99, 0xa4, 0x1d, 0x61, 0x02, 0xe2, 0xfb, 0x60, 0x9c, 0xa0, 0x60, 0xe7, - 0xaf, 0x9a, 0xe5, 0x28, 0xbe, 0x45, 0xf9, 0x89, 0x5f, 0x2b, 0xb0, 0xb4, 0x49, 0x41, 0x86, 0x88, - 0x47, 0x3a, 0x0d, 0x66, 0x7e, 0x3b, 0x4c, 0x64, 0xa4, 0xa0, 0xd1, 0xf1, 0x11, 0x8b, 0x3c, 0xc6, - 0x26, 0x54, 0x85, 0x58, 0xde, 0x38, 0x7f, 0x82, 0x2c, 0x48, 0xc5, 0x8f, 0x16, 0xd5, 0x0f, 0x60, - 0x39, 0xa1, 0x39, 0xbf, 0xe7, 0xaf, 0xc3, 0xdc, 0xd8, 0xdb, 0x84, 0x8a, 0x97, 0x43, 0x5a, 0xcb, - 0x54, 0xef, 0xc1, 0xd9, 0x6e, 0x60, 0x78, 0x41, 0x62, 0xd8, 0x27, 0x68, 0x4b, 0xf3, 0x1b, 0x72, - 0x5b, 0x9e, 0x82, 0xe8, 0xc2, 0x62, 0x37, 0x70, 0xdc, 0x97, 0x10, 0x4a, 0xfc, 0x07, 0x19, 0xb9, - 0x33, 0x12, 0xde, 0x5d, 0x14, 0xd5, 0x65, 0x96, 0x8d, 0x49, 0xf6, 0xf6, 0x1d, 0x58, 0x62, 0xc9, - 0x90, 0x97, 0x19, 0xc4, 0x39, 0x91, 0x8a, 0x49, 0xca, 0x7d, 0x00, 0x67, 0xc6, 0x87, 0xda, 0x18, - 0xa8, 0xbc, 0x29, 0x03, 0x95, 0x8d, 0xd4, 0x95, 0x96, 0x70, 0xca, 0x5f, 0xe4, 0x22, 0xfe, 0x78, - 0x02, 0x4c, 0xf9, 0xae, 0x0c, 0x53, 0x5e, 0x9c, 0x2c, 0x55, 0x42, 0x29, 0x93, 0xd6, 0x99, 0x4f, - 0xb1, 0xce, 0xbd, 0x04, 0x96, 0x59, 0x48, 0x42, 0xbf, 0x31, 0x0d, 0xff, 0x2c, 0x50, 0xe6, 0x23, - 0x06, 0x65, 0x86, 0x5d, 0x87, 0x99, 0xaa, 0xdb, 0x31, 0x28, 0x73, 0x25, 0x43, 0xd3, 0x10, 0xc9, - 0xfc, 0x45, 0x01, 0x4a, 0x61, 0x5d, 0x62, 0x86, 0x93, 0x53, 0x95, 0x4b, 0x99, 0xaa, 0xe8, 0x39, - 0x99, 0x7f, 0xc9, 0x73, 0xb2, 0x70, 0x82, 0x73, 0x72, 0x05, 0x4a, 0xf4, 0x07, 0x7d, 0x8d, 0xc1, - 0xce, 0xbd, 0x22, 0x25, 0x68, 0x78, 0x7f, 0x6c, 0x62, 0x33, 0x27, 0x34, 0xb1, 0x18, 0x6c, 0x3a, - 0x1b, 0x87, 0x4d, 0xdf, 0x0f, 0xcf, 0x30, 0x76, 0xe0, 0xad, 0xa7, 0x4a, 0x4c, 0x3d, 0xbd, 0x62, - 0xd0, 0x5e, 0x29, 0x09, 0xed, 0x8d, 0xdb, 0x67, 0x43, 0x7b, 0xdf, 0xa0, 0x7f, 0xdf, 0x61, 0x58, - 0x68, 0xd4, 0xce, 0xb8, 0x8f, 0x7c, 0x17, 0x20, 0x74, 0x07, 0x02, 0x10, 0x3d, 0x9b, 0x3a, 0x3a, - 0x2d, 0xc2, 0xa8, 0xee, 0xc1, 0x92, 0xb4, 0x10, 0xe3, 0x1c, 0xeb, 0xc9, 0x7c, 0xdc, 0x84, 0x04, - 0xeb, 0x17, 0xd3, 0x11, 0x4f, 0x31, 0x21, 0x9b, 0xf8, 0x7e, 0x02, 0x90, 0x3f, 0xb1, 0x85, 0xde, - 0x94, 0xf1, 0xf8, 0x53, 0xdb, 0x55, 0x02, 0x8e, 0xa7, 0x91, 0x85, 0xe1, 0xf1, 0x6a, 0x06, 0x46, - 0x96, 0x38, 0xa5, 0x49, 0xe3, 0xf1, 0x7d, 0xcb, 0xb6, 0xfc, 0x03, 0x56, 0x3f, 0xc3, 0xe2, 0x71, - 0x41, 0x6a, 0x52, 0x40, 0x0d, 0xbf, 0xb0, 0x02, 0xbd, 0xe7, 0x98, 0x98, 0x5a, 0xed, 0xb4, 0x56, - 0x24, 0x84, 0x4d, 0xc7, 0xc4, 0xe3, 0xfd, 0x54, 0x3c, 0xed, 0x7e, 0x2a, 0xc5, 0xf6, 0xd3, 0x12, - 0xcc, 0x78, 0xd8, 0xf0, 0x1d, 0x9b, 0x5d, 0xd1, 0x35, 0x5e, 0x22, 0x0b, 0x31, 0xc4, 0xbe, 0x4f, - 0xfa, 0xe0, 0x81, 0x14, 0x2f, 0x46, 0x82, 0xbe, 0xb9, 0x8c, 0xa0, 0x2f, 0x23, 0x57, 0x19, 0x0b, - 0xfa, 0x2a, 0x19, 0x41, 0xdf, 0x89, 0x52, 0x95, 0xe3, 0xf0, 0xb6, 0x7a, 0x5c, 0x78, 0x1b, 0x8d, - 0x0f, 0xe7, 0xa5, 0xf8, 0xf0, 0x9b, 0xdc, 0x82, 0xff, 0xae, 0xc0, 0x72, 0x62, 0xcb, 0xf0, 0x4d, - 0x78, 0x3b, 0x96, 0xc6, 0x5c, 0xc9, 0x98, 0xa7, 0x30, 0x8b, 0xd9, 0x94, 0xb2, 0x98, 0x6f, 0x66, - 0x35, 0x79, 0xe5, 0x49, 0xcc, 0x3f, 0xe4, 0xe0, 0xe2, 0x9e, 0x6b, 0xc6, 0xa2, 0x2e, 0x7e, 0x85, - 0x3e, 0xb9, 0x23, 0x78, 0x5f, 0xc4, 0xd9, 0xb9, 0x93, 0xa3, 0x3e, 0x3c, 0xd4, 0xfe, 0x78, 0x1c, - 0x6a, 0xe7, 0x4f, 0x73, 0xbf, 0x17, 0xad, 0xd0, 0x8f, 0x65, 0x03, 0x65, 0x01, 0xc1, 0x07, 0x51, - 0x21, 0xc7, 0x0c, 0xf0, 0x6b, 0x4e, 0xe4, 0xa8, 0xb0, 0x36, 0x59, 0x01, 0x1e, 0xa1, 0xfd, 0x7f, - 0x98, 0xdf, 0x7e, 0x81, 0x7b, 0xdd, 0x23, 0xbb, 0x77, 0x8a, 0x59, 0xaf, 0x41, 0xbe, 0x37, 0x34, - 0x39, 0xd0, 0x4d, 0x7e, 0x46, 0x83, 0xce, 0xbc, 0x1c, 0x74, 0xea, 0x50, 0x1b, 0xf7, 0xc0, 0xad, - 0x75, 0x89, 0x58, 0xab, 0x49, 0x98, 0x89, 0xf0, 0x39, 0x8d, 0x97, 0x38, 0x1d, 0x7b, 0xec, 0x35, - 0x12, 0xa3, 0x63, 0xcf, 0x93, 0x9d, 0x5c, 0x5e, 0x76, 0x72, 0xea, 0xdf, 0x29, 0x50, 0x26, 0x3d, - 0x7c, 0x25, 0xfd, 0xf9, 0x0d, 0x2e, 0x3f, 0xbe, 0xc1, 0x85, 0x17, 0xc1, 0x42, 0xf4, 0x22, 0x38, - 0xd6, 0x7c, 0x9a, 0x92, 0x93, 0x9a, 0xcf, 0x84, 0x74, 0xec, 0x79, 0xea, 0x1a, 0xcc, 0x31, 0xdd, - 0xf8, 0xc8, 0x6b, 0x90, 0x1f, 0x79, 0x03, 0xb1, 0x7e, 0x23, 0x6f, 0xa0, 0xfe, 0x95, 0x02, 0x95, - 0x66, 0x10, 0x18, 0xbd, 0x83, 0x53, 0x0c, 0x20, 0x54, 0x2e, 0x17, 0x55, 0x2e, 0x39, 0x88, 0xb1, - 0xba, 0x85, 0x09, 0xea, 0x4e, 0x4b, 0xea, 0xaa, 0x50, 0x15, 0xba, 0x4c, 0x54, 0xb8, 0x0d, 0xa8, - 0xe3, 0x78, 0xc1, 0xa7, 0x8e, 0x77, 0x68, 0x78, 0xe6, 0xe9, 0x2e, 0x79, 0x08, 0x0a, 0xfc, 0xbd, - 0x7f, 0xfe, 0xea, 0xb4, 0x46, 0x7f, 0xab, 0x57, 0xe0, 0x8c, 0x24, 0x6f, 0x62, 0xc7, 0xf7, 0xa0, - 0x4c, 0x0f, 0x2d, 0x1e, 0xff, 0xdf, 0x88, 0xe6, 0x51, 0x8f, 0x39, 0xdc, 0xd4, 0x2d, 0x58, 0x20, - 0xe1, 0x0b, 0xa5, 0x87, 0xfe, 0xe5, 0xad, 0x58, 0x88, 0xbc, 0x9c, 0x10, 0x11, 0x0b, 0x8f, 0xff, - 0x53, 0x81, 0x69, 0x4a, 0x4f, 0x84, 0x14, 0x2b, 0x50, 0xf2, 0xb0, 0xeb, 0xe8, 0x81, 0xd1, 0x0f, - 0xbf, 0xa5, 0x20, 0x84, 0x5d, 0xa3, 0x4f, 0x61, 0x7d, 0x5a, 0x69, 0x5a, 0x7d, 0xec, 0x07, 0xe2, - 0x83, 0x8a, 0x32, 0xa1, 0x6d, 0x31, 0x12, 0x99, 0x18, 0x9a, 0x12, 0x2b, 0xd0, 0xcc, 0x17, 0xfd, - 0x8d, 0xae, 0xb2, 0x87, 0xac, 0xd9, 0xb9, 0x11, 0xfa, 0xc0, 0xb5, 0x01, 0xc5, 0x58, 0x52, 0x23, - 0x2c, 0xa3, 0x6b, 0x50, 0xa0, 0x20, 0xe9, 0x6c, 0xd6, 0x2c, 0x51, 0x16, 0xf5, 0x63, 0x40, 0xd1, - 0x49, 0xe2, 0x0b, 0x71, 0x0d, 0x66, 0xe8, 0x1c, 0x8a, 0xd8, 0x6e, 0x21, 0x21, 0x42, 0xe3, 0x0c, - 0xea, 0x8f, 0x00, 0x31, 0x99, 0x52, 0x3c, 0x77, 0x9a, 0x85, 0xca, 0x88, 0xec, 0xfe, 0x45, 0x81, - 0x33, 0x92, 0x74, 0xae, 0xdf, 0x15, 0x59, 0x7c, 0x8a, 0x7a, 0x5c, 0xf4, 0x87, 0xd2, 0x71, 0x77, - 0x2d, 0xa9, 0xc6, 0xd7, 0x74, 0xd4, 0xfd, 0x4e, 0x01, 0x68, 0x8e, 0x82, 0x03, 0x8e, 0x23, 0x46, - 0x17, 0x4b, 0x89, 0x2d, 0x56, 0x03, 0x8a, 0xae, 0xe1, 0xfb, 0x87, 0x8e, 0x27, 0xee, 0x56, 0x61, - 0x99, 0xa2, 0x7f, 0xa3, 0xe0, 0x40, 0xa4, 0x33, 0xc9, 0x6f, 0xf4, 0x3a, 0x54, 0xd9, 0xc7, 0x3c, - 0xba, 0x61, 0x9a, 0x1e, 0xf6, 0x7d, 0x9e, 0xd7, 0xac, 0x30, 0x6a, 0x93, 0x11, 0x09, 0x9b, 0x45, - 0xa1, 0xf1, 0xe0, 0x48, 0x0f, 0x9c, 0x67, 0xd8, 0xe6, 0xf7, 0xa5, 0x8a, 0xa0, 0xee, 0x12, 0x22, - 0xcb, 0x2d, 0xf5, 0x2d, 0x3f, 0xf0, 0x04, 0x9b, 0xc8, 0x90, 0x71, 0x2a, 0x65, 0x53, 0xff, 0x49, - 0x81, 0x5a, 0x67, 0x34, 0x18, 0xb0, 0xc9, 0x7d, 0x99, 0x45, 0xbe, 0xce, 0x87, 0x92, 0x4b, 0x9a, - 0xf6, 0x78, 0xa2, 0xf8, 0x10, 0x5f, 0x09, 0xc4, 0x73, 0x13, 0x16, 0x22, 0x1a, 0x73, 0xc3, 0x91, - 0x02, 0x5e, 0x45, 0x0e, 0x78, 0xd5, 0x26, 0x20, 0x86, 0x6a, 0xbc, 0xf4, 0x28, 0xd5, 0xb3, 0x70, - 0x46, 0x12, 0xc1, 0x8f, 0xdc, 0xeb, 0x50, 0xe1, 0x0f, 0x03, 0xb9, 0x41, 0x9c, 0x83, 0x22, 0x71, - 0x9d, 0x3d, 0xcb, 0x14, 0x39, 0xed, 0x59, 0xd7, 0x31, 0x37, 0x2d, 0xd3, 0x53, 0xbf, 0x07, 0x15, - 0xfe, 0x05, 0x01, 0xe7, 0xfd, 0x04, 0xaa, 0xfc, 0x19, 0xa1, 0x2e, 0x3d, 0xfb, 0x95, 0xbf, 0xcf, - 0x89, 0x8a, 0xd7, 0x2a, 0x76, 0xb4, 0xa8, 0xfe, 0x18, 0x1a, 0x2c, 0x2a, 0x90, 0x04, 0x8b, 0x01, - 0x7e, 0x02, 0xe2, 0xfd, 0x4d, 0x86, 0x7c, 0xb9, 0x65, 0xc5, 0x8b, 0x16, 0xd5, 0x0b, 0xb0, 0x92, - 0x2a, 0x9f, 0x8f, 0xde, 0x85, 0xda, 0xb8, 0x82, 0xbd, 0x4d, 0x0d, 0x13, 0xf5, 0x4a, 0x24, 0x51, - 0xbf, 0x14, 0x06, 0xb4, 0x39, 0x71, 0x42, 0xd1, 0x98, 0x75, 0x7c, 0x11, 0xc9, 0x4f, 0xba, 0x88, - 0x14, 0xa4, 0x8b, 0x88, 0xfa, 0x38, 0x9c, 0x43, 0x7e, 0x1d, 0xfc, 0x80, 0x5e, 0x58, 0x59, 0xdf, - 0xc2, 0xa9, 0x9d, 0x4f, 0x1f, 0x1f, 0x63, 0xd2, 0x22, 0xfc, 0xea, 0x35, 0xa8, 0xc8, 0xee, 0x2d, - 0xe2, 0xb1, 0x94, 0x84, 0xc7, 0xaa, 0xc6, 0x9c, 0xd5, 0xdb, 0xb1, 0x38, 0x3d, 0x6d, 0x5e, 0x63, - 0x51, 0xfa, 0x5d, 0xc9, 0x6d, 0xbd, 0x26, 0xe5, 0x63, 0xbf, 0x26, 0x8f, 0xb5, 0xc8, 0xfd, 0xf8, - 0xa7, 0x3e, 0x69, 0xcf, 0x07, 0xaa, 0x5e, 0x82, 0xf2, 0xde, 0xa4, 0xef, 0xb8, 0x0a, 0xe2, 0x25, - 0xd0, 0x1d, 0x58, 0xfc, 0xd4, 0x1a, 0x60, 0xff, 0xc8, 0x0f, 0xf0, 0xb0, 0x45, 0xdd, 0xcb, 0xbe, - 0x85, 0x3d, 0xb4, 0x0a, 0x40, 0x2f, 0x57, 0xae, 0x63, 0x85, 0xdf, 0xae, 0x44, 0x28, 0xea, 0x17, - 0x0a, 0xcc, 0x8f, 0x1b, 0xee, 0xd1, 0x2b, 0xe4, 0x79, 0x28, 0x91, 0x91, 0xfa, 0x81, 0x31, 0x74, - 0x45, 0x1e, 0x2b, 0x24, 0xa0, 0x77, 0x61, 0x7a, 0xdf, 0x17, 0x20, 0x54, 0x0c, 0x62, 0x4f, 0x53, - 0x41, 0x2b, 0xec, 0xfb, 0x2d, 0x13, 0xdd, 0x01, 0x18, 0xf9, 0xd8, 0xe4, 0x59, 0xab, 0x7c, 0xf2, - 0xe0, 0xdf, 0x8b, 0xbe, 0x3c, 0x20, 0xac, 0xec, 0xe1, 0xd0, 0x5d, 0x28, 0x5b, 0xb6, 0x63, 0x62, - 0x9a, 0x9f, 0x34, 0x39, 0x42, 0x35, 0xb1, 0x21, 0x30, 0xde, 0x3d, 0x1f, 0x9b, 0xaa, 0xce, 0xcf, - 0x2d, 0x31, 0x9b, 0xdc, 0x14, 0x1e, 0xc2, 0x02, 0x73, 0x3f, 0xfb, 0xa1, 0xb2, 0xc2, 0x1a, 0x57, - 0xd2, 0xc7, 0x42, 0x67, 0x45, 0xab, 0x59, 0x3c, 0x32, 0x11, 0x8d, 0xd4, 0x7b, 0x70, 0x56, 0xba, - 0xaf, 0x9d, 0xe2, 0x02, 0xa5, 0x7e, 0x16, 0x83, 0x61, 0xc6, 0xa6, 0xca, 0xa1, 0x0e, 0x61, 0xa9, - 0x93, 0xa1, 0x0e, 0x9f, 0x41, 0x1d, 0xbe, 0xba, 0x07, 0xe7, 0x24, 0x8c, 0x48, 0xd2, 0xe5, 0x6e, - 0x2c, 0xd8, 0x5a, 0x9b, 0x2c, 0x2f, 0x16, 0x75, 0xfd, 0x8f, 0x02, 0x8b, 0x69, 0x0c, 0x2f, 0x89, - 0x4f, 0xfe, 0x70, 0xc2, 0xb3, 0xd4, 0xdb, 0xc7, 0x29, 0xf4, 0x67, 0xc1, 0x73, 0xdb, 0xd0, 0x48, - 0x9b, 0xc3, 0xe4, 0x9a, 0xe4, 0x4f, 0xb6, 0x26, 0x7f, 0xca, 0x45, 0x30, 0xf8, 0x66, 0x10, 0x78, - 0xd6, 0xd3, 0x11, 0x31, 0xe7, 0x57, 0x88, 0x89, 0x6d, 0x86, 0x48, 0x0f, 0x9b, 0xc8, 0x1b, 0xa9, - 0x0d, 0xc7, 0x7d, 0xa7, 0xa2, 0x3d, 0x5a, 0xda, 0x65, 0xfa, 0xe6, 0x71, 0x92, 0xbe, 0xb5, 0x70, - 0xe9, 0xff, 0x2a, 0x50, 0x95, 0x17, 0x04, 0x7d, 0x0c, 0x60, 0x84, 0x9a, 0xf3, 0x4d, 0x70, 0xf1, - 0x98, 0x01, 0x6a, 0x91, 0x26, 0xe8, 0x32, 0xe4, 0x7b, 0xee, 0x88, 0xaf, 0x8e, 0x94, 0xc8, 0xdd, - 0x74, 0x47, 0xcc, 0x37, 0x10, 0x06, 0x72, 0xad, 0x61, 0x59, 0xf8, 0x34, 0xef, 0xf6, 0x98, 0xd6, - 0x30, 0x6e, 0xce, 0x86, 0xee, 0x43, 0xf5, 0xd0, 0xb3, 0x02, 0xe3, 0xe9, 0x00, 0xeb, 0x03, 0xe3, - 0x08, 0x7b, 0xdc, 0xbb, 0x65, 0xba, 0xa1, 0x8a, 0x68, 0xf2, 0x88, 0xb4, 0x50, 0x5f, 0x40, 0x51, - 0x68, 0x71, 0x8c, 0xdf, 0x6e, 0xc3, 0xf2, 0x88, 0xb0, 0xe9, 0xf4, 0x09, 0xa6, 0x6d, 0xd8, 0x8e, - 0xee, 0x63, 0x72, 0xc0, 0x8a, 0xef, 0x50, 0x26, 0x3a, 0xd5, 0x45, 0xda, 0x6e, 0xd3, 0xf1, 0x70, - 0xdb, 0xb0, 0x9d, 0x2e, 0x6b, 0xa4, 0xba, 0x50, 0x8e, 0x0c, 0xea, 0x98, 0xce, 0x37, 0x61, 0x41, - 0xa4, 0xcb, 0x7d, 0x1c, 0xf0, 0x43, 0xe0, 0x98, 0x6e, 0xe7, 0x79, 0x8b, 0x2e, 0x0e, 0xd8, 0x83, - 0x86, 0x8f, 0xe0, 0x9c, 0x86, 0x1d, 0x17, 0xdb, 0xe1, 0x8a, 0x3d, 0x72, 0xfa, 0xa7, 0xf0, 0xb9, - 0xe7, 0xa1, 0x91, 0xd6, 0x9e, 0xed, 0xf1, 0xeb, 0x97, 0xa1, 0x28, 0xbe, 0x99, 0x47, 0xb3, 0x90, - 0xdf, 0xdd, 0xec, 0xd4, 0xa6, 0xc8, 0x8f, 0xbd, 0xad, 0x4e, 0x4d, 0x41, 0x45, 0x28, 0x74, 0x37, - 0x77, 0x3b, 0xb5, 0xdc, 0xf5, 0x21, 0xd4, 0xe2, 0x9f, 0x8d, 0xa3, 0x65, 0x38, 0xd3, 0xd1, 0x76, - 0x3a, 0xcd, 0x07, 0xcd, 0xdd, 0xd6, 0x4e, 0x5b, 0xef, 0x68, 0xad, 0x27, 0xcd, 0xdd, 0xed, 0xda, - 0x14, 0x5a, 0x87, 0x0b, 0xd1, 0x8a, 0x87, 0x3b, 0xdd, 0x5d, 0x7d, 0x77, 0x47, 0xdf, 0xdc, 0x69, - 0xef, 0x36, 0x5b, 0xed, 0x6d, 0xad, 0xa6, 0xa0, 0x0b, 0x70, 0x2e, 0xca, 0x72, 0xbf, 0xb5, 0xd5, - 0xd2, 0xb6, 0x37, 0xc9, 0xef, 0xe6, 0xa3, 0x5a, 0xee, 0xfa, 0x87, 0x50, 0x91, 0xbe, 0xfb, 0x26, - 0x2a, 0x75, 0x76, 0xb6, 0x6a, 0x53, 0xa8, 0x02, 0xa5, 0xa8, 0x9c, 0x22, 0x14, 0xda, 0x3b, 0x5b, - 0xdb, 0xb5, 0x1c, 0x02, 0x98, 0xd9, 0x6d, 0x6a, 0x0f, 0xb6, 0x77, 0x6b, 0xf9, 0xeb, 0xf7, 0x60, - 0x3e, 0xf6, 0x5e, 0x1d, 0x2d, 0x40, 0xa5, 0xdb, 0x6c, 0x6f, 0xdd, 0xdf, 0xf9, 0x81, 0xae, 0x6d, - 0x37, 0xb7, 0x3e, 0xaf, 0x4d, 0xa1, 0x45, 0xa8, 0x09, 0x52, 0x7b, 0x67, 0x97, 0x51, 0x95, 0xeb, - 0xcf, 0x62, 0x7b, 0x09, 0xa3, 0xb3, 0xb0, 0x10, 0x76, 0xa9, 0x6f, 0x6a, 0xdb, 0xcd, 0xdd, 0x6d, - 0xa2, 0x89, 0x44, 0xd6, 0xf6, 0xda, 0xed, 0x56, 0xfb, 0x41, 0x4d, 0x21, 0x52, 0xc7, 0xe4, 0xed, - 0x1f, 0xb4, 0x08, 0x73, 0x4e, 0x66, 0xde, 0x6b, 0x7f, 0xb7, 0xbd, 0xf3, 0xfd, 0x76, 0x2d, 0x7f, - 0xeb, 0xd7, 0xf3, 0xe1, 0x57, 0xbb, 0x5d, 0xec, 0xd1, 0x37, 0x27, 0x5b, 0x30, 0x2b, 0xfe, 0x13, - 0x83, 0xe4, 0x71, 0xe5, 0xff, 0x1c, 0xd1, 0x58, 0x49, 0xad, 0xe3, 0x71, 0xef, 0x14, 0x7a, 0x42, - 0xe3, 0xd0, 0xc8, 0x77, 0x02, 0x6b, 0xb1, 0xd8, 0x2f, 0xf1, 0x39, 0x42, 0x63, 0x3d, 0x83, 0x23, - 0x94, 0xfb, 0x39, 0x09, 0x32, 0xa3, 0x1f, 0xc9, 0xa1, 0x75, 0x39, 0x46, 0x4c, 0xf9, 0xfe, 0xae, - 0xa1, 0x66, 0xb1, 0x84, 0xa2, 0x75, 0xa8, 0xc5, 0x3f, 0x92, 0x43, 0x12, 0xc4, 0x3a, 0xe1, 0x1b, - 0xbc, 0xc6, 0x6b, 0xd9, 0x4c, 0xd1, 0x0e, 0x12, 0xdf, 0x7e, 0x5d, 0xca, 0xfe, 0x9a, 0x26, 0xa5, - 0x83, 0x49, 0x9f, 0xdc, 0xb0, 0xc9, 0x91, 0x9f, 0xf0, 0xa3, 0xd8, 0xe7, 0x56, 0x29, 0x5f, 0x81, - 0xc8, 0x93, 0x93, 0xfe, 0x05, 0x80, 0x3a, 0x85, 0xfe, 0x1f, 0xcc, 0xc7, 0x9e, 0x0d, 0x20, 0xa9, - 0x61, 0xfa, 0x6b, 0x88, 0xc6, 0xa5, 0x4c, 0x1e, 0x79, 0x55, 0xa3, 0x4f, 0x03, 0xe2, 0xab, 0x9a, - 0xf2, 0xe4, 0x20, 0xbe, 0xaa, 0xa9, 0x2f, 0x0b, 0xa8, 0x21, 0x4a, 0xcf, 0x00, 0x64, 0x43, 0x4c, - 0x7b, 0x76, 0xd0, 0x58, 0xcf, 0xe0, 0x88, 0x4e, 0x48, 0xec, 0x21, 0x80, 0x3c, 0x21, 0xe9, 0x4f, - 0x0c, 0x1a, 0x97, 0x32, 0x79, 0xe2, 0x2b, 0x39, 0x4e, 0x40, 0x26, 0x57, 0x32, 0x91, 0x04, 0x4f, - 0xae, 0x64, 0x32, 0x7f, 0xc9, 0x57, 0x32, 0x96, 0x32, 0x54, 0x33, 0x93, 0x21, 0x69, 0x2b, 0x99, - 0x9e, 0x30, 0x51, 0xa7, 0xd0, 0x21, 0xd4, 0x27, 0xc1, 0xf0, 0xe8, 0xc6, 0x29, 0xb2, 0x05, 0x8d, - 0x37, 0x4e, 0xc6, 0x1c, 0x76, 0x8c, 0x01, 0x25, 0x8f, 0x19, 0xf4, 0xba, 0x3c, 0xdd, 0x13, 0x8e, - 0xb1, 0xc6, 0xe5, 0xe3, 0xd8, 0xc2, 0x6e, 0x1e, 0x40, 0x51, 0x00, 0xfc, 0x48, 0x72, 0x81, 0xb1, - 0xc4, 0x42, 0xe3, 0x7c, 0x7a, 0x65, 0x28, 0xe8, 0x3b, 0x50, 0x20, 0x54, 0xb4, 0x1c, 0xe7, 0x13, - 0x02, 0xea, 0xc9, 0x8a, 0xb0, 0x71, 0x13, 0x66, 0x18, 0x72, 0x8d, 0xa4, 0x2b, 0xb5, 0x84, 0xac, - 0x37, 0x1a, 0x69, 0x55, 0xa1, 0x88, 0x0e, 0xfb, 0xbf, 0x36, 0x1c, 0x88, 0x46, 0xab, 0xf1, 0xcf, - 0xe3, 0x65, 0xc4, 0xbb, 0x71, 0x71, 0x62, 0x7d, 0xd4, 0x66, 0x63, 0x41, 0xe0, 0x7a, 0x46, 0xc4, - 0x9e, 0x66, 0xb3, 0xe9, 0xf7, 0x00, 0xb6, 0xb8, 0xc9, 0x7b, 0x82, 0xbc, 0xb8, 0x13, 0xef, 0x62, - 0xf2, 0xe2, 0x4e, 0xbe, 0x6e, 0xa8, 0x53, 0xe8, 0x00, 0xce, 0xa4, 0xa0, 0x39, 0xe8, 0x72, 0xd2, - 0x14, 0xd3, 0xe0, 0xa4, 0xc6, 0x95, 0x63, 0xf9, 0xa2, 0x0b, 0xc8, 0xf7, 0xde, 0xb9, 0x34, 0x88, - 0x23, 0x65, 0x01, 0xe3, 0x3b, 0xed, 0xd6, 0x3f, 0xe4, 0x61, 0x8e, 0xa1, 0x70, 0xfc, 0xe0, 0x7e, - 0x0c, 0x30, 0x06, 0xb4, 0xd1, 0x85, 0xf8, 0xa8, 0xa5, 0x6c, 0x40, 0x63, 0x75, 0x52, 0x75, 0xd4, - 0x40, 0x22, 0x40, 0xb1, 0x6c, 0x20, 0x49, 0xdc, 0x5b, 0x36, 0x90, 0x14, 0x84, 0x59, 0x9d, 0x42, - 0x9f, 0x41, 0x29, 0xc4, 0x25, 0x91, 0x8c, 0x68, 0xc6, 0x00, 0xd6, 0xc6, 0x85, 0x09, 0xb5, 0x51, - 0xed, 0x22, 0x70, 0xa3, 0xac, 0x5d, 0x12, 0xca, 0x94, 0xb5, 0x4b, 0xc3, 0x29, 0xc7, 0xe3, 0x65, - 0xc0, 0x45, 0xca, 0x78, 0x25, 0x7c, 0x28, 0x65, 0xbc, 0x32, 0xe2, 0xa1, 0x4e, 0xdd, 0x5f, 0xfb, - 0xed, 0x1f, 0x57, 0x95, 0x2f, 0xfe, 0xb8, 0x3a, 0xf5, 0x17, 0x5f, 0xae, 0x2a, 0xbf, 0xfd, 0x72, - 0x55, 0xf9, 0xfd, 0x97, 0xab, 0xca, 0x1f, 0xbe, 0x5c, 0x55, 0xfe, 0xfa, 0xbf, 0x57, 0xa7, 0x7e, - 0x98, 0x7b, 0xfe, 0xf6, 0xd3, 0x19, 0xfa, 0x5f, 0xa2, 0x6e, 0xff, 0x5f, 0x00, 0x00, 0x00, 0xff, - 0xff, 0x5e, 0xaf, 0xb3, 0x38, 0xdf, 0x4b, 0x00, 0x00, + // 5599 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x7c, 0x4d, 0x6c, 0x1c, 0xc9, + 0x75, 0x30, 0x7b, 0x66, 0x48, 0xce, 0xbc, 0xe1, 0x0c, 0x87, 0x25, 0x52, 0x1c, 0x0d, 0x25, 0x2e, + 0xd9, 0xf2, 0xfe, 0x48, 0xda, 0xe5, 0x6a, 0xb9, 0xda, 0xb5, 0x44, 0x6b, 0x57, 0x1a, 0x91, 0x94, + 0xc4, 0xb5, 0x44, 0x8e, 0x7b, 0x48, 0xf9, 0xef, 0x83, 0xfb, 0x6b, 0x4d, 0x17, 0x87, 0xbd, 0x3b, + 0xd3, 0xdd, 0xee, 0xee, 0x91, 0x44, 0x9f, 0x7c, 0x4d, 0x4e, 0x01, 0x0c, 0xc3, 0x80, 0x11, 0x20, + 0xc8, 0x29, 0x07, 0x1f, 0x9c, 0x4b, 0x82, 0x00, 0x81, 0x93, 0x4b, 0x10, 0x38, 0x01, 0x0c, 0xf8, + 0x12, 0xc0, 0x87, 0x00, 0xb1, 0x37, 0xb7, 0x1c, 0x72, 0xf2, 0x21, 0xb7, 0x04, 0xf5, 0xd7, 0xd3, + 0xd5, 0xdd, 0xd3, 0x33, 0xd4, 0xae, 0xbd, 0x7b, 0x9a, 0xee, 0x57, 0xef, 0xbd, 0xaa, 0x7a, 0xf5, + 0xea, 0xd5, 0xab, 0xf7, 0x5e, 0x0f, 0x94, 0x0c, 0xd7, 0xda, 0x70, 0x3d, 0x27, 0x70, 0x10, 0x78, + 0x03, 0x3b, 0xb0, 0xfa, 0x78, 0xe3, 0xd9, 0x3b, 0x8d, 0xb7, 0xba, 0x56, 0x70, 0x32, 0x78, 0xba, + 0xd1, 0x71, 0xfa, 0x6f, 0x77, 0x9d, 0xae, 0xf3, 0x36, 0x45, 0x79, 0x3a, 0x38, 0xa6, 0x6f, 0xf4, + 0x85, 0x3e, 0x31, 0x52, 0xf5, 0x2a, 0x54, 0x9f, 0x60, 0xcf, 0xb7, 0x1c, 0x5b, 0xc3, 0xdf, 0x1f, + 0x60, 0x3f, 0x40, 0x75, 0x98, 0x7d, 0xc6, 0x20, 0x75, 0x65, 0x4d, 0x79, 0xa3, 0xa4, 0x89, 0x57, + 0xf5, 0xaf, 0x14, 0x98, 0x0f, 0x91, 0x7d, 0xd7, 0xb1, 0x7d, 0x3c, 0x1a, 0x1b, 0xad, 0xc3, 0x1c, + 0x1f, 0x96, 0x6e, 0x1b, 0x7d, 0x5c, 0xcf, 0xd1, 0xe6, 0x32, 0x87, 0xed, 0x1b, 0x7d, 0x8c, 0x5e, + 0x87, 0x79, 0x81, 0x22, 0x98, 0xe4, 0x29, 0x56, 0x95, 0x83, 0x79, 0x6f, 0x68, 0x03, 0xce, 0x09, + 0x44, 0xc3, 0xb5, 0x42, 0xe4, 0x02, 0x45, 0x5e, 0xe0, 0x4d, 0x4d, 0xd7, 0xe2, 0xf8, 0xea, 0x77, + 0xa1, 0xb4, 0xb3, 0xdf, 0xde, 0x76, 0xec, 0x63, 0xab, 0x4b, 0x86, 0xe8, 0x63, 0x8f, 0xd0, 0xd4, + 0x95, 0xb5, 0x3c, 0x19, 0x22, 0x7f, 0x45, 0x0d, 0x28, 0xfa, 0xd8, 0xf0, 0x3a, 0x27, 0xd8, 0xaf, + 0xe7, 0x68, 0x53, 0xf8, 0x4e, 0xa8, 0x1c, 0x37, 0xb0, 0x1c, 0xdb, 0xaf, 0xe7, 0x19, 0x15, 0x7f, + 0x55, 0xff, 0x5c, 0x81, 0x72, 0xcb, 0xf1, 0x82, 0xc7, 0x86, 0xeb, 0x5a, 0x76, 0x17, 0x5d, 0x87, + 0x22, 0x95, 0x65, 0xc7, 0xe9, 0x51, 0x19, 0x54, 0x37, 0x17, 0x37, 0x86, 0x0b, 0xb2, 0xd1, 0xe2, + 0x6d, 0x5a, 0x88, 0x85, 0x5e, 0x85, 0x6a, 0xc7, 0xb1, 0x03, 0xc3, 0xb2, 0xb1, 0xa7, 0xbb, 0x8e, + 0x17, 0x50, 0xe1, 0x4c, 0x6b, 0x95, 0x10, 0x4a, 0xf8, 0xa3, 0x15, 0x28, 0x9d, 0x38, 0x7e, 0xc0, + 0x30, 0xf2, 0x14, 0xa3, 0x48, 0x00, 0xb4, 0x71, 0x19, 0x66, 0x69, 0xa3, 0xe5, 0x72, 0x31, 0xcc, + 0x90, 0xd7, 0x3d, 0x57, 0xfd, 0xb5, 0x02, 0xd3, 0x8f, 0x9d, 0x81, 0x1d, 0xc4, 0xba, 0x31, 0x82, + 0x13, 0xbe, 0x44, 0x91, 0x6e, 0x8c, 0xe0, 0x64, 0xd8, 0x0d, 0xc1, 0x60, 0xab, 0xc4, 0xba, 0x21, + 0x8d, 0x0d, 0x28, 0x7a, 0xd8, 0x30, 0x1d, 0xbb, 0x77, 0x4a, 0x87, 0x50, 0xd4, 0xc2, 0x77, 0xb2, + 0x7c, 0x3e, 0xee, 0x59, 0xf6, 0xe0, 0x85, 0xee, 0xe1, 0x9e, 0xf1, 0x14, 0xf7, 0xe8, 0x50, 0x8a, + 0x5a, 0x95, 0x83, 0x35, 0x06, 0x45, 0x1f, 0x42, 0xd9, 0xf5, 0x1c, 0xd7, 0xe8, 0x1a, 0x44, 0x82, + 0xf5, 0x69, 0x2a, 0xa4, 0x8b, 0x51, 0x21, 0xd1, 0x01, 0xb7, 0x86, 0x38, 0x5a, 0x94, 0x40, 0xfd, + 0x85, 0x02, 0xf3, 0x44, 0x61, 0x7c, 0xd7, 0xe8, 0xe0, 0x03, 0xba, 0x0c, 0xe8, 0x5d, 0x98, 0xb5, + 0x71, 0xf0, 0xdc, 0xf1, 0x3e, 0xe1, 0x42, 0xbf, 0x10, 0xe5, 0x17, 0x62, 0x3f, 0x76, 0x4c, 0xac, + 0x09, 0x4c, 0x74, 0x0d, 0xf2, 0xae, 0x65, 0xd2, 0x49, 0x66, 0x12, 0x10, 0x2c, 0x82, 0x6c, 0xb9, + 0x1d, 0x3a, 0xeb, 0x6c, 0x64, 0xcb, 0xed, 0x10, 0x21, 0x06, 0x86, 0xd7, 0xc5, 0x81, 0x6e, 0x99, + 0x7c, 0x41, 0x8a, 0x0c, 0xb0, 0x67, 0xaa, 0x2a, 0xc0, 0x9e, 0x1d, 0xbc, 0x7f, 0xe3, 0x89, 0xd1, + 0x1b, 0x60, 0xb4, 0x08, 0xd3, 0xcf, 0xc8, 0x03, 0x1d, 0x77, 0x5e, 0x63, 0x2f, 0xea, 0x2f, 0x0a, + 0xb0, 0xf2, 0x88, 0x08, 0xad, 0x6d, 0xd8, 0xe6, 0x53, 0xe7, 0x45, 0x1b, 0x77, 0x06, 0x9e, 0x15, + 0x9c, 0x6e, 0x3b, 0x76, 0x80, 0x5f, 0x04, 0xe8, 0x21, 0x2c, 0xd8, 0xa2, 0x5b, 0x5d, 0x68, 0x26, + 0xe1, 0x50, 0xde, 0x5c, 0x49, 0x1d, 0x1b, 0x93, 0x93, 0x56, 0xb3, 0x65, 0x80, 0x8f, 0xee, 0x0d, + 0x97, 0x4d, 0xf0, 0xc9, 0x51, 0x3e, 0xd2, 0x1c, 0xdb, 0xbb, 0x74, 0x34, 0x9c, 0x8b, 0x58, 0x51, + 0xc1, 0xe3, 0x7d, 0x20, 0x1b, 0x59, 0x37, 0x7c, 0x7d, 0xe0, 0x63, 0x8f, 0xca, 0xa8, 0xbc, 0x79, + 0x3e, 0x4a, 0x3f, 0x9c, 0xb0, 0x56, 0xf2, 0x06, 0x76, 0xd3, 0x3f, 0xf2, 0xb1, 0x87, 0x6e, 0x52, + 0xa3, 0x40, 0xe8, 0xba, 0x9e, 0x33, 0x70, 0xeb, 0xc5, 0x4c, 0x42, 0xa0, 0x84, 0x0f, 0x08, 0x26, + 0xb5, 0x15, 0x5c, 0xf1, 0x74, 0xcf, 0x71, 0x82, 0x63, 0x5f, 0x28, 0x9b, 0x00, 0x6b, 0x14, 0x8a, + 0xde, 0x86, 0x73, 0xfe, 0xc0, 0x75, 0x7b, 0xb8, 0x8f, 0xed, 0xc0, 0xe8, 0xb1, 0x8e, 0xfc, 0xfa, + 0xf4, 0x5a, 0xfe, 0x8d, 0xbc, 0x86, 0xa2, 0x4d, 0x94, 0xb1, 0x8f, 0x56, 0x01, 0x5c, 0xcf, 0x7a, + 0x66, 0xf5, 0x70, 0x17, 0x9b, 0xf5, 0x19, 0xca, 0x34, 0x02, 0x41, 0xef, 0x11, 0xfb, 0xd1, 0xe9, + 0x38, 0x7d, 0xb7, 0x5e, 0x4a, 0xca, 0x5b, 0xac, 0x53, 0xcb, 0x73, 0x8e, 0xad, 0x1e, 0xd6, 0x04, + 0x2e, 0xfa, 0x2a, 0x14, 0x0d, 0xd7, 0x35, 0xbc, 0xbe, 0xe3, 0xd5, 0x61, 0x3c, 0x5d, 0x88, 0x8c, + 0x6e, 0xc0, 0x22, 0xe7, 0xa1, 0xbb, 0xac, 0x91, 0x6d, 0xcd, 0x59, 0xa2, 0x55, 0xf7, 0x72, 0x75, + 0x45, 0x43, 0xbc, 0x9d, 0xd3, 0x92, 0x8d, 0xaa, 0xfe, 0x93, 0x02, 0xf3, 0x31, 0x9e, 0xe8, 0x23, + 0x98, 0x13, 0x1c, 0x82, 0x53, 0x17, 0xf3, 0x8d, 0xf2, 0x7a, 0xc6, 0x30, 0x36, 0xf8, 0xef, 0xe1, + 0xa9, 0x8b, 0xe9, 0x1e, 0x14, 0x2f, 0xe8, 0x32, 0x54, 0x7a, 0x4e, 0xc7, 0xe8, 0x51, 0x53, 0xe1, + 0xe1, 0x63, 0x6e, 0x29, 0xe6, 0x42, 0xa0, 0x86, 0x8f, 0xd5, 0xbb, 0x50, 0x8e, 0x30, 0x40, 0x08, + 0xaa, 0x1a, 0xeb, 0x6a, 0x07, 0x1f, 0x1b, 0x83, 0x5e, 0x50, 0x9b, 0x42, 0x55, 0x80, 0x23, 0xbb, + 0x43, 0x2c, 0xb3, 0x8d, 0xcd, 0x9a, 0x82, 0x2a, 0x50, 0x7a, 0x24, 0x58, 0xd4, 0x72, 0xea, 0x4f, + 0xf3, 0xb0, 0x44, 0x15, 0xaf, 0xe5, 0x98, 0x7c, 0x27, 0x70, 0x33, 0x7e, 0x19, 0x2a, 0x1d, 0xba, + 0x96, 0xba, 0x6b, 0x78, 0xd8, 0x0e, 0xb8, 0x31, 0x9b, 0x63, 0xc0, 0x16, 0x85, 0x21, 0x0d, 0x6a, + 0x3e, 0x9f, 0x91, 0xde, 0x61, 0x3b, 0x87, 0x2b, 0xb7, 0x34, 0xeb, 0x8c, 0x8d, 0xa6, 0xcd, 0xfb, + 0x89, 0x9d, 0x37, 0xeb, 0x9f, 0xfa, 0x9d, 0xa0, 0xc7, 0x4e, 0x82, 0xf2, 0xe6, 0x46, 0x82, 0x55, + 0x7c, 0xb0, 0x1b, 0x6d, 0x46, 0xb0, 0x6b, 0x07, 0xde, 0xa9, 0x26, 0xc8, 0xd1, 0x1d, 0x28, 0x3a, + 0xcf, 0xb0, 0x77, 0x82, 0x0d, 0x66, 0x23, 0xca, 0x9b, 0x97, 0x13, 0xac, 0xb6, 0x85, 0x6d, 0xd6, + 0xb0, 0xef, 0x0c, 0xbc, 0x0e, 0xf6, 0xb5, 0x90, 0x08, 0x35, 0xa1, 0xe4, 0x09, 0x30, 0x35, 0xa3, + 0x13, 0x72, 0x18, 0x52, 0x35, 0xb6, 0x60, 0x2e, 0x3a, 0x38, 0x54, 0x83, 0xfc, 0x27, 0xf8, 0x94, + 0x0b, 0x93, 0x3c, 0x0e, 0xed, 0x13, 0x5b, 0x61, 0xf6, 0xb2, 0x95, 0xbb, 0xa9, 0xa8, 0x1e, 0xa0, + 0xe1, 0x4c, 0x1f, 0xe3, 0xc0, 0x30, 0x8d, 0xc0, 0x40, 0x08, 0x0a, 0xf4, 0x80, 0x67, 0x2c, 0xe8, + 0x33, 0xe1, 0x3a, 0xe0, 0x86, 0xb6, 0xa4, 0x91, 0x47, 0x74, 0x11, 0x4a, 0xa1, 0x25, 0xe2, 0xa7, + 0xfc, 0x10, 0x40, 0x4e, 0x5b, 0x23, 0x08, 0x70, 0xdf, 0x0d, 0xa8, 0x60, 0x2a, 0x9a, 0x78, 0x55, + 0xff, 0x64, 0x1a, 0x6a, 0x09, 0x5d, 0xd8, 0x82, 0x62, 0x9f, 0x77, 0xcf, 0x6d, 0xe0, 0xaa, 0x74, + 0xe4, 0x26, 0x06, 0xa9, 0x85, 0xf8, 0xe4, 0x44, 0x23, 0xba, 0x16, 0xf1, 0x49, 0xc2, 0x77, 0xa6, + 0xe4, 0x5d, 0xdd, 0xb4, 0x3c, 0xdc, 0x09, 0x1c, 0xef, 0x94, 0x0f, 0x74, 0xae, 0xe7, 0x74, 0x77, + 0x04, 0x0c, 0xdd, 0x00, 0x30, 0x6d, 0x5f, 0xa7, 0x3a, 0xdc, 0xe5, 0xeb, 0xb8, 0x14, 0xed, 0x3e, + 0x74, 0x3d, 0xb4, 0x92, 0x69, 0xfb, 0x7c, 0xc8, 0xb7, 0xa1, 0x42, 0xce, 0x71, 0xbd, 0xcf, 0xbc, + 0x06, 0x66, 0x90, 0xca, 0x9b, 0xcb, 0xf2, 0xb8, 0x43, 0xaf, 0x42, 0x9b, 0x73, 0x87, 0x2f, 0x3e, + 0xba, 0x0b, 0x33, 0xf4, 0x28, 0xf5, 0xeb, 0x33, 0x94, 0xec, 0x8d, 0xf4, 0xe9, 0x72, 0xed, 0x7b, + 0x44, 0x51, 0x99, 0xf2, 0x71, 0x3a, 0x74, 0x00, 0x65, 0xc3, 0xb6, 0x9d, 0xc0, 0x60, 0x16, 0x7f, + 0x96, 0xb2, 0x79, 0x2b, 0x93, 0x4d, 0x73, 0x88, 0xcf, 0x78, 0x45, 0x39, 0xa0, 0xaf, 0xc2, 0x34, + 0x3d, 0x12, 0xb8, 0x0d, 0x5f, 0x1f, 0xbb, 0x29, 0x34, 0x86, 0x8f, 0x3e, 0x80, 0xd9, 0xe7, 0x96, + 0x6d, 0x3a, 0xcf, 0x7d, 0x6e, 0x4f, 0x25, 0x15, 0xfe, 0x26, 0x6b, 0x4a, 0x10, 0x0b, 0x9a, 0xc6, + 0x2d, 0x28, 0x47, 0xe6, 0x77, 0x16, 0xfd, 0x6d, 0x7c, 0x08, 0xb5, 0xf8, 0x9c, 0xce, 0xa4, 0xff, + 0x03, 0x58, 0xd4, 0x06, 0xf6, 0x70, 0x68, 0xc2, 0x65, 0xbe, 0x01, 0x33, 0x5c, 0x1b, 0x98, 0x32, + 0x5e, 0xcc, 0x12, 0xab, 0xc6, 0x71, 0xa3, 0xde, 0xef, 0x89, 0x61, 0x9b, 0x3d, 0xec, 0xf1, 0x1e, + 0x85, 0xf7, 0xfb, 0x90, 0x41, 0xd5, 0x0f, 0x60, 0x29, 0xd6, 0x2d, 0x77, 0xbe, 0xbf, 0x02, 0x55, + 0xd7, 0x31, 0x75, 0x9f, 0x81, 0x89, 0xe7, 0xc1, 0x6d, 0xa2, 0x1b, 0xe2, 0xee, 0x99, 0x84, 0xbc, + 0x1d, 0x38, 0x6e, 0x72, 0xd8, 0x93, 0x91, 0xd7, 0xe1, 0x7c, 0x9c, 0x9c, 0x75, 0xaf, 0xde, 0x81, + 0x65, 0x0d, 0xf7, 0x9d, 0x67, 0xf8, 0x65, 0x59, 0x37, 0xa0, 0x9e, 0x64, 0xc0, 0x99, 0x7f, 0x1b, + 0x96, 0x87, 0xd0, 0x76, 0x60, 0x04, 0x03, 0xff, 0x4c, 0xcc, 0xf9, 0xcd, 0xe4, 0xa9, 0xe3, 0xb3, + 0x85, 0x2c, 0x6a, 0xe2, 0x55, 0x5d, 0x86, 0xe9, 0x96, 0x63, 0xee, 0xb5, 0x50, 0x15, 0x72, 0x96, + 0xcb, 0x89, 0x73, 0x96, 0xab, 0x76, 0xa2, 0x7d, 0xee, 0x33, 0x9f, 0x91, 0x75, 0x1d, 0x47, 0x45, + 0x37, 0xa1, 0x6a, 0x98, 0xa6, 0x45, 0x14, 0xc9, 0xe8, 0xe9, 0x96, 0xcb, 0x2e, 0x10, 0xe5, 0xcd, + 0x85, 0xd8, 0xd2, 0xef, 0xb5, 0xb4, 0xca, 0x10, 0x71, 0xcf, 0xf5, 0xd5, 0x7b, 0x50, 0x0a, 0x7d, + 0x34, 0xe2, 0x5b, 0xc8, 0x3e, 0x58, 0xa6, 0x2f, 0x17, 0x5e, 0x41, 0xf6, 0x13, 0x87, 0x24, 0x1f, + 0xe6, 0x7b, 0x00, 0xa1, 0x51, 0x15, 0xee, 0xe1, 0x52, 0x2a, 0x4b, 0x2d, 0x82, 0xa8, 0xfe, 0x47, + 0x21, 0x6a, 0x64, 0x23, 0x53, 0x36, 0xc3, 0x29, 0x9b, 0x92, 0xd1, 0xcd, 0x9d, 0xd1, 0xe8, 0xbe, + 0x03, 0xd3, 0x7e, 0x60, 0x04, 0x98, 0x7b, 0xd3, 0x2b, 0xe9, 0x84, 0xa4, 0x63, 0xac, 0x31, 0x4c, + 0x74, 0x09, 0xa0, 0xe3, 0x61, 0x23, 0xc0, 0xa6, 0x6e, 0xb0, 0x53, 0x21, 0xaf, 0x95, 0x38, 0xa4, + 0x19, 0x10, 0x2b, 0x22, 0xfc, 0xff, 0x94, 0x83, 0x70, 0xc4, 0x32, 0x0e, 0x6f, 0x02, 0xa1, 0xf5, + 0x9a, 0x19, 0x6b, 0xbd, 0x38, 0x29, 0xb7, 0x5e, 0x43, 0x4b, 0x3c, 0x9b, 0x65, 0x89, 0x19, 0xd1, + 0x24, 0x96, 0xb8, 0x98, 0x65, 0x89, 0x39, 0x9b, 0x6c, 0x4b, 0x9c, 0x62, 0x48, 0x4a, 0x69, 0x86, + 0xe4, 0x8b, 0x34, 0x9d, 0xbf, 0x52, 0xa0, 0x9e, 0xdc, 0xcf, 0xdc, 0x8e, 0xdd, 0x80, 0x19, 0x9f, + 0x42, 0xb2, 0xed, 0x27, 0xa7, 0xe2, 0xb8, 0xe8, 0x1e, 0x14, 0x2c, 0xfb, 0xd8, 0xe1, 0x1b, 0x6f, + 0x23, 0x93, 0x86, 0xf7, 0xb4, 0xb1, 0x67, 0x1f, 0x3b, 0x4c, 0x82, 0x94, 0xb6, 0xf1, 0x55, 0x28, + 0x85, 0xa0, 0x33, 0xcd, 0x67, 0x0f, 0x16, 0x63, 0x7a, 0xcb, 0x2e, 0x77, 0xa1, 0xa2, 0x2b, 0x93, + 0x2a, 0xba, 0xfa, 0x7b, 0x25, 0xba, 0xf9, 0xee, 0x5b, 0xbd, 0x00, 0x7b, 0x89, 0xcd, 0xf7, 0xbe, + 0xe0, 0xcb, 0x76, 0xde, 0x5a, 0x06, 0x5f, 0x76, 0x77, 0xe2, 0xbb, 0xe8, 0x09, 0x54, 0xa9, 0xda, + 0xe9, 0x3e, 0xee, 0x51, 0xff, 0x85, 0xfb, 0xb0, 0x6f, 0xa7, 0x33, 0x60, 0xbd, 0x33, 0xb5, 0x6d, + 0x73, 0x0a, 0x26, 0xaf, 0x4a, 0x2f, 0x0a, 0x6b, 0xdc, 0x05, 0x94, 0x44, 0x3a, 0x93, 0x04, 0x1f, + 0x13, 0x1b, 0xe6, 0x07, 0xa9, 0xa7, 0xe9, 0x31, 0x1d, 0x46, 0xb6, 0x36, 0xb0, 0xa1, 0x6a, 0x1c, + 0x57, 0xfd, 0xb7, 0x3c, 0xc0, 0xb0, 0xf1, 0x4b, 0x6e, 0xbc, 0xb6, 0x42, 0x23, 0xc2, 0xbc, 0x40, + 0x35, 0x9d, 0x65, 0xaa, 0xf9, 0xd8, 0x93, 0xcd, 0x07, 0xf3, 0x07, 0x5f, 0x1f, 0xc1, 0xe0, 0xcc, + 0x86, 0x63, 0xf6, 0xcb, 0x66, 0x38, 0xee, 0xc3, 0xf9, 0xb8, 0x9a, 0x70, 0xab, 0xf1, 0x26, 0x4c, + 0x5b, 0x01, 0xee, 0xb3, 0xa8, 0x5e, 0x2c, 0x88, 0x10, 0x41, 0x67, 0x48, 0xea, 0x87, 0x70, 0x5e, + 0x5e, 0xab, 0xb3, 0xb9, 0x13, 0xea, 0xa3, 0xb8, 0x3f, 0x32, 0x34, 0x5f, 0x5c, 0x3f, 0x52, 0xc3, + 0x31, 0x71, 0x1a, 0x86, 0xa9, 0xfe, 0xb3, 0x02, 0x4b, 0xb1, 0xa6, 0x11, 0x1b, 0xff, 0xbb, 0x89, + 0x0d, 0xcc, 0xec, 0xdd, 0x8d, 0x8c, 0x5e, 0xfe, 0x88, 0xbb, 0xf8, 0x9b, 0xd0, 0x90, 0x97, 0x47, + 0x12, 0xed, 0xad, 0xd8, 0x56, 0x5e, 0x1f, 0x3b, 0xe8, 0x70, 0x3f, 0xb7, 0x60, 0x25, 0x95, 0x71, + 0x52, 0xe6, 0xf9, 0x09, 0x65, 0xfe, 0x3f, 0xb9, 0xa8, 0xcd, 0x6e, 0x06, 0x81, 0x67, 0x3d, 0x1d, + 0x04, 0xf8, 0xf3, 0x75, 0x74, 0x76, 0xc2, 0x9d, 0xcd, 0xec, 0xec, 0x9b, 0xe9, 0x94, 0xc3, 0xde, + 0x53, 0xf7, 0x78, 0x5b, 0xde, 0xe3, 0x05, 0xca, 0xea, 0x9d, 0xb1, 0xac, 0x32, 0x77, 0xfb, 0x17, + 0xb9, 0x89, 0xff, 0x45, 0x81, 0xf9, 0xd8, 0xaa, 0xa0, 0xbb, 0x00, 0x46, 0x38, 0x74, 0xae, 0x1f, + 0x6b, 0xe3, 0xa6, 0xa8, 0x45, 0x68, 0xc8, 0x99, 0xc8, 0x7c, 0xb8, 0x94, 0x33, 0x31, 0xc5, 0x87, + 0x0b, 0x5d, 0xb8, 0xdb, 0xc3, 0x0b, 0x28, 0x0b, 0x5c, 0xaa, 0x99, 0x17, 0x50, 0x46, 0x2b, 0x48, + 0xd4, 0x1f, 0xe5, 0x60, 0x31, 0x8d, 0x3b, 0x7a, 0x0d, 0xf2, 0x1d, 0x77, 0xc0, 0x67, 0x22, 0xa5, + 0x00, 0xb6, 0xdd, 0xc1, 0x91, 0x6f, 0x74, 0xb1, 0x46, 0x10, 0xd0, 0xdb, 0x30, 0xd3, 0xc7, 0x7d, + 0xc7, 0x3b, 0xe5, 0xe3, 0x96, 0x42, 0x00, 0x8f, 0x69, 0x0b, 0xc3, 0xe6, 0x68, 0x68, 0x73, 0xe8, + 0xea, 0xb2, 0xf1, 0xd6, 0x25, 0x8f, 0x9e, 0x35, 0x31, 0x92, 0xd0, 0xbf, 0xdd, 0x84, 0x59, 0xd7, + 0x73, 0x3a, 0xd8, 0xf7, 0x79, 0x84, 0xa2, 0x1e, 0xcb, 0x49, 0x90, 0x26, 0x4e, 0xc3, 0x11, 0xd1, + 0x16, 0x40, 0x98, 0x19, 0x10, 0x27, 0x53, 0x43, 0x9a, 0x87, 0x68, 0x65, 0x22, 0x89, 0x60, 0x93, + 0x5b, 0x62, 0xba, 0xe0, 0xd4, 0x7f, 0x54, 0x60, 0x2e, 0x3a, 0x46, 0x74, 0x11, 0x4a, 0x84, 0xa1, + 0x1f, 0x18, 0x7d, 0x97, 0xc7, 0xc0, 0x87, 0x00, 0xb4, 0x0f, 0x0b, 0x26, 0x0b, 0x16, 0xea, 0x96, + 0x1d, 0x60, 0xef, 0xd8, 0xe8, 0x08, 0xa7, 0x67, 0x3d, 0x65, 0xda, 0x7b, 0x02, 0x87, 0xcd, 0xa5, + 0xc6, 0x69, 0x43, 0x30, 0x6a, 0x02, 0x84, 0x7c, 0xc4, 0xa6, 0x9c, 0x80, 0x51, 0x84, 0x48, 0xfd, + 0x5f, 0x05, 0x96, 0x52, 0xb1, 0x52, 0x43, 0x5f, 0x9b, 0x50, 0xf4, 0x5e, 0xe8, 0x4f, 0x4f, 0x03, + 0xec, 0xa7, 0x2d, 0xf0, 0x51, 0x24, 0xbe, 0x3d, 0xeb, 0xbd, 0xb8, 0x47, 0xf0, 0xd0, 0x0d, 0x28, + 0x79, 0x2f, 0x74, 0xec, 0x79, 0x8e, 0x27, 0x74, 0x72, 0x24, 0x51, 0xd1, 0x7b, 0xb1, 0x4b, 0x11, + 0x49, 0x4f, 0x81, 0xe8, 0xa9, 0x30, 0xa6, 0xa7, 0x60, 0xd8, 0x53, 0x10, 0xf6, 0x34, 0x3d, 0xa6, + 0xa7, 0x80, 0xf7, 0xa4, 0x7e, 0x0c, 0x73, 0x51, 0x95, 0x19, 0xb3, 0x84, 0xb7, 0xa1, 0xc2, 0x55, + 0x4a, 0xef, 0x38, 0x03, 0x3b, 0x18, 0x27, 0x86, 0x39, 0x8e, 0xbd, 0x4d, 0x90, 0xd5, 0x9f, 0x29, + 0x50, 0xda, 0xeb, 0x1b, 0x5d, 0xdc, 0x76, 0x71, 0x87, 0xd8, 0x14, 0x8b, 0xbc, 0x70, 0x11, 0xb3, + 0x17, 0xf4, 0x50, 0xb6, 0x8f, 0xec, 0x44, 0x7c, 0x4d, 0xca, 0x22, 0x08, 0x0e, 0x63, 0x8c, 0xe2, + 0x67, 0xb5, 0x6c, 0x9b, 0x50, 0xfc, 0x3a, 0x3e, 0x65, 0xbe, 0xff, 0x84, 0x74, 0xea, 0x8f, 0x0b, + 0xb0, 0x3c, 0x22, 0x52, 0x4b, 0x1d, 0x47, 0x77, 0xa0, 0xbb, 0xd8, 0xb3, 0x1c, 0x53, 0x88, 0xb6, + 0xe3, 0x0e, 0x5a, 0x14, 0x80, 0x56, 0x80, 0xbc, 0xe8, 0xdf, 0x1f, 0x38, 0xfc, 0x6c, 0xca, 0x6b, + 0xc5, 0x8e, 0x3b, 0xf8, 0x06, 0x79, 0x17, 0xb4, 0xfe, 0x89, 0xe1, 0x61, 0xa6, 0x46, 0x8c, 0xb6, + 0x4d, 0x01, 0xe8, 0x1d, 0x58, 0x62, 0x06, 0x45, 0xef, 0x59, 0x7d, 0x8b, 0x6c, 0xaf, 0x88, 0xee, + 0xe4, 0x35, 0xc4, 0x1a, 0x1f, 0x91, 0xb6, 0x3d, 0x9b, 0x69, 0x8b, 0x0a, 0x15, 0xc7, 0xe9, 0xeb, + 0x7e, 0xc7, 0xf1, 0xb0, 0x6e, 0x98, 0x1f, 0x53, 0x8d, 0xc9, 0x6b, 0x65, 0xc7, 0xe9, 0xb7, 0x09, + 0xac, 0x69, 0x7e, 0x8c, 0x5e, 0x81, 0x72, 0xc7, 0x1d, 0xf8, 0x38, 0xd0, 0xc9, 0x0f, 0xbd, 0x4f, + 0x97, 0x34, 0x60, 0xa0, 0x6d, 0x77, 0xe0, 0x47, 0x10, 0xfa, 0xc4, 0x5b, 0x9b, 0x8d, 0x22, 0x3c, + 0xc6, 0x7d, 0x9a, 0x90, 0x3a, 0x19, 0x74, 0xb1, 0x6b, 0x74, 0x31, 0x1b, 0x9a, 0xb8, 0x14, 0x4b, + 0x09, 0xa9, 0x87, 0x1c, 0x85, 0x0e, 0x50, 0xab, 0x9e, 0x44, 0x5f, 0x7d, 0xf4, 0x11, 0xcc, 0x0e, + 0x6c, 0xeb, 0xd8, 0xc2, 0x66, 0xbd, 0x44, 0x69, 0xaf, 0x4f, 0x10, 0x17, 0xdf, 0x38, 0x62, 0x24, + 0x3c, 0x4c, 0xcf, 0x19, 0xa0, 0x2d, 0x68, 0x70, 0x41, 0xf9, 0xcf, 0x0d, 0x37, 0x2e, 0x2d, 0xa0, + 0x22, 0x38, 0xcf, 0x30, 0xda, 0xcf, 0x0d, 0x37, 0x2a, 0xb1, 0xc6, 0x16, 0xcc, 0x45, 0x99, 0x9e, + 0x49, 0x97, 0xee, 0x41, 0x45, 0x9a, 0x24, 0x59, 0x6d, 0x2a, 0x14, 0xdf, 0xfa, 0x81, 0xd8, 0x00, + 0x45, 0x02, 0x68, 0x5b, 0x3f, 0xa0, 0x69, 0x44, 0x3a, 0x32, 0xca, 0xa7, 0xa0, 0xb1, 0x17, 0xd5, + 0x80, 0x8a, 0x94, 0xb9, 0x23, 0x26, 0x8a, 0xa6, 0xe8, 0xb8, 0x89, 0x22, 0xcf, 0x04, 0xe6, 0x39, + 0x3d, 0x31, 0x02, 0xfa, 0x4c, 0x60, 0x34, 0x47, 0xc4, 0x22, 0xde, 0xf4, 0x99, 0x76, 0x81, 0x9f, + 0xf1, 0xb4, 0x6e, 0x49, 0x63, 0x2f, 0xaa, 0x09, 0xb0, 0x6d, 0xb8, 0xc6, 0x53, 0xab, 0x67, 0x05, + 0xa7, 0xe8, 0x0a, 0xd4, 0x0c, 0xd3, 0xd4, 0x3b, 0x02, 0x62, 0x61, 0x91, 0x66, 0x9f, 0x37, 0x4c, + 0x73, 0x3b, 0x02, 0x46, 0xd7, 0x60, 0xc1, 0xf4, 0x1c, 0x57, 0xc6, 0x65, 0x79, 0xf7, 0x1a, 0x69, + 0x88, 0x22, 0xab, 0xff, 0x30, 0x03, 0x97, 0xe4, 0x65, 0x8b, 0x67, 0x44, 0xb7, 0x60, 0x2e, 0xd6, + 0x6b, 0x22, 0x97, 0x38, 0x1c, 0xa7, 0x26, 0xe1, 0xc6, 0x72, 0x7e, 0xb9, 0x44, 0xce, 0x2f, 0x35, + 0xdb, 0x9a, 0xff, 0x9c, 0xb2, 0xad, 0x85, 0xcf, 0x98, 0x6d, 0x9d, 0x7e, 0xd9, 0x6c, 0xeb, 0xdc, + 0xc4, 0xd9, 0xd6, 0xd7, 0xe8, 0xcd, 0x50, 0xf4, 0x48, 0xcf, 0x38, 0xb6, 0xb1, 0x2b, 0x21, 0x77, + 0x5b, 0x54, 0x70, 0xc4, 0xb2, 0xb2, 0xb3, 0x67, 0xc9, 0xca, 0x16, 0x47, 0x66, 0x65, 0xd7, 0x60, + 0xce, 0x76, 0x74, 0x1b, 0x3f, 0xd7, 0xc9, 0xb2, 0xf8, 0xf5, 0x32, 0x5b, 0x23, 0xdb, 0xd9, 0xc7, + 0xcf, 0x5b, 0x04, 0x82, 0xd6, 0x61, 0xae, 0x6f, 0xf8, 0x9f, 0x60, 0x93, 0xa6, 0x47, 0xfd, 0x7a, + 0x85, 0x6a, 0x52, 0x99, 0xc1, 0x5a, 0x04, 0x84, 0x5e, 0x85, 0x70, 0x1c, 0x1c, 0xa9, 0x4a, 0x91, + 0x2a, 0x02, 0xca, 0xd0, 0x22, 0x19, 0xde, 0xf9, 0x97, 0xcc, 0xf0, 0xd6, 0xce, 0x92, 0xe1, 0x7d, + 0x0b, 0x6a, 0xe2, 0x59, 0xa4, 0x78, 0x59, 0xc4, 0x8e, 0x66, 0x77, 0xe7, 0x45, 0x9b, 0x48, 0xe3, + 0x8e, 0x4a, 0x08, 0x43, 0x66, 0x42, 0xf8, 0xe7, 0x0a, 0xf7, 0x53, 0xc3, 0x0d, 0xc4, 0x33, 0x51, + 0x52, 0x12, 0x51, 0x79, 0x99, 0x24, 0x22, 0x3a, 0x1c, 0x99, 0x66, 0xbd, 0x32, 0x9a, 0xd3, 0xb8, + 0x44, 0xab, 0xfa, 0x23, 0x05, 0x2e, 0x71, 0x27, 0x72, 0x44, 0x11, 0x44, 0x8a, 0x5a, 0x2a, 0x23, + 0xd4, 0xb2, 0xe3, 0x61, 0x13, 0xdb, 0x81, 0x65, 0xf4, 0x74, 0xdf, 0xc5, 0x1d, 0x91, 0x5a, 0x19, + 0x82, 0xa9, 0x7b, 0xb1, 0x0e, 0x73, 0xac, 0xf6, 0x85, 0xfb, 0xca, 0xac, 0xc4, 0xa5, 0x4c, 0xcb, + 0x5f, 0x18, 0x48, 0x75, 0x60, 0x79, 0x44, 0x4e, 0x2a, 0x55, 0x0c, 0x4a, 0x52, 0x0c, 0x99, 0x73, + 0x4a, 0x8a, 0xe1, 0xc7, 0x0a, 0xbc, 0xc2, 0x49, 0x46, 0xda, 0xbe, 0x2f, 0x42, 0x10, 0x7f, 0xa3, + 0x84, 0x3e, 0x7e, 0x5c, 0xa5, 0xb6, 0x93, 0x2a, 0xf5, 0x6a, 0x8a, 0x04, 0xb2, 0x95, 0xea, 0xc9, + 0x48, 0xa5, 0xba, 0x96, 0xc5, 0x6b, 0xac, 0x3c, 0x7f, 0xa6, 0xc0, 0x85, 0x91, 0x03, 0x88, 0x39, + 0x4d, 0x4a, 0xdc, 0x69, 0xe2, 0x0e, 0xd7, 0xd0, 0x8f, 0x65, 0x0e, 0x17, 0x75, 0x55, 0xb9, 0x67, + 0xa3, 0xf7, 0x8d, 0x17, 0x56, 0x7f, 0xd0, 0xe7, 0x1e, 0x17, 0x61, 0xf7, 0x98, 0x41, 0x5e, 0xc2, + 0xe5, 0x52, 0x9b, 0xb0, 0x10, 0x8e, 0x32, 0x33, 0xc5, 0x1e, 0x49, 0x99, 0xe7, 0xe4, 0x94, 0xb9, + 0x0d, 0x33, 0x3b, 0xf8, 0x99, 0xd5, 0xc1, 0x9f, 0x4b, 0x05, 0xd8, 0x1a, 0x94, 0x5d, 0xec, 0xf5, + 0x2d, 0xdf, 0x0f, 0x0f, 0xc1, 0x92, 0x16, 0x05, 0xa9, 0x3f, 0x9f, 0x81, 0xf9, 0xb8, 0x46, 0xdc, + 0x4a, 0x64, 0xe8, 0x2f, 0xa5, 0xde, 0x24, 0x53, 0x42, 0x28, 0xd7, 0x84, 0xcb, 0x9f, 0x4b, 0xa6, + 0xaf, 0x42, 0xb7, 0x5e, 0xdc, 0x04, 0xea, 0x30, 0xdb, 0x71, 0xfa, 0x7d, 0xc3, 0x36, 0x45, 0x99, + 0x1e, 0x7f, 0x25, 0x32, 0x33, 0xbc, 0x2e, 0x0b, 0x9e, 0x94, 0x34, 0xfa, 0x4c, 0x16, 0x8c, 0xdc, + 0xe2, 0x2c, 0x9b, 0xe6, 0xf8, 0xe9, 0x41, 0x5a, 0xd2, 0x80, 0x83, 0x76, 0x2c, 0x0f, 0xbd, 0x01, + 0x05, 0x6c, 0x3f, 0x13, 0x51, 0x55, 0xe9, 0x12, 0x2f, 0xdc, 0x7c, 0x8d, 0x62, 0xa0, 0x2b, 0x30, + 0xd3, 0x27, 0x4a, 0x20, 0xf2, 0x40, 0x0b, 0x89, 0x72, 0x36, 0x8d, 0x23, 0xa0, 0x37, 0x61, 0xd6, + 0xa4, 0xeb, 0x21, 0xfc, 0x5a, 0x24, 0x55, 0x0b, 0xd0, 0x26, 0x4d, 0xa0, 0xa0, 0x3b, 0x61, 0x04, + 0xa9, 0x94, 0x0c, 0xed, 0xc6, 0xc4, 0x9c, 0x1a, 0x3c, 0xda, 0x97, 0x2f, 0x47, 0x90, 0x8c, 0x43, + 0xc5, 0xb9, 0x64, 0x47, 0x89, 0x2f, 0x40, 0xb1, 0xe7, 0x74, 0x99, 0x72, 0x94, 0x59, 0x8d, 0x67, + 0xcf, 0xe9, 0x52, 0xdd, 0x58, 0x84, 0x69, 0x3f, 0x30, 0x2d, 0x9b, 0x7a, 0x16, 0x45, 0x8d, 0xbd, + 0x90, 0x2d, 0x45, 0x1f, 0x74, 0xc7, 0xee, 0xe0, 0x7a, 0x85, 0x36, 0x95, 0x28, 0xe4, 0xc0, 0xee, + 0xd0, 0x6b, 0x52, 0x10, 0x9c, 0xd6, 0xab, 0x14, 0x4e, 0x1e, 0x87, 0x81, 0x9c, 0xf9, 0x11, 0x81, + 0x9c, 0xd8, 0x80, 0x53, 0x02, 0x39, 0xb5, 0x91, 0x81, 0x9c, 0x38, 0xed, 0x97, 0xa1, 0x90, 0xe0, + 0xef, 0x14, 0x38, 0xbf, 0x4d, 0xb3, 0x01, 0x11, 0x8b, 0x74, 0x96, 0xe4, 0xf6, 0xbb, 0x61, 0xc5, + 0x41, 0x4a, 0xda, 0x38, 0x3e, 0x63, 0x51, 0x70, 0xb0, 0x0d, 0x55, 0xc1, 0x96, 0x13, 0xe7, 0x27, + 0x28, 0x57, 0xa8, 0xf8, 0xd1, 0x57, 0xf5, 0x36, 0x2c, 0x27, 0x46, 0xce, 0x63, 0xb2, 0xeb, 0x30, + 0x37, 0xb4, 0x36, 0xe1, 0xc0, 0xcb, 0x21, 0x6c, 0xcf, 0x54, 0xb7, 0x60, 0xa9, 0x1d, 0x18, 0x5e, + 0x90, 0x98, 0xf6, 0x04, 0xb4, 0xb4, 0x10, 0x41, 0xa6, 0xe5, 0xb5, 0x02, 0x6d, 0x58, 0x6c, 0x07, + 0x8e, 0xfb, 0x12, 0x4c, 0x89, 0xfd, 0x20, 0x33, 0x77, 0x06, 0xc2, 0xba, 0x8b, 0x57, 0x75, 0x99, + 0x95, 0x4d, 0x24, 0x7b, 0xfb, 0x1a, 0x9c, 0x67, 0x55, 0x0b, 0x2f, 0x33, 0x89, 0x0b, 0xa2, 0x66, + 0x22, 0xc9, 0xf7, 0x01, 0x9c, 0x93, 0x02, 0x6c, 0x3c, 0xa3, 0x78, 0x5d, 0xce, 0x28, 0x8e, 0x0e, + 0xc8, 0x85, 0x09, 0xc5, 0x9f, 0xe4, 0x22, 0xf6, 0x78, 0x44, 0x5a, 0xe1, 0x3d, 0x39, 0x9f, 0xf8, + 0xca, 0x68, 0xae, 0x52, 0x3a, 0x31, 0xa9, 0x9d, 0xf9, 0x14, 0xed, 0x3c, 0x4a, 0xe4, 0x2c, 0x0a, + 0xc9, 0x1c, 0x6d, 0x6c, 0x84, 0x7f, 0x94, 0x6c, 0xc5, 0x23, 0x96, 0x73, 0x0c, 0xbb, 0x0e, 0x13, + 0x15, 0xef, 0xc6, 0x12, 0x15, 0x2b, 0x19, 0x23, 0x0d, 0x53, 0x14, 0x3f, 0x29, 0x40, 0x29, 0x6c, + 0x4b, 0x48, 0x38, 0x29, 0xaa, 0x5c, 0x8a, 0xa8, 0xa2, 0xe7, 0x64, 0xfe, 0x25, 0xcf, 0xc9, 0xc2, + 0x04, 0xe7, 0xe4, 0x0a, 0x94, 0xe8, 0x03, 0x2d, 0xdd, 0x64, 0xe7, 0x5e, 0x91, 0x02, 0x34, 0x7c, + 0x3c, 0x54, 0xb1, 0x99, 0x09, 0x55, 0x2c, 0x96, 0xdf, 0x9c, 0x8d, 0xe7, 0x37, 0x6f, 0x85, 0x67, + 0x58, 0x31, 0x19, 0x70, 0x0d, 0x39, 0xa6, 0x9e, 0x5e, 0xb1, 0xd0, 0x5e, 0x29, 0x19, 0xda, 0x1b, + 0xd2, 0x7f, 0x69, 0xf3, 0x1d, 0x07, 0x2c, 0x69, 0x19, 0xd5, 0x33, 0x6e, 0x23, 0xdf, 0x93, 0x62, + 0xec, 0x2c, 0x79, 0xb5, 0x94, 0x3a, 0x3b, 0x29, 0xbc, 0x7e, 0x04, 0xe7, 0xa5, 0x85, 0x18, 0x16, + 0x43, 0x4d, 0x66, 0xe3, 0x46, 0x54, 0x42, 0xfd, 0x66, 0x3a, 0x62, 0x29, 0x46, 0x94, 0xfd, 0xdc, + 0x4a, 0x64, 0xc3, 0x26, 0xd6, 0xd0, 0xeb, 0x72, 0xe2, 0xfc, 0xcc, 0x7a, 0x95, 0xc8, 0x9b, 0x53, + 0xcf, 0xc2, 0xf0, 0x78, 0x33, 0x0b, 0x46, 0x96, 0x38, 0xa4, 0x49, 0xfd, 0xf1, 0x63, 0xcb, 0xb6, + 0xfc, 0x13, 0xd6, 0x3e, 0xc3, 0xfc, 0x71, 0x01, 0x6a, 0xd2, 0x80, 0x1a, 0x7e, 0x61, 0x05, 0x7a, + 0xc7, 0x31, 0x31, 0xd5, 0xda, 0x69, 0xad, 0x48, 0x00, 0xdb, 0x8e, 0x89, 0x87, 0xfb, 0xa9, 0x78, + 0xd6, 0xfd, 0x54, 0x8a, 0xed, 0xa7, 0xf3, 0x30, 0xe3, 0x61, 0xc3, 0x77, 0x6c, 0x76, 0x45, 0xd7, + 0xf8, 0x1b, 0x59, 0x88, 0x3e, 0xf6, 0x7d, 0xd2, 0x07, 0x77, 0xa4, 0xf8, 0x6b, 0xc4, 0xe9, 0x9b, + 0xcb, 0x70, 0xfa, 0x32, 0x8a, 0x8a, 0x62, 0x4e, 0x5f, 0x25, 0xc3, 0xe9, 0x9b, 0xa8, 0xa6, 0x68, + 0xe8, 0xde, 0x56, 0xc7, 0xb9, 0xb7, 0x51, 0xff, 0x70, 0x5e, 0xf2, 0x0f, 0xbf, 0xc8, 0x2d, 0xf8, + 0xaf, 0x0a, 0x2c, 0x27, 0xb6, 0x0c, 0xdf, 0x84, 0xef, 0xc6, 0xea, 0x8d, 0x56, 0x32, 0xe4, 0x14, + 0x96, 0x1b, 0x35, 0xa5, 0x72, 0xa3, 0xb7, 0xb2, 0x48, 0x3e, 0xf7, 0x6a, 0xa3, 0xdf, 0xe6, 0xe0, + 0x95, 0x23, 0xd7, 0x8c, 0x79, 0x5d, 0xfc, 0x0a, 0x3d, 0xb9, 0x21, 0xb8, 0x25, 0x27, 0x4c, 0x27, + 0x8a, 0xfa, 0x70, 0x57, 0xfb, 0x4e, 0x3c, 0x67, 0x3a, 0xe1, 0xfd, 0x5e, 0x50, 0xa1, 0xef, 0xa5, + 0xa5, 0xb4, 0x6f, 0x4b, 0x29, 0xa1, 0xec, 0x09, 0xfe, 0x81, 0x13, 0x39, 0x2a, 0xac, 0x8d, 0x1e, + 0x00, 0xf7, 0xd0, 0xfe, 0x3f, 0xcc, 0xef, 0xbe, 0xc0, 0x9d, 0xf6, 0xa9, 0xdd, 0x39, 0x83, 0xd4, + 0x6b, 0x90, 0xef, 0xf4, 0x4d, 0x1e, 0xe8, 0x26, 0x8f, 0x51, 0xa7, 0x33, 0x2f, 0x3b, 0x9d, 0x3a, + 0xd4, 0x86, 0x3d, 0x70, 0x6d, 0x3d, 0x4f, 0xb4, 0xd5, 0x24, 0xc8, 0x84, 0xf9, 0x9c, 0xc6, 0xdf, + 0x38, 0x1c, 0x7b, 0xac, 0x6c, 0x98, 0xc1, 0xb1, 0xe7, 0xc9, 0x46, 0x2e, 0x2f, 0x1b, 0x39, 0xf5, + 0xa7, 0x0a, 0x94, 0x49, 0x0f, 0x9f, 0x69, 0xfc, 0xfc, 0x06, 0x97, 0x1f, 0xde, 0xe0, 0xc2, 0x8b, + 0x60, 0x21, 0x7a, 0x11, 0x1c, 0x8e, 0x7c, 0x9a, 0x82, 0x93, 0x23, 0x9f, 0x09, 0xe1, 0xd8, 0xf3, + 0xd4, 0x35, 0x98, 0x63, 0x63, 0xe3, 0x33, 0xaf, 0x41, 0x7e, 0xe0, 0xf5, 0xc4, 0xfa, 0x0d, 0xbc, + 0x9e, 0xfa, 0xa7, 0x0a, 0x54, 0x9a, 0x41, 0x60, 0x74, 0x4e, 0xce, 0x30, 0x81, 0x70, 0x70, 0xb9, + 0xe8, 0xe0, 0x92, 0x93, 0x18, 0x0e, 0xb7, 0x30, 0x62, 0xb8, 0xd3, 0xd2, 0x70, 0x55, 0xa8, 0x8a, + 0xb1, 0x8c, 0x1c, 0xf0, 0x3e, 0xa0, 0x96, 0xe3, 0x05, 0xf7, 0x1d, 0xef, 0xb9, 0xe1, 0x99, 0x67, + 0xbb, 0xe4, 0x21, 0x28, 0xf0, 0x8f, 0x03, 0xf3, 0x6f, 0x4c, 0x6b, 0xf4, 0x59, 0x7d, 0x1d, 0xce, + 0x49, 0xfc, 0x46, 0x76, 0xbc, 0x05, 0x65, 0x7a, 0x68, 0x71, 0xff, 0xff, 0x5a, 0x34, 0x8f, 0x3a, + 0xe6, 0x70, 0x53, 0x77, 0x60, 0x81, 0xb8, 0x2f, 0x14, 0x1e, 0xda, 0x97, 0xb7, 0x63, 0x2e, 0xf2, + 0x72, 0x82, 0x45, 0xcc, 0x3d, 0xfe, 0x77, 0x05, 0xa6, 0x29, 0x3c, 0xe1, 0x52, 0xac, 0x40, 0xc9, + 0xc3, 0xae, 0xa3, 0x07, 0x46, 0x37, 0xfc, 0xf0, 0x92, 0x00, 0x0e, 0x8d, 0x2e, 0x0d, 0xeb, 0xd3, + 0x46, 0xd3, 0xea, 0x62, 0x3f, 0x10, 0x5f, 0x5f, 0x96, 0x09, 0x6c, 0x87, 0x81, 0x88, 0x60, 0x68, + 0x4a, 0xac, 0x40, 0x33, 0x5f, 0xf4, 0x19, 0xbd, 0xc1, 0xbe, 0x38, 0xc9, 0xce, 0x8d, 0xd0, 0x2f, + 0x51, 0x1a, 0x50, 0x8c, 0x25, 0x35, 0xc2, 0x77, 0x74, 0x05, 0x0a, 0x34, 0x48, 0x3a, 0x9b, 0x25, + 0x25, 0x8a, 0xa2, 0xde, 0x01, 0x14, 0x15, 0x12, 0x5f, 0x88, 0x2b, 0x30, 0x43, 0x65, 0x28, 0x7c, + 0xbb, 0x85, 0x04, 0x0b, 0x8d, 0x23, 0xa8, 0xdf, 0x05, 0xc4, 0x78, 0x4a, 0xfe, 0xdc, 0x59, 0x16, + 0x2a, 0xc3, 0xb3, 0xfb, 0x5b, 0x05, 0xce, 0x49, 0xdc, 0xf9, 0xf8, 0x5e, 0x97, 0xd9, 0xa7, 0x0c, + 0x8f, 0xb3, 0xfe, 0x40, 0x3a, 0xee, 0xae, 0x24, 0x87, 0xf1, 0x07, 0x3a, 0xea, 0x7e, 0xa5, 0x00, + 0x34, 0x07, 0xc1, 0x09, 0x8f, 0x23, 0x46, 0x17, 0x4b, 0x89, 0x2d, 0x56, 0x03, 0x8a, 0xae, 0xe1, + 0xfb, 0xcf, 0x1d, 0x4f, 0xdc, 0xad, 0xc2, 0x77, 0x1a, 0xfd, 0x1b, 0x04, 0x27, 0x22, 0x9d, 0x49, + 0x9e, 0xd1, 0xab, 0x50, 0x65, 0x5f, 0xfe, 0xea, 0x86, 0x69, 0x7a, 0xa2, 0x34, 0xa6, 0xa4, 0x55, + 0x18, 0xb4, 0xc9, 0x80, 0x04, 0xcd, 0xa2, 0xa1, 0xf1, 0xe0, 0x54, 0x0f, 0x9c, 0x4f, 0xb0, 0xcd, + 0xef, 0x4b, 0x15, 0x01, 0x3d, 0x24, 0x40, 0x96, 0x5b, 0xea, 0x5a, 0x7e, 0xe0, 0x09, 0x34, 0x91, + 0x21, 0xe3, 0x50, 0x8a, 0xa6, 0xfe, 0xb5, 0x02, 0xb5, 0xd6, 0xa0, 0xd7, 0x63, 0xc2, 0x7d, 0x99, + 0x45, 0xbe, 0xca, 0xa7, 0x92, 0x4b, 0xaa, 0xf6, 0x50, 0x50, 0x7c, 0x8a, 0x9f, 0x4b, 0x88, 0xe7, + 0x3a, 0x2c, 0x44, 0x46, 0xcc, 0x15, 0x47, 0x72, 0x78, 0x15, 0xd9, 0xe1, 0x55, 0x9b, 0x80, 0x58, + 0x54, 0xe3, 0xa5, 0x67, 0xa9, 0x2e, 0xc1, 0x39, 0x89, 0x05, 0x3f, 0x72, 0xaf, 0x42, 0x85, 0x97, + 0xde, 0x70, 0x85, 0xb8, 0x00, 0x45, 0x62, 0x3a, 0x3b, 0x96, 0x29, 0x72, 0xda, 0xb3, 0xae, 0x63, + 0x6e, 0x5b, 0xa6, 0xa7, 0x7e, 0x03, 0x2a, 0xfc, 0x73, 0x43, 0x8e, 0x7b, 0x17, 0xaa, 0xbc, 0x1e, + 0x4a, 0x97, 0xbe, 0xcf, 0xb9, 0x90, 0x52, 0xff, 0x23, 0x44, 0x61, 0x47, 0x5f, 0xd5, 0xef, 0x41, + 0x83, 0x79, 0x05, 0x12, 0x63, 0x31, 0xc1, 0xbb, 0x20, 0x0a, 0x65, 0x33, 0xf8, 0xcb, 0x94, 0x15, + 0x2f, 0xfa, 0xaa, 0x5e, 0x82, 0x95, 0x54, 0xfe, 0x7c, 0xf6, 0x2e, 0xd4, 0x86, 0x0d, 0xec, 0x23, + 0x92, 0x30, 0x51, 0xaf, 0x44, 0x12, 0xf5, 0xe7, 0x43, 0x87, 0x36, 0x27, 0x4e, 0x28, 0xea, 0xb3, + 0x0e, 0x2f, 0x22, 0xf9, 0x51, 0x17, 0x91, 0x82, 0x74, 0x11, 0x51, 0x1f, 0x87, 0x32, 0xe4, 0xd7, + 0xc1, 0xdb, 0xf4, 0xc2, 0xca, 0xfa, 0x16, 0x46, 0xed, 0x62, 0xfa, 0xfc, 0x18, 0x92, 0x16, 0xc1, + 0x57, 0xaf, 0x40, 0x45, 0x36, 0x6f, 0x11, 0x8b, 0xa5, 0x24, 0x2c, 0x56, 0x35, 0x66, 0xac, 0xde, + 0x89, 0xf9, 0xe9, 0x69, 0x72, 0x8d, 0x79, 0xe9, 0x37, 0x25, 0xb3, 0xf5, 0x15, 0x29, 0x1f, 0xfb, + 0x07, 0xb2, 0x58, 0x8b, 0xdc, 0x8e, 0xdf, 0xf7, 0x09, 0x3d, 0x9f, 0xa8, 0x7a, 0x19, 0xca, 0x47, + 0xa3, 0x3e, 0xfa, 0x2e, 0x88, 0x4a, 0xa0, 0xf7, 0x61, 0xf1, 0xbe, 0xd5, 0xc3, 0xfe, 0xa9, 0x1f, + 0xe0, 0xfe, 0x1e, 0x35, 0x2f, 0xc7, 0x16, 0xf6, 0xd0, 0x2a, 0x00, 0xbd, 0x5c, 0xb9, 0x8e, 0x15, + 0x7e, 0xe8, 0x1a, 0x81, 0xa8, 0xbf, 0x51, 0x60, 0x7e, 0x48, 0x38, 0x49, 0x4d, 0xd6, 0x7b, 0x30, + 0x7d, 0xec, 0x8b, 0x20, 0x54, 0x2c, 0xc4, 0x9e, 0x36, 0x04, 0xad, 0x70, 0xec, 0xef, 0x99, 0xe8, + 0x7d, 0x80, 0x81, 0x8f, 0x4d, 0x9e, 0xb5, 0x1a, 0x53, 0x99, 0x56, 0x22, 0xa8, 0xac, 0x70, 0xe8, + 0x26, 0x94, 0x2d, 0xdb, 0x31, 0x31, 0xcd, 0x4f, 0x9a, 0xe3, 0xaa, 0xd3, 0x80, 0xe1, 0x1e, 0xf9, + 0xd8, 0x54, 0x75, 0x7e, 0x6e, 0x09, 0x69, 0x72, 0x55, 0x78, 0x08, 0x0b, 0xcc, 0xfc, 0x1c, 0x87, + 0x83, 0x4d, 0xad, 0xfd, 0x8d, 0x49, 0x45, 0xab, 0x59, 0xdc, 0x33, 0x11, 0x44, 0xea, 0x16, 0x2c, + 0xc5, 0xea, 0x18, 0x27, 0x8f, 0xde, 0x7e, 0x14, 0x0b, 0xc3, 0x0c, 0x55, 0xf5, 0xba, 0x5c, 0x03, + 0x9e, 0x55, 0x36, 0xc9, 0xcb, 0x91, 0x8f, 0xe0, 0x82, 0x14, 0x23, 0x92, 0xc6, 0x72, 0x33, 0xe6, + 0x6c, 0xad, 0x8d, 0xe6, 0x17, 0xf3, 0xba, 0xfe, 0x4b, 0x81, 0xc5, 0x34, 0x84, 0x97, 0x8c, 0x4f, + 0x7e, 0x67, 0xc4, 0xf7, 0x23, 0xef, 0x8e, 0x1b, 0xd0, 0x1f, 0x25, 0x9e, 0xbb, 0xcf, 0xaa, 0xcf, + 0xc7, 0xaf, 0x49, 0x7e, 0xb2, 0x35, 0xf9, 0x7d, 0x2e, 0x12, 0x83, 0xcf, 0xa8, 0x10, 0xff, 0x0c, + 0x31, 0xb1, 0xed, 0x58, 0x81, 0xf8, 0xb5, 0x54, 0xc2, 0x31, 0xf5, 0xe1, 0x5a, 0xda, 0x65, 0xfa, + 0xfa, 0x38, 0x4e, 0x5f, 0xda, 0x70, 0xe9, 0x7f, 0x2b, 0x50, 0x95, 0x17, 0x04, 0xdd, 0x49, 0xa9, + 0x0e, 0x7f, 0x65, 0xcc, 0x04, 0xa5, 0xe2, 0x70, 0x5e, 0x8d, 0x9d, 0x9b, 0xbc, 0x1a, 0x3b, 0x3f, + 0x59, 0x35, 0xf6, 0x3d, 0xa8, 0x3e, 0xf7, 0xac, 0xc0, 0x78, 0xda, 0xc3, 0x7a, 0xcf, 0x38, 0xc5, + 0x1e, 0xb7, 0x6e, 0x99, 0x66, 0xa8, 0x22, 0x48, 0x1e, 0x11, 0x0a, 0xf5, 0xef, 0x15, 0x28, 0x8a, + 0x61, 0x8c, 0xad, 0x87, 0x5e, 0x1e, 0x10, 0x34, 0x9d, 0xd6, 0x60, 0xda, 0x86, 0xed, 0xe8, 0x3e, + 0x26, 0x27, 0xec, 0xd8, 0xea, 0xe2, 0x45, 0x4a, 0xb7, 0xed, 0x78, 0x78, 0xdf, 0xb0, 0x9d, 0x36, + 0x23, 0x42, 0x4d, 0xa8, 0x31, 0x7e, 0x94, 0x15, 0x61, 0x3a, 0xd6, 0xae, 0x57, 0x29, 0x01, 0x61, + 0x42, 0x98, 0xf9, 0xea, 0x5f, 0xe6, 0xa1, 0x1c, 0x91, 0xcc, 0x98, 0x09, 0x6c, 0xc3, 0x82, 0xc8, + 0xb9, 0xfb, 0x38, 0x98, 0xac, 0x30, 0x7a, 0x9e, 0x53, 0xb4, 0x71, 0xc0, 0xce, 0x93, 0xbb, 0x30, + 0x6f, 0x3c, 0x33, 0xac, 0x1e, 0x95, 0xfa, 0x44, 0x87, 0x51, 0x35, 0xc4, 0x0f, 0x4f, 0x24, 0x36, + 0xef, 0x89, 0xea, 0xa5, 0x81, 0xe2, 0x0e, 0x8b, 0xb3, 0x7d, 0x9f, 0xd3, 0x8d, 0x2b, 0x99, 0xf6, + 0x7c, 0x3f, 0xec, 0x8f, 0xd6, 0x6e, 0xd2, 0x72, 0x74, 0x9f, 0x7f, 0x66, 0x3a, 0xba, 0x3f, 0x82, + 0x7b, 0x9f, 0xa2, 0x12, 0x81, 0xf5, 0x8d, 0x8f, 0x1d, 0x4f, 0x8f, 0xd2, 0xcf, 0x8e, 0x11, 0x18, + 0xa5, 0x68, 0x85, 0x4c, 0xd4, 0x0f, 0xe1, 0x82, 0x86, 0x1d, 0x17, 0xdb, 0xe1, 0x3e, 0x79, 0xe4, + 0x74, 0xcf, 0x70, 0xd2, 0x5d, 0x84, 0x46, 0x1a, 0x3d, 0xb3, 0xac, 0x57, 0x5f, 0x83, 0xa2, 0xf8, + 0x5b, 0x23, 0x34, 0x0b, 0xf9, 0xc3, 0xed, 0x56, 0x6d, 0x8a, 0x3c, 0x1c, 0xed, 0xb4, 0x6a, 0x0a, + 0x2a, 0x42, 0xa1, 0xbd, 0x7d, 0xd8, 0xaa, 0xe5, 0xae, 0xf6, 0xa1, 0x16, 0xff, 0x67, 0x1f, 0xb4, + 0x0c, 0xe7, 0x5a, 0xda, 0x41, 0xab, 0xf9, 0xa0, 0x79, 0xb8, 0x77, 0xb0, 0xaf, 0xb7, 0xb4, 0xbd, + 0x27, 0xcd, 0xc3, 0xdd, 0xda, 0x14, 0x5a, 0x87, 0x4b, 0xd1, 0x86, 0x87, 0x07, 0xed, 0x43, 0xfd, + 0xf0, 0x40, 0xdf, 0x3e, 0xd8, 0x3f, 0x6c, 0xee, 0xed, 0xef, 0x6a, 0x35, 0x05, 0x5d, 0x82, 0x0b, + 0x51, 0x94, 0x7b, 0x7b, 0x3b, 0x7b, 0xda, 0xee, 0x36, 0x79, 0x6e, 0x3e, 0xaa, 0xe5, 0xae, 0x7e, + 0x00, 0x15, 0xe9, 0xaf, 0x79, 0xc8, 0x90, 0x5a, 0x07, 0x3b, 0xb5, 0x29, 0x54, 0x81, 0x52, 0x94, + 0x4f, 0x11, 0x0a, 0xfb, 0x07, 0x3b, 0xbb, 0xb5, 0x1c, 0x02, 0x98, 0x39, 0x6c, 0x6a, 0x0f, 0x76, + 0x0f, 0x6b, 0xf9, 0xab, 0x5b, 0xf1, 0x8f, 0x54, 0x30, 0x5a, 0x80, 0x4a, 0xbb, 0xb9, 0xbf, 0x73, + 0xef, 0xe0, 0x5b, 0xba, 0xb6, 0xdb, 0xdc, 0xf9, 0x76, 0x6d, 0x0a, 0x2d, 0x42, 0x4d, 0x80, 0xf6, + 0x0f, 0x0e, 0x19, 0x54, 0xb9, 0xfa, 0x49, 0xcc, 0x82, 0x61, 0xb4, 0x04, 0x0b, 0x61, 0x97, 0xfa, + 0xb6, 0xb6, 0xdb, 0x3c, 0xdc, 0x25, 0x23, 0x91, 0xc0, 0xda, 0xd1, 0xfe, 0xfe, 0xde, 0xfe, 0x83, + 0x9a, 0x42, 0xb8, 0x0e, 0xc1, 0xbb, 0xdf, 0xda, 0x23, 0xc8, 0x39, 0x19, 0xf9, 0x68, 0xff, 0xeb, + 0xfb, 0x07, 0xdf, 0xdc, 0xaf, 0xe5, 0x37, 0x7f, 0xb8, 0x10, 0xfe, 0xb1, 0x4a, 0x1b, 0x7b, 0xb4, + 0xd2, 0x67, 0x07, 0x66, 0xc5, 0x9f, 0x65, 0x49, 0xe7, 0x9c, 0xfc, 0xe7, 0x5e, 0x8d, 0x95, 0xd4, + 0x36, 0x7e, 0xdb, 0x98, 0x42, 0x4f, 0xa8, 0xf7, 0x1f, 0xf9, 0x8c, 0x72, 0x2d, 0xe6, 0x71, 0x27, + 0xbe, 0xd6, 0x6c, 0xac, 0x67, 0x60, 0x84, 0x7c, 0xbf, 0x4d, 0x5c, 0xfb, 0xe8, 0x7f, 0x08, 0xa0, + 0x75, 0xd9, 0x33, 0x4f, 0xf9, 0x7b, 0x82, 0x86, 0x9a, 0x85, 0x12, 0xb2, 0xd6, 0xa1, 0x16, 0xff, + 0x0f, 0x01, 0x24, 0x05, 0xb6, 0x47, 0xfc, 0x45, 0x41, 0xe3, 0x2b, 0xd9, 0x48, 0xd1, 0x0e, 0x12, + 0x9f, 0xc6, 0x5f, 0xce, 0xfe, 0xd8, 0x38, 0xa5, 0x83, 0x51, 0x5f, 0x24, 0x33, 0xe1, 0xc8, 0x5f, + 0xba, 0xa1, 0xd8, 0xd7, 0xe8, 0x29, 0x1f, 0xc9, 0xca, 0xc2, 0x49, 0xff, 0x40, 0x52, 0x9d, 0x42, + 0xff, 0x0f, 0xe6, 0x63, 0xc5, 0x1a, 0x48, 0x22, 0x4c, 0xaf, 0x41, 0x69, 0x5c, 0xce, 0xc4, 0x91, + 0x57, 0x35, 0x5a, 0x90, 0x11, 0x5f, 0xd5, 0x94, 0x42, 0x8f, 0xf8, 0xaa, 0xa6, 0xd6, 0x73, 0x50, + 0x45, 0x94, 0x8a, 0x2f, 0x64, 0x45, 0x4c, 0x2b, 0xf6, 0x68, 0xac, 0x67, 0x60, 0x44, 0x05, 0x12, + 0x2b, 0xbf, 0x90, 0x05, 0x92, 0x5e, 0xd8, 0xd1, 0xb8, 0x9c, 0x89, 0x13, 0x5f, 0xc9, 0x61, 0xda, + 0x37, 0xb9, 0x92, 0x89, 0xd2, 0x83, 0xe4, 0x4a, 0x26, 0xb3, 0xc6, 0x7c, 0x25, 0x63, 0x89, 0x5a, + 0x35, 0x33, 0x05, 0x95, 0xb6, 0x92, 0xe9, 0x69, 0x2a, 0x75, 0x0a, 0x3d, 0x87, 0xfa, 0xa8, 0xe4, + 0x07, 0xba, 0x76, 0x86, 0x1c, 0x4d, 0xe3, 0xcd, 0xc9, 0x90, 0xc3, 0x8e, 0x31, 0xa0, 0xe4, 0x31, + 0x83, 0x5e, 0x95, 0xc5, 0x3d, 0xe2, 0x18, 0x6b, 0xbc, 0x36, 0x0e, 0x2d, 0xec, 0xe6, 0x01, 0x14, + 0x45, 0x5a, 0x05, 0x49, 0x26, 0x30, 0x96, 0xce, 0x69, 0x5c, 0x4c, 0x6f, 0x0c, 0x19, 0x7d, 0x0d, + 0x0a, 0x04, 0x8a, 0x96, 0xe3, 0x78, 0x82, 0x41, 0x3d, 0xd9, 0x10, 0x12, 0x37, 0x61, 0x86, 0xe5, + 0x0b, 0x90, 0x14, 0xc8, 0x90, 0xf2, 0x19, 0x8d, 0x46, 0x5a, 0x53, 0xc8, 0xa2, 0xc5, 0xfe, 0x7a, + 0x90, 0x87, 0xff, 0xd1, 0x6a, 0xfc, 0xdf, 0x83, 0xe4, 0x3c, 0x43, 0xe3, 0x95, 0x91, 0xed, 0x51, + 0x9d, 0x8d, 0xb9, 0xde, 0xeb, 0x19, 0xf7, 0xa4, 0x34, 0x9d, 0x4d, 0xbf, 0x7d, 0xb1, 0xc5, 0x4d, + 0xde, 0xce, 0xe4, 0xc5, 0x1d, 0x79, 0x03, 0x96, 0x17, 0x77, 0xf4, 0x25, 0x8f, 0x6d, 0x8d, 0xf8, + 0xa7, 0x98, 0x6a, 0xd6, 0xe7, 0xc0, 0x69, 0x5b, 0x63, 0xc4, 0x67, 0xc6, 0xea, 0x14, 0x3a, 0x81, + 0x73, 0x29, 0xdf, 0x21, 0xa3, 0xd7, 0x46, 0xdb, 0x5f, 0xa9, 0x97, 0xd7, 0xc7, 0xe2, 0x45, 0x7b, + 0x4a, 0x89, 0x05, 0xca, 0x3d, 0x8d, 0x0e, 0x46, 0xca, 0x3d, 0x65, 0x05, 0x15, 0xa9, 0x22, 0x72, + 0x1b, 0x72, 0x21, 0x2d, 0x40, 0x96, 0xa2, 0x88, 0x71, 0x8b, 0xb1, 0xf9, 0x17, 0x79, 0x98, 0x63, + 0x31, 0x5c, 0xee, 0x80, 0x3c, 0x06, 0x18, 0xa6, 0x43, 0xd0, 0xa5, 0xf8, 0xb4, 0xa5, 0x5c, 0x52, + 0x63, 0x75, 0x54, 0x73, 0x54, 0xd1, 0x23, 0x69, 0x06, 0x59, 0xd1, 0x93, 0x59, 0x13, 0x59, 0xd1, + 0x53, 0xf2, 0x13, 0xea, 0x14, 0xfa, 0x08, 0x4a, 0x61, 0x54, 0x1b, 0xc9, 0xf1, 0xf0, 0x58, 0x78, + 0xbe, 0x71, 0x69, 0x44, 0x6b, 0x74, 0x74, 0x91, 0x60, 0xb5, 0x3c, 0xba, 0x64, 0x20, 0x5c, 0x1e, + 0x5d, 0x5a, 0x94, 0x7b, 0x38, 0x5f, 0x16, 0xf6, 0x4a, 0x99, 0xaf, 0x14, 0x5d, 0x4c, 0x99, 0xaf, + 0x1c, 0x2f, 0x53, 0xa7, 0xee, 0xad, 0xfd, 0xf2, 0x77, 0xab, 0xca, 0x6f, 0x7e, 0xb7, 0x3a, 0xf5, + 0xc3, 0x4f, 0x57, 0x95, 0x5f, 0x7e, 0xba, 0xaa, 0xfc, 0xfa, 0xd3, 0x55, 0xe5, 0xb7, 0x9f, 0xae, + 0x2a, 0x7f, 0xf6, 0x9f, 0xab, 0x53, 0xdf, 0xc9, 0x3d, 0x7b, 0xe7, 0xe9, 0x0c, 0xfd, 0x43, 0xd2, + 0x77, 0xff, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xf4, 0x4c, 0x5c, 0x4a, 0x56, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -7655,6 +8483,11 @@ type RuntimeServiceClient interface { ContainerStats(ctx context.Context, in *ContainerStatsRequest, opts ...grpc.CallOption) (*ContainerStatsResponse, error) // ListContainerStats returns stats of all running containers. ListContainerStats(ctx context.Context, in *ListContainerStatsRequest, opts ...grpc.CallOption) (*ListContainerStatsResponse, error) + // PodSandboxStats returns stats of the pod. If the pod sandbox does not + // exist, the call returns an error. + PodSandboxStats(ctx context.Context, in *PodSandboxStatsRequest, opts ...grpc.CallOption) (*PodSandboxStatsResponse, error) + // ListPodSandboxStats returns stats of the pods matching a filter. + ListPodSandboxStats(ctx context.Context, in *ListPodSandboxStatsRequest, opts ...grpc.CallOption) (*ListPodSandboxStatsResponse, error) // UpdateRuntimeConfig updates the runtime configuration based on the given request. UpdateRuntimeConfig(ctx context.Context, in *UpdateRuntimeConfigRequest, opts ...grpc.CallOption) (*UpdateRuntimeConfigResponse, error) // Status returns the status of the runtime. @@ -7849,6 +8682,24 @@ func (c *runtimeServiceClient) ListContainerStats(ctx context.Context, in *ListC return out, nil } +func (c *runtimeServiceClient) PodSandboxStats(ctx context.Context, in *PodSandboxStatsRequest, opts ...grpc.CallOption) (*PodSandboxStatsResponse, error) { + out := new(PodSandboxStatsResponse) + err := c.cc.Invoke(ctx, "/runtime.v1.RuntimeService/PodSandboxStats", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *runtimeServiceClient) ListPodSandboxStats(ctx context.Context, in *ListPodSandboxStatsRequest, opts ...grpc.CallOption) (*ListPodSandboxStatsResponse, error) { + out := new(ListPodSandboxStatsResponse) + err := c.cc.Invoke(ctx, "/runtime.v1.RuntimeService/ListPodSandboxStats", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *runtimeServiceClient) UpdateRuntimeConfig(ctx context.Context, in *UpdateRuntimeConfigRequest, opts ...grpc.CallOption) (*UpdateRuntimeConfigResponse, error) { out := new(UpdateRuntimeConfigResponse) err := c.cc.Invoke(ctx, "/runtime.v1.RuntimeService/UpdateRuntimeConfig", in, out, opts...) @@ -7935,6 +8786,11 @@ type RuntimeServiceServer interface { ContainerStats(context.Context, *ContainerStatsRequest) (*ContainerStatsResponse, error) // ListContainerStats returns stats of all running containers. ListContainerStats(context.Context, *ListContainerStatsRequest) (*ListContainerStatsResponse, error) + // PodSandboxStats returns stats of the pod. If the pod sandbox does not + // exist, the call returns an error. + PodSandboxStats(context.Context, *PodSandboxStatsRequest) (*PodSandboxStatsResponse, error) + // ListPodSandboxStats returns stats of the pods matching a filter. + ListPodSandboxStats(context.Context, *ListPodSandboxStatsRequest) (*ListPodSandboxStatsResponse, error) // UpdateRuntimeConfig updates the runtime configuration based on the given request. UpdateRuntimeConfig(context.Context, *UpdateRuntimeConfigRequest) (*UpdateRuntimeConfigResponse, error) // Status returns the status of the runtime. @@ -8005,6 +8861,12 @@ func (*UnimplementedRuntimeServiceServer) ContainerStats(ctx context.Context, re func (*UnimplementedRuntimeServiceServer) ListContainerStats(ctx context.Context, req *ListContainerStatsRequest) (*ListContainerStatsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListContainerStats not implemented") } +func (*UnimplementedRuntimeServiceServer) PodSandboxStats(ctx context.Context, req *PodSandboxStatsRequest) (*PodSandboxStatsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PodSandboxStats not implemented") +} +func (*UnimplementedRuntimeServiceServer) ListPodSandboxStats(ctx context.Context, req *ListPodSandboxStatsRequest) (*ListPodSandboxStatsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListPodSandboxStats not implemented") +} func (*UnimplementedRuntimeServiceServer) UpdateRuntimeConfig(ctx context.Context, req *UpdateRuntimeConfigRequest) (*UpdateRuntimeConfigResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method UpdateRuntimeConfig not implemented") } @@ -8376,6 +9238,42 @@ func _RuntimeService_ListContainerStats_Handler(srv interface{}, ctx context.Con return interceptor(ctx, in, info, handler) } +func _RuntimeService_PodSandboxStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PodSandboxStatsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RuntimeServiceServer).PodSandboxStats(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/runtime.v1.RuntimeService/PodSandboxStats", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RuntimeServiceServer).PodSandboxStats(ctx, req.(*PodSandboxStatsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _RuntimeService_ListPodSandboxStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListPodSandboxStatsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RuntimeServiceServer).ListPodSandboxStats(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/runtime.v1.RuntimeService/ListPodSandboxStats", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RuntimeServiceServer).ListPodSandboxStats(ctx, req.(*ListPodSandboxStatsRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _RuntimeService_UpdateRuntimeConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(UpdateRuntimeConfigRequest) if err := dec(in); err != nil { @@ -8496,6 +9394,14 @@ var _RuntimeService_serviceDesc = grpc.ServiceDesc{ MethodName: "ListContainerStats", Handler: _RuntimeService_ListContainerStats_Handler, }, + { + MethodName: "PodSandboxStats", + Handler: _RuntimeService_PodSandboxStats_Handler, + }, + { + MethodName: "ListPodSandboxStats", + Handler: _RuntimeService_ListPodSandboxStats_Handler, + }, { MethodName: "UpdateRuntimeConfig", Handler: _RuntimeService_UpdateRuntimeConfig_Handler, @@ -9250,6 +10156,30 @@ func (m *LinuxPodSandboxConfig) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Resources != nil { + { + size, err := m.Resources.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + if m.Overhead != nil { + { + size, err := m.Overhead.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } if len(m.Sysctls) > 0 { for k := range m.Sysctls { v := m.Sysctls[k] @@ -10272,6 +11202,611 @@ func (m *ListPodSandboxResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) return len(dAtA) - i, nil } +func (m *PodSandboxStatsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PodSandboxStatsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PodSandboxStatsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.PodSandboxId) > 0 { + i -= len(m.PodSandboxId) + copy(dAtA[i:], m.PodSandboxId) + i = encodeVarintApi(dAtA, i, uint64(len(m.PodSandboxId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *PodSandboxStatsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PodSandboxStatsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PodSandboxStatsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Stats != nil { + { + size, err := m.Stats.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *PodSandboxStatsFilter) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PodSandboxStatsFilter) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PodSandboxStatsFilter) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.LabelSelector) > 0 { + for k := range m.LabelSelector { + v := m.LabelSelector[k] + baseI := i + i -= len(v) + copy(dAtA[i:], v) + i = encodeVarintApi(dAtA, i, uint64(len(v))) + i-- + dAtA[i] = 0x12 + i -= len(k) + copy(dAtA[i:], k) + i = encodeVarintApi(dAtA, i, uint64(len(k))) + i-- + dAtA[i] = 0xa + i = encodeVarintApi(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0x12 + } + } + if len(m.Id) > 0 { + i -= len(m.Id) + copy(dAtA[i:], m.Id) + i = encodeVarintApi(dAtA, i, uint64(len(m.Id))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ListPodSandboxStatsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ListPodSandboxStatsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ListPodSandboxStatsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Filter != nil { + { + size, err := m.Filter.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ListPodSandboxStatsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ListPodSandboxStatsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ListPodSandboxStatsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Stats) > 0 { + for iNdEx := len(m.Stats) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Stats[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *PodSandboxAttributes) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PodSandboxAttributes) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PodSandboxAttributes) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Annotations) > 0 { + for k := range m.Annotations { + v := m.Annotations[k] + baseI := i + i -= len(v) + copy(dAtA[i:], v) + i = encodeVarintApi(dAtA, i, uint64(len(v))) + i-- + dAtA[i] = 0x12 + i -= len(k) + copy(dAtA[i:], k) + i = encodeVarintApi(dAtA, i, uint64(len(k))) + i-- + dAtA[i] = 0xa + i = encodeVarintApi(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0x22 + } + } + if len(m.Labels) > 0 { + for k := range m.Labels { + v := m.Labels[k] + baseI := i + i -= len(v) + copy(dAtA[i:], v) + i = encodeVarintApi(dAtA, i, uint64(len(v))) + i-- + dAtA[i] = 0x12 + i -= len(k) + copy(dAtA[i:], k) + i = encodeVarintApi(dAtA, i, uint64(len(k))) + i-- + dAtA[i] = 0xa + i = encodeVarintApi(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0x1a + } + } + if m.Metadata != nil { + { + size, err := m.Metadata.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Id) > 0 { + i -= len(m.Id) + copy(dAtA[i:], m.Id) + i = encodeVarintApi(dAtA, i, uint64(len(m.Id))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *PodSandboxStats) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PodSandboxStats) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PodSandboxStats) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Windows != nil { + { + size, err := m.Windows.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if m.Linux != nil { + { + size, err := m.Linux.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Attributes != nil { + { + size, err := m.Attributes.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *LinuxPodSandboxStats) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *LinuxPodSandboxStats) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *LinuxPodSandboxStats) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Containers) > 0 { + for iNdEx := len(m.Containers) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Containers[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + } + if m.Process != nil { + { + size, err := m.Process.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + if m.Network != nil { + { + size, err := m.Network.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if m.Memory != nil { + { + size, err := m.Memory.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Cpu != nil { + { + size, err := m.Cpu.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *WindowsPodSandboxStats) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *WindowsPodSandboxStats) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *WindowsPodSandboxStats) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *NetworkUsage) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *NetworkUsage) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *NetworkUsage) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Interfaces) > 0 { + for iNdEx := len(m.Interfaces) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Interfaces[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if m.DefaultInterface != nil { + { + size, err := m.DefaultInterface.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Timestamp != 0 { + i = encodeVarintApi(dAtA, i, uint64(m.Timestamp)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *NetworkInterfaceUsage) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *NetworkInterfaceUsage) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *NetworkInterfaceUsage) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.TxErrors != nil { + { + size, err := m.TxErrors.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + if m.TxBytes != nil { + { + size, err := m.TxBytes.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + if m.RxErrors != nil { + { + size, err := m.RxErrors.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if m.RxBytes != nil { + { + size, err := m.RxBytes.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintApi(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ProcessUsage) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ProcessUsage) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ProcessUsage) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ProcessCount != nil { + { + size, err := m.ProcessCount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Timestamp != 0 { + i = encodeVarintApi(dAtA, i, uint64(m.Timestamp)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func (m *ImageSpec) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -10686,21 +12221,21 @@ func (m *LinuxContainerSecurityContext) MarshalToSizedBuffer(dAtA []byte) (int, dAtA[i] = 0x4a } if len(m.SupplementalGroups) > 0 { - dAtA28 := make([]byte, len(m.SupplementalGroups)*10) - var j27 int + dAtA46 := make([]byte, len(m.SupplementalGroups)*10) + var j45 int for _, num1 := range m.SupplementalGroups { num := uint64(num1) for num >= 1<<7 { - dAtA28[j27] = uint8(uint64(num)&0x7f | 0x80) + dAtA46[j45] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j27++ + j45++ } - dAtA28[j27] = uint8(num) - j27++ + dAtA46[j45] = uint8(num) + j45++ } - i -= j27 - copy(dAtA[i:], dAtA28[:j27]) - i = encodeVarintApi(dAtA, i, uint64(j27)) + i -= j45 + copy(dAtA[i:], dAtA46[:j45]) + i = encodeVarintApi(dAtA, i, uint64(j45)) i-- dAtA[i] = 0x42 } @@ -12539,21 +14074,21 @@ func (m *PortForwardRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { var l int _ = l if len(m.Port) > 0 { - dAtA54 := make([]byte, len(m.Port)*10) - var j53 int + dAtA72 := make([]byte, len(m.Port)*10) + var j71 int for _, num1 := range m.Port { num := uint64(num1) for num >= 1<<7 { - dAtA54[j53] = uint8(uint64(num)&0x7f | 0x80) + dAtA72[j71] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j53++ + j71++ } - dAtA54[j53] = uint8(num) - j53++ + dAtA72[j71] = uint8(num) + j71++ } - i -= j53 - copy(dAtA[i:], dAtA54[:j53]) - i = encodeVarintApi(dAtA, i, uint64(j53)) + i -= j71 + copy(dAtA[i:], dAtA72[:j71]) + i = encodeVarintApi(dAtA, i, uint64(j71)) i-- dAtA[i] = 0x12 } @@ -13946,6 +15481,18 @@ func (m *CpuUsage) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.UsageNanoCores != nil { + { + size, err := m.UsageNanoCores.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } if m.UsageCoreNanoSeconds != nil { { size, err := m.UsageCoreNanoSeconds.MarshalToSizedBuffer(dAtA[:i]) @@ -13986,6 +15533,66 @@ func (m *MemoryUsage) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.MajorPageFaults != nil { + { + size, err := m.MajorPageFaults.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + if m.PageFaults != nil { + { + size, err := m.PageFaults.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + if m.RssBytes != nil { + { + size, err := m.RssBytes.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + if m.UsageBytes != nil { + { + size, err := m.UsageBytes.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + if m.AvailableBytes != nil { + { + size, err := m.AvailableBytes.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } if m.WorkingSetBytes != nil { { size, err := m.WorkingSetBytes.MarshalToSizedBuffer(dAtA[:i]) @@ -14305,6 +15912,14 @@ func (m *LinuxPodSandboxConfig) Size() (n int) { n += mapEntrySize + 1 + sovApi(uint64(mapEntrySize)) } } + if m.Overhead != nil { + l = m.Overhead.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.Resources != nil { + l = m.Resources.Size() + n += 1 + l + sovApi(uint64(l)) + } return n } @@ -14715,6 +16330,242 @@ func (m *ListPodSandboxResponse) Size() (n int) { return n } +func (m *PodSandboxStatsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.PodSandboxId) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func (m *PodSandboxStatsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Stats != nil { + l = m.Stats.Size() + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func (m *PodSandboxStatsFilter) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Id) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + if len(m.LabelSelector) > 0 { + for k, v := range m.LabelSelector { + _ = k + _ = v + mapEntrySize := 1 + len(k) + sovApi(uint64(len(k))) + 1 + len(v) + sovApi(uint64(len(v))) + n += mapEntrySize + 1 + sovApi(uint64(mapEntrySize)) + } + } + return n +} + +func (m *ListPodSandboxStatsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Filter != nil { + l = m.Filter.Size() + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func (m *ListPodSandboxStatsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Stats) > 0 { + for _, e := range m.Stats { + l = e.Size() + n += 1 + l + sovApi(uint64(l)) + } + } + return n +} + +func (m *PodSandboxAttributes) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Id) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + if m.Metadata != nil { + l = m.Metadata.Size() + n += 1 + l + sovApi(uint64(l)) + } + if len(m.Labels) > 0 { + for k, v := range m.Labels { + _ = k + _ = v + mapEntrySize := 1 + len(k) + sovApi(uint64(len(k))) + 1 + len(v) + sovApi(uint64(len(v))) + n += mapEntrySize + 1 + sovApi(uint64(mapEntrySize)) + } + } + if len(m.Annotations) > 0 { + for k, v := range m.Annotations { + _ = k + _ = v + mapEntrySize := 1 + len(k) + sovApi(uint64(len(k))) + 1 + len(v) + sovApi(uint64(len(v))) + n += mapEntrySize + 1 + sovApi(uint64(mapEntrySize)) + } + } + return n +} + +func (m *PodSandboxStats) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Attributes != nil { + l = m.Attributes.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.Linux != nil { + l = m.Linux.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.Windows != nil { + l = m.Windows.Size() + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func (m *LinuxPodSandboxStats) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Cpu != nil { + l = m.Cpu.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.Memory != nil { + l = m.Memory.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.Network != nil { + l = m.Network.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.Process != nil { + l = m.Process.Size() + n += 1 + l + sovApi(uint64(l)) + } + if len(m.Containers) > 0 { + for _, e := range m.Containers { + l = e.Size() + n += 1 + l + sovApi(uint64(l)) + } + } + return n +} + +func (m *WindowsPodSandboxStats) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *NetworkUsage) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Timestamp != 0 { + n += 1 + sovApi(uint64(m.Timestamp)) + } + if m.DefaultInterface != nil { + l = m.DefaultInterface.Size() + n += 1 + l + sovApi(uint64(l)) + } + if len(m.Interfaces) > 0 { + for _, e := range m.Interfaces { + l = e.Size() + n += 1 + l + sovApi(uint64(l)) + } + } + return n +} + +func (m *NetworkInterfaceUsage) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Name) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + if m.RxBytes != nil { + l = m.RxBytes.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.RxErrors != nil { + l = m.RxErrors.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.TxBytes != nil { + l = m.TxBytes.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.TxErrors != nil { + l = m.TxErrors.Size() + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func (m *ProcessUsage) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Timestamp != 0 { + n += 1 + sovApi(uint64(m.Timestamp)) + } + if m.ProcessCount != nil { + l = m.ProcessCount.Size() + n += 1 + l + sovApi(uint64(l)) + } + return n +} + func (m *ImageSpec) Size() (n int) { if m == nil { return 0 @@ -16253,6 +18104,10 @@ func (m *CpuUsage) Size() (n int) { l = m.UsageCoreNanoSeconds.Size() n += 1 + l + sovApi(uint64(l)) } + if m.UsageNanoCores != nil { + l = m.UsageNanoCores.Size() + n += 1 + l + sovApi(uint64(l)) + } return n } @@ -16269,6 +18124,26 @@ func (m *MemoryUsage) Size() (n int) { l = m.WorkingSetBytes.Size() n += 1 + l + sovApi(uint64(l)) } + if m.AvailableBytes != nil { + l = m.AvailableBytes.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.UsageBytes != nil { + l = m.UsageBytes.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.RssBytes != nil { + l = m.RssBytes.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.PageFaults != nil { + l = m.PageFaults.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.MajorPageFaults != nil { + l = m.MajorPageFaults.Size() + n += 1 + l + sovApi(uint64(l)) + } return n } @@ -16433,6 +18308,8 @@ func (this *LinuxPodSandboxConfig) String() string { `CgroupParent:` + fmt.Sprintf("%v", this.CgroupParent) + `,`, `SecurityContext:` + strings.Replace(this.SecurityContext.String(), "LinuxSandboxSecurityContext", "LinuxSandboxSecurityContext", 1) + `,`, `Sysctls:` + mapStringForSysctls + `,`, + `Overhead:` + strings.Replace(this.Overhead.String(), "LinuxContainerResources", "LinuxContainerResources", 1) + `,`, + `Resources:` + strings.Replace(this.Resources.String(), "LinuxContainerResources", "LinuxContainerResources", 1) + `,`, `}`, }, "") return s @@ -16761,6 +18638,187 @@ func (this *ListPodSandboxResponse) String() string { }, "") return s } +func (this *PodSandboxStatsRequest) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PodSandboxStatsRequest{`, + `PodSandboxId:` + fmt.Sprintf("%v", this.PodSandboxId) + `,`, + `}`, + }, "") + return s +} +func (this *PodSandboxStatsResponse) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PodSandboxStatsResponse{`, + `Stats:` + strings.Replace(this.Stats.String(), "PodSandboxStats", "PodSandboxStats", 1) + `,`, + `}`, + }, "") + return s +} +func (this *PodSandboxStatsFilter) String() string { + if this == nil { + return "nil" + } + keysForLabelSelector := make([]string, 0, len(this.LabelSelector)) + for k := range this.LabelSelector { + keysForLabelSelector = append(keysForLabelSelector, k) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForLabelSelector) + mapStringForLabelSelector := "map[string]string{" + for _, k := range keysForLabelSelector { + mapStringForLabelSelector += fmt.Sprintf("%v: %v,", k, this.LabelSelector[k]) + } + mapStringForLabelSelector += "}" + s := strings.Join([]string{`&PodSandboxStatsFilter{`, + `Id:` + fmt.Sprintf("%v", this.Id) + `,`, + `LabelSelector:` + mapStringForLabelSelector + `,`, + `}`, + }, "") + return s +} +func (this *ListPodSandboxStatsRequest) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ListPodSandboxStatsRequest{`, + `Filter:` + strings.Replace(this.Filter.String(), "PodSandboxStatsFilter", "PodSandboxStatsFilter", 1) + `,`, + `}`, + }, "") + return s +} +func (this *ListPodSandboxStatsResponse) String() string { + if this == nil { + return "nil" + } + repeatedStringForStats := "[]*PodSandboxStats{" + for _, f := range this.Stats { + repeatedStringForStats += strings.Replace(f.String(), "PodSandboxStats", "PodSandboxStats", 1) + "," + } + repeatedStringForStats += "}" + s := strings.Join([]string{`&ListPodSandboxStatsResponse{`, + `Stats:` + repeatedStringForStats + `,`, + `}`, + }, "") + return s +} +func (this *PodSandboxAttributes) String() string { + if this == nil { + return "nil" + } + keysForLabels := make([]string, 0, len(this.Labels)) + for k := range this.Labels { + keysForLabels = append(keysForLabels, k) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) + mapStringForLabels := "map[string]string{" + for _, k := range keysForLabels { + mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) + } + mapStringForLabels += "}" + keysForAnnotations := make([]string, 0, len(this.Annotations)) + for k := range this.Annotations { + keysForAnnotations = append(keysForAnnotations, k) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForAnnotations) + mapStringForAnnotations := "map[string]string{" + for _, k := range keysForAnnotations { + mapStringForAnnotations += fmt.Sprintf("%v: %v,", k, this.Annotations[k]) + } + mapStringForAnnotations += "}" + s := strings.Join([]string{`&PodSandboxAttributes{`, + `Id:` + fmt.Sprintf("%v", this.Id) + `,`, + `Metadata:` + strings.Replace(this.Metadata.String(), "PodSandboxMetadata", "PodSandboxMetadata", 1) + `,`, + `Labels:` + mapStringForLabels + `,`, + `Annotations:` + mapStringForAnnotations + `,`, + `}`, + }, "") + return s +} +func (this *PodSandboxStats) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PodSandboxStats{`, + `Attributes:` + strings.Replace(this.Attributes.String(), "PodSandboxAttributes", "PodSandboxAttributes", 1) + `,`, + `Linux:` + strings.Replace(this.Linux.String(), "LinuxPodSandboxStats", "LinuxPodSandboxStats", 1) + `,`, + `Windows:` + strings.Replace(this.Windows.String(), "WindowsPodSandboxStats", "WindowsPodSandboxStats", 1) + `,`, + `}`, + }, "") + return s +} +func (this *LinuxPodSandboxStats) String() string { + if this == nil { + return "nil" + } + repeatedStringForContainers := "[]*ContainerStats{" + for _, f := range this.Containers { + repeatedStringForContainers += strings.Replace(f.String(), "ContainerStats", "ContainerStats", 1) + "," + } + repeatedStringForContainers += "}" + s := strings.Join([]string{`&LinuxPodSandboxStats{`, + `Cpu:` + strings.Replace(this.Cpu.String(), "CpuUsage", "CpuUsage", 1) + `,`, + `Memory:` + strings.Replace(this.Memory.String(), "MemoryUsage", "MemoryUsage", 1) + `,`, + `Network:` + strings.Replace(this.Network.String(), "NetworkUsage", "NetworkUsage", 1) + `,`, + `Process:` + strings.Replace(this.Process.String(), "ProcessUsage", "ProcessUsage", 1) + `,`, + `Containers:` + repeatedStringForContainers + `,`, + `}`, + }, "") + return s +} +func (this *WindowsPodSandboxStats) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&WindowsPodSandboxStats{`, + `}`, + }, "") + return s +} +func (this *NetworkUsage) String() string { + if this == nil { + return "nil" + } + repeatedStringForInterfaces := "[]*NetworkInterfaceUsage{" + for _, f := range this.Interfaces { + repeatedStringForInterfaces += strings.Replace(f.String(), "NetworkInterfaceUsage", "NetworkInterfaceUsage", 1) + "," + } + repeatedStringForInterfaces += "}" + s := strings.Join([]string{`&NetworkUsage{`, + `Timestamp:` + fmt.Sprintf("%v", this.Timestamp) + `,`, + `DefaultInterface:` + strings.Replace(this.DefaultInterface.String(), "NetworkInterfaceUsage", "NetworkInterfaceUsage", 1) + `,`, + `Interfaces:` + repeatedStringForInterfaces + `,`, + `}`, + }, "") + return s +} +func (this *NetworkInterfaceUsage) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&NetworkInterfaceUsage{`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `RxBytes:` + strings.Replace(this.RxBytes.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `RxErrors:` + strings.Replace(this.RxErrors.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `TxBytes:` + strings.Replace(this.TxBytes.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `TxErrors:` + strings.Replace(this.TxErrors.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `}`, + }, "") + return s +} +func (this *ProcessUsage) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ProcessUsage{`, + `Timestamp:` + fmt.Sprintf("%v", this.Timestamp) + `,`, + `ProcessCount:` + strings.Replace(this.ProcessCount.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `}`, + }, "") + return s +} func (this *ImageSpec) String() string { if this == nil { return "nil" @@ -17836,6 +19894,7 @@ func (this *CpuUsage) String() string { s := strings.Join([]string{`&CpuUsage{`, `Timestamp:` + fmt.Sprintf("%v", this.Timestamp) + `,`, `UsageCoreNanoSeconds:` + strings.Replace(this.UsageCoreNanoSeconds.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `UsageNanoCores:` + strings.Replace(this.UsageNanoCores.String(), "UInt64Value", "UInt64Value", 1) + `,`, `}`, }, "") return s @@ -17847,6 +19906,11 @@ func (this *MemoryUsage) String() string { s := strings.Join([]string{`&MemoryUsage{`, `Timestamp:` + fmt.Sprintf("%v", this.Timestamp) + `,`, `WorkingSetBytes:` + strings.Replace(this.WorkingSetBytes.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `AvailableBytes:` + strings.Replace(this.AvailableBytes.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `UsageBytes:` + strings.Replace(this.UsageBytes.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `RssBytes:` + strings.Replace(this.RssBytes.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `PageFaults:` + strings.Replace(this.PageFaults.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `MajorPageFaults:` + strings.Replace(this.MajorPageFaults.String(), "UInt64Value", "UInt64Value", 1) + `,`, `}`, }, "") return s @@ -19543,6 +21607,78 @@ func (m *LinuxPodSandboxConfig) Unmarshal(dAtA []byte) error { } m.Sysctls[mapkey] = mapvalue iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Overhead", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Overhead == nil { + m.Overhead = &LinuxContainerResources{} + } + if err := m.Overhead.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Resources", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Resources == nil { + m.Resources = &LinuxContainerResources{} + } + if err := m.Resources.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipApi(dAtA[iNdEx:]) @@ -22864,6 +25000,1831 @@ func (m *ListPodSandboxResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *PodSandboxStatsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PodSandboxStatsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PodSandboxStatsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PodSandboxId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PodSandboxId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PodSandboxStatsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PodSandboxStatsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PodSandboxStatsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Stats", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Stats == nil { + m.Stats = &PodSandboxStats{} + } + if err := m.Stats.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PodSandboxStatsFilter) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PodSandboxStatsFilter: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PodSandboxStatsFilter: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Id = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LabelSelector", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.LabelSelector == nil { + m.LabelSelector = make(map[string]string) + } + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthApi + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return ErrInvalidLengthApi + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthApi + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue < 0 { + return ErrInvalidLengthApi + } + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.LabelSelector[mapkey] = mapvalue + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ListPodSandboxStatsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ListPodSandboxStatsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ListPodSandboxStatsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Filter", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Filter == nil { + m.Filter = &PodSandboxStatsFilter{} + } + if err := m.Filter.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ListPodSandboxStatsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ListPodSandboxStatsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ListPodSandboxStatsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Stats", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Stats = append(m.Stats, &PodSandboxStats{}) + if err := m.Stats[len(m.Stats)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PodSandboxAttributes) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PodSandboxAttributes: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PodSandboxAttributes: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Id = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Metadata == nil { + m.Metadata = &PodSandboxMetadata{} + } + if err := m.Metadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Labels", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Labels == nil { + m.Labels = make(map[string]string) + } + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthApi + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return ErrInvalidLengthApi + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthApi + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue < 0 { + return ErrInvalidLengthApi + } + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.Labels[mapkey] = mapvalue + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Annotations", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Annotations == nil { + m.Annotations = make(map[string]string) + } + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthApi + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return ErrInvalidLengthApi + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthApi + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue < 0 { + return ErrInvalidLengthApi + } + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.Annotations[mapkey] = mapvalue + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PodSandboxStats) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PodSandboxStats: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PodSandboxStats: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Attributes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Attributes == nil { + m.Attributes = &PodSandboxAttributes{} + } + if err := m.Attributes.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Linux", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Linux == nil { + m.Linux = &LinuxPodSandboxStats{} + } + if err := m.Linux.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Windows", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Windows == nil { + m.Windows = &WindowsPodSandboxStats{} + } + if err := m.Windows.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *LinuxPodSandboxStats) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: LinuxPodSandboxStats: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LinuxPodSandboxStats: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Cpu", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Cpu == nil { + m.Cpu = &CpuUsage{} + } + if err := m.Cpu.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Memory", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Memory == nil { + m.Memory = &MemoryUsage{} + } + if err := m.Memory.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Network", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Network == nil { + m.Network = &NetworkUsage{} + } + if err := m.Network.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Process", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Process == nil { + m.Process = &ProcessUsage{} + } + if err := m.Process.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Containers", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Containers = append(m.Containers, &ContainerStats{}) + if err := m.Containers[len(m.Containers)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *WindowsPodSandboxStats) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: WindowsPodSandboxStats: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: WindowsPodSandboxStats: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *NetworkUsage) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: NetworkUsage: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: NetworkUsage: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + m.Timestamp = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Timestamp |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DefaultInterface", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.DefaultInterface == nil { + m.DefaultInterface = &NetworkInterfaceUsage{} + } + if err := m.DefaultInterface.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Interfaces", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Interfaces = append(m.Interfaces, &NetworkInterfaceUsage{}) + if err := m.Interfaces[len(m.Interfaces)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *NetworkInterfaceUsage) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: NetworkInterfaceUsage: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: NetworkInterfaceUsage: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RxBytes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.RxBytes == nil { + m.RxBytes = &UInt64Value{} + } + if err := m.RxBytes.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RxErrors", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.RxErrors == nil { + m.RxErrors = &UInt64Value{} + } + if err := m.RxErrors.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TxBytes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.TxBytes == nil { + m.TxBytes = &UInt64Value{} + } + if err := m.TxBytes.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TxErrors", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.TxErrors == nil { + m.TxErrors = &UInt64Value{} + } + if err := m.TxErrors.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ProcessUsage) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ProcessUsage: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ProcessUsage: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + m.Timestamp = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Timestamp |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProcessCount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ProcessCount == nil { + m.ProcessCount = &UInt64Value{} + } + if err := m.ProcessCount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *ImageSpec) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -34284,6 +38245,42 @@ func (m *CpuUsage) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UsageNanoCores", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.UsageNanoCores == nil { + m.UsageNanoCores = &UInt64Value{} + } + if err := m.UsageNanoCores.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipApi(dAtA[iNdEx:]) @@ -34389,6 +38386,186 @@ func (m *MemoryUsage) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AvailableBytes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.AvailableBytes == nil { + m.AvailableBytes = &UInt64Value{} + } + if err := m.AvailableBytes.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UsageBytes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.UsageBytes == nil { + m.UsageBytes = &UInt64Value{} + } + if err := m.UsageBytes.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RssBytes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.RssBytes == nil { + m.RssBytes = &UInt64Value{} + } + if err := m.RssBytes.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PageFaults", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.PageFaults == nil { + m.PageFaults = &UInt64Value{} + } + if err := m.PageFaults.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MajorPageFaults", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.MajorPageFaults == nil { + m.MajorPageFaults = &UInt64Value{} + } + if err := m.MajorPageFaults.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipApi(dAtA[iNdEx:]) diff --git a/vendor/k8s.io/cri-api/pkg/apis/runtime/v1/api.proto b/vendor/k8s.io/cri-api/pkg/apis/runtime/v1/api.proto index 655600392..673f64ffb 100644 --- a/vendor/k8s.io/cri-api/pkg/apis/runtime/v1/api.proto +++ b/vendor/k8s.io/cri-api/pkg/apis/runtime/v1/api.proto @@ -103,6 +103,12 @@ service RuntimeService { // ListContainerStats returns stats of all running containers. rpc ListContainerStats(ListContainerStatsRequest) returns (ListContainerStatsResponse) {} + // PodSandboxStats returns stats of the pod. If the pod sandbox does not + // exist, the call returns an error. + rpc PodSandboxStats(PodSandboxStatsRequest) returns (PodSandboxStatsResponse) {} + // ListPodSandboxStats returns stats of the pods matching a filter. + rpc ListPodSandboxStats(ListPodSandboxStatsRequest) returns (ListPodSandboxStatsResponse) {} + // UpdateRuntimeConfig updates the runtime configuration based on the given request. rpc UpdateRuntimeConfig(UpdateRuntimeConfigRequest) returns (UpdateRuntimeConfigResponse) {} @@ -324,6 +330,10 @@ message LinuxPodSandboxConfig { LinuxSandboxSecurityContext security_context = 2; // Sysctls holds linux sysctls config for the sandbox. map sysctls = 3; + // Optional overhead represents the overheads associated with this sandbox + LinuxContainerResources overhead = 4; + // Optional resources represents the sum of container resources for this sandbox + LinuxContainerResources resources = 5; } // PodSandboxMetadata holds all necessary information for building the sandbox name. @@ -545,6 +555,113 @@ message ListPodSandboxResponse { repeated PodSandbox items = 1; } +message PodSandboxStatsRequest { + // ID of the pod sandbox for which to retrieve stats. + string pod_sandbox_id = 1; +} + +message PodSandboxStatsResponse { + PodSandboxStats stats = 1; +} + +// PodSandboxStatsFilter is used to filter the list of pod sandboxes to retrieve stats for. +// All those fields are combined with 'AND'. +message PodSandboxStatsFilter { + // ID of the pod sandbox. + string id = 1; + // LabelSelector to select matches. + // Only api.MatchLabels is supported for now and the requirements + // are ANDed. MatchExpressions is not supported yet. + map label_selector = 2; +} + +message ListPodSandboxStatsRequest { + // Filter for the list request. + PodSandboxStatsFilter filter = 1; +} + +message ListPodSandboxStatsResponse { + // Stats of the pod sandbox. + repeated PodSandboxStats stats = 1; +} + +// PodSandboxAttributes provides basic information of the pod sandbox. +message PodSandboxAttributes { + // ID of the pod. + string id = 1; + // Metadata of the pod. + PodSandboxMetadata metadata = 2; + // Key-value pairs that may be used to scope and select individual resources. + map labels = 3; + // Unstructured key-value map holding arbitrary metadata. + // Annotations MUST NOT be altered by the runtime; the value of this field + // MUST be identical to that of the corresponding PodSandboxStatus used to + // instantiate the PodSandbox this status represents. + map annotations = 4; +} + +// PodSandboxStats provides the resource usage statistics for a pod. +// The linux or windows field will be populated depending on the platform. +message PodSandboxStats { + // Information of the pod. + PodSandboxAttributes attributes = 1; + // Stats from linux. + LinuxPodSandboxStats linux = 2; + // Stats from windows. + WindowsPodSandboxStats windows = 3; +} + +// LinuxPodSandboxStats provides the resource usage statistics for a pod sandbox on linux. +message LinuxPodSandboxStats { + // CPU usage gathered for the pod sandbox. + CpuUsage cpu = 1; + // Memory usage gathered for the pod sandbox. + MemoryUsage memory = 2; + // Network usage gathered for the pod sandbox + NetworkUsage network = 3; + // Stats pertaining to processes in the pod sandbox. + ProcessUsage process = 4; + // Stats of containers in the measured pod sandbox. + repeated ContainerStats containers = 5; +} + +// WindowsPodSandboxStats provides the resource usage statistics for a pod sandbox on windows +message WindowsPodSandboxStats { + // TODO: Add stats relevant to windows. +} + +// NetworkUsage contains data about network resources. +message NetworkUsage { + // The time at which these stats were updated. + int64 timestamp = 1; + // Stats for the default network interface. + NetworkInterfaceUsage default_interface = 2; + // Stats for all found network interfaces, excluding the default. + repeated NetworkInterfaceUsage interfaces = 3; +} + +// NetworkInterfaceUsage contains resource value data about a network interface. +message NetworkInterfaceUsage { + // The name of the network interface. + string name = 1; + // Cumulative count of bytes received. + UInt64Value rx_bytes = 2; + // Cumulative count of receive errors encountered. + UInt64Value rx_errors = 3; + // Cumulative count of bytes transmitted. + UInt64Value tx_bytes = 4; + // Cumulative count of transmit errors encountered. + UInt64Value tx_errors = 5; +} + +// ProcessUsage are stats pertaining to processes. +message ProcessUsage { + // The time at which these stats were updated. + int64 timestamp = 1; + // Number of processes. + UInt64Value process_count = 2; +} + // ImageSpec is an internal representation of an image. message ImageSpec { // Container's Image field (e.g. imageID or imageDigest). @@ -1351,6 +1468,9 @@ message CpuUsage { int64 timestamp = 1; // Cumulative CPU usage (sum across all cores) since object creation. UInt64Value usage_core_nano_seconds = 2; + // Total CPU usage (sum of all cores) averaged over the sample window. + // The "core" unit can be interpreted as CPU core-nanoseconds per second. + UInt64Value usage_nano_cores = 3; } // MemoryUsage provides the memory usage information. @@ -1359,6 +1479,16 @@ message MemoryUsage { int64 timestamp = 1; // The amount of working set memory in bytes. UInt64Value working_set_bytes = 2; + // Available memory for use. This is defined as the memory limit - workingSetBytes. + UInt64Value available_bytes = 3; + // Total memory in use. This includes all memory regardless of when it was accessed. + UInt64Value usage_bytes = 4; + // The amount of anonymous and swap cache memory (includes transparent hugepages). + UInt64Value rss_bytes = 5; + // Cumulative number of minor page faults. + UInt64Value page_faults = 6; + // Cumulative number of major page faults. + UInt64Value major_page_faults = 7; } message ReopenContainerLogRequest { diff --git a/vendor/k8s.io/cri-api/pkg/apis/runtime/v1alpha2/api.pb.go b/vendor/k8s.io/cri-api/pkg/apis/runtime/v1alpha2/api.pb.go index 800310a6a..f6d2a668e 100644 --- a/vendor/k8s.io/cri-api/pkg/apis/runtime/v1alpha2/api.pb.go +++ b/vendor/k8s.io/cri-api/pkg/apis/runtime/v1alpha2/api.pb.go @@ -933,9 +933,13 @@ type LinuxPodSandboxConfig struct { // LinuxSandboxSecurityContext holds sandbox security attributes. SecurityContext *LinuxSandboxSecurityContext `protobuf:"bytes,2,opt,name=security_context,json=securityContext,proto3" json:"security_context,omitempty"` // Sysctls holds linux sysctls config for the sandbox. - Sysctls map[string]string `protobuf:"bytes,3,rep,name=sysctls,proto3" json:"sysctls,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_sizecache int32 `json:"-"` + Sysctls map[string]string `protobuf:"bytes,3,rep,name=sysctls,proto3" json:"sysctls,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // Optional overhead represents the overheads associated with this sandbox + Overhead *LinuxContainerResources `protobuf:"bytes,4,opt,name=overhead,proto3" json:"overhead,omitempty"` + // Optional resources represents the sum of container resources for this sandbox + Resources *LinuxContainerResources `protobuf:"bytes,5,opt,name=resources,proto3" json:"resources,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *LinuxPodSandboxConfig) Reset() { *m = LinuxPodSandboxConfig{} } @@ -991,6 +995,20 @@ func (m *LinuxPodSandboxConfig) GetSysctls() map[string]string { return nil } +func (m *LinuxPodSandboxConfig) GetOverhead() *LinuxContainerResources { + if m != nil { + return m.Overhead + } + return nil +} + +func (m *LinuxPodSandboxConfig) GetResources() *LinuxContainerResources { + if m != nil { + return m.Resources + } + return nil +} + // PodSandboxMetadata holds all necessary information for building the sandbox name. // The container runtime is encouraged to expose the metadata associated with the // PodSandbox in its user interface for better user experience. For example, @@ -2235,6 +2253,716 @@ func (m *ListPodSandboxResponse) GetItems() []*PodSandbox { return nil } +type PodSandboxStatsRequest struct { + // ID of the pod sandbox for which to retrieve stats. + PodSandboxId string `protobuf:"bytes,1,opt,name=pod_sandbox_id,json=podSandboxId,proto3" json:"pod_sandbox_id,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PodSandboxStatsRequest) Reset() { *m = PodSandboxStatsRequest{} } +func (*PodSandboxStatsRequest) ProtoMessage() {} +func (*PodSandboxStatsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{30} +} +func (m *PodSandboxStatsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PodSandboxStatsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PodSandboxStatsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PodSandboxStatsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_PodSandboxStatsRequest.Merge(m, src) +} +func (m *PodSandboxStatsRequest) XXX_Size() int { + return m.Size() +} +func (m *PodSandboxStatsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_PodSandboxStatsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_PodSandboxStatsRequest proto.InternalMessageInfo + +func (m *PodSandboxStatsRequest) GetPodSandboxId() string { + if m != nil { + return m.PodSandboxId + } + return "" +} + +type PodSandboxStatsResponse struct { + Stats *PodSandboxStats `protobuf:"bytes,1,opt,name=stats,proto3" json:"stats,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PodSandboxStatsResponse) Reset() { *m = PodSandboxStatsResponse{} } +func (*PodSandboxStatsResponse) ProtoMessage() {} +func (*PodSandboxStatsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{31} +} +func (m *PodSandboxStatsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PodSandboxStatsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PodSandboxStatsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PodSandboxStatsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_PodSandboxStatsResponse.Merge(m, src) +} +func (m *PodSandboxStatsResponse) XXX_Size() int { + return m.Size() +} +func (m *PodSandboxStatsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_PodSandboxStatsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_PodSandboxStatsResponse proto.InternalMessageInfo + +func (m *PodSandboxStatsResponse) GetStats() *PodSandboxStats { + if m != nil { + return m.Stats + } + return nil +} + +// PodSandboxStatsFilter is used to filter pod sandboxes. +// All those fields are combined with 'AND'. +type PodSandboxStatsFilter struct { + // ID of the pod sandbox. + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // LabelSelector to select matches. + // Only api.MatchLabels is supported for now and the requirements + // are ANDed. MatchExpressions is not supported yet. + LabelSelector map[string]string `protobuf:"bytes,2,rep,name=label_selector,json=labelSelector,proto3" json:"label_selector,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PodSandboxStatsFilter) Reset() { *m = PodSandboxStatsFilter{} } +func (*PodSandboxStatsFilter) ProtoMessage() {} +func (*PodSandboxStatsFilter) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{32} +} +func (m *PodSandboxStatsFilter) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PodSandboxStatsFilter) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PodSandboxStatsFilter.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PodSandboxStatsFilter) XXX_Merge(src proto.Message) { + xxx_messageInfo_PodSandboxStatsFilter.Merge(m, src) +} +func (m *PodSandboxStatsFilter) XXX_Size() int { + return m.Size() +} +func (m *PodSandboxStatsFilter) XXX_DiscardUnknown() { + xxx_messageInfo_PodSandboxStatsFilter.DiscardUnknown(m) +} + +var xxx_messageInfo_PodSandboxStatsFilter proto.InternalMessageInfo + +func (m *PodSandboxStatsFilter) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +func (m *PodSandboxStatsFilter) GetLabelSelector() map[string]string { + if m != nil { + return m.LabelSelector + } + return nil +} + +type ListPodSandboxStatsRequest struct { + // Filter for the list request. + Filter *PodSandboxStatsFilter `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ListPodSandboxStatsRequest) Reset() { *m = ListPodSandboxStatsRequest{} } +func (*ListPodSandboxStatsRequest) ProtoMessage() {} +func (*ListPodSandboxStatsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{33} +} +func (m *ListPodSandboxStatsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ListPodSandboxStatsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ListPodSandboxStatsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ListPodSandboxStatsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListPodSandboxStatsRequest.Merge(m, src) +} +func (m *ListPodSandboxStatsRequest) XXX_Size() int { + return m.Size() +} +func (m *ListPodSandboxStatsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ListPodSandboxStatsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ListPodSandboxStatsRequest proto.InternalMessageInfo + +func (m *ListPodSandboxStatsRequest) GetFilter() *PodSandboxStatsFilter { + if m != nil { + return m.Filter + } + return nil +} + +type ListPodSandboxStatsResponse struct { + // Stats of the pod sandbox. + Stats []*PodSandboxStats `protobuf:"bytes,1,rep,name=stats,proto3" json:"stats,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ListPodSandboxStatsResponse) Reset() { *m = ListPodSandboxStatsResponse{} } +func (*ListPodSandboxStatsResponse) ProtoMessage() {} +func (*ListPodSandboxStatsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{34} +} +func (m *ListPodSandboxStatsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ListPodSandboxStatsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ListPodSandboxStatsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ListPodSandboxStatsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListPodSandboxStatsResponse.Merge(m, src) +} +func (m *ListPodSandboxStatsResponse) XXX_Size() int { + return m.Size() +} +func (m *ListPodSandboxStatsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ListPodSandboxStatsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_ListPodSandboxStatsResponse proto.InternalMessageInfo + +func (m *ListPodSandboxStatsResponse) GetStats() []*PodSandboxStats { + if m != nil { + return m.Stats + } + return nil +} + +// PodSandboxAttributes provides basic information of the pod sandbox. +type PodSandboxAttributes struct { + // ID of the pod sandbox. + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Metadata of the pod sandbox. + Metadata *PodSandboxMetadata `protobuf:"bytes,2,opt,name=metadata,proto3" json:"metadata,omitempty"` + // Key-value pairs that may be used to scope and select individual resources. + Labels map[string]string `protobuf:"bytes,3,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // Unstructured key-value map holding arbitrary metadata. + // Annotations MUST NOT be altered by the runtime; the value of this field + // MUST be identical to that of the corresponding PodSandboxStatus used to + // instantiate the PodSandbox this status represents. + Annotations map[string]string `protobuf:"bytes,4,rep,name=annotations,proto3" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PodSandboxAttributes) Reset() { *m = PodSandboxAttributes{} } +func (*PodSandboxAttributes) ProtoMessage() {} +func (*PodSandboxAttributes) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{35} +} +func (m *PodSandboxAttributes) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PodSandboxAttributes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PodSandboxAttributes.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PodSandboxAttributes) XXX_Merge(src proto.Message) { + xxx_messageInfo_PodSandboxAttributes.Merge(m, src) +} +func (m *PodSandboxAttributes) XXX_Size() int { + return m.Size() +} +func (m *PodSandboxAttributes) XXX_DiscardUnknown() { + xxx_messageInfo_PodSandboxAttributes.DiscardUnknown(m) +} + +var xxx_messageInfo_PodSandboxAttributes proto.InternalMessageInfo + +func (m *PodSandboxAttributes) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +func (m *PodSandboxAttributes) GetMetadata() *PodSandboxMetadata { + if m != nil { + return m.Metadata + } + return nil +} + +func (m *PodSandboxAttributes) GetLabels() map[string]string { + if m != nil { + return m.Labels + } + return nil +} + +func (m *PodSandboxAttributes) GetAnnotations() map[string]string { + if m != nil { + return m.Annotations + } + return nil +} + +// PodSandboxStats provides the resource usage statistics for a pod. +// The linux or windows field will be populated depending on the platform. +type PodSandboxStats struct { + // Information of the pod. + Attributes *PodSandboxAttributes `protobuf:"bytes,1,opt,name=attributes,proto3" json:"attributes,omitempty"` + // Stats from linux. + Linux *LinuxPodSandboxStats `protobuf:"bytes,2,opt,name=linux,proto3" json:"linux,omitempty"` + // Stats from windows. + Windows *WindowsPodSandboxStats `protobuf:"bytes,3,opt,name=windows,proto3" json:"windows,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PodSandboxStats) Reset() { *m = PodSandboxStats{} } +func (*PodSandboxStats) ProtoMessage() {} +func (*PodSandboxStats) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{36} +} +func (m *PodSandboxStats) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PodSandboxStats) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PodSandboxStats.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PodSandboxStats) XXX_Merge(src proto.Message) { + xxx_messageInfo_PodSandboxStats.Merge(m, src) +} +func (m *PodSandboxStats) XXX_Size() int { + return m.Size() +} +func (m *PodSandboxStats) XXX_DiscardUnknown() { + xxx_messageInfo_PodSandboxStats.DiscardUnknown(m) +} + +var xxx_messageInfo_PodSandboxStats proto.InternalMessageInfo + +func (m *PodSandboxStats) GetAttributes() *PodSandboxAttributes { + if m != nil { + return m.Attributes + } + return nil +} + +func (m *PodSandboxStats) GetLinux() *LinuxPodSandboxStats { + if m != nil { + return m.Linux + } + return nil +} + +func (m *PodSandboxStats) GetWindows() *WindowsPodSandboxStats { + if m != nil { + return m.Windows + } + return nil +} + +// LinuxPodSandboxStats provides the resource usage statistics for a pod sandbox on linux. +type LinuxPodSandboxStats struct { + // CPU usage gathered for the pod sandbox. + Cpu *CpuUsage `protobuf:"bytes,1,opt,name=cpu,proto3" json:"cpu,omitempty"` + // Memory usage gathered for the pod sandbox. + Memory *MemoryUsage `protobuf:"bytes,2,opt,name=memory,proto3" json:"memory,omitempty"` + // Network usage gathered for the pod sandbox + Network *NetworkUsage `protobuf:"bytes,3,opt,name=network,proto3" json:"network,omitempty"` + // Stats pertaining to processes in the pod sandbox. + Process *ProcessUsage `protobuf:"bytes,4,opt,name=process,proto3" json:"process,omitempty"` + // Stats of containers in the measured pod sandbox. + Containers []*ContainerStats `protobuf:"bytes,5,rep,name=containers,proto3" json:"containers,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *LinuxPodSandboxStats) Reset() { *m = LinuxPodSandboxStats{} } +func (*LinuxPodSandboxStats) ProtoMessage() {} +func (*LinuxPodSandboxStats) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{37} +} +func (m *LinuxPodSandboxStats) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *LinuxPodSandboxStats) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_LinuxPodSandboxStats.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *LinuxPodSandboxStats) XXX_Merge(src proto.Message) { + xxx_messageInfo_LinuxPodSandboxStats.Merge(m, src) +} +func (m *LinuxPodSandboxStats) XXX_Size() int { + return m.Size() +} +func (m *LinuxPodSandboxStats) XXX_DiscardUnknown() { + xxx_messageInfo_LinuxPodSandboxStats.DiscardUnknown(m) +} + +var xxx_messageInfo_LinuxPodSandboxStats proto.InternalMessageInfo + +func (m *LinuxPodSandboxStats) GetCpu() *CpuUsage { + if m != nil { + return m.Cpu + } + return nil +} + +func (m *LinuxPodSandboxStats) GetMemory() *MemoryUsage { + if m != nil { + return m.Memory + } + return nil +} + +func (m *LinuxPodSandboxStats) GetNetwork() *NetworkUsage { + if m != nil { + return m.Network + } + return nil +} + +func (m *LinuxPodSandboxStats) GetProcess() *ProcessUsage { + if m != nil { + return m.Process + } + return nil +} + +func (m *LinuxPodSandboxStats) GetContainers() []*ContainerStats { + if m != nil { + return m.Containers + } + return nil +} + +// WindowsPodSandboxStats provides the resource usage statistics for a pod sandbox on windows +type WindowsPodSandboxStats struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *WindowsPodSandboxStats) Reset() { *m = WindowsPodSandboxStats{} } +func (*WindowsPodSandboxStats) ProtoMessage() {} +func (*WindowsPodSandboxStats) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{38} +} +func (m *WindowsPodSandboxStats) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *WindowsPodSandboxStats) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_WindowsPodSandboxStats.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *WindowsPodSandboxStats) XXX_Merge(src proto.Message) { + xxx_messageInfo_WindowsPodSandboxStats.Merge(m, src) +} +func (m *WindowsPodSandboxStats) XXX_Size() int { + return m.Size() +} +func (m *WindowsPodSandboxStats) XXX_DiscardUnknown() { + xxx_messageInfo_WindowsPodSandboxStats.DiscardUnknown(m) +} + +var xxx_messageInfo_WindowsPodSandboxStats proto.InternalMessageInfo + +// NetworkUsage contains data about network resources. +type NetworkUsage struct { + // The time at which these stats were updated. + Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // Stats for the default network interface. + DefaultInterface *NetworkInterfaceUsage `protobuf:"bytes,2,opt,name=default_interface,json=defaultInterface,proto3" json:"default_interface,omitempty"` + // Stats for all found network interfaces, excluding the default. + Interfaces []*NetworkInterfaceUsage `protobuf:"bytes,3,rep,name=interfaces,proto3" json:"interfaces,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *NetworkUsage) Reset() { *m = NetworkUsage{} } +func (*NetworkUsage) ProtoMessage() {} +func (*NetworkUsage) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{39} +} +func (m *NetworkUsage) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *NetworkUsage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_NetworkUsage.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *NetworkUsage) XXX_Merge(src proto.Message) { + xxx_messageInfo_NetworkUsage.Merge(m, src) +} +func (m *NetworkUsage) XXX_Size() int { + return m.Size() +} +func (m *NetworkUsage) XXX_DiscardUnknown() { + xxx_messageInfo_NetworkUsage.DiscardUnknown(m) +} + +var xxx_messageInfo_NetworkUsage proto.InternalMessageInfo + +func (m *NetworkUsage) GetTimestamp() int64 { + if m != nil { + return m.Timestamp + } + return 0 +} + +func (m *NetworkUsage) GetDefaultInterface() *NetworkInterfaceUsage { + if m != nil { + return m.DefaultInterface + } + return nil +} + +func (m *NetworkUsage) GetInterfaces() []*NetworkInterfaceUsage { + if m != nil { + return m.Interfaces + } + return nil +} + +// NetworkInterfaceUsage contains resource value data about a network interface. +type NetworkInterfaceUsage struct { + // The name of the network interface. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // Cumulative count of bytes received. + RxBytes *UInt64Value `protobuf:"bytes,2,opt,name=rx_bytes,json=rxBytes,proto3" json:"rx_bytes,omitempty"` + // Cumulative count of receive errors encountered. + RxErrors *UInt64Value `protobuf:"bytes,3,opt,name=rx_errors,json=rxErrors,proto3" json:"rx_errors,omitempty"` + // Cumulative count of bytes transmitted. + TxBytes *UInt64Value `protobuf:"bytes,4,opt,name=tx_bytes,json=txBytes,proto3" json:"tx_bytes,omitempty"` + // Cumulative count of transmit errors encountered. + TxErrors *UInt64Value `protobuf:"bytes,5,opt,name=tx_errors,json=txErrors,proto3" json:"tx_errors,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *NetworkInterfaceUsage) Reset() { *m = NetworkInterfaceUsage{} } +func (*NetworkInterfaceUsage) ProtoMessage() {} +func (*NetworkInterfaceUsage) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{40} +} +func (m *NetworkInterfaceUsage) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *NetworkInterfaceUsage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_NetworkInterfaceUsage.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *NetworkInterfaceUsage) XXX_Merge(src proto.Message) { + xxx_messageInfo_NetworkInterfaceUsage.Merge(m, src) +} +func (m *NetworkInterfaceUsage) XXX_Size() int { + return m.Size() +} +func (m *NetworkInterfaceUsage) XXX_DiscardUnknown() { + xxx_messageInfo_NetworkInterfaceUsage.DiscardUnknown(m) +} + +var xxx_messageInfo_NetworkInterfaceUsage proto.InternalMessageInfo + +func (m *NetworkInterfaceUsage) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *NetworkInterfaceUsage) GetRxBytes() *UInt64Value { + if m != nil { + return m.RxBytes + } + return nil +} + +func (m *NetworkInterfaceUsage) GetRxErrors() *UInt64Value { + if m != nil { + return m.RxErrors + } + return nil +} + +func (m *NetworkInterfaceUsage) GetTxBytes() *UInt64Value { + if m != nil { + return m.TxBytes + } + return nil +} + +func (m *NetworkInterfaceUsage) GetTxErrors() *UInt64Value { + if m != nil { + return m.TxErrors + } + return nil +} + +// ProcessUsage are stats pertaining to processes. +type ProcessUsage struct { + // The time at which these stats were updated. + Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // Number of processes. + ProcessCount *UInt64Value `protobuf:"bytes,2,opt,name=process_count,json=processCount,proto3" json:"process_count,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ProcessUsage) Reset() { *m = ProcessUsage{} } +func (*ProcessUsage) ProtoMessage() {} +func (*ProcessUsage) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{41} +} +func (m *ProcessUsage) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ProcessUsage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ProcessUsage.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ProcessUsage) XXX_Merge(src proto.Message) { + xxx_messageInfo_ProcessUsage.Merge(m, src) +} +func (m *ProcessUsage) XXX_Size() int { + return m.Size() +} +func (m *ProcessUsage) XXX_DiscardUnknown() { + xxx_messageInfo_ProcessUsage.DiscardUnknown(m) +} + +var xxx_messageInfo_ProcessUsage proto.InternalMessageInfo + +func (m *ProcessUsage) GetTimestamp() int64 { + if m != nil { + return m.Timestamp + } + return 0 +} + +func (m *ProcessUsage) GetProcessCount() *UInt64Value { + if m != nil { + return m.ProcessCount + } + return nil +} + // ImageSpec is an internal representation of an image. type ImageSpec struct { // Container's Image field (e.g. imageID or imageDigest). @@ -2250,7 +2978,7 @@ type ImageSpec struct { func (m *ImageSpec) Reset() { *m = ImageSpec{} } func (*ImageSpec) ProtoMessage() {} func (*ImageSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{30} + return fileDescriptor_00212fb1f9d3bf1c, []int{42} } func (m *ImageSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2303,7 +3031,7 @@ type KeyValue struct { func (m *KeyValue) Reset() { *m = KeyValue{} } func (*KeyValue) ProtoMessage() {} func (*KeyValue) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{31} + return fileDescriptor_00212fb1f9d3bf1c, []int{43} } func (m *KeyValue) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2380,7 +3108,7 @@ type LinuxContainerResources struct { func (m *LinuxContainerResources) Reset() { *m = LinuxContainerResources{} } func (*LinuxContainerResources) ProtoMessage() {} func (*LinuxContainerResources) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{32} + return fileDescriptor_00212fb1f9d3bf1c, []int{44} } func (m *LinuxContainerResources) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2495,7 +3223,7 @@ type HugepageLimit struct { func (m *HugepageLimit) Reset() { *m = HugepageLimit{} } func (*HugepageLimit) ProtoMessage() {} func (*HugepageLimit) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{33} + return fileDescriptor_00212fb1f9d3bf1c, []int{45} } func (m *HugepageLimit) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2551,7 +3279,7 @@ type SELinuxOption struct { func (m *SELinuxOption) Reset() { *m = SELinuxOption{} } func (*SELinuxOption) ProtoMessage() {} func (*SELinuxOption) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{34} + return fileDescriptor_00212fb1f9d3bf1c, []int{46} } func (m *SELinuxOption) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2621,7 +3349,7 @@ type Capability struct { func (m *Capability) Reset() { *m = Capability{} } func (*Capability) ProtoMessage() {} func (*Capability) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{35} + return fileDescriptor_00212fb1f9d3bf1c, []int{47} } func (m *Capability) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2741,7 +3469,7 @@ type LinuxContainerSecurityContext struct { func (m *LinuxContainerSecurityContext) Reset() { *m = LinuxContainerSecurityContext{} } func (*LinuxContainerSecurityContext) ProtoMessage() {} func (*LinuxContainerSecurityContext) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{36} + return fileDescriptor_00212fb1f9d3bf1c, []int{48} } func (m *LinuxContainerSecurityContext) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2898,7 +3626,7 @@ type LinuxContainerConfig struct { func (m *LinuxContainerConfig) Reset() { *m = LinuxContainerConfig{} } func (*LinuxContainerConfig) ProtoMessage() {} func (*LinuxContainerConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{37} + return fileDescriptor_00212fb1f9d3bf1c, []int{49} } func (m *LinuxContainerConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2960,7 +3688,7 @@ type WindowsSandboxSecurityContext struct { func (m *WindowsSandboxSecurityContext) Reset() { *m = WindowsSandboxSecurityContext{} } func (*WindowsSandboxSecurityContext) ProtoMessage() {} func (*WindowsSandboxSecurityContext) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{38} + return fileDescriptor_00212fb1f9d3bf1c, []int{50} } func (m *WindowsSandboxSecurityContext) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3022,7 +3750,7 @@ type WindowsPodSandboxConfig struct { func (m *WindowsPodSandboxConfig) Reset() { *m = WindowsPodSandboxConfig{} } func (*WindowsPodSandboxConfig) ProtoMessage() {} func (*WindowsPodSandboxConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{39} + return fileDescriptor_00212fb1f9d3bf1c, []int{51} } func (m *WindowsPodSandboxConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3075,7 +3803,7 @@ type WindowsContainerSecurityContext struct { func (m *WindowsContainerSecurityContext) Reset() { *m = WindowsContainerSecurityContext{} } func (*WindowsContainerSecurityContext) ProtoMessage() {} func (*WindowsContainerSecurityContext) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{40} + return fileDescriptor_00212fb1f9d3bf1c, []int{52} } func (m *WindowsContainerSecurityContext) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3139,7 +3867,7 @@ type WindowsContainerConfig struct { func (m *WindowsContainerConfig) Reset() { *m = WindowsContainerConfig{} } func (*WindowsContainerConfig) ProtoMessage() {} func (*WindowsContainerConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{41} + return fileDescriptor_00212fb1f9d3bf1c, []int{53} } func (m *WindowsContainerConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3200,7 +3928,7 @@ type WindowsContainerResources struct { func (m *WindowsContainerResources) Reset() { *m = WindowsContainerResources{} } func (*WindowsContainerResources) ProtoMessage() {} func (*WindowsContainerResources) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{42} + return fileDescriptor_00212fb1f9d3bf1c, []int{54} } func (m *WindowsContainerResources) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3274,7 +4002,7 @@ type ContainerMetadata struct { func (m *ContainerMetadata) Reset() { *m = ContainerMetadata{} } func (*ContainerMetadata) ProtoMessage() {} func (*ContainerMetadata) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{43} + return fileDescriptor_00212fb1f9d3bf1c, []int{55} } func (m *ContainerMetadata) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3335,7 +4063,7 @@ type Device struct { func (m *Device) Reset() { *m = Device{} } func (*Device) ProtoMessage() {} func (*Device) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{44} + return fileDescriptor_00212fb1f9d3bf1c, []int{56} } func (m *Device) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3454,7 +4182,7 @@ type ContainerConfig struct { func (m *ContainerConfig) Reset() { *m = ContainerConfig{} } func (*ContainerConfig) ProtoMessage() {} func (*ContainerConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{45} + return fileDescriptor_00212fb1f9d3bf1c, []int{57} } func (m *ContainerConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3612,7 +4340,7 @@ type CreateContainerRequest struct { func (m *CreateContainerRequest) Reset() { *m = CreateContainerRequest{} } func (*CreateContainerRequest) ProtoMessage() {} func (*CreateContainerRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{46} + return fileDescriptor_00212fb1f9d3bf1c, []int{58} } func (m *CreateContainerRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3672,7 +4400,7 @@ type CreateContainerResponse struct { func (m *CreateContainerResponse) Reset() { *m = CreateContainerResponse{} } func (*CreateContainerResponse) ProtoMessage() {} func (*CreateContainerResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{47} + return fileDescriptor_00212fb1f9d3bf1c, []int{59} } func (m *CreateContainerResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3718,7 +4446,7 @@ type StartContainerRequest struct { func (m *StartContainerRequest) Reset() { *m = StartContainerRequest{} } func (*StartContainerRequest) ProtoMessage() {} func (*StartContainerRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{48} + return fileDescriptor_00212fb1f9d3bf1c, []int{60} } func (m *StartContainerRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3762,7 +4490,7 @@ type StartContainerResponse struct { func (m *StartContainerResponse) Reset() { *m = StartContainerResponse{} } func (*StartContainerResponse) ProtoMessage() {} func (*StartContainerResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{49} + return fileDescriptor_00212fb1f9d3bf1c, []int{61} } func (m *StartContainerResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3804,7 +4532,7 @@ type StopContainerRequest struct { func (m *StopContainerRequest) Reset() { *m = StopContainerRequest{} } func (*StopContainerRequest) ProtoMessage() {} func (*StopContainerRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{50} + return fileDescriptor_00212fb1f9d3bf1c, []int{62} } func (m *StopContainerRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3855,7 +4583,7 @@ type StopContainerResponse struct { func (m *StopContainerResponse) Reset() { *m = StopContainerResponse{} } func (*StopContainerResponse) ProtoMessage() {} func (*StopContainerResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{51} + return fileDescriptor_00212fb1f9d3bf1c, []int{63} } func (m *StopContainerResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3894,7 +4622,7 @@ type RemoveContainerRequest struct { func (m *RemoveContainerRequest) Reset() { *m = RemoveContainerRequest{} } func (*RemoveContainerRequest) ProtoMessage() {} func (*RemoveContainerRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{52} + return fileDescriptor_00212fb1f9d3bf1c, []int{64} } func (m *RemoveContainerRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3938,7 +4666,7 @@ type RemoveContainerResponse struct { func (m *RemoveContainerResponse) Reset() { *m = RemoveContainerResponse{} } func (*RemoveContainerResponse) ProtoMessage() {} func (*RemoveContainerResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{53} + return fileDescriptor_00212fb1f9d3bf1c, []int{65} } func (m *RemoveContainerResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3978,7 +4706,7 @@ type ContainerStateValue struct { func (m *ContainerStateValue) Reset() { *m = ContainerStateValue{} } func (*ContainerStateValue) ProtoMessage() {} func (*ContainerStateValue) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{54} + return fileDescriptor_00212fb1f9d3bf1c, []int{66} } func (m *ContainerStateValue) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4034,7 +4762,7 @@ type ContainerFilter struct { func (m *ContainerFilter) Reset() { *m = ContainerFilter{} } func (*ContainerFilter) ProtoMessage() {} func (*ContainerFilter) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{55} + return fileDescriptor_00212fb1f9d3bf1c, []int{67} } func (m *ContainerFilter) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4100,7 +4828,7 @@ type ListContainersRequest struct { func (m *ListContainersRequest) Reset() { *m = ListContainersRequest{} } func (*ListContainersRequest) ProtoMessage() {} func (*ListContainersRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{56} + return fileDescriptor_00212fb1f9d3bf1c, []int{68} } func (m *ListContainersRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4169,7 +4897,7 @@ type Container struct { func (m *Container) Reset() { *m = Container{} } func (*Container) ProtoMessage() {} func (*Container) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{57} + return fileDescriptor_00212fb1f9d3bf1c, []int{69} } func (m *Container) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4271,7 +4999,7 @@ type ListContainersResponse struct { func (m *ListContainersResponse) Reset() { *m = ListContainersResponse{} } func (*ListContainersResponse) ProtoMessage() {} func (*ListContainersResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{58} + return fileDescriptor_00212fb1f9d3bf1c, []int{70} } func (m *ListContainersResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4319,7 +5047,7 @@ type ContainerStatusRequest struct { func (m *ContainerStatusRequest) Reset() { *m = ContainerStatusRequest{} } func (*ContainerStatusRequest) ProtoMessage() {} func (*ContainerStatusRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{59} + return fileDescriptor_00212fb1f9d3bf1c, []int{71} } func (m *ContainerStatusRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4406,7 +5134,7 @@ type ContainerStatus struct { func (m *ContainerStatus) Reset() { *m = ContainerStatus{} } func (*ContainerStatus) ProtoMessage() {} func (*ContainerStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{60} + return fileDescriptor_00212fb1f9d3bf1c, []int{72} } func (m *ContainerStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4555,7 +5283,7 @@ type ContainerStatusResponse struct { func (m *ContainerStatusResponse) Reset() { *m = ContainerStatusResponse{} } func (*ContainerStatusResponse) ProtoMessage() {} func (*ContainerStatusResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{61} + return fileDescriptor_00212fb1f9d3bf1c, []int{73} } func (m *ContainerStatusResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4616,7 +5344,7 @@ type UpdateContainerResourcesRequest struct { func (m *UpdateContainerResourcesRequest) Reset() { *m = UpdateContainerResourcesRequest{} } func (*UpdateContainerResourcesRequest) ProtoMessage() {} func (*UpdateContainerResourcesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{62} + return fileDescriptor_00212fb1f9d3bf1c, []int{74} } func (m *UpdateContainerResourcesRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4681,7 +5409,7 @@ type UpdateContainerResourcesResponse struct { func (m *UpdateContainerResourcesResponse) Reset() { *m = UpdateContainerResourcesResponse{} } func (*UpdateContainerResourcesResponse) ProtoMessage() {} func (*UpdateContainerResourcesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{63} + return fileDescriptor_00212fb1f9d3bf1c, []int{75} } func (m *UpdateContainerResourcesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4724,7 +5452,7 @@ type ExecSyncRequest struct { func (m *ExecSyncRequest) Reset() { *m = ExecSyncRequest{} } func (*ExecSyncRequest) ProtoMessage() {} func (*ExecSyncRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{64} + return fileDescriptor_00212fb1f9d3bf1c, []int{76} } func (m *ExecSyncRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4788,7 +5516,7 @@ type ExecSyncResponse struct { func (m *ExecSyncResponse) Reset() { *m = ExecSyncResponse{} } func (*ExecSyncResponse) ProtoMessage() {} func (*ExecSyncResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{65} + return fileDescriptor_00212fb1f9d3bf1c, []int{77} } func (m *ExecSyncResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4864,7 +5592,7 @@ type ExecRequest struct { func (m *ExecRequest) Reset() { *m = ExecRequest{} } func (*ExecRequest) ProtoMessage() {} func (*ExecRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{66} + return fileDescriptor_00212fb1f9d3bf1c, []int{78} } func (m *ExecRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4945,7 +5673,7 @@ type ExecResponse struct { func (m *ExecResponse) Reset() { *m = ExecResponse{} } func (*ExecResponse) ProtoMessage() {} func (*ExecResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{67} + return fileDescriptor_00212fb1f9d3bf1c, []int{79} } func (m *ExecResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5006,7 +5734,7 @@ type AttachRequest struct { func (m *AttachRequest) Reset() { *m = AttachRequest{} } func (*AttachRequest) ProtoMessage() {} func (*AttachRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{68} + return fileDescriptor_00212fb1f9d3bf1c, []int{80} } func (m *AttachRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5080,7 +5808,7 @@ type AttachResponse struct { func (m *AttachResponse) Reset() { *m = AttachResponse{} } func (*AttachResponse) ProtoMessage() {} func (*AttachResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{69} + return fileDescriptor_00212fb1f9d3bf1c, []int{81} } func (m *AttachResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5128,7 +5856,7 @@ type PortForwardRequest struct { func (m *PortForwardRequest) Reset() { *m = PortForwardRequest{} } func (*PortForwardRequest) ProtoMessage() {} func (*PortForwardRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{70} + return fileDescriptor_00212fb1f9d3bf1c, []int{82} } func (m *PortForwardRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5181,7 +5909,7 @@ type PortForwardResponse struct { func (m *PortForwardResponse) Reset() { *m = PortForwardResponse{} } func (*PortForwardResponse) ProtoMessage() {} func (*PortForwardResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{71} + return fileDescriptor_00212fb1f9d3bf1c, []int{83} } func (m *PortForwardResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5227,7 +5955,7 @@ type ImageFilter struct { func (m *ImageFilter) Reset() { *m = ImageFilter{} } func (*ImageFilter) ProtoMessage() {} func (*ImageFilter) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{72} + return fileDescriptor_00212fb1f9d3bf1c, []int{84} } func (m *ImageFilter) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5273,7 +6001,7 @@ type ListImagesRequest struct { func (m *ListImagesRequest) Reset() { *m = ListImagesRequest{} } func (*ListImagesRequest) ProtoMessage() {} func (*ListImagesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{73} + return fileDescriptor_00212fb1f9d3bf1c, []int{85} } func (m *ListImagesRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5335,7 +6063,7 @@ type Image struct { func (m *Image) Reset() { *m = Image{} } func (*Image) ProtoMessage() {} func (*Image) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{74} + return fileDescriptor_00212fb1f9d3bf1c, []int{86} } func (m *Image) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5423,7 +6151,7 @@ type ListImagesResponse struct { func (m *ListImagesResponse) Reset() { *m = ListImagesResponse{} } func (*ListImagesResponse) ProtoMessage() {} func (*ListImagesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{75} + return fileDescriptor_00212fb1f9d3bf1c, []int{87} } func (m *ListImagesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5471,7 +6199,7 @@ type ImageStatusRequest struct { func (m *ImageStatusRequest) Reset() { *m = ImageStatusRequest{} } func (*ImageStatusRequest) ProtoMessage() {} func (*ImageStatusRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{76} + return fileDescriptor_00212fb1f9d3bf1c, []int{88} } func (m *ImageStatusRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5529,7 +6257,7 @@ type ImageStatusResponse struct { func (m *ImageStatusResponse) Reset() { *m = ImageStatusResponse{} } func (*ImageStatusResponse) ProtoMessage() {} func (*ImageStatusResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{77} + return fileDescriptor_00212fb1f9d3bf1c, []int{89} } func (m *ImageStatusResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5590,7 +6318,7 @@ type AuthConfig struct { func (m *AuthConfig) Reset() { *m = AuthConfig{} } func (*AuthConfig) ProtoMessage() {} func (*AuthConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{78} + return fileDescriptor_00212fb1f9d3bf1c, []int{90} } func (m *AuthConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5675,7 +6403,7 @@ type PullImageRequest struct { func (m *PullImageRequest) Reset() { *m = PullImageRequest{} } func (*PullImageRequest) ProtoMessage() {} func (*PullImageRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{79} + return fileDescriptor_00212fb1f9d3bf1c, []int{91} } func (m *PullImageRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5736,7 +6464,7 @@ type PullImageResponse struct { func (m *PullImageResponse) Reset() { *m = PullImageResponse{} } func (*PullImageResponse) ProtoMessage() {} func (*PullImageResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{80} + return fileDescriptor_00212fb1f9d3bf1c, []int{92} } func (m *PullImageResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5782,7 +6510,7 @@ type RemoveImageRequest struct { func (m *RemoveImageRequest) Reset() { *m = RemoveImageRequest{} } func (*RemoveImageRequest) ProtoMessage() {} func (*RemoveImageRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{81} + return fileDescriptor_00212fb1f9d3bf1c, []int{93} } func (m *RemoveImageRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5826,7 +6554,7 @@ type RemoveImageResponse struct { func (m *RemoveImageResponse) Reset() { *m = RemoveImageResponse{} } func (*RemoveImageResponse) ProtoMessage() {} func (*RemoveImageResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{82} + return fileDescriptor_00212fb1f9d3bf1c, []int{94} } func (m *RemoveImageResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5866,7 +6594,7 @@ type NetworkConfig struct { func (m *NetworkConfig) Reset() { *m = NetworkConfig{} } func (*NetworkConfig) ProtoMessage() {} func (*NetworkConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{83} + return fileDescriptor_00212fb1f9d3bf1c, []int{95} } func (m *NetworkConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5911,7 +6639,7 @@ type RuntimeConfig struct { func (m *RuntimeConfig) Reset() { *m = RuntimeConfig{} } func (*RuntimeConfig) ProtoMessage() {} func (*RuntimeConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{84} + return fileDescriptor_00212fb1f9d3bf1c, []int{96} } func (m *RuntimeConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5956,7 +6684,7 @@ type UpdateRuntimeConfigRequest struct { func (m *UpdateRuntimeConfigRequest) Reset() { *m = UpdateRuntimeConfigRequest{} } func (*UpdateRuntimeConfigRequest) ProtoMessage() {} func (*UpdateRuntimeConfigRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{85} + return fileDescriptor_00212fb1f9d3bf1c, []int{97} } func (m *UpdateRuntimeConfigRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6000,7 +6728,7 @@ type UpdateRuntimeConfigResponse struct { func (m *UpdateRuntimeConfigResponse) Reset() { *m = UpdateRuntimeConfigResponse{} } func (*UpdateRuntimeConfigResponse) ProtoMessage() {} func (*UpdateRuntimeConfigResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{86} + return fileDescriptor_00212fb1f9d3bf1c, []int{98} } func (m *UpdateRuntimeConfigResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6058,7 +6786,7 @@ type RuntimeCondition struct { func (m *RuntimeCondition) Reset() { *m = RuntimeCondition{} } func (*RuntimeCondition) ProtoMessage() {} func (*RuntimeCondition) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{87} + return fileDescriptor_00212fb1f9d3bf1c, []int{99} } func (m *RuntimeCondition) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6126,7 +6854,7 @@ type RuntimeStatus struct { func (m *RuntimeStatus) Reset() { *m = RuntimeStatus{} } func (*RuntimeStatus) ProtoMessage() {} func (*RuntimeStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{88} + return fileDescriptor_00212fb1f9d3bf1c, []int{100} } func (m *RuntimeStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6172,7 +6900,7 @@ type StatusRequest struct { func (m *StatusRequest) Reset() { *m = StatusRequest{} } func (*StatusRequest) ProtoMessage() {} func (*StatusRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{89} + return fileDescriptor_00212fb1f9d3bf1c, []int{101} } func (m *StatusRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6223,7 +6951,7 @@ type StatusResponse struct { func (m *StatusResponse) Reset() { *m = StatusResponse{} } func (*StatusResponse) ProtoMessage() {} func (*StatusResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{90} + return fileDescriptor_00212fb1f9d3bf1c, []int{102} } func (m *StatusResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6274,7 +7002,7 @@ type ImageFsInfoRequest struct { func (m *ImageFsInfoRequest) Reset() { *m = ImageFsInfoRequest{} } func (*ImageFsInfoRequest) ProtoMessage() {} func (*ImageFsInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{91} + return fileDescriptor_00212fb1f9d3bf1c, []int{103} } func (m *ImageFsInfoRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6314,7 +7042,7 @@ type UInt64Value struct { func (m *UInt64Value) Reset() { *m = UInt64Value{} } func (*UInt64Value) ProtoMessage() {} func (*UInt64Value) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{92} + return fileDescriptor_00212fb1f9d3bf1c, []int{104} } func (m *UInt64Value) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6361,7 +7089,7 @@ type FilesystemIdentifier struct { func (m *FilesystemIdentifier) Reset() { *m = FilesystemIdentifier{} } func (*FilesystemIdentifier) ProtoMessage() {} func (*FilesystemIdentifier) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{93} + return fileDescriptor_00212fb1f9d3bf1c, []int{105} } func (m *FilesystemIdentifier) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6418,7 +7146,7 @@ type FilesystemUsage struct { func (m *FilesystemUsage) Reset() { *m = FilesystemUsage{} } func (*FilesystemUsage) ProtoMessage() {} func (*FilesystemUsage) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{94} + return fileDescriptor_00212fb1f9d3bf1c, []int{106} } func (m *FilesystemUsage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6485,7 +7213,7 @@ type ImageFsInfoResponse struct { func (m *ImageFsInfoResponse) Reset() { *m = ImageFsInfoResponse{} } func (*ImageFsInfoResponse) ProtoMessage() {} func (*ImageFsInfoResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{95} + return fileDescriptor_00212fb1f9d3bf1c, []int{107} } func (m *ImageFsInfoResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6531,7 +7259,7 @@ type ContainerStatsRequest struct { func (m *ContainerStatsRequest) Reset() { *m = ContainerStatsRequest{} } func (*ContainerStatsRequest) ProtoMessage() {} func (*ContainerStatsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{96} + return fileDescriptor_00212fb1f9d3bf1c, []int{108} } func (m *ContainerStatsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6577,7 +7305,7 @@ type ContainerStatsResponse struct { func (m *ContainerStatsResponse) Reset() { *m = ContainerStatsResponse{} } func (*ContainerStatsResponse) ProtoMessage() {} func (*ContainerStatsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{97} + return fileDescriptor_00212fb1f9d3bf1c, []int{109} } func (m *ContainerStatsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6623,7 +7351,7 @@ type ListContainerStatsRequest struct { func (m *ListContainerStatsRequest) Reset() { *m = ListContainerStatsRequest{} } func (*ListContainerStatsRequest) ProtoMessage() {} func (*ListContainerStatsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{98} + return fileDescriptor_00212fb1f9d3bf1c, []int{110} } func (m *ListContainerStatsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6677,7 +7405,7 @@ type ContainerStatsFilter struct { func (m *ContainerStatsFilter) Reset() { *m = ContainerStatsFilter{} } func (*ContainerStatsFilter) ProtoMessage() {} func (*ContainerStatsFilter) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{99} + return fileDescriptor_00212fb1f9d3bf1c, []int{111} } func (m *ContainerStatsFilter) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6737,7 +7465,7 @@ type ListContainerStatsResponse struct { func (m *ListContainerStatsResponse) Reset() { *m = ListContainerStatsResponse{} } func (*ListContainerStatsResponse) ProtoMessage() {} func (*ListContainerStatsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{100} + return fileDescriptor_00212fb1f9d3bf1c, []int{112} } func (m *ListContainerStatsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6793,7 +7521,7 @@ type ContainerAttributes struct { func (m *ContainerAttributes) Reset() { *m = ContainerAttributes{} } func (*ContainerAttributes) ProtoMessage() {} func (*ContainerAttributes) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{101} + return fileDescriptor_00212fb1f9d3bf1c, []int{113} } func (m *ContainerAttributes) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6867,7 +7595,7 @@ type ContainerStats struct { func (m *ContainerStats) Reset() { *m = ContainerStats{} } func (*ContainerStats) ProtoMessage() {} func (*ContainerStats) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{102} + return fileDescriptor_00212fb1f9d3bf1c, []int{114} } func (m *ContainerStats) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6930,6 +7658,9 @@ type CpuUsage struct { Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Cumulative CPU usage (sum across all cores) since object creation. UsageCoreNanoSeconds *UInt64Value `protobuf:"bytes,2,opt,name=usage_core_nano_seconds,json=usageCoreNanoSeconds,proto3" json:"usage_core_nano_seconds,omitempty"` + // Total CPU usage (sum of all cores) averaged over the sample window. + // The "core" unit can be interpreted as CPU core-nanoseconds per second. + UsageNanoCores *UInt64Value `protobuf:"bytes,3,opt,name=usage_nano_cores,json=usageNanoCores,proto3" json:"usage_nano_cores,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_sizecache int32 `json:"-"` } @@ -6937,7 +7668,7 @@ type CpuUsage struct { func (m *CpuUsage) Reset() { *m = CpuUsage{} } func (*CpuUsage) ProtoMessage() {} func (*CpuUsage) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{103} + return fileDescriptor_00212fb1f9d3bf1c, []int{115} } func (m *CpuUsage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6980,12 +7711,29 @@ func (m *CpuUsage) GetUsageCoreNanoSeconds() *UInt64Value { return nil } +func (m *CpuUsage) GetUsageNanoCores() *UInt64Value { + if m != nil { + return m.UsageNanoCores + } + return nil +} + // MemoryUsage provides the memory usage information. type MemoryUsage struct { // Timestamp in nanoseconds at which the information were collected. Must be > 0. Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // The amount of working set memory in bytes. - WorkingSetBytes *UInt64Value `protobuf:"bytes,2,opt,name=working_set_bytes,json=workingSetBytes,proto3" json:"working_set_bytes,omitempty"` + WorkingSetBytes *UInt64Value `protobuf:"bytes,2,opt,name=working_set_bytes,json=workingSetBytes,proto3" json:"working_set_bytes,omitempty"` + // Available memory for use. This is defined as the memory limit = workingSetBytes. + AvailableBytes *UInt64Value `protobuf:"bytes,3,opt,name=available_bytes,json=availableBytes,proto3" json:"available_bytes,omitempty"` + // Total memory in use. This includes all memory regardless of when it was accessed. + UsageBytes *UInt64Value `protobuf:"bytes,4,opt,name=usage_bytes,json=usageBytes,proto3" json:"usage_bytes,omitempty"` + // The amount of anonymous and swap cache memory (includes transparent hugepages). + RssBytes *UInt64Value `protobuf:"bytes,5,opt,name=rss_bytes,json=rssBytes,proto3" json:"rss_bytes,omitempty"` + // Cumulative number of minor page faults. + PageFaults *UInt64Value `protobuf:"bytes,6,opt,name=page_faults,json=pageFaults,proto3" json:"page_faults,omitempty"` + // Cumulative number of major page faults. + MajorPageFaults *UInt64Value `protobuf:"bytes,7,opt,name=major_page_faults,json=majorPageFaults,proto3" json:"major_page_faults,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_sizecache int32 `json:"-"` } @@ -6993,7 +7741,7 @@ type MemoryUsage struct { func (m *MemoryUsage) Reset() { *m = MemoryUsage{} } func (*MemoryUsage) ProtoMessage() {} func (*MemoryUsage) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{104} + return fileDescriptor_00212fb1f9d3bf1c, []int{116} } func (m *MemoryUsage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -7036,6 +7784,41 @@ func (m *MemoryUsage) GetWorkingSetBytes() *UInt64Value { return nil } +func (m *MemoryUsage) GetAvailableBytes() *UInt64Value { + if m != nil { + return m.AvailableBytes + } + return nil +} + +func (m *MemoryUsage) GetUsageBytes() *UInt64Value { + if m != nil { + return m.UsageBytes + } + return nil +} + +func (m *MemoryUsage) GetRssBytes() *UInt64Value { + if m != nil { + return m.RssBytes + } + return nil +} + +func (m *MemoryUsage) GetPageFaults() *UInt64Value { + if m != nil { + return m.PageFaults + } + return nil +} + +func (m *MemoryUsage) GetMajorPageFaults() *UInt64Value { + if m != nil { + return m.MajorPageFaults + } + return nil +} + type ReopenContainerLogRequest struct { // ID of the container for which to reopen the log. ContainerId string `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` @@ -7046,7 +7829,7 @@ type ReopenContainerLogRequest struct { func (m *ReopenContainerLogRequest) Reset() { *m = ReopenContainerLogRequest{} } func (*ReopenContainerLogRequest) ProtoMessage() {} func (*ReopenContainerLogRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{105} + return fileDescriptor_00212fb1f9d3bf1c, []int{117} } func (m *ReopenContainerLogRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -7090,7 +7873,7 @@ type ReopenContainerLogResponse struct { func (m *ReopenContainerLogResponse) Reset() { *m = ReopenContainerLogResponse{} } func (*ReopenContainerLogResponse) ProtoMessage() {} func (*ReopenContainerLogResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{106} + return fileDescriptor_00212fb1f9d3bf1c, []int{118} } func (m *ReopenContainerLogResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -7165,6 +7948,21 @@ func init() { proto.RegisterMapType((map[string]string)(nil), "runtime.v1alpha2.PodSandbox.AnnotationsEntry") proto.RegisterMapType((map[string]string)(nil), "runtime.v1alpha2.PodSandbox.LabelsEntry") proto.RegisterType((*ListPodSandboxResponse)(nil), "runtime.v1alpha2.ListPodSandboxResponse") + proto.RegisterType((*PodSandboxStatsRequest)(nil), "runtime.v1alpha2.PodSandboxStatsRequest") + proto.RegisterType((*PodSandboxStatsResponse)(nil), "runtime.v1alpha2.PodSandboxStatsResponse") + proto.RegisterType((*PodSandboxStatsFilter)(nil), "runtime.v1alpha2.PodSandboxStatsFilter") + proto.RegisterMapType((map[string]string)(nil), "runtime.v1alpha2.PodSandboxStatsFilter.LabelSelectorEntry") + proto.RegisterType((*ListPodSandboxStatsRequest)(nil), "runtime.v1alpha2.ListPodSandboxStatsRequest") + proto.RegisterType((*ListPodSandboxStatsResponse)(nil), "runtime.v1alpha2.ListPodSandboxStatsResponse") + proto.RegisterType((*PodSandboxAttributes)(nil), "runtime.v1alpha2.PodSandboxAttributes") + proto.RegisterMapType((map[string]string)(nil), "runtime.v1alpha2.PodSandboxAttributes.AnnotationsEntry") + proto.RegisterMapType((map[string]string)(nil), "runtime.v1alpha2.PodSandboxAttributes.LabelsEntry") + proto.RegisterType((*PodSandboxStats)(nil), "runtime.v1alpha2.PodSandboxStats") + proto.RegisterType((*LinuxPodSandboxStats)(nil), "runtime.v1alpha2.LinuxPodSandboxStats") + proto.RegisterType((*WindowsPodSandboxStats)(nil), "runtime.v1alpha2.WindowsPodSandboxStats") + proto.RegisterType((*NetworkUsage)(nil), "runtime.v1alpha2.NetworkUsage") + proto.RegisterType((*NetworkInterfaceUsage)(nil), "runtime.v1alpha2.NetworkInterfaceUsage") + proto.RegisterType((*ProcessUsage)(nil), "runtime.v1alpha2.ProcessUsage") proto.RegisterType((*ImageSpec)(nil), "runtime.v1alpha2.ImageSpec") proto.RegisterMapType((map[string]string)(nil), "runtime.v1alpha2.ImageSpec.AnnotationsEntry") proto.RegisterType((*KeyValue)(nil), "runtime.v1alpha2.KeyValue") @@ -7263,329 +8061,359 @@ func init() { func init() { proto.RegisterFile("api.proto", fileDescriptor_00212fb1f9d3bf1c) } var fileDescriptor_00212fb1f9d3bf1c = []byte{ - // 5147 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x7c, 0x4d, 0x6c, 0x1b, 0x59, - 0x72, 0xb0, 0x9a, 0xa4, 0x24, 0xb2, 0x28, 0x52, 0xd4, 0xb3, 0x6c, 0xd1, 0xf4, 0xd8, 0x63, 0xb5, - 0xc7, 0xbf, 0x33, 0x96, 0xd7, 0x9a, 0x59, 0xcf, 0x67, 0x7b, 0xc6, 0x63, 0x59, 0x92, 0x6d, 0x7e, - 0x6b, 0x53, 0x4c, 0x53, 0x9a, 0x9f, 0x9d, 0x01, 0x7a, 0x5b, 0xec, 0x27, 0xaa, 0xd7, 0x64, 0x77, - 0x4f, 0x77, 0xd3, 0xb2, 0x36, 0x40, 0xb0, 0xc0, 0x02, 0x7b, 0xc8, 0x29, 0x40, 0x90, 0x4b, 0x6e, - 0xd9, 0x1c, 0x72, 0xc8, 0x29, 0x08, 0x72, 0xca, 0x69, 0x83, 0x1c, 0x16, 0x01, 0x82, 0xe4, 0xb4, - 0x48, 0x90, 0x4b, 0x66, 0x82, 0x00, 0x8b, 0x00, 0x01, 0x82, 0x9c, 0x73, 0x08, 0xde, 0x5f, 0xff, - 0x37, 0x7f, 0x6c, 0xcf, 0xce, 0xe4, 0xc4, 0x7e, 0xd5, 0x55, 0xf5, 0xea, 0xd5, 0xab, 0x57, 0xaf, - 0x5e, 0xd5, 0x6b, 0x42, 0x49, 0xb3, 0x8d, 0x35, 0xdb, 0xb1, 0x3c, 0x0b, 0xd5, 0x9c, 0xa1, 0xe9, - 0x19, 0x03, 0xbc, 0xf6, 0xfc, 0xa6, 0xd6, 0xb7, 0x0f, 0xb5, 0xf5, 0xc6, 0xf5, 0x9e, 0xe1, 0x1d, - 0x0e, 0xf7, 0xd7, 0xba, 0xd6, 0xe0, 0x46, 0xcf, 0xea, 0x59, 0x37, 0x28, 0xe2, 0xfe, 0xf0, 0x80, - 0xb6, 0x68, 0x83, 0x3e, 0x31, 0x06, 0xf2, 0x35, 0xa8, 0x7e, 0x8c, 0x1d, 0xd7, 0xb0, 0x4c, 0x05, - 0x7f, 0x39, 0xc4, 0xae, 0x87, 0xea, 0x30, 0xff, 0x9c, 0x41, 0xea, 0xd2, 0x79, 0xe9, 0x4a, 0x49, - 0x11, 0x4d, 0xf9, 0xcf, 0x24, 0x58, 0xf4, 0x91, 0x5d, 0xdb, 0x32, 0x5d, 0x9c, 0x8d, 0x8d, 0x56, - 0x61, 0x81, 0x0b, 0xa7, 0x9a, 0xda, 0x00, 0xd7, 0x73, 0xf4, 0x75, 0x99, 0xc3, 0x5a, 0xda, 0x00, - 0xa3, 0xcb, 0xb0, 0x28, 0x50, 0x04, 0x93, 0x3c, 0xc5, 0xaa, 0x72, 0x30, 0xef, 0x0d, 0xad, 0xc1, - 0x09, 0x81, 0xa8, 0xd9, 0x86, 0x8f, 0x5c, 0xa0, 0xc8, 0x4b, 0xfc, 0xd5, 0x86, 0x6d, 0x70, 0x7c, - 0xf9, 0x73, 0x28, 0x6d, 0xb5, 0x3a, 0x9b, 0x96, 0x79, 0x60, 0xf4, 0x88, 0x88, 0x2e, 0x76, 0x08, - 0x4d, 0x5d, 0x3a, 0x9f, 0x27, 0x22, 0xf2, 0x26, 0x6a, 0x40, 0xd1, 0xc5, 0x9a, 0xd3, 0x3d, 0xc4, - 0x6e, 0x3d, 0x47, 0x5f, 0xf9, 0x6d, 0x42, 0x65, 0xd9, 0x9e, 0x61, 0x99, 0x6e, 0x3d, 0xcf, 0xa8, - 0x78, 0x53, 0xfe, 0x85, 0x04, 0xe5, 0xb6, 0xe5, 0x78, 0x4f, 0x35, 0xdb, 0x36, 0xcc, 0x1e, 0xba, - 0x05, 0x45, 0xaa, 0xcb, 0xae, 0xd5, 0xa7, 0x3a, 0xa8, 0xae, 0x37, 0xd6, 0xe2, 0xd3, 0xb2, 0xd6, - 0xe6, 0x18, 0x8a, 0x8f, 0x8b, 0x2e, 0x42, 0xb5, 0x6b, 0x99, 0x9e, 0x66, 0x98, 0xd8, 0x51, 0x6d, - 0xcb, 0xf1, 0xa8, 0x8a, 0x66, 0x95, 0x8a, 0x0f, 0x25, 0xbd, 0xa0, 0x33, 0x50, 0x3a, 0xb4, 0x5c, - 0x8f, 0x61, 0xe4, 0x29, 0x46, 0x91, 0x00, 0xe8, 0xcb, 0x15, 0x98, 0xa7, 0x2f, 0x0d, 0x9b, 0x2b, - 0x63, 0x8e, 0x34, 0x9b, 0xb6, 0xfc, 0x6b, 0x09, 0x66, 0x9f, 0x5a, 0x43, 0xd3, 0x8b, 0x75, 0xa3, - 0x79, 0x87, 0x7c, 0xa2, 0x42, 0xdd, 0x68, 0xde, 0x61, 0xd0, 0x0d, 0xc1, 0x60, 0x73, 0xc5, 0xba, - 0x21, 0x2f, 0x1b, 0x50, 0x74, 0xb0, 0xa6, 0x5b, 0x66, 0xff, 0x98, 0x8a, 0x50, 0x54, 0xfc, 0x36, - 0x99, 0x44, 0x17, 0xf7, 0x0d, 0x73, 0xf8, 0x42, 0x75, 0x70, 0x5f, 0xdb, 0xc7, 0x7d, 0x2a, 0x4a, - 0x51, 0xa9, 0x72, 0xb0, 0xc2, 0xa0, 0x68, 0x0b, 0xca, 0xb6, 0x63, 0xd9, 0x5a, 0x4f, 0x23, 0x7a, - 0xac, 0xcf, 0x52, 0x55, 0xc9, 0x49, 0x55, 0x51, 0xb1, 0xdb, 0x01, 0xa6, 0x12, 0x26, 0x93, 0xff, - 0x41, 0x82, 0x45, 0x62, 0x3c, 0xae, 0xad, 0x75, 0xf1, 0x0e, 0x9d, 0x12, 0x74, 0x1b, 0xe6, 0x4d, - 0xec, 0x1d, 0x59, 0xce, 0x33, 0x3e, 0x01, 0x6f, 0x26, 0xb9, 0xfa, 0x34, 0x4f, 0x2d, 0x1d, 0x2b, - 0x02, 0x1f, 0xdd, 0x84, 0xbc, 0x6d, 0xe8, 0x74, 0xc0, 0x13, 0x90, 0x11, 0x5c, 0x42, 0x62, 0xd8, - 0x5d, 0xaa, 0x87, 0x49, 0x48, 0x0c, 0xbb, 0x4b, 0x94, 0xeb, 0x69, 0x4e, 0x0f, 0x7b, 0xaa, 0xa1, - 0xf3, 0x89, 0x2a, 0x32, 0x40, 0x53, 0x97, 0x65, 0x80, 0xa6, 0xe9, 0xdd, 0x7a, 0xef, 0x63, 0xad, - 0x3f, 0xc4, 0x68, 0x19, 0x66, 0x9f, 0x93, 0x07, 0x3a, 0x92, 0xbc, 0xc2, 0x1a, 0xf2, 0x57, 0x05, - 0x38, 0xf3, 0x84, 0x28, 0xb3, 0xa3, 0x99, 0xfa, 0xbe, 0xf5, 0xa2, 0x83, 0xbb, 0x43, 0xc7, 0xf0, - 0x8e, 0x37, 0x2d, 0xd3, 0xc3, 0x2f, 0x3c, 0xd4, 0x82, 0x25, 0x53, 0x74, 0xab, 0x0a, 0xbb, 0x25, - 0x1c, 0xca, 0xeb, 0xab, 0x23, 0x24, 0x64, 0xfa, 0x53, 0x6a, 0x66, 0x14, 0xe0, 0xa2, 0xc7, 0xc1, - 0xa4, 0x0a, 0x6e, 0x39, 0xca, 0x2d, 0x65, 0xbc, 0x9d, 0x6d, 0x2a, 0x19, 0xe7, 0x25, 0x66, 0x5d, - 0x70, 0xfa, 0x00, 0xc8, 0x92, 0x57, 0x35, 0x57, 0x1d, 0xba, 0xd8, 0xa1, 0x5a, 0x2b, 0xaf, 0xbf, - 0x91, 0xe4, 0x12, 0xa8, 0x40, 0x29, 0x39, 0x43, 0x73, 0xc3, 0xdd, 0x73, 0xb1, 0x83, 0xee, 0x51, - 0x27, 0x42, 0xa8, 0x7b, 0x8e, 0x35, 0xb4, 0xeb, 0xc5, 0x09, 0xc8, 0x81, 0x92, 0x3f, 0x22, 0xf8, - 0xd4, 0xc3, 0x70, 0x43, 0x55, 0x1d, 0xcb, 0xf2, 0x0e, 0x5c, 0x61, 0x9c, 0x02, 0xac, 0x50, 0x28, - 0xba, 0x01, 0x27, 0xdc, 0xa1, 0x6d, 0xf7, 0xf1, 0x00, 0x9b, 0x9e, 0xd6, 0x67, 0xdd, 0xb9, 0xf5, - 0xd9, 0xf3, 0xf9, 0x2b, 0x79, 0x05, 0x85, 0x5f, 0x51, 0xc6, 0x2e, 0x3a, 0x07, 0x60, 0x3b, 0xc6, - 0x73, 0xa3, 0x8f, 0x7b, 0x58, 0xaf, 0xcf, 0x51, 0xa6, 0x21, 0x08, 0xba, 0x4b, 0xbc, 0x4e, 0xb7, - 0x6b, 0x0d, 0xec, 0x7a, 0x29, 0x6b, 0x1e, 0xc4, 0x2c, 0xb6, 0x1d, 0xeb, 0xc0, 0xe8, 0x63, 0x45, - 0x50, 0xa0, 0x0f, 0xa1, 0xa8, 0xd9, 0xb6, 0xe6, 0x0c, 0x2c, 0xa7, 0x0e, 0x93, 0x52, 0xfb, 0x24, - 0xe8, 0x3d, 0x58, 0xe6, 0x9c, 0x54, 0x9b, 0xbd, 0x64, 0xcb, 0x7a, 0x9e, 0x58, 0xde, 0x83, 0x5c, - 0x5d, 0x52, 0x10, 0x7f, 0xcf, 0x69, 0xc9, 0x22, 0x97, 0xff, 0x4e, 0x82, 0xc5, 0x18, 0x4f, 0xd4, - 0x86, 0x05, 0xc1, 0xc1, 0x3b, 0xb6, 0x31, 0x5f, 0x5e, 0xd7, 0xc7, 0x0a, 0xb3, 0xc6, 0x7f, 0x77, - 0x8f, 0x6d, 0x4c, 0xd7, 0xaf, 0x68, 0xa0, 0x0b, 0x50, 0xe9, 0x5b, 0x5d, 0xad, 0x4f, 0x9d, 0x8d, - 0x83, 0x0f, 0xb8, 0xaf, 0x59, 0xf0, 0x81, 0x0a, 0x3e, 0x90, 0xef, 0x43, 0x39, 0xc4, 0x00, 0x21, - 0xa8, 0x2a, 0xac, 0xc3, 0x2d, 0x7c, 0xa0, 0x0d, 0xfb, 0x5e, 0x6d, 0x06, 0x55, 0x01, 0xf6, 0xcc, - 0x2e, 0xf1, 0xf0, 0x26, 0xd6, 0x6b, 0x12, 0xaa, 0x40, 0xe9, 0x89, 0x60, 0x51, 0xcb, 0xc9, 0xbf, - 0xc8, 0xc1, 0x49, 0x6a, 0x96, 0x6d, 0x4b, 0xe7, 0x6b, 0x86, 0x6f, 0x07, 0x17, 0xa0, 0xd2, 0xa5, - 0xb3, 0xab, 0xda, 0x9a, 0x83, 0x4d, 0x8f, 0xbb, 0xc3, 0x05, 0x06, 0x6c, 0x53, 0x18, 0xfa, 0x14, - 0x6a, 0x2e, 0x1f, 0x91, 0xda, 0x65, 0x6b, 0x8c, 0x2f, 0x80, 0x94, 0xb1, 0x8f, 0x58, 0x98, 0xca, - 0xa2, 0x9b, 0x58, 0xa9, 0xf3, 0xee, 0xb1, 0xdb, 0xf5, 0xfa, 0x6c, 0x5f, 0x29, 0xaf, 0xbf, 0x97, - 0xc1, 0x30, 0x2e, 0xf8, 0x5a, 0x87, 0x91, 0x6d, 0x9b, 0x9e, 0x73, 0xac, 0x08, 0x26, 0x8d, 0x3b, - 0xb0, 0x10, 0x7e, 0x81, 0x6a, 0x90, 0x7f, 0x86, 0x8f, 0xf9, 0xa0, 0xc8, 0x63, 0xe0, 0x51, 0x98, - 0xa6, 0x59, 0xe3, 0x4e, 0xee, 0xff, 0x49, 0xb2, 0x03, 0x28, 0xe8, 0xe5, 0x29, 0xf6, 0x34, 0x5d, - 0xf3, 0x34, 0x84, 0xa0, 0x40, 0x37, 0x6c, 0xc6, 0x82, 0x3e, 0x13, 0xae, 0x43, 0xee, 0x26, 0x4b, - 0x0a, 0x79, 0x44, 0x6f, 0x40, 0xc9, 0xf7, 0x1a, 0x7c, 0xd7, 0x0e, 0x00, 0x64, 0xf7, 0xd4, 0x3c, - 0x0f, 0x0f, 0x6c, 0x8f, 0xae, 0xb7, 0x8a, 0x22, 0x9a, 0xf2, 0x5f, 0xce, 0x42, 0x2d, 0x31, 0x27, - 0xf7, 0xa1, 0x38, 0xe0, 0xdd, 0x73, 0xaf, 0xf5, 0x56, 0xca, 0x16, 0x9a, 0x10, 0x55, 0xf1, 0xa9, - 0xc8, 0x0e, 0x45, 0x66, 0x3e, 0x14, 0x69, 0xf8, 0x6d, 0x66, 0x72, 0x3d, 0x55, 0x37, 0x1c, 0xdc, - 0xf5, 0x2c, 0xe7, 0x98, 0x8b, 0xbb, 0xd0, 0xb7, 0x7a, 0x5b, 0x02, 0x86, 0xee, 0x00, 0xe8, 0xa6, - 0xab, 0x52, 0x8b, 0xea, 0x51, 0xa1, 0xcb, 0xeb, 0x67, 0x92, 0x42, 0xf8, 0x61, 0x85, 0x52, 0xd2, - 0x4d, 0x97, 0x8b, 0xff, 0x00, 0x2a, 0x64, 0x77, 0x56, 0x07, 0x2c, 0x22, 0x60, 0x6e, 0xa3, 0xbc, - 0x7e, 0x36, 0x6d, 0x0c, 0x7e, 0xdc, 0xa0, 0x2c, 0xd8, 0x41, 0xc3, 0x45, 0x0f, 0x61, 0x8e, 0x6e, - 0x93, 0x6e, 0x7d, 0x8e, 0x12, 0xaf, 0x8d, 0x52, 0x00, 0xb7, 0x88, 0x27, 0x94, 0x80, 0x19, 0x04, - 0xa7, 0x46, 0x7b, 0x50, 0xd6, 0x4c, 0xd3, 0xf2, 0x34, 0xe6, 0xb5, 0xe7, 0x29, 0xb3, 0x77, 0x27, - 0x60, 0xb6, 0x11, 0x50, 0x31, 0x8e, 0x61, 0x3e, 0xe8, 0x43, 0x98, 0xa5, 0x6e, 0x9d, 0x7b, 0xe0, - 0xcb, 0x13, 0x1a, 0xad, 0xc2, 0xa8, 0xd0, 0x26, 0xcc, 0x1f, 0x19, 0xa6, 0x6e, 0x1d, 0xb9, 0xdc, - 0x1b, 0x5e, 0x4d, 0x32, 0xf8, 0x84, 0x21, 0x24, 0x58, 0x08, 0xca, 0xc6, 0x6d, 0x28, 0x87, 0x46, - 0x3c, 0x8d, 0xa5, 0x37, 0xee, 0x41, 0x2d, 0x3e, 0xbe, 0xa9, 0x56, 0xca, 0xef, 0xc2, 0xb2, 0x32, - 0x34, 0x03, 0xd1, 0x44, 0xb0, 0x7c, 0x07, 0xe6, 0xb8, 0xc5, 0x30, 0xb3, 0x95, 0xc7, 0x2b, 0x5a, - 0xe1, 0x14, 0xe1, 0xe8, 0xf7, 0x50, 0x33, 0xf5, 0x3e, 0x76, 0x78, 0xbf, 0x22, 0xfa, 0x7d, 0xcc, - 0xa0, 0xf2, 0x87, 0x70, 0x32, 0xd6, 0x39, 0x0f, 0xbe, 0xdf, 0x82, 0xaa, 0x6d, 0xe9, 0xaa, 0xcb, - 0xc0, 0x24, 0xb6, 0xe0, 0xbe, 0xcc, 0xf6, 0x71, 0x9b, 0x3a, 0x21, 0xef, 0x78, 0x96, 0x9d, 0x14, - 0x7e, 0x32, 0xf2, 0x3a, 0x9c, 0x8a, 0x93, 0xb3, 0xee, 0xe5, 0x8f, 0x60, 0x45, 0xc1, 0x03, 0xeb, - 0x39, 0x7e, 0x59, 0xd6, 0x0d, 0xa8, 0x27, 0x19, 0x70, 0xe6, 0x9f, 0xc1, 0x4a, 0x00, 0xed, 0x78, - 0x9a, 0x37, 0x74, 0xa7, 0x62, 0xce, 0x4f, 0x26, 0xfb, 0x96, 0xcb, 0xa6, 0xb3, 0xa8, 0x88, 0xa6, - 0xbc, 0x02, 0xb3, 0x6d, 0x4b, 0x6f, 0xb6, 0x51, 0x15, 0x72, 0x86, 0xcd, 0x89, 0x73, 0x86, 0x2d, - 0x1b, 0xe1, 0x3e, 0x5b, 0x2c, 0x42, 0x64, 0x5d, 0xc7, 0x51, 0xd1, 0x3d, 0xa8, 0x6a, 0xba, 0x6e, - 0x10, 0x73, 0xd2, 0xfa, 0xaa, 0x61, 0xb3, 0x03, 0x44, 0x79, 0x7d, 0x25, 0xd5, 0x00, 0x9a, 0x6d, - 0xa5, 0x12, 0xa0, 0x37, 0x6d, 0x57, 0x7e, 0x0c, 0x25, 0x3f, 0x0a, 0x23, 0xb1, 0x42, 0x34, 0xca, - 0x9a, 0x20, 0x66, 0xf3, 0x8f, 0x23, 0xbb, 0x89, 0x8d, 0x8e, 0x8b, 0x7c, 0x17, 0xc0, 0x77, 0xc8, - 0x22, 0x18, 0x3c, 0x33, 0x82, 0xb1, 0x12, 0x42, 0x97, 0x7f, 0x16, 0x71, 0xd3, 0x21, 0x25, 0xe8, - 0xbe, 0x12, 0xf4, 0x88, 0xdb, 0xce, 0xbd, 0x94, 0xdb, 0x7e, 0x1f, 0x66, 0x5d, 0x4f, 0xf3, 0x30, - 0x8f, 0xa6, 0x57, 0x47, 0x91, 0x13, 0x21, 0xb0, 0xc2, 0xf0, 0xd1, 0x59, 0x80, 0xae, 0x83, 0x35, - 0x0f, 0xeb, 0xaa, 0xc6, 0xf6, 0x98, 0xbc, 0x52, 0xe2, 0x90, 0x0d, 0x8f, 0xf8, 0x1b, 0x71, 0x22, - 0x98, 0xcd, 0xf2, 0x37, 0x19, 0x53, 0x1d, 0x9c, 0x0d, 0x7c, 0x9f, 0x37, 0x37, 0xa1, 0xcf, 0xe3, - 0x0c, 0xb8, 0xcf, 0x0b, 0x3c, 0xfa, 0xfc, 0x78, 0x8f, 0xce, 0x48, 0x27, 0xf1, 0xe8, 0xc5, 0xf1, - 0x1e, 0x9d, 0x33, 0x1b, 0xed, 0xd1, 0x53, 0xdc, 0x4f, 0x29, 0xcd, 0xfd, 0x7c, 0x9b, 0x6e, 0xf7, - 0x9f, 0x25, 0xa8, 0x27, 0xbd, 0x00, 0xf7, 0x7e, 0x77, 0x60, 0xce, 0xa5, 0x90, 0x49, 0x7c, 0x2f, - 0xa7, 0xe5, 0x14, 0xe8, 0x31, 0x14, 0x0c, 0xf3, 0xc0, 0xe2, 0x8b, 0xf6, 0xbd, 0x09, 0x28, 0x79, - 0xaf, 0x6b, 0x4d, 0xf3, 0xc0, 0x62, 0xda, 0xa4, 0x1c, 0x1a, 0xef, 0x43, 0xc9, 0x07, 0x4d, 0x35, - 0xb6, 0x1d, 0x58, 0x8e, 0xd9, 0x36, 0x3b, 0x00, 0xfa, 0x4b, 0x42, 0x9a, 0x6e, 0x49, 0xc8, 0x3f, - 0xcd, 0x85, 0x97, 0xec, 0x43, 0xa3, 0xef, 0x61, 0x27, 0xb1, 0x64, 0x3f, 0x10, 0xdc, 0xd9, 0x7a, - 0xbd, 0x34, 0x96, 0x3b, 0x3b, 0x53, 0xf1, 0x55, 0xf7, 0x05, 0x54, 0xa9, 0x51, 0xaa, 0x2e, 0xee, - 0xd3, 0xb8, 0x89, 0xc7, 0xb0, 0xdf, 0x1f, 0xc5, 0x86, 0x49, 0xc2, 0x4c, 0xbb, 0xc3, 0xe9, 0x98, - 0x06, 0x2b, 0xfd, 0x30, 0xac, 0x71, 0x1f, 0x50, 0x12, 0x69, 0x2a, 0x9d, 0x76, 0x88, 0x2f, 0x74, - 0xbd, 0xd4, 0x7d, 0xfa, 0x80, 0x8a, 0x31, 0x89, 0xad, 0x30, 0x81, 0x15, 0x4e, 0x21, 0xff, 0x67, - 0x1e, 0x20, 0x78, 0xf9, 0x7f, 0xc8, 0x09, 0xde, 0xf7, 0x1d, 0x10, 0x8b, 0x47, 0xaf, 0x8c, 0x62, - 0x9c, 0xea, 0x7a, 0x76, 0xa2, 0xae, 0x87, 0x45, 0xa6, 0xd7, 0x47, 0xb2, 0x99, 0xda, 0xe9, 0xcc, - 0x7f, 0xd7, 0x9c, 0xce, 0x13, 0x38, 0x15, 0x37, 0x22, 0xee, 0x71, 0xd6, 0x61, 0xd6, 0xf0, 0xf0, - 0x80, 0xe5, 0x11, 0x53, 0xd3, 0x10, 0x21, 0x22, 0x86, 0x2a, 0xff, 0x85, 0x04, 0xa5, 0xe6, 0x40, - 0xeb, 0xe1, 0x8e, 0x8d, 0xbb, 0xa4, 0x57, 0x83, 0x34, 0xb8, 0x24, 0xac, 0x81, 0x5a, 0x51, 0x35, - 0x33, 0xa7, 0xf4, 0x4e, 0x4a, 0x92, 0x43, 0xf0, 0x19, 0xad, 0xe5, 0x57, 0xd6, 0xc0, 0x3a, 0x14, - 0x7f, 0x80, 0x8f, 0x99, 0x3b, 0x9a, 0x90, 0x4e, 0xfe, 0x93, 0x02, 0xac, 0xd0, 0xed, 0x70, 0x53, - 0xa4, 0x15, 0x15, 0xec, 0x5a, 0x43, 0xa7, 0x8b, 0x5d, 0x6a, 0xa7, 0xf6, 0x50, 0xb5, 0xb1, 0x63, - 0x58, 0x3a, 0x4f, 0x6c, 0x95, 0xba, 0xf6, 0xb0, 0x4d, 0x01, 0xe8, 0x0c, 0x90, 0x86, 0xfa, 0xe5, - 0xd0, 0xe2, 0x4b, 0x28, 0xaf, 0x14, 0xbb, 0xf6, 0xf0, 0x77, 0x48, 0x5b, 0xd0, 0xba, 0x87, 0x9a, - 0x83, 0x5d, 0xba, 0x42, 0x18, 0x6d, 0x87, 0x02, 0xd0, 0x4d, 0x38, 0x39, 0xc0, 0x03, 0xcb, 0x39, - 0x56, 0xfb, 0xc6, 0xc0, 0xf0, 0x54, 0xc3, 0x54, 0xf7, 0x8f, 0x3d, 0xec, 0xf2, 0xd5, 0x80, 0xd8, - 0xcb, 0x27, 0xe4, 0x5d, 0xd3, 0x7c, 0x40, 0xde, 0x20, 0x19, 0x2a, 0x96, 0x35, 0x50, 0xdd, 0xae, - 0xe5, 0x60, 0x55, 0xd3, 0x7f, 0x4c, 0x23, 0x84, 0xbc, 0x52, 0xb6, 0xac, 0x41, 0x87, 0xc0, 0x36, - 0xf4, 0x1f, 0xa3, 0x37, 0xa1, 0xdc, 0xb5, 0x87, 0x2e, 0xf6, 0x54, 0xf2, 0x43, 0x03, 0x80, 0x92, - 0x02, 0x0c, 0xb4, 0x69, 0x0f, 0xdd, 0x10, 0xc2, 0x80, 0x18, 0xc4, 0x7c, 0x18, 0xe1, 0x29, 0x1e, - 0xd0, 0x0c, 0xda, 0xe1, 0xb0, 0x87, 0x6d, 0xad, 0x87, 0x99, 0x68, 0x62, 0xe7, 0x4e, 0xc9, 0xa0, - 0x3d, 0xe6, 0x88, 0x54, 0x4c, 0xa5, 0x7a, 0x18, 0x6e, 0xba, 0xa8, 0x0d, 0xf3, 0x43, 0xd3, 0x38, - 0x30, 0xb0, 0x5e, 0x2f, 0x51, 0x0e, 0xb7, 0x32, 0x02, 0x91, 0xa4, 0xe6, 0xd7, 0xf6, 0x18, 0x21, - 0xcf, 0x19, 0x70, 0x36, 0xe8, 0x0e, 0x34, 0xb8, 0xd2, 0xdc, 0x23, 0xcd, 0x8e, 0x6b, 0x0e, 0xa8, - 0x3a, 0x4e, 0x31, 0x8c, 0xce, 0x91, 0x66, 0x87, 0xb5, 0xd7, 0xb8, 0x03, 0x0b, 0x61, 0xa6, 0x53, - 0xd9, 0xd5, 0x03, 0xa8, 0x44, 0x86, 0x4a, 0x66, 0x9e, 0x2a, 0xc8, 0x35, 0x7e, 0x22, 0x96, 0x44, - 0x91, 0x00, 0x3a, 0xc6, 0x4f, 0x68, 0x26, 0x94, 0x4a, 0x46, 0xf9, 0x14, 0x14, 0xd6, 0x90, 0x35, - 0xa8, 0x44, 0x12, 0x8e, 0x08, 0x41, 0x81, 0x66, 0x16, 0x79, 0xba, 0x82, 0x3c, 0x13, 0x98, 0x63, - 0xf5, 0x85, 0x04, 0xf4, 0x99, 0xc0, 0x68, 0x0a, 0x8b, 0x1d, 0xfe, 0xe9, 0x33, 0xed, 0x02, 0x3f, - 0xe7, 0x19, 0xeb, 0x92, 0xc2, 0x1a, 0xb2, 0x0e, 0xb0, 0xa9, 0xd9, 0xda, 0xbe, 0xd1, 0x37, 0xbc, - 0x63, 0x74, 0x15, 0x6a, 0x9a, 0xae, 0xab, 0x5d, 0x01, 0x31, 0xb0, 0xa8, 0x23, 0x2c, 0x6a, 0xba, - 0xbe, 0x19, 0x02, 0xa3, 0xb7, 0x61, 0x49, 0x77, 0x2c, 0x3b, 0x8a, 0xcb, 0x0a, 0x0b, 0x35, 0xf2, - 0x22, 0x8c, 0x2c, 0xff, 0x66, 0x0e, 0xce, 0x46, 0xa7, 0x2d, 0x9e, 0xd4, 0xbd, 0x0f, 0x0b, 0xb1, - 0x5e, 0x33, 0x92, 0x9f, 0x81, 0xb4, 0x4a, 0x84, 0x22, 0x96, 0xa4, 0xcc, 0x25, 0x92, 0x94, 0xa9, - 0x69, 0xe3, 0xfc, 0x6b, 0x4d, 0x1b, 0x17, 0x5e, 0x4b, 0xda, 0x78, 0xf6, 0xd5, 0xd2, 0xc6, 0x0b, - 0x53, 0xa6, 0x8d, 0x2f, 0xd1, 0x6d, 0x4a, 0xf4, 0x4e, 0x93, 0x4a, 0xcc, 0x05, 0x54, 0xfc, 0x3e, - 0x4c, 0x51, 0xc0, 0x8a, 0xa5, 0x97, 0xe7, 0xa7, 0x49, 0x2f, 0x17, 0x33, 0xd3, 0xcb, 0xe7, 0x61, - 0xc1, 0xb4, 0x54, 0x13, 0x1f, 0xa9, 0x64, 0xba, 0xdc, 0x7a, 0x99, 0xcd, 0x9d, 0x69, 0xb5, 0xf0, - 0x51, 0x9b, 0x40, 0xd0, 0x2a, 0x2c, 0x0c, 0x34, 0xf7, 0x19, 0xd6, 0x69, 0x6e, 0xd7, 0xad, 0x57, - 0xa8, 0x9d, 0x95, 0x19, 0xac, 0x4d, 0x40, 0xe8, 0x22, 0xf8, 0x72, 0x70, 0xa4, 0x2a, 0x45, 0xaa, - 0x08, 0x28, 0x43, 0x0b, 0xa5, 0xaa, 0x17, 0x5f, 0x29, 0x55, 0x5d, 0x9b, 0x3e, 0x55, 0x7d, 0x1d, - 0x6a, 0xe2, 0x59, 0xe4, 0xaa, 0xd9, 0x31, 0x84, 0xa6, 0xa9, 0x17, 0xc5, 0x3b, 0x91, 0x8f, 0xce, - 0xca, 0x6c, 0xc3, 0xc8, 0xcc, 0xf6, 0x5f, 0x4b, 0xb0, 0x1c, 0x5d, 0x6a, 0x3c, 0x71, 0xf7, 0x08, - 0x4a, 0x8e, 0xf0, 0x95, 0x7c, 0x79, 0x5d, 0x9d, 0xd8, 0xb9, 0x2a, 0x01, 0x2d, 0xfa, 0x61, 0x66, - 0xbe, 0xf8, 0xc6, 0x38, 0x7e, 0xe3, 0x32, 0xc6, 0xf2, 0x1f, 0x4a, 0x70, 0x96, 0xe7, 0xc6, 0x32, - 0xaa, 0x3f, 0x29, 0xe6, 0x2a, 0x65, 0x98, 0x6b, 0xd7, 0xc1, 0x3a, 0x36, 0x3d, 0x43, 0xeb, 0xab, - 0xae, 0x8d, 0xbb, 0x22, 0xe3, 0x14, 0x80, 0x69, 0x98, 0xb2, 0x0a, 0x0b, 0xac, 0x18, 0xe8, 0x58, - 0x5d, 0xec, 0xba, 0xbc, 0xe6, 0x57, 0xa6, 0xf5, 0x40, 0x06, 0x92, 0x87, 0xb0, 0x92, 0x91, 0xb0, - 0x4b, 0x55, 0x86, 0x94, 0xa5, 0x8c, 0x91, 0x23, 0x4b, 0x2a, 0xe3, 0x8f, 0x24, 0x78, 0x93, 0x93, - 0x64, 0xfa, 0xcd, 0x6f, 0x43, 0x1d, 0xbf, 0x94, 0xe0, 0x54, 0x5c, 0x2e, 0xae, 0x8e, 0x66, 0xd2, - 0xc8, 0xde, 0xce, 0xd4, 0xc3, 0x68, 0x33, 0xfb, 0x22, 0xd3, 0xcc, 0x6e, 0x8e, 0xe7, 0x38, 0x56, - 0xb7, 0x7f, 0x2e, 0xc1, 0xe9, 0x4c, 0x31, 0x62, 0x81, 0x98, 0x14, 0x0f, 0xc4, 0x78, 0x10, 0xd7, - 0xb5, 0x86, 0xa6, 0x17, 0x0a, 0xe2, 0x36, 0x69, 0x0d, 0x9a, 0x45, 0x4b, 0xea, 0x40, 0x7b, 0x61, - 0x0c, 0x86, 0x03, 0x1e, 0xc5, 0x11, 0x76, 0x4f, 0x19, 0xe4, 0x25, 0xc2, 0x38, 0x79, 0x03, 0x96, - 0x7c, 0x29, 0x47, 0xd6, 0x2e, 0x42, 0xb5, 0x88, 0x5c, 0xb4, 0x16, 0x61, 0xc2, 0xdc, 0x16, 0x7e, - 0x6e, 0x74, 0xf1, 0x6b, 0x29, 0x92, 0x9f, 0x87, 0xb2, 0x8d, 0x9d, 0x81, 0xe1, 0xba, 0xfe, 0x36, - 0x5a, 0x52, 0xc2, 0x20, 0xf9, 0xdf, 0xe7, 0x60, 0x31, 0x6e, 0x1d, 0x1f, 0x25, 0x4a, 0x1f, 0x17, - 0x52, 0x36, 0xf8, 0xf8, 0x40, 0x43, 0xa7, 0xc7, 0x9b, 0xe2, 0x48, 0x91, 0xcb, 0xca, 0xf0, 0xf9, - 0xc7, 0x06, 0x71, 0xde, 0xa8, 0xc3, 0x7c, 0xd7, 0x1a, 0x0c, 0x34, 0x53, 0x17, 0x77, 0x1b, 0x78, - 0x93, 0xe8, 0x4f, 0x73, 0x7a, 0x44, 0xed, 0x04, 0x4c, 0x9f, 0xc9, 0xe4, 0x1d, 0x59, 0xce, 0x33, - 0xc3, 0xa4, 0x25, 0x14, 0xba, 0x15, 0x97, 0x14, 0xe0, 0xa0, 0x2d, 0xc3, 0x41, 0x6b, 0x50, 0xc0, - 0xe6, 0x73, 0x71, 0x3c, 0x4c, 0xb9, 0xfc, 0x20, 0x0e, 0x13, 0x0a, 0xc5, 0x43, 0x37, 0x60, 0x6e, - 0x40, 0xcc, 0x42, 0x24, 0xc6, 0x56, 0x32, 0xee, 0x00, 0x28, 0x1c, 0x0d, 0xad, 0xc3, 0xbc, 0x4e, - 0xe7, 0x49, 0xc4, 0xd0, 0xf5, 0x94, 0xc2, 0x0c, 0x45, 0x50, 0x04, 0x22, 0xda, 0xf6, 0x0f, 0xbf, - 0xa5, 0xac, 0x53, 0x6b, 0x6c, 0x2a, 0x52, 0x4f, 0xc0, 0xbb, 0xd1, 0xa3, 0x19, 0x50, 0x5e, 0xeb, - 0xe3, 0x79, 0x8d, 0x3e, 0x06, 0x9f, 0x86, 0x62, 0xdf, 0xea, 0x31, 0x33, 0x2a, 0xb3, 0x6b, 0x33, - 0x7d, 0xab, 0x47, 0xad, 0x68, 0x19, 0x66, 0x5d, 0x4f, 0x37, 0x4c, 0x1a, 0xb3, 0x14, 0x15, 0xd6, - 0x20, 0x8b, 0x8f, 0x3e, 0xa8, 0x96, 0xd9, 0xc5, 0xf5, 0x0a, 0x7d, 0x55, 0xa2, 0x90, 0x1d, 0xb3, - 0x4b, 0x0f, 0x69, 0x9e, 0x77, 0x5c, 0xaf, 0x52, 0x38, 0x79, 0x44, 0x1f, 0x88, 0xdc, 0xe5, 0x62, - 0x56, 0x9e, 0x27, 0x6d, 0x43, 0x14, 0xa9, 0xcb, 0x07, 0x41, 0xb9, 0x86, 0xed, 0xe9, 0x57, 0xc6, - 0xbb, 0x97, 0xef, 0x50, 0xb5, 0xe6, 0x6f, 0x25, 0x38, 0xb5, 0x49, 0xd3, 0x20, 0x21, 0x3f, 0x36, - 0x4d, 0xed, 0xe0, 0xb6, 0x5f, 0xd6, 0xc9, 0xcc, 0xc7, 0xc7, 0xc7, 0x2d, 0xaa, 0x3a, 0x4d, 0xa8, - 0x0a, 0xe6, 0x9c, 0x45, 0x7e, 0xe2, 0xca, 0x50, 0xc5, 0x0d, 0x37, 0xe5, 0x0f, 0x60, 0x25, 0x31, - 0x0a, 0x9e, 0x89, 0x58, 0x85, 0x85, 0xc0, 0x5f, 0xf9, 0x83, 0x28, 0xfb, 0xb0, 0xa6, 0x2e, 0xdf, - 0x81, 0x93, 0x1d, 0x4f, 0x73, 0xbc, 0x84, 0x0a, 0x26, 0xa0, 0xa5, 0x35, 0x9f, 0x28, 0x2d, 0x2f, - 0xcb, 0x74, 0x60, 0xb9, 0xe3, 0x59, 0xf6, 0x4b, 0x30, 0x25, 0x5e, 0x87, 0x8c, 0xdf, 0x1a, 0x8a, - 0xfd, 0x41, 0x34, 0xe5, 0x15, 0x56, 0xa1, 0x4a, 0xf6, 0x76, 0x17, 0x4e, 0xb1, 0x02, 0xd1, 0xcb, - 0x0c, 0xe2, 0xb4, 0x28, 0x4f, 0x25, 0xf9, 0x3e, 0x85, 0x13, 0xc1, 0xb6, 0x18, 0xa4, 0x5e, 0x6f, - 0x45, 0x53, 0xaf, 0xe7, 0x47, 0xcc, 0x7a, 0x24, 0xf3, 0xfa, 0xa7, 0xb9, 0x90, 0x5f, 0xcf, 0x48, - 0xbc, 0xde, 0x8d, 0x26, 0x5e, 0x2f, 0x8e, 0xe3, 0x1d, 0xc9, 0xbb, 0x26, 0xad, 0x36, 0x9f, 0x62, - 0xb5, 0x9f, 0x27, 0xb2, 0xb3, 0x85, 0xac, 0xf4, 0x76, 0x4c, 0xda, 0xdf, 0x4a, 0x72, 0x56, 0x61, - 0xc9, 0x59, 0xbf, 0x6b, 0xbf, 0x9e, 0x77, 0x3b, 0x96, 0x9c, 0x5d, 0x1d, 0x2b, 0xaf, 0x9f, 0x9b, - 0xfd, 0xab, 0x02, 0x94, 0xfc, 0x77, 0x09, 0x9d, 0x27, 0xd5, 0x96, 0x4b, 0x51, 0x5b, 0x78, 0x07, - 0xce, 0xbf, 0xd2, 0x0e, 0x5c, 0x98, 0x78, 0x07, 0x3e, 0x03, 0x25, 0xfa, 0x40, 0x6f, 0xc0, 0xb0, - 0x1d, 0xb5, 0x48, 0x01, 0x0a, 0x3e, 0x08, 0xcc, 0x70, 0x6e, 0x2a, 0x33, 0x8c, 0xa5, 0x83, 0xe7, - 0xe3, 0xe9, 0xe0, 0x8f, 0xfc, 0x1d, 0x91, 0x6d, 0xa2, 0x97, 0x47, 0xf0, 0x4d, 0xdd, 0x0b, 0x63, - 0x69, 0xca, 0x52, 0x56, 0x9a, 0x32, 0xe0, 0x32, 0x3a, 0x4d, 0xf9, 0x2d, 0xee, 0x10, 0x7b, 0x2c, - 0xc7, 0x1b, 0xb6, 0x45, 0xee, 0x59, 0xef, 0x02, 0xf8, 0x4e, 0x44, 0x24, 0x7a, 0xcf, 0x8c, 0x18, - 0xa3, 0x12, 0x42, 0x27, 0x6c, 0x23, 0x53, 0x13, 0xd4, 0xac, 0x27, 0xf3, 0x8f, 0x19, 0x05, 0xeb, - 0xff, 0x99, 0x0d, 0xf9, 0x97, 0x8c, 0x5a, 0xec, 0x47, 0x89, 0x32, 0xc4, 0x94, 0x56, 0x7c, 0x2b, - 0x5a, 0x85, 0x78, 0x49, 0xab, 0x4b, 0x14, 0x21, 0x68, 0xe4, 0xa2, 0x39, 0xfc, 0x35, 0x4b, 0xb5, - 0x96, 0x38, 0x64, 0x83, 0x9e, 0x0c, 0x0e, 0x0c, 0xd3, 0x70, 0x0f, 0xd9, 0xfb, 0x39, 0x76, 0x32, - 0x10, 0xa0, 0x0d, 0x9a, 0x22, 0xc4, 0x2f, 0x0c, 0x4f, 0xed, 0x5a, 0x3a, 0xa6, 0x36, 0x3d, 0xab, - 0x14, 0x09, 0x60, 0xd3, 0xd2, 0x71, 0xb0, 0xf2, 0x8a, 0x2f, 0xb7, 0xf2, 0x4a, 0xb1, 0x95, 0x77, - 0x0a, 0xe6, 0x1c, 0xac, 0xb9, 0x96, 0xc9, 0x12, 0x0a, 0x0a, 0x6f, 0x91, 0xa9, 0x19, 0x60, 0xd7, - 0x25, 0x3d, 0xf1, 0x70, 0x8d, 0x37, 0x43, 0x61, 0xe6, 0xc2, 0xd8, 0x30, 0x73, 0x44, 0x8d, 0x37, - 0x16, 0x66, 0x56, 0xc6, 0x86, 0x99, 0x13, 0x95, 0x78, 0x83, 0x40, 0xbb, 0x3a, 0x59, 0xa0, 0x1d, - 0x8e, 0x4b, 0x17, 0x23, 0x71, 0xe9, 0xb7, 0xb9, 0x58, 0x7f, 0x2d, 0xc1, 0x4a, 0x62, 0x59, 0xf1, - 0xe5, 0x7a, 0x3b, 0x56, 0x04, 0x5e, 0x1d, 0xab, 0x33, 0xbf, 0x06, 0xfc, 0x28, 0x52, 0x03, 0x7e, - 0x77, 0x3c, 0xe1, 0x6b, 0x2f, 0x01, 0xff, 0x77, 0x0e, 0xde, 0xdc, 0xb3, 0xf5, 0x58, 0x84, 0xc7, - 0x8f, 0xfd, 0x93, 0x3b, 0x8e, 0x8f, 0x44, 0xac, 0x9f, 0x9b, 0x36, 0x83, 0xc5, 0xc3, 0xfd, 0xed, - 0x20, 0xdc, 0xcf, 0x4f, 0x9f, 0x9f, 0x10, 0xb4, 0x48, 0x8f, 0x1a, 0x31, 0x0b, 0x3e, 0x1e, 0x24, - 0x59, 0x8d, 0x19, 0xf2, 0x37, 0x5c, 0xdc, 0x92, 0xe1, 0x7c, 0xb6, 0x00, 0x3c, 0x3e, 0xfc, 0x11, - 0x2c, 0x6e, 0xbf, 0xc0, 0xdd, 0xce, 0xb1, 0xd9, 0x9d, 0x62, 0x1e, 0x6a, 0x90, 0xef, 0x0e, 0x74, - 0x9e, 0xf0, 0x27, 0x8f, 0xe1, 0x90, 0x37, 0x1f, 0x0d, 0x79, 0x55, 0xa8, 0x05, 0x3d, 0x70, 0x5b, - 0x3e, 0x45, 0x6c, 0x59, 0x27, 0xc8, 0x84, 0xf9, 0x82, 0xc2, 0x5b, 0x1c, 0x8e, 0x1d, 0x76, 0x3f, - 0x8c, 0xc1, 0xb1, 0xe3, 0x44, 0x5d, 0x63, 0x3e, 0xea, 0x1a, 0xe5, 0x3f, 0x96, 0xa0, 0x4c, 0x7a, - 0x78, 0x25, 0xf9, 0xf9, 0xb9, 0x32, 0x1f, 0x9c, 0x2b, 0xfd, 0xe3, 0x69, 0x21, 0x7c, 0x3c, 0x0d, - 0x24, 0x9f, 0xa5, 0xe0, 0xa4, 0xe4, 0x73, 0x3e, 0x1c, 0x3b, 0x8e, 0x7c, 0x1e, 0x16, 0x98, 0x6c, - 0x7c, 0xe4, 0x35, 0xc8, 0x0f, 0x9d, 0xbe, 0x98, 0xbf, 0xa1, 0xd3, 0x97, 0x7f, 0x5f, 0x82, 0xca, - 0x86, 0xe7, 0x69, 0xdd, 0xc3, 0x29, 0x06, 0xe0, 0x0b, 0x97, 0x0b, 0x0b, 0x97, 0x1c, 0x44, 0x20, - 0x6e, 0x21, 0x43, 0xdc, 0xd9, 0x88, 0xb8, 0x32, 0x54, 0x85, 0x2c, 0x99, 0x02, 0xb7, 0x00, 0xb5, - 0x2d, 0xc7, 0x7b, 0x68, 0x39, 0x47, 0x9a, 0xa3, 0x4f, 0x77, 0xdc, 0x44, 0x50, 0xe0, 0xdf, 0x7f, - 0xe4, 0xaf, 0xcc, 0x2a, 0xf4, 0x59, 0xbe, 0x0c, 0x27, 0x22, 0xfc, 0x32, 0x3b, 0xbe, 0x0f, 0x65, - 0xba, 0xc9, 0xf1, 0x73, 0xc7, 0xcd, 0x70, 0x85, 0x79, 0xa2, 0x2d, 0x51, 0xfe, 0xff, 0xb0, 0x44, - 0x82, 0x21, 0x0a, 0xf7, 0xfd, 0xce, 0xf7, 0x63, 0x41, 0xf9, 0xd9, 0x0c, 0x46, 0xb1, 0x80, 0xfc, - 0x37, 0x12, 0xcc, 0x52, 0x78, 0x22, 0x40, 0x39, 0x03, 0x25, 0x07, 0xdb, 0x96, 0xea, 0x69, 0x3d, - 0xff, 0x6b, 0x1b, 0x02, 0xd8, 0xd5, 0x7a, 0xb4, 0x98, 0x41, 0x5f, 0xea, 0x46, 0x0f, 0xbb, 0x9e, - 0xf8, 0xe4, 0xa6, 0x4c, 0x60, 0x5b, 0x0c, 0x44, 0x94, 0x44, 0xcb, 0x84, 0x05, 0x5a, 0x0d, 0xa4, - 0xcf, 0x68, 0x8d, 0x5d, 0x4b, 0x9e, 0xa4, 0x3a, 0x44, 0x2f, 0x2d, 0x37, 0xa0, 0x18, 0x2b, 0xe8, - 0xf8, 0x6d, 0x74, 0x03, 0x0a, 0x34, 0x05, 0x3c, 0x3f, 0x5e, 0x6f, 0x14, 0x51, 0xde, 0x06, 0x14, - 0x56, 0x1b, 0x9f, 0xa0, 0x1b, 0x30, 0x47, 0xb5, 0x2a, 0x62, 0xc7, 0x95, 0x0c, 0x46, 0x0a, 0x47, - 0x93, 0x35, 0x40, 0x8c, 0x73, 0x24, 0x5e, 0x9c, 0x7e, 0x1a, 0x47, 0xc4, 0x8f, 0x7f, 0x23, 0xc1, - 0x89, 0x48, 0x1f, 0x5c, 0xd6, 0xeb, 0xd1, 0x4e, 0x32, 0x45, 0xe5, 0x1d, 0x6c, 0x46, 0x36, 0xcc, - 0x1b, 0x59, 0x22, 0x7d, 0x43, 0x9b, 0xe5, 0xdf, 0x4b, 0x00, 0x1b, 0x43, 0xef, 0x90, 0xe7, 0x4d, - 0xc3, 0x53, 0x29, 0xc5, 0xa6, 0xb2, 0x01, 0x45, 0x5b, 0x73, 0xdd, 0x23, 0xcb, 0x11, 0x27, 0x3e, - 0xbf, 0x4d, 0x33, 0x9c, 0x43, 0xef, 0x50, 0x94, 0x81, 0xc9, 0x33, 0xba, 0x08, 0x55, 0xf6, 0x49, - 0x98, 0xaa, 0xe9, 0xba, 0x83, 0x5d, 0x97, 0xd7, 0x83, 0x2b, 0x0c, 0xba, 0xc1, 0x80, 0x04, 0xcd, - 0xa0, 0x65, 0x01, 0xef, 0x58, 0xf5, 0xac, 0x67, 0xd8, 0xe4, 0x27, 0xb7, 0x8a, 0x80, 0xee, 0x12, - 0x20, 0xab, 0xba, 0xf5, 0x0c, 0xd7, 0x73, 0x04, 0x9a, 0xa8, 0x1d, 0x72, 0x28, 0x45, 0x23, 0x93, - 0x52, 0x6b, 0x0f, 0xfb, 0x7d, 0xa6, 0xe2, 0x97, 0x9f, 0xf6, 0xef, 0xf1, 0x01, 0xe5, 0xb2, 0x16, - 0x41, 0xa0, 0x34, 0x3e, 0xdc, 0xd7, 0x98, 0xa2, 0xfa, 0x1e, 0x2c, 0x85, 0xc6, 0xc0, 0xcd, 0x2a, - 0x12, 0x62, 0x4b, 0xd1, 0x10, 0x5b, 0x7e, 0x04, 0x88, 0x65, 0x65, 0x5e, 0x71, 0xdc, 0xf2, 0x49, - 0x38, 0x11, 0x61, 0xc4, 0xb7, 0xee, 0x6b, 0x50, 0xe1, 0xd7, 0x39, 0xb9, 0xa1, 0x9c, 0x86, 0x22, - 0x71, 0xc1, 0x5d, 0x43, 0x17, 0x77, 0x04, 0xe6, 0x6d, 0x4b, 0xdf, 0x34, 0x74, 0x47, 0xfe, 0x04, - 0x2a, 0xfc, 0xbb, 0x12, 0x8e, 0xfb, 0x10, 0xaa, 0xfc, 0xf2, 0xa7, 0x1a, 0xb9, 0xd6, 0x9d, 0xf6, - 0x95, 0x57, 0xb8, 0x13, 0xa5, 0x62, 0x86, 0x9b, 0xb2, 0x0e, 0x0d, 0x16, 0x63, 0x44, 0xd8, 0x8b, - 0xc1, 0x3e, 0x04, 0x71, 0xdb, 0x69, 0x6c, 0x2f, 0x51, 0xfa, 0x8a, 0x13, 0x6e, 0xca, 0x67, 0xe1, - 0x4c, 0x6a, 0x2f, 0x5c, 0x13, 0x36, 0xd4, 0x82, 0x17, 0xec, 0xee, 0xb1, 0x7f, 0x09, 0x42, 0x0a, - 0x5d, 0x82, 0x38, 0xe5, 0x87, 0xd0, 0x39, 0xb1, 0xeb, 0xd1, 0xf8, 0x38, 0x38, 0x0c, 0xe5, 0xb3, - 0x0e, 0x43, 0x85, 0xc8, 0x61, 0x48, 0xee, 0xf8, 0xfa, 0xe4, 0x87, 0xd4, 0x07, 0xf4, 0x30, 0xcd, - 0xfa, 0x16, 0x0e, 0x51, 0x1e, 0x35, 0x4a, 0x86, 0xaa, 0x84, 0xa8, 0xe4, 0xab, 0x50, 0x89, 0xba, - 0xc6, 0x90, 0x9f, 0x93, 0x12, 0x7e, 0xae, 0x1a, 0x73, 0x71, 0xef, 0xc7, 0xce, 0x07, 0xd9, 0x3a, - 0x8e, 0x9d, 0x0e, 0xee, 0x45, 0x9c, 0xdd, 0xb5, 0x94, 0x9a, 0xf6, 0x37, 0xe4, 0xe7, 0x96, 0xf9, - 0x7e, 0xf0, 0xd0, 0x25, 0xf4, 0x7c, 0xd0, 0xf2, 0x05, 0x28, 0xef, 0x65, 0x7d, 0x25, 0x58, 0x10, - 0x77, 0xb0, 0x6e, 0xc1, 0xf2, 0x43, 0xa3, 0x8f, 0xdd, 0x63, 0xd7, 0xc3, 0x83, 0x26, 0x75, 0x4a, - 0x07, 0x06, 0x76, 0xd0, 0x39, 0x00, 0x7a, 0xc0, 0xb3, 0x2d, 0xc3, 0xff, 0xde, 0x29, 0x04, 0x91, - 0xff, 0x43, 0x82, 0xc5, 0x80, 0x70, 0x8f, 0x1e, 0x6c, 0xdf, 0x80, 0x12, 0x19, 0xaf, 0xeb, 0x69, - 0x03, 0x5b, 0x54, 0xfb, 0x7c, 0x00, 0xba, 0x0b, 0xb3, 0x07, 0xae, 0x48, 0xa8, 0xa5, 0x96, 0x17, - 0xd2, 0x04, 0x51, 0x0a, 0x07, 0x6e, 0x53, 0x47, 0x1f, 0x00, 0x0c, 0x5d, 0xac, 0xf3, 0x0a, 0x5f, - 0x3e, 0x2b, 0xbc, 0xd8, 0x0b, 0xdf, 0xed, 0x20, 0x04, 0xec, 0xfa, 0xd6, 0x3d, 0x28, 0x1b, 0xa6, - 0xa5, 0x63, 0x5a, 0xdd, 0xd5, 0x79, 0xce, 0x6d, 0x0c, 0x39, 0x30, 0x8a, 0x3d, 0x17, 0xeb, 0x32, - 0xe6, 0x7b, 0xa1, 0xd0, 0x2f, 0x37, 0x94, 0x16, 0x2c, 0x31, 0xa7, 0x75, 0xe0, 0x0b, 0x2e, 0x2c, - 0x76, 0x75, 0xd4, 0xe8, 0xa8, 0xb6, 0x94, 0x9a, 0xc1, 0x63, 0x21, 0x41, 0x2a, 0xdf, 0x81, 0x93, - 0x91, 0xf3, 0xe3, 0x14, 0x07, 0x3a, 0xb9, 0x1d, 0x4b, 0x23, 0x05, 0xe6, 0xcc, 0x93, 0x34, 0xc2, - 0x9a, 0xc7, 0x25, 0x69, 0x5c, 0x96, 0xa4, 0x71, 0xe5, 0xcf, 0xe1, 0x74, 0x24, 0xdf, 0x15, 0x91, - 0xe8, 0x5e, 0x2c, 0xd4, 0xbb, 0x34, 0x8e, 0x6b, 0x2c, 0xe6, 0xfb, 0x2f, 0x09, 0x96, 0xd3, 0x10, - 0x5e, 0x32, 0x1f, 0xfb, 0xa3, 0x8c, 0x4b, 0xc6, 0xb7, 0x27, 0x13, 0xeb, 0xb7, 0x92, 0xcb, 0xde, - 0x85, 0x46, 0x9a, 0x3e, 0x93, 0xb3, 0x94, 0x9f, 0x66, 0x96, 0x7e, 0x9e, 0x0f, 0xd5, 0x25, 0x36, - 0x3c, 0xcf, 0x31, 0xf6, 0x87, 0xc4, 0xe4, 0x5f, 0x7b, 0xae, 0xaf, 0xe9, 0x67, 0xad, 0x98, 0x6a, - 0x6f, 0x8e, 0x20, 0x0f, 0xe4, 0x48, 0xcd, 0x5c, 0x7d, 0x9a, 0x76, 0xe8, 0xbf, 0x35, 0x19, 0xbf, - 0xef, 0x6c, 0x7a, 0xf8, 0xe7, 0x39, 0xa8, 0x46, 0xa7, 0x08, 0x6d, 0x03, 0x68, 0xbe, 0xe4, 0x7c, - 0xa1, 0x5c, 0x9c, 0x68, 0x98, 0x4a, 0x88, 0x10, 0xbd, 0x03, 0xf9, 0xae, 0x3d, 0xe4, 0xb3, 0x96, - 0x52, 0x2a, 0xdf, 0xb4, 0x87, 0xcc, 0xa3, 0x10, 0x34, 0x72, 0x08, 0x63, 0x37, 0x1f, 0xb2, 0xbd, - 0xe4, 0x53, 0xfa, 0x9e, 0xd1, 0x70, 0x64, 0xf4, 0x18, 0xaa, 0x47, 0x8e, 0xe1, 0x69, 0xfb, 0x7d, - 0xac, 0xf6, 0xb5, 0x63, 0xec, 0x70, 0x2f, 0x39, 0x81, 0x23, 0xab, 0x08, 0xc2, 0x27, 0x84, 0x4e, - 0xfe, 0x3d, 0x28, 0x0a, 0x89, 0xc6, 0xec, 0x08, 0xbb, 0xb0, 0x32, 0x24, 0x68, 0x2a, 0xbd, 0x56, - 0x6b, 0x6a, 0xa6, 0xa5, 0xba, 0x98, 0x6c, 0xe3, 0xe2, 0x9b, 0xa6, 0x31, 0x2e, 0x7a, 0x99, 0x52, - 0x6f, 0x5a, 0x0e, 0x6e, 0x69, 0xa6, 0xd5, 0x61, 0xa4, 0xf2, 0x73, 0x28, 0x87, 0x06, 0x38, 0x46, - 0x84, 0x26, 0x2c, 0x89, 0x8b, 0x0a, 0x2e, 0xf6, 0xf8, 0xf6, 0x32, 0x51, 0xe7, 0x8b, 0x9c, 0xae, - 0x83, 0x3d, 0x76, 0xb9, 0xe4, 0x1e, 0x9c, 0x56, 0xb0, 0x65, 0x63, 0xd3, 0x9f, 0xcf, 0x27, 0x56, - 0x6f, 0x0a, 0x0f, 0xfe, 0x06, 0x34, 0xd2, 0xe8, 0x99, 0x7f, 0xb8, 0x76, 0x09, 0x8a, 0xe2, 0xff, - 0x20, 0xd0, 0x3c, 0xe4, 0x77, 0x37, 0xdb, 0xb5, 0x19, 0xf2, 0xb0, 0xb7, 0xd5, 0xae, 0x49, 0xa8, - 0x08, 0x85, 0xce, 0xe6, 0x6e, 0xbb, 0x96, 0xbb, 0x36, 0x80, 0x5a, 0xfc, 0xcf, 0x10, 0xd0, 0x0a, - 0x9c, 0x68, 0x2b, 0x3b, 0xed, 0x8d, 0x47, 0x1b, 0xbb, 0xcd, 0x9d, 0x96, 0xda, 0x56, 0x9a, 0x1f, - 0x6f, 0xec, 0x6e, 0xd7, 0x66, 0xd0, 0x2a, 0x9c, 0x0d, 0xbf, 0x78, 0xbc, 0xd3, 0xd9, 0x55, 0x77, - 0x77, 0xd4, 0xcd, 0x9d, 0xd6, 0xee, 0x46, 0xb3, 0xb5, 0xad, 0xd4, 0x24, 0x74, 0x16, 0x4e, 0x87, - 0x51, 0x1e, 0x34, 0xb7, 0x9a, 0xca, 0xf6, 0x26, 0x79, 0xde, 0x78, 0x52, 0xcb, 0x5d, 0xfb, 0x10, - 0x2a, 0x91, 0xff, 0x2e, 0x20, 0x22, 0xb5, 0x77, 0xb6, 0x6a, 0x33, 0xa8, 0x02, 0xa5, 0x30, 0x9f, - 0x22, 0x14, 0x5a, 0x3b, 0x5b, 0xdb, 0xb5, 0x1c, 0x02, 0x98, 0xdb, 0xdd, 0x50, 0x1e, 0x6d, 0xef, - 0xd6, 0xf2, 0xd7, 0xee, 0xc0, 0x62, 0xec, 0x3b, 0x05, 0xb4, 0x04, 0x95, 0xce, 0x46, 0x6b, 0xeb, - 0xc1, 0xce, 0xa7, 0xaa, 0xb2, 0xbd, 0xb1, 0xf5, 0x59, 0x6d, 0x06, 0x2d, 0x43, 0x4d, 0x80, 0x5a, - 0x3b, 0xbb, 0x0c, 0x2a, 0x5d, 0x7b, 0x16, 0x5b, 0x6f, 0x18, 0x9d, 0x84, 0x25, 0xbf, 0x4b, 0x75, - 0x53, 0xd9, 0xde, 0xd8, 0xdd, 0x26, 0x92, 0x44, 0xc0, 0xca, 0x5e, 0xab, 0xd5, 0x6c, 0x3d, 0xaa, - 0x49, 0x84, 0x6b, 0x00, 0xde, 0xfe, 0xb4, 0x49, 0x90, 0x73, 0x51, 0xe4, 0xbd, 0xd6, 0x0f, 0x5a, - 0x3b, 0x9f, 0xb4, 0x6a, 0xf9, 0xf5, 0x5f, 0x2e, 0xf9, 0xdf, 0x93, 0x77, 0xb0, 0x43, 0xef, 0xff, - 0xb4, 0x61, 0x5e, 0xfc, 0xd7, 0x48, 0x8a, 0xb7, 0x8e, 0xfe, 0x43, 0x4a, 0x63, 0x75, 0x04, 0x06, - 0x8f, 0xbd, 0x67, 0xd0, 0x3e, 0x8d, 0x85, 0x43, 0xdf, 0x8d, 0x5c, 0x4a, 0x8d, 0x3c, 0x13, 0x9f, - 0xaa, 0x34, 0x2e, 0x8f, 0xc5, 0xf3, 0xfb, 0xc0, 0x24, 0xdc, 0x0d, 0x7f, 0x9a, 0x89, 0x2e, 0xa7, - 0xc5, 0xa9, 0x29, 0xdf, 0x7e, 0x36, 0xae, 0x8c, 0x47, 0xf4, 0xbb, 0x79, 0x06, 0xb5, 0xf8, 0x67, - 0x9a, 0x28, 0x25, 0xc9, 0x9c, 0xf1, 0x2d, 0x68, 0xe3, 0xda, 0x24, 0xa8, 0xe1, 0xce, 0x12, 0xdf, - 0x1d, 0x5e, 0x9d, 0xe4, 0xfb, 0xac, 0xcc, 0xce, 0xb2, 0x3e, 0xe5, 0x62, 0x0a, 0x8c, 0x7e, 0xea, - 0x81, 0x52, 0x3f, 0xf2, 0x4b, 0xf9, 0xa2, 0x28, 0x4d, 0x81, 0xe9, 0x5f, 0x8d, 0xc8, 0x33, 0xe8, - 0x10, 0x16, 0x63, 0x17, 0x39, 0x50, 0x0a, 0x79, 0xfa, 0x8d, 0x95, 0xc6, 0xd5, 0x09, 0x30, 0xa3, - 0x16, 0x11, 0xbe, 0xb8, 0x91, 0x6e, 0x11, 0x29, 0xd7, 0x42, 0xd2, 0x2d, 0x22, 0xf5, 0x0e, 0x08, - 0x35, 0xee, 0xc8, 0x85, 0x8d, 0x34, 0xe3, 0x4e, 0xbb, 0x26, 0xd2, 0xb8, 0x3c, 0x16, 0x2f, 0xac, - 0xb4, 0xd8, 0xf5, 0x8d, 0x34, 0xa5, 0xa5, 0x5f, 0x0f, 0x69, 0x5c, 0x9d, 0x00, 0x33, 0x6e, 0x05, - 0x41, 0x31, 0x38, 0xcb, 0x0a, 0x12, 0x57, 0x17, 0xb2, 0xac, 0x20, 0x59, 0x57, 0xe6, 0x56, 0x10, - 0x2b, 0xe2, 0x5e, 0x99, 0xa0, 0xe8, 0x94, 0x6d, 0x05, 0xe9, 0xe5, 0x29, 0x79, 0x06, 0xfd, 0x4c, - 0x82, 0x7a, 0x56, 0x8d, 0x03, 0xdd, 0x9c, 0xba, 0x20, 0xd3, 0x58, 0x9f, 0x86, 0xc4, 0x97, 0xe2, - 0x4b, 0x40, 0xc9, 0x3d, 0x10, 0xbd, 0x9d, 0x36, 0x33, 0x19, 0x3b, 0x6d, 0xe3, 0x9d, 0xc9, 0x90, - 0xfd, 0x2e, 0x3b, 0x50, 0x14, 0x55, 0x15, 0x94, 0xe2, 0xa5, 0x63, 0x35, 0x9d, 0x86, 0x3c, 0x0a, - 0xc5, 0x67, 0xfa, 0x08, 0x0a, 0x04, 0x8a, 0xce, 0xa6, 0x63, 0x0b, 0x66, 0xe7, 0xb2, 0x5e, 0xfb, - 0x8c, 0x9e, 0xc2, 0x1c, 0x2b, 0x23, 0xa0, 0x94, 0x2c, 0x44, 0xa4, 0xd8, 0xd1, 0x38, 0x9f, 0x8d, - 0xe0, 0xb3, 0xfb, 0x82, 0xfd, 0x0d, 0x15, 0xaf, 0x10, 0xa0, 0xb7, 0xd2, 0xff, 0x6d, 0x22, 0x5a, - 0x90, 0x68, 0x5c, 0x1c, 0x83, 0x15, 0x5e, 0x14, 0xb1, 0x08, 0xf8, 0xf2, 0xd8, 0x63, 0x4c, 0xf6, - 0xa2, 0x48, 0x3f, 0x28, 0x31, 0x23, 0x49, 0x1e, 0xa4, 0xd2, 0x8c, 0x24, 0xf3, 0xf8, 0x9a, 0x66, - 0x24, 0xd9, 0x67, 0x33, 0x79, 0x06, 0x79, 0x70, 0x22, 0x25, 0x6d, 0x86, 0xde, 0xc9, 0x32, 0xf2, - 0xb4, 0x1c, 0x5e, 0xe3, 0xfa, 0x84, 0xd8, 0xe1, 0xc9, 0xe7, 0x8b, 0xfe, 0xcd, 0xec, 0x5c, 0x52, - 0xe6, 0xe4, 0xc7, 0x97, 0xf8, 0xfa, 0xbf, 0xe4, 0x61, 0x81, 0xa5, 0x44, 0x79, 0x04, 0xf3, 0x19, - 0x40, 0x50, 0x8d, 0x40, 0x17, 0xd2, 0x75, 0x12, 0x29, 0xf1, 0x34, 0xde, 0x1a, 0x8d, 0x14, 0x36, - 0xb4, 0x50, 0x66, 0x3f, 0xcd, 0xd0, 0x92, 0x05, 0x8c, 0x34, 0x43, 0x4b, 0x29, 0x0f, 0xc8, 0x33, - 0xe8, 0x63, 0x28, 0xf9, 0x29, 0x64, 0x94, 0x96, 0x82, 0x8e, 0xe5, 0xc8, 0x1b, 0x17, 0x46, 0xe2, - 0x84, 0xa5, 0x0e, 0xe5, 0x87, 0xd3, 0xa4, 0x4e, 0xe6, 0xa1, 0xd3, 0xa4, 0x4e, 0x4b, 0x32, 0x07, - 0x3a, 0x61, 0x59, 0xa4, 0x4c, 0x9d, 0x44, 0x92, 0x78, 0x99, 0x3a, 0x89, 0xa6, 0xa2, 0xe4, 0x99, - 0x07, 0x97, 0x7e, 0xf5, 0xd5, 0x39, 0xe9, 0x9f, 0xbe, 0x3a, 0x37, 0xf3, 0xd3, 0xaf, 0xcf, 0x49, - 0xbf, 0xfa, 0xfa, 0x9c, 0xf4, 0x8f, 0x5f, 0x9f, 0x93, 0xfe, 0xf5, 0xeb, 0x73, 0xd2, 0x1f, 0xfc, - 0xdb, 0xb9, 0x99, 0x1f, 0x16, 0x05, 0xf5, 0xfe, 0x1c, 0xfd, 0x33, 0xb9, 0x77, 0xff, 0x37, 0x00, - 0x00, 0xff, 0xff, 0xf5, 0x05, 0x0e, 0x59, 0x12, 0x50, 0x00, 0x00, + // 5632 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x3c, 0x4b, 0x6c, 0x1b, 0x59, + 0x72, 0x6a, 0x92, 0x92, 0xc8, 0xa2, 0x48, 0xd1, 0xcf, 0xb2, 0x45, 0xd3, 0x63, 0xd9, 0x6e, 0x8f, + 0xbf, 0x33, 0x96, 0xd7, 0x9a, 0x19, 0xcf, 0x58, 0x9e, 0xb1, 0x2d, 0x4b, 0xb2, 0xcd, 0x5d, 0x5b, + 0x62, 0x9a, 0xd2, 0x7c, 0x76, 0x26, 0xe8, 0x6d, 0xb1, 0x9f, 0xa8, 0x1e, 0x93, 0xdd, 0x3d, 0xdd, + 0x4d, 0xdb, 0xda, 0x5c, 0x16, 0x58, 0x60, 0x0f, 0x7b, 0x0a, 0x10, 0x04, 0x01, 0x72, 0xdb, 0xe4, + 0x90, 0x43, 0x4e, 0x9b, 0x20, 0xa7, 0x9c, 0x12, 0x24, 0xc8, 0x22, 0x1f, 0x24, 0xa7, 0x45, 0x82, + 0xbd, 0x64, 0x26, 0x08, 0xb0, 0x08, 0x10, 0x20, 0xc8, 0x39, 0x87, 0xe0, 0xfd, 0xfa, 0xc7, 0x6e, + 0xb2, 0x69, 0xcf, 0x6f, 0x4f, 0xec, 0x57, 0x5d, 0x55, 0xaf, 0x5e, 0xbd, 0x7a, 0xf5, 0xea, 0xbd, + 0xaa, 0x26, 0x94, 0x34, 0xdb, 0x58, 0xb6, 0x1d, 0xcb, 0xb3, 0x50, 0xcd, 0x19, 0x98, 0x9e, 0xd1, + 0xc7, 0xcb, 0x4f, 0xaf, 0x6b, 0x3d, 0xfb, 0x40, 0x5b, 0x69, 0x5c, 0xed, 0x1a, 0xde, 0xc1, 0x60, + 0x6f, 0xb9, 0x63, 0xf5, 0xaf, 0x75, 0xad, 0xae, 0x75, 0x8d, 0x22, 0xee, 0x0d, 0xf6, 0x69, 0x8b, + 0x36, 0xe8, 0x13, 0x63, 0x20, 0x5f, 0x81, 0xea, 0xfb, 0xd8, 0x71, 0x0d, 0xcb, 0x54, 0xf0, 0x67, + 0x03, 0xec, 0x7a, 0xa8, 0x0e, 0xb3, 0x4f, 0x19, 0xa4, 0x2e, 0x9d, 0x91, 0x2e, 0x95, 0x14, 0xd1, + 0x94, 0xff, 0x44, 0x82, 0x79, 0x1f, 0xd9, 0xb5, 0x2d, 0xd3, 0xc5, 0xe9, 0xd8, 0xe8, 0x2c, 0xcc, + 0x71, 0xe1, 0x54, 0x53, 0xeb, 0xe3, 0x7a, 0x8e, 0xbe, 0x2e, 0x73, 0xd8, 0x96, 0xd6, 0xc7, 0xe8, + 0x22, 0xcc, 0x0b, 0x14, 0xc1, 0x24, 0x4f, 0xb1, 0xaa, 0x1c, 0xcc, 0x7b, 0x43, 0xcb, 0x70, 0x54, + 0x20, 0x6a, 0xb6, 0xe1, 0x23, 0x17, 0x28, 0xf2, 0x11, 0xfe, 0x6a, 0xcd, 0x36, 0x38, 0xbe, 0xfc, + 0x31, 0x94, 0x36, 0xb6, 0xda, 0xeb, 0x96, 0xb9, 0x6f, 0x74, 0x89, 0x88, 0x2e, 0x76, 0x08, 0x4d, + 0x5d, 0x3a, 0x93, 0x27, 0x22, 0xf2, 0x26, 0x6a, 0x40, 0xd1, 0xc5, 0x9a, 0xd3, 0x39, 0xc0, 0x6e, + 0x3d, 0x47, 0x5f, 0xf9, 0x6d, 0x42, 0x65, 0xd9, 0x9e, 0x61, 0x99, 0x6e, 0x3d, 0xcf, 0xa8, 0x78, + 0x53, 0xfe, 0x23, 0x09, 0xca, 0x2d, 0xcb, 0xf1, 0x1e, 0x6b, 0xb6, 0x6d, 0x98, 0x5d, 0x74, 0x03, + 0x8a, 0x54, 0x97, 0x1d, 0xab, 0x47, 0x75, 0x50, 0x5d, 0x69, 0x2c, 0xc7, 0xa7, 0x65, 0xb9, 0xc5, + 0x31, 0x14, 0x1f, 0x17, 0x9d, 0x87, 0x6a, 0xc7, 0x32, 0x3d, 0xcd, 0x30, 0xb1, 0xa3, 0xda, 0x96, + 0xe3, 0x51, 0x15, 0x4d, 0x2b, 0x15, 0x1f, 0x4a, 0x7a, 0x41, 0x27, 0xa1, 0x74, 0x60, 0xb9, 0x1e, + 0xc3, 0xc8, 0x53, 0x8c, 0x22, 0x01, 0xd0, 0x97, 0x8b, 0x30, 0x4b, 0x5f, 0x1a, 0x36, 0x57, 0xc6, + 0x0c, 0x69, 0x36, 0x6d, 0xf9, 0x97, 0x12, 0x4c, 0x3f, 0xb6, 0x06, 0xa6, 0x17, 0xeb, 0x46, 0xf3, + 0x0e, 0xf8, 0x44, 0x85, 0xba, 0xd1, 0xbc, 0x83, 0xa0, 0x1b, 0x82, 0xc1, 0xe6, 0x8a, 0x75, 0x43, + 0x5e, 0x36, 0xa0, 0xe8, 0x60, 0x4d, 0xb7, 0xcc, 0xde, 0x21, 0x15, 0xa1, 0xa8, 0xf8, 0x6d, 0x32, + 0x89, 0x2e, 0xee, 0x19, 0xe6, 0xe0, 0xb9, 0xea, 0xe0, 0x9e, 0xb6, 0x87, 0x7b, 0x54, 0x94, 0xa2, + 0x52, 0xe5, 0x60, 0x85, 0x41, 0xd1, 0x06, 0x94, 0x6d, 0xc7, 0xb2, 0xb5, 0xae, 0x46, 0xf4, 0x58, + 0x9f, 0xa6, 0xaa, 0x92, 0x87, 0x55, 0x45, 0xc5, 0x6e, 0x05, 0x98, 0x4a, 0x98, 0x4c, 0xfe, 0x67, + 0x09, 0xe6, 0x89, 0xf1, 0xb8, 0xb6, 0xd6, 0xc1, 0xdb, 0x74, 0x4a, 0xd0, 0x4d, 0x98, 0x35, 0xb1, + 0xf7, 0xcc, 0x72, 0x9e, 0xf0, 0x09, 0x38, 0x3d, 0xcc, 0xd5, 0xa7, 0x79, 0x6c, 0xe9, 0x58, 0x11, + 0xf8, 0xe8, 0x3a, 0xe4, 0x6d, 0x43, 0xa7, 0x03, 0xce, 0x40, 0x46, 0x70, 0x09, 0x89, 0x61, 0x77, + 0xa8, 0x1e, 0xb2, 0x90, 0x18, 0x76, 0x87, 0x28, 0xd7, 0xd3, 0x9c, 0x2e, 0xf6, 0x54, 0x43, 0xe7, + 0x13, 0x55, 0x64, 0x80, 0xa6, 0x2e, 0xcb, 0x00, 0x4d, 0xd3, 0xbb, 0xf1, 0xe6, 0xfb, 0x5a, 0x6f, + 0x80, 0xd1, 0x02, 0x4c, 0x3f, 0x25, 0x0f, 0x74, 0x24, 0x79, 0x85, 0x35, 0xe4, 0xcf, 0x0b, 0x70, + 0xf2, 0x11, 0x51, 0x66, 0x5b, 0x33, 0xf5, 0x3d, 0xeb, 0x79, 0x1b, 0x77, 0x06, 0x8e, 0xe1, 0x1d, + 0xae, 0x5b, 0xa6, 0x87, 0x9f, 0x7b, 0x68, 0x0b, 0x8e, 0x98, 0xa2, 0x5b, 0x55, 0xd8, 0x2d, 0xe1, + 0x50, 0x5e, 0x39, 0x3b, 0x42, 0x42, 0xa6, 0x3f, 0xa5, 0x66, 0x46, 0x01, 0x2e, 0x7a, 0x18, 0x4c, + 0xaa, 0xe0, 0x96, 0xa3, 0xdc, 0x12, 0xc6, 0xdb, 0xde, 0xa4, 0x92, 0x71, 0x5e, 0x62, 0xd6, 0x05, + 0xa7, 0x77, 0x81, 0x2c, 0x79, 0x55, 0x73, 0xd5, 0x81, 0x8b, 0x1d, 0xaa, 0xb5, 0xf2, 0xca, 0x2b, + 0xc3, 0x5c, 0x02, 0x15, 0x28, 0x25, 0x67, 0x60, 0xae, 0xb9, 0xbb, 0x2e, 0x76, 0xd0, 0x6d, 0xea, + 0x44, 0x08, 0x75, 0xd7, 0xb1, 0x06, 0x76, 0xbd, 0x98, 0x81, 0x1c, 0x28, 0xf9, 0x03, 0x82, 0x4f, + 0x3d, 0x0c, 0x37, 0x54, 0xd5, 0xb1, 0x2c, 0x6f, 0xdf, 0x15, 0xc6, 0x29, 0xc0, 0x0a, 0x85, 0xa2, + 0x6b, 0x70, 0xd4, 0x1d, 0xd8, 0x76, 0x0f, 0xf7, 0xb1, 0xe9, 0x69, 0x3d, 0xd6, 0x9d, 0x5b, 0x9f, + 0x3e, 0x93, 0xbf, 0x94, 0x57, 0x50, 0xf8, 0x15, 0x65, 0xec, 0xa2, 0x25, 0x00, 0xdb, 0x31, 0x9e, + 0x1a, 0x3d, 0xdc, 0xc5, 0x7a, 0x7d, 0x86, 0x32, 0x0d, 0x41, 0xd0, 0x2d, 0xe2, 0x75, 0x3a, 0x1d, + 0xab, 0x6f, 0xd7, 0x4b, 0x69, 0xf3, 0x20, 0x66, 0xb1, 0xe5, 0x58, 0xfb, 0x46, 0x0f, 0x2b, 0x82, + 0x02, 0xbd, 0x07, 0x45, 0xcd, 0xb6, 0x35, 0xa7, 0x6f, 0x39, 0x75, 0xc8, 0x4a, 0xed, 0x93, 0xa0, + 0x37, 0x61, 0x81, 0x73, 0x52, 0x6d, 0xf6, 0x92, 0x2d, 0xeb, 0x59, 0x62, 0x79, 0xf7, 0x72, 0x75, + 0x49, 0x41, 0xfc, 0x3d, 0xa7, 0x25, 0x8b, 0x5c, 0xfe, 0x7b, 0x09, 0xe6, 0x63, 0x3c, 0x51, 0x0b, + 0xe6, 0x04, 0x07, 0xef, 0xd0, 0xc6, 0x7c, 0x79, 0x5d, 0x1d, 0x2b, 0xcc, 0x32, 0xff, 0xdd, 0x39, + 0xb4, 0x31, 0x5d, 0xbf, 0xa2, 0x81, 0xce, 0x41, 0xa5, 0x67, 0x75, 0xb4, 0x1e, 0x75, 0x36, 0x0e, + 0xde, 0xe7, 0xbe, 0x66, 0xce, 0x07, 0x2a, 0x78, 0x5f, 0xbe, 0x0b, 0xe5, 0x10, 0x03, 0x84, 0xa0, + 0xaa, 0xb0, 0x0e, 0x37, 0xf0, 0xbe, 0x36, 0xe8, 0x79, 0xb5, 0x29, 0x54, 0x05, 0xd8, 0x35, 0x3b, + 0xc4, 0xc3, 0x9b, 0x58, 0xaf, 0x49, 0xa8, 0x02, 0xa5, 0x47, 0x82, 0x45, 0x2d, 0x27, 0xff, 0x59, + 0x1e, 0x8e, 0x51, 0xb3, 0x6c, 0x59, 0x3a, 0x5f, 0x33, 0x7c, 0x3b, 0x38, 0x07, 0x95, 0x0e, 0x9d, + 0x5d, 0xd5, 0xd6, 0x1c, 0x6c, 0x7a, 0xdc, 0x1d, 0xce, 0x31, 0x60, 0x8b, 0xc2, 0xd0, 0x87, 0x50, + 0x73, 0xf9, 0x88, 0xd4, 0x0e, 0x5b, 0x63, 0x7c, 0x01, 0x24, 0x8c, 0x7d, 0xc4, 0xc2, 0x54, 0xe6, + 0xdd, 0xa1, 0x95, 0x3a, 0xeb, 0x1e, 0xba, 0x1d, 0xaf, 0xc7, 0xf6, 0x95, 0xf2, 0xca, 0x9b, 0x29, + 0x0c, 0xe3, 0x82, 0x2f, 0xb7, 0x19, 0xd9, 0xa6, 0xe9, 0x39, 0x87, 0x8a, 0x60, 0x82, 0x36, 0xa1, + 0x68, 0x3d, 0xc5, 0xce, 0x01, 0xd6, 0x98, 0x67, 0x29, 0xaf, 0x5c, 0x4e, 0x61, 0xb8, 0x2e, 0xfc, + 0xbd, 0x82, 0x5d, 0x6b, 0xe0, 0x74, 0xb0, 0xab, 0xf8, 0xa4, 0xe8, 0x01, 0x94, 0x1c, 0x01, 0xa6, + 0xae, 0x79, 0x22, 0x3e, 0x01, 0x6d, 0x63, 0x15, 0xe6, 0xc2, 0x82, 0xa2, 0x1a, 0xe4, 0x9f, 0xe0, + 0x43, 0xae, 0x64, 0xf2, 0x18, 0x78, 0x38, 0x36, 0xf3, 0xac, 0xb1, 0x9a, 0x7b, 0x47, 0x92, 0x1d, + 0x40, 0xc1, 0xa8, 0x1f, 0x63, 0x4f, 0xd3, 0x35, 0x4f, 0x43, 0x08, 0x0a, 0x34, 0x80, 0x60, 0x2c, + 0xe8, 0x33, 0xe1, 0x3a, 0xe0, 0x6e, 0xbb, 0xa4, 0x90, 0x47, 0xf4, 0x0a, 0x94, 0x7c, 0x2f, 0xc6, + 0xa3, 0x88, 0x00, 0x40, 0x76, 0x73, 0xcd, 0xf3, 0x70, 0xdf, 0xf6, 0xa8, 0x92, 0x2a, 0x8a, 0x68, + 0xca, 0x7f, 0x3e, 0x0d, 0xb5, 0x21, 0x1b, 0xb9, 0x0b, 0xc5, 0x3e, 0xef, 0x9e, 0x7b, 0xd1, 0x57, + 0x13, 0xb6, 0xf4, 0x21, 0x51, 0x15, 0x9f, 0x8a, 0xec, 0x98, 0xc4, 0x12, 0x43, 0x91, 0x8f, 0xdf, + 0x66, 0x4b, 0xa0, 0xab, 0xea, 0x86, 0x83, 0x3b, 0x9e, 0xe5, 0x1c, 0x72, 0x71, 0xe7, 0x7a, 0x56, + 0x77, 0x43, 0xc0, 0xd0, 0x2a, 0x80, 0x6e, 0xba, 0x2a, 0xb5, 0xf0, 0x2e, 0x9f, 0xd9, 0x93, 0xc3, + 0x42, 0xf8, 0x61, 0x8e, 0x52, 0xd2, 0x4d, 0x97, 0x8b, 0x7f, 0x0f, 0x2a, 0x24, 0x5a, 0x50, 0xfb, + 0x2c, 0x42, 0x61, 0x6e, 0xac, 0xbc, 0x72, 0x2a, 0x69, 0x0c, 0x7e, 0x1c, 0xa3, 0xcc, 0xd9, 0x41, + 0xc3, 0x45, 0xf7, 0x61, 0x86, 0x6e, 0xdb, 0x6e, 0x7d, 0x86, 0x12, 0x2f, 0x8f, 0x52, 0x00, 0xb7, + 0xd0, 0x47, 0x94, 0x80, 0x19, 0x28, 0xa7, 0x46, 0xbb, 0x50, 0xd6, 0x4c, 0xd3, 0xf2, 0x34, 0xb6, + 0x8b, 0xcc, 0x52, 0x66, 0x6f, 0x64, 0x60, 0xb6, 0x16, 0x50, 0x31, 0x8e, 0x61, 0x3e, 0xe8, 0x3d, + 0x98, 0xa6, 0xdb, 0x0c, 0xdf, 0x11, 0x2e, 0x66, 0x5c, 0x44, 0x0a, 0xa3, 0x42, 0xeb, 0x30, 0xfb, + 0xcc, 0x30, 0x75, 0xeb, 0x99, 0xcb, 0xbd, 0x73, 0x82, 0xb1, 0x7f, 0xc0, 0x10, 0x86, 0x58, 0x08, + 0xca, 0xc6, 0x4d, 0x28, 0x87, 0x46, 0x3c, 0x89, 0xa5, 0x37, 0x6e, 0x43, 0x2d, 0x3e, 0xbe, 0x89, + 0x56, 0xca, 0xef, 0xc0, 0x82, 0x32, 0x30, 0x03, 0xd1, 0x44, 0xf0, 0xbe, 0x0a, 0x33, 0xdc, 0x62, + 0x98, 0xd9, 0xca, 0xe3, 0x15, 0xad, 0x70, 0x8a, 0x70, 0x34, 0x7e, 0xa0, 0x99, 0x7a, 0x0f, 0x3b, + 0xbc, 0x5f, 0x11, 0x8d, 0x3f, 0x64, 0x50, 0xf9, 0x3d, 0x38, 0x16, 0xeb, 0x9c, 0x1f, 0x06, 0x5e, + 0x85, 0xaa, 0x6d, 0xe9, 0xaa, 0xcb, 0xc0, 0x24, 0xd6, 0xe1, 0xbe, 0xd5, 0xf6, 0x71, 0x9b, 0x3a, + 0x21, 0x6f, 0x7b, 0x96, 0x3d, 0x2c, 0x7c, 0x36, 0xf2, 0x3a, 0x1c, 0x8f, 0x93, 0xb3, 0xee, 0xe5, + 0x3b, 0xb0, 0xa8, 0xe0, 0xbe, 0xf5, 0x14, 0xbf, 0x28, 0xeb, 0x06, 0xd4, 0x87, 0x19, 0x70, 0xe6, + 0x1f, 0xc1, 0x62, 0x00, 0x6d, 0x7b, 0x9a, 0x37, 0x70, 0x27, 0x62, 0xce, 0x4f, 0x4a, 0x7b, 0x96, + 0xcb, 0xa6, 0xb3, 0xa8, 0x88, 0xa6, 0xbc, 0x08, 0xd3, 0x2d, 0x4b, 0x6f, 0xb6, 0x50, 0x15, 0x72, + 0x86, 0xcd, 0x89, 0x73, 0x86, 0x2d, 0x1b, 0xe1, 0x3e, 0xb7, 0x58, 0xc4, 0xca, 0xba, 0x8e, 0xa3, + 0xa2, 0xdb, 0x50, 0xd5, 0x74, 0xdd, 0x20, 0xe6, 0xa4, 0xf5, 0x54, 0xc3, 0x66, 0x07, 0x9a, 0xf2, + 0xca, 0x62, 0xa2, 0x01, 0x34, 0x5b, 0x4a, 0x25, 0x40, 0x6f, 0xda, 0xae, 0xfc, 0x10, 0x4a, 0x7e, + 0x54, 0x48, 0x62, 0x97, 0x68, 0xd4, 0x97, 0x21, 0x86, 0xf4, 0x8f, 0x47, 0x3b, 0x43, 0x1b, 0x2f, + 0x17, 0xf9, 0x16, 0x80, 0xef, 0x90, 0x45, 0x70, 0x7a, 0x72, 0x04, 0x63, 0x25, 0x84, 0x2e, 0xff, + 0x38, 0xe2, 0xa6, 0x43, 0x4a, 0xd0, 0x7d, 0x25, 0xe8, 0x11, 0xb7, 0x9d, 0x7b, 0x21, 0xb7, 0xfd, + 0x36, 0x4c, 0xbb, 0x9e, 0xe6, 0x61, 0x1e, 0xdd, 0x9f, 0x1d, 0x45, 0x4e, 0x84, 0xc0, 0x0a, 0xc3, + 0x47, 0xa7, 0x00, 0x3a, 0x0e, 0xd6, 0x3c, 0xac, 0xab, 0x1a, 0xdb, 0x63, 0xf2, 0x4a, 0x89, 0x43, + 0xd6, 0x3c, 0xe2, 0x6f, 0xc4, 0x09, 0x25, 0x75, 0x73, 0x4d, 0x99, 0xea, 0xe0, 0xac, 0xe2, 0xfb, + 0xbc, 0x99, 0x8c, 0x3e, 0x8f, 0x33, 0xe0, 0x3e, 0x2f, 0xf0, 0xe8, 0xb3, 0xe3, 0x3d, 0x3a, 0x23, + 0xcd, 0xe2, 0xd1, 0x8b, 0xe3, 0x3d, 0x3a, 0x67, 0x36, 0xda, 0xa3, 0x27, 0xb8, 0x9f, 0x52, 0x92, + 0xfb, 0xf9, 0x26, 0xdd, 0xee, 0xbf, 0x49, 0x50, 0x1f, 0xf6, 0x02, 0xdc, 0xfb, 0xad, 0xc2, 0x8c, + 0x4b, 0x21, 0x59, 0x7c, 0x2f, 0xa7, 0xe5, 0x14, 0xe8, 0x21, 0x14, 0x0c, 0x73, 0xdf, 0xe2, 0x8b, + 0xf6, 0xcd, 0x0c, 0x94, 0xbc, 0xd7, 0xe5, 0xa6, 0xb9, 0x6f, 0x31, 0x6d, 0x52, 0x0e, 0x8d, 0xb7, + 0xa1, 0xe4, 0x83, 0x26, 0x1a, 0xdb, 0x36, 0x2c, 0xc4, 0x6c, 0x9b, 0x1d, 0x48, 0xfd, 0x25, 0x21, + 0x4d, 0xb6, 0x24, 0xe4, 0x1f, 0xe5, 0xc2, 0x4b, 0xf6, 0xbe, 0xd1, 0xf3, 0xb0, 0x33, 0xb4, 0x64, + 0xdf, 0x15, 0xdc, 0xd9, 0x7a, 0xbd, 0x30, 0x96, 0x3b, 0x3b, 0xe3, 0xf1, 0x55, 0xf7, 0x09, 0x54, + 0xa9, 0x51, 0xaa, 0x2e, 0xee, 0xd1, 0xb8, 0x89, 0xc7, 0xd4, 0x6f, 0x8d, 0x62, 0xc3, 0x24, 0x61, + 0xa6, 0xdd, 0xe6, 0x74, 0x4c, 0x83, 0x95, 0x5e, 0x18, 0xd6, 0xb8, 0x0b, 0x68, 0x18, 0x69, 0x22, + 0x9d, 0xb6, 0x89, 0x2f, 0x74, 0xbd, 0xc4, 0x7d, 0x7a, 0x9f, 0x8a, 0x91, 0xc5, 0x56, 0x98, 0xc0, + 0x0a, 0xa7, 0x90, 0xff, 0x3b, 0x0f, 0x10, 0xbc, 0xfc, 0x0d, 0x72, 0x82, 0x77, 0x7d, 0x07, 0xc4, + 0xe2, 0xd1, 0x4b, 0xa3, 0x18, 0x27, 0xba, 0x9e, 0xed, 0xa8, 0xeb, 0x61, 0x91, 0xe9, 0xd5, 0x91, + 0x6c, 0x26, 0x76, 0x3a, 0xb3, 0xdf, 0x36, 0xa7, 0xf3, 0x08, 0x8e, 0xc7, 0x8d, 0x88, 0x7b, 0x9c, + 0x15, 0x98, 0x36, 0x3c, 0xdc, 0x67, 0xf7, 0x9a, 0x89, 0xd7, 0x22, 0x21, 0x22, 0x86, 0x2a, 0xdf, + 0x86, 0xe3, 0xd1, 0xd9, 0x9b, 0x2c, 0x8c, 0x91, 0x95, 0x78, 0x1c, 0x14, 0x38, 0x40, 0x6e, 0x37, + 0x23, 0x2e, 0x9e, 0xe2, 0x94, 0x0c, 0x5f, 0xfe, 0x47, 0x09, 0x8e, 0xc5, 0x5e, 0xa5, 0xb8, 0x0b, + 0x6d, 0x68, 0xc1, 0x33, 0x8f, 0xb9, 0x3a, 0xb6, 0xaf, 0xaf, 0x71, 0xd5, 0xff, 0x36, 0x34, 0xa2, + 0x13, 0x16, 0x51, 0xf3, 0x9d, 0xd8, 0xd2, 0xbf, 0x98, 0x51, 0x74, 0x7f, 0xfd, 0xbf, 0x0f, 0x27, + 0x13, 0xd9, 0x0f, 0xcf, 0x42, 0x7e, 0xa2, 0x59, 0xf8, 0x69, 0x3e, 0xbc, 0x03, 0xac, 0x79, 0x9e, + 0x63, 0xec, 0x0d, 0x3c, 0xfc, 0x55, 0x84, 0x59, 0xdf, 0xf5, 0x3d, 0x01, 0xf3, 0xd7, 0x2b, 0xa3, + 0xe8, 0x03, 0x49, 0x12, 0x7d, 0xc2, 0x47, 0x51, 0x9f, 0x50, 0xa0, 0x0c, 0xdf, 0xce, 0xc8, 0x70, + 0xa4, 0x77, 0xf8, 0x26, 0x17, 0xfd, 0xaf, 0x24, 0x98, 0x8f, 0xcd, 0x13, 0xba, 0x0f, 0xa0, 0xf9, + 0xa2, 0x73, 0xeb, 0xb9, 0x90, 0x6d, 0xa0, 0x4a, 0x88, 0x92, 0xec, 0xb9, 0x2c, 0x8e, 0x4c, 0xdd, + 0x73, 0x13, 0xe2, 0x48, 0x3f, 0x8c, 0xbc, 0x17, 0x1c, 0x9d, 0xd9, 0x65, 0xee, 0xa5, 0x0c, 0x47, + 0x67, 0xc6, 0x41, 0x10, 0xca, 0x3f, 0xcf, 0xc1, 0x42, 0x52, 0x1f, 0xe8, 0x75, 0xc8, 0x77, 0xec, + 0x01, 0x1f, 0x5b, 0x42, 0x1a, 0x65, 0xdd, 0x1e, 0xec, 0xba, 0x5a, 0x17, 0x2b, 0x04, 0x0d, 0xbd, + 0x05, 0x33, 0x7d, 0xdc, 0xb7, 0x9c, 0x43, 0x3e, 0x92, 0x84, 0x0b, 0x8e, 0xc7, 0xf4, 0x3d, 0xa3, + 0xe1, 0xc8, 0xe8, 0x9d, 0x20, 0x18, 0x67, 0x23, 0x58, 0x4a, 0x38, 0x85, 0x30, 0x04, 0x46, 0xe8, + 0x47, 0xe0, 0xef, 0xc0, 0xac, 0xed, 0x58, 0x1d, 0xec, 0xba, 0xfc, 0x46, 0x66, 0x29, 0x31, 0xd3, + 0x43, 0x10, 0x38, 0x25, 0x47, 0x47, 0x77, 0x01, 0xfc, 0x7c, 0x8b, 0xd8, 0xff, 0xce, 0x24, 0x8c, + 0x4f, 0xe0, 0x30, 0x85, 0x85, 0x68, 0xc8, 0xb9, 0x37, 0x59, 0xad, 0xf2, 0x3f, 0x48, 0x30, 0x17, + 0x96, 0x17, 0xbd, 0x02, 0x25, 0xc2, 0xd6, 0xf5, 0xb4, 0xbe, 0xcd, 0xf3, 0x08, 0x01, 0x00, 0xed, + 0xc0, 0x11, 0x9d, 0x5d, 0xa3, 0xaa, 0x86, 0xe9, 0x61, 0x67, 0x5f, 0xeb, 0x88, 0xf0, 0xeb, 0x62, + 0xaa, 0x22, 0x9a, 0x02, 0x93, 0x8d, 0xab, 0xc6, 0x39, 0xf8, 0x60, 0xf4, 0x00, 0xc0, 0xe7, 0x26, + 0x96, 0x75, 0x66, 0x76, 0x21, 0x52, 0xf9, 0x0f, 0x72, 0x70, 0x2c, 0x11, 0x2b, 0xf1, 0x22, 0xf0, + 0x1d, 0x28, 0x3a, 0xcf, 0xd5, 0xbd, 0x43, 0x0f, 0xbb, 0xe9, 0x46, 0xb0, 0x1b, 0xca, 0x0e, 0xcc, + 0x3a, 0xcf, 0xef, 0x11, 0x6c, 0xb4, 0x0a, 0x25, 0xe7, 0xb9, 0x8a, 0x1d, 0xc7, 0x72, 0x84, 0x25, + 0x8f, 0x21, 0x2d, 0x3a, 0xcf, 0x37, 0x29, 0x3a, 0xe9, 0xd5, 0x13, 0xbd, 0x16, 0x32, 0xf5, 0xea, + 0x05, 0xbd, 0x7a, 0x7e, 0xaf, 0xd3, 0x99, 0x7a, 0xf5, 0x78, 0xaf, 0xb2, 0x0d, 0x73, 0x61, 0xe3, + 0x1a, 0x33, 0xcd, 0xf7, 0xa0, 0xc2, 0x8d, 0x4f, 0xed, 0x58, 0x03, 0xd3, 0xcb, 0xa6, 0x9e, 0x39, + 0x4e, 0xb3, 0x4e, 0x48, 0xe4, 0x9f, 0x4b, 0x50, 0x6a, 0xf6, 0xb5, 0x2e, 0x6e, 0xdb, 0xb8, 0x43, + 0xbc, 0x95, 0x41, 0x1a, 0x7c, 0x02, 0x58, 0x03, 0x6d, 0x45, 0xfd, 0x2f, 0xdb, 0x8f, 0x5f, 0x4f, + 0xc8, 0xd0, 0x08, 0x3e, 0x63, 0x9c, 0xee, 0xcb, 0x7a, 0xce, 0x15, 0x28, 0x7e, 0x0f, 0x1f, 0xb2, + 0xb3, 0x4b, 0x46, 0x3a, 0xf9, 0x67, 0x05, 0x58, 0x4c, 0xb9, 0xdb, 0xa6, 0x41, 0xad, 0x3d, 0x50, + 0x6d, 0xec, 0x18, 0x96, 0x2e, 0xd4, 0xdc, 0xb1, 0x07, 0x2d, 0x0a, 0x40, 0x27, 0x81, 0x34, 0xd4, + 0xcf, 0x06, 0x16, 0xdf, 0x0d, 0xf3, 0x4a, 0xb1, 0x63, 0x0f, 0x7e, 0x8b, 0xb4, 0x05, 0xad, 0x7b, + 0xa0, 0x39, 0x98, 0x19, 0x19, 0xa3, 0x6d, 0x53, 0x00, 0xba, 0x0e, 0xc7, 0x98, 0x4b, 0x52, 0x7b, + 0x46, 0xdf, 0x20, 0xcb, 0x31, 0x64, 0x53, 0x79, 0x05, 0xb1, 0x97, 0x8f, 0xc8, 0xbb, 0xa6, 0xc9, + 0xec, 0x47, 0x86, 0x8a, 0x65, 0xf5, 0x55, 0xb7, 0x63, 0x39, 0x58, 0xd5, 0xf4, 0x4f, 0xa9, 0x0d, + 0xe5, 0x95, 0xb2, 0x65, 0xf5, 0xdb, 0x04, 0xb6, 0xa6, 0x7f, 0x8a, 0x4e, 0x43, 0xb9, 0x63, 0x0f, + 0x5c, 0xec, 0xa9, 0xe4, 0x87, 0xde, 0x16, 0x94, 0x14, 0x60, 0xa0, 0x75, 0x7b, 0xe0, 0x86, 0x10, + 0xfa, 0x24, 0x7a, 0x9c, 0x0d, 0x23, 0x3c, 0xc6, 0x7d, 0x9a, 0xfe, 0x3b, 0x18, 0x74, 0xb1, 0xad, + 0x75, 0x31, 0x13, 0x4d, 0x1c, 0xf3, 0x13, 0xd2, 0x7f, 0x0f, 0x39, 0x22, 0x15, 0x53, 0xa9, 0x1e, + 0x84, 0x9b, 0x2e, 0x6a, 0xc1, 0xec, 0xc0, 0x34, 0xf6, 0x0d, 0xac, 0xd7, 0x4b, 0x94, 0xc3, 0x8d, + 0xcc, 0x59, 0x85, 0xe5, 0x5d, 0x46, 0xc8, 0x13, 0x1e, 0x9c, 0x0d, 0x5a, 0x85, 0x06, 0x57, 0x9a, + 0xfb, 0x4c, 0xb3, 0xe3, 0x9a, 0x03, 0xaa, 0x8e, 0xe3, 0x0c, 0xa3, 0xfd, 0x4c, 0xb3, 0xc3, 0xda, + 0x6b, 0xac, 0xc2, 0x5c, 0x98, 0xe9, 0x44, 0x76, 0x75, 0x0f, 0x2a, 0x91, 0xa1, 0x92, 0x99, 0xa7, + 0x0a, 0x72, 0x8d, 0x1f, 0x8a, 0x25, 0x51, 0x24, 0x80, 0xb6, 0xf1, 0x43, 0x9a, 0xc6, 0xa5, 0x92, + 0x51, 0x3e, 0x05, 0x85, 0x35, 0x64, 0x0d, 0x2a, 0x91, 0x6c, 0x29, 0x71, 0x69, 0x34, 0x2d, 0xca, + 0x5d, 0x1a, 0x79, 0x26, 0x30, 0xc7, 0xea, 0x09, 0x09, 0xe8, 0x33, 0x81, 0xd1, 0xfc, 0x1b, 0xcb, + 0x14, 0xd0, 0x67, 0xda, 0x05, 0x7e, 0xca, 0xd3, 0xed, 0x25, 0x85, 0x35, 0x64, 0x1d, 0x60, 0x5d, + 0xb3, 0xb5, 0x3d, 0xa3, 0x67, 0x78, 0x87, 0xe8, 0x32, 0xd4, 0x34, 0x5d, 0x57, 0x3b, 0x02, 0x62, + 0x60, 0x51, 0x04, 0x31, 0xaf, 0xe9, 0xfa, 0x7a, 0x08, 0x8c, 0x5e, 0x83, 0x23, 0xba, 0x63, 0xd9, + 0x51, 0x5c, 0x56, 0x15, 0x51, 0x23, 0x2f, 0xc2, 0xc8, 0xf2, 0xaf, 0x67, 0xe0, 0x54, 0x74, 0xda, + 0xe2, 0x19, 0xe9, 0xbb, 0x30, 0x17, 0xeb, 0x35, 0x25, 0x73, 0x1b, 0x48, 0xab, 0x44, 0x28, 0x62, + 0x19, 0xd6, 0xdc, 0x50, 0x86, 0x35, 0x31, 0xe7, 0x9d, 0xff, 0x52, 0x73, 0xde, 0x85, 0x2f, 0x25, + 0xe7, 0x3d, 0xfd, 0x72, 0x39, 0xef, 0xb9, 0x09, 0x73, 0xde, 0x17, 0xe8, 0x99, 0x56, 0xf4, 0x4e, + 0x77, 0x4c, 0xe6, 0x02, 0x2a, 0x7e, 0x1f, 0xa6, 0xa8, 0xbe, 0x89, 0xe5, 0xc6, 0x67, 0x27, 0xc9, + 0x8d, 0x17, 0x53, 0x73, 0xe3, 0x67, 0x60, 0xce, 0xb4, 0x54, 0x13, 0x3f, 0x53, 0xc9, 0x74, 0xb9, + 0xf5, 0x32, 0x9b, 0x3b, 0xd3, 0xda, 0xc2, 0xcf, 0x5a, 0x04, 0x82, 0xce, 0xc2, 0x5c, 0x5f, 0x73, + 0x9f, 0x60, 0x9d, 0x26, 0xa6, 0xdd, 0x7a, 0x85, 0xda, 0x59, 0x99, 0xc1, 0x5a, 0x04, 0x84, 0xce, + 0x83, 0x2f, 0x07, 0x47, 0xaa, 0x52, 0xa4, 0x8a, 0x80, 0x32, 0xb4, 0x50, 0x9e, 0x7d, 0xfe, 0xa5, + 0xf2, 0xec, 0xb5, 0xc9, 0xf3, 0xec, 0x57, 0xa1, 0x26, 0x9e, 0x45, 0xa2, 0x9d, 0xdd, 0x59, 0xd2, + 0x1c, 0xfb, 0xbc, 0x78, 0x27, 0x92, 0xe9, 0x69, 0x69, 0x79, 0x18, 0x99, 0x96, 0xff, 0x4b, 0x89, + 0xc7, 0xca, 0xfe, 0x52, 0xe3, 0x59, 0xbe, 0x48, 0xca, 0x56, 0x7a, 0xf1, 0x94, 0x2d, 0xfa, 0x7e, + 0x6a, 0xb2, 0xfb, 0xda, 0x38, 0x7e, 0xe3, 0xd2, 0xdd, 0xf2, 0xef, 0x49, 0x70, 0x8a, 0x87, 0xad, + 0x29, 0xa5, 0x2b, 0x09, 0xe6, 0x2a, 0xa5, 0x98, 0x6b, 0xc7, 0xc1, 0x3a, 0x36, 0x3d, 0x43, 0xeb, + 0xa9, 0xae, 0x8d, 0x3b, 0x22, 0x3d, 0x15, 0x80, 0x69, 0x98, 0x72, 0x16, 0xe6, 0x58, 0x25, 0x13, + 0x8f, 0xd4, 0x59, 0xc1, 0x52, 0x99, 0x16, 0x33, 0x31, 0x90, 0x3c, 0x80, 0xc5, 0x94, 0xec, 0x5e, + 0xa2, 0x32, 0xa4, 0x34, 0x65, 0x8c, 0x1c, 0xd9, 0xb0, 0x32, 0x7e, 0x5f, 0x82, 0xd3, 0x9c, 0x24, + 0xd5, 0x6f, 0x7e, 0x13, 0xea, 0xf8, 0x2b, 0xc9, 0x3f, 0x5b, 0xc4, 0x8d, 0xac, 0x39, 0x6c, 0x64, + 0xaf, 0xa5, 0xea, 0x61, 0xb4, 0x99, 0x7d, 0x92, 0x6a, 0x66, 0xd7, 0xc7, 0x73, 0x1c, 0xab, 0xdb, + 0x3f, 0x95, 0xe0, 0x44, 0xaa, 0x18, 0xb1, 0x40, 0x4c, 0x8a, 0x07, 0x62, 0x3c, 0x88, 0x0b, 0xe2, + 0x64, 0x16, 0xc4, 0xd1, 0x20, 0x98, 0x47, 0x4b, 0x6a, 0x5f, 0x7b, 0x6e, 0xf4, 0x07, 0x7d, 0x1e, + 0xc5, 0x11, 0x76, 0x8f, 0x19, 0xe4, 0x05, 0xc2, 0x38, 0x79, 0x0d, 0x8e, 0xf8, 0x52, 0x8e, 0x2c, + 0x74, 0x08, 0x15, 0x2e, 0xe4, 0xa2, 0x85, 0x0b, 0x26, 0xcc, 0x6c, 0xe0, 0xa7, 0x46, 0x07, 0x7f, + 0x29, 0x15, 0x7e, 0x67, 0xa0, 0x6c, 0x63, 0xa7, 0x6f, 0xb8, 0xae, 0xbf, 0x8d, 0x96, 0x94, 0x30, + 0x48, 0xfe, 0xcf, 0x19, 0x98, 0x8f, 0x5b, 0xc7, 0x9d, 0xa1, 0x3a, 0x89, 0x73, 0x23, 0xce, 0xb4, + 0x09, 0x17, 0x41, 0xd7, 0xc5, 0x91, 0x22, 0x97, 0x96, 0x0e, 0xf4, 0x8f, 0x0d, 0xe2, 0xbc, 0x51, + 0x87, 0xd9, 0x8e, 0xd5, 0xef, 0x6b, 0xa6, 0x2e, 0x0a, 0x33, 0x79, 0x93, 0xe8, 0x4f, 0x73, 0xba, + 0xec, 0x0a, 0xa8, 0xa4, 0xd0, 0x67, 0x32, 0x79, 0xe4, 0x24, 0x69, 0x98, 0xb4, 0xde, 0x82, 0x6e, + 0xc5, 0x25, 0x05, 0x38, 0x68, 0xc3, 0x70, 0xd0, 0x32, 0x14, 0xb0, 0xf9, 0x54, 0xdc, 0x25, 0x27, + 0x5c, 0x39, 0x88, 0xc3, 0x84, 0x42, 0xf1, 0xd0, 0x35, 0x98, 0xe9, 0x13, 0xb3, 0x10, 0x59, 0xb4, + 0xc5, 0x94, 0x02, 0x46, 0x85, 0xa3, 0xa1, 0x15, 0x98, 0xd5, 0xe9, 0x3c, 0x89, 0x18, 0xba, 0x9e, + 0x50, 0xc5, 0x41, 0x11, 0x14, 0x81, 0x88, 0x36, 0xfd, 0xfb, 0xb1, 0x52, 0xda, 0x15, 0x77, 0x6c, + 0x2a, 0x12, 0xaf, 0xc6, 0x76, 0xa2, 0x47, 0x33, 0x48, 0xbb, 0x6b, 0x8b, 0xf3, 0x1a, 0x7d, 0x67, + 0x7e, 0x02, 0x8a, 0x3d, 0xab, 0xcb, 0xcc, 0xa8, 0xcc, 0x6a, 0x7e, 0x7b, 0x56, 0x97, 0x5a, 0xd1, + 0x02, 0x4c, 0xbb, 0x9e, 0x6e, 0x98, 0x34, 0x66, 0x29, 0x2a, 0xac, 0x41, 0x16, 0x1f, 0x7d, 0x50, + 0x2d, 0xb3, 0x83, 0xeb, 0x15, 0xfa, 0xaa, 0x44, 0x21, 0xdb, 0x66, 0x87, 0x1e, 0xd2, 0x3c, 0xef, + 0xb0, 0x5e, 0xa5, 0x70, 0xf2, 0x18, 0x5c, 0x50, 0xcd, 0x8f, 0xbc, 0xa0, 0x8a, 0x89, 0x9d, 0x70, + 0x41, 0x55, 0x1b, 0x73, 0x41, 0x15, 0xe7, 0xf0, 0x6d, 0x28, 0xed, 0xf8, 0x1b, 0x09, 0x8e, 0xaf, + 0xd3, 0x9c, 0x49, 0xc8, 0x8f, 0x4d, 0x52, 0x68, 0x70, 0xd3, 0xaf, 0x01, 0x49, 0x4d, 0xde, 0xc7, + 0xc7, 0x2d, 0x4a, 0x40, 0x9a, 0x50, 0x15, 0xcc, 0x39, 0x8b, 0x7c, 0xe6, 0x32, 0x92, 0x8a, 0x1b, + 0x6e, 0xca, 0xef, 0xc2, 0xe2, 0xd0, 0x28, 0xf8, 0x0d, 0xf5, 0x59, 0x98, 0x0b, 0xfc, 0x95, 0x3f, + 0x88, 0xb2, 0x0f, 0x6b, 0xea, 0xf2, 0x2a, 0x1c, 0x6b, 0x7b, 0x9a, 0xe3, 0x0d, 0xa9, 0x20, 0x03, + 0x2d, 0x2d, 0x10, 0x89, 0xd2, 0xf2, 0x1a, 0x8e, 0x36, 0x2c, 0xb4, 0x3d, 0xcb, 0x7e, 0x01, 0xa6, + 0xc4, 0xeb, 0x90, 0xf1, 0x5b, 0x03, 0xb1, 0x3f, 0x88, 0xa6, 0xbc, 0xc8, 0xca, 0x59, 0x86, 0x7b, + 0xbb, 0x05, 0xc7, 0x59, 0x35, 0xc9, 0x8b, 0x0c, 0xe2, 0x84, 0xa8, 0x65, 0x19, 0xe6, 0xfb, 0x18, + 0x8e, 0x46, 0xae, 0x09, 0x79, 0x9e, 0xf6, 0x46, 0x34, 0x4f, 0x3b, 0xee, 0x72, 0xd1, 0x4f, 0xd3, + 0xfe, 0x71, 0x2e, 0xe4, 0xd7, 0x53, 0xd2, 0x2e, 0xb7, 0xa2, 0x59, 0xda, 0xf3, 0xe3, 0x78, 0x47, + 0x92, 0xb4, 0xc3, 0x56, 0x9b, 0x4f, 0xb0, 0xda, 0x8f, 0x87, 0x32, 0x3b, 0x85, 0xb4, 0x5c, 0x78, + 0x4c, 0xda, 0xaf, 0x25, 0xa7, 0xa3, 0xb0, 0x4c, 0xae, 0xdf, 0xb5, 0x9f, 0xce, 0xb9, 0x19, 0x4b, + 0xe7, 0x9c, 0x1d, 0x2b, 0xaf, 0x9f, 0xc8, 0xf9, 0x8b, 0x02, 0x94, 0xfc, 0x77, 0x43, 0x3a, 0x1f, + 0x56, 0x5b, 0x2e, 0x41, 0x6d, 0xe1, 0x1d, 0x38, 0xff, 0x52, 0x3b, 0x70, 0x21, 0xf3, 0x0e, 0x7c, + 0x12, 0x4a, 0xf4, 0x81, 0x96, 0xef, 0xb2, 0x1d, 0xb5, 0x48, 0x01, 0x0a, 0xde, 0x0f, 0xcc, 0x70, + 0x66, 0x22, 0x33, 0x8c, 0xe5, 0x8e, 0x67, 0xe3, 0xb9, 0xe3, 0x3b, 0xfe, 0x8e, 0x58, 0x4c, 0xbb, + 0x5a, 0xf6, 0xf9, 0x26, 0xee, 0x85, 0xb1, 0x6b, 0xca, 0x52, 0xda, 0x35, 0x65, 0xc0, 0xe5, 0x5b, + 0x9b, 0x1b, 0xda, 0x65, 0x09, 0xe1, 0xb0, 0x2d, 0x72, 0xcf, 0x7a, 0x2b, 0x92, 0x65, 0x60, 0x09, + 0xc0, 0x93, 0x23, 0xc6, 0x18, 0x49, 0x30, 0xec, 0xc2, 0xf1, 0xc8, 0xd4, 0x04, 0x05, 0x6e, 0xd9, + 0xfc, 0x63, 0x4a, 0x75, 0xdb, 0xff, 0x4d, 0x87, 0xfc, 0x4b, 0x4a, 0xe1, 0xd6, 0x9d, 0xa1, 0x8c, + 0xe2, 0x84, 0x56, 0x7c, 0x23, 0x5a, 0xb2, 0xf0, 0x82, 0x56, 0x37, 0x54, 0xb1, 0x40, 0x23, 0x17, + 0xcd, 0xe1, 0xaf, 0xd9, 0x55, 0x6b, 0x89, 0x43, 0xd6, 0xe8, 0xc9, 0x60, 0xdf, 0x30, 0x0d, 0xf7, + 0x80, 0xbd, 0x9f, 0x61, 0x27, 0x03, 0x01, 0x5a, 0xa3, 0x57, 0x84, 0xf8, 0xb9, 0xe1, 0xa9, 0x1d, + 0x4b, 0xc7, 0xd4, 0xa6, 0xa7, 0x95, 0x22, 0x01, 0xac, 0x5b, 0x3a, 0x0e, 0x56, 0x5e, 0xf1, 0xc5, + 0x56, 0x5e, 0x29, 0xb6, 0xf2, 0x8e, 0xc3, 0x8c, 0x83, 0x35, 0xd7, 0x32, 0xd9, 0x85, 0x82, 0xc2, + 0x5b, 0x64, 0x6a, 0xfa, 0xd8, 0x75, 0x49, 0x4f, 0x3c, 0x5c, 0xe3, 0xcd, 0x50, 0x98, 0x39, 0x37, + 0x36, 0xcc, 0x1c, 0x51, 0x10, 0x16, 0x0b, 0x33, 0x2b, 0x63, 0xc3, 0xcc, 0x4c, 0xf5, 0x60, 0x41, + 0xa0, 0x5d, 0xcd, 0x16, 0x68, 0x87, 0xe3, 0xd2, 0xf9, 0x48, 0x5c, 0xfa, 0x4d, 0x2e, 0xd6, 0x5f, + 0x4a, 0xb0, 0x38, 0xb4, 0xac, 0xf8, 0x72, 0xbd, 0x19, 0xab, 0x18, 0x3b, 0x3b, 0x56, 0x67, 0x7e, + 0xc1, 0xd8, 0x83, 0x48, 0xc1, 0xd8, 0x1b, 0xe3, 0x09, 0xbf, 0xf4, 0x7a, 0xb1, 0xff, 0xcd, 0xc1, + 0xe9, 0x5d, 0x5b, 0x8f, 0x45, 0x78, 0xfc, 0xd8, 0x9f, 0xdd, 0x71, 0xdc, 0x89, 0x26, 0xa3, 0x27, + 0xb8, 0xc1, 0xe2, 0xe1, 0xfe, 0x66, 0x3c, 0x1f, 0x3d, 0xd1, 0xfd, 0x84, 0xa0, 0x45, 0x7a, 0x52, + 0x19, 0xc1, 0xbd, 0x84, 0x64, 0xd9, 0xe8, 0x21, 0x7f, 0xc5, 0xc9, 0x2d, 0x19, 0xce, 0xa4, 0x0b, + 0xc0, 0xe3, 0xc3, 0x1f, 0xc0, 0xfc, 0xe6, 0x73, 0xdc, 0x69, 0x1f, 0x9a, 0x9d, 0x09, 0xe6, 0xa1, + 0x06, 0xf9, 0x4e, 0x5f, 0xe7, 0x17, 0xfe, 0xe4, 0x31, 0x1c, 0xf2, 0xe6, 0xa3, 0x21, 0xaf, 0x0a, + 0xb5, 0xa0, 0x07, 0x6e, 0xcb, 0xc7, 0x89, 0x2d, 0xeb, 0x04, 0x99, 0x30, 0x9f, 0x53, 0x78, 0x8b, + 0xc3, 0xb1, 0xc3, 0x8a, 0xc9, 0x19, 0x1c, 0x3b, 0x4e, 0xd4, 0x35, 0xe6, 0xa3, 0xae, 0x51, 0xfe, + 0x43, 0x09, 0xca, 0xa4, 0x87, 0x97, 0x92, 0x9f, 0x9f, 0x2b, 0xf3, 0xc1, 0xb9, 0xd2, 0x3f, 0x9e, + 0x16, 0xc2, 0xc7, 0xd3, 0x40, 0xf2, 0x69, 0x0a, 0x1e, 0x96, 0x7c, 0xc6, 0x87, 0x63, 0xc7, 0x91, + 0xcf, 0xc0, 0x1c, 0x93, 0x8d, 0x8f, 0xbc, 0x06, 0xf9, 0x81, 0xd3, 0x13, 0xf3, 0x37, 0x70, 0x7a, + 0xf2, 0x4f, 0x25, 0xa8, 0xac, 0x79, 0x9e, 0xd6, 0x39, 0x98, 0x60, 0x00, 0xbe, 0x70, 0xb9, 0xb0, + 0x70, 0xc3, 0x83, 0x08, 0xc4, 0x2d, 0xa4, 0x88, 0x3b, 0x1d, 0x11, 0x57, 0x86, 0xaa, 0x90, 0x25, + 0x55, 0xe0, 0x2d, 0x40, 0x2d, 0xcb, 0xf1, 0xee, 0x5b, 0xce, 0x33, 0xcd, 0xd1, 0x27, 0x3b, 0x6e, + 0x22, 0x28, 0xf0, 0x8f, 0x57, 0xf3, 0x97, 0xa6, 0x15, 0xfa, 0x2c, 0x5f, 0x84, 0xa3, 0x11, 0x7e, + 0xa9, 0x1d, 0xdf, 0x85, 0x32, 0xdd, 0xe4, 0xf8, 0xb9, 0xe3, 0x7a, 0x38, 0xc3, 0x9c, 0x69, 0x4b, + 0x94, 0xbf, 0x0b, 0x47, 0x48, 0x30, 0x44, 0xe1, 0xbe, 0xdf, 0x79, 0x2b, 0x16, 0x94, 0x9f, 0x4a, + 0x61, 0x14, 0x0b, 0xc8, 0x7f, 0x2d, 0xc1, 0x34, 0x85, 0x0f, 0x05, 0x28, 0x27, 0xa1, 0xe4, 0x60, + 0xdb, 0x52, 0x3d, 0xad, 0xeb, 0x7f, 0x2a, 0x4c, 0x00, 0x3b, 0x5a, 0x97, 0x26, 0x33, 0xe8, 0x4b, + 0xdd, 0xe8, 0x62, 0xd7, 0x13, 0xdf, 0x0b, 0x97, 0x09, 0x6c, 0x83, 0x81, 0x88, 0x92, 0x68, 0x9a, + 0xb0, 0x40, 0xb3, 0x81, 0xf4, 0x19, 0x2d, 0xb3, 0x6f, 0x98, 0xb2, 0x64, 0x87, 0xe8, 0x17, 0x4e, + 0x0d, 0x28, 0xc6, 0x12, 0x3a, 0x7e, 0x1b, 0x5d, 0x83, 0x02, 0xbd, 0x02, 0x9e, 0x1d, 0xaf, 0x37, + 0x8a, 0x28, 0x6f, 0x02, 0x0a, 0xab, 0x8d, 0x4f, 0xd0, 0x35, 0x98, 0xa1, 0x5a, 0x15, 0xb1, 0xe3, + 0x62, 0x0a, 0x23, 0x85, 0xa3, 0xc9, 0x1a, 0x20, 0xc6, 0x39, 0x12, 0x2f, 0x4e, 0x3e, 0x8d, 0x23, + 0xe2, 0xc7, 0xbf, 0x96, 0xe0, 0x68, 0xa4, 0x0f, 0x2e, 0xeb, 0xd5, 0x68, 0x27, 0xa9, 0xa2, 0xf2, + 0x0e, 0xd6, 0x23, 0x1b, 0xe6, 0xb5, 0x34, 0x91, 0xbe, 0xa2, 0xcd, 0xf2, 0x9f, 0x24, 0x80, 0xb5, + 0x81, 0x77, 0xc0, 0xef, 0x4d, 0xc3, 0x53, 0x29, 0xc5, 0xa6, 0xb2, 0x01, 0x45, 0x5b, 0x73, 0xdd, + 0x67, 0x96, 0x23, 0x4e, 0x7c, 0x7e, 0x9b, 0xde, 0x70, 0x0e, 0xbc, 0x03, 0x91, 0x06, 0x26, 0xcf, + 0xe8, 0x3c, 0x54, 0xd9, 0xf7, 0xec, 0xaa, 0xa6, 0xeb, 0x8e, 0x28, 0x4d, 0x2a, 0x29, 0x15, 0x06, + 0x5d, 0x63, 0x40, 0x82, 0x66, 0xd0, 0xb4, 0x80, 0x77, 0xa8, 0x7a, 0xd6, 0x13, 0x6c, 0xf2, 0x93, + 0x5b, 0x45, 0x40, 0x77, 0x08, 0x90, 0x65, 0xdd, 0xba, 0x86, 0xeb, 0x39, 0x02, 0x4d, 0xe4, 0x0e, + 0x39, 0x94, 0xa2, 0x91, 0x49, 0xa9, 0xb5, 0x06, 0xbd, 0x1e, 0x53, 0xf1, 0x8b, 0x4f, 0xfb, 0x77, + 0xf8, 0x80, 0x72, 0x69, 0x8b, 0x20, 0x50, 0x1a, 0x1f, 0xee, 0x97, 0x78, 0x45, 0xf5, 0x1d, 0x38, + 0x12, 0x1a, 0x03, 0x37, 0xab, 0x48, 0x88, 0x2d, 0x45, 0x43, 0x6c, 0xf9, 0x01, 0x20, 0x76, 0x2b, + 0xf3, 0x92, 0xe3, 0x96, 0x8f, 0xc1, 0xd1, 0x08, 0x23, 0xbe, 0x75, 0x5f, 0x81, 0x0a, 0x2f, 0x7d, + 0xe2, 0x86, 0x72, 0x02, 0x8a, 0xc4, 0x05, 0x77, 0x0c, 0x5d, 0xd4, 0x08, 0xcc, 0xda, 0x96, 0xbe, + 0x6e, 0xe8, 0x8e, 0xfc, 0x01, 0x54, 0xf8, 0x47, 0xb1, 0x1c, 0xf7, 0x3e, 0x54, 0x79, 0x9d, 0x9a, + 0x1a, 0xf9, 0x06, 0xec, 0x74, 0x6a, 0x15, 0x96, 0x50, 0x8b, 0x19, 0x6e, 0xca, 0x3a, 0x34, 0x58, + 0x8c, 0x11, 0x61, 0x2f, 0x06, 0x7b, 0x1f, 0x44, 0x69, 0xf4, 0xd8, 0x5e, 0xa2, 0xf4, 0x15, 0x27, + 0xdc, 0x94, 0x4f, 0xc1, 0xc9, 0xc4, 0x5e, 0xb8, 0x26, 0x6c, 0xa8, 0x05, 0x2f, 0xd8, 0x87, 0x4a, + 0x7e, 0x11, 0x84, 0x14, 0x2a, 0x82, 0x38, 0xee, 0x87, 0xd0, 0x39, 0xb1, 0xeb, 0xd1, 0xf8, 0x38, + 0x38, 0x0c, 0xe5, 0xd3, 0x0e, 0x43, 0x85, 0xc8, 0x61, 0x48, 0x6e, 0xfb, 0xfa, 0xe4, 0x87, 0xd4, + 0x7b, 0xf4, 0x30, 0xcd, 0xfa, 0x16, 0x0e, 0x51, 0x1e, 0x35, 0x4a, 0x86, 0xaa, 0x84, 0xa8, 0xe4, + 0xcb, 0x50, 0x89, 0xba, 0xc6, 0x90, 0x9f, 0x93, 0x86, 0xfc, 0x5c, 0x35, 0xe6, 0xe2, 0xde, 0x8e, + 0x9d, 0x0f, 0xd2, 0x75, 0x1c, 0x3b, 0x1d, 0xdc, 0x8e, 0x38, 0xbb, 0x2b, 0x09, 0x39, 0xed, 0xaf, + 0xc8, 0xcf, 0x2d, 0xf0, 0xfd, 0xe0, 0xbe, 0x4b, 0xe8, 0xf9, 0xa0, 0xe5, 0x73, 0x50, 0xde, 0x4d, + 0xfb, 0x8b, 0x83, 0x82, 0xa8, 0xc1, 0xba, 0x01, 0x0b, 0xf7, 0x8d, 0x1e, 0x76, 0x0f, 0x5d, 0x0f, + 0xf7, 0x9b, 0xd4, 0x29, 0xed, 0x1b, 0xd8, 0x41, 0x4b, 0x00, 0xf4, 0x80, 0x67, 0x5b, 0x86, 0xff, + 0xb1, 0x76, 0x08, 0x22, 0xff, 0x97, 0x04, 0xf3, 0x01, 0x61, 0x96, 0xca, 0xb8, 0x5b, 0x30, 0xbd, + 0xef, 0x8a, 0x0b, 0xb5, 0xc4, 0xf4, 0x42, 0x92, 0x20, 0x4a, 0x61, 0xdf, 0x6d, 0xea, 0xe8, 0x5d, + 0x80, 0x81, 0x8b, 0x75, 0x9e, 0xe1, 0xcb, 0x54, 0x37, 0x58, 0x22, 0x04, 0xac, 0x7c, 0xeb, 0x36, + 0x94, 0x0d, 0xd3, 0xd2, 0x31, 0xcd, 0xee, 0xea, 0xd9, 0x6a, 0x07, 0x81, 0x51, 0xec, 0xba, 0x58, + 0x97, 0x31, 0xdf, 0x0b, 0x85, 0x7e, 0xb9, 0xa1, 0x6c, 0xc1, 0x11, 0xe6, 0xb4, 0xf6, 0x7d, 0xc1, + 0x47, 0xd4, 0x7f, 0xc7, 0xb4, 0xa5, 0xd4, 0x0c, 0x1e, 0x0b, 0x09, 0x52, 0x79, 0x15, 0x8e, 0xc5, + 0x2a, 0x51, 0xb3, 0xdf, 0x5c, 0xb7, 0x62, 0xd7, 0x48, 0x81, 0x39, 0xdf, 0x88, 0x7e, 0x1f, 0x30, + 0xbe, 0xfc, 0x95, 0x17, 0xa6, 0x7f, 0x0c, 0x27, 0x22, 0xf7, 0x5d, 0x11, 0x89, 0x6e, 0xc7, 0x42, + 0xbd, 0x0b, 0xe3, 0xb8, 0xc6, 0x62, 0xbe, 0xff, 0x91, 0x60, 0x21, 0x09, 0xe1, 0x05, 0xef, 0x63, + 0x7f, 0x90, 0xf2, 0x45, 0xd2, 0xcd, 0x6c, 0x62, 0x7d, 0x2d, 0x77, 0xd9, 0x3b, 0xec, 0xfb, 0x84, + 0xf1, 0xb3, 0x94, 0x9f, 0x64, 0x96, 0x7e, 0x92, 0x0f, 0xe5, 0x25, 0x46, 0x7c, 0x3d, 0xf0, 0xd2, + 0x77, 0x7d, 0xcd, 0xd8, 0xc7, 0x03, 0xd7, 0x47, 0x90, 0x8f, 0xf9, 0x76, 0xe0, 0xc3, 0xa4, 0x43, + 0xff, 0x8d, 0x6c, 0xfc, 0xbe, 0xb5, 0xd7, 0xc3, 0x3f, 0xc9, 0x41, 0x35, 0x3a, 0x45, 0x68, 0x33, + 0xe1, 0xcb, 0x81, 0xf3, 0x99, 0x86, 0x19, 0xf9, 0x70, 0x80, 0x57, 0xe7, 0xe7, 0x26, 0xad, 0xce, + 0xcf, 0x4f, 0x52, 0x9d, 0xff, 0x10, 0xaa, 0xcf, 0x1c, 0xc3, 0xd3, 0xf6, 0x7a, 0x58, 0xed, 0x69, + 0x87, 0xd8, 0xe1, 0x5e, 0x32, 0x83, 0x23, 0xab, 0x08, 0xc2, 0x47, 0x84, 0x4e, 0xfe, 0x3b, 0x09, + 0x8a, 0x42, 0xa4, 0xb1, 0x35, 0xf1, 0x8b, 0x03, 0x82, 0xa6, 0xd2, 0xba, 0x5a, 0x53, 0x33, 0x2d, + 0xd5, 0xc5, 0x64, 0x1f, 0xcf, 0x58, 0x55, 0xbe, 0x40, 0xa9, 0xd7, 0x2d, 0x07, 0x6f, 0x69, 0xa6, + 0xd5, 0x66, 0xa4, 0xe8, 0x01, 0xd4, 0x18, 0x57, 0xca, 0x90, 0xb0, 0xce, 0xb8, 0x63, 0x54, 0x29, + 0x19, 0x61, 0x45, 0x58, 0xba, 0xf2, 0xdf, 0xe6, 0xa1, 0x1c, 0xd2, 0xd5, 0x98, 0xc1, 0x34, 0xe1, + 0x88, 0xa8, 0x79, 0x70, 0xb1, 0x37, 0x49, 0x71, 0xfc, 0x3c, 0xa7, 0x6b, 0x63, 0x8f, 0xed, 0x57, + 0xf7, 0x61, 0x5e, 0x7b, 0xaa, 0x19, 0x3d, 0x3a, 0x1b, 0x13, 0x6c, 0x79, 0x55, 0x9f, 0xca, 0xdf, + 0xf7, 0x98, 0x26, 0x26, 0xa8, 0x99, 0x07, 0x4a, 0x11, 0x14, 0xeb, 0xbb, 0x2e, 0xa7, 0xce, 0x56, + 0x36, 0xef, 0xb8, 0xae, 0xdf, 0x37, 0xad, 0xd3, 0xa5, 0x1f, 0x2c, 0xb8, 0xfc, 0xe3, 0xe9, 0x71, + 0x7d, 0x13, 0x8a, 0xfb, 0x94, 0x80, 0xa8, 0xb3, 0xaf, 0x7d, 0x6a, 0x39, 0x6a, 0x98, 0xcb, 0x6c, + 0x26, 0x75, 0x52, 0xba, 0x96, 0xcf, 0x4a, 0xbe, 0x0d, 0x27, 0x14, 0x6c, 0xd9, 0xd8, 0xf4, 0x57, + 0xda, 0x23, 0xab, 0x3b, 0xc1, 0xde, 0xfa, 0x0a, 0x34, 0x92, 0xe8, 0x99, 0xe7, 0xbe, 0x72, 0x01, + 0x8a, 0xe2, 0x6f, 0xc6, 0xd0, 0x2c, 0xe4, 0x77, 0xd6, 0x5b, 0xb5, 0x29, 0xf2, 0xb0, 0xbb, 0xd1, + 0xaa, 0x49, 0xa8, 0x08, 0x85, 0xf6, 0xfa, 0x4e, 0xab, 0x96, 0xbb, 0xd2, 0x87, 0x5a, 0xfc, 0x3f, + 0xb6, 0xd0, 0x22, 0x1c, 0x6d, 0x29, 0xdb, 0xad, 0xb5, 0x07, 0x6b, 0x3b, 0xcd, 0xed, 0x2d, 0xb5, + 0xa5, 0x34, 0xdf, 0x5f, 0xdb, 0xd9, 0xac, 0x4d, 0xa1, 0xb3, 0x70, 0x2a, 0xfc, 0xe2, 0xe1, 0x76, + 0x7b, 0x47, 0xdd, 0xd9, 0x56, 0xd7, 0xb7, 0xb7, 0x76, 0xd6, 0x9a, 0x5b, 0x9b, 0x4a, 0x4d, 0x42, + 0xa7, 0xe0, 0x44, 0x18, 0xe5, 0x5e, 0x73, 0xa3, 0xa9, 0x6c, 0xae, 0x93, 0xe7, 0xb5, 0x47, 0xb5, + 0xdc, 0x95, 0xf7, 0xa0, 0x12, 0xf9, 0x4b, 0x2c, 0x22, 0x52, 0x6b, 0x7b, 0xa3, 0x36, 0x85, 0x2a, + 0x50, 0x0a, 0xf3, 0x29, 0x42, 0x61, 0x6b, 0x7b, 0x63, 0xb3, 0x96, 0x43, 0x00, 0x33, 0x3b, 0x6b, + 0xca, 0x83, 0xcd, 0x9d, 0x5a, 0xfe, 0xca, 0x6a, 0xfc, 0x43, 0x28, 0x8c, 0x8e, 0x40, 0xa5, 0xbd, + 0xb6, 0xb5, 0x71, 0x6f, 0xfb, 0x43, 0x55, 0xd9, 0x5c, 0xdb, 0xf8, 0xa8, 0x36, 0x85, 0x16, 0xa0, + 0x26, 0x40, 0x5b, 0xdb, 0x3b, 0x0c, 0x2a, 0x5d, 0x79, 0x12, 0xf3, 0x84, 0x18, 0x1d, 0x83, 0x23, + 0x7e, 0x97, 0xea, 0xba, 0xb2, 0xb9, 0xb6, 0xb3, 0x49, 0x24, 0x89, 0x80, 0x95, 0xdd, 0xad, 0xad, + 0xe6, 0xd6, 0x83, 0x9a, 0x44, 0xb8, 0x06, 0xe0, 0xcd, 0x0f, 0x9b, 0x04, 0x39, 0x17, 0x45, 0xde, + 0xdd, 0xfa, 0xde, 0xd6, 0xf6, 0x07, 0x5b, 0xb5, 0xfc, 0xca, 0xcf, 0x8e, 0xfa, 0x7f, 0x53, 0xd4, + 0xc6, 0x0e, 0xad, 0xcc, 0x6a, 0xc1, 0xac, 0xf8, 0x0b, 0xbb, 0x84, 0x7d, 0x34, 0xfa, 0xc7, 0x7b, + 0x8d, 0xb3, 0x23, 0x30, 0xf8, 0xa9, 0x68, 0x0a, 0xed, 0xd1, 0x53, 0x4a, 0xe8, 0xf3, 0xdf, 0x0b, + 0x89, 0x67, 0x82, 0xa1, 0x2f, 0x8e, 0x1b, 0x17, 0xc7, 0xe2, 0xf9, 0x7d, 0x60, 0x72, 0x10, 0x09, + 0xff, 0xc3, 0x06, 0xba, 0x98, 0x74, 0x82, 0x48, 0xf8, 0x0b, 0x8f, 0xc6, 0xa5, 0xf1, 0x88, 0x7e, + 0x37, 0x4f, 0xa0, 0x16, 0xff, 0xb7, 0x0d, 0x94, 0x70, 0xfd, 0x9f, 0xf2, 0x97, 0x1e, 0x8d, 0x2b, + 0x59, 0x50, 0xc3, 0x9d, 0x0d, 0xfd, 0x7d, 0xc4, 0xe5, 0x2c, 0x9f, 0xd9, 0xa7, 0x76, 0x96, 0xf6, + 0x45, 0x3e, 0x53, 0x60, 0xf4, 0x0b, 0x4d, 0x94, 0xf8, 0x5f, 0x0d, 0x09, 0x1f, 0x86, 0x27, 0x29, + 0x30, 0xf9, 0xe3, 0x5f, 0x79, 0x0a, 0x1d, 0xc0, 0x7c, 0xac, 0xc4, 0x06, 0x25, 0x90, 0x27, 0xd7, + 0x12, 0x35, 0x2e, 0x67, 0xc0, 0x8c, 0x5a, 0x44, 0xb8, 0xa4, 0x26, 0xd9, 0x22, 0x12, 0x0a, 0x76, + 0x92, 0x2d, 0x22, 0xb1, 0x3a, 0x87, 0x1a, 0x77, 0xa4, 0x94, 0x26, 0xc9, 0xb8, 0x93, 0x0a, 0x78, + 0x1a, 0x17, 0xc7, 0xe2, 0x85, 0x95, 0x16, 0x2b, 0xac, 0x49, 0x52, 0x5a, 0x72, 0xe1, 0x4e, 0xe3, + 0x72, 0x06, 0xcc, 0xb8, 0x15, 0x04, 0x69, 0xfa, 0x34, 0x2b, 0x18, 0x2a, 0x2a, 0x49, 0xb3, 0x82, + 0xe1, 0x8c, 0x3f, 0xb7, 0x82, 0x58, 0x7a, 0xfd, 0x52, 0x86, 0x74, 0x60, 0xba, 0x15, 0x24, 0x27, + 0x0e, 0xe5, 0x29, 0xf4, 0x63, 0x09, 0xea, 0x69, 0xd9, 0x27, 0x74, 0x7d, 0xe2, 0x54, 0x59, 0x63, + 0x65, 0x12, 0x12, 0x5f, 0x8a, 0xcf, 0x00, 0x0d, 0xef, 0x81, 0xe8, 0xb5, 0xa4, 0x99, 0x49, 0xd9, + 0x69, 0x1b, 0xaf, 0x67, 0x43, 0xf6, 0xbb, 0x6c, 0x43, 0x51, 0xe4, 0xbb, 0x50, 0x82, 0x97, 0x8e, + 0x65, 0xdb, 0x1a, 0xf2, 0x28, 0x14, 0x9f, 0xe9, 0x03, 0x28, 0x10, 0x28, 0x3a, 0x95, 0x8c, 0x2d, + 0x98, 0x2d, 0xa5, 0xbd, 0xf6, 0x19, 0x3d, 0x86, 0x19, 0x96, 0xe0, 0x41, 0x09, 0xf7, 0x43, 0x91, + 0x34, 0x54, 0xe3, 0x4c, 0x3a, 0x82, 0xcf, 0xee, 0x13, 0xf6, 0xef, 0xa6, 0x3c, 0x77, 0x83, 0x5e, + 0x4d, 0xfe, 0xd3, 0xb0, 0x68, 0xaa, 0xa8, 0x71, 0x7e, 0x0c, 0x56, 0x78, 0x51, 0xc4, 0xce, 0x26, + 0x17, 0xc7, 0x1e, 0x30, 0xd3, 0x17, 0x45, 0xf2, 0x11, 0x96, 0x19, 0xc9, 0xf0, 0x11, 0x37, 0xc9, + 0x48, 0x52, 0x2f, 0x16, 0x92, 0x8c, 0x24, 0xfd, 0xd4, 0xcc, 0xd6, 0x61, 0xfc, 0x6b, 0xe6, 0x4b, + 0xe3, 0xbf, 0xbd, 0x4f, 0x5f, 0x87, 0x29, 0xdf, 0xf7, 0xcb, 0x53, 0xc8, 0x83, 0xa3, 0x09, 0x7f, + 0x00, 0x80, 0x5e, 0x1f, 0xb7, 0x75, 0x44, 0x7a, 0xbc, 0x9a, 0x11, 0x3b, 0xdc, 0x6b, 0xc2, 0x85, + 0x6d, 0x52, 0xaf, 0xe9, 0xb7, 0xc7, 0x49, 0xbd, 0x8e, 0xba, 0x05, 0xa6, 0xc6, 0xcd, 0x9d, 0xda, + 0xe9, 0xf4, 0x5b, 0xcc, 0x54, 0xe3, 0x8e, 0xbb, 0xb0, 0x95, 0x5f, 0xe5, 0x61, 0x8e, 0x5d, 0xc6, + 0xf3, 0x08, 0xed, 0x23, 0x80, 0x20, 0x0f, 0x86, 0xce, 0x25, 0x2b, 0x25, 0x92, 0x5c, 0x6c, 0xbc, + 0x3a, 0x1a, 0x29, 0xbc, 0x90, 0x42, 0x39, 0xa5, 0xa4, 0x85, 0x34, 0x9c, 0x3a, 0x4b, 0x5a, 0x48, + 0x09, 0x89, 0x29, 0x79, 0x0a, 0xbd, 0x0f, 0x25, 0x3f, 0x79, 0x81, 0x92, 0x92, 0x1f, 0xb1, 0xec, + 0x4c, 0xe3, 0xdc, 0x48, 0x9c, 0xb0, 0xd4, 0xa1, 0xcc, 0x44, 0x92, 0xd4, 0xc3, 0x19, 0x90, 0x24, + 0xa9, 0x93, 0xd2, 0x1b, 0x81, 0x4e, 0xd8, 0xfd, 0x65, 0xaa, 0x4e, 0x22, 0xd7, 0xc7, 0xa9, 0x3a, + 0x89, 0x5e, 0x82, 0xca, 0x53, 0xf7, 0x2e, 0xfc, 0xe2, 0xf3, 0x25, 0xe9, 0x5f, 0x3f, 0x5f, 0x9a, + 0xfa, 0xd1, 0x17, 0x4b, 0xd2, 0x2f, 0xbe, 0x58, 0x92, 0xfe, 0xe5, 0x8b, 0x25, 0xe9, 0xdf, 0xbf, + 0x58, 0x92, 0x7e, 0xf7, 0x3f, 0x96, 0xa6, 0xbe, 0x5f, 0x14, 0xd4, 0x7b, 0x33, 0xf4, 0x3f, 0x98, + 0xdf, 0xf8, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x2a, 0xb2, 0xfb, 0xb6, 0x49, 0x5b, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -7665,6 +8493,11 @@ type RuntimeServiceClient interface { ContainerStats(ctx context.Context, in *ContainerStatsRequest, opts ...grpc.CallOption) (*ContainerStatsResponse, error) // ListContainerStats returns stats of all running containers. ListContainerStats(ctx context.Context, in *ListContainerStatsRequest, opts ...grpc.CallOption) (*ListContainerStatsResponse, error) + // PodSandboxStats returns stats of the pod sandbox. If the pod sandbox does not + // exist, the call returns an error. + PodSandboxStats(ctx context.Context, in *PodSandboxStatsRequest, opts ...grpc.CallOption) (*PodSandboxStatsResponse, error) + // ListPodSandboxStats returns stats of the pod sandboxes matching a filter. + ListPodSandboxStats(ctx context.Context, in *ListPodSandboxStatsRequest, opts ...grpc.CallOption) (*ListPodSandboxStatsResponse, error) // UpdateRuntimeConfig updates the runtime configuration based on the given request. UpdateRuntimeConfig(ctx context.Context, in *UpdateRuntimeConfigRequest, opts ...grpc.CallOption) (*UpdateRuntimeConfigResponse, error) // Status returns the status of the runtime. @@ -7859,6 +8692,24 @@ func (c *runtimeServiceClient) ListContainerStats(ctx context.Context, in *ListC return out, nil } +func (c *runtimeServiceClient) PodSandboxStats(ctx context.Context, in *PodSandboxStatsRequest, opts ...grpc.CallOption) (*PodSandboxStatsResponse, error) { + out := new(PodSandboxStatsResponse) + err := c.cc.Invoke(ctx, "/runtime.v1alpha2.RuntimeService/PodSandboxStats", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *runtimeServiceClient) ListPodSandboxStats(ctx context.Context, in *ListPodSandboxStatsRequest, opts ...grpc.CallOption) (*ListPodSandboxStatsResponse, error) { + out := new(ListPodSandboxStatsResponse) + err := c.cc.Invoke(ctx, "/runtime.v1alpha2.RuntimeService/ListPodSandboxStats", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *runtimeServiceClient) UpdateRuntimeConfig(ctx context.Context, in *UpdateRuntimeConfigRequest, opts ...grpc.CallOption) (*UpdateRuntimeConfigResponse, error) { out := new(UpdateRuntimeConfigResponse) err := c.cc.Invoke(ctx, "/runtime.v1alpha2.RuntimeService/UpdateRuntimeConfig", in, out, opts...) @@ -7944,6 +8795,11 @@ type RuntimeServiceServer interface { ContainerStats(context.Context, *ContainerStatsRequest) (*ContainerStatsResponse, error) // ListContainerStats returns stats of all running containers. ListContainerStats(context.Context, *ListContainerStatsRequest) (*ListContainerStatsResponse, error) + // PodSandboxStats returns stats of the pod sandbox. If the pod sandbox does not + // exist, the call returns an error. + PodSandboxStats(context.Context, *PodSandboxStatsRequest) (*PodSandboxStatsResponse, error) + // ListPodSandboxStats returns stats of the pod sandboxes matching a filter. + ListPodSandboxStats(context.Context, *ListPodSandboxStatsRequest) (*ListPodSandboxStatsResponse, error) // UpdateRuntimeConfig updates the runtime configuration based on the given request. UpdateRuntimeConfig(context.Context, *UpdateRuntimeConfigRequest) (*UpdateRuntimeConfigResponse, error) // Status returns the status of the runtime. @@ -8014,6 +8870,12 @@ func (*UnimplementedRuntimeServiceServer) ContainerStats(ctx context.Context, re func (*UnimplementedRuntimeServiceServer) ListContainerStats(ctx context.Context, req *ListContainerStatsRequest) (*ListContainerStatsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListContainerStats not implemented") } +func (*UnimplementedRuntimeServiceServer) PodSandboxStats(ctx context.Context, req *PodSandboxStatsRequest) (*PodSandboxStatsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PodSandboxStats not implemented") +} +func (*UnimplementedRuntimeServiceServer) ListPodSandboxStats(ctx context.Context, req *ListPodSandboxStatsRequest) (*ListPodSandboxStatsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListPodSandboxStats not implemented") +} func (*UnimplementedRuntimeServiceServer) UpdateRuntimeConfig(ctx context.Context, req *UpdateRuntimeConfigRequest) (*UpdateRuntimeConfigResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method UpdateRuntimeConfig not implemented") } @@ -8385,6 +9247,42 @@ func _RuntimeService_ListContainerStats_Handler(srv interface{}, ctx context.Con return interceptor(ctx, in, info, handler) } +func _RuntimeService_PodSandboxStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PodSandboxStatsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RuntimeServiceServer).PodSandboxStats(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/runtime.v1alpha2.RuntimeService/PodSandboxStats", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RuntimeServiceServer).PodSandboxStats(ctx, req.(*PodSandboxStatsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _RuntimeService_ListPodSandboxStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListPodSandboxStatsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RuntimeServiceServer).ListPodSandboxStats(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/runtime.v1alpha2.RuntimeService/ListPodSandboxStats", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RuntimeServiceServer).ListPodSandboxStats(ctx, req.(*ListPodSandboxStatsRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _RuntimeService_UpdateRuntimeConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(UpdateRuntimeConfigRequest) if err := dec(in); err != nil { @@ -8505,6 +9403,14 @@ var _RuntimeService_serviceDesc = grpc.ServiceDesc{ MethodName: "ListContainerStats", Handler: _RuntimeService_ListContainerStats_Handler, }, + { + MethodName: "PodSandboxStats", + Handler: _RuntimeService_PodSandboxStats_Handler, + }, + { + MethodName: "ListPodSandboxStats", + Handler: _RuntimeService_ListPodSandboxStats_Handler, + }, { MethodName: "UpdateRuntimeConfig", Handler: _RuntimeService_UpdateRuntimeConfig_Handler, @@ -9259,6 +10165,30 @@ func (m *LinuxPodSandboxConfig) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Resources != nil { + { + size, err := m.Resources.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + if m.Overhead != nil { + { + size, err := m.Overhead.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } if len(m.Sysctls) > 0 { for k := range m.Sysctls { v := m.Sysctls[k] @@ -10281,6 +11211,611 @@ func (m *ListPodSandboxResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) return len(dAtA) - i, nil } +func (m *PodSandboxStatsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PodSandboxStatsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PodSandboxStatsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.PodSandboxId) > 0 { + i -= len(m.PodSandboxId) + copy(dAtA[i:], m.PodSandboxId) + i = encodeVarintApi(dAtA, i, uint64(len(m.PodSandboxId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *PodSandboxStatsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PodSandboxStatsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PodSandboxStatsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Stats != nil { + { + size, err := m.Stats.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *PodSandboxStatsFilter) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PodSandboxStatsFilter) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PodSandboxStatsFilter) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.LabelSelector) > 0 { + for k := range m.LabelSelector { + v := m.LabelSelector[k] + baseI := i + i -= len(v) + copy(dAtA[i:], v) + i = encodeVarintApi(dAtA, i, uint64(len(v))) + i-- + dAtA[i] = 0x12 + i -= len(k) + copy(dAtA[i:], k) + i = encodeVarintApi(dAtA, i, uint64(len(k))) + i-- + dAtA[i] = 0xa + i = encodeVarintApi(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0x12 + } + } + if len(m.Id) > 0 { + i -= len(m.Id) + copy(dAtA[i:], m.Id) + i = encodeVarintApi(dAtA, i, uint64(len(m.Id))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ListPodSandboxStatsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ListPodSandboxStatsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ListPodSandboxStatsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Filter != nil { + { + size, err := m.Filter.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ListPodSandboxStatsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ListPodSandboxStatsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ListPodSandboxStatsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Stats) > 0 { + for iNdEx := len(m.Stats) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Stats[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *PodSandboxAttributes) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PodSandboxAttributes) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PodSandboxAttributes) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Annotations) > 0 { + for k := range m.Annotations { + v := m.Annotations[k] + baseI := i + i -= len(v) + copy(dAtA[i:], v) + i = encodeVarintApi(dAtA, i, uint64(len(v))) + i-- + dAtA[i] = 0x12 + i -= len(k) + copy(dAtA[i:], k) + i = encodeVarintApi(dAtA, i, uint64(len(k))) + i-- + dAtA[i] = 0xa + i = encodeVarintApi(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0x22 + } + } + if len(m.Labels) > 0 { + for k := range m.Labels { + v := m.Labels[k] + baseI := i + i -= len(v) + copy(dAtA[i:], v) + i = encodeVarintApi(dAtA, i, uint64(len(v))) + i-- + dAtA[i] = 0x12 + i -= len(k) + copy(dAtA[i:], k) + i = encodeVarintApi(dAtA, i, uint64(len(k))) + i-- + dAtA[i] = 0xa + i = encodeVarintApi(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0x1a + } + } + if m.Metadata != nil { + { + size, err := m.Metadata.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Id) > 0 { + i -= len(m.Id) + copy(dAtA[i:], m.Id) + i = encodeVarintApi(dAtA, i, uint64(len(m.Id))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *PodSandboxStats) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PodSandboxStats) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PodSandboxStats) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Windows != nil { + { + size, err := m.Windows.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if m.Linux != nil { + { + size, err := m.Linux.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Attributes != nil { + { + size, err := m.Attributes.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *LinuxPodSandboxStats) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *LinuxPodSandboxStats) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *LinuxPodSandboxStats) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Containers) > 0 { + for iNdEx := len(m.Containers) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Containers[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + } + if m.Process != nil { + { + size, err := m.Process.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + if m.Network != nil { + { + size, err := m.Network.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if m.Memory != nil { + { + size, err := m.Memory.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Cpu != nil { + { + size, err := m.Cpu.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *WindowsPodSandboxStats) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *WindowsPodSandboxStats) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *WindowsPodSandboxStats) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *NetworkUsage) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *NetworkUsage) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *NetworkUsage) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Interfaces) > 0 { + for iNdEx := len(m.Interfaces) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Interfaces[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if m.DefaultInterface != nil { + { + size, err := m.DefaultInterface.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Timestamp != 0 { + i = encodeVarintApi(dAtA, i, uint64(m.Timestamp)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *NetworkInterfaceUsage) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *NetworkInterfaceUsage) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *NetworkInterfaceUsage) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.TxErrors != nil { + { + size, err := m.TxErrors.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + if m.TxBytes != nil { + { + size, err := m.TxBytes.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + if m.RxErrors != nil { + { + size, err := m.RxErrors.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if m.RxBytes != nil { + { + size, err := m.RxBytes.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintApi(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ProcessUsage) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ProcessUsage) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ProcessUsage) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ProcessCount != nil { + { + size, err := m.ProcessCount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Timestamp != 0 { + i = encodeVarintApi(dAtA, i, uint64(m.Timestamp)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func (m *ImageSpec) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -10695,21 +12230,21 @@ func (m *LinuxContainerSecurityContext) MarshalToSizedBuffer(dAtA []byte) (int, dAtA[i] = 0x4a } if len(m.SupplementalGroups) > 0 { - dAtA28 := make([]byte, len(m.SupplementalGroups)*10) - var j27 int + dAtA46 := make([]byte, len(m.SupplementalGroups)*10) + var j45 int for _, num1 := range m.SupplementalGroups { num := uint64(num1) for num >= 1<<7 { - dAtA28[j27] = uint8(uint64(num)&0x7f | 0x80) + dAtA46[j45] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j27++ + j45++ } - dAtA28[j27] = uint8(num) - j27++ + dAtA46[j45] = uint8(num) + j45++ } - i -= j27 - copy(dAtA[i:], dAtA28[:j27]) - i = encodeVarintApi(dAtA, i, uint64(j27)) + i -= j45 + copy(dAtA[i:], dAtA46[:j45]) + i = encodeVarintApi(dAtA, i, uint64(j45)) i-- dAtA[i] = 0x42 } @@ -12548,21 +14083,21 @@ func (m *PortForwardRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { var l int _ = l if len(m.Port) > 0 { - dAtA54 := make([]byte, len(m.Port)*10) - var j53 int + dAtA72 := make([]byte, len(m.Port)*10) + var j71 int for _, num1 := range m.Port { num := uint64(num1) for num >= 1<<7 { - dAtA54[j53] = uint8(uint64(num)&0x7f | 0x80) + dAtA72[j71] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j53++ + j71++ } - dAtA54[j53] = uint8(num) - j53++ + dAtA72[j71] = uint8(num) + j71++ } - i -= j53 - copy(dAtA[i:], dAtA54[:j53]) - i = encodeVarintApi(dAtA, i, uint64(j53)) + i -= j71 + copy(dAtA[i:], dAtA72[:j71]) + i = encodeVarintApi(dAtA, i, uint64(j71)) i-- dAtA[i] = 0x12 } @@ -13955,6 +15490,18 @@ func (m *CpuUsage) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.UsageNanoCores != nil { + { + size, err := m.UsageNanoCores.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } if m.UsageCoreNanoSeconds != nil { { size, err := m.UsageCoreNanoSeconds.MarshalToSizedBuffer(dAtA[:i]) @@ -13995,6 +15542,66 @@ func (m *MemoryUsage) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.MajorPageFaults != nil { + { + size, err := m.MajorPageFaults.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + if m.PageFaults != nil { + { + size, err := m.PageFaults.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + if m.RssBytes != nil { + { + size, err := m.RssBytes.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + if m.UsageBytes != nil { + { + size, err := m.UsageBytes.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + if m.AvailableBytes != nil { + { + size, err := m.AvailableBytes.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } if m.WorkingSetBytes != nil { { size, err := m.WorkingSetBytes.MarshalToSizedBuffer(dAtA[:i]) @@ -14314,6 +15921,14 @@ func (m *LinuxPodSandboxConfig) Size() (n int) { n += mapEntrySize + 1 + sovApi(uint64(mapEntrySize)) } } + if m.Overhead != nil { + l = m.Overhead.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.Resources != nil { + l = m.Resources.Size() + n += 1 + l + sovApi(uint64(l)) + } return n } @@ -14724,6 +16339,242 @@ func (m *ListPodSandboxResponse) Size() (n int) { return n } +func (m *PodSandboxStatsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.PodSandboxId) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func (m *PodSandboxStatsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Stats != nil { + l = m.Stats.Size() + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func (m *PodSandboxStatsFilter) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Id) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + if len(m.LabelSelector) > 0 { + for k, v := range m.LabelSelector { + _ = k + _ = v + mapEntrySize := 1 + len(k) + sovApi(uint64(len(k))) + 1 + len(v) + sovApi(uint64(len(v))) + n += mapEntrySize + 1 + sovApi(uint64(mapEntrySize)) + } + } + return n +} + +func (m *ListPodSandboxStatsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Filter != nil { + l = m.Filter.Size() + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func (m *ListPodSandboxStatsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Stats) > 0 { + for _, e := range m.Stats { + l = e.Size() + n += 1 + l + sovApi(uint64(l)) + } + } + return n +} + +func (m *PodSandboxAttributes) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Id) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + if m.Metadata != nil { + l = m.Metadata.Size() + n += 1 + l + sovApi(uint64(l)) + } + if len(m.Labels) > 0 { + for k, v := range m.Labels { + _ = k + _ = v + mapEntrySize := 1 + len(k) + sovApi(uint64(len(k))) + 1 + len(v) + sovApi(uint64(len(v))) + n += mapEntrySize + 1 + sovApi(uint64(mapEntrySize)) + } + } + if len(m.Annotations) > 0 { + for k, v := range m.Annotations { + _ = k + _ = v + mapEntrySize := 1 + len(k) + sovApi(uint64(len(k))) + 1 + len(v) + sovApi(uint64(len(v))) + n += mapEntrySize + 1 + sovApi(uint64(mapEntrySize)) + } + } + return n +} + +func (m *PodSandboxStats) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Attributes != nil { + l = m.Attributes.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.Linux != nil { + l = m.Linux.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.Windows != nil { + l = m.Windows.Size() + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func (m *LinuxPodSandboxStats) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Cpu != nil { + l = m.Cpu.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.Memory != nil { + l = m.Memory.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.Network != nil { + l = m.Network.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.Process != nil { + l = m.Process.Size() + n += 1 + l + sovApi(uint64(l)) + } + if len(m.Containers) > 0 { + for _, e := range m.Containers { + l = e.Size() + n += 1 + l + sovApi(uint64(l)) + } + } + return n +} + +func (m *WindowsPodSandboxStats) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *NetworkUsage) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Timestamp != 0 { + n += 1 + sovApi(uint64(m.Timestamp)) + } + if m.DefaultInterface != nil { + l = m.DefaultInterface.Size() + n += 1 + l + sovApi(uint64(l)) + } + if len(m.Interfaces) > 0 { + for _, e := range m.Interfaces { + l = e.Size() + n += 1 + l + sovApi(uint64(l)) + } + } + return n +} + +func (m *NetworkInterfaceUsage) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Name) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + if m.RxBytes != nil { + l = m.RxBytes.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.RxErrors != nil { + l = m.RxErrors.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.TxBytes != nil { + l = m.TxBytes.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.TxErrors != nil { + l = m.TxErrors.Size() + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func (m *ProcessUsage) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Timestamp != 0 { + n += 1 + sovApi(uint64(m.Timestamp)) + } + if m.ProcessCount != nil { + l = m.ProcessCount.Size() + n += 1 + l + sovApi(uint64(l)) + } + return n +} + func (m *ImageSpec) Size() (n int) { if m == nil { return 0 @@ -16262,6 +18113,10 @@ func (m *CpuUsage) Size() (n int) { l = m.UsageCoreNanoSeconds.Size() n += 1 + l + sovApi(uint64(l)) } + if m.UsageNanoCores != nil { + l = m.UsageNanoCores.Size() + n += 1 + l + sovApi(uint64(l)) + } return n } @@ -16278,6 +18133,26 @@ func (m *MemoryUsage) Size() (n int) { l = m.WorkingSetBytes.Size() n += 1 + l + sovApi(uint64(l)) } + if m.AvailableBytes != nil { + l = m.AvailableBytes.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.UsageBytes != nil { + l = m.UsageBytes.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.RssBytes != nil { + l = m.RssBytes.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.PageFaults != nil { + l = m.PageFaults.Size() + n += 1 + l + sovApi(uint64(l)) + } + if m.MajorPageFaults != nil { + l = m.MajorPageFaults.Size() + n += 1 + l + sovApi(uint64(l)) + } return n } @@ -16442,6 +18317,8 @@ func (this *LinuxPodSandboxConfig) String() string { `CgroupParent:` + fmt.Sprintf("%v", this.CgroupParent) + `,`, `SecurityContext:` + strings.Replace(this.SecurityContext.String(), "LinuxSandboxSecurityContext", "LinuxSandboxSecurityContext", 1) + `,`, `Sysctls:` + mapStringForSysctls + `,`, + `Overhead:` + strings.Replace(this.Overhead.String(), "LinuxContainerResources", "LinuxContainerResources", 1) + `,`, + `Resources:` + strings.Replace(this.Resources.String(), "LinuxContainerResources", "LinuxContainerResources", 1) + `,`, `}`, }, "") return s @@ -16770,6 +18647,187 @@ func (this *ListPodSandboxResponse) String() string { }, "") return s } +func (this *PodSandboxStatsRequest) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PodSandboxStatsRequest{`, + `PodSandboxId:` + fmt.Sprintf("%v", this.PodSandboxId) + `,`, + `}`, + }, "") + return s +} +func (this *PodSandboxStatsResponse) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PodSandboxStatsResponse{`, + `Stats:` + strings.Replace(this.Stats.String(), "PodSandboxStats", "PodSandboxStats", 1) + `,`, + `}`, + }, "") + return s +} +func (this *PodSandboxStatsFilter) String() string { + if this == nil { + return "nil" + } + keysForLabelSelector := make([]string, 0, len(this.LabelSelector)) + for k := range this.LabelSelector { + keysForLabelSelector = append(keysForLabelSelector, k) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForLabelSelector) + mapStringForLabelSelector := "map[string]string{" + for _, k := range keysForLabelSelector { + mapStringForLabelSelector += fmt.Sprintf("%v: %v,", k, this.LabelSelector[k]) + } + mapStringForLabelSelector += "}" + s := strings.Join([]string{`&PodSandboxStatsFilter{`, + `Id:` + fmt.Sprintf("%v", this.Id) + `,`, + `LabelSelector:` + mapStringForLabelSelector + `,`, + `}`, + }, "") + return s +} +func (this *ListPodSandboxStatsRequest) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ListPodSandboxStatsRequest{`, + `Filter:` + strings.Replace(this.Filter.String(), "PodSandboxStatsFilter", "PodSandboxStatsFilter", 1) + `,`, + `}`, + }, "") + return s +} +func (this *ListPodSandboxStatsResponse) String() string { + if this == nil { + return "nil" + } + repeatedStringForStats := "[]*PodSandboxStats{" + for _, f := range this.Stats { + repeatedStringForStats += strings.Replace(f.String(), "PodSandboxStats", "PodSandboxStats", 1) + "," + } + repeatedStringForStats += "}" + s := strings.Join([]string{`&ListPodSandboxStatsResponse{`, + `Stats:` + repeatedStringForStats + `,`, + `}`, + }, "") + return s +} +func (this *PodSandboxAttributes) String() string { + if this == nil { + return "nil" + } + keysForLabels := make([]string, 0, len(this.Labels)) + for k := range this.Labels { + keysForLabels = append(keysForLabels, k) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) + mapStringForLabels := "map[string]string{" + for _, k := range keysForLabels { + mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) + } + mapStringForLabels += "}" + keysForAnnotations := make([]string, 0, len(this.Annotations)) + for k := range this.Annotations { + keysForAnnotations = append(keysForAnnotations, k) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForAnnotations) + mapStringForAnnotations := "map[string]string{" + for _, k := range keysForAnnotations { + mapStringForAnnotations += fmt.Sprintf("%v: %v,", k, this.Annotations[k]) + } + mapStringForAnnotations += "}" + s := strings.Join([]string{`&PodSandboxAttributes{`, + `Id:` + fmt.Sprintf("%v", this.Id) + `,`, + `Metadata:` + strings.Replace(this.Metadata.String(), "PodSandboxMetadata", "PodSandboxMetadata", 1) + `,`, + `Labels:` + mapStringForLabels + `,`, + `Annotations:` + mapStringForAnnotations + `,`, + `}`, + }, "") + return s +} +func (this *PodSandboxStats) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PodSandboxStats{`, + `Attributes:` + strings.Replace(this.Attributes.String(), "PodSandboxAttributes", "PodSandboxAttributes", 1) + `,`, + `Linux:` + strings.Replace(this.Linux.String(), "LinuxPodSandboxStats", "LinuxPodSandboxStats", 1) + `,`, + `Windows:` + strings.Replace(this.Windows.String(), "WindowsPodSandboxStats", "WindowsPodSandboxStats", 1) + `,`, + `}`, + }, "") + return s +} +func (this *LinuxPodSandboxStats) String() string { + if this == nil { + return "nil" + } + repeatedStringForContainers := "[]*ContainerStats{" + for _, f := range this.Containers { + repeatedStringForContainers += strings.Replace(f.String(), "ContainerStats", "ContainerStats", 1) + "," + } + repeatedStringForContainers += "}" + s := strings.Join([]string{`&LinuxPodSandboxStats{`, + `Cpu:` + strings.Replace(this.Cpu.String(), "CpuUsage", "CpuUsage", 1) + `,`, + `Memory:` + strings.Replace(this.Memory.String(), "MemoryUsage", "MemoryUsage", 1) + `,`, + `Network:` + strings.Replace(this.Network.String(), "NetworkUsage", "NetworkUsage", 1) + `,`, + `Process:` + strings.Replace(this.Process.String(), "ProcessUsage", "ProcessUsage", 1) + `,`, + `Containers:` + repeatedStringForContainers + `,`, + `}`, + }, "") + return s +} +func (this *WindowsPodSandboxStats) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&WindowsPodSandboxStats{`, + `}`, + }, "") + return s +} +func (this *NetworkUsage) String() string { + if this == nil { + return "nil" + } + repeatedStringForInterfaces := "[]*NetworkInterfaceUsage{" + for _, f := range this.Interfaces { + repeatedStringForInterfaces += strings.Replace(f.String(), "NetworkInterfaceUsage", "NetworkInterfaceUsage", 1) + "," + } + repeatedStringForInterfaces += "}" + s := strings.Join([]string{`&NetworkUsage{`, + `Timestamp:` + fmt.Sprintf("%v", this.Timestamp) + `,`, + `DefaultInterface:` + strings.Replace(this.DefaultInterface.String(), "NetworkInterfaceUsage", "NetworkInterfaceUsage", 1) + `,`, + `Interfaces:` + repeatedStringForInterfaces + `,`, + `}`, + }, "") + return s +} +func (this *NetworkInterfaceUsage) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&NetworkInterfaceUsage{`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `RxBytes:` + strings.Replace(this.RxBytes.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `RxErrors:` + strings.Replace(this.RxErrors.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `TxBytes:` + strings.Replace(this.TxBytes.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `TxErrors:` + strings.Replace(this.TxErrors.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `}`, + }, "") + return s +} +func (this *ProcessUsage) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ProcessUsage{`, + `Timestamp:` + fmt.Sprintf("%v", this.Timestamp) + `,`, + `ProcessCount:` + strings.Replace(this.ProcessCount.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `}`, + }, "") + return s +} func (this *ImageSpec) String() string { if this == nil { return "nil" @@ -17845,6 +19903,7 @@ func (this *CpuUsage) String() string { s := strings.Join([]string{`&CpuUsage{`, `Timestamp:` + fmt.Sprintf("%v", this.Timestamp) + `,`, `UsageCoreNanoSeconds:` + strings.Replace(this.UsageCoreNanoSeconds.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `UsageNanoCores:` + strings.Replace(this.UsageNanoCores.String(), "UInt64Value", "UInt64Value", 1) + `,`, `}`, }, "") return s @@ -17856,6 +19915,11 @@ func (this *MemoryUsage) String() string { s := strings.Join([]string{`&MemoryUsage{`, `Timestamp:` + fmt.Sprintf("%v", this.Timestamp) + `,`, `WorkingSetBytes:` + strings.Replace(this.WorkingSetBytes.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `AvailableBytes:` + strings.Replace(this.AvailableBytes.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `UsageBytes:` + strings.Replace(this.UsageBytes.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `RssBytes:` + strings.Replace(this.RssBytes.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `PageFaults:` + strings.Replace(this.PageFaults.String(), "UInt64Value", "UInt64Value", 1) + `,`, + `MajorPageFaults:` + strings.Replace(this.MajorPageFaults.String(), "UInt64Value", "UInt64Value", 1) + `,`, `}`, }, "") return s @@ -19552,6 +21616,78 @@ func (m *LinuxPodSandboxConfig) Unmarshal(dAtA []byte) error { } m.Sysctls[mapkey] = mapvalue iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Overhead", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Overhead == nil { + m.Overhead = &LinuxContainerResources{} + } + if err := m.Overhead.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Resources", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Resources == nil { + m.Resources = &LinuxContainerResources{} + } + if err := m.Resources.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipApi(dAtA[iNdEx:]) @@ -22873,6 +25009,1831 @@ func (m *ListPodSandboxResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *PodSandboxStatsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PodSandboxStatsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PodSandboxStatsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PodSandboxId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PodSandboxId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PodSandboxStatsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PodSandboxStatsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PodSandboxStatsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Stats", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Stats == nil { + m.Stats = &PodSandboxStats{} + } + if err := m.Stats.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PodSandboxStatsFilter) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PodSandboxStatsFilter: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PodSandboxStatsFilter: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Id = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LabelSelector", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.LabelSelector == nil { + m.LabelSelector = make(map[string]string) + } + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthApi + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return ErrInvalidLengthApi + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthApi + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue < 0 { + return ErrInvalidLengthApi + } + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.LabelSelector[mapkey] = mapvalue + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ListPodSandboxStatsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ListPodSandboxStatsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ListPodSandboxStatsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Filter", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Filter == nil { + m.Filter = &PodSandboxStatsFilter{} + } + if err := m.Filter.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ListPodSandboxStatsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ListPodSandboxStatsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ListPodSandboxStatsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Stats", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Stats = append(m.Stats, &PodSandboxStats{}) + if err := m.Stats[len(m.Stats)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PodSandboxAttributes) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PodSandboxAttributes: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PodSandboxAttributes: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Id = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Metadata == nil { + m.Metadata = &PodSandboxMetadata{} + } + if err := m.Metadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Labels", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Labels == nil { + m.Labels = make(map[string]string) + } + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthApi + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return ErrInvalidLengthApi + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthApi + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue < 0 { + return ErrInvalidLengthApi + } + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.Labels[mapkey] = mapvalue + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Annotations", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Annotations == nil { + m.Annotations = make(map[string]string) + } + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthApi + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return ErrInvalidLengthApi + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthApi + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue < 0 { + return ErrInvalidLengthApi + } + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.Annotations[mapkey] = mapvalue + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PodSandboxStats) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PodSandboxStats: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PodSandboxStats: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Attributes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Attributes == nil { + m.Attributes = &PodSandboxAttributes{} + } + if err := m.Attributes.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Linux", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Linux == nil { + m.Linux = &LinuxPodSandboxStats{} + } + if err := m.Linux.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Windows", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Windows == nil { + m.Windows = &WindowsPodSandboxStats{} + } + if err := m.Windows.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *LinuxPodSandboxStats) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: LinuxPodSandboxStats: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LinuxPodSandboxStats: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Cpu", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Cpu == nil { + m.Cpu = &CpuUsage{} + } + if err := m.Cpu.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Memory", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Memory == nil { + m.Memory = &MemoryUsage{} + } + if err := m.Memory.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Network", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Network == nil { + m.Network = &NetworkUsage{} + } + if err := m.Network.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Process", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Process == nil { + m.Process = &ProcessUsage{} + } + if err := m.Process.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Containers", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Containers = append(m.Containers, &ContainerStats{}) + if err := m.Containers[len(m.Containers)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *WindowsPodSandboxStats) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: WindowsPodSandboxStats: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: WindowsPodSandboxStats: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *NetworkUsage) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: NetworkUsage: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: NetworkUsage: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + m.Timestamp = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Timestamp |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DefaultInterface", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.DefaultInterface == nil { + m.DefaultInterface = &NetworkInterfaceUsage{} + } + if err := m.DefaultInterface.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Interfaces", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Interfaces = append(m.Interfaces, &NetworkInterfaceUsage{}) + if err := m.Interfaces[len(m.Interfaces)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *NetworkInterfaceUsage) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: NetworkInterfaceUsage: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: NetworkInterfaceUsage: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RxBytes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.RxBytes == nil { + m.RxBytes = &UInt64Value{} + } + if err := m.RxBytes.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RxErrors", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.RxErrors == nil { + m.RxErrors = &UInt64Value{} + } + if err := m.RxErrors.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TxBytes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.TxBytes == nil { + m.TxBytes = &UInt64Value{} + } + if err := m.TxBytes.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TxErrors", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.TxErrors == nil { + m.TxErrors = &UInt64Value{} + } + if err := m.TxErrors.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ProcessUsage) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ProcessUsage: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ProcessUsage: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + m.Timestamp = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Timestamp |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProcessCount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ProcessCount == nil { + m.ProcessCount = &UInt64Value{} + } + if err := m.ProcessCount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *ImageSpec) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -34293,6 +38254,42 @@ func (m *CpuUsage) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UsageNanoCores", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.UsageNanoCores == nil { + m.UsageNanoCores = &UInt64Value{} + } + if err := m.UsageNanoCores.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipApi(dAtA[iNdEx:]) @@ -34398,6 +38395,186 @@ func (m *MemoryUsage) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AvailableBytes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.AvailableBytes == nil { + m.AvailableBytes = &UInt64Value{} + } + if err := m.AvailableBytes.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UsageBytes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.UsageBytes == nil { + m.UsageBytes = &UInt64Value{} + } + if err := m.UsageBytes.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RssBytes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.RssBytes == nil { + m.RssBytes = &UInt64Value{} + } + if err := m.RssBytes.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PageFaults", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.PageFaults == nil { + m.PageFaults = &UInt64Value{} + } + if err := m.PageFaults.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MajorPageFaults", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.MajorPageFaults == nil { + m.MajorPageFaults = &UInt64Value{} + } + if err := m.MajorPageFaults.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipApi(dAtA[iNdEx:]) diff --git a/vendor/k8s.io/cri-api/pkg/apis/runtime/v1alpha2/api.proto b/vendor/k8s.io/cri-api/pkg/apis/runtime/v1alpha2/api.proto index 1e579187f..22194efb6 100644 --- a/vendor/k8s.io/cri-api/pkg/apis/runtime/v1alpha2/api.proto +++ b/vendor/k8s.io/cri-api/pkg/apis/runtime/v1alpha2/api.proto @@ -102,6 +102,12 @@ service RuntimeService { // ListContainerStats returns stats of all running containers. rpc ListContainerStats(ListContainerStatsRequest) returns (ListContainerStatsResponse) {} + // PodSandboxStats returns stats of the pod sandbox. If the pod sandbox does not + // exist, the call returns an error. + rpc PodSandboxStats(PodSandboxStatsRequest) returns (PodSandboxStatsResponse) {} + // ListPodSandboxStats returns stats of the pod sandboxes matching a filter. + rpc ListPodSandboxStats(ListPodSandboxStatsRequest) returns (ListPodSandboxStatsResponse) {} + // UpdateRuntimeConfig updates the runtime configuration based on the given request. rpc UpdateRuntimeConfig(UpdateRuntimeConfigRequest) returns (UpdateRuntimeConfigResponse) {} @@ -323,6 +329,10 @@ message LinuxPodSandboxConfig { LinuxSandboxSecurityContext security_context = 2; // Sysctls holds linux sysctls config for the sandbox. map sysctls = 3; + // Optional overhead represents the overheads associated with this sandbox + LinuxContainerResources overhead = 4; + // Optional resources represents the sum of container resources for this sandbox + LinuxContainerResources resources = 5; } // PodSandboxMetadata holds all necessary information for building the sandbox name. @@ -549,6 +559,113 @@ message ListPodSandboxResponse { repeated PodSandbox items = 1; } +message PodSandboxStatsRequest { + // ID of the pod sandbox for which to retrieve stats. + string pod_sandbox_id = 1; +} + +message PodSandboxStatsResponse { + PodSandboxStats stats = 1; +} + +// PodSandboxStatsFilter is used to filter pod sandboxes. +// All those fields are combined with 'AND'. +message PodSandboxStatsFilter { + // ID of the pod sandbox. + string id = 1; + // LabelSelector to select matches. + // Only api.MatchLabels is supported for now and the requirements + // are ANDed. MatchExpressions is not supported yet. + map label_selector = 2; +} + +message ListPodSandboxStatsRequest { + // Filter for the list request. + PodSandboxStatsFilter filter = 1; +} + +message ListPodSandboxStatsResponse { + // Stats of the pod sandbox. + repeated PodSandboxStats stats = 1; +} + +// PodSandboxAttributes provides basic information of the pod sandbox. +message PodSandboxAttributes { + // ID of the pod sandbox. + string id = 1; + // Metadata of the pod sandbox. + PodSandboxMetadata metadata = 2; + // Key-value pairs that may be used to scope and select individual resources. + map labels = 3; + // Unstructured key-value map holding arbitrary metadata. + // Annotations MUST NOT be altered by the runtime; the value of this field + // MUST be identical to that of the corresponding PodSandboxStatus used to + // instantiate the PodSandbox this status represents. + map annotations = 4; +} + +// PodSandboxStats provides the resource usage statistics for a pod. +// The linux or windows field will be populated depending on the platform. +message PodSandboxStats { + // Information of the pod. + PodSandboxAttributes attributes = 1; + // Stats from linux. + LinuxPodSandboxStats linux = 2; + // Stats from windows. + WindowsPodSandboxStats windows = 3; +} + +// LinuxPodSandboxStats provides the resource usage statistics for a pod sandbox on linux. +message LinuxPodSandboxStats { + // CPU usage gathered for the pod sandbox. + CpuUsage cpu = 1; + // Memory usage gathered for the pod sandbox. + MemoryUsage memory = 2; + // Network usage gathered for the pod sandbox + NetworkUsage network = 3; + // Stats pertaining to processes in the pod sandbox. + ProcessUsage process = 4; + // Stats of containers in the measured pod sandbox. + repeated ContainerStats containers = 5; +} + +// WindowsPodSandboxStats provides the resource usage statistics for a pod sandbox on windows +message WindowsPodSandboxStats { + // TODO: Add stats relevant to windows. +} + +// NetworkUsage contains data about network resources. +message NetworkUsage { + // The time at which these stats were updated. + int64 timestamp = 1; + // Stats for the default network interface. + NetworkInterfaceUsage default_interface = 2; + // Stats for all found network interfaces, excluding the default. + repeated NetworkInterfaceUsage interfaces = 3; +} + +// NetworkInterfaceUsage contains resource value data about a network interface. +message NetworkInterfaceUsage { + // The name of the network interface. + string name = 1; + // Cumulative count of bytes received. + UInt64Value rx_bytes = 2; + // Cumulative count of receive errors encountered. + UInt64Value rx_errors = 3; + // Cumulative count of bytes transmitted. + UInt64Value tx_bytes = 4; + // Cumulative count of transmit errors encountered. + UInt64Value tx_errors = 5; +} + +// ProcessUsage are stats pertaining to processes. +message ProcessUsage { + // The time at which these stats were updated. + int64 timestamp = 1; + // Number of processes. + UInt64Value process_count = 2; +} + // ImageSpec is an internal representation of an image. message ImageSpec { // Container's Image field (e.g. imageID or imageDigest). @@ -1359,6 +1476,9 @@ message CpuUsage { int64 timestamp = 1; // Cumulative CPU usage (sum across all cores) since object creation. UInt64Value usage_core_nano_seconds = 2; + // Total CPU usage (sum of all cores) averaged over the sample window. + // The "core" unit can be interpreted as CPU core-nanoseconds per second. + UInt64Value usage_nano_cores = 3; } // MemoryUsage provides the memory usage information. @@ -1367,6 +1487,16 @@ message MemoryUsage { int64 timestamp = 1; // The amount of working set memory in bytes. UInt64Value working_set_bytes = 2; + // Available memory for use. This is defined as the memory limit = workingSetBytes. + UInt64Value available_bytes = 3; + // Total memory in use. This includes all memory regardless of when it was accessed. + UInt64Value usage_bytes = 4; + // The amount of anonymous and swap cache memory (includes transparent hugepages). + UInt64Value rss_bytes = 5; + // Cumulative number of minor page faults. + UInt64Value page_faults = 6; + // Cumulative number of major page faults. + UInt64Value major_page_faults = 7; } message ReopenContainerLogRequest { diff --git a/vendor/modules.txt b/vendor/modules.txt index 92a818c1e..946f811b2 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -368,6 +368,12 @@ github.com/tchap/go-patricia/patricia # github.com/urfave/cli v1.22.2 => github.com/urfave/cli v1.22.1 ## explicit github.com/urfave/cli +# github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5 +## explicit +github.com/vishvananda/netlink +github.com/vishvananda/netlink/nl +# github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f +github.com/vishvananda/netns # go.etcd.io/bbolt v1.3.6 ## explicit go.etcd.io/bbolt @@ -679,7 +685,7 @@ k8s.io/component-base/logs/logreduction k8s.io/component-base/metrics k8s.io/component-base/metrics/legacyregistry k8s.io/component-base/version -# k8s.io/cri-api v0.22.0 +# k8s.io/cri-api v0.23.0-alpha.4 ## explicit k8s.io/cri-api/pkg/apis/runtime/v1 k8s.io/cri-api/pkg/apis/runtime/v1alpha2 From 2e6d5709e32253c3c98956f07c71cb9b6b1d5fd4 Mon Sep 17 00:00:00 2001 From: David Porter Date: Tue, 5 Oct 2021 13:28:36 -0700 Subject: [PATCH 2/2] Implement CRI container and pods stats See https://kep.k8s.io/2371 * Implement new CRI RPCs - `ListPodSandboxStats` and `PodSandboxStats` * `ListPodSandboxStats` and `PodSandboxStats` which return stats about pod sandbox. To obtain pod sandbox stats, underlying metrics are read from the pod sandbox cgroup parent. * Process info is obtained by calling into the underlying task * Network stats are taken by looking up network metrics based on the pod sandbox network namespace path * Return more detailed stats for cpu and memory for existing container stats. These metrics use the underlying task's metrics to obtain stats. Signed-off-by: David Porter --- pkg/cri/server/container_stats_list_linux.go | 219 +++++++++++--- .../server/container_stats_list_linux_test.go | 275 ++++++++++++++++++ pkg/cri/server/instrumented_service.go | 106 +++++++ pkg/cri/server/sandbox_list.go | 6 + pkg/cri/server/sandbox_stats.go | 47 +++ pkg/cri/server/sandbox_stats_linux.go | 177 +++++++++++ pkg/cri/server/sandbox_stats_list.go | 80 +++++ pkg/cri/server/sandbox_stats_other.go | 37 +++ pkg/cri/server/sandbox_stats_windows.go | 34 +++ pkg/cri/store/container/container.go | 24 ++ pkg/cri/store/container/container_test.go | 34 +++ pkg/cri/store/sandbox/sandbox.go | 24 ++ pkg/cri/store/sandbox/sandbox_test.go | 33 +++ pkg/cri/store/stats/stats.go | 27 ++ 14 files changed, 1090 insertions(+), 33 deletions(-) create mode 100644 pkg/cri/server/sandbox_stats.go create mode 100644 pkg/cri/server/sandbox_stats_linux.go create mode 100644 pkg/cri/server/sandbox_stats_list.go create mode 100644 pkg/cri/server/sandbox_stats_other.go create mode 100644 pkg/cri/server/sandbox_stats_windows.go create mode 100644 pkg/cri/store/stats/stats.go diff --git a/pkg/cri/server/container_stats_list_linux.go b/pkg/cri/server/container_stats_list_linux.go index 2b50233b9..bac0de339 100644 --- a/pkg/cri/server/container_stats_list_linux.go +++ b/pkg/cri/server/container_stats_list_linux.go @@ -17,6 +17,8 @@ package server import ( + "time" + "github.com/containerd/containerd/api/types" v1 "github.com/containerd/containerd/metrics/types/v1" v2 "github.com/containerd/containerd/metrics/types/v2" @@ -25,6 +27,7 @@ import ( runtime "k8s.io/cri-api/pkg/apis/runtime/v1" containerstore "github.com/containerd/containerd/pkg/cri/store/container" + stats "github.com/containerd/containerd/pkg/cri/store/stats" ) func (c *criService) containerMetrics( @@ -60,45 +63,89 @@ func (c *criService) containerMetrics( if err != nil { return nil, errors.Wrap(err, "failed to extract container metrics") } - switch metrics := s.(type) { - case *v1.Metrics: - if metrics.CPU != nil && metrics.CPU.Usage != nil { - cs.Cpu = &runtime.CpuUsage{ - Timestamp: stats.Timestamp.UnixNano(), - UsageCoreNanoSeconds: &runtime.UInt64Value{Value: metrics.CPU.Usage.Total}, - } - } - if metrics.Memory != nil && metrics.Memory.Usage != nil { - cs.Memory = &runtime.MemoryUsage{ - Timestamp: stats.Timestamp.UnixNano(), - WorkingSetBytes: &runtime.UInt64Value{ - Value: getWorkingSet(metrics.Memory), - }, - } - } - case *v2.Metrics: - if metrics.CPU != nil { - cs.Cpu = &runtime.CpuUsage{ - Timestamp: stats.Timestamp.UnixNano(), - UsageCoreNanoSeconds: &runtime.UInt64Value{Value: metrics.CPU.UsageUsec * 1000}, - } - } - if metrics.Memory != nil { - cs.Memory = &runtime.MemoryUsage{ - Timestamp: stats.Timestamp.UnixNano(), - WorkingSetBytes: &runtime.UInt64Value{ - Value: getWorkingSetV2(metrics.Memory), - }, - } - } - default: - return &cs, errors.Errorf("unexpected metrics type: %v", metrics) + + cpuStats, err := c.cpuContainerStats(meta.ID, false /* isSandbox */, s, stats.Timestamp) + if err != nil { + return nil, errors.Wrap(err, "failed to obtain cpu stats") } + cs.Cpu = cpuStats + + memoryStats, err := c.memoryContainerStats(meta.ID, s, stats.Timestamp) + if err != nil { + return nil, errors.Wrap(err, "failed to obtain memory stats") + } + cs.Memory = memoryStats } return &cs, nil } +func (c *criService) getUsageNanoCores(containerID string, isSandbox bool, currentUsageCoreNanoSeconds uint64, currentTimestamp time.Time) (uint64, error) { + var oldStats *stats.ContainerStats + + if isSandbox { + sandbox, err := c.sandboxStore.Get(containerID) + if err != nil { + return 0, errors.Wrapf(err, "failed to get sandbox container: %s", containerID) + } + oldStats = sandbox.Stats + } else { + container, err := c.containerStore.Get(containerID) + if err != nil { + return 0, errors.Wrapf(err, "failed to get container ID: %s", containerID) + } + oldStats = container.Stats + } + + if oldStats == nil { + newStats := &stats.ContainerStats{ + UsageCoreNanoSeconds: currentUsageCoreNanoSeconds, + Timestamp: currentTimestamp, + } + if isSandbox { + err := c.sandboxStore.UpdateContainerStats(containerID, newStats) + if err != nil { + return 0, errors.Wrapf(err, "failed to update sandbox stats container ID: %s", containerID) + } + } else { + err := c.containerStore.UpdateContainerStats(containerID, newStats) + if err != nil { + return 0, errors.Wrapf(err, "failed to update container stats ID: %s", containerID) + } + } + return 0, nil + } + + nanoSeconds := currentTimestamp.UnixNano() - oldStats.Timestamp.UnixNano() + + // zero or negative interval + if nanoSeconds <= 0 { + return 0, nil + } + + newUsageNanoCores := uint64(float64(currentUsageCoreNanoSeconds-oldStats.UsageCoreNanoSeconds) / + float64(nanoSeconds) * float64(time.Second/time.Nanosecond)) + + newStats := &stats.ContainerStats{ + UsageCoreNanoSeconds: currentUsageCoreNanoSeconds, + Timestamp: currentTimestamp, + } + if isSandbox { + err := c.sandboxStore.UpdateContainerStats(containerID, newStats) + if err != nil { + return 0, errors.Wrapf(err, "failed to update sandbox container stats: %s", containerID) + } + + } else { + err := c.containerStore.UpdateContainerStats(containerID, newStats) + if err != nil { + return 0, errors.Wrapf(err, "failed to update container stats ID: %s", containerID) + } + } + + return newUsageNanoCores, nil +} + // getWorkingSet calculates workingset memory from cgroup memory stats. // The caller should make sure memory is not nil. // workingset = usage - total_inactive_file @@ -123,3 +170,109 @@ func getWorkingSetV2(memory *v2.MemoryStat) uint64 { } return workingSet } + +func isMemoryUnlimited(v uint64) bool { + // Size after which we consider memory to be "unlimited". This is not + // MaxInt64 due to rounding by the kernel. + // TODO: k8s or cadvisor should export this https://github.com/google/cadvisor/blob/2b6fbacac7598e0140b5bc8428e3bdd7d86cf5b9/metrics/prometheus.go#L1969-L1971 + const maxMemorySize = uint64(1 << 62) + + return v > maxMemorySize +} + +// https://github.com/kubernetes/kubernetes/blob/b47f8263e18c7b13dba33fba23187e5e0477cdbd/pkg/kubelet/stats/helper.go#L68-L71 +func getAvailableBytes(memory *v1.MemoryStat, workingSetBytes uint64) uint64 { + // memory limit - working set bytes + if !isMemoryUnlimited(memory.Usage.Limit) { + return memory.Usage.Limit - workingSetBytes + } + return 0 +} + +func getAvailableBytesV2(memory *v2.MemoryStat, workingSetBytes uint64) uint64 { + // memory limit (memory.max) for cgroupv2 - working set bytes + if !isMemoryUnlimited(memory.UsageLimit) { + return memory.UsageLimit - workingSetBytes + } + return 0 +} + +func (c *criService) cpuContainerStats(ID string, isSandbox bool, stats interface{}, timestamp time.Time) (*runtime.CpuUsage, error) { + switch metrics := stats.(type) { + case *v1.Metrics: + if metrics.CPU != nil && metrics.CPU.Usage != nil { + + usageNanoCores, err := c.getUsageNanoCores(ID, isSandbox, metrics.CPU.Usage.Total, timestamp) + if err != nil { + return nil, errors.Wrapf(err, "failed to get usage nano cores, containerID: %s", ID) + } + + return &runtime.CpuUsage{ + Timestamp: timestamp.UnixNano(), + UsageCoreNanoSeconds: &runtime.UInt64Value{Value: metrics.CPU.Usage.Total}, + UsageNanoCores: &runtime.UInt64Value{Value: usageNanoCores}, + }, nil + } + case *v2.Metrics: + if metrics.CPU != nil { + // convert to nano seconds + usageCoreNanoSeconds := metrics.CPU.UsageUsec * 1000 + + usageNanoCores, err := c.getUsageNanoCores(ID, isSandbox, usageCoreNanoSeconds, timestamp) + if err != nil { + return nil, errors.Wrapf(err, "failed to get usage nano cores, containerID: %s", ID) + } + + return &runtime.CpuUsage{ + Timestamp: timestamp.UnixNano(), + UsageCoreNanoSeconds: &runtime.UInt64Value{Value: usageCoreNanoSeconds}, + UsageNanoCores: &runtime.UInt64Value{Value: usageNanoCores}, + }, nil + } + default: + return nil, errors.Errorf("unexpected metrics type: %v", metrics) + } + return nil, nil +} + +func (c *criService) memoryContainerStats(ID string, stats interface{}, timestamp time.Time) (*runtime.MemoryUsage, error) { + switch metrics := stats.(type) { + case *v1.Metrics: + if metrics.Memory != nil && metrics.Memory.Usage != nil { + workingSetBytes := getWorkingSet(metrics.Memory) + + return &runtime.MemoryUsage{ + Timestamp: timestamp.UnixNano(), + WorkingSetBytes: &runtime.UInt64Value{ + Value: workingSetBytes, + }, + AvailableBytes: &runtime.UInt64Value{Value: getAvailableBytes(metrics.Memory, workingSetBytes)}, + UsageBytes: &runtime.UInt64Value{Value: metrics.Memory.Usage.Usage}, + RssBytes: &runtime.UInt64Value{Value: metrics.Memory.TotalRSS}, + PageFaults: &runtime.UInt64Value{Value: metrics.Memory.TotalPgFault}, + MajorPageFaults: &runtime.UInt64Value{Value: metrics.Memory.TotalPgMajFault}, + }, nil + } + case *v2.Metrics: + if metrics.Memory != nil { + workingSetBytes := getWorkingSetV2(metrics.Memory) + + return &runtime.MemoryUsage{ + Timestamp: timestamp.UnixNano(), + WorkingSetBytes: &runtime.UInt64Value{ + Value: workingSetBytes, + }, + AvailableBytes: &runtime.UInt64Value{Value: getAvailableBytesV2(metrics.Memory, workingSetBytes)}, + UsageBytes: &runtime.UInt64Value{Value: metrics.Memory.Usage}, + // Use Anon memory for RSS as cAdvisor on cgroupv2 + // see https://github.com/google/cadvisor/blob/a9858972e75642c2b1914c8d5428e33e6392c08a/container/libcontainer/handler.go#L799 + RssBytes: &runtime.UInt64Value{Value: metrics.Memory.Anon}, + PageFaults: &runtime.UInt64Value{Value: metrics.Memory.Pgfault}, + MajorPageFaults: &runtime.UInt64Value{Value: metrics.Memory.Pgmajfault}, + }, nil + } + default: + return nil, errors.Errorf("unexpected metrics type: %v", metrics) + } + return nil, nil +} diff --git a/pkg/cri/server/container_stats_list_linux_test.go b/pkg/cri/server/container_stats_list_linux_test.go index a35b5f21a..dba05fe5c 100644 --- a/pkg/cri/server/container_stats_list_linux_test.go +++ b/pkg/cri/server/container_stats_list_linux_test.go @@ -17,10 +17,15 @@ package server import ( + "math" "testing" + "time" v1 "github.com/containerd/cgroups/stats/v1" + v2 "github.com/containerd/cgroups/v2/stats" + containerstore "github.com/containerd/containerd/pkg/cri/store/container" "github.com/stretchr/testify/assert" + runtime "k8s.io/cri-api/pkg/apis/runtime/v1" ) func TestGetWorkingSet(t *testing.T) { @@ -53,3 +58,273 @@ func TestGetWorkingSet(t *testing.T) { }) } } + +func TestGetWorkingSetV2(t *testing.T) { + for desc, test := range map[string]struct { + memory *v2.MemoryStat + expected uint64 + }{ + "nil memory usage": { + memory: &v2.MemoryStat{}, + expected: 0, + }, + "memory usage higher than inactive_total_file": { + memory: &v2.MemoryStat{ + InactiveFile: 1000, + Usage: 2000, + }, + expected: 1000, + }, + "memory usage lower than inactive_total_file": { + memory: &v2.MemoryStat{ + InactiveFile: 2000, + Usage: 1000, + }, + expected: 0, + }, + } { + t.Run(desc, func(t *testing.T) { + got := getWorkingSetV2(test.memory) + assert.Equal(t, test.expected, got) + }) + } +} + +func TestGetAvailableBytes(t *testing.T) { + for desc, test := range map[string]struct { + memory *v1.MemoryStat + workingSetBytes uint64 + expected uint64 + }{ + + "no limit": { + memory: &v1.MemoryStat{ + Usage: &v1.MemoryEntry{ + Limit: math.MaxUint64, // no limit + Usage: 1000, + }, + }, + workingSetBytes: 500, + expected: 0, + }, + "with limit": { + memory: &v1.MemoryStat{ + Usage: &v1.MemoryEntry{ + Limit: 5000, + Usage: 1000, + }, + }, + workingSetBytes: 500, + expected: 5000 - 500, + }, + } { + t.Run(desc, func(t *testing.T) { + got := getAvailableBytes(test.memory, test.workingSetBytes) + assert.Equal(t, test.expected, got) + }) + } +} + +func TestGetAvailableBytesV2(t *testing.T) { + for desc, test := range map[string]struct { + memory *v2.MemoryStat + workingSetBytes uint64 + expected uint64 + }{ + + "no limit": { + memory: &v2.MemoryStat{ + UsageLimit: math.MaxUint64, // no limit + Usage: 1000, + }, + workingSetBytes: 500, + expected: 0, + }, + "with limit": { + memory: &v2.MemoryStat{ + UsageLimit: 5000, + Usage: 1000, + }, + workingSetBytes: 500, + expected: 5000 - 500, + }, + } { + t.Run(desc, func(t *testing.T) { + got := getAvailableBytesV2(test.memory, test.workingSetBytes) + assert.Equal(t, test.expected, got) + }) + } +} + +func TestContainerMetricsCPU(t *testing.T) { + c := newTestCRIService() + timestamp := time.Now() + secondAfterTimeStamp := timestamp.Add(time.Second) + ID := "ID" + + for desc, test := range map[string]struct { + firstMetrics interface{} + secondMetrics interface{} + expectedFirst *runtime.CpuUsage + expectedSecond *runtime.CpuUsage + }{ + + "v1 metrics": { + firstMetrics: &v1.Metrics{ + CPU: &v1.CPUStat{ + Usage: &v1.CPUUsage{ + Total: 50, + }, + }, + }, + secondMetrics: &v1.Metrics{ + CPU: &v1.CPUStat{ + Usage: &v1.CPUUsage{ + Total: 500, + }, + }, + }, + expectedFirst: &runtime.CpuUsage{ + Timestamp: timestamp.UnixNano(), + UsageCoreNanoSeconds: &runtime.UInt64Value{Value: 50}, + UsageNanoCores: &runtime.UInt64Value{Value: 0}, + }, + expectedSecond: &runtime.CpuUsage{ + Timestamp: secondAfterTimeStamp.UnixNano(), + UsageCoreNanoSeconds: &runtime.UInt64Value{Value: 500}, + UsageNanoCores: &runtime.UInt64Value{Value: 450}, + }, + }, + } { + t.Run(desc, func(t *testing.T) { + container, err := containerstore.NewContainer( + containerstore.Metadata{ID: ID}, + ) + assert.NoError(t, err) + assert.Nil(t, container.Stats) + err = c.containerStore.Add(container) + assert.NoError(t, err) + + cpuUsage, err := c.cpuContainerStats(ID, false, test.firstMetrics, timestamp) + assert.NoError(t, err) + + container, err = c.containerStore.Get(ID) + assert.NoError(t, err) + assert.NotNil(t, container.Stats) + + assert.Equal(t, test.expectedFirst, cpuUsage) + + cpuUsage, err = c.cpuContainerStats(ID, false, test.secondMetrics, secondAfterTimeStamp) + assert.NoError(t, err) + assert.Equal(t, test.expectedSecond, cpuUsage) + + container, err = c.containerStore.Get(ID) + assert.NoError(t, err) + assert.NotNil(t, container.Stats) + }) + } + +} + +func TestContainerMetricsMemory(t *testing.T) { + c := newTestCRIService() + timestamp := time.Now() + + for desc, test := range map[string]struct { + metrics interface{} + expected *runtime.MemoryUsage + }{ + "v1 metrics - no memory limit": { + metrics: &v1.Metrics{ + Memory: &v1.MemoryStat{ + Usage: &v1.MemoryEntry{ + Limit: math.MaxUint64, // no limit + Usage: 1000, + }, + TotalRSS: 10, + TotalPgFault: 11, + TotalPgMajFault: 12, + TotalInactiveFile: 500, + }, + }, + expected: &runtime.MemoryUsage{ + Timestamp: timestamp.UnixNano(), + WorkingSetBytes: &runtime.UInt64Value{Value: 500}, + AvailableBytes: &runtime.UInt64Value{Value: 0}, + UsageBytes: &runtime.UInt64Value{Value: 1000}, + RssBytes: &runtime.UInt64Value{Value: 10}, + PageFaults: &runtime.UInt64Value{Value: 11}, + MajorPageFaults: &runtime.UInt64Value{Value: 12}, + }, + }, + "v1 metrics - memory limit": { + metrics: &v1.Metrics{ + Memory: &v1.MemoryStat{ + Usage: &v1.MemoryEntry{ + Limit: 5000, + Usage: 1000, + }, + TotalRSS: 10, + TotalPgFault: 11, + TotalPgMajFault: 12, + TotalInactiveFile: 500, + }, + }, + expected: &runtime.MemoryUsage{ + Timestamp: timestamp.UnixNano(), + WorkingSetBytes: &runtime.UInt64Value{Value: 500}, + AvailableBytes: &runtime.UInt64Value{Value: 4500}, + UsageBytes: &runtime.UInt64Value{Value: 1000}, + RssBytes: &runtime.UInt64Value{Value: 10}, + PageFaults: &runtime.UInt64Value{Value: 11}, + MajorPageFaults: &runtime.UInt64Value{Value: 12}, + }, + }, + "v2 metrics - memory limit": { + metrics: &v2.Metrics{ + Memory: &v2.MemoryStat{ + Usage: 1000, + UsageLimit: 5000, + InactiveFile: 0, + Pgfault: 11, + Pgmajfault: 12, + }, + }, + expected: &runtime.MemoryUsage{ + Timestamp: timestamp.UnixNano(), + WorkingSetBytes: &runtime.UInt64Value{Value: 1000}, + AvailableBytes: &runtime.UInt64Value{Value: 4000}, + UsageBytes: &runtime.UInt64Value{Value: 1000}, + RssBytes: &runtime.UInt64Value{Value: 0}, + PageFaults: &runtime.UInt64Value{Value: 11}, + MajorPageFaults: &runtime.UInt64Value{Value: 12}, + }, + }, + "v2 metrics - no memory limit": { + metrics: &v2.Metrics{ + Memory: &v2.MemoryStat{ + Usage: 1000, + UsageLimit: math.MaxUint64, // no limit + InactiveFile: 0, + Pgfault: 11, + Pgmajfault: 12, + }, + }, + expected: &runtime.MemoryUsage{ + Timestamp: timestamp.UnixNano(), + WorkingSetBytes: &runtime.UInt64Value{Value: 1000}, + AvailableBytes: &runtime.UInt64Value{Value: 0}, + UsageBytes: &runtime.UInt64Value{Value: 1000}, + RssBytes: &runtime.UInt64Value{Value: 0}, + PageFaults: &runtime.UInt64Value{Value: 11}, + MajorPageFaults: &runtime.UInt64Value{Value: 12}, + }, + }, + } { + t.Run(desc, func(t *testing.T) { + got, err := c.memoryContainerStats("ID", test.metrics, timestamp) + assert.NoError(t, err) + assert.Equal(t, test.expected, got) + }) + } +} diff --git a/pkg/cri/server/instrumented_service.go b/pkg/cri/server/instrumented_service.go index bdbb2af03..00304791c 100644 --- a/pkg/cri/server/instrumented_service.go +++ b/pkg/cri/server/instrumented_service.go @@ -1198,6 +1198,59 @@ func (in *instrumentedAlphaService) ImageFsInfo(ctx context.Context, r *runtime_ return res, errdefs.ToGRPC(err) } +func (in *instrumentedService) PodSandboxStats(ctx context.Context, r *runtime.PodSandboxStatsRequest) (res *runtime.PodSandboxStatsResponse, err error) { + if err := in.checkInitialized(); err != nil { + return nil, err + } + log.G(ctx).Debugf("PodSandboxStats for %q", r.GetPodSandboxId()) + defer func() { + if err != nil { + log.G(ctx).WithError(err).Errorf("PodSandboxStats for %q failed", r.GetPodSandboxId()) + } else { + log.G(ctx).Debugf("PodSandboxStats for %q returns stats %+v", r.GetPodSandboxId(), res.GetStats()) + } + }() + res, err = in.c.PodSandboxStats(ctrdutil.WithNamespace(ctx), r) + return res, errdefs.ToGRPC(err) +} + +func (in *instrumentedAlphaService) PodSandboxStats(ctx context.Context, r *runtime_alpha.PodSandboxStatsRequest) (res *runtime_alpha.PodSandboxStatsResponse, err error) { + if err := in.checkInitialized(); err != nil { + return nil, err + } + log.G(ctx).Debugf("PodSandboxStats for %q", r.GetPodSandboxId()) + defer func() { + if err != nil { + log.G(ctx).WithError(err).Errorf("PodSandboxStats for %q failed", r.GetPodSandboxId()) + } else { + log.G(ctx).Debugf("PodSandboxStats for %q returns stats %+v", r.GetPodSandboxId(), res.GetStats()) + } + }() + // converts request and response for earlier CRI version to call and get response from the current version + var v1r runtime.PodSandboxStatsRequest + if err := alphaReqToV1Req(r, &v1r); err != nil { + return nil, errdefs.ToGRPC(err) + } + var v1res *runtime.PodSandboxStatsResponse + v1res, err = in.c.PodSandboxStats(ctrdutil.WithNamespace(ctx), &v1r) + if v1res != nil { + resp := &runtime_alpha.PodSandboxStatsResponse{} + perr := v1RespToAlphaResp(v1res, resp) + if perr == nil { + res = resp + } else { + // actual error has precidence on error returned vs parse error issues + if err == nil { + err = perr + } else { + // extra log entry if convert response parse error and request error + log.G(ctx).WithError(err).Errorf("PodSandboxStats for %q failed", r.GetPodSandboxId()) + } + } + } + return res, errdefs.ToGRPC(err) +} + func (in *instrumentedService) ContainerStats(ctx context.Context, r *runtime.ContainerStatsRequest) (res *runtime.ContainerStatsResponse, err error) { if err := in.checkInitialized(); err != nil { return nil, err @@ -1251,6 +1304,59 @@ func (in *instrumentedAlphaService) ContainerStats(ctx context.Context, r *runti return res, errdefs.ToGRPC(err) } +func (in *instrumentedService) ListPodSandboxStats(ctx context.Context, r *runtime.ListPodSandboxStatsRequest) (res *runtime.ListPodSandboxStatsResponse, err error) { + if err := in.checkInitialized(); err != nil { + return nil, err + } + log.G(ctx).Tracef("ListPodSandboxStats with filter %+v", r.GetFilter()) + defer func() { + if err != nil { + log.G(ctx).WithError(err).Error("ListPodSandboxStats failed") + } else { + log.G(ctx).Tracef("ListPodSandboxStats returns stats %+v", res.GetStats()) + } + }() + res, err = in.c.ListPodSandboxStats(ctrdutil.WithNamespace(ctx), r) + return res, errdefs.ToGRPC(err) +} + +func (in *instrumentedAlphaService) ListPodSandboxStats(ctx context.Context, r *runtime_alpha.ListPodSandboxStatsRequest) (res *runtime_alpha.ListPodSandboxStatsResponse, err error) { + if err := in.checkInitialized(); err != nil { + return nil, err + } + log.G(ctx).Tracef("ListPodSandboxStats with filter %+v", r.GetFilter()) + defer func() { + if err != nil { + log.G(ctx).WithError(err).Error("ListPodSandboxStats failed") + } else { + log.G(ctx).Tracef("ListPodSandboxStats returns stats %+v", res.GetStats()) + } + }() + // converts request and response for earlier CRI version to call and get response from the current version + var v1r runtime.ListPodSandboxStatsRequest + if err := alphaReqToV1Req(r, &v1r); err != nil { + return nil, errdefs.ToGRPC(err) + } + var v1res *runtime.ListPodSandboxStatsResponse + v1res, err = in.c.ListPodSandboxStats(ctrdutil.WithNamespace(ctx), &v1r) + if v1res != nil { + resp := &runtime_alpha.ListPodSandboxStatsResponse{} + perr := v1RespToAlphaResp(v1res, resp) + if perr == nil { + res = resp + } else { + // actual error has precidence on error returned vs parse error issues + if err == nil { + err = perr + } else { + // extra log entry if convert response parse error and request error + log.G(ctx).WithError(perr).Error("ListPodSandboxStats failed") + } + } + } + return res, errdefs.ToGRPC(err) +} + func (in *instrumentedService) ListContainerStats(ctx context.Context, r *runtime.ListContainerStatsRequest) (res *runtime.ListContainerStatsResponse, err error) { if err := in.checkInitialized(); err != nil { return nil, err diff --git a/pkg/cri/server/sandbox_list.go b/pkg/cri/server/sandbox_list.go index b6ab200b6..a236cfe68 100644 --- a/pkg/cri/server/sandbox_list.go +++ b/pkg/cri/server/sandbox_list.go @@ -63,6 +63,12 @@ func (c *criService) normalizePodSandboxFilter(filter *runtime.PodSandboxFilter) } } +func (c *criService) normalizePodSandboxStatsFilter(filter *runtime.PodSandboxStatsFilter) { + if sb, err := c.sandboxStore.Get(filter.GetId()); err == nil { + filter.Id = sb.ID + } +} + // filterCRISandboxes filters CRISandboxes. func (c *criService) filterCRISandboxes(sandboxes []*runtime.PodSandbox, filter *runtime.PodSandboxFilter) []*runtime.PodSandbox { if filter == nil { diff --git a/pkg/cri/server/sandbox_stats.go b/pkg/cri/server/sandbox_stats.go new file mode 100644 index 000000000..f3402c939 --- /dev/null +++ b/pkg/cri/server/sandbox_stats.go @@ -0,0 +1,47 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package server + +import ( + "github.com/pkg/errors" + "golang.org/x/net/context" + runtime "k8s.io/cri-api/pkg/apis/runtime/v1" +) + +func (c *criService) PodSandboxStats( + ctx context.Context, + r *runtime.PodSandboxStatsRequest, +) (*runtime.PodSandboxStatsResponse, error) { + + sandbox, err := c.sandboxStore.Get(r.GetPodSandboxId()) + if err != nil { + return nil, errors.Wrapf(err, "an error occurred when trying to find sandbox %s", r.GetPodSandboxId()) + } + + metrics, err := metricsForSandbox(sandbox) + if err != nil { + return nil, errors.Wrapf(err, "failed getting metrics for sandbox %s", r.GetPodSandboxId()) + } + + podSandboxStats, err := c.podSandboxStats(ctx, sandbox, metrics) + + if err != nil { + return nil, errors.Wrapf(err, "failed to decode pod sandbox metrics %s", r.GetPodSandboxId()) + } + + return &runtime.PodSandboxStatsResponse{Stats: podSandboxStats}, nil +} diff --git a/pkg/cri/server/sandbox_stats_linux.go b/pkg/cri/server/sandbox_stats_linux.go new file mode 100644 index 000000000..ad4feb59d --- /dev/null +++ b/pkg/cri/server/sandbox_stats_linux.go @@ -0,0 +1,177 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package server + +import ( + "time" + + "github.com/containernetworking/plugins/pkg/ns" + "github.com/pkg/errors" + "golang.org/x/net/context" + runtime "k8s.io/cri-api/pkg/apis/runtime/v1" + + "github.com/containerd/cgroups" + cgroupsv2 "github.com/containerd/cgroups/v2" + + "github.com/vishvananda/netlink" + + "github.com/containerd/containerd/log" + sandboxstore "github.com/containerd/containerd/pkg/cri/store/sandbox" +) + +func (c *criService) podSandboxStats( + ctx context.Context, + sandbox sandboxstore.Sandbox, + stats interface{}, +) (*runtime.PodSandboxStats, error) { + meta := sandbox.Metadata + + if sandbox.Status.Get().State != sandboxstore.StateReady { + return nil, errors.Errorf("failed to get pod sandbox stats since sandbox container %q is not in ready state", meta.ID) + } + + var podSandboxStats runtime.PodSandboxStats + podSandboxStats.Attributes = &runtime.PodSandboxAttributes{ + Id: meta.ID, + Metadata: meta.Config.GetMetadata(), + Labels: meta.Config.GetLabels(), + Annotations: meta.Config.GetAnnotations(), + } + + podSandboxStats.Linux = &runtime.LinuxPodSandboxStats{} + + if stats != nil { + timestamp := time.Now() + + cpuStats, err := c.cpuContainerStats(meta.ID, true /* isSandbox */, stats, timestamp) + if err != nil { + return nil, errors.Wrap(err, "failed to obtain cpu stats") + } + podSandboxStats.Linux.Cpu = cpuStats + + memoryStats, err := c.memoryContainerStats(meta.ID, stats, timestamp) + if err != nil { + return nil, errors.Wrap(err, "failed to obtain memory stats") + } + podSandboxStats.Linux.Memory = memoryStats + + if sandbox.NetNSPath != "" { + rxBytes, rxErrors, txBytes, txErrors := getContainerNetIO(ctx, sandbox.NetNSPath) + podSandboxStats.Linux.Network = &runtime.NetworkUsage{ + DefaultInterface: &runtime.NetworkInterfaceUsage{ + Name: defaultIfName, + RxBytes: &runtime.UInt64Value{Value: rxBytes}, + RxErrors: &runtime.UInt64Value{Value: rxErrors}, + TxBytes: &runtime.UInt64Value{Value: txBytes}, + TxErrors: &runtime.UInt64Value{Value: txErrors}, + }, + } + } + + var pidCount uint64 + for _, cntr := range c.containerStore.List() { + if cntr.SandboxID != sandbox.ID { + continue + } + + state := cntr.Status.Get().State() + if state != runtime.ContainerState_CONTAINER_RUNNING { + continue + } + + task, err := cntr.Container.Task(ctx, nil) + if err != nil { + return nil, err + } + + processes, err := task.Pids(ctx) + if err != nil { + return nil, err + } + pidCount += uint64(len(processes)) + + } + podSandboxStats.Linux.Process = &runtime.ProcessUsage{ + Timestamp: timestamp.UnixNano(), + ProcessCount: &runtime.UInt64Value{Value: pidCount}, + } + + listContainerStatsRequest := &runtime.ListContainerStatsRequest{Filter: &runtime.ContainerStatsFilter{PodSandboxId: meta.ID}} + resp, err := c.ListContainerStats(ctx, listContainerStatsRequest) + if err != nil { + return nil, errors.Wrap(err, "failed to obtain container stats during podSandboxStats call") + } + podSandboxStats.Linux.Containers = resp.GetStats() + } + + return &podSandboxStats, nil +} + +// https://github.com/cri-o/cri-o/blob/74a5cf8dffd305b311eb1c7f43a4781738c388c1/internal/oci/stats.go#L32 +func getContainerNetIO(ctx context.Context, netNsPath string) (rxBytes, rxErrors, txBytes, txErrors uint64) { + ns.WithNetNSPath(netNsPath, func(_ ns.NetNS) error { + link, err := netlink.LinkByName(defaultIfName) + if err != nil { + log.G(ctx).WithError(err).Errorf("unable to retrieve network namespace stats for netNsPath: %v, interface: %v", netNsPath, defaultIfName) + return err + } + attrs := link.Attrs() + if attrs != nil && attrs.Statistics != nil { + rxBytes = attrs.Statistics.RxBytes + rxErrors = attrs.Statistics.RxErrors + txBytes = attrs.Statistics.TxBytes + txErrors = attrs.Statistics.TxErrors + } + return nil + }) + + return rxBytes, rxErrors, txBytes, txErrors +} + +func metricsForSandbox(sandbox sandboxstore.Sandbox) (interface{}, error) { + cgroupPath := sandbox.Config.GetLinux().GetCgroupParent() + + if cgroupPath == "" { + return nil, errors.Errorf("failed to get cgroup metrics for sandbox %v because cgroupPath is empty", sandbox.ID) + } + + var statsx interface{} + if cgroups.Mode() == cgroups.Unified { + cg, err := cgroupsv2.LoadManager("/sys/fs/cgroup", cgroupPath) + if err != nil { + return nil, errors.Wrapf(err, "failed to load sandbox cgroup: %v", cgroupPath) + } + stats, err := cg.Stat() + if err != nil { + return nil, errors.Wrapf(err, "failed to get stats for cgroup: %v", cgroupPath) + } + statsx = stats + + } else { + control, err := cgroups.Load(cgroups.V1, cgroups.StaticPath(cgroupPath)) + if err != nil { + return nil, errors.Wrapf(err, "failed to load sandbox cgroup: %v", cgroupPath) + } + stats, err := control.Stat(cgroups.IgnoreNotExist) + if err != nil { + return nil, errors.Wrapf(err, "failed to get stats for cgroup %v", cgroupPath) + } + statsx = stats + } + + return statsx, nil +} diff --git a/pkg/cri/server/sandbox_stats_list.go b/pkg/cri/server/sandbox_stats_list.go new file mode 100644 index 000000000..cefcc43ee --- /dev/null +++ b/pkg/cri/server/sandbox_stats_list.go @@ -0,0 +1,80 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package server + +import ( + sandboxstore "github.com/containerd/containerd/pkg/cri/store/sandbox" + "github.com/pkg/errors" + "golang.org/x/net/context" + runtime "k8s.io/cri-api/pkg/apis/runtime/v1" +) + +// ListPodSandboxStats returns stats of all ready sandboxes. +func (c *criService) ListPodSandboxStats( + ctx context.Context, + r *runtime.ListPodSandboxStatsRequest, +) (*runtime.ListPodSandboxStatsResponse, error) { + sandboxes := c.sandboxesForListPodSandboxStatsRequest(r) + + podSandboxStats := new(runtime.ListPodSandboxStatsResponse) + for _, sandbox := range sandboxes { + metrics, err := metricsForSandbox(sandbox) + + if err != nil { + return nil, errors.Wrapf(err, "failed to obtain metrics for sandbox %q", sandbox.ID) + } + + sandboxStats, err := c.podSandboxStats(ctx, sandbox, metrics) + if err != nil { + return nil, errors.Wrapf(err, "failed to decode sandbox container metrics for sandbox %q", sandbox.ID) + } + podSandboxStats.Stats = append(podSandboxStats.Stats, sandboxStats) + } + + return podSandboxStats, nil +} + +func (c *criService) sandboxesForListPodSandboxStatsRequest(r *runtime.ListPodSandboxStatsRequest) []sandboxstore.Sandbox { + sandboxesInStore := c.sandboxStore.List() + + if r.GetFilter() == nil { + return sandboxesInStore + } + + c.normalizePodSandboxStatsFilter(r.GetFilter()) + + var sandboxes []sandboxstore.Sandbox + for _, sandbox := range sandboxesInStore { + if r.GetFilter().GetId() != "" && sandbox.ID != r.GetFilter().GetId() { + continue + } + + if r.GetFilter().GetLabelSelector() != nil && + !matchLabelSelector(r.GetFilter().GetLabelSelector(), sandbox.Config.GetLabels()) { + continue + } + + // We can't obtain metrics for sandboxes that aren't in ready state + if sandbox.Status.Get().State != sandboxstore.StateReady { + continue + } + + sandboxes = append(sandboxes, sandbox) + } + + return sandboxes +} diff --git a/pkg/cri/server/sandbox_stats_other.go b/pkg/cri/server/sandbox_stats_other.go new file mode 100644 index 000000000..88c94d182 --- /dev/null +++ b/pkg/cri/server/sandbox_stats_other.go @@ -0,0 +1,37 @@ +//go:build !windows && !linux +// +build !windows,!linux + +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package server + +import ( + "golang.org/x/net/context" + runtime "k8s.io/cri-api/pkg/apis/runtime/v1" + + "github.com/containerd/containerd/errdefs" + sandboxstore "github.com/containerd/containerd/pkg/cri/store/sandbox" + "github.com/pkg/errors" +) + +func (c *criService) podSandboxStats(ctx context.Context, sandbox sandboxstore.Sandbox, stats interface{}) (*runtime.PodSandboxStats, error) { + return nil, errors.Wrap(errdefs.ErrNotImplemented, "pod sandbox stats not implemented") +} + +func metricsForSandbox(sandbox sandboxstore.Sandbox) (interface{}, error) { + return nil, errors.Wrap(errdefs.ErrNotImplemented, "metrics for sandbox not implemented") +} diff --git a/pkg/cri/server/sandbox_stats_windows.go b/pkg/cri/server/sandbox_stats_windows.go new file mode 100644 index 000000000..3798a5e1b --- /dev/null +++ b/pkg/cri/server/sandbox_stats_windows.go @@ -0,0 +1,34 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package server + +import ( + "golang.org/x/net/context" + runtime "k8s.io/cri-api/pkg/apis/runtime/v1" + + "github.com/containerd/containerd/errdefs" + sandboxstore "github.com/containerd/containerd/pkg/cri/store/sandbox" + "github.com/pkg/errors" +) + +func (c *criService) podSandboxStats(ctx context.Context, sandbox sandboxstore.Sandbox, stats interface{}) (*runtime.PodSandboxStats, error) { + return nil, errors.Wrap(errdefs.ErrNotImplemented, "pod sandbox stats not implemented on windows") +} + +func metricsForSandbox(sandbox sandboxstore.Sandbox) (interface{}, error) { + return nil, errors.Wrap(errdefs.ErrNotImplemented, "metrics for sandbox not implemented on windows") +} diff --git a/pkg/cri/store/container/container.go b/pkg/cri/store/container/container.go index 9bf89918d..dd584bc5a 100644 --- a/pkg/cri/store/container/container.go +++ b/pkg/cri/store/container/container.go @@ -24,6 +24,7 @@ import ( cio "github.com/containerd/containerd/pkg/cri/io" "github.com/containerd/containerd/pkg/cri/store" "github.com/containerd/containerd/pkg/cri/store/label" + "github.com/containerd/containerd/pkg/cri/store/stats" "github.com/containerd/containerd/pkg/cri/store/truncindex" runtime "k8s.io/cri-api/pkg/apis/runtime/v1" @@ -46,6 +47,8 @@ type Container struct { // IsStopSignaledWithTimeout the default is 0, and it is set to 1 after sending // the signal once to avoid repeated sending of the signal. IsStopSignaledWithTimeout *uint32 + // Stats contains (mutable) stats for the container + Stats *stats.ContainerStats } // Opts sets specific information to newly created Container. @@ -166,6 +169,27 @@ func (s *Store) List() []Container { return containers } +func (s *Store) UpdateContainerStats(id string, newContainerStats *stats.ContainerStats) error { + s.lock.RLock() + defer s.lock.RUnlock() + id, err := s.idIndex.Get(id) + if err != nil { + if err == truncindex.ErrNotExist { + err = errdefs.ErrNotFound + } + return err + } + + if _, ok := s.containers[id]; !ok { + return errdefs.ErrNotFound + } + + c := s.containers[id] + c.Stats = newContainerStats + s.containers[id] = c + return nil +} + // Delete deletes the container from store with specified id. func (s *Store) Delete(id string) { s.lock.Lock() diff --git a/pkg/cri/store/container/container_test.go b/pkg/cri/store/container/container_test.go index b72307ca1..6f7bd69b6 100644 --- a/pkg/cri/store/container/container_test.go +++ b/pkg/cri/store/container/container_test.go @@ -24,6 +24,7 @@ import ( "github.com/containerd/containerd/errdefs" cio "github.com/containerd/containerd/pkg/cri/io" "github.com/containerd/containerd/pkg/cri/store/label" + "github.com/containerd/containerd/pkg/cri/store/stats" "github.com/opencontainers/selinux/go-selinux" assertlib "github.com/stretchr/testify/assert" @@ -132,6 +133,25 @@ func TestContainerStore(t *testing.T) { Removing: true, }, } + + stats := map[string]*stats.ContainerStats{ + "1": { + Timestamp: time.Now(), + UsageCoreNanoSeconds: 1, + }, + "2abcd": { + Timestamp: time.Now(), + UsageCoreNanoSeconds: 2, + }, + "4a333": { + Timestamp: time.Now(), + UsageCoreNanoSeconds: 3, + }, + "4abcd": { + Timestamp: time.Now(), + UsageCoreNanoSeconds: 4, + }, + } assert := assertlib.New(t) containers := map[string]Container{} for id := range metadatas { @@ -163,12 +183,26 @@ func TestContainerStore(t *testing.T) { got, err := s.Get(genTruncIndex(id)) assert.NoError(err) assert.Equal(c, got) + assert.Nil(c.Stats) } t.Logf("should be able to list containers") cs := s.List() assert.Len(cs, len(containers)) + t.Logf("should be able to update stats on container") + for id := range containers { + err := s.UpdateContainerStats(id, stats[id]) + assert.NoError(err) + } + + // Validate stats were updated + cs = s.List() + assert.Len(cs, len(containers)) + for _, c := range cs { + assert.Equal(stats[c.ID], c.Stats) + } + if selinux.GetEnabled() { t.Logf("should have reserved labels (requires -tag selinux)") assert.Equal(map[string]bool{ diff --git a/pkg/cri/store/sandbox/sandbox.go b/pkg/cri/store/sandbox/sandbox.go index ea2916c9f..854372afb 100644 --- a/pkg/cri/store/sandbox/sandbox.go +++ b/pkg/cri/store/sandbox/sandbox.go @@ -23,6 +23,7 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/pkg/cri/store" "github.com/containerd/containerd/pkg/cri/store/label" + "github.com/containerd/containerd/pkg/cri/store/stats" "github.com/containerd/containerd/pkg/cri/store/truncindex" "github.com/containerd/containerd/pkg/netns" ) @@ -42,6 +43,8 @@ type Sandbox struct { NetNS *netns.NetNS // StopCh is used to propagate the stop information of the sandbox. *store.StopCh + // Stats contains (mutable) stats for the (pause) sandbox container + Stats *stats.ContainerStats } // NewSandbox creates an internally used sandbox type. This functions reminds @@ -121,6 +124,27 @@ func (s *Store) List() []Sandbox { return sandboxes } +func (s *Store) UpdateContainerStats(id string, newContainerStats *stats.ContainerStats) error { + s.lock.RLock() + defer s.lock.RUnlock() + id, err := s.idIndex.Get(id) + if err != nil { + if err == truncindex.ErrNotExist { + err = errdefs.ErrNotFound + } + return err + } + + if _, ok := s.sandboxes[id]; !ok { + return errdefs.ErrNotFound + } + + c := s.sandboxes[id] + c.Stats = newContainerStats + s.sandboxes[id] = c + return nil +} + // Delete deletes the sandbox with specified id. func (s *Store) Delete(id string) { s.lock.Lock() diff --git a/pkg/cri/store/sandbox/sandbox_test.go b/pkg/cri/store/sandbox/sandbox_test.go index fcebdf266..68ff056ea 100644 --- a/pkg/cri/store/sandbox/sandbox_test.go +++ b/pkg/cri/store/sandbox/sandbox_test.go @@ -18,9 +18,11 @@ package sandbox import ( "testing" + "time" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/pkg/cri/store/label" + "github.com/containerd/containerd/pkg/cri/store/stats" assertlib "github.com/stretchr/testify/assert" runtime "k8s.io/cri-api/pkg/apis/runtime/v1" @@ -109,6 +111,24 @@ func TestSandboxStore(t *testing.T) { }, Status{State: StateUnknown}, ) + stats := map[string]*stats.ContainerStats{ + "1": { + Timestamp: time.Now(), + UsageCoreNanoSeconds: 1, + }, + "2abcd": { + Timestamp: time.Now(), + UsageCoreNanoSeconds: 2, + }, + "4a333": { + Timestamp: time.Now(), + UsageCoreNanoSeconds: 3, + }, + "4abcd": { + Timestamp: time.Now(), + UsageCoreNanoSeconds: 4, + }, + } assert := assertlib.New(t) s := NewStore(label.NewStore()) @@ -136,6 +156,19 @@ func TestSandboxStore(t *testing.T) { sbs := s.List() assert.Len(sbs, sbNum) + t.Logf("should be able to update stats on container") + for id := range sandboxes { + err := s.UpdateContainerStats(id, stats[id]) + assert.NoError(err) + } + + // Validate stats were updated + sbs = s.List() + assert.Len(sbs, sbNum) + for _, sb := range sbs { + assert.Equal(stats[sb.ID], sb.Stats) + } + for testID, v := range sandboxes { truncID := genTruncIndex(testID) diff --git a/pkg/cri/store/stats/stats.go b/pkg/cri/store/stats/stats.go new file mode 100644 index 000000000..b2dd581ab --- /dev/null +++ b/pkg/cri/store/stats/stats.go @@ -0,0 +1,27 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package stats + +import "time" + +// ContainerStats contains the information about container stats. +type ContainerStats struct { + // Timestamp of when stats were collected + Timestamp time.Time + // Cumulative CPU usage (sum across all cores) since object creation. + UsageCoreNanoSeconds uint64 +}